// Author: Jaakko Salli
// Modified by:
// Created: Aug-31-2006
-// RCS-ID: $Id:
+// RCS-ID: $Id$
// Copyright: (c) 2005 Jaakko Salli
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/odcombo.h"
#include "wx/settings.h"
+#include "wx/dc.h"
#if wxUSE_IMAGE
#include "wx/image.h"
#endif
-const wxChar wxBitmapComboBoxNameStr[] = wxT("bitmapComboBox");
-
-
-// These macros allow wxArrayPtrVoid to be used in more convenient manner
-#define GetBitmapPtr(n) ((wxBitmap*)m_bitmaps[n])
-
-
-#define IMAGE_SPACING_RIGHT 4 // Space left of image
-
-#define IMAGE_SPACING_LEFT 4 // Space right of image, left of text
-
-#define IMAGE_SPACING_VERTICAL 2 // Space top and bottom of image
-
#define IMAGE_SPACING_CTRL_VERTICAL 7 // Spacing used in control size calculation
-#define EXTRA_FONT_HEIGHT 0 // Add to increase min. height of list items
-
// ============================================================================
// implementation
BEGIN_EVENT_TABLE(wxBitmapComboBox, wxOwnerDrawnComboBox)
- EVT_SIZE(wxBitmapComboBox::OnResize)
+ EVT_SIZE(wxBitmapComboBox::OnSize)
END_EVENT_TABLE()
void wxBitmapComboBox::Init()
{
- m_fontHeight = 0;
- m_imgAreaWidth = 0;
m_inResize = false;
}
return false;
}
- PostCreate();
+ UpdateInternals();
return true;
}
return false;
}
- PostCreate();
+ UpdateInternals();
return true;
}
-void wxBitmapComboBox::PostCreate()
-{
- m_fontHeight = GetCharHeight() + EXTRA_FONT_HEIGHT;
-}
-
wxBitmapComboBox::~wxBitmapComboBox()
{
Clear();
void wxBitmapComboBox::SetItemBitmap(unsigned int n, const wxBitmap& bitmap)
{
- wxCHECK_RET( n < m_bitmaps.size(), wxT("invalid item index") );
OnAddBitmap(bitmap);
- *GetBitmapPtr(n) = bitmap;
+ DoSetItemBitmap(n, bitmap);
if ( (int)n == GetSelection() )
Refresh();
}
-wxBitmap wxBitmapComboBox::GetItemBitmap(unsigned int n) const
+int wxBitmapComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
+ unsigned int pos,
+ void **clientData, wxClientDataType type)
{
- wxCHECK_MSG( n < m_bitmaps.size(), wxNullBitmap, wxT("invalid item index") );
- return *GetBitmapPtr(n);
-}
-
-int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
- unsigned int pos, void *clientData)
-{
- int n = DoInsertWithImage(item, bitmap, pos);
- if ( n != wxNOT_FOUND )
- SetClientData(n, clientData);
+ const unsigned int numItems = items.GetCount();
+ const unsigned int countNew = GetCount() + numItems;
- return n;
-}
+ wxASSERT( numItems == 1 || !HasFlag(wxCB_SORT) ); // Sanity check
-int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
- unsigned int pos, wxClientData *clientData)
-{
- int n = DoInsertWithImage(item, bitmap, pos);
- if ( n != wxNOT_FOUND )
- SetClientObject(n, clientData);
+ m_bitmaps.Alloc(countNew);
- return n;
-}
-
-bool wxBitmapComboBox::OnAddBitmap(const wxBitmap& bitmap)
-{
- if ( bitmap.Ok() )
+ for ( unsigned int i = 0; i < numItems; i++ )
{
- int width = bitmap.GetWidth();
- int height = bitmap.GetHeight();
-
- if ( m_usedImgSize.x <= 0 )
- {
- //
- // If size not yet determined, get it from this image.
- m_usedImgSize.x = width;
- m_usedImgSize.y = height;
-
- InvalidateBestSize();
- wxSize newSz = GetBestSize();
- wxSize sz = GetSize();
- if ( newSz.y > sz.y )
- SetSize(sz.x, newSz.y);
- else
- DetermineIndent();
- }
-
- wxCHECK_MSG(width == m_usedImgSize.x && height == m_usedImgSize.y,
- false,
- wxT("you can only add images of same size"));
+ m_bitmaps.Insert(new wxBitmap(wxNullBitmap), pos + i);
}
- return true;
-}
-
-bool wxBitmapComboBox::DoInsertBitmap(const wxBitmap& bitmap, unsigned int pos)
-{
- if ( !OnAddBitmap(bitmap) )
- return false;
-
- // NB: We must try to set the image before DoInsert or
- // DoAppend because OnMeasureItem might be called
- // before it returns.
- m_bitmaps.Insert( new wxBitmap(bitmap), pos);
+ const int index = wxOwnerDrawnComboBox::DoInsertItems(items, pos,
+ clientData, type);
- return true;
-}
-
-int wxBitmapComboBox::DoAppendWithImage(const wxString& item, const wxBitmap& image)
-{
- unsigned int pos = m_bitmaps.size();
-
- if ( !DoInsertBitmap(image, pos) )
- return wxNOT_FOUND;
-
- int index = wxOwnerDrawnComboBox::DoAppend(item);
-
- if ( index < 0 )
- index = m_bitmaps.size();
-
- // Need to re-check the index incase DoAppend sorted
- if ( (unsigned int) index != pos )
+ if ( index == wxNOT_FOUND )
+ {
+ for ( int i = numItems-1; i >= 0; i-- )
+ BCBDoDeleteOneItem(pos + i);
+ }
+ else if ( ((unsigned int)index) != pos )
{
- wxBitmap* bmp = GetBitmapPtr(pos);
+ // Move pre-inserted empty bitmap into correct position
+ // (usually happens when combo box has wxCB_SORT style)
+ wxBitmap* bmp = static_cast<wxBitmap*>(m_bitmaps[pos]);
m_bitmaps.RemoveAt(pos);
m_bitmaps.Insert(bmp, index);
}
return index;
}
-int wxBitmapComboBox::DoInsertWithImage(const wxString& item,
- const wxBitmap& image,
- unsigned int pos)
+int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap)
{
- if ( !DoInsertBitmap(image, pos) )
- return wxNOT_FOUND;
-
- return wxOwnerDrawnComboBox::DoInsert(item, pos);
+ const int n = wxOwnerDrawnComboBox::Append(item);
+ if(n != wxNOT_FOUND)
+ SetItemBitmap(n, bitmap);
+ return n;
}
-int wxBitmapComboBox::DoAppend(const wxString& item)
+int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
+ void *clientData)
{
- return DoAppendWithImage(item, wxNullBitmap);
+ const int n = wxOwnerDrawnComboBox::Append(item, clientData);
+ if(n != wxNOT_FOUND)
+ SetItemBitmap(n, bitmap);
+ return n;
}
-int wxBitmapComboBox::DoInsert(const wxString& item, unsigned int pos)
+int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
+ wxClientData *clientData)
{
- return DoInsertWithImage(item, wxNullBitmap, pos);
+ const int n = wxOwnerDrawnComboBox::Append(item, clientData);
+ if(n != wxNOT_FOUND)
+ SetItemBitmap(n, bitmap);
+ return n;
}
-void wxBitmapComboBox::Clear()
+int wxBitmapComboBox::Insert(const wxString& item,
+ const wxBitmap& bitmap,
+ unsigned int pos)
{
- wxOwnerDrawnComboBox::Clear();
-
- unsigned int i;
-
- for ( i=0; i<m_bitmaps.size(); i++ )
- delete GetBitmapPtr(i);
+ const int n = wxOwnerDrawnComboBox::Insert(item, pos);
+ if(n != wxNOT_FOUND)
+ SetItemBitmap(n, bitmap);
+ return n;
+}
- m_bitmaps.Empty();
+int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
+ unsigned int pos, void *clientData)
+{
+ const int n = wxOwnerDrawnComboBox::Insert(item, pos, clientData);
+ if(n != wxNOT_FOUND)
+ SetItemBitmap(n, bitmap);
+ return n;
+}
- m_usedImgSize.x = 0;
- m_usedImgSize.y = 0;
+int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
+ unsigned int pos, wxClientData *clientData)
+{
+ const int n = wxOwnerDrawnComboBox::Insert(item, pos, clientData);
+ if(n != wxNOT_FOUND)
+ SetItemBitmap(n, bitmap);
+ return n;
+}
- DetermineIndent();
+void wxBitmapComboBox::DoClear()
+{
+ wxOwnerDrawnComboBox::DoClear();
+ wxBitmapComboBoxBase::BCBDoClear();
}
-void wxBitmapComboBox::Delete(unsigned int n)
+void wxBitmapComboBox::DoDeleteOneItem(unsigned int n)
{
- wxOwnerDrawnComboBox::Delete(n);
- delete GetBitmapPtr(n);
- m_bitmaps.RemoveAt(n);
+ wxOwnerDrawnComboBox::DoDeleteOneItem(n);
+ wxBitmapComboBoxBase::BCBDoDeleteOneItem(n);
}
// ----------------------------------------------------------------------------
// wxBitmapComboBox event handlers and such
// ----------------------------------------------------------------------------
-void wxBitmapComboBox::DetermineIndent()
-{
- //
- // Recalculate amount of empty space needed in front of
- // text in control itself.
- int indent = m_imgAreaWidth = 0;
-
- if ( m_usedImgSize.x > 0 )
- {
- indent = m_usedImgSize.y + IMAGE_SPACING_LEFT + IMAGE_SPACING_RIGHT;
- m_imgAreaWidth = indent;
-
- indent -= 3;
- }
-
- SetCustomPaintWidth(indent);
-}
-
-void wxBitmapComboBox::OnResize(wxSizeEvent& event)
+void wxBitmapComboBox::OnSize(wxSizeEvent& event)
{
// Prevent infinite looping
if ( !m_inResize )
{
wxSize sz = wxOwnerDrawnComboBox::DoGetBestSize();
- // Scale control to match height of highest image.
- int h2 = m_usedImgSize.y + IMAGE_SPACING_CTRL_VERTICAL;
+ if ( HasFlag(wxCB_READONLY) )
+ {
+ // Scale control to match height of highest image.
+ int h2 = m_usedImgSize.y + IMAGE_SPACING_CTRL_VERTICAL;
- if ( h2 > sz.y )
- sz.y = h2;
+ if ( h2 > sz.y )
+ sz.y = h2;
+
+ CacheBestSize(sz);
+ }
- CacheBestSize(sz);
return sz;
}
bool wxBitmapComboBox::SetFont(const wxFont& font)
{
bool res = wxOwnerDrawnComboBox::SetFont(font);
- m_fontHeight = GetCharHeight() + EXTRA_FONT_HEIGHT;
+ UpdateInternals();
return res;
}
{
if ( GetCustomPaintWidth() == 0 ||
!(flags & wxODCB_PAINTING_SELECTED) ||
- item < 0 )
+ item < 0 ||
+ ( (flags & wxODCB_PAINTING_CONTROL) && (GetInternalFlags() & wxCC_FULL_BUTTON)) )
{
wxOwnerDrawnComboBox::OnDrawBackground(dc, rect, item, flags);
return;
}
- //
- // Just paint simple selection background under where is text
- // (ie. emulate what MSW image choice does).
- //
-
- int xPos = 0; // Starting x of selection rectangle
- const int vSizeDec = 1; // Vertical size reduction of selection rectangle edges
-
- xPos = GetCustomPaintWidth() + 2;
-
- wxCoord x, y;
- GetTextExtent(GetString(item), &x, &y, 0, 0);
-
- dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
-
- wxColour selCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
- dc.SetPen(selCol);
- dc.SetBrush(selCol);
- dc.DrawRectangle(rect.x+xPos,
- rect.y+vSizeDec,
- x + 4,
- rect.height-(vSizeDec*2));
+ wxBitmapComboBoxBase::DrawBackground(dc, rect, item, flags);
}
void wxBitmapComboBox::OnDrawItem(wxDC& dc,
{
wxString text;
int imgAreaWidth = m_imgAreaWidth;
- bool drawText;
if ( imgAreaWidth == 0 )
{
if ( flags & wxODCB_PAINTING_CONTROL )
{
text = GetValue();
- if ( HasFlag(wxCB_READONLY) )
- drawText = true;
- else
- drawText = false;
+ if ( !HasFlag(wxCB_READONLY) )
+ text.clear();
}
else
{
text = GetString(item);
- drawText = true;
- }
-
- const wxBitmap& bmp = *GetBitmapPtr(item);
- if ( bmp.Ok() )
- {
- wxCoord w = bmp.GetWidth();
- wxCoord h = bmp.GetHeight();
-
- // Draw the image centered
- dc.DrawBitmap(bmp,
- rect.x + (m_usedImgSize.x-w)/2 + IMAGE_SPACING_LEFT,
- rect.y + (rect.height-h)/2,
- true);
}
- if ( drawText )
- dc.DrawText(GetString(item),
- rect.x + imgAreaWidth + 1,
- rect.y + (rect.height-dc.GetCharHeight())/2);
+ wxBitmapComboBoxBase::DrawItem(dc, rect, item, text, flags);
}
-wxCoord wxBitmapComboBox::OnMeasureItem(size_t WXUNUSED(item)) const
+wxCoord wxBitmapComboBox::OnMeasureItem(size_t item) const
{
- int imgHeightArea = m_usedImgSize.y + 2;
- return imgHeightArea > m_fontHeight ? imgHeightArea : m_fontHeight;
+ return wxBitmapComboBoxBase::MeasureItem(item);
}
wxCoord wxBitmapComboBox::OnMeasureItemWidth(size_t item) const