]> git.saurik.com Git - wxWidgets.git/blob - src/common/bmpcboxcmn.cpp
native wxBitmapComboBox implementation for MSW (patch 1941399)
[wxWidgets.git] / src / common / bmpcboxcmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/bmpcboxcmn.cpp
3 // Purpose: wxBitmapComboBox
4 // Author: Jaakko Salli
5 // Created: 2008-04-09
6 // RCS-ID: $Id:$
7 // Copyright: (c) 2008 Jaakko Salli
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #include "wx/wxprec.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
25 #include "wx/bmpcbox.h"
26
27 #if wxUSE_BITMAPCOMBOBOX
28
29 #ifndef WX_PRECOMP
30 #include "wx/log.h"
31 #endif
32
33 #include "wx/settings.h"
34
35 // For wxODCB_XXX flags
36 #include "wx/odcombo.h"
37
38
39 const wxChar wxBitmapComboBoxNameStr[] = wxT("bitmapComboBox");
40
41 #if defined(wxBITMAPCOMBOBOX_OWNERDRAWN_BASED)
42
43 #define IMAGE_SPACING_RIGHT 4 // Space left of image
44
45 #define IMAGE_SPACING_LEFT 4 // Space right of image, left of text
46
47 #define EXTRA_FONT_HEIGHT 0 // Add to increase min. height of list items
48
49 #define wxBCB_DEFAULT_ITEM_HEIGHT 13
50
51
52 // This macros allows wxArrayPtrVoid to be used in more convenient manner
53 #define GetBitmapPtr(n) ((wxBitmap*)m_bitmaps[n])
54
55
56 // ----------------------------------------------------------------------------
57 // Initialization
58 // ----------------------------------------------------------------------------
59
60 void wxBitmapComboBoxBase::Init()
61 {
62 m_fontHeight = 0;
63 m_imgAreaWidth = 0;
64 m_indent = 0;
65 m_usedImgSize = wxSize(-1, -1);
66 }
67
68 void wxBitmapComboBoxBase::UpdateInternals()
69 {
70 m_fontHeight = GetControl()->GetCharHeight() + EXTRA_FONT_HEIGHT;
71
72 while ( m_bitmaps.GetCount() < GetItemContainer()->GetCount() )
73 m_bitmaps.Add( new wxBitmap() );
74 }
75
76 // ----------------------------------------------------------------------------
77 // Item manipulation
78 // ----------------------------------------------------------------------------
79
80 void wxBitmapComboBoxBase::DoSetItemBitmap(unsigned int n, const wxBitmap& bitmap)
81 {
82 wxCHECK_RET( n < m_bitmaps.size(), "invalid item index" );
83 *GetBitmapPtr(n) = bitmap;
84 }
85
86 wxBitmap wxBitmapComboBoxBase::GetItemBitmap(unsigned int n) const
87 {
88 wxCHECK_MSG( n < m_bitmaps.size(), wxNullBitmap, "invalid item index" );
89 return *GetBitmapPtr(n);
90 }
91
92 // ----------------------------------------------------------------------------
93 // wxItemContainer methods
94 // ----------------------------------------------------------------------------
95
96 void wxBitmapComboBoxBase::BCBDoClear()
97 {
98 for ( unsigned i = 0; i < m_bitmaps.size(); i++ )
99 delete GetBitmapPtr(i);
100
101 m_bitmaps.Empty();
102
103 m_usedImgSize.x = -1;
104 m_usedImgSize.y = -1;
105
106 DetermineIndent();
107 }
108
109 void wxBitmapComboBoxBase::BCBDoDeleteOneItem(unsigned int n)
110 {
111 delete GetBitmapPtr(n);
112 m_bitmaps.RemoveAt(n);
113 }
114
115 // ----------------------------------------------------------------------------
116 // Preparation and Calculations
117 // ----------------------------------------------------------------------------
118
119 bool wxBitmapComboBoxBase::OnAddBitmap(const wxBitmap& bitmap)
120 {
121 if ( bitmap.IsOk() )
122 {
123 int width = bitmap.GetWidth();
124 int height = bitmap.GetHeight();
125
126 if ( m_usedImgSize.x < 0 )
127 {
128 // If size not yet determined, get it from this image.
129 m_usedImgSize.x = width;
130 m_usedImgSize.y = height;
131
132 // Adjust control size to vertically fit the bitmap
133 wxWindow* ctrl = GetControl();
134 ctrl->InvalidateBestSize();
135 wxSize newSz = ctrl->GetBestSize();
136 wxSize sz = ctrl->GetSize();
137 if ( newSz.y > sz.y )
138 ctrl->SetSize(sz.x, newSz.y);
139 else
140 DetermineIndent();
141 }
142
143 wxCHECK_MSG( width == m_usedImgSize.x && height == m_usedImgSize.y,
144 false,
145 "you can only add images of same size" );
146
147 return true;
148 }
149
150 return false;
151 }
152
153 int wxBitmapComboBoxBase::DetermineIndent()
154 {
155 // Recalculate amount of empty space needed in front of
156 // text in control itself.
157 int indent = m_imgAreaWidth = 0;
158
159 if ( m_usedImgSize.x > 0 )
160 {
161 indent = m_usedImgSize.x + IMAGE_SPACING_LEFT + IMAGE_SPACING_RIGHT;
162 m_imgAreaWidth = indent;
163
164 indent -= 3;
165 }
166
167 return indent;
168 }
169
170 // ----------------------------------------------------------------------------
171 // Item drawing and measuring
172 // ----------------------------------------------------------------------------
173
174 void wxBitmapComboBoxBase::DrawBackground(wxDC& dc,
175 const wxRect& rect,
176 int WXUNUSED(item),
177 int flags) const
178 {
179 if ( flags & wxODCB_PAINTING_SELECTED )
180 {
181 const int vSizeDec = 0; // Vertical size reduction of selection rectangle edges
182
183 dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
184
185 wxColour selCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
186 dc.SetPen(selCol);
187 dc.SetBrush(selCol);
188 dc.DrawRectangle(rect.x,
189 rect.y+vSizeDec,
190 rect.width,
191 rect.height-(vSizeDec*2));
192 }
193 else
194 {
195 dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
196
197 wxColour selCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
198 dc.SetPen(selCol);
199 dc.SetBrush(selCol);
200 dc.DrawRectangle(rect);
201 }
202 }
203
204 void wxBitmapComboBoxBase::DrawItem(wxDC& dc,
205 const wxRect& rect,
206 int item,
207 const wxString& text,
208 int WXUNUSED(flags)) const
209 {
210 const wxBitmap& bmp = *GetBitmapPtr(item);
211 if ( bmp.IsOk() )
212 {
213 wxCoord w = bmp.GetWidth();
214 wxCoord h = bmp.GetHeight();
215
216 // Draw the image centered
217 dc.DrawBitmap(bmp,
218 rect.x + (m_usedImgSize.x-w)/2 + IMAGE_SPACING_LEFT,
219 rect.y + (rect.height-h)/2,
220 true);
221 }
222
223 if ( text.length() )
224 dc.DrawText(text,
225 rect.x + m_imgAreaWidth + 1,
226 rect.y + (rect.height-dc.GetCharHeight())/2);
227 }
228
229 wxCoord wxBitmapComboBoxBase::MeasureItem(size_t WXUNUSED(item)) const
230 {
231 if ( m_usedImgSize.y >= 0 )
232 {
233 int imgHeightArea = m_usedImgSize.y + 2;
234 return imgHeightArea > m_fontHeight ? imgHeightArea : m_fontHeight;
235 }
236
237 return wxBCB_DEFAULT_ITEM_HEIGHT;
238 }
239
240 #endif // wxBITMAPCOMBOBOX_OWNERDRAWN_BASED
241
242 #endif // wxUSE_BITMAPCOMBOBOX