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