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