native wxBitmapComboBox implementation for MSW (patch 1941399)
[wxWidgets.git] / src / generic / bmpcboxg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/bmpcboxg.cpp
3 // Purpose: wxBitmapComboBox
4 // Author: Jaakko Salli
5 // Modified by:
6 // Created: Aug-31-2006
7 // RCS-ID: $Id$
8 // Copyright: (c) 2005 Jaakko Salli
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_BITMAPCOMBOBOX
27
28 #include "wx/bmpcbox.h"
29
30 #if defined(wxGENERIC_BITMAPCOMBOBOX)
31
32 #ifndef WX_PRECOMP
33 #include "wx/log.h"
34 #endif
35
36 #include "wx/odcombo.h"
37 #include "wx/settings.h"
38 #include "wx/dc.h"
39
40 #if wxUSE_IMAGE
41 #include "wx/image.h"
42 #endif
43
44
45 #define IMAGE_SPACING_CTRL_VERTICAL 7 // Spacing used in control size calculation
46
47
48 // ============================================================================
49 // implementation
50 // ============================================================================
51
52
53 BEGIN_EVENT_TABLE(wxBitmapComboBox, wxOwnerDrawnComboBox)
54 EVT_SIZE(wxBitmapComboBox::OnSize)
55 END_EVENT_TABLE()
56
57
58 IMPLEMENT_DYNAMIC_CLASS(wxBitmapComboBox, wxOwnerDrawnComboBox)
59
60 void wxBitmapComboBox::Init()
61 {
62 m_inResize = false;
63 }
64
65 wxBitmapComboBox::wxBitmapComboBox(wxWindow *parent,
66 wxWindowID id,
67 const wxString& value,
68 const wxPoint& pos,
69 const wxSize& size,
70 const wxArrayString& choices,
71 long style,
72 const wxValidator& validator,
73 const wxString& name)
74 : wxOwnerDrawnComboBox(),
75 wxBitmapComboBoxBase()
76 {
77 Init();
78
79 Create(parent,id,value,pos,size,choices,style,validator,name);
80 }
81
82 bool wxBitmapComboBox::Create(wxWindow *parent,
83 wxWindowID id,
84 const wxString& value,
85 const wxPoint& pos,
86 const wxSize& size,
87 const wxArrayString& choices,
88 long style,
89 const wxValidator& validator,
90 const wxString& name)
91 {
92 if ( !wxOwnerDrawnComboBox::Create(parent, id, value,
93 pos, size,
94 choices, style,
95 validator, name) )
96 {
97 return false;
98 }
99
100 UpdateInternals();
101
102 return true;
103 }
104
105 bool wxBitmapComboBox::Create(wxWindow *parent,
106 wxWindowID id,
107 const wxString& value,
108 const wxPoint& pos,
109 const wxSize& size,
110 int n,
111 const wxString choices[],
112 long style,
113 const wxValidator& validator,
114 const wxString& name)
115 {
116 if ( !wxOwnerDrawnComboBox::Create(parent, id, value,
117 pos, size, n,
118 choices, style,
119 validator, name) )
120 {
121 return false;
122 }
123
124 UpdateInternals();
125
126 return true;
127 }
128
129 wxBitmapComboBox::~wxBitmapComboBox()
130 {
131 Clear();
132 }
133
134 // ----------------------------------------------------------------------------
135 // Item manipulation
136 // ----------------------------------------------------------------------------
137
138 void wxBitmapComboBox::SetItemBitmap(unsigned int n, const wxBitmap& bitmap)
139 {
140 OnAddBitmap(bitmap);
141 DoSetItemBitmap(n, bitmap);
142
143 if ( (int)n == GetSelection() )
144 Refresh();
145 }
146
147 int wxBitmapComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
148 unsigned int pos,
149 void **clientData, wxClientDataType type)
150 {
151 const unsigned int numItems = items.GetCount();
152 const unsigned int countNew = GetCount() + numItems;
153
154 m_bitmaps.Alloc(countNew);
155
156 for ( unsigned int i = 0; i < numItems; i++ )
157 {
158 m_bitmaps.Insert(new wxBitmap(wxNullBitmap), pos + i);
159 }
160
161 const int index = wxOwnerDrawnComboBox::DoInsertItems(items, pos,
162 clientData, type);
163
164 if ( index == wxNOT_FOUND )
165 {
166 for ( int i = numItems-1; i >= 0; i-- )
167 BCBDoDeleteOneItem(pos + i);
168 }
169
170 return index;
171 }
172
173 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap)
174 {
175 const int n = wxOwnerDrawnComboBox::Append(item);
176 if(n != wxNOT_FOUND)
177 SetItemBitmap(n, bitmap);
178 return n;
179 }
180
181 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
182 void *clientData)
183 {
184 const int n = wxOwnerDrawnComboBox::Append(item, clientData);
185 if(n != wxNOT_FOUND)
186 SetItemBitmap(n, bitmap);
187 return n;
188 }
189
190 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
191 wxClientData *clientData)
192 {
193 const int n = wxOwnerDrawnComboBox::Append(item, clientData);
194 if(n != wxNOT_FOUND)
195 SetItemBitmap(n, bitmap);
196 return n;
197 }
198
199 int wxBitmapComboBox::Insert(const wxString& item,
200 const wxBitmap& bitmap,
201 unsigned int pos)
202 {
203 const int n = wxOwnerDrawnComboBox::Insert(item, pos);
204 if(n != wxNOT_FOUND)
205 SetItemBitmap(n, bitmap);
206 return n;
207 }
208
209 int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
210 unsigned int pos, void *clientData)
211 {
212 const int n = wxOwnerDrawnComboBox::Insert(item, pos, clientData);
213 if(n != wxNOT_FOUND)
214 SetItemBitmap(n, bitmap);
215 return n;
216 }
217
218 int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
219 unsigned int pos, wxClientData *clientData)
220 {
221 const int n = wxOwnerDrawnComboBox::Insert(item, pos, clientData);
222 if(n != wxNOT_FOUND)
223 SetItemBitmap(n, bitmap);
224 return n;
225 }
226
227 void wxBitmapComboBox::DoClear()
228 {
229 wxOwnerDrawnComboBox::DoClear();
230 wxBitmapComboBoxBase::BCBDoClear();
231 }
232
233 void wxBitmapComboBox::DoDeleteOneItem(unsigned int n)
234 {
235 wxOwnerDrawnComboBox::DoDeleteOneItem(n);
236 wxBitmapComboBoxBase::BCBDoDeleteOneItem(n);
237 }
238
239 // ----------------------------------------------------------------------------
240 // wxBitmapComboBox event handlers and such
241 // ----------------------------------------------------------------------------
242
243 void wxBitmapComboBox::OnSize(wxSizeEvent& event)
244 {
245 // Prevent infinite looping
246 if ( !m_inResize )
247 {
248 m_inResize = true;
249 DetermineIndent();
250 m_inResize = false;
251 }
252
253 event.Skip();
254 }
255
256 wxSize wxBitmapComboBox::DoGetBestSize() const
257 {
258 wxSize sz = wxOwnerDrawnComboBox::DoGetBestSize();
259
260 if ( HasFlag(wxCB_READONLY) )
261 {
262 // Scale control to match height of highest image.
263 int h2 = m_usedImgSize.y + IMAGE_SPACING_CTRL_VERTICAL;
264
265 if ( h2 > sz.y )
266 sz.y = h2;
267
268 CacheBestSize(sz);
269 }
270
271 return sz;
272 }
273
274 // ----------------------------------------------------------------------------
275 // wxBitmapComboBox miscellaneous
276 // ----------------------------------------------------------------------------
277
278 bool wxBitmapComboBox::SetFont(const wxFont& font)
279 {
280 bool res = wxOwnerDrawnComboBox::SetFont(font);
281 UpdateInternals();
282 return res;
283 }
284
285 // ----------------------------------------------------------------------------
286 // wxBitmapComboBox item drawing and measuring
287 // ----------------------------------------------------------------------------
288
289 void wxBitmapComboBox::OnDrawBackground(wxDC& dc,
290 const wxRect& rect,
291 int item,
292 int flags) const
293 {
294 if ( GetCustomPaintWidth() == 0 ||
295 !(flags & wxODCB_PAINTING_SELECTED) ||
296 item < 0 ||
297 ( (flags & wxODCB_PAINTING_CONTROL) && (GetInternalFlags() & wxCC_FULL_BUTTON)) )
298 {
299 wxOwnerDrawnComboBox::OnDrawBackground(dc, rect, item, flags);
300 return;
301 }
302
303 wxBitmapComboBoxBase::DrawBackground(dc, rect, item, flags);
304 }
305
306 void wxBitmapComboBox::OnDrawItem(wxDC& dc,
307 const wxRect& rect,
308 int item,
309 int flags) const
310 {
311 wxString text;
312 int imgAreaWidth = m_imgAreaWidth;
313
314 if ( imgAreaWidth == 0 )
315 {
316 wxOwnerDrawnComboBox::OnDrawItem(dc, rect, item, flags);
317 return;
318 }
319
320 if ( flags & wxODCB_PAINTING_CONTROL )
321 {
322 text = GetValue();
323 if ( !HasFlag(wxCB_READONLY) )
324 text.clear();
325 }
326 else
327 {
328 text = GetString(item);
329 }
330
331 wxBitmapComboBoxBase::DrawItem(dc, rect, item, text, flags);
332 }
333
334 wxCoord wxBitmapComboBox::OnMeasureItem(size_t item) const
335 {
336 return wxBitmapComboBoxBase::MeasureItem(item);
337 }
338
339 wxCoord wxBitmapComboBox::OnMeasureItemWidth(size_t item) const
340 {
341 wxCoord x, y;
342 GetTextExtent(GetString(item), &x, &y, 0, 0);
343 x += m_imgAreaWidth;
344 return x;
345 }
346
347 #endif // defined(wxGENERIC_BITMAPCOMBOBOX)
348
349 #endif // wxUSE_BITMAPCOMBOBOX