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