]> git.saurik.com Git - wxWidgets.git/blob - src/generic/bmpcboxg.cpp
Fix crash in wxDC::GetMultiLineTextExtent() after last commit.
[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 DoClear();
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 wxASSERT( numItems == 1 || !HasFlag(wxCB_SORT) ); // Sanity check
155
156 m_bitmaps.Alloc(countNew);
157
158 for ( unsigned int i = 0; i < numItems; i++ )
159 {
160 m_bitmaps.Insert(new wxBitmap(wxNullBitmap), pos + i);
161 }
162
163 const int index = wxOwnerDrawnComboBox::DoInsertItems(items, pos,
164 clientData, type);
165
166 if ( index == wxNOT_FOUND )
167 {
168 for ( int i = numItems-1; i >= 0; i-- )
169 BCBDoDeleteOneItem(pos + i);
170 }
171 else if ( ((unsigned int)index) != pos )
172 {
173 // Move pre-inserted empty bitmap into correct position
174 // (usually happens when combo box has wxCB_SORT style)
175 wxBitmap* bmp = static_cast<wxBitmap*>(m_bitmaps[pos]);
176 m_bitmaps.RemoveAt(pos);
177 m_bitmaps.Insert(bmp, index);
178 }
179
180 return index;
181 }
182
183 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap)
184 {
185 const int n = wxOwnerDrawnComboBox::Append(item);
186 if(n != wxNOT_FOUND)
187 SetItemBitmap(n, bitmap);
188 return n;
189 }
190
191 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
192 void *clientData)
193 {
194 const int n = wxOwnerDrawnComboBox::Append(item, clientData);
195 if(n != wxNOT_FOUND)
196 SetItemBitmap(n, bitmap);
197 return n;
198 }
199
200 int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
201 wxClientData *clientData)
202 {
203 const int n = wxOwnerDrawnComboBox::Append(item, clientData);
204 if(n != wxNOT_FOUND)
205 SetItemBitmap(n, bitmap);
206 return n;
207 }
208
209 int wxBitmapComboBox::Insert(const wxString& item,
210 const wxBitmap& bitmap,
211 unsigned int pos)
212 {
213 const int n = wxOwnerDrawnComboBox::Insert(item, pos);
214 if(n != wxNOT_FOUND)
215 SetItemBitmap(n, bitmap);
216 return n;
217 }
218
219 int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
220 unsigned int pos, void *clientData)
221 {
222 const int n = wxOwnerDrawnComboBox::Insert(item, pos, clientData);
223 if(n != wxNOT_FOUND)
224 SetItemBitmap(n, bitmap);
225 return n;
226 }
227
228 int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
229 unsigned int pos, wxClientData *clientData)
230 {
231 const int n = wxOwnerDrawnComboBox::Insert(item, pos, clientData);
232 if(n != wxNOT_FOUND)
233 SetItemBitmap(n, bitmap);
234 return n;
235 }
236
237 void wxBitmapComboBox::DoClear()
238 {
239 wxOwnerDrawnComboBox::DoClear();
240 wxBitmapComboBoxBase::BCBDoClear();
241 }
242
243 void wxBitmapComboBox::DoDeleteOneItem(unsigned int n)
244 {
245 wxOwnerDrawnComboBox::DoDeleteOneItem(n);
246 wxBitmapComboBoxBase::BCBDoDeleteOneItem(n);
247 }
248
249 // ----------------------------------------------------------------------------
250 // wxBitmapComboBox event handlers and such
251 // ----------------------------------------------------------------------------
252
253 void wxBitmapComboBox::OnSize(wxSizeEvent& event)
254 {
255 // Prevent infinite looping
256 if ( !m_inResize )
257 {
258 m_inResize = true;
259 DetermineIndent();
260 m_inResize = false;
261 }
262
263 event.Skip();
264 }
265
266 wxSize wxBitmapComboBox::DoGetBestSize() const
267 {
268 wxSize sz = wxOwnerDrawnComboBox::DoGetBestSize();
269
270 if ( HasFlag(wxCB_READONLY) )
271 {
272 // Scale control to match height of highest image.
273 int h2 = m_usedImgSize.y + IMAGE_SPACING_CTRL_VERTICAL;
274
275 if ( h2 > sz.y )
276 sz.y = h2;
277
278 CacheBestSize(sz);
279 }
280
281 return sz;
282 }
283
284 // ----------------------------------------------------------------------------
285 // wxBitmapComboBox miscellaneous
286 // ----------------------------------------------------------------------------
287
288 bool wxBitmapComboBox::SetFont(const wxFont& font)
289 {
290 bool res = wxOwnerDrawnComboBox::SetFont(font);
291 UpdateInternals();
292 return res;
293 }
294
295 // ----------------------------------------------------------------------------
296 // wxBitmapComboBox item drawing and measuring
297 // ----------------------------------------------------------------------------
298
299 void wxBitmapComboBox::OnDrawBackground(wxDC& dc,
300 const wxRect& rect,
301 int item,
302 int flags) const
303 {
304 if ( GetCustomPaintWidth() == 0 ||
305 !(flags & wxODCB_PAINTING_SELECTED) ||
306 item < 0 ||
307 ( (flags & wxODCB_PAINTING_CONTROL) && (GetInternalFlags() & wxCC_FULL_BUTTON)) )
308 {
309 wxOwnerDrawnComboBox::OnDrawBackground(dc, rect, item, flags);
310 return;
311 }
312
313 wxBitmapComboBoxBase::DrawBackground(dc, rect, item, flags);
314 }
315
316 void wxBitmapComboBox::OnDrawItem(wxDC& dc,
317 const wxRect& rect,
318 int item,
319 int flags) const
320 {
321 wxString text;
322 int imgAreaWidth = m_imgAreaWidth;
323
324 if ( imgAreaWidth == 0 )
325 {
326 wxOwnerDrawnComboBox::OnDrawItem(dc, rect, item, flags);
327 return;
328 }
329
330 if ( flags & wxODCB_PAINTING_CONTROL )
331 {
332 text = GetValue();
333 if ( !HasFlag(wxCB_READONLY) )
334 text.clear();
335 }
336 else
337 {
338 text = GetString(item);
339 }
340
341 wxBitmapComboBoxBase::DrawItem(dc, rect, item, text, flags);
342 }
343
344 wxCoord wxBitmapComboBox::OnMeasureItem(size_t item) const
345 {
346 return wxBitmapComboBoxBase::MeasureItem(item);
347 }
348
349 wxCoord wxBitmapComboBox::OnMeasureItemWidth(size_t item) const
350 {
351 wxCoord x, y;
352 GetTextExtent(GetString(item), &x, &y, 0, 0);
353 x += m_imgAreaWidth;
354 return x;
355 }
356
357 #endif // defined(wxGENERIC_BITMAPCOMBOBOX)
358
359 #endif // wxUSE_BITMAPCOMBOBOX