1 /////////////////////////////////////////////////////////////////////////////
2 // Program:     wxWidgets Widgets Sample
3 // Name:        odcombobox.cpp
4 // Purpose:     Part of the widgets sample showing wxOwnerDrawnComboBox
5 // Author:      Jaakko Salli (based on combobox page by Vadim Zeitlin)
6 // Created:     Jul-28-2006
7 // Copyright:   (c) 2006 Jaakko Salli
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // for compilers that support precompilation, includes "wx/wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 #if wxUSE_ODCOMBOBOX
27 
28 // for all others, include the necessary headers
29 #ifndef WX_PRECOMP
30     #include "wx/log.h"
31 
32     #include "wx/bitmap.h"
33     #include "wx/button.h"
34     #include "wx/checkbox.h"
35     #include "wx/combobox.h"
36     #include "wx/radiobox.h"
37     #include "wx/statbox.h"
38     #include "wx/textctrl.h"
39 #endif
40 
41 #include "wx/dc.h"
42 #include "wx/dcmemory.h"
43 #include "wx/sizer.h"
44 #include "wx/odcombo.h"
45 
46 
47 #include "itemcontainer.h"
48 #include "widgets.h"
49 
50 #include "icons/odcombobox.xpm"
51 
52 // ----------------------------------------------------------------------------
53 // constants
54 // ----------------------------------------------------------------------------
55 
56 // control ids
57 enum
58 {
59     ODComboPage_Reset = wxID_HIGHEST,
60     ODComboPage_PopupMinWidth,
61     ODComboPage_PopupHeight,
62     ODComboPage_ButtonWidth,
63     ODComboPage_ButtonHeight,
64     ODComboPage_ButtonSpacing,
65     ODComboPage_CurText,
66     ODComboPage_InsertionPointText,
67     ODComboPage_Insert,
68     ODComboPage_InsertText,
69     ODComboPage_Add,
70     ODComboPage_AddText,
71     ODComboPage_AddSeveral,
72     ODComboPage_AddMany,
73     ODComboPage_Clear,
74     ODComboPage_Change,
75     ODComboPage_ChangeText,
76     ODComboPage_Delete,
77     ODComboPage_DeleteText,
78     ODComboPage_DeleteSel,
79     ODComboPage_Combo,
80     ODComboPage_ContainerTests
81 };
82 
83 
84 // ----------------------------------------------------------------------------
85 // ODComboboxWidgetsPage
86 // ----------------------------------------------------------------------------
87 
88 class ODComboboxWidgetsPage : public ItemContainerWidgetsPage
89 {
90 public:
91     ODComboboxWidgetsPage(WidgetsBookCtrl *book, wxImageList *imaglist);
92 
GetWidget() const93     virtual wxControl *GetWidget() const { return m_combobox; }
GetTextEntry() const94     virtual wxTextEntryBase *GetTextEntry() const
95         { return m_combobox ? m_combobox->GetTextCtrl() : NULL; }
GetContainer() const96     virtual wxItemContainer* GetContainer() const { return m_combobox; }
RecreateWidget()97     virtual void RecreateWidget() { CreateCombo(); }
98 
99     // lazy creation of the content
100     virtual void CreateContent();
101 
102 protected:
103     // event handlers
104     void OnButtonReset(wxCommandEvent& event);
105     void OnButtonChange(wxCommandEvent& event);
106     void OnButtonDelete(wxCommandEvent& event);
107     void OnButtonDeleteSel(wxCommandEvent& event);
108     void OnButtonClear(wxCommandEvent& event);
109     void OnButtonInsert(wxCommandEvent &event);
110     void OnButtonAdd(wxCommandEvent& event);
111     void OnButtonAddSeveral(wxCommandEvent& event);
112     void OnButtonAddMany(wxCommandEvent& event);
113 
114     void OnComboBox(wxCommandEvent& event);
115     void OnDropDown(wxCommandEvent& event);
116     void OnCloseUp(wxCommandEvent& event);
117     void OnComboText(wxCommandEvent& event);
118 
119     void OnCheckOrRadioBox(wxCommandEvent& event);
120 
121     void OnTextPopupWidth(wxCommandEvent& event);
122     void OnTextPopupHeight(wxCommandEvent& event);
123     void OnTextButtonAll(wxCommandEvent& event);
124 
125     void OnUpdateUICurText(wxUpdateUIEvent& event);
126     void OnUpdateUIInsertionPointText(wxUpdateUIEvent& event);
127 
128     void OnUpdateUIInsert(wxUpdateUIEvent& event);
129     void OnUpdateUIAddSeveral(wxUpdateUIEvent& event);
130     void OnUpdateUIClearButton(wxUpdateUIEvent& event);
131     void OnUpdateUIDeleteButton(wxUpdateUIEvent& event);
132     void OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event);
133     void OnUpdateUIResetButton(wxUpdateUIEvent& event);
134 
135     // reset the odcombobox parameters
136     void Reset();
137 
138     // (re)create the odcombobox
139     void CreateCombo();
140 
141     // helper that gets all button values from controls and calls SetButtonPosition
142     void GetButtonPosition();
143 
144     // helper to create the button bitmap
145     wxBitmap CreateBitmap(const wxColour& colour);
146 
147     // the controls
148     // ------------
149 
150     // the checkboxes for styles
151     wxCheckBox *m_chkSort,
152                *m_chkReadonly,
153                *m_chkDclickcycles,
154                *m_chkBitmapbutton,
155                *m_chkStdbutton;
156 
157     // the text entries for popup and button adjustment
158     wxTextCtrl *m_textPopupMinWidth,
159                *m_textPopupHeight,
160                *m_textButtonWidth,
161                *m_textButtonHeight,
162                *m_textButtonSpacing;
163 
164     // the checkboxes for same
165     wxCheckBox *m_chkAlignpopupright,
166                *m_chkAlignbutleft;
167 
168     // the combobox itself and the sizer it is in
169     wxOwnerDrawnComboBox *m_combobox;
170     wxSizer *m_sizerCombo;
171 
172     // the text entries for "Add/change string" and "Delete" buttons
173     wxTextCtrl *m_textInsert,
174                *m_textAdd,
175                *m_textChange,
176                *m_textDelete;
177 
178 private:
179     wxDECLARE_EVENT_TABLE();
180     DECLARE_WIDGETS_PAGE(ODComboboxWidgetsPage)
181 };
182 
183 // ----------------------------------------------------------------------------
184 // event tables
185 // ----------------------------------------------------------------------------
186 
187 wxBEGIN_EVENT_TABLE(ODComboboxWidgetsPage, WidgetsPage)
188     EVT_BUTTON(ODComboPage_Reset, ODComboboxWidgetsPage::OnButtonReset)
189     EVT_BUTTON(ODComboPage_Change, ODComboboxWidgetsPage::OnButtonChange)
190     EVT_BUTTON(ODComboPage_Delete, ODComboboxWidgetsPage::OnButtonDelete)
191     EVT_BUTTON(ODComboPage_DeleteSel, ODComboboxWidgetsPage::OnButtonDeleteSel)
192     EVT_BUTTON(ODComboPage_Clear, ODComboboxWidgetsPage::OnButtonClear)
193     EVT_BUTTON(ODComboPage_Insert, ODComboboxWidgetsPage::OnButtonInsert)
194     EVT_BUTTON(ODComboPage_Add, ODComboboxWidgetsPage::OnButtonAdd)
195     EVT_BUTTON(ODComboPage_AddSeveral, ODComboboxWidgetsPage::OnButtonAddSeveral)
196     EVT_BUTTON(ODComboPage_AddMany, ODComboboxWidgetsPage::OnButtonAddMany)
197     EVT_BUTTON(ODComboPage_ContainerTests, ItemContainerWidgetsPage::OnButtonTestItemContainer)
198 
199     EVT_TEXT_ENTER(ODComboPage_InsertText, ODComboboxWidgetsPage::OnButtonInsert)
200     EVT_TEXT_ENTER(ODComboPage_AddText, ODComboboxWidgetsPage::OnButtonAdd)
201     EVT_TEXT_ENTER(ODComboPage_DeleteText, ODComboboxWidgetsPage::OnButtonDelete)
202 
203     EVT_TEXT(ODComboPage_PopupMinWidth, ODComboboxWidgetsPage::OnTextPopupWidth)
204     EVT_TEXT(ODComboPage_PopupHeight, ODComboboxWidgetsPage::OnTextPopupHeight)
205     EVT_TEXT(ODComboPage_ButtonWidth, ODComboboxWidgetsPage::OnTextButtonAll)
206     EVT_TEXT(ODComboPage_ButtonHeight, ODComboboxWidgetsPage::OnTextButtonAll)
207     EVT_TEXT(ODComboPage_ButtonSpacing, ODComboboxWidgetsPage::OnTextButtonAll)
208 
209     EVT_UPDATE_UI(ODComboPage_CurText, ODComboboxWidgetsPage::OnUpdateUICurText)
210     EVT_UPDATE_UI(ODComboPage_InsertionPointText, ODComboboxWidgetsPage::OnUpdateUIInsertionPointText)
211 
212     EVT_UPDATE_UI(ODComboPage_Reset, ODComboboxWidgetsPage::OnUpdateUIResetButton)
213     EVT_UPDATE_UI(ODComboPage_Insert, ODComboboxWidgetsPage::OnUpdateUIInsert)
214     EVT_UPDATE_UI(ODComboPage_AddSeveral, ODComboboxWidgetsPage::OnUpdateUIAddSeveral)
215     EVT_UPDATE_UI(ODComboPage_Clear, ODComboboxWidgetsPage::OnUpdateUIClearButton)
216     EVT_UPDATE_UI(ODComboPage_DeleteText, ODComboboxWidgetsPage::OnUpdateUIClearButton)
217     EVT_UPDATE_UI(ODComboPage_Delete, ODComboboxWidgetsPage::OnUpdateUIDeleteButton)
218     EVT_UPDATE_UI(ODComboPage_Change, ODComboboxWidgetsPage::OnUpdateUIDeleteSelButton)
219     EVT_UPDATE_UI(ODComboPage_ChangeText, ODComboboxWidgetsPage::OnUpdateUIDeleteSelButton)
220     EVT_UPDATE_UI(ODComboPage_DeleteSel, ODComboboxWidgetsPage::OnUpdateUIDeleteSelButton)
221 
222     EVT_COMBOBOX_DROPDOWN(ODComboPage_Combo, ODComboboxWidgetsPage::OnDropDown)
223     EVT_COMBOBOX_CLOSEUP(ODComboPage_Combo, ODComboboxWidgetsPage::OnCloseUp)
224     EVT_COMBOBOX(ODComboPage_Combo, ODComboboxWidgetsPage::OnComboBox)
225     EVT_TEXT(ODComboPage_Combo, ODComboboxWidgetsPage::OnComboText)
226     EVT_TEXT_ENTER(ODComboPage_Combo, ODComboboxWidgetsPage::OnComboText)
227 
228     EVT_CHECKBOX(wxID_ANY, ODComboboxWidgetsPage::OnCheckOrRadioBox)
229     EVT_RADIOBOX(wxID_ANY, ODComboboxWidgetsPage::OnCheckOrRadioBox)
230 wxEND_EVENT_TABLE()
231 
232 // ============================================================================
233 // implementation
234 // ============================================================================
235 
236 //
237 // wxOwnerDrawnComboBox needs to subclassed so that owner-drawing
238 // callbacks can be implemented.
239 class DemoODComboBox : public wxOwnerDrawnComboBox
240 {
241 public:
OnDrawItem(wxDC & dc,const wxRect & rect,int item,int WXUNUSED (flags)) const242     virtual void OnDrawItem(wxDC& dc,
243                             const wxRect& rect,
244                             int item,
245                             int WXUNUSED(flags)) const
246     {
247         if ( item == wxNOT_FOUND )
248             return;
249 
250         wxColour txtCol;
251         int mod = item % 4;
252 
253         if ( mod == 0 )
254             txtCol = *wxBLACK;
255         else if ( mod == 1 )
256             txtCol = *wxRED;
257         else if ( mod == 2 )
258             txtCol = *wxGREEN;
259         else
260             txtCol = *wxBLUE;
261 
262         dc.SetTextForeground(txtCol);
263 
264         dc.DrawText(GetString(item),
265                     rect.x + 3,
266                     rect.y + ((rect.height - dc.GetCharHeight())/2)
267                    );
268     }
269 
OnDrawBackground(wxDC & dc,const wxRect & rect,int item,int flags) const270     virtual void OnDrawBackground(wxDC& dc, const wxRect& rect,
271                                   int item, int flags ) const
272     {
273 
274         // If item is selected or even, or we are painting the
275         // combo control itself, use the default rendering.
276         if ( (flags & (wxODCB_PAINTING_CONTROL|wxODCB_PAINTING_SELECTED)) ||
277              (item & 1) == 0 )
278         {
279             wxOwnerDrawnComboBox::OnDrawBackground(dc,rect,item,flags);
280             return;
281         }
282 
283         // Otherwise, draw every other background with different colour.
284         wxColour bgCol(240,240,250);
285         dc.SetBrush(wxBrush(bgCol));
286         dc.SetPen(wxPen(bgCol));
287         dc.DrawRectangle(rect);
288     }
289 
OnMeasureItem(size_t WXUNUSED (item)) const290     virtual wxCoord OnMeasureItem(size_t WXUNUSED(item)) const
291     {
292         return 48;
293     }
294 
OnMeasureItemWidth(size_t WXUNUSED (item)) const295     virtual wxCoord OnMeasureItemWidth(size_t WXUNUSED(item)) const
296     {
297         return -1; // default - will be measured from text width
298     }
299 };
300 
301 
302 IMPLEMENT_WIDGETS_PAGE(ODComboboxWidgetsPage, wxT("OwnerDrawnCombobox"),
303                        GENERIC_CTRLS | WITH_ITEMS_CTRLS | COMBO_CTRLS
304                        );
305 
ODComboboxWidgetsPage(WidgetsBookCtrl * book,wxImageList * imaglist)306 ODComboboxWidgetsPage::ODComboboxWidgetsPage(WidgetsBookCtrl *book,
307                                              wxImageList *imaglist)
308                   : ItemContainerWidgetsPage(book, imaglist, odcombobox_xpm),
309                     m_textPopupMinWidth(NULL), m_textPopupHeight(NULL)
310 {
311     // init everything
312     m_chkSort =
313     m_chkReadonly =
314     m_chkDclickcycles = (wxCheckBox *)NULL;
315 
316     m_combobox = (wxOwnerDrawnComboBox *)NULL;
317     m_sizerCombo = (wxSizer *)NULL;
318 }
319 
CreateContent()320 void ODComboboxWidgetsPage::CreateContent()
321 {
322     /*
323        What we create here is a frame having 3 panes: style pane is the
324        leftmost one, in the middle the pane with buttons allowing to perform
325        miscellaneous combobox operations and the pane containing the combobox
326        itself to the right
327     */
328     wxTextCtrl *text;
329     wxSizer *sizerRow;
330 
331     wxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
332 
333     wxSizer *sizerLeft = new wxBoxSizer(wxVERTICAL);
334 
335     // left pane - style box
336     wxStaticBox *box = new wxStaticBox(this, wxID_ANY, wxT("&Set style"));
337 
338     wxSizer *sizerStyle = new wxStaticBoxSizer(box, wxVERTICAL);
339 
340     m_chkSort = CreateCheckBoxAndAddToSizer(sizerStyle, wxT("&Sort items"));
341     m_chkReadonly = CreateCheckBoxAndAddToSizer(sizerStyle, wxT("&Read only"));
342     m_chkDclickcycles = CreateCheckBoxAndAddToSizer(sizerStyle, wxT("&Double-click Cycles"));
343 
344     sizerStyle->AddSpacer(4);
345 
346     m_chkBitmapbutton = CreateCheckBoxAndAddToSizer(sizerStyle, wxT("&Bitmap button"));
347     m_chkStdbutton = CreateCheckBoxAndAddToSizer(sizerStyle, wxT("B&lank button background"));
348 
349     wxButton *btn = new wxButton(this, ODComboPage_Reset, wxT("&Reset"));
350     sizerStyle->Add(btn, 0, wxALIGN_CENTRE_HORIZONTAL | wxALL, 3);
351 
352     sizerLeft->Add(sizerStyle, 0, wxGROW | wxALIGN_CENTRE_HORIZONTAL);
353 
354     // left pane - popup adjustment box
355     box = new wxStaticBox(this, wxID_ANY, wxT("Adjust &popup"));
356 
357     wxSizer *sizerPopupPos = new wxStaticBoxSizer(box, wxVERTICAL);
358 
359     sizerRow = CreateSizerWithTextAndLabel(wxT("Min. Width:"),
360                                            ODComboPage_PopupMinWidth,
361                                            &m_textPopupMinWidth);
362     m_textPopupMinWidth->SetValue(wxT("-1"));
363     sizerPopupPos->Add(sizerRow, 0, wxALL | wxGROW, 5);
364 
365     sizerRow = CreateSizerWithTextAndLabel(wxT("Max. Height:"),
366                                            ODComboPage_PopupHeight,
367                                            &m_textPopupHeight);
368     m_textPopupHeight->SetValue(wxT("-1"));
369     sizerPopupPos->Add(sizerRow, 0, wxALL | wxGROW, 5);
370 
371     m_chkAlignpopupright = CreateCheckBoxAndAddToSizer(sizerPopupPos, wxT("Align Right"));
372 
373     sizerLeft->Add(sizerPopupPos, 0, wxGROW | wxALIGN_CENTRE_HORIZONTAL | wxTOP, 2);
374 
375     // left pane - button adjustment box
376     box = new wxStaticBox(this, wxID_ANY, wxT("Adjust &button"));
377 
378     wxSizer *sizerButtonPos = new wxStaticBoxSizer(box, wxVERTICAL);
379 
380     sizerRow = CreateSizerWithTextAndLabel(wxT("Width:"),
381                                            ODComboPage_ButtonWidth,
382                                            &m_textButtonWidth);
383     m_textButtonWidth->SetValue(wxT("-1"));
384     sizerButtonPos->Add(sizerRow, 0, wxALL | wxGROW, 5);
385 
386     sizerRow = CreateSizerWithTextAndLabel(wxT("VSpacing:"),
387                                            ODComboPage_ButtonSpacing,
388                                            &m_textButtonSpacing);
389     m_textButtonSpacing->SetValue(wxT("0"));
390     sizerButtonPos->Add(sizerRow, 0, wxALL | wxGROW, 5);
391 
392     sizerRow = CreateSizerWithTextAndLabel(wxT("Height:"),
393                                            ODComboPage_ButtonHeight,
394                                            &m_textButtonHeight);
395     m_textButtonHeight->SetValue(wxT("-1"));
396     sizerButtonPos->Add(sizerRow, 0, wxALL | wxGROW, 5);
397 
398     m_chkAlignbutleft = CreateCheckBoxAndAddToSizer(sizerButtonPos, wxT("Align Left"));
399 
400     sizerLeft->Add(sizerButtonPos, 0, wxGROW | wxALIGN_CENTRE_HORIZONTAL | wxTOP, 2);
401 
402     // middle pane
403     wxStaticBox *box2 = new wxStaticBox(this, wxID_ANY,
404         wxT("&Change combobox contents"));
405     wxSizer *sizerMiddle = new wxStaticBoxSizer(box2, wxVERTICAL);
406 
407     btn = new wxButton(this, ODComboPage_ContainerTests, wxT("Run &tests"));
408     sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
409 
410     sizerRow = CreateSizerWithTextAndLabel(wxT("Current selection"),
411                                            ODComboPage_CurText,
412                                            &text);
413     text->SetEditable(false);
414 
415     sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
416 
417     sizerRow = CreateSizerWithTextAndLabel(wxT("Insertion Point"),
418                                            ODComboPage_InsertionPointText,
419                                            &text);
420     text->SetEditable(false);
421 
422     sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
423 
424     sizerRow = CreateSizerWithTextAndButton(ODComboPage_Insert,
425                                             wxT("&Insert this string"),
426                                             ODComboPage_InsertText,
427                                             &m_textInsert);
428     sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
429 
430     sizerRow = CreateSizerWithTextAndButton(ODComboPage_Add,
431                                             wxT("&Add this string"),
432                                             ODComboPage_AddText,
433                                             &m_textAdd);
434     sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
435 
436     btn = new wxButton(this, ODComboPage_AddSeveral, wxT("&Append a few strings"));
437     sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
438 
439     btn = new wxButton(this, ODComboPage_AddMany, wxT("Append &many strings"));
440     sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
441 
442     sizerRow = CreateSizerWithTextAndButton(ODComboPage_Change,
443                                             wxT("C&hange current"),
444                                             ODComboPage_ChangeText,
445                                             &m_textChange);
446     sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
447 
448     sizerRow = CreateSizerWithTextAndButton(ODComboPage_Delete,
449                                             wxT("&Delete this item"),
450                                             ODComboPage_DeleteText,
451                                             &m_textDelete);
452     sizerMiddle->Add(sizerRow, 0, wxALL | wxGROW, 5);
453 
454     btn = new wxButton(this, ODComboPage_DeleteSel, wxT("Delete &selection"));
455     sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
456 
457     btn = new wxButton(this, ODComboPage_Clear, wxT("&Clear"));
458     sizerMiddle->Add(btn, 0, wxALL | wxGROW, 5);
459 
460     // right pane
461     wxSizer *sizerRight = new wxBoxSizer(wxVERTICAL);
462     m_combobox = new DemoODComboBox();
463     m_combobox->Create(this, ODComboPage_Combo, wxEmptyString,
464                        wxDefaultPosition, wxDefaultSize,
465                        0, NULL,
466                        0);
467     sizerRight->Add(m_combobox, 0, wxGROW | wxALL, 5);
468     sizerRight->SetMinSize(150, 0);
469     m_sizerCombo = sizerRight; // save it to modify it later
470 
471     // the 3 panes panes compose the window
472     sizerTop->Add(sizerLeft, 4, wxGROW | (wxALL & ~wxLEFT), 10);
473     sizerTop->Add(sizerMiddle, 5, wxGROW | wxALL, 10);
474     sizerTop->Add(sizerRight, 4, wxGROW | (wxALL & ~wxRIGHT), 10);
475 
476     // final initializations
477     Reset();
478 
479     SetSizer(sizerTop);
480 }
481 
482 // ----------------------------------------------------------------------------
483 // operations
484 // ----------------------------------------------------------------------------
485 
Reset()486 void ODComboboxWidgetsPage::Reset()
487 {
488     m_chkSort->SetValue(false);
489     m_chkReadonly->SetValue(false);
490     m_chkDclickcycles->SetValue(false);
491     m_chkDclickcycles->Enable(false);
492     m_chkBitmapbutton->SetValue(false);
493     m_chkStdbutton->SetValue(false);
494     m_chkStdbutton->Enable(false);
495 }
496 
CreateCombo()497 void ODComboboxWidgetsPage::CreateCombo()
498 {
499     int flags = ms_defaultFlags;
500 
501     if ( m_chkSort->GetValue() )
502         flags |= wxCB_SORT;
503     if ( m_chkReadonly->GetValue() )
504         flags |= wxCB_READONLY;
505     if ( m_chkDclickcycles->GetValue() )
506         flags |= wxODCB_DCLICK_CYCLES;
507 
508     wxArrayString items;
509     if ( m_combobox )
510     {
511         unsigned int count = m_combobox->GetCount();
512         for ( unsigned int n = 0; n < count; n++ )
513         {
514             items.Add(m_combobox->GetString(n));
515         }
516 
517         m_sizerCombo->Detach( m_combobox );
518         delete m_combobox;
519     }
520 
521     m_combobox = new DemoODComboBox();
522     m_combobox->Create(this, ODComboPage_Combo, wxEmptyString,
523                        wxDefaultPosition, wxDefaultSize,
524                        0, NULL,
525                        flags);
526 
527     unsigned int count = items.GetCount();
528     for ( unsigned int n = 0; n < count; n++ )
529     {
530         m_combobox->Append(items[n]);
531     }
532 
533     // Update from controls that edit popup position etc.
534 
535     wxUpdateUIEvent tempEvt;
536     OnTextPopupWidth(tempEvt);
537     OnTextPopupHeight(tempEvt);
538     GetButtonPosition();
539 
540     m_combobox->SetPopupAnchor( m_chkAlignpopupright->GetValue() ? wxRIGHT : wxLEFT );
541 
542     if ( m_chkBitmapbutton->GetValue() )
543     {
544         wxBitmap bmpNormal = CreateBitmap(*wxBLUE);
545         wxBitmap bmpPressed = CreateBitmap(wxColour(0,0,128));
546         wxBitmap bmpHover = CreateBitmap(wxColour(128,128,255));
547         m_combobox->SetButtonBitmaps(bmpNormal,m_chkStdbutton->GetValue(),bmpPressed,bmpHover);
548     }
549 
550     m_sizerCombo->Add(m_combobox, 0, wxGROW | wxALL, 5);
551     m_sizerCombo->Layout();
552 }
553 
554 // ----------------------------------------------------------------------------
555 // event handlers
556 // ----------------------------------------------------------------------------
557 
OnButtonReset(wxCommandEvent & WXUNUSED (event))558 void ODComboboxWidgetsPage::OnButtonReset(wxCommandEvent& WXUNUSED(event))
559 {
560     Reset();
561 
562     CreateCombo();
563 }
564 
OnButtonChange(wxCommandEvent & WXUNUSED (event))565 void ODComboboxWidgetsPage::OnButtonChange(wxCommandEvent& WXUNUSED(event))
566 {
567     int sel = m_combobox->GetSelection();
568     if ( sel != wxNOT_FOUND )
569     {
570 #ifndef __WXGTK__
571         m_combobox->SetString(sel, m_textChange->GetValue());
572 #else
573         wxLogMessage(wxT("Not implemented in wxGTK"));
574 #endif
575     }
576 }
577 
OnButtonDelete(wxCommandEvent & WXUNUSED (event))578 void ODComboboxWidgetsPage::OnButtonDelete(wxCommandEvent& WXUNUSED(event))
579 {
580     unsigned long n;
581     if ( !m_textDelete->GetValue().ToULong(&n) ||
582             (n >= m_combobox->GetCount()) )
583     {
584         return;
585     }
586 
587     m_combobox->Delete(n);
588 }
589 
OnButtonDeleteSel(wxCommandEvent & WXUNUSED (event))590 void ODComboboxWidgetsPage::OnButtonDeleteSel(wxCommandEvent& WXUNUSED(event))
591 {
592     int sel = m_combobox->GetSelection();
593     if ( sel != wxNOT_FOUND )
594     {
595         m_combobox->Delete(sel);
596     }
597 }
598 
OnButtonClear(wxCommandEvent & WXUNUSED (event))599 void ODComboboxWidgetsPage::OnButtonClear(wxCommandEvent& WXUNUSED(event))
600 {
601     m_combobox->Clear();
602 }
603 
OnButtonInsert(wxCommandEvent & WXUNUSED (event))604 void ODComboboxWidgetsPage::OnButtonInsert(wxCommandEvent& WXUNUSED(event))
605 {
606     static unsigned int s_item = 0;
607 
608     wxString s = m_textInsert->GetValue();
609     if ( !m_textInsert->IsModified() )
610     {
611         // update the default string
612         m_textInsert->SetValue(wxString::Format(wxT("test item %u"), ++s_item));
613     }
614 
615     if (m_combobox->GetSelection() >= 0)
616         m_combobox->Insert(s, m_combobox->GetSelection());
617 }
618 
OnButtonAdd(wxCommandEvent & WXUNUSED (event))619 void ODComboboxWidgetsPage::OnButtonAdd(wxCommandEvent& WXUNUSED(event))
620 {
621     static unsigned int s_item = 0;
622 
623     wxString s = m_textAdd->GetValue();
624     if ( !m_textAdd->IsModified() )
625     {
626         // update the default string
627         m_textAdd->SetValue(wxString::Format(wxT("test item %u"), ++s_item));
628     }
629 
630     m_combobox->Append(s);
631 }
632 
OnButtonAddMany(wxCommandEvent & WXUNUSED (event))633 void ODComboboxWidgetsPage::OnButtonAddMany(wxCommandEvent& WXUNUSED(event))
634 {
635     // "many" means 1000 here
636     for ( unsigned int n = 0; n < 1000; n++ )
637     {
638         m_combobox->Append(wxString::Format(wxT("item #%u"), n));
639     }
640 }
641 
OnButtonAddSeveral(wxCommandEvent & WXUNUSED (event))642 void ODComboboxWidgetsPage::OnButtonAddSeveral(wxCommandEvent& WXUNUSED(event))
643 {
644     m_combobox->Append(wxT("First"));
645     m_combobox->Append(wxT("another one"));
646     m_combobox->Append(wxT("and the last (very very very very very very very very very very long) one"));
647 }
648 
OnTextPopupWidth(wxCommandEvent & WXUNUSED (event))649 void ODComboboxWidgetsPage::OnTextPopupWidth(wxCommandEvent& WXUNUSED(event))
650 {
651     long l = 0;
652 
653     if (!m_textPopupMinWidth)
654     {
655         return;
656     }
657 
658     m_textPopupMinWidth->GetValue().ToLong(&l);
659 
660     if (m_combobox && l > 0)
661     {
662         m_combobox->SetPopupMinWidth(l);
663     }
664 }
665 
OnTextPopupHeight(wxCommandEvent & WXUNUSED (event))666 void ODComboboxWidgetsPage::OnTextPopupHeight(wxCommandEvent& WXUNUSED(event))
667 {
668     long l = 0;
669 
670     if (!m_textPopupHeight)
671     {
672         return;
673     }
674 
675     m_textPopupHeight->GetValue().ToLong(&l);
676 
677     if (m_combobox && l > 0)
678     {
679         m_combobox->SetPopupMaxHeight(l);
680     }
681 }
682 
GetButtonPosition()683 void ODComboboxWidgetsPage::GetButtonPosition()
684 {
685     long w = -1;
686     long h = -1;
687     long spacing = 0;
688 
689     m_textButtonWidth->GetValue().ToLong(&w);
690     m_textButtonSpacing->GetValue().ToLong(&spacing);
691     m_textButtonHeight->GetValue().ToLong(&h);
692     int align = m_chkAlignbutleft->GetValue() ?
693                 wxLEFT : wxRIGHT;
694 
695     m_combobox->SetButtonPosition(w,h,align,spacing);
696 }
697 
OnTextButtonAll(wxCommandEvent & WXUNUSED (event))698 void ODComboboxWidgetsPage::OnTextButtonAll(wxCommandEvent& WXUNUSED(event))
699 {
700     if (m_combobox)
701     {
702         if ( m_chkBitmapbutton->GetValue() )
703             CreateCombo();
704         else
705             GetButtonPosition();
706     }
707 }
708 
OnUpdateUICurText(wxUpdateUIEvent & event)709 void ODComboboxWidgetsPage::OnUpdateUICurText(wxUpdateUIEvent& event)
710 {
711     if (m_combobox)
712         event.SetText( wxString::Format(wxT("%d"), m_combobox->GetSelection()) );
713 }
714 
OnUpdateUIInsertionPointText(wxUpdateUIEvent & event)715 void ODComboboxWidgetsPage::OnUpdateUIInsertionPointText(wxUpdateUIEvent& event)
716 {
717     if (m_combobox)
718         event.SetText( wxString::Format(wxT("%ld"), m_combobox->GetInsertionPoint()) );
719 }
720 
OnUpdateUIResetButton(wxUpdateUIEvent & event)721 void ODComboboxWidgetsPage::OnUpdateUIResetButton(wxUpdateUIEvent& event)
722 {
723     if (m_combobox)
724         event.Enable( m_chkSort->GetValue() || m_chkReadonly->GetValue() ||
725                       m_chkBitmapbutton->GetValue() );
726 }
727 
OnUpdateUIInsert(wxUpdateUIEvent & event)728 void ODComboboxWidgetsPage::OnUpdateUIInsert(wxUpdateUIEvent& event)
729 {
730     if (m_combobox)
731     {
732         bool enable = !(m_combobox->GetWindowStyle() & wxCB_SORT) &&
733                        (m_combobox->GetSelection() >= 0);
734 
735         event.Enable(enable);
736     }
737 }
738 
OnUpdateUIDeleteButton(wxUpdateUIEvent & event)739 void ODComboboxWidgetsPage::OnUpdateUIDeleteButton(wxUpdateUIEvent& event)
740 {
741     if (m_combobox)
742     {
743       unsigned long n;
744       event.Enable(m_textDelete->GetValue().ToULong(&n) &&
745         (n < (unsigned)m_combobox->GetCount()));
746     }
747 }
748 
OnUpdateUIDeleteSelButton(wxUpdateUIEvent & event)749 void ODComboboxWidgetsPage::OnUpdateUIDeleteSelButton(wxUpdateUIEvent& event)
750 {
751     if (m_combobox)
752         event.Enable(m_combobox->GetSelection() != wxNOT_FOUND);
753 }
754 
OnUpdateUIClearButton(wxUpdateUIEvent & event)755 void ODComboboxWidgetsPage::OnUpdateUIClearButton(wxUpdateUIEvent& event)
756 {
757     if (m_combobox)
758         event.Enable(m_combobox->GetCount() != 0);
759 }
760 
OnUpdateUIAddSeveral(wxUpdateUIEvent & event)761 void ODComboboxWidgetsPage::OnUpdateUIAddSeveral(wxUpdateUIEvent& event)
762 {
763     if (m_combobox)
764         event.Enable(!(m_combobox->GetWindowStyle() & wxCB_SORT));
765 }
766 
OnComboText(wxCommandEvent & event)767 void ODComboboxWidgetsPage::OnComboText(wxCommandEvent& event)
768 {
769     if (!m_combobox)
770         return;
771 
772     wxString s = event.GetString();
773 
774     wxASSERT_MSG( s == m_combobox->GetValue(),
775                   wxT("event and combobox values should be the same") );
776 
777     if (event.GetEventType() == wxEVT_TEXT_ENTER)
778     {
779         wxLogMessage(wxT("OwnerDrawnCombobox enter pressed (now '%s')"), s.c_str());
780     }
781     else
782     {
783         wxLogMessage(wxT("OwnerDrawnCombobox text changed (now '%s')"), s.c_str());
784     }
785 }
786 
OnComboBox(wxCommandEvent & event)787 void ODComboboxWidgetsPage::OnComboBox(wxCommandEvent& event)
788 {
789     long sel = event.GetInt();
790     m_textDelete->SetValue(wxString::Format(wxT("%ld"), sel));
791 
792     wxLogMessage(wxT("OwnerDrawnCombobox item %ld selected"), sel);
793 
794     wxLogMessage(wxT("OwnerDrawnCombobox GetValue(): %s"), m_combobox->GetValue().c_str() );
795 }
796 
OnCheckOrRadioBox(wxCommandEvent & event)797 void ODComboboxWidgetsPage::OnCheckOrRadioBox(wxCommandEvent& event)
798 {
799     wxObject* ctrl = event.GetEventObject();
800 
801     // Double-click cycles only applies to read-only combobox
802     if ( ctrl == (wxObject*) m_chkReadonly )
803     {
804         m_chkDclickcycles->Enable( m_chkReadonly->GetValue() );
805     }
806     else if ( ctrl == (wxObject*) m_chkBitmapbutton )
807     {
808         m_chkStdbutton->Enable( m_chkBitmapbutton->GetValue() );
809     }
810     else if ( ctrl == (wxObject*) m_chkAlignbutleft )
811     {
812         wxUpdateUIEvent tempEvt;
813         OnTextButtonAll(tempEvt);
814     }
815 
816     CreateCombo();
817 }
818 
CreateBitmap(const wxColour & colour)819 wxBitmap ODComboboxWidgetsPage::CreateBitmap(const wxColour& colour)
820 {
821     int ch = m_combobox->GetClientSize().y - 1;
822     int h0 = ch - 5;
823 
824     long w = -1;
825     long h = -1;
826 
827     m_textButtonWidth->GetValue().ToLong(&w);
828     m_textButtonHeight->GetValue().ToLong(&h);
829 
830     if ( w <= 0 )
831         w = h0 - 1;
832     if ( h <= 0 )
833         h = h0;
834     if ( h > ch )
835         h = ch;
836 
837     wxMemoryDC dc;
838     wxBitmap bmp(w,h);
839     dc.SelectObject(bmp);
840 
841     // Draw transparent background
842     wxColour magic(255,0,255);
843     wxBrush magicBrush(magic);
844     dc.SetBrush(magicBrush);
845     dc.SetPen(*wxTRANSPARENT_PEN);
846     dc.DrawRectangle(0,0,bmp.GetWidth(),bmp.GetHeight());
847 
848     // Draw image content
849     dc.SetBrush(wxBrush(colour));
850     dc.DrawCircle(h/2,h/2+1,(h/2));
851 
852     dc.SelectObject(wxNullBitmap);
853 
854     // Finalize transparency with a mask
855     wxMask *mask = new wxMask(bmp, magic);
856     bmp.SetMask(mask);
857 
858     return bmp;
859 }
860 
OnDropDown(wxCommandEvent & WXUNUSED (event))861 void ODComboboxWidgetsPage::OnDropDown(wxCommandEvent& WXUNUSED(event))
862 {
863     wxLogMessage(wxT("Combobox dropped down"));
864 }
865 
OnCloseUp(wxCommandEvent & WXUNUSED (event))866 void ODComboboxWidgetsPage::OnCloseUp(wxCommandEvent& WXUNUSED(event))
867 {
868     wxLogMessage(wxT("Combobox closed up"));
869 }
870 
871 #endif //wxUSE_ODCOMBOBOX
872