Rescale images automatically with informations about internal requirements (Jaakko...
[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 "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
98 virtual wxControl *GetWidget() const { return m_combobox; }
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
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
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
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 sizerTop->Fit(this);
375 }
376
377 // ----------------------------------------------------------------------------
378 // operations
379 // ----------------------------------------------------------------------------
380
381 void BitmapComboBoxWidgetsPage::Reset()
382 {
383 m_chkSort->SetValue(false);
384 m_chkReadonly->SetValue(true);
385 }
386
387 void BitmapComboBoxWidgetsPage::CreateCombo()
388 {
389 int flags = ms_defaultFlags;
390
391 if ( m_chkSort->GetValue() )
392 flags |= wxCB_SORT;
393 if ( m_chkReadonly->GetValue() )
394 flags |= wxCB_READONLY;
395
396 wxArrayString items;
397 wxArrayPtrVoid bitmaps;
398 if ( m_combobox )
399 {
400 unsigned int count = m_combobox->GetCount();
401 for ( unsigned int n = 0; n < count; n++ )
402 {
403 items.Add(m_combobox->GetString(n));
404 bitmaps.Add(new wxBitmap(m_combobox->GetItemBitmap(n)));
405 }
406
407 m_sizerCombo->Detach( m_combobox );
408 delete m_combobox;
409 }
410
411 m_combobox = new wxBitmapComboBox();
412 m_combobox->Create(this, BitmapComboBoxPage_Combo, wxEmptyString,
413 wxDefaultPosition, wxDefaultSize,
414 0, NULL,
415 flags);
416
417 #if defined(wxGENERIC_BITMAPCOMBOBOX)
418 // This will sure make the list look nicer when larger images are used.
419 m_combobox->SetPopupMaxHeight(600);
420 #endif
421
422 unsigned int count = items.GetCount();
423 for ( unsigned int n = 0; n < count; n++ )
424 {
425 wxBitmap* bmp = (wxBitmap*) bitmaps[n];
426 m_combobox->Append(items[n], *bmp);
427 delete bmp;
428 }
429
430 m_sizerCombo->Add(m_combobox, 0, wxGROW | wxALL, 5);
431 m_sizerCombo->Layout();
432
433 // Allow changing height inorder to demonstrate flexible
434 // size of image "thumbnail" painted in the control itself.
435 long h = 0;
436 m_textChangeHeight->GetValue().ToLong(&h);
437 if ( h >= 5 )
438 m_combobox->SetSize(wxDefaultCoord, h);
439 }
440
441 // ----------------------------------------------------------------------------
442 // event handlers
443 // ----------------------------------------------------------------------------
444
445 void BitmapComboBoxWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
446 {
447 Reset();
448
449 CreateCombo();
450 }
451
452 void BitmapComboBoxWidgetsPage::OnButtonChange(wxCommandEvent& WXUNUSED(event))
453 {
454 int sel = m_combobox->GetSelection();
455 if ( sel != wxNOT_FOUND )
456 {
457 #ifndef __WXGTK__
458 m_combobox->SetString(sel, m_textChange->GetValue());
459 #else
460 wxLogMessage(_T("Not implemented in wxGTK"));
461 #endif
462 }
463 }
464
465 void BitmapComboBoxWidgetsPage::OnButtonDelete(wxCommandEvent& WXUNUSED(event))
466 {
467 unsigned long n;
468 if ( !m_textDelete->GetValue().ToULong(&n) ||
469 (n >= m_combobox->GetCount()) )
470 {
471 return;
472 }
473
474 m_combobox->Delete(n);
475 }
476
477 void BitmapComboBoxWidgetsPage::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(event))
478 {
479 int sel = m_combobox->GetSelection();
480 if ( sel != wxNOT_FOUND )
481 {
482 m_combobox->Delete(sel);
483 }
484 }
485
486 void BitmapComboBoxWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
487 {
488 m_combobox->Clear();
489 }
490
491 void BitmapComboBoxWidgetsPage::OnButtonInsert(wxCommandEvent& WXUNUSED(event))
492 {
493 static unsigned int s_item = 0;
494
495 wxString s = m_textInsert->GetValue();
496 if ( !m_textInsert->IsModified() )
497 {
498 // update the default string
499 m_textInsert->SetValue(wxString::Format(_T("test item %u"), ++s_item));
500 }
501
502 int sel = m_combobox->GetSelection();
503 if ( sel == wxNOT_FOUND )
504 sel = m_combobox->GetCount();
505
506 m_combobox->Insert(s, wxNullBitmap, m_combobox->GetSelection());
507 }
508
509 void BitmapComboBoxWidgetsPage::OnTextChangeHeight(wxCommandEvent& WXUNUSED(event))
510 {
511 long h = 0;
512 m_textChangeHeight->GetValue().ToLong(&h);
513 if ( h < 5 )
514 return;
515 m_combobox->SetSize(wxDefaultCoord, h);
516 }
517
518 void BitmapComboBoxWidgetsPage::OnButtonLoadFromFile(wxCommandEvent& WXUNUSED(event))
519 {
520 wxString s;
521 int sel = m_combobox->GetSelection();
522 if ( sel == wxNOT_FOUND )
523 sel = m_combobox->GetCount();
524
525 m_combobox->Insert(s, QueryBitmap(&s), sel);
526 }
527
528 void BitmapComboBoxWidgetsPage::OnButtonSetFromFile(wxCommandEvent& WXUNUSED(event))
529 {
530 m_combobox->SetItemBitmap(m_combobox->GetSelection(), QueryBitmap(NULL));
531 }
532
533 void BitmapComboBoxWidgetsPage::OnButtonAddMany(wxCommandEvent& WXUNUSED(event))
534 {
535 // "many" means 1000 here
536 for ( unsigned int n = 0; n < 1000; n++ )
537 {
538 m_combobox->Append(wxString::Format(_T("item #%u"), n));
539 }
540 }
541
542 void BitmapComboBoxWidgetsPage::OnButtonAddSeveral(wxCommandEvent& WXUNUSED(event))
543 {
544 m_combobox->Append(_T("First"));
545 m_combobox->Append(_T("another one"));
546 m_combobox->Append(_T("and the last (very very very very very very very very very very long) one"));
547 }
548
549 void BitmapComboBoxWidgetsPage::OnButtonAddSeveralWithImages(wxCommandEvent& WXUNUSED(event))
550 {
551 int i;
552
553 for ( i=0; i<4; i++ )
554 {
555 wxString s;
556 wxBitmap bmp = CreateRandomBitmap(&s);
557 m_combobox->Append(s, bmp);
558 }
559 }
560
561 #if wxUSE_IMAGE
562 void BitmapComboBoxWidgetsPage::RescaleImage(wxImage& image, int w, int h)
563 {
564 if ( image.GetWidth() == w && image.GetHeight() == h )
565 return;
566
567 if ( w <= 0 || h <= 0 )
568 return;
569
570 static bool isFirstScale = true;
571
572 if ( isFirstScale && m_combobox->GetCount() > 0 )
573 {
574 wxMessageBox( wxT("wxBitmapComboBox normally only supports images of one size. ")
575 wxT("However, for demonstration purposes, loaded bitmaps are scaled to fit ")
576 wxT("using wxImage::Rescale."),
577 wxT("Notice"),
578 wxOK,
579 this );
580
581 isFirstScale = false;
582 }
583
584 image.Rescale(w, h);
585 }
586 #endif
587
588 void BitmapComboBoxWidgetsPage::LoadWidgetImages( wxArrayString* strings, wxImageList* images )
589 {
590 wxFileName fn;
591 fn.AssignCwd();
592 fn.AppendDir(wxT("icons"));
593
594 wxSetCursor(*wxHOURGLASS_CURSOR);
595
596 if ( !wxDir::Exists(fn.GetFullPath()) ||
597 !wxDir::GetAllFiles(fn.GetFullPath(),strings,wxT("*.xpm")) )
598 {
599 fn.RemoveLastDir();
600 fn.RemoveLastDir();
601 fn.AppendDir(wxT("icons"));
602 if ( !wxDir::Exists(fn.GetFullPath()) ||
603 !wxDir::GetAllFiles(fn.GetFullPath(),strings,wxT("*.xpm")) )
604 {
605 // Try ../../../samples/widgets/icons
606 fn.AssignCwd();
607 fn.RemoveLastDir();
608 fn.RemoveLastDir();
609 fn.RemoveLastDir();
610 fn.AppendDir(wxT("samples"));
611 fn.AppendDir(wxT("widgets"));
612 fn.AppendDir(wxT("icons"));
613 if ( !wxDir::Exists(fn.GetFullPath()) ||
614 !wxDir::GetAllFiles(fn.GetFullPath(),strings,wxT("*.xpm")) )
615 {
616 wxLogWarning(wxT("Could not load widget icons."));
617 wxSetCursor(*wxSTANDARD_CURSOR);
618 return;
619 }
620 }
621 }
622
623 unsigned int i;
624
625 // Get size of existing images in list
626 wxSize foundSize = m_combobox->GetBitmapSize();
627
628 for ( i=0; i<strings->size(); i++ )
629 {
630 fn.SetFullName((*strings)[i]);
631 wxString name =fn.GetName();
632
633 // Handle few exceptions
634 if ( name == wxT("bmpbtn") )
635 {
636 strings->RemoveAt(i);
637 i--;
638 }
639 else
640 {
641 #if wxUSE_IMAGE
642 wxASSERT(fn.FileExists());
643 wxImage image(fn.GetFullPath());
644 wxASSERT(image.Ok());
645 RescaleImage(image, foundSize.x, foundSize.y);
646 wxBitmap bmp(image);
647 wxASSERT( bmp.Ok() );
648 #else
649 wxBitmap bmp(wxNullBitmap);
650 #endif
651 images->Add(bmp);
652 (*strings)[i] = name;
653 }
654 }
655
656 wxSetCursor(*wxSTANDARD_CURSOR);
657 }
658
659 void BitmapComboBoxWidgetsPage::OnButtonAddWidgetIcons(wxCommandEvent& WXUNUSED(event))
660 {
661 wxArrayString strings;
662
663 wxSize sz = m_combobox->GetBitmapSize();
664 if ( sz.x <= 0 )
665 {
666 sz.x = 32;
667 sz.y = 32;
668 }
669
670 wxImageList images(sz.x, sz.y);
671
672 LoadWidgetImages(&strings, &images);
673
674 unsigned int i;
675
676 for ( i=0; i<strings.size(); i++ )
677 {
678 m_combobox->Append(strings[i], images.GetBitmap(i));
679 }
680 }
681
682 void BitmapComboBoxWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
683 {
684 if (m_combobox)
685 event.Enable( m_chkSort->GetValue() || m_chkReadonly->GetValue() );
686 }
687
688 void BitmapComboBoxWidgetsPage::OnUpdateUIInsert(wxUpdateUIEvent& event)
689 {
690 if (m_combobox)
691 {
692 bool enable = !(m_combobox->GetWindowStyle() & wxCB_SORT);
693
694 event.Enable(enable);
695 }
696 }
697
698 void BitmapComboBoxWidgetsPage::OnUpdateUIDeleteButton(wxUpdateUIEvent& event)
699 {
700 if (m_combobox)
701 {
702 unsigned long n;
703 event.Enable(m_textDelete->GetValue().ToULong(&n) &&
704 (n < (unsigned)m_combobox->GetCount()));
705 }
706 }
707
708 void BitmapComboBoxWidgetsPage::OnUpdateUIItemManipulator(wxUpdateUIEvent& event)
709 {
710 if (m_combobox)
711 event.Enable(m_combobox->GetSelection() != wxNOT_FOUND);
712 }
713
714 void BitmapComboBoxWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
715 {
716 if (m_combobox)
717 event.Enable(m_combobox->GetCount() != 0);
718 }
719
720 void BitmapComboBoxWidgetsPage::OnUpdateUIAddSeveral(wxUpdateUIEvent& event)
721 {
722 if (m_combobox)
723 event.Enable(!(m_combobox->GetWindowStyle() & wxCB_SORT));
724 }
725
726 void BitmapComboBoxWidgetsPage::OnUpdateUIAddSeveralWithImages(wxUpdateUIEvent& event)
727 {
728 if (m_combobox)
729 event.Enable(!(m_combobox->GetWindowStyle() & wxCB_SORT));
730 }
731
732 void BitmapComboBoxWidgetsPage::OnComboText(wxCommandEvent& event)
733 {
734 if (!m_combobox)
735 return;
736
737 wxString s = event.GetString();
738
739 wxASSERT_MSG( s == m_combobox->GetValue(),
740 _T("event and combobox values should be the same") );
741
742 if (event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
743 wxLogMessage(_T("BitmapCombobox enter pressed (now '%s')"), s.c_str());
744 else
745 wxLogMessage(_T("BitmapCombobox text changed (now '%s')"), s.c_str());
746 }
747
748 void BitmapComboBoxWidgetsPage::OnComboBox(wxCommandEvent& event)
749 {
750 long sel = event.GetInt();
751 m_textDelete->SetValue(wxString::Format(_T("%ld"), sel));
752
753 wxLogMessage(_T("BitmapCombobox item %ld selected"), sel);
754
755 wxLogMessage(_T("BitmapCombobox GetValue(): %s"), m_combobox->GetValue().c_str() );
756 }
757
758 void BitmapComboBoxWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& WXUNUSED(event))
759 {
760 CreateCombo();
761 }
762
763 #if wxUSE_IMAGE
764 wxBitmap BitmapComboBoxWidgetsPage::LoadBitmap(const wxString& filepath)
765 {
766 // Get size of existing images in list
767 wxSize foundSize = m_combobox->GetBitmapSize();
768
769 // Have some reasonable maximum size
770 if ( foundSize.x <= 0 )
771 {
772 foundSize.x = IMG_SIZE_TRUNC;
773 foundSize.y = IMG_SIZE_TRUNC;
774 }
775
776 wxImage image(filepath);
777 if ( image.Ok() )
778 {
779 // Rescale very large images
780 int ow = image.GetWidth();
781 int oh = image.GetHeight();
782
783 if ( foundSize.x > 0 &&
784 (ow != foundSize.x || oh != foundSize.y) )
785 {
786 int w = ow;
787 if ( w > foundSize.x )
788 w = foundSize.x;
789 int h = oh;
790 if ( h > foundSize.y )
791 h = foundSize.y;
792
793 RescaleImage(image, w, h);
794 }
795
796 return wxBitmap(image);
797 }
798
799 return wxNullBitmap;
800 }
801 #else
802 wxBitmap BitmapComboBoxWidgetsPage::LoadBitmap(const wxString& WXUNUSED(filepath))
803 {
804 return wxNullBitmap;
805 }
806 #endif
807
808 wxBitmap BitmapComboBoxWidgetsPage::QueryBitmap(wxString* pStr)
809 {
810 wxString filepath = wxFileSelector(wxT("Choose image file"),
811 wxEmptyString,
812 wxEmptyString,
813 wxEmptyString,
814 wxT("*.*"),
815 wxFD_OPEN | wxFD_FILE_MUST_EXIST,
816 this);
817
818 wxBitmap bitmap;
819
820 ::wxSetCursor( *wxHOURGLASS_CURSOR );
821
822 if ( filepath.length() )
823 {
824 if ( pStr )
825 {
826 *pStr = wxFileName(filepath).GetName();
827 }
828
829 bitmap = LoadBitmap(filepath);
830 }
831
832 wxLogDebug(wxT("%i, %i"),bitmap.GetWidth(), bitmap.GetHeight());
833
834 ::wxSetCursor( *wxSTANDARD_CURSOR );
835
836 return bitmap;
837 }
838
839 wxBitmap BitmapComboBoxWidgetsPage::CreateBitmap(const wxColour& colour)
840 {
841 int ch = m_combobox->GetBitmapSize().y;
842 int h0 = ch - 5;
843
844 long w = ch;
845 long h = ch;
846
847 if ( w <= 0 )
848 w = h0 - 1;
849 if ( h <= 0 )
850 h = h0;
851 if ( h > ch )
852 h = ch;
853
854 wxMemoryDC dc;
855 wxBitmap bmp(w,h);
856 dc.SelectObject(bmp);
857
858 // Draw transparent background
859 wxColour magic(255,0,255);
860 wxBrush magicBrush(magic);
861 dc.SetBrush(magicBrush);
862 dc.SetPen(*wxTRANSPARENT_PEN);
863 dc.DrawRectangle(0,0,bmp.GetWidth(),bmp.GetHeight());
864
865 // Draw image content
866 dc.SetBrush(wxBrush(colour));
867 dc.DrawCircle(h/2,h/2+1,(h/2));
868
869 dc.SelectObject(wxNullBitmap);
870
871 // Finalize transparency with a mask
872 wxMask *mask = new wxMask(bmp, magic);
873 bmp.SetMask(mask);
874
875 return bmp;
876 }
877
878 wxBitmap BitmapComboBoxWidgetsPage::CreateRandomBitmap( wxString* pStr )
879 {
880 int i = rand() % 6;
881 const wxChar* str = wxT("");
882 wxBitmap bmp;
883
884 if ( i == 0 )
885 {
886 str = wxT("Red Circle");
887 bmp = CreateBitmap( *wxRED );
888 }
889 else if ( i == 1 )
890 {
891 str = wxT("Green Circle");
892 bmp = CreateBitmap( *wxGREEN );
893 }
894 else if ( i == 2 )
895 {
896 str = wxT("Blue Circle");
897 bmp = CreateBitmap( *wxBLUE );
898 }
899 else if ( i == 3 )
900 {
901 str = wxT("Black Circle");
902 bmp = CreateBitmap( *wxBLACK );
903 }
904 else if ( i == 4 )
905 {
906 str = wxT("Cyan Circle");
907 bmp = CreateBitmap( *wxCYAN );
908 }
909 else if ( i == 5 )
910 {
911 str = wxT("Light Grey Circle");
912 bmp = CreateBitmap( *wxLIGHT_GREY );
913 }
914
915 if ( pStr )
916 *pStr = str;
917
918 return bmp;
919 }
920
921 #endif //wxUSE_BITMAPCOMBOBOX