show combobox drop down/close up events (closes #10954)
[wxWidgets.git] / samples / widgets / bmpcombobox.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWidgets Widgets Sample
3 // Name: bmpcombobox.cpp
4 // Purpose: Part of the widgets sample showing wxBitmapComboBox
5 // Author: Jaakko Salli
6 // Created: Sep-01-2006
7 // Id: $Id$
8 // Copyright: (c) 2006 Jaakko Salli
9 // License: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // for compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #if wxUSE_BITMAPCOMBOBOX
28
29 // for all others, include the necessary headers
30 #ifndef WX_PRECOMP
31 #include "wx/log.h"
32
33 #include "wx/bitmap.h"
34 #include "wx/button.h"
35 #include "wx/checkbox.h"
36 #include "wx/combobox.h"
37 #include "wx/radiobox.h"
38 #include "wx/statbox.h"
39 #include "wx/textctrl.h"
40 #include "wx/filedlg.h"
41 #endif
42
43 #include "wx/stattext.h"
44 #include "wx/dc.h"
45 #include "wx/dcmemory.h"
46 #include "wx/sizer.h"
47 #include "wx/icon.h"
48 #include "wx/dir.h"
49 #include "wx/msgdlg.h"
50 #include "wx/filename.h"
51 #include "wx/image.h"
52 #include "wx/imaglist.h"
53 #include "wx/bmpcbox.h"
54
55 #include "itemcontainer.h"
56 #include "widgets.h"
57
58 #include "icons/bmpcombobox.xpm"
59
60 // Images loaded from file are reduced this width and height, if larger
61 #define IMG_SIZE_TRUNC 256
62
63
64 // ----------------------------------------------------------------------------
65 // constants
66 // ----------------------------------------------------------------------------
67
68 // control ids
69 enum
70 {
71 BitmapComboBoxPage_Reset = wxID_HIGHEST,
72 BitmapComboBoxPage_Insert,
73 BitmapComboBoxPage_InsertText,
74 BitmapComboBoxPage_ChangeHeight,
75 BitmapComboBoxPage_LoadFromFile,
76 BitmapComboBoxPage_SetFromFile,
77 BitmapComboBoxPage_AddWidgetIcons,
78 BitmapComboBoxPage_AddSeveralWithImages,
79 BitmapComboBoxPage_AddSeveral,
80 BitmapComboBoxPage_AddMany,
81 BitmapComboBoxPage_Clear,
82 BitmapComboBoxPage_Change,
83 BitmapComboBoxPage_Delete,
84 BitmapComboBoxPage_DeleteText,
85 BitmapComboBoxPage_DeleteSel,
86 BitmapComboBoxPage_Combo,
87 BitmapComboBoxPage_ContainerTests
88 };
89
90 // kinds of comboboxes
91 enum
92 {
93 ComboKind_Default,
94 ComboKind_Simple,
95 ComboKind_DropDown
96 };
97
98 // ----------------------------------------------------------------------------
99 // BitmapComboBoxWidgetsPage
100 // ----------------------------------------------------------------------------
101
102 class BitmapComboBoxWidgetsPage : public ItemContainerWidgetsPage
103 {
104 public:
105 BitmapComboBoxWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist);
106
107 virtual wxControl *GetWidget() const { return m_combobox; }
108 virtual wxItemContainer* GetContainer() const { return m_combobox; }
109 virtual void RecreateWidget() { CreateCombo(); }
110
111 // lazy creation of the content
112 virtual void CreateContent();
113
114 protected:
115 // event handlers
116 void OnButtonReset(wxCommandEvent& event);
117 void OnButtonChange(wxCommandEvent& event);
118 void OnButtonDelete(wxCommandEvent& event);
119 void OnButtonDeleteSel(wxCommandEvent& event);
120 void OnButtonClear(wxCommandEvent& event);
121 void OnButtonInsert(wxCommandEvent &event);
122 void OnTextChangeHeight(wxCommandEvent& event);
123 void OnButtonLoadFromFile(wxCommandEvent& event);
124 void OnButtonSetFromFile(wxCommandEvent& event);
125 void OnButtonAddSeveral(wxCommandEvent& event);
126 void OnButtonAddSeveralWithImages(wxCommandEvent& event);
127 void OnButtonAddWidgetIcons(wxCommandEvent& event);
128 void OnButtonAddMany(wxCommandEvent& event);
129
130 void OnComboBox(wxCommandEvent& event);
131 void OnDropDown(wxCommandEvent& event);
132 void OnCloseUp(wxCommandEvent& event);
133 void OnComboText(wxCommandEvent& event);
134
135 void OnCheckOrRadioBox(wxCommandEvent& event);
136
137 void OnTextPopupWidth(wxCommandEvent& event);
138 void OnTextPopupHeight(wxCommandEvent& event);
139 void OnTextButtonAll(wxCommandEvent& event);
140
141 void OnUpdateUIInsert(wxUpdateUIEvent& event);
142 void OnUpdateUIAddSeveral(wxUpdateUIEvent& event);
143 void OnUpdateUIAddSeveralWithImages(wxUpdateUIEvent& event);
144 void OnUpdateUIClearButton(wxUpdateUIEvent& event);
145 void OnUpdateUIDeleteButton(wxUpdateUIEvent& event);
146 void OnUpdateUIItemManipulator(wxUpdateUIEvent& event);
147 void OnUpdateUIResetButton(wxUpdateUIEvent& event);
148
149 // reset the bmpcombobox parameters
150 void Reset();
151
152 // (re)create the bmpcombobox
153 void CreateCombo();
154
155 // helpers for creating bitmaps
156 wxBitmap CreateBitmap(const wxColour& colour);
157 wxBitmap LoadBitmap(const wxString& filepath);
158 wxBitmap QueryBitmap(wxString* pStr);
159
160 void LoadWidgetImages( wxArrayString* strings, wxImageList* images );
161
162 wxSizer *CreateSizerWithSmallTextAndLabel(const wxString& label,
163 wxWindowID id,
164 wxTextCtrl **ppText);
165
166 #if wxUSE_IMAGE
167 void RescaleImage(wxImage& image, int w, int h);
168 #endif
169
170 // the controls
171 // ------------
172
173 // the sel mode radiobox
174 wxRadioBox *m_radioKind;
175
176 // the checkboxes for styles
177 wxCheckBox *m_chkSort,
178 *m_chkReadonly;
179
180 // the combobox itself and the sizer it is in
181 wxBitmapComboBox *m_combobox;
182 wxSizer *m_sizerCombo;
183
184 // the text entries for "Add/change string" and "Delete" buttons
185 wxTextCtrl *m_textInsert,
186 *m_textChangeHeight,
187 *m_textChange,
188 *m_textDelete;
189
190 private:
191 DECLARE_EVENT_TABLE()
192 DECLARE_WIDGETS_PAGE(BitmapComboBoxWidgetsPage)
193 };
194
195 // ----------------------------------------------------------------------------
196 // event tables
197 // ----------------------------------------------------------------------------
198
199 BEGIN_EVENT_TABLE(BitmapComboBoxWidgetsPage, WidgetsPage)
200 EVT_BUTTON(BitmapComboBoxPage_Reset, BitmapComboBoxWidgetsPage::OnButtonReset)
201 EVT_BUTTON(BitmapComboBoxPage_Change, BitmapComboBoxWidgetsPage::OnButtonChange)
202 EVT_BUTTON(BitmapComboBoxPage_Delete, BitmapComboBoxWidgetsPage::OnButtonDelete)
203 EVT_BUTTON(BitmapComboBoxPage_DeleteSel, BitmapComboBoxWidgetsPage::OnButtonDeleteSel)
204 EVT_BUTTON(BitmapComboBoxPage_Clear, BitmapComboBoxWidgetsPage::OnButtonClear)
205 EVT_BUTTON(BitmapComboBoxPage_Insert, BitmapComboBoxWidgetsPage::OnButtonInsert)
206 EVT_BUTTON(BitmapComboBoxPage_AddSeveral, BitmapComboBoxWidgetsPage::OnButtonAddSeveral)
207 EVT_BUTTON(BitmapComboBoxPage_AddSeveralWithImages, BitmapComboBoxWidgetsPage::OnButtonAddSeveralWithImages)
208 EVT_BUTTON(BitmapComboBoxPage_AddWidgetIcons, BitmapComboBoxWidgetsPage::OnButtonAddWidgetIcons)
209 EVT_BUTTON(BitmapComboBoxPage_AddMany, BitmapComboBoxWidgetsPage::OnButtonAddMany)
210 EVT_BUTTON(BitmapComboBoxPage_LoadFromFile, BitmapComboBoxWidgetsPage::OnButtonLoadFromFile)
211 EVT_BUTTON(BitmapComboBoxPage_SetFromFile, BitmapComboBoxWidgetsPage::OnButtonSetFromFile)
212 EVT_BUTTON(BitmapComboBoxPage_ContainerTests, ItemContainerWidgetsPage::OnButtonTestItemContainer)
213
214 EVT_TEXT_ENTER(BitmapComboBoxPage_InsertText, BitmapComboBoxWidgetsPage::OnButtonInsert)
215 EVT_TEXT(BitmapComboBoxPage_ChangeHeight, BitmapComboBoxWidgetsPage::OnTextChangeHeight)
216 EVT_TEXT_ENTER(BitmapComboBoxPage_DeleteText, BitmapComboBoxWidgetsPage::OnButtonDelete)
217
218 EVT_UPDATE_UI(BitmapComboBoxPage_Reset, BitmapComboBoxWidgetsPage::OnUpdateUIResetButton)
219 EVT_UPDATE_UI(BitmapComboBoxPage_Insert, BitmapComboBoxWidgetsPage::OnUpdateUIInsert)
220 EVT_UPDATE_UI(BitmapComboBoxPage_LoadFromFile, BitmapComboBoxWidgetsPage::OnUpdateUIInsert)
221 EVT_UPDATE_UI(BitmapComboBoxPage_AddSeveral, BitmapComboBoxWidgetsPage::OnUpdateUIAddSeveral)
222 EVT_UPDATE_UI(BitmapComboBoxPage_AddSeveralWithImages, BitmapComboBoxWidgetsPage::OnUpdateUIAddSeveralWithImages)
223 EVT_UPDATE_UI(BitmapComboBoxPage_Clear, BitmapComboBoxWidgetsPage::OnUpdateUIClearButton)
224 EVT_UPDATE_UI(BitmapComboBoxPage_DeleteText, BitmapComboBoxWidgetsPage::OnUpdateUIClearButton)
225 EVT_UPDATE_UI(BitmapComboBoxPage_Delete, BitmapComboBoxWidgetsPage::OnUpdateUIDeleteButton)
226 EVT_UPDATE_UI(BitmapComboBoxPage_Change, BitmapComboBoxWidgetsPage::OnUpdateUIItemManipulator)
227 EVT_UPDATE_UI(BitmapComboBoxPage_SetFromFile, BitmapComboBoxWidgetsPage::OnUpdateUIItemManipulator)
228 EVT_UPDATE_UI(BitmapComboBoxPage_DeleteSel, BitmapComboBoxWidgetsPage::OnUpdateUIItemManipulator)
229
230 EVT_COMBOBOX_DROPDOWN(BitmapComboBoxPage_Combo, BitmapComboBoxWidgetsPage::OnDropDown)
231 EVT_COMBOBOX_CLOSEUP(BitmapComboBoxPage_Combo, BitmapComboBoxWidgetsPage::OnCloseUp)
232 EVT_COMBOBOX(BitmapComboBoxPage_Combo, BitmapComboBoxWidgetsPage::OnComboBox)
233 EVT_TEXT(BitmapComboBoxPage_Combo, BitmapComboBoxWidgetsPage::OnComboText)
234 EVT_TEXT_ENTER(BitmapComboBoxPage_Combo, BitmapComboBoxWidgetsPage::OnComboText)
235
236 EVT_CHECKBOX(wxID_ANY, BitmapComboBoxWidgetsPage::OnCheckOrRadioBox)
237 EVT_RADIOBOX(wxID_ANY, BitmapComboBoxWidgetsPage::OnCheckOrRadioBox)
238 END_EVENT_TABLE()
239
240 // ============================================================================
241 // implementation
242 // ============================================================================
243
244 #if defined(__WXMSW__) || defined(__WXGTK__)
245 #define NATIVE_OR_GENERIC_CTRLS NATIVE_CTRLS
246 #else
247 #define NATIVE_OR_GENERIC_CTRLS GENERIC_CTRLS
248 #endif
249
250 IMPLEMENT_WIDGETS_PAGE(BitmapComboBoxWidgetsPage, _T("BitmapCombobox"),
251 NATIVE_OR_GENERIC_CTRLS | WITH_ITEMS_CTRLS | COMBO_CTRLS
252 );
253
254
255 BitmapComboBoxWidgetsPage::BitmapComboBoxWidgetsPage(WidgetsBookCtrl *book,
256 wxImageList *imaglist)
257 : ItemContainerWidgetsPage(book, imaglist, bmpcombobox_xpm)
258 {
259 // init everything
260 m_chkSort =
261 m_chkReadonly = NULL;
262
263 m_combobox = NULL;
264 m_sizerCombo = NULL;
265
266 m_textInsert =
267 m_textChangeHeight =
268 m_textChange =
269 m_textDelete = NULL;
270 }
271
272 // create a sizer containing a label and a small text ctrl
273 wxSizer *BitmapComboBoxWidgetsPage::CreateSizerWithSmallTextAndLabel(const wxString& label,
274 wxWindowID id,
275 wxTextCtrl **ppText)
276 {
277 wxControl* control = new wxStaticText(this, wxID_ANY, label);
278 wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
279 wxTextCtrl *text = new wxTextCtrl(this, id, wxEmptyString,
280 wxDefaultPosition, wxSize(50,wxDefaultCoord), wxTE_PROCESS_ENTER);
281
282 sizerRow->Add(control, 0, wxRIGHT | wxALIGN_CENTRE_VERTICAL, 5);
283 sizerRow->Add(text, 1, wxFIXED_MINSIZE | wxLEFT | wxALIGN_CENTRE_VERTICAL, 5);
284
285 if ( ppText )
286 *ppText = text;
287
288 return sizerRow;
289 }
290
291 void BitmapComboBoxWidgetsPage::CreateContent()
292 {
293 /*
294 What we create here is a frame having 3 panes: style pane is the
295 leftmost one, in the middle the pane with buttons allowing to perform
296 miscellaneous combobox operations and the pane containing the combobox
297 itself to the right
298 */
299 wxSizer *sizerRow;
300
301 wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
302
303 wxSizer *sizerLeft = new wxBoxSizer(wxVERTICAL);
304
305 // left pane - style box
306 wxStaticBox *box = new wxStaticBox(this, wxID_ANY, _T("&Set style"));
307
308
309 // should be in sync with ComboKind_XXX values
310 static const wxString kinds[] =
311 {
312 _T("default"),
313 _T("simple"),
314 _T("drop down"),
315 };
316
317 m_radioKind = new wxRadioBox(this, wxID_ANY, _T("Combobox &kind:"),
318 wxDefaultPosition, wxDefaultSize,
319 WXSIZEOF(kinds), kinds,
320 1, wxRA_SPECIFY_COLS);
321
322 wxSizer *sizerStyle = new wxStaticBoxSizer(box, wxVERTICAL);
323
324 m_chkSort = CreateCheckBoxAndAddToSizer(sizerStyle, _T("&Sort items"));
325 m_chkReadonly = CreateCheckBoxAndAddToSizer(sizerStyle, _T("&Read only"));
326
327 wxButton *btn = new wxButton(this, BitmapComboBoxPage_Reset, _T("&Reset"));
328 sizerStyle->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 3);
329
330 sizerLeft->Add(sizerStyle, 0, wxGROW | wxALIGN_CENTRE_HORIZONTAL);
331 sizerLeft->Add(m_radioKind, 0, wxGROW | wxALL, 5);
332
333 // left pane - other options box
334 box = new wxStaticBox(this, wxID_ANY, _T("Demo options"));
335
336 wxSizer *sizerOptions = new wxStaticBoxSizer(box, wxVERTICAL);
337
338 sizerRow = CreateSizerWithSmallTextAndLabel(_T("Control &height:"),
339 BitmapComboBoxPage_ChangeHeight,
340 &m_textChangeHeight);
341 m_textChangeHeight->SetSize(20, wxDefaultCoord);
342 sizerOptions->Add(sizerRow, 0, wxALL | wxFIXED_MINSIZE /*| wxGROW*/, 5);
343
344 sizerLeft->Add(sizerOptions, 0, wxGROW | wxALIGN_CENTRE_HORIZONTAL | wxTOP, 2);
345
346 // middle pane
347 wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY,
348 _T("&Change wxBitmapComboBox contents"));
349 wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
350
351 btn = new wxButton(this, BitmapComboBoxPage_ContainerTests, _T("Run &tests"));
352 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
353
354 #if wxUSE_IMAGE
355 btn = new wxButton(this, BitmapComboBoxPage_AddWidgetIcons, _T("Add &widget icons"));
356 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
357
358 btn = new wxButton(this, BitmapComboBoxPage_LoadFromFile, _T("Insert image from &file"));
359 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
360
361 btn = new wxButton(this, BitmapComboBoxPage_SetFromFile, _T("&Set image from file"));
362 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
363 #endif
364
365 btn = new wxButton(this, BitmapComboBoxPage_AddSeveralWithImages, _T("A&ppend a few strings with images"));
366 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
367
368 btn = new wxButton(this, BitmapComboBoxPage_AddSeveral, _T("Append a &few strings"));
369 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
370
371 btn = new wxButton(this, BitmapComboBoxPage_AddMany, _T("Append &many strings"));
372 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
373
374 sizerRow = CreateSizerWithTextAndButton(BitmapComboBoxPage_Delete,
375 _T("&Delete this item"),
376 BitmapComboBoxPage_DeleteText,
377 &m_textDelete);
378 sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
379
380 btn = new wxButton(this, BitmapComboBoxPage_DeleteSel, _T("Delete &selection"));
381 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
382
383 btn = new wxButton(this, BitmapComboBoxPage_Clear, _T("&Clear"));
384 sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
385
386 #if wxUSE_IMAGE
387 wxInitAllImageHandlers();
388 #endif
389
390 // right pane
391 wxSizer *sizerRight = new wxBoxSizer(wxVERTICAL);
392 m_combobox = new wxBitmapComboBox();
393 m_combobox->Create(this, BitmapComboBoxPage_Combo, wxEmptyString,
394 wxDefaultPosition, wxDefaultSize,
395 0, NULL,
396 wxCB_READONLY);
397
398 #if defined(wxGENERIC_BITMAPCOMBOBOX)
399 // This will sure make the list look nicer when larger images are used.
400 m_combobox->SetPopupMaxHeight(600);
401 #endif
402
403 sizerRight->Add(m_combobox, 0, wxGROW | wxALL, 5);
404 sizerRight->SetMinSize(150, 0);
405 m_sizerCombo = sizerRight; // save it to modify it later
406
407 // the 3 panes panes compose the window
408 sizerTop->Add(sizerLeft, 0, wxGROW | (wxALL & ~wxLEFT), 10);
409 sizerTop->Add(sizerMiddle, 5, wxGROW | wxALL, 10);
410 sizerTop->Add(sizerRight, 4, wxGROW | (wxALL & ~wxRIGHT), 10);
411
412 // final initializations
413 Reset();
414
415 SetSizer(sizerTop);
416 }
417
418 // ----------------------------------------------------------------------------
419 // operations
420 // ----------------------------------------------------------------------------
421
422 void BitmapComboBoxWidgetsPage::Reset()
423 {
424 m_chkSort->SetValue(false);
425 m_chkReadonly->SetValue(true);
426 }
427
428 void BitmapComboBoxWidgetsPage::CreateCombo()
429 {
430 int flags = ms_defaultFlags;
431
432 if ( m_chkSort->GetValue() )
433 flags |= wxCB_SORT;
434 if ( m_chkReadonly->GetValue() )
435 flags |= wxCB_READONLY;
436
437 switch ( m_radioKind->GetSelection() )
438 {
439 default:
440 wxFAIL_MSG( _T("unknown combo kind") );
441 // fall through
442
443 case ComboKind_Default:
444 break;
445
446 case ComboKind_Simple:
447 flags |= wxCB_SIMPLE;
448 break;
449
450 case ComboKind_DropDown:
451 flags = wxCB_DROPDOWN;
452 break;
453 }
454
455 wxArrayString items;
456 wxArrayPtrVoid bitmaps;
457 if ( m_combobox )
458 {
459 unsigned int count = m_combobox->GetCount();
460 for ( unsigned int n = 0; n < count; n++ )
461 {
462 items.Add(m_combobox->GetString(n));
463 bitmaps.Add(new wxBitmap(m_combobox->GetItemBitmap(n)));
464 }
465
466 m_sizerCombo->Detach( m_combobox );
467 delete m_combobox;
468 }
469
470 m_combobox = new wxBitmapComboBox();
471 m_combobox->Create(this, BitmapComboBoxPage_Combo, wxEmptyString,
472 wxDefaultPosition, wxDefaultSize,
473 0, NULL,
474 flags);
475
476 #if defined(wxGENERIC_BITMAPCOMBOBOX)
477 // This will sure make the list look nicer when larger images are used.
478 m_combobox->SetPopupMaxHeight(600);
479 #endif
480
481 unsigned int count = items.GetCount();
482 for ( unsigned int n = 0; n < count; n++ )
483 {
484 wxBitmap* bmp = (wxBitmap*) bitmaps[n];
485 m_combobox->Append(items[n], *bmp);
486 delete bmp;
487 }
488
489 m_sizerCombo->Add(m_combobox, 0, wxGROW | wxALL, 5);
490 m_sizerCombo->Layout();
491
492 // Allow changing height inorder to demonstrate flexible
493 // size of image "thumbnail" painted in the control itself.
494 long h = 0;
495 m_textChangeHeight->GetValue().ToLong(&h);
496 if ( h >= 5 )
497 m_combobox->SetSize(wxDefaultCoord, h);
498 }
499
500 // ----------------------------------------------------------------------------
501 // event handlers
502 // ----------------------------------------------------------------------------
503
504 void BitmapComboBoxWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
505 {
506 Reset();
507
508 CreateCombo();
509 }
510
511 void BitmapComboBoxWidgetsPage::OnButtonChange(wxCommandEvent& WXUNUSED(event))
512 {
513 int sel = m_combobox->GetSelection();
514 if ( sel != wxNOT_FOUND )
515 {
516 #ifndef __WXGTK__
517 m_combobox->SetString(sel, m_textChange->GetValue());
518 #else
519 wxLogMessage(_T("Not implemented in wxGTK"));
520 #endif
521 }
522 }
523
524 void BitmapComboBoxWidgetsPage::OnButtonDelete(wxCommandEvent& WXUNUSED(event))
525 {
526 unsigned long n;
527 if ( !m_textDelete->GetValue().ToULong(&n) ||
528 (n >= m_combobox->GetCount()) )
529 {
530 return;
531 }
532
533 m_combobox->Delete(n);
534 }
535
536 void BitmapComboBoxWidgetsPage::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(event))
537 {
538 int sel = m_combobox->GetSelection();
539 if ( sel != wxNOT_FOUND )
540 {
541 m_combobox->Delete(sel);
542 }
543 }
544
545 void BitmapComboBoxWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
546 {
547 m_combobox->Clear();
548 }
549
550 void BitmapComboBoxWidgetsPage::OnButtonInsert(wxCommandEvent& WXUNUSED(event))
551 {
552 static unsigned int s_item = 0;
553
554 wxString s = m_textInsert->GetValue();
555 if ( !m_textInsert->IsModified() )
556 {
557 // update the default string
558 m_textInsert->SetValue(wxString::Format(_T("test item %u"), ++s_item));
559 }
560
561 int sel = m_combobox->GetSelection();
562 if ( sel == wxNOT_FOUND )
563 sel = m_combobox->GetCount();
564
565 m_combobox->Insert(s, wxNullBitmap, m_combobox->GetSelection());
566 }
567
568 void BitmapComboBoxWidgetsPage::OnTextChangeHeight(wxCommandEvent& WXUNUSED(event))
569 {
570 long h = 0;
571 if ( m_textChangeHeight )
572 m_textChangeHeight->GetValue().ToLong(&h);
573 if ( h < 5 )
574 return;
575 m_combobox->SetSize(wxDefaultCoord, h);
576 }
577
578 void BitmapComboBoxWidgetsPage::OnButtonLoadFromFile(wxCommandEvent& WXUNUSED(event))
579 {
580 wxString s;
581 int sel = m_combobox->GetSelection();
582 if ( sel == wxNOT_FOUND )
583 sel = m_combobox->GetCount();
584
585 wxBitmap bmp = QueryBitmap(&s);
586 if (bmp.IsOk())
587 m_combobox->Insert(s, bmp, sel);
588 }
589
590 void BitmapComboBoxWidgetsPage::OnButtonSetFromFile(wxCommandEvent& WXUNUSED(event))
591 {
592 wxBitmap bmp = QueryBitmap(NULL);
593 if (bmp.IsOk())
594 m_combobox->SetItemBitmap(m_combobox->GetSelection(), bmp);
595 }
596
597 void BitmapComboBoxWidgetsPage::OnButtonAddMany(wxCommandEvent& WXUNUSED(event))
598 {
599 // "many" means 1000 here
600 for ( unsigned int n = 0; n < 1000; n++ )
601 {
602 m_combobox->Append(wxString::Format(_T("item #%u"), n));
603 }
604 }
605
606 void BitmapComboBoxWidgetsPage::OnButtonAddSeveral(wxCommandEvent& WXUNUSED(event))
607 {
608 m_combobox->Append(_T("First"));
609 m_combobox->Append(_T("another one"));
610 m_combobox->Append(_T("and the last (very very very very very very very very very very long) one"));
611 }
612
613 void BitmapComboBoxWidgetsPage::OnButtonAddSeveralWithImages(wxCommandEvent& WXUNUSED(event))
614 {
615 static const struct TestEntry
616 {
617 const char *text;
618 unsigned long rgb;
619 } s_entries[] =
620 {
621 { "Red circle", 0x0000ff },
622 { "Blue circle", 0xff0000 },
623 { "Green circle", 0x00ff00 },
624 { "Black circle", 0x000000 },
625 };
626
627 for ( unsigned i = 0; i < WXSIZEOF(s_entries); i++ )
628 {
629 const TestEntry& e = s_entries[i];
630 m_combobox->Append(e.text, CreateBitmap(wxColour(e.rgb)));
631 }
632 }
633
634 #if wxUSE_IMAGE
635 void BitmapComboBoxWidgetsPage::RescaleImage(wxImage& image, int w, int h)
636 {
637 if ( image.GetWidth() == w && image.GetHeight() == h )
638 return;
639
640 if ( w <= 0 || h <= 0 )
641 return;
642
643 static bool isFirstScale = true;
644
645 if ( isFirstScale && m_combobox->GetCount() > 0 )
646 {
647 wxMessageBox( wxT("wxBitmapComboBox normally only supports images of one size. ")
648 wxT("However, for demonstration purposes, loaded bitmaps are scaled to fit ")
649 wxT("using wxImage::Rescale."),
650 wxT("Notice"),
651 wxOK,
652 this );
653
654 isFirstScale = false;
655 }
656
657 image.Rescale(w, h);
658 }
659 #endif
660
661 void BitmapComboBoxWidgetsPage::LoadWidgetImages( wxArrayString* strings, wxImageList* images )
662 {
663 wxFileName fn;
664 fn.AssignCwd();
665 fn.AppendDir(wxT("icons"));
666
667 wxSetCursor(*wxHOURGLASS_CURSOR);
668
669 if ( !wxDir::Exists(fn.GetFullPath()) ||
670 !wxDir::GetAllFiles(fn.GetFullPath(),strings,wxT("*.xpm")) )
671 {
672 // Try ../../samples/widgets/icons
673 fn.RemoveLastDir();
674 fn.RemoveLastDir();
675 fn.AppendDir(wxT("icons"));
676 if ( !wxDir::Exists(fn.GetFullPath()) ||
677 !wxDir::GetAllFiles(fn.GetFullPath(),strings,wxT("*.xpm")) )
678 {
679 // Try ../../../samples/widgets/icons
680 fn.AssignCwd();
681 fn.RemoveLastDir();
682 fn.RemoveLastDir();
683 fn.RemoveLastDir();
684 fn.AppendDir(wxT("samples"));
685 fn.AppendDir(wxT("widgets"));
686 fn.AppendDir(wxT("icons"));
687 if ( !wxDir::Exists(fn.GetFullPath()) ||
688 !wxDir::GetAllFiles(fn.GetFullPath(),strings,wxT("*.xpm")) )
689 {
690 wxLogWarning(wxT("Could not load widget icons."));
691 wxSetCursor(*wxSTANDARD_CURSOR);
692 return;
693 }
694 }
695 }
696
697 unsigned int i;
698
699 // Get size of existing images in list
700 wxSize foundSize = m_combobox->GetBitmapSize();
701
702 for ( i=0; i<strings->size(); i++ )
703 {
704 fn.SetFullName((*strings)[i]);
705 wxString name = fn.GetName();
706
707 // Handle few exceptions
708 if ( name == wxT("bmpbtn") )
709 {
710 strings->RemoveAt(i);
711 i--;
712 }
713 else
714 {
715 #if wxUSE_IMAGE
716 wxASSERT(fn.FileExists());
717 wxImage image(fn.GetFullPath());
718 wxASSERT(image.Ok());
719 RescaleImage(image, foundSize.x, foundSize.y);
720 wxBitmap bmp(image);
721 wxASSERT( bmp.Ok() );
722 #else
723 wxBitmap bmp(wxNullBitmap);
724 #endif
725 images->Add(bmp);
726 (*strings)[i] = name;
727
728 // if the combobox is empty, use as bitmap size of the image list
729 // the size of the first valid image loaded
730 if (foundSize == wxDefaultSize)
731 foundSize = bmp.GetSize();
732 }
733 }
734
735 wxSetCursor(*wxSTANDARD_CURSOR);
736 }
737
738 void BitmapComboBoxWidgetsPage::OnButtonAddWidgetIcons(wxCommandEvent& WXUNUSED(event))
739 {
740 wxArrayString strings;
741
742 wxSize sz = m_combobox->GetBitmapSize();
743 if ( sz.x <= 0 )
744 {
745 sz.x = 32;
746 sz.y = 32;
747 }
748
749 wxImageList images(sz.x, sz.y);
750
751 LoadWidgetImages(&strings, &images);
752
753 unsigned int i;
754
755 for ( i=0; i<strings.size(); i++ )
756 {
757 m_combobox->Append(strings[i], images.GetBitmap(i));
758 }
759 }
760
761 void BitmapComboBoxWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
762 {
763 if (m_combobox)
764 event.Enable( m_chkSort->GetValue() || m_chkReadonly->GetValue() );
765 }
766
767 void BitmapComboBoxWidgetsPage::OnUpdateUIInsert(wxUpdateUIEvent& event)
768 {
769 if (m_combobox)
770 {
771 bool enable = !(m_combobox->GetWindowStyle() & wxCB_SORT);
772
773 event.Enable(enable);
774 }
775 }
776
777 void BitmapComboBoxWidgetsPage::OnUpdateUIDeleteButton(wxUpdateUIEvent& event)
778 {
779 if (m_combobox)
780 {
781 unsigned long n;
782 event.Enable(m_textDelete->GetValue().ToULong(&n) &&
783 (n < (unsigned)m_combobox->GetCount()));
784 }
785 }
786
787 void BitmapComboBoxWidgetsPage::OnUpdateUIItemManipulator(wxUpdateUIEvent& event)
788 {
789 if (m_combobox)
790 event.Enable(m_combobox->GetSelection() != wxNOT_FOUND);
791 }
792
793 void BitmapComboBoxWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
794 {
795 if (m_combobox)
796 event.Enable(m_combobox->GetCount() != 0);
797 }
798
799 void BitmapComboBoxWidgetsPage::OnUpdateUIAddSeveral(wxUpdateUIEvent& event)
800 {
801 if (m_combobox)
802 event.Enable(!(m_combobox->GetWindowStyle() & wxCB_SORT));
803 }
804
805 void BitmapComboBoxWidgetsPage::OnUpdateUIAddSeveralWithImages(wxUpdateUIEvent& event)
806 {
807 if (m_combobox)
808 event.Enable(!(m_combobox->GetWindowStyle() & wxCB_SORT));
809 }
810
811 void BitmapComboBoxWidgetsPage::OnComboText(wxCommandEvent& event)
812 {
813 if (!m_combobox)
814 return;
815
816 wxString s = event.GetString();
817
818 wxASSERT_MSG( s == m_combobox->GetValue(),
819 _T("event and combobox values should be the same") );
820
821 if (event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
822 wxLogMessage(_T("BitmapCombobox enter pressed (now '%s')"), s.c_str());
823 else
824 wxLogMessage(_T("BitmapCombobox text changed (now '%s')"), s.c_str());
825 }
826
827 void BitmapComboBoxWidgetsPage::OnComboBox(wxCommandEvent& event)
828 {
829 long sel = event.GetInt();
830 m_textDelete->SetValue(wxString::Format(_T("%ld"), sel));
831
832 wxLogMessage(_T("BitmapCombobox item %ld selected"), sel);
833
834 wxLogMessage(_T("BitmapCombobox GetValue(): %s"), m_combobox->GetValue().c_str() );
835 }
836
837 void BitmapComboBoxWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
838 {
839 CreateCombo();
840 }
841
842 #if wxUSE_IMAGE
843 wxBitmap BitmapComboBoxWidgetsPage::LoadBitmap(const wxString& filepath)
844 {
845 // Get size of existing images in list
846 wxSize foundSize = m_combobox->GetBitmapSize();
847
848 // Have some reasonable maximum size
849 if ( foundSize.x <= 0 )
850 {
851 foundSize.x = IMG_SIZE_TRUNC;
852 foundSize.y = IMG_SIZE_TRUNC;
853 }
854
855 wxImage image(filepath);
856 if ( image.Ok() )
857 {
858 // Rescale very large images
859 int ow = image.GetWidth();
860 int oh = image.GetHeight();
861
862 if ( foundSize.x > 0 &&
863 (ow != foundSize.x || oh != foundSize.y) )
864 {
865 int w = ow;
866 if ( w > foundSize.x )
867 w = foundSize.x;
868 int h = oh;
869 if ( h > foundSize.y )
870 h = foundSize.y;
871
872 RescaleImage(image, w, h);
873 }
874
875 return wxBitmap(image);
876 }
877
878 return wxNullBitmap;
879 }
880 #else
881 wxBitmap BitmapComboBoxWidgetsPage::LoadBitmap(const wxString& WXUNUSED(filepath))
882 {
883 return wxNullBitmap;
884 }
885 #endif
886
887 wxBitmap BitmapComboBoxWidgetsPage::QueryBitmap(wxString* pStr)
888 {
889 wxString filepath = wxLoadFileSelector(wxT("image"),
890 wxEmptyString,
891 wxEmptyString,
892 this);
893
894 wxBitmap bitmap;
895
896 ::wxSetCursor( *wxHOURGLASS_CURSOR );
897
898 if ( filepath.length() )
899 {
900 if ( pStr )
901 {
902 *pStr = wxFileName(filepath).GetName();
903 }
904
905 bitmap = LoadBitmap(filepath);
906 }
907
908 if (bitmap.IsOk())
909 wxLogDebug(wxT("%i, %i"),bitmap.GetWidth(), bitmap.GetHeight());
910
911 ::wxSetCursor( *wxSTANDARD_CURSOR );
912
913 return bitmap;
914 }
915
916 wxBitmap BitmapComboBoxWidgetsPage::CreateBitmap(const wxColour& colour)
917 {
918 const int w = 10,
919 h = 10;
920
921 wxMemoryDC dc;
922 wxBitmap bmp(w, h);
923 dc.SelectObject(bmp);
924
925 // Draw transparent background
926 wxColour magic(255, 0, 255);
927 wxBrush magicBrush(magic);
928 dc.SetBrush(magicBrush);
929 dc.SetPen(*wxTRANSPARENT_PEN);
930 dc.DrawRectangle(0, 0, w, h);
931
932 // Draw image content
933 dc.SetBrush(wxBrush(colour));
934 dc.DrawCircle(h/2, h/2+1, h/2);
935
936 dc.SelectObject(wxNullBitmap);
937
938 // Finalize transparency with a mask
939 wxMask *mask = new wxMask(bmp, magic);
940 bmp.SetMask(mask);
941
942 return bmp;
943 }
944
945 void BitmapComboBoxWidgetsPage::OnDropDown(wxCommandEvent& event)
946 {
947 wxLogMessage(_T("Combobox dropped down"));
948 }
949
950 void BitmapComboBoxWidgetsPage::OnCloseUp(wxCommandEvent& event)
951 {
952 wxLogMessage(_T("Combobox closed up"));
953 }
954
955 #endif // wxUSE_BITMAPCOMBOBOX