]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bmpcbox.cpp
Add missing t_str() call to fix wxUSE_STL build after r73792.
[wxWidgets.git] / src / msw / bmpcbox.cpp
CommitLineData
f696015c 1/////////////////////////////////////////////////////////////////////////////
80fdcdb9 2// Name: src/msw/bmpcbox.cpp
f696015c
VZ
3// Purpose: wxBitmapComboBox
4// Author: Jaakko Salli
5// Created: 2008-04-06
41fb3475 6// RCS-ID: $Id$
f696015c
VZ
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#if wxUSE_BITMAPCOMBOBOX
26
27#include "wx/bmpcbox.h"
28
29#ifndef WX_PRECOMP
30 #include "wx/log.h"
31#endif
32
33#include "wx/settings.h"
4f082fb3 34#include "wx/vector.h"
f696015c
VZ
35
36#include "wx/msw/dcclient.h"
37#include "wx/msw/private.h"
38
39// For wxODCB_XXX flags
40#include "wx/odcombo.h"
41
42
43#define IMAGE_SPACING_CTRL_VERTICAL 7 // Spacing used in control size calculation
44
45
46// ============================================================================
47// implementation
48// ============================================================================
49
50
51BEGIN_EVENT_TABLE(wxBitmapComboBox, wxComboBox)
52 EVT_SIZE(wxBitmapComboBox::OnSize)
53END_EVENT_TABLE()
54
55
56IMPLEMENT_DYNAMIC_CLASS(wxBitmapComboBox, wxComboBox)
57
58
59// ----------------------------------------------------------------------------
60// wxBitmapComboBox creation
61// ----------------------------------------------------------------------------
62
63void wxBitmapComboBox::Init()
64{
65 m_inResize = false;
66}
67
68wxBitmapComboBox::wxBitmapComboBox(wxWindow *parent,
69 wxWindowID id,
70 const wxString& value,
71 const wxPoint& pos,
72 const wxSize& size,
73 const wxArrayString& choices,
74 long style,
75 const wxValidator& validator,
76 const wxString& name)
77 : wxComboBox(),
78 wxBitmapComboBoxBase()
79{
80 Init();
81
82 Create(parent,id,value,pos,size,choices,style,validator,name);
83}
84
85bool wxBitmapComboBox::Create(wxWindow *parent,
86 wxWindowID id,
87 const wxString& value,
88 const wxPoint& pos,
89 const wxSize& size,
90 const wxArrayString& choices,
91 long style,
92 const wxValidator& validator,
93 const wxString& name)
94{
95 wxCArrayString chs(choices);
96 return Create(parent, id, value, pos, size, chs.GetCount(),
97 chs.GetStrings(), style, validator, name);
98}
99
100bool wxBitmapComboBox::Create(wxWindow *parent,
101 wxWindowID id,
102 const wxString& value,
103 const wxPoint& pos,
104 const wxSize& size,
105 int n,
106 const wxString choices[],
107 long style,
108 const wxValidator& validator,
109 const wxString& name)
110{
111 if ( !wxComboBox::Create(parent, id, value, pos, size,
112 n, choices, style, validator, name) )
113 return false;
114
115 UpdateInternals();
116
117 return true;
118}
119
120WXDWORD wxBitmapComboBox::MSWGetStyle(long style, WXDWORD *exstyle) const
121{
122 return wxComboBox::MSWGetStyle(style, exstyle) | CBS_OWNERDRAWFIXED | CBS_HASSTRINGS;
123}
124
125void wxBitmapComboBox::RecreateControl()
126{
127 //
128 // Recreate control so that WM_MEASUREITEM gets called again.
129 // Can't use CBS_OWNERDRAWVARIABLE because it has odd
130 // mouse-wheel behaviour.
131 //
132 wxString value = GetValue();
133 wxPoint pos = GetPosition();
134 wxSize size = GetSize();
a9afb057 135 size.y = GetBestSize().y;
f696015c
VZ
136 wxArrayString strings = GetStrings();
137
4f082fb3
VZ
138 // Save the client data pointers before clearing the control.
139 wxVector<wxClientData*> clientData;
140 clientData.reserve(strings.size());
141 for ( size_t n = 0; n < strings.size(); ++n )
142 clientData.push_back(GetClientObject(n));
143
f696015c
VZ
144 wxComboBox::DoClear();
145
146 HWND hwnd = GetHwnd();
147 DissociateHandle();
148 ::DestroyWindow(hwnd);
149
4f320d7c 150 if ( !MSWCreateControl(wxT("COMBOBOX"), wxEmptyString, pos, size) )
f696015c
VZ
151 return;
152
153 // initialize the controls contents
154 for ( unsigned int i = 0; i < strings.size(); i++ )
155 {
4f082fb3 156 wxComboBox::Append(strings[i], clientData[i]);
f696015c
VZ
157 }
158
159 // and make sure it has the same attributes as before
160 if ( m_hasFont )
161 {
162 // calling SetFont(m_font) would do nothing as the code would
163 // notice that the font didn't change, so force it to believe
164 // that it did
165 wxFont font = m_font;
166 m_font = wxNullFont;
167 SetFont(font);
168 }
169
170 if ( m_hasFgCol )
171 {
172 wxColour colFg = m_foregroundColour;
173 m_foregroundColour = wxNullColour;
174 SetForegroundColour(colFg);
175 }
176
177 if ( m_hasBgCol )
178 {
179 wxColour colBg = m_backgroundColour;
180 m_backgroundColour = wxNullColour;
181 SetBackgroundColour(colBg);
182 }
183 else
184 {
185 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
186 }
a9afb057
JS
187
188 ::SendMessage(GetHwnd(), CB_SETITEMHEIGHT, 0, MeasureItem(0));
4f320d7c
JS
189
190 // Revert the old string value
df541b86
JS
191 if ( !HasFlag(wxCB_READONLY) )
192 ChangeValue(value);
f696015c
VZ
193}
194
195wxBitmapComboBox::~wxBitmapComboBox()
196{
197 Clear();
198}
199
41ce9ae1
JS
200wxSize wxBitmapComboBox::DoGetBestSize() const
201{
202 wxSize best = wxComboBox::DoGetBestSize();
203 wxSize bitmapSize = GetBitmapSize();
204
205 wxCoord useHeightBitmap = EDIT_HEIGHT_FROM_CHAR_HEIGHT(bitmapSize.y);
206 if ( best.y < useHeightBitmap )
207 {
208 best.y = useHeightBitmap;
209 CacheBestSize(best);
210 }
211 return best;
212}
213
f696015c
VZ
214// ----------------------------------------------------------------------------
215// Item manipulation
216// ----------------------------------------------------------------------------
217
218void wxBitmapComboBox::SetItemBitmap(unsigned int n, const wxBitmap& bitmap)
219{
220 OnAddBitmap(bitmap);
221 DoSetItemBitmap(n, bitmap);
222
223 if ( (int)n == GetSelection() )
224 Refresh();
225}
226
227int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap)
228{
229 OnAddBitmap(bitmap);
230 const int n = wxComboBox::Append(item);
231 if ( n != wxNOT_FOUND )
232 DoSetItemBitmap(n, bitmap);
233 return n;
234}
235
236int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
237 void *clientData)
238{
239 OnAddBitmap(bitmap);
240 const int n = wxComboBox::Append(item, clientData);
241 if ( n != wxNOT_FOUND )
242 DoSetItemBitmap(n, bitmap);
243 return n;
244}
245
246int wxBitmapComboBox::Append(const wxString& item, const wxBitmap& bitmap,
247 wxClientData *clientData)
248{
249 OnAddBitmap(bitmap);
250 const int n = wxComboBox::Append(item, clientData);
251 if ( n != wxNOT_FOUND )
252 DoSetItemBitmap(n, bitmap);
253 return n;
254}
255
256int wxBitmapComboBox::Insert(const wxString& item,
257 const wxBitmap& bitmap,
258 unsigned int pos)
259{
260 OnAddBitmap(bitmap);
261 const int n = wxComboBox::Insert(item, pos);
262 if ( n != wxNOT_FOUND )
263 DoSetItemBitmap(n, bitmap);
264 return n;
265}
266
05f5b3f7
VZ
267int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
268 unsigned int pos, void *clientData)
269{
270 OnAddBitmap(bitmap);
271 const int n = wxComboBox::Insert(item, pos, clientData);
272 if ( n != wxNOT_FOUND )
273 DoSetItemBitmap(n, bitmap);
274 return n;
275}
276
f696015c
VZ
277int wxBitmapComboBox::Insert(const wxString& item, const wxBitmap& bitmap,
278 unsigned int pos, wxClientData *clientData)
279{
280 OnAddBitmap(bitmap);
281 const int n = wxComboBox::Insert(item, pos, clientData);
282 if ( n != wxNOT_FOUND )
283 DoSetItemBitmap(n, bitmap);
284 return n;
285}
286
287int wxBitmapComboBox::DoInsertItems(const wxArrayStringsAdapter & items,
288 unsigned int pos,
289 void **clientData, wxClientDataType type)
290{
291 const unsigned int numItems = items.GetCount();
292 const unsigned int countNew = GetCount() + numItems;
293
befee9b7
JS
294 wxASSERT( numItems == 1 || !HasFlag(wxCB_SORT) ); // Sanity check
295
f696015c
VZ
296 m_bitmaps.Alloc(countNew);
297
298 for ( unsigned int i = 0; i < numItems; i++ )
299 {
300 m_bitmaps.Insert(new wxBitmap(wxNullBitmap), pos + i);
301 }
302
303 const int index = wxComboBox::DoInsertItems(items, pos,
304 clientData, type);
305
306 if ( index == wxNOT_FOUND )
307 {
308 for ( int i = numItems-1; i >= 0; i-- )
309 BCBDoDeleteOneItem(pos + i);
310 }
befee9b7
JS
311 else if ( ((unsigned int)index) != pos )
312 {
313 // Move pre-inserted empty bitmap into correct position
314 // (usually happens when combo box has wxCB_SORT style)
315 wxBitmap* bmp = static_cast<wxBitmap*>(m_bitmaps[pos]);
316 m_bitmaps.RemoveAt(pos);
317 m_bitmaps.Insert(bmp, index);
318 }
f696015c
VZ
319
320 return index;
321}
322
323bool wxBitmapComboBox::OnAddBitmap(const wxBitmap& bitmap)
324{
325 if ( wxBitmapComboBoxBase::OnAddBitmap(bitmap) )
326 {
327 // Need to recreate control for a new measureitem call?
328 int prevItemHeight = ::SendMessage(GetHwnd(), CB_GETITEMHEIGHT, 0, 0);
329
330 if ( prevItemHeight != MeasureItem(0) )
331 RecreateControl();
332
333 return true;
334 }
03647350 335
f696015c
VZ
336 return false;
337}
338
339void wxBitmapComboBox::DoClear()
340{
341 wxComboBox::DoClear();
342 wxBitmapComboBoxBase::BCBDoClear();
343}
344
345void wxBitmapComboBox::DoDeleteOneItem(unsigned int n)
346{
347 wxComboBox::DoDeleteOneItem(n);
348 wxBitmapComboBoxBase::BCBDoDeleteOneItem(n);
349}
350
351// ----------------------------------------------------------------------------
352// wxBitmapComboBox event handlers and such
353// ----------------------------------------------------------------------------
354
355void wxBitmapComboBox::OnSize(wxSizeEvent& event)
356{
357 // Prevent infinite looping
358 if ( !m_inResize )
359 {
360 m_inResize = true;
361 DetermineIndent();
362 m_inResize = false;
363 }
364
365 event.Skip();
366}
367
368// ----------------------------------------------------------------------------
369// wxBitmapComboBox miscellaneous
370// ----------------------------------------------------------------------------
371
372bool wxBitmapComboBox::SetFont(const wxFont& font)
373{
374 bool res = wxComboBox::SetFont(font);
375 UpdateInternals();
376 return res;
377}
378
379// ----------------------------------------------------------------------------
380// wxBitmapComboBox item drawing and measuring
381// ----------------------------------------------------------------------------
382
383bool wxBitmapComboBox::MSWOnDraw(WXDRAWITEMSTRUCT *item)
384{
385 LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT) item;
386 int pos = lpDrawItem->itemID;
387
388 // Draw default for item -1, which means 'focus rect only'
389 if ( pos == -1 )
390 return FALSE;
391
03647350 392 int flags = 0;
f696015c
VZ
393 if ( lpDrawItem->itemState & ODS_COMBOBOXEDIT )
394 flags |= wxODCB_PAINTING_CONTROL;
395 if ( lpDrawItem->itemState & ODS_SELECTED )
396 flags |= wxODCB_PAINTING_SELECTED;
397
398 wxString text;
399
400 if ( flags & wxODCB_PAINTING_CONTROL )
401 {
402 text = GetValue();
403 if ( !HasFlag(wxCB_READONLY) )
404 text.clear();
405 }
406 else
407 {
408 text = GetString(pos);
409 }
410
411 wxPaintDCEx dc(this, lpDrawItem->hDC);
412 wxRect rect = wxRectFromRECT(lpDrawItem->rcItem);
413 wxBitmapComboBoxBase::DrawBackground(dc, rect, pos, flags);
414 wxBitmapComboBoxBase::DrawItem(dc, rect, pos, text, flags);
415
416 // If the item has the focus, draw focus rectangle.
417 // Commented out since regular combo box doesn't
418 // seem to do it either.
419 //if ( lpDrawItem->itemState & ODS_FOCUS )
420 // DrawFocusRect(lpDrawItem->hDC, &lpDrawItem->rcItem);
421
422 return TRUE;
423}
424
425bool wxBitmapComboBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
426{
427 LPMEASUREITEMSTRUCT lpMeasureItem = (LPMEASUREITEMSTRUCT) item;
428 int pos = lpMeasureItem->itemID;
429
430 lpMeasureItem->itemHeight = wxBitmapComboBoxBase::MeasureItem(pos);
431
432 return TRUE;
433}
434
435#endif // wxUSE_BITMAPCOMBOBOX