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