[ 1524693 ] wxOwnerDrawnComboBox focus paint fix.
[wxWidgets.git] / samples / combo / combo.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: combo.cpp
3 // Purpose: wxComboCtrl sample
4 // Author: Jaakko Salli
5 // Modified by:
6 // Created: Apr-30-2006
7 // RCS-ID: $Id$
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows licence
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 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers)
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32
33 #if !wxUSE_COMBOCTRL
34 #error "Please set wxUSE_COMBOCTRL to 1 and rebuild the library."
35 #endif
36
37 #include "wx/image.h"
38
39 #include "wx/combo.h"
40 #include "wx/odcombo.h"
41
42 // ----------------------------------------------------------------------------
43 // resources
44 // ----------------------------------------------------------------------------
45
46 // the application icon (under Windows and OS/2 it is in resources and even
47 // though we could still include the XPM here it would be unused)
48 #if !defined(__WXMSW__) && !defined(__WXPM__)
49 #include "../sample.xpm"
50 #endif
51
52 // ----------------------------------------------------------------------------
53 // private classes
54 // ----------------------------------------------------------------------------
55
56 // Define a new application type, each program should derive a class from wxApp
57 class MyApp : public wxApp
58 {
59 public:
60 // override base class virtuals
61 // ----------------------------
62
63 // this one is called on application startup and is a good place for the app
64 // initialization (doing it here and not in the ctor allows to have an error
65 // return: if OnInit() returns false, the application terminates)
66 virtual bool OnInit();
67 };
68
69 // Define a new frame type: this is going to be our main frame
70 class MyFrame : public wxFrame
71 {
72 public:
73 // ctor and dtor
74 MyFrame(const wxString& title);
75 ~MyFrame();
76
77 // event handlers (these functions should _not_ be virtual)
78 void OnQuit(wxCommandEvent& event);
79 void OnAbout(wxCommandEvent& event);
80
81 void OnShowComparison( wxCommandEvent& event );
82
83 // log wxComboCtrl events
84 void OnComboBoxUpdate( wxCommandEvent& event );
85
86 protected:
87 wxTextCtrl* m_logWin;
88 wxLog* m_logOld;
89
90 // Common list of items for all dialogs.
91 wxArrayString m_arrItems;
92
93 private:
94 // any class wishing to process wxWidgets events must use this macro
95 DECLARE_EVENT_TABLE()
96 };
97
98 // ----------------------------------------------------------------------------
99 // constants
100 // ----------------------------------------------------------------------------
101
102 // IDs for the controls and the menu commands
103 enum
104 {
105 ComboControl_Compare = wxID_HIGHEST,
106
107 // menu items
108 ComboControl_Quit = wxID_EXIT,
109
110 // it is important for the id corresponding to the "About" command to have
111 // this standard value as otherwise it won't be handled properly under Mac
112 // (where it is special and put into the "Apple" menu)
113 ComboControl_About = wxID_ABOUT
114 };
115
116 // ----------------------------------------------------------------------------
117 // event tables and other macros for wxWidgets
118 // ----------------------------------------------------------------------------
119
120 // the event tables connect the wxWidgets events with the functions (event
121 // handlers) which process them. It can be also done at run-time, but for the
122 // simple menu events like this the static method is much simpler.
123 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
124 EVT_TEXT(wxID_ANY,MyFrame::OnComboBoxUpdate)
125 EVT_COMBOBOX(wxID_ANY,MyFrame::OnComboBoxUpdate)
126
127 EVT_MENU(ComboControl_Compare, MyFrame::OnShowComparison)
128 EVT_MENU(ComboControl_Quit, MyFrame::OnQuit)
129 EVT_MENU(ComboControl_About, MyFrame::OnAbout)
130 END_EVENT_TABLE()
131
132 // Create a new application object: this macro will allow wxWidgets to create
133 // the application object during program execution (it's better than using a
134 // static object for many reasons) and also implements the accessor function
135 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
136 // not wxApp)
137 IMPLEMENT_APP(MyApp)
138
139 // ============================================================================
140 // implementation
141 // ============================================================================
142
143 // ----------------------------------------------------------------------------
144 // the application class
145 // ----------------------------------------------------------------------------
146
147 // 'Main program' equivalent: the program execution "starts" here
148 bool MyApp::OnInit()
149 {
150 // create the main application window
151 MyFrame *frame = new MyFrame(_T("wxComboCtrl and wxOwnerDrawnComboBox Sample"));
152
153 // and show it (the frames, unlike simple controls, are not shown when
154 // created initially)
155 frame->Show(true);
156
157 // success: wxApp::OnRun() will be called which will enter the main message
158 // loop and the application will run. If we returned false here, the
159 // application would exit immediately.
160 return true;
161 }
162
163
164 // ----------------------------------------------------------------------------
165 // wxOwnerDrawnComboBox with custom paint list items
166 // ----------------------------------------------------------------------------
167
168 class wxPenStyleComboBox : public wxOwnerDrawnComboBox
169 {
170 public:
171 virtual void OnDrawItem( wxDC& dc,
172 const wxRect& rect,
173 int item,
174 int flags ) const
175 {
176 if ( item == wxNOT_FOUND )
177 return;
178
179 wxRect r(rect);
180 r.Deflate(3);
181 r.height -= 2;
182
183 int penStyle = wxSOLID;
184 if ( item == 1 )
185 penStyle = wxTRANSPARENT;
186 else if ( item == 2 )
187 penStyle = wxDOT;
188 else if ( item == 3 )
189 penStyle = wxLONG_DASH;
190 else if ( item == 4 )
191 penStyle = wxSHORT_DASH;
192 else if ( item == 5 )
193 penStyle = wxDOT_DASH;
194 else if ( item == 6 )
195 penStyle = wxBDIAGONAL_HATCH;
196 else if ( item == 7 )
197 penStyle = wxCROSSDIAG_HATCH;
198 else if ( item == 8 )
199 penStyle = wxFDIAGONAL_HATCH;
200 else if ( item == 9 )
201 penStyle = wxCROSS_HATCH;
202 else if ( item == 10 )
203 penStyle = wxHORIZONTAL_HATCH;
204 else if ( item == 11 )
205 penStyle = wxVERTICAL_HATCH;
206
207 wxPen pen( dc.GetTextForeground(), 3, penStyle );
208
209 // Get text colour as pen colour
210 dc.SetPen( pen );
211
212 if ( !(flags & wxODCB_PAINTING_CONTROL) )
213 {
214 dc.DrawText(GetString( item ),
215 r.x + 3,
216 (r.y + 0) + ( (r.height/2) - dc.GetCharHeight() )/2
217 );
218
219 dc.DrawLine( r.x+5, r.y+((r.height/4)*3), r.x+r.width - 5, r.y+((r.height/4)*3) );
220 }
221 else
222 {
223 dc.DrawLine( r.x+5, r.y+r.height/2, r.x+r.width - 5, r.y+r.height/2 );
224 }
225 }
226
227 virtual void OnDrawBackground( wxDC& dc, const wxRect& rect,
228 int item, int flags ) const
229 {
230
231 // If item is selected or even, or we are painting the
232 // combo control itself, use the default rendering.
233 if ( GetVListBoxComboPopup()->IsCurrent((size_t)item) ||
234 (flags & wxODCB_PAINTING_CONTROL) ||
235 (item & 1) == 0 )
236 {
237 wxOwnerDrawnComboBox::OnDrawBackground(dc,rect,item,flags);
238 return;
239 }
240
241 // Otherwise, draw every other background with different colour.
242 wxColour bgCol(240,240,250);
243 dc.SetBrush(wxBrush(bgCol));
244 dc.SetPen(wxPen(bgCol));
245 dc.DrawRectangle(rect);
246 }
247
248 virtual wxCoord OnMeasureItem( size_t item ) const
249 {
250 // Simply demonstrate the ability to have variable-height items
251 if ( item & 1 )
252 return 36;
253 else
254 return 24;
255 }
256
257 virtual wxCoord OnMeasureItemWidth( size_t WXUNUSED(item) ) const
258 {
259 return -1; // default - will be measured from text width
260 }
261
262 };
263
264
265 // ----------------------------------------------------------------------------
266 // wxListView Custom popup interface
267 // ----------------------------------------------------------------------------
268
269 #include <wx/listctrl.h>
270
271 class ListViewComboPopup : public wxListView, public wxComboPopup
272 {
273 public:
274
275 virtual void Init()
276 {
277 m_value = -1;
278 m_itemHere = -1; // hot item in list
279 }
280
281 virtual bool Create( wxWindow* parent )
282 {
283 return wxListView::Create(parent,1,
284 wxPoint(0,0),wxDefaultSize,
285 wxLC_LIST|wxLC_SINGLE_SEL|
286 wxLC_SORT_ASCENDING|wxSIMPLE_BORDER);
287 }
288
289 virtual wxWindow *GetControl() { return this; }
290
291 virtual void SetStringValue( const wxString& s )
292 {
293 int n = wxListView::FindItem(-1,s);
294 if ( n >= 0 && n < GetItemCount() )
295 wxListView::Select(n);
296 }
297
298 virtual wxString GetStringValue() const
299 {
300 if ( m_value >= 0 )
301 return wxListView::GetItemText(m_value);
302 return wxEmptyString;
303 }
304
305 //
306 // Popup event handlers
307 //
308
309 // Mouse hot-tracking
310 void OnMouseMove(wxMouseEvent& event)
311 {
312 // Move selection to cursor if it is inside the popup
313
314 int resFlags;
315 int itemHere = HitTest(event.GetPosition(),resFlags);
316 if ( itemHere >= 0 )
317 {
318 wxListView::Select(itemHere,true);
319 m_itemHere = itemHere;
320 }
321 event.Skip();
322 }
323
324 // On mouse left, set the value and close the popup
325 void OnMouseClick(wxMouseEvent& WXUNUSED(event))
326 {
327 m_value = m_itemHere;
328 // TODO: Send event
329 Dismiss();
330 }
331
332 //
333 // Utilies for item manipulation
334 //
335
336 void AddSelection( const wxString& selstr )
337 {
338 wxListView::InsertItem(GetItemCount(),selstr);
339 }
340
341 protected:
342
343 int m_value; // current item index
344 int m_itemHere; // hot item in popup
345
346 private:
347 DECLARE_EVENT_TABLE()
348 };
349
350 BEGIN_EVENT_TABLE(ListViewComboPopup, wxListView)
351 EVT_MOTION(ListViewComboPopup::OnMouseMove)
352 // NOTE: Left down event is used instead of left up right now
353 // since MSW wxListCtrl doesn't seem to emit left ups
354 // consistently.
355 EVT_LEFT_DOWN(ListViewComboPopup::OnMouseClick)
356 END_EVENT_TABLE()
357
358
359 // ----------------------------------------------------------------------------
360 // wxTreeCtrl Custom popup interface
361 // ----------------------------------------------------------------------------
362
363 #include <wx/treectrl.h>
364
365 class TreeCtrlComboPopup : public wxTreeCtrl, public wxComboPopup
366 {
367 public:
368
369 virtual void Init()
370 {
371 }
372
373 virtual bool Create( wxWindow* parent )
374 {
375 return wxTreeCtrl::Create(parent,1,
376 wxPoint(0,0),wxDefaultSize,
377 wxTR_HIDE_ROOT|wxTR_HAS_BUTTONS|
378 wxTR_SINGLE|wxTR_LINES_AT_ROOT|
379 wxSIMPLE_BORDER);
380 }
381
382 virtual void OnShow()
383 {
384 // make sure selected item is visible
385 if ( m_value.IsOk() )
386 EnsureVisible(m_value);
387 }
388
389 virtual wxSize GetAdjustedSize( int minWidth,
390 int WXUNUSED(prefHeight),
391 int maxHeight )
392 {
393 return wxSize(wxMax(300,minWidth),wxMin(250,maxHeight));
394 }
395
396 virtual wxWindow *GetControl() { return this; }
397
398 // Needed by SetStringValue
399 wxTreeItemId FindItemByText( wxTreeItemId parent, const wxString& text )
400 {
401 wxTreeItemIdValue cookie;
402 wxTreeItemId child = GetFirstChild(parent,cookie);
403 while ( child.IsOk() )
404 {
405 if ( GetItemText(child) == text )
406 {
407 return child;
408 }
409 if ( ItemHasChildren(child) )
410 {
411 wxTreeItemId found = FindItemByText(child,text);
412 if ( found.IsOk() )
413 return found;
414 }
415 child = GetNextChild(parent,cookie);
416 }
417 return wxTreeItemId();
418 }
419
420 virtual void SetStringValue( const wxString& s )
421 {
422 wxTreeItemId root = GetRootItem();
423 if ( !root.IsOk() )
424 return;
425
426 wxTreeItemId found = FindItemByText(root,s);
427 if ( found.IsOk() )
428 {
429 m_value = m_itemHere = found;
430 wxTreeCtrl::SelectItem(found);
431 }
432 }
433
434 virtual wxString GetStringValue() const
435 {
436 if ( m_value.IsOk() )
437 return wxTreeCtrl::GetItemText(m_value);
438 return wxEmptyString;
439 }
440
441 //
442 // Popup event handlers
443 //
444
445 // Mouse hot-tracking
446 void OnMouseMove(wxMouseEvent& event)
447 {
448 int resFlags;
449 wxTreeItemId itemHere = HitTest(event.GetPosition(),resFlags);
450 if ( itemHere.IsOk() && (resFlags & wxTREE_HITTEST_ONITEMLABEL) )
451 {
452 wxTreeCtrl::SelectItem(itemHere,true);
453 m_itemHere = itemHere;
454 }
455 event.Skip();
456 }
457
458 // On mouse left, set the value and close the popup
459 void OnMouseClick(wxMouseEvent& event)
460 {
461 int resFlags;
462 wxTreeItemId itemHere = HitTest(event.GetPosition(),resFlags);
463 if ( itemHere.IsOk() && (resFlags & wxTREE_HITTEST_ONITEMLABEL) )
464 {
465 m_itemHere = itemHere;
466 m_value = itemHere;
467 Dismiss();
468 // TODO: Send event
469 }
470 event.Skip();
471 }
472
473 protected:
474
475 wxTreeItemId m_value; // current item index
476 wxTreeItemId m_itemHere; // hot item in popup
477
478 private:
479 DECLARE_EVENT_TABLE()
480 };
481
482 BEGIN_EVENT_TABLE(TreeCtrlComboPopup, wxTreeCtrl)
483 EVT_MOTION(TreeCtrlComboPopup::OnMouseMove)
484 // NOTE: Left down event is used instead of left up right now
485 // since MSW wxTreeCtrl doesn't seem to emit left ups
486 // consistently.
487 EVT_LEFT_DOWN(TreeCtrlComboPopup::OnMouseClick)
488 END_EVENT_TABLE()
489
490 // ----------------------------------------------------------------------------
491 // wxComboCtrl with entirely custom button action (opens file dialog)
492 // ----------------------------------------------------------------------------
493
494 class wxFileSelectorCombo : public wxComboCtrl
495 {
496 public:
497 wxFileSelectorCombo() : wxComboCtrl() { Init(); }
498
499 wxFileSelectorCombo(wxWindow *parent,
500 wxWindowID id = wxID_ANY,
501 const wxString& value = wxEmptyString,
502 const wxPoint& pos = wxDefaultPosition,
503 const wxSize& size = wxDefaultSize,
504 long style = 0,
505 const wxValidator& validator = wxDefaultValidator,
506 const wxString& name = wxComboBoxNameStr)
507 : wxComboCtrl()
508 {
509 Init();
510 Create(parent,id,value,
511 pos,size,
512 // Style flag wxCC_STD_BUTTON makes the button
513 // behave more like a standard push button.
514 style | wxCC_STD_BUTTON,
515 validator,name);
516
517 //
518 // Prepare custom button bitmap (just '...' text)
519 wxMemoryDC dc;
520 wxBitmap bmp(12,16);
521 dc.SelectObject(bmp);
522
523 // Draw transparent background
524 wxColour magic(255,0,255);
525 wxBrush magicBrush(magic);
526 dc.SetBrush( magicBrush );
527 dc.SetPen( *wxTRANSPARENT_PEN );
528 dc.DrawRectangle(0,0,bmp.GetWidth(),bmp.GetHeight());
529
530 // Draw text
531 wxString str = wxT("...");
532 int w,h;
533 dc.GetTextExtent(str, &w, &h, 0, 0);
534 dc.DrawText(str, (bmp.GetWidth()-w)/2, (bmp.GetHeight()-h)/2);
535
536 dc.SelectObject( wxNullBitmap );
537
538 // Finalize transparency with a mask
539 wxMask *mask = new wxMask( bmp, magic );
540 bmp.SetMask( mask );
541
542 SetButtonBitmaps(bmp,true);
543 }
544
545 virtual void OnButtonClick()
546 {
547 // Show standard wxFileDialog on button click
548
549 wxFileDialog dlg(this,
550 wxT("Choose File"),
551 wxEmptyString,
552 GetValue(),
553 wxT("All files (*.*)|*.*"),
554 wxFD_OPEN);
555
556 if ( dlg.ShowModal() == wxID_OK )
557 {
558 SetValue(dlg.GetPath());
559 }
560 }
561
562 // Implement empty DoSetPopupControl to prevent assertion failure.
563 virtual void DoSetPopupControl(wxComboPopup* WXUNUSED(popup))
564 {
565 }
566
567 private:
568 void Init()
569 {
570 // Initialize member variables here
571 }
572 };
573
574 // ----------------------------------------------------------------------------
575 // main frame
576 // ----------------------------------------------------------------------------
577
578 // frame constructor
579 MyFrame::MyFrame(const wxString& title)
580 : wxFrame(NULL, wxID_ANY, title)
581 {
582 wxBoxSizer* topSizer;
583 wxBoxSizer* topRowSizer;
584 wxBoxSizer* colSizer;
585 wxBoxSizer* rowSizer;
586
587 // set the frame icon
588 SetIcon(wxICON(sample));
589
590 #if wxUSE_MENUS
591 // create a menu bar
592 wxMenu *fileMenu = new wxMenu;
593
594 // the "About" item should be in the help menu
595 wxMenu *helpMenu = new wxMenu;
596 helpMenu->Append(ComboControl_About, _T("&About...\tF1"), _T("Show about dialog"));
597
598 fileMenu->Append(ComboControl_Compare, _T("&Compare against wxComboBox..."),
599 _T("Show some wxOwnerDrawnComboBoxes side-by-side with native wxComboBoxes."));
600 fileMenu->AppendSeparator();
601 fileMenu->Append(ComboControl_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
602
603 // now append the freshly created menu to the menu bar...
604 wxMenuBar *menuBar = new wxMenuBar();
605 menuBar->Append(fileMenu, _T("&File"));
606 menuBar->Append(helpMenu, _T("&Help"));
607
608 // ... and attach this menu bar to the frame
609 SetMenuBar(menuBar);
610 #endif // wxUSE_MENUS
611
612 wxPanel* panel = new wxPanel(this);
613
614 // Prepare log window right away since it shows EVT_TEXTs
615 m_logWin = new wxTextCtrl( panel, 105, wxEmptyString, wxDefaultPosition,
616 wxSize(-1,125), wxTE_MULTILINE|wxFULL_REPAINT_ON_RESIZE );
617 m_logWin->SetEditable(false);
618 wxLogTextCtrl* logger = new wxLogTextCtrl( m_logWin );
619 m_logOld = logger->SetActiveTarget( logger );
620 logger->SetTimestamp( NULL );
621
622
623 topSizer = new wxBoxSizer( wxVERTICAL );
624
625 topRowSizer = new wxBoxSizer( wxHORIZONTAL );
626
627 colSizer = new wxBoxSizer( wxVERTICAL );
628
629
630 wxComboCtrl* cc;
631 wxGenericComboControl* gcc;
632 wxOwnerDrawnComboBox* odc;
633
634 // Create common strings array
635 m_arrItems.Add( wxT("Solid") );
636 m_arrItems.Add( wxT("Transparent") );
637 m_arrItems.Add( wxT("Dot") );
638 m_arrItems.Add( wxT("Long Dash") );
639 m_arrItems.Add( wxT("Short Dash") );
640 m_arrItems.Add( wxT("Dot Dash") );
641 m_arrItems.Add( wxT("Backward Diagonal Hatch") );
642 m_arrItems.Add( wxT("Cross-diagonal Hatch") );
643 m_arrItems.Add( wxT("Forward Diagonal Hatch") );
644 m_arrItems.Add( wxT("Cross Hatch") );
645 m_arrItems.Add( wxT("Horizontal Hatch") );
646 m_arrItems.Add( wxT("Vertical Hatch") );
647
648
649 //
650 // Create pen selector ODComboBox with owner-drawn items
651 //
652 rowSizer = new wxBoxSizer( wxHORIZONTAL );
653 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
654 wxT("OwnerDrawnComboBox with owner-drawn items:")), 1,
655 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
656 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
657
658 rowSizer = new wxBoxSizer( wxHORIZONTAL );
659
660
661 // When defining derivative class for callbacks, we need
662 // to use two-stage creation (or redefine the common wx
663 // constructor).
664 odc = new wxPenStyleComboBox();
665 odc->Create(panel,wxID_ANY,wxEmptyString,
666 wxDefaultPosition, wxDefaultSize,
667 m_arrItems,
668 wxCB_READONLY //wxNO_BORDER | wxCB_READONLY
669 );
670
671
672 odc->SetSelection(0);
673
674 rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
675 rowSizer->AddStretchSpacer(1);
676 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
677
678
679
680 //
681 // Same but with changed button position
682 //
683 rowSizer = new wxBoxSizer( wxHORIZONTAL );
684 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
685 wxT("OwnerDrawnComboBox with owner-drawn items and button on the left:")), 1,
686 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
687 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
688
689 rowSizer = new wxBoxSizer( wxHORIZONTAL );
690
691
692 // When defining derivative class for callbacks, we need
693 // to use two-stage creation (or redefine the common wx
694 // constructor).
695 odc = new wxPenStyleComboBox();
696 odc->Create(panel,wxID_ANY,wxEmptyString,
697 wxDefaultPosition, wxDefaultSize,
698 m_arrItems,
699 wxCB_READONLY //wxNO_BORDER | wxCB_READONLY
700 );
701
702
703 odc->SetSelection(0);
704
705 // Use button size that is slightly smaller than the default.
706 wxSize butSize = odc->GetButtonSize();
707 odc->SetButtonPosition(butSize.x - 2, // button width
708 butSize.y - 6, // button height
709 wxLEFT, // side
710 2 // horizontal spacing
711 );
712
713 rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
714 rowSizer->AddStretchSpacer(1);
715 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
716
717
718 //
719 // List View wxComboCtrl
720 //
721
722 rowSizer = new wxBoxSizer( wxHORIZONTAL );
723 rowSizer->Add( new wxStaticText(panel,wxID_ANY,wxT("List View wxComboCtrl:")), 1,
724 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
725 rowSizer->Add( new wxStaticText(panel,wxID_ANY,wxT("Tree Ctrl wxComboControl:")), 1,
726 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
727 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
728
729 rowSizer = new wxBoxSizer( wxHORIZONTAL );
730 cc = new wxComboCtrl(panel,2,wxEmptyString,
731 wxDefaultPosition, wxDefaultSize);
732
733 cc->SetPopupMinWidth(300);
734
735 ListViewComboPopup* iface = new ListViewComboPopup();
736 cc->SetPopupControl(iface);
737
738 int i;
739 for ( i=0; i<100; i++ )
740 iface->AddSelection( wxString::Format(wxT("Item %02i"),i));
741
742 rowSizer->Add( cc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
743
744
745 //
746 // Tree Ctrl wxComboCtrl
747 //
748
749 // Note that we test that wxGenericComboControl works
750 gcc = new wxGenericComboControl(panel,wxID_ANY,wxEmptyString,
751 wxDefaultPosition, wxDefaultSize);
752
753 // Set popup interface right away, otherwise some of the calls
754 // below may fail
755 TreeCtrlComboPopup* tcPopup = new TreeCtrlComboPopup();
756 gcc->SetPopupControl(tcPopup);
757
758 // Add items using wxTreeCtrl methods directly
759 wxTreeItemId rootId = tcPopup->AddRoot(wxT("<hidden_root>"));
760
761 wxTreeItemId groupId;
762
763 for ( i=0; i<4; i++ )
764 {
765 groupId = tcPopup->AppendItem(rootId,
766 wxString::Format(wxT("Branch %02i"),i));
767
768 int n;
769 for ( n=0; n<25; n++ )
770 tcPopup->AppendItem(groupId,
771 wxString::Format(wxT("Subitem %02i"),(i*25)+n));
772 }
773
774 gcc->SetValue(wxT("Subitem 05"));
775
776 // Move button to left - it makes more sense for a tree ctrl
777 gcc->SetButtonPosition(-1, // button width
778 -1, // button height
779 wxLEFT, // side
780 0 // horizontal spacing
781 );
782
783 rowSizer->Add( gcc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
784
785 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
786
787 #if wxUSE_IMAGE
788 wxInitAllImageHandlers();
789
790 //
791 // Custom Dropbutton Bitmaps
792 // (second one uses blank button background)
793 //
794 rowSizer = new wxBoxSizer( wxHORIZONTAL );
795 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
796 wxT("OwnerDrawnComboBox with simple dropbutton graphics:")), 1,
797 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
798
799 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
800
801 rowSizer = new wxBoxSizer( wxHORIZONTAL );
802
803 odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
804 wxDefaultPosition, wxDefaultSize,
805 m_arrItems,
806 (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
807 );
808
809 wxOwnerDrawnComboBox* odc2;
810 odc2 = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
811 wxDefaultPosition, wxDefaultSize,
812 m_arrItems,
813 (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
814 );
815
816 // Load images from disk
817 wxImage imgNormal(wxT("dropbutn.png"));
818 wxImage imgPressed(wxT("dropbutp.png"));
819 wxImage imgHover(wxT("dropbuth.png"));
820
821 if ( imgNormal.Ok() && imgPressed.Ok() && imgHover.Ok() )
822 {
823 wxBitmap bmpNormal(imgNormal);
824 wxBitmap bmpPressed(imgPressed);
825 wxBitmap bmpHover(imgHover);
826 odc->SetButtonBitmaps(bmpNormal,false,bmpPressed,bmpHover);
827 odc2->SetButtonBitmaps(bmpNormal,true,bmpPressed,bmpHover);
828 }
829 else
830 wxLogError(wxT("Dropbutton images not found"));
831
832 //odc2->SetButtonPosition(0, // width adjustment
833 // 0, // height adjustment
834 // wxLEFT, // side
835 // 0 // horizontal spacing
836 // );
837
838 rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
839 rowSizer->Add( odc2, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
840 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
841 #endif
842
843
844 //
845 // wxComboCtrl with totally custom button action (open file dialog)
846 //
847 rowSizer = new wxBoxSizer( wxHORIZONTAL );
848 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
849 wxT("wxComboCtrl with custom button action:")), 1,
850 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
851
852
853 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
854
855 rowSizer = new wxBoxSizer( wxHORIZONTAL );
856 wxFileSelectorCombo* fsc;
857
858 fsc = new wxFileSelectorCombo(panel,wxID_ANY,wxEmptyString,
859 wxDefaultPosition, wxDefaultSize,
860 (long)0
861 );
862
863 rowSizer->Add( fsc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
864 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
865
866
867 // Make sure GetFeatures is implemented
868 wxComboCtrl::GetFeatures();
869
870
871 topRowSizer->Add( colSizer, 1, wxALL, 2 );
872
873 topRowSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 5 );
874 topSizer->Add( topRowSizer, 1, wxEXPAND );
875
876 panel->SetSizer( topSizer );
877 topSizer->SetSizeHints( panel );
878
879 SetSize(740,400);
880 Centre();
881 }
882
883 // event handlers
884
885 void MyFrame::OnComboBoxUpdate( wxCommandEvent& event )
886 {
887 // Don't show messages for the log output window (it'll crash)
888 if ( !event.GetEventObject()->IsKindOf(CLASSINFO(wxComboCtrl)) )
889 return;
890
891 if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
892 wxLogDebug(wxT("EVT_COMBOBOX(id=%i,selection=%i)"),event.GetId(),event.GetSelection());
893 else if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED )
894 wxLogDebug(wxT("EVT_TEXT(id=%i,string=\"%s\")"),event.GetId(),event.GetString().c_str());
895 }
896
897 void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
898 {
899 //
900 // Show some wxOwnerDrawComboBoxes for comparison
901 //
902
903 wxBoxSizer* colSizer;
904 wxBoxSizer* rowSizer;
905 wxStaticBoxSizer* groupSizer;
906
907 wxComboBox* cb;
908 wxOwnerDrawnComboBox* odc;
909
910 const int border = 4;
911
912 wxDialog* dlg = new wxDialog(this,wxID_ANY,
913 wxT("Compare against wxComboBox"),
914 wxDefaultPosition,wxDefaultSize,
915 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
916
917 colSizer = new wxBoxSizer( wxVERTICAL );
918
919 rowSizer = new wxBoxSizer(wxHORIZONTAL);
920
921 groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxOwnerDrawnComboBox ")),
922 wxVERTICAL);
923
924 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
925 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
926
927 odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
928 wxDefaultPosition, wxDefaultSize,
929 m_arrItems,
930 wxCB_SORT // wxNO_BORDER|wxCB_READONLY
931 );
932
933 odc->Append(wxT("H - Appended Item")); // test sorting in append
934
935 odc->SetValue(wxT("Dot Dash"));
936
937 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
938
939 //
940 // Readonly ODComboBox
941 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
942 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
943
944 odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
945 wxDefaultPosition, wxDefaultSize,
946 m_arrItems,
947 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
948 );
949
950 odc->SetValue(wxT("Dot Dash"));
951 odc->SetText(wxT("Dot Dash (Testing SetText)"));
952
953 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
954
955 //
956 // Disabled ODComboBox
957 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Disabled:")), 0,
958 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
959
960 odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
961 wxDefaultPosition, wxDefaultSize,
962 m_arrItems,
963 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
964 );
965
966 odc->SetValue(wxT("Dot Dash"));
967 odc->Enable(false);
968
969 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
970
971 rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
972
973
974 groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxComboBox ")),
975 wxVERTICAL);
976
977 //
978 // wxComboBox
979 //
980 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
981 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
982
983 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
984 wxDefaultPosition, wxDefaultSize,
985 m_arrItems,
986 wxCB_SORT // wxNO_BORDER|wxCB_READONLY
987 );
988
989 cb->Append(wxT("H - Appended Item")); // test sorting in append
990
991 cb->SetValue(wxT("Dot Dash"));
992
993 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
994
995 //
996 // Readonly wxComboBox
997 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
998 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
999
1000 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
1001 wxDefaultPosition, wxDefaultSize,
1002 m_arrItems,
1003 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
1004 );
1005
1006 cb->SetValue(wxT("Dot Dash"));
1007
1008 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1009
1010 //
1011 // Disabled wxComboBox
1012 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Disabled:")), 0,
1013 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
1014
1015 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
1016 wxDefaultPosition, wxDefaultSize,
1017 m_arrItems,
1018 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
1019 );
1020
1021 cb->SetValue(wxT("Dot Dash"));
1022 cb->Enable(false);
1023
1024 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1025
1026 rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
1027
1028 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, border );
1029
1030 dlg->SetSizer( colSizer );
1031 colSizer->SetSizeHints( dlg );
1032
1033 dlg->SetSize(60,240);
1034 dlg->Centre();
1035 dlg->ShowModal();
1036 }
1037
1038 MyFrame::~MyFrame()
1039 {
1040 delete wxLog::SetActiveTarget(m_logOld);
1041 }
1042
1043 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1044 {
1045 // true is to force the frame to close
1046 Close(true);
1047 }
1048
1049 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1050 {
1051 wxMessageBox(wxString::Format(
1052 _T("Welcome to %s!\n")
1053 _T("\n")
1054 _T("This is the wxWidgets wxComboCtrl and wxOwnerDrawnComboBox sample\n")
1055 _T("running under %s."),
1056 wxVERSION_STRING,
1057 wxGetOsDescription().c_str()
1058 ),
1059 _T("About wxComboCtrl sample"),
1060 wxOK | wxICON_INFORMATION,
1061 this);
1062 }