1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxComboCtrl sample
4 // Author: Jaakko Salli
6 // Created: Apr-30-2006
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers)
34 #error "Please set wxUSE_COMBOCTRL to 1 and rebuild the library."
40 #include "wx/odcombo.h"
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
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"
52 // ----------------------------------------------------------------------------
54 // ----------------------------------------------------------------------------
56 // Define a new application type, each program should derive a class from wxApp
57 class MyApp
: public wxApp
60 // override base class virtuals
61 // ----------------------------
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();
69 // Define a new frame type: this is going to be our main frame
70 class MyFrame
: public wxFrame
74 MyFrame(const wxString
& title
);
77 // event handlers (these functions should _not_ be virtual)
78 void OnQuit(wxCommandEvent
& event
);
79 void OnAbout(wxCommandEvent
& event
);
81 void OnShowComparison( wxCommandEvent
& event
);
83 // log wxComboCtrl events
84 void OnComboBoxUpdate( wxCommandEvent
& event
);
86 void OnIdle( wxIdleEvent
& event
);
89 wxCheckBox
* m_cbUseAnim
;
95 // Common list of items for all dialogs.
96 wxArrayString m_arrItems
;
99 // any class wishing to process wxWidgets events must use this macro
100 DECLARE_EVENT_TABLE()
103 // ----------------------------------------------------------------------------
105 // ----------------------------------------------------------------------------
107 // IDs for the controls and the menu commands
110 ComboControl_Compare
= wxID_HIGHEST
,
113 ComboControl_Quit
= wxID_EXIT
,
115 // it is important for the id corresponding to the "About" command to have
116 // this standard value as otherwise it won't be handled properly under Mac
117 // (where it is special and put into the "Apple" menu)
118 ComboControl_About
= wxID_ABOUT
121 // ----------------------------------------------------------------------------
122 // event tables and other macros for wxWidgets
123 // ----------------------------------------------------------------------------
125 // the event tables connect the wxWidgets events with the functions (event
126 // handlers) which process them. It can be also done at run-time, but for the
127 // simple menu events like this the static method is much simpler.
128 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
129 EVT_TEXT(wxID_ANY
,MyFrame::OnComboBoxUpdate
)
130 EVT_COMBOBOX(wxID_ANY
,MyFrame::OnComboBoxUpdate
)
132 EVT_MENU(ComboControl_Compare
, MyFrame::OnShowComparison
)
133 EVT_MENU(ComboControl_Quit
, MyFrame::OnQuit
)
134 EVT_MENU(ComboControl_About
, MyFrame::OnAbout
)
136 EVT_IDLE(MyFrame::OnIdle
)
139 // Create a new application object: this macro will allow wxWidgets to create
140 // the application object during program execution (it's better than using a
141 // static object for many reasons) and also implements the accessor function
142 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
146 // ============================================================================
148 // ============================================================================
150 // ----------------------------------------------------------------------------
151 // the application class
152 // ----------------------------------------------------------------------------
154 // 'Main program' equivalent: the program execution "starts" here
157 if ( !wxApp::OnInit() )
160 // create the main application window
161 MyFrame
*frame
= new MyFrame(_T("wxComboCtrl and wxOwnerDrawnComboBox Sample"));
163 // and show it (the frames, unlike simple controls, are not shown when
164 // created initially)
167 // success: wxApp::OnRun() will be called which will enter the main message
168 // loop and the application will run. If we returned false here, the
169 // application would exit immediately.
174 // ----------------------------------------------------------------------------
175 // wxOwnerDrawnComboBox with custom paint list items
176 // ----------------------------------------------------------------------------
178 class wxPenStyleComboBox
: public wxOwnerDrawnComboBox
181 virtual void OnDrawItem( wxDC
& dc
,
186 if ( item
== wxNOT_FOUND
)
193 int penStyle
= wxSOLID
;
195 penStyle
= wxTRANSPARENT
;
196 else if ( item
== 2 )
198 else if ( item
== 3 )
199 penStyle
= wxLONG_DASH
;
200 else if ( item
== 4 )
201 penStyle
= wxSHORT_DASH
;
202 else if ( item
== 5 )
203 penStyle
= wxDOT_DASH
;
204 else if ( item
== 6 )
205 penStyle
= wxBDIAGONAL_HATCH
;
206 else if ( item
== 7 )
207 penStyle
= wxCROSSDIAG_HATCH
;
208 else if ( item
== 8 )
209 penStyle
= wxFDIAGONAL_HATCH
;
210 else if ( item
== 9 )
211 penStyle
= wxCROSS_HATCH
;
212 else if ( item
== 10 )
213 penStyle
= wxHORIZONTAL_HATCH
;
214 else if ( item
== 11 )
215 penStyle
= wxVERTICAL_HATCH
;
217 wxPen
pen( dc
.GetTextForeground(), 3, penStyle
);
219 // Get text colour as pen colour
222 if ( !(flags
& wxODCB_PAINTING_CONTROL
) )
224 dc
.DrawText(GetString( item
),
226 (r
.y
+ 0) + ( (r
.height
/2) - dc
.GetCharHeight() )/2
229 dc
.DrawLine( r
.x
+5, r
.y
+((r
.height
/4)*3), r
.x
+r
.width
- 5, r
.y
+((r
.height
/4)*3) );
233 dc
.DrawLine( r
.x
+5, r
.y
+r
.height
/2, r
.x
+r
.width
- 5, r
.y
+r
.height
/2 );
237 virtual void OnDrawBackground( wxDC
& dc
, const wxRect
& rect
,
238 int item
, int flags
) const
241 // If item is selected or even, or we are painting the
242 // combo control itself, use the default rendering.
243 if ( (flags
& (wxODCB_PAINTING_CONTROL
|wxODCB_PAINTING_SELECTED
)) ||
246 wxOwnerDrawnComboBox::OnDrawBackground(dc
,rect
,item
,flags
);
250 // Otherwise, draw every other background with different colour.
251 wxColour
bgCol(240,240,250);
252 dc
.SetBrush(wxBrush(bgCol
));
253 dc
.SetPen(wxPen(bgCol
));
254 dc
.DrawRectangle(rect
);
257 virtual wxCoord
OnMeasureItem( size_t item
) const
259 // Simply demonstrate the ability to have variable-height items
266 virtual wxCoord
OnMeasureItemWidth( size_t WXUNUSED(item
) ) const
268 return -1; // default - will be measured from text width
274 // ----------------------------------------------------------------------------
275 // wxListView Custom popup interface
276 // ----------------------------------------------------------------------------
278 #include <wx/listctrl.h>
280 class ListViewComboPopup
: public wxListView
, public wxComboPopup
287 m_itemHere
= -1; // hot item in list
290 virtual bool Create( wxWindow
* parent
)
292 return wxListView::Create(parent
,1,
293 wxPoint(0,0),wxDefaultSize
,
294 wxLC_LIST
|wxLC_SINGLE_SEL
|
295 wxLC_SORT_ASCENDING
|wxSIMPLE_BORDER
);
298 virtual wxWindow
*GetControl() { return this; }
300 virtual void SetStringValue( const wxString
& s
)
302 int n
= wxListView::FindItem(-1,s
);
303 if ( n
>= 0 && n
< GetItemCount() )
304 wxListView::Select(n
);
307 virtual wxString
GetStringValue() const
310 return wxListView::GetItemText(m_value
);
311 return wxEmptyString
;
315 // Popup event handlers
318 // Mouse hot-tracking
319 void OnMouseMove(wxMouseEvent
& event
)
321 // Move selection to cursor if it is inside the popup
324 int itemHere
= HitTest(event
.GetPosition(),resFlags
);
327 wxListView::Select(itemHere
,true);
328 m_itemHere
= itemHere
;
333 // On mouse left, set the value and close the popup
334 void OnMouseClick(wxMouseEvent
& WXUNUSED(event
))
336 m_value
= m_itemHere
;
342 // Utilies for item manipulation
345 void AddSelection( const wxString
& selstr
)
347 wxListView::InsertItem(GetItemCount(),selstr
);
352 int m_value
; // current item index
353 int m_itemHere
; // hot item in popup
356 DECLARE_EVENT_TABLE()
359 BEGIN_EVENT_TABLE(ListViewComboPopup
, wxListView
)
360 EVT_MOTION(ListViewComboPopup::OnMouseMove
)
361 // NOTE: Left down event is used instead of left up right now
362 // since MSW wxListCtrl doesn't seem to emit left ups
364 EVT_LEFT_DOWN(ListViewComboPopup::OnMouseClick
)
368 // ----------------------------------------------------------------------------
369 // wxTreeCtrl Custom popup interface
370 // ----------------------------------------------------------------------------
372 #include <wx/treectrl.h>
374 class TreeCtrlComboPopup
: public wxTreeCtrl
, public wxComboPopup
382 virtual bool Create( wxWindow
* parent
)
384 return wxTreeCtrl::Create(parent
,1,
385 wxPoint(0,0),wxDefaultSize
,
386 wxTR_HIDE_ROOT
|wxTR_HAS_BUTTONS
|
387 wxTR_SINGLE
|wxTR_LINES_AT_ROOT
|
391 virtual void OnShow()
393 // make sure selected item is visible
394 if ( m_value
.IsOk() )
395 EnsureVisible(m_value
);
398 virtual wxSize
GetAdjustedSize( int minWidth
,
399 int WXUNUSED(prefHeight
),
402 return wxSize(wxMax(300,minWidth
),wxMin(250,maxHeight
));
405 virtual wxWindow
*GetControl() { return this; }
407 // Needed by SetStringValue
408 wxTreeItemId
FindItemByText( wxTreeItemId parent
, const wxString
& text
)
410 wxTreeItemIdValue cookie
;
411 wxTreeItemId child
= GetFirstChild(parent
,cookie
);
412 while ( child
.IsOk() )
414 if ( GetItemText(child
) == text
)
418 if ( ItemHasChildren(child
) )
420 wxTreeItemId found
= FindItemByText(child
,text
);
424 child
= GetNextChild(parent
,cookie
);
426 return wxTreeItemId();
429 virtual void SetStringValue( const wxString
& s
)
431 wxTreeItemId root
= GetRootItem();
435 wxTreeItemId found
= FindItemByText(root
,s
);
438 m_value
= m_itemHere
= found
;
439 wxTreeCtrl::SelectItem(found
);
443 virtual wxString
GetStringValue() const
445 if ( m_value
.IsOk() )
446 return wxTreeCtrl::GetItemText(m_value
);
447 return wxEmptyString
;
451 // Popup event handlers
454 // Mouse hot-tracking
455 void OnMouseMove(wxMouseEvent
& event
)
458 wxTreeItemId itemHere
= HitTest(event
.GetPosition(),resFlags
);
459 if ( itemHere
.IsOk() && (resFlags
& wxTREE_HITTEST_ONITEMLABEL
) )
461 wxTreeCtrl::SelectItem(itemHere
,true);
462 m_itemHere
= itemHere
;
467 // On mouse left, set the value and close the popup
468 void OnMouseClick(wxMouseEvent
& event
)
471 wxTreeItemId itemHere
= HitTest(event
.GetPosition(),resFlags
);
472 if ( itemHere
.IsOk() && (resFlags
& wxTREE_HITTEST_ONITEMLABEL
) )
474 m_itemHere
= itemHere
;
484 wxTreeItemId m_value
; // current item index
485 wxTreeItemId m_itemHere
; // hot item in popup
488 DECLARE_EVENT_TABLE()
491 BEGIN_EVENT_TABLE(TreeCtrlComboPopup
, wxTreeCtrl
)
492 EVT_MOTION(TreeCtrlComboPopup::OnMouseMove
)
493 // NOTE: Left down event is used instead of left up right now
494 // since MSW wxTreeCtrl doesn't seem to emit left ups
496 EVT_LEFT_DOWN(TreeCtrlComboPopup::OnMouseClick
)
499 // ----------------------------------------------------------------------------
500 // wxComboCtrl with custom popup animation. We use EVT_TIMER, which is quite
501 // safe, but requires much more can than doing it in a single function (ie.
502 // AnimateShow) and using combination of wxSleep and wxSafeYield.
503 // ----------------------------------------------------------------------------
507 #define CUSTOM_COMBOBOX_ANIMATION_DURATION 200 // In milliseconds
509 #include "wx/timer.h"
511 class wxComboCtrlWithCustomPopupAnim
: public wxComboCtrl
515 virtual bool AnimateShow( const wxRect
& rect
, int flags
)
517 MyFrame
* myFrame
= (MyFrame
*) ::wxGetTopLevelParent(this);
519 if ( !myFrame
->m_cbUseAnim
->GetValue() )
522 m_animStart
= ::wxGetLocalTimeMillis();
528 wxBitmap
bitmap( rect
.width
, rect
.height
, -1 );
529 wxMemoryDC
memdc( bitmap
);
530 memdc
.Blit( 0, 0, rect
.width
, rect
.height
, &dc
, rect
.x
, rect
.y
);
531 memdc
.SelectObject(wxNullBitmap
);
532 m_animBackBitmap
= bitmap
;
534 m_animTimer
.SetOwner( this, wxID_ANY
);
535 m_animTimer
.Start( 10, wxTIMER_CONTINUOUS
);
537 OnTimerEvent(*((wxTimerEvent
*)NULL
)); // Event is never used, so we can give NULL
541 void OnTimerEvent( wxTimerEvent
& WXUNUSED(event
) )
543 bool stopTimer
= false;
545 wxWindow
* popup
= GetPopupControl()->GetControl();
547 const wxRect
& rect
= m_animRect
;
549 // Popup was hidden before it was fully shown?
550 if ( IsPopupWindowState(Hidden
) )
556 wxLongLong t
= ::wxGetLocalTimeMillis();
558 int pos
= (int) (t
-m_animStart
).GetLo();
559 if ( pos
< CUSTOM_COMBOBOX_ANIMATION_DURATION
)
562 // Actual animation happens here
564 int width
= rect
.width
;
565 int height
= rect
.height
;
567 int center_x
= rect
.x
+ (width
/2);
568 int center_y
= rect
.y
+ (height
/2);
570 double d_height
= (double) height
;
572 dc
.SetPen( *wxBLACK_PEN
);
573 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
575 int w
= (((pos
*256)/CUSTOM_COMBOBOX_ANIMATION_DURATION
)*width
)/256;
577 double ratio
= ((double)w
/ (double)width
);
578 int h
= (int)(d_height
* ratio
);
579 dc
.DrawBitmap( m_animBackBitmap
, rect
.x
, rect
.y
);
580 dc
.DrawRectangle( center_x
- w
/2, center_y
- h
/2, w
, h
);
590 dc
.DrawBitmap( m_animBackBitmap
, rect
.x
, rect
.y
);
593 DoShowPopup( m_animRect
, m_animFlags
);
599 // Popup animation related
600 wxLongLong m_animStart
;
603 wxBitmap m_animBackBitmap
;
607 DECLARE_EVENT_TABLE()
610 BEGIN_EVENT_TABLE(wxComboCtrlWithCustomPopupAnim
, wxComboCtrl
)
611 EVT_TIMER(wxID_ANY
, wxComboCtrlWithCustomPopupAnim::OnTimerEvent
)
616 #define wxComboCtrlWithCustomPopupAnim wxComboCtrl
620 // ----------------------------------------------------------------------------
621 // wxComboCtrl with entirely custom button action (opens file dialog)
622 // ----------------------------------------------------------------------------
624 class wxFileSelectorCombo
: public wxComboCtrl
627 wxFileSelectorCombo() : wxComboCtrl() { Init(); }
629 wxFileSelectorCombo(wxWindow
*parent
,
630 wxWindowID id
= wxID_ANY
,
631 const wxString
& value
= wxEmptyString
,
632 const wxPoint
& pos
= wxDefaultPosition
,
633 const wxSize
& size
= wxDefaultSize
,
635 const wxValidator
& validator
= wxDefaultValidator
,
636 const wxString
& name
= wxComboBoxNameStr
)
640 Create(parent
,id
,value
,
642 // Style flag wxCC_STD_BUTTON makes the button
643 // behave more like a standard push button.
644 style
| wxCC_STD_BUTTON
,
648 // Prepare custom button bitmap (just '...' text)
651 dc
.SelectObject(bmp
);
653 // Draw transparent background
654 wxColour
magic(255,0,255);
655 wxBrush
magicBrush(magic
);
656 dc
.SetBrush( magicBrush
);
657 dc
.SetPen( *wxTRANSPARENT_PEN
);
658 dc
.DrawRectangle(0,0,bmp
.GetWidth(),bmp
.GetHeight());
661 wxString str
= wxT("...");
663 dc
.GetTextExtent(str
, &w
, &h
, 0, 0);
664 dc
.DrawText(str
, (bmp
.GetWidth()-w
)/2, (bmp
.GetHeight()-h
)/2);
666 dc
.SelectObject( wxNullBitmap
);
668 // Finalize transparency with a mask
669 wxMask
*mask
= new wxMask( bmp
, magic
);
672 SetButtonBitmaps(bmp
,true);
675 virtual void OnButtonClick()
677 // Show standard wxFileDialog on button click
679 wxFileDialog
dlg(this,
683 wxT("All files (*.*)|*.*"),
686 if ( dlg
.ShowModal() == wxID_OK
)
688 SetValue(dlg
.GetPath());
692 // Implement empty DoSetPopupControl to prevent assertion failure.
693 virtual void DoSetPopupControl(wxComboPopup
* WXUNUSED(popup
))
700 // Initialize member variables here
704 // ----------------------------------------------------------------------------
706 // ----------------------------------------------------------------------------
709 MyFrame::MyFrame(const wxString
& title
)
710 : wxFrame(NULL
, wxID_ANY
, title
)
712 wxBoxSizer
* topSizer
;
713 wxBoxSizer
* topRowSizer
;
714 wxBoxSizer
* colSizer
;
715 wxBoxSizer
* rowSizer
;
717 // set the frame icon
718 SetIcon(wxICON(sample
));
722 wxMenu
*fileMenu
= new wxMenu
;
724 // the "About" item should be in the help menu
725 wxMenu
*helpMenu
= new wxMenu
;
726 helpMenu
->Append(ComboControl_About
, _T("&About...\tF1"), _T("Show about dialog"));
728 fileMenu
->Append(ComboControl_Compare
, _T("&Compare against wxComboBox..."),
729 _T("Show some wxOwnerDrawnComboBoxes side-by-side with native wxComboBoxes."));
730 fileMenu
->AppendSeparator();
731 fileMenu
->Append(ComboControl_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
733 // now append the freshly created menu to the menu bar...
734 wxMenuBar
*menuBar
= new wxMenuBar();
735 menuBar
->Append(fileMenu
, _T("&File"));
736 menuBar
->Append(helpMenu
, _T("&Help"));
738 // ... and attach this menu bar to the frame
740 #endif // wxUSE_MENUS
742 wxPanel
* panel
= new wxPanel(this);
744 // Prepare log window right away since it shows EVT_TEXTs
745 m_logWin
= new wxTextCtrl( panel
, 105, wxEmptyString
, wxDefaultPosition
,
746 wxSize(-1,125), wxTE_MULTILINE
|wxFULL_REPAINT_ON_RESIZE
);
747 m_logWin
->SetEditable(false);
748 wxLogTextCtrl
* logger
= new wxLogTextCtrl( m_logWin
);
749 m_logOld
= logger
->SetActiveTarget( logger
);
750 logger
->SetTimestamp( NULL
);
753 topSizer
= new wxBoxSizer( wxVERTICAL
);
755 topRowSizer
= new wxBoxSizer( wxHORIZONTAL
);
757 colSizer
= new wxBoxSizer( wxVERTICAL
);
761 wxGenericComboCtrl
* gcc
;
762 wxOwnerDrawnComboBox
* odc
;
764 // Create common strings array
765 m_arrItems
.Add( wxT("Solid") );
766 m_arrItems
.Add( wxT("Transparent") );
767 m_arrItems
.Add( wxT("Dot") );
768 m_arrItems
.Add( wxT("Long Dash") );
769 m_arrItems
.Add( wxT("Short Dash") );
770 m_arrItems
.Add( wxT("Dot Dash") );
771 m_arrItems
.Add( wxT("Backward Diagonal Hatch") );
772 m_arrItems
.Add( wxT("Cross-diagonal Hatch") );
773 m_arrItems
.Add( wxT("Forward Diagonal Hatch") );
774 m_arrItems
.Add( wxT("Cross Hatch") );
775 m_arrItems
.Add( wxT("Horizontal Hatch") );
776 m_arrItems
.Add( wxT("Vertical Hatch") );
780 // Create pen selector ODComboBox with owner-drawn items
782 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
783 rowSizer
->Add( new wxStaticText(panel
,wxID_ANY
,
784 wxT("OwnerDrawnComboBox with owner-drawn items:")), 1,
785 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, 4 );
786 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
788 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
791 // When defining derivative class for callbacks, we need
792 // to use two-stage creation (or redefine the common wx
794 odc
= new wxPenStyleComboBox();
795 odc
->Create(panel
,wxID_ANY
,wxEmptyString
,
796 wxDefaultPosition
, wxDefaultSize
,
798 wxCB_READONLY
//wxNO_BORDER | wxCB_READONLY
802 odc
->SetSelection(0);
804 rowSizer
->Add( odc
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 4 );
805 rowSizer
->AddStretchSpacer(1);
806 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
811 // Same but with changed button position
813 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
814 rowSizer
->Add( new wxStaticText(panel
,wxID_ANY
,
815 wxT("OwnerDrawnComboBox with owner-drawn items and button on the left:")), 1,
816 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, 4 );
817 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
819 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
822 // When defining derivative class for callbacks, we need
823 // to use two-stage creation (or redefine the common wx
825 odc
= new wxPenStyleComboBox();
826 odc
->Create(panel
,wxID_ANY
,wxEmptyString
,
827 wxDefaultPosition
, wxDefaultSize
,
829 wxCB_READONLY
//wxNO_BORDER | wxCB_READONLY
833 odc
->SetSelection(0);
835 // Use button size that is slightly smaller than the default.
836 wxSize butSize
= odc
->GetButtonSize();
837 odc
->SetButtonPosition(butSize
.x
- 2, // button width
838 butSize
.y
- 6, // button height
840 2 // horizontal spacing
843 rowSizer
->Add( odc
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 4 );
844 rowSizer
->AddStretchSpacer(1);
845 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
849 // List View wxComboCtrl
852 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
853 rowSizer
->Add( new wxStaticText(panel
,wxID_ANY
,wxT("List View wxComboCtrl:")), 1,
854 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, 4 );
855 rowSizer
->Add( new wxStaticText(panel
,wxID_ANY
,wxT("Tree Ctrl wxComboControl:")), 1,
856 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, 4 );
857 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
859 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
860 cc
= new wxComboCtrlWithCustomPopupAnim();
861 cc
->Create(panel
, wxID_ANY
, wxEmptyString
);
863 // Make sure we use popup that allows focusing the listview.
864 cc
->UseAltPopupWindow();
866 cc
->SetPopupMinWidth(300);
868 ListViewComboPopup
* iface
= new ListViewComboPopup();
869 cc
->SetPopupControl(iface
);
872 for ( i
=0; i
<100; i
++ )
873 iface
->AddSelection( wxString::Format(wxT("Item %02i"),i
));
875 rowSizer
->Add( cc
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
879 // Tree Ctrl wxComboCtrl
882 // Note that we test that wxGenericComboCtrl works
883 gcc
= new wxGenericComboCtrl(panel
,wxID_ANY
,wxEmptyString
,
884 wxDefaultPosition
, wxDefaultSize
);
886 // Make sure we use popup that allows focusing the treectrl.
887 gcc
->UseAltPopupWindow();
889 // Set popup interface right away, otherwise some of the calls
891 TreeCtrlComboPopup
* tcPopup
= new TreeCtrlComboPopup();
892 gcc
->SetPopupControl(tcPopup
);
894 // Add items using wxTreeCtrl methods directly
895 wxTreeItemId rootId
= tcPopup
->AddRoot(wxT("<hidden_root>"));
897 wxTreeItemId groupId
;
899 for ( i
=0; i
<4; i
++ )
901 groupId
= tcPopup
->AppendItem(rootId
,
902 wxString::Format(wxT("Branch %02i"),i
));
905 for ( n
=0; n
<25; n
++ )
906 tcPopup
->AppendItem(groupId
,
907 wxString::Format(wxT("Subitem %02i"),(i
*25)+n
));
910 gcc
->SetValue(wxT("Subitem 05"));
912 // Move button to left - it makes more sense for a tree ctrl
913 gcc
->SetButtonPosition(-1, // button width
916 0 // horizontal spacing
919 rowSizer
->Add( gcc
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 5 );
921 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
924 wxInitAllImageHandlers();
927 // Custom Dropbutton Bitmaps
928 // (second one uses blank button background)
930 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
931 rowSizer
->Add( new wxStaticText(panel
,wxID_ANY
,
932 wxT("OwnerDrawnComboBox with simple dropbutton graphics:")), 1,
933 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, 4 );
935 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
937 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
939 odc
= new wxOwnerDrawnComboBox(panel
,wxID_ANY
,wxEmptyString
,
940 wxDefaultPosition
, wxDefaultSize
,
942 (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
945 wxOwnerDrawnComboBox
* odc2
;
946 odc2
= new wxOwnerDrawnComboBox(panel
,wxID_ANY
,wxEmptyString
,
947 wxDefaultPosition
, wxDefaultSize
,
949 (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
952 // Load images from disk
953 wxImage
imgNormal(wxT("dropbutn.png"));
954 wxImage
imgPressed(wxT("dropbutp.png"));
955 wxImage
imgHover(wxT("dropbuth.png"));
957 if ( imgNormal
.IsOk() && imgPressed
.IsOk() && imgHover
.IsOk() )
959 wxBitmap
bmpNormal(imgNormal
);
960 wxBitmap
bmpPressed(imgPressed
);
961 wxBitmap
bmpHover(imgHover
);
962 odc
->SetButtonBitmaps(bmpNormal
,false,bmpPressed
,bmpHover
);
963 odc2
->SetButtonBitmaps(bmpNormal
,true,bmpPressed
,bmpHover
);
966 wxLogError(wxT("Dropbutton images not found"));
968 //odc2->SetButtonPosition(0, // width adjustment
969 // 0, // height adjustment
971 // 0 // horizontal spacing
974 rowSizer
->Add( odc
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 4 );
975 rowSizer
->Add( odc2
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 4 );
976 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
981 // wxComboCtrl with totally custom button action (open file dialog)
983 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
984 rowSizer
->Add( new wxStaticText(panel
,wxID_ANY
,
985 wxT("wxComboCtrl with custom button action:")), 1,
986 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, 4 );
989 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
991 rowSizer
= new wxBoxSizer( wxHORIZONTAL
);
992 wxFileSelectorCombo
* fsc
;
994 fsc
= new wxFileSelectorCombo(panel
,wxID_ANY
,wxEmptyString
,
995 wxDefaultPosition
, wxDefaultSize
,
999 rowSizer
->Add( fsc
, 1, wxALIGN_CENTER_VERTICAL
|wxALL
, 4 );
1000 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, 5 );
1003 // Make sure GetFeatures is implemented
1004 wxComboCtrl::GetFeatures();
1007 topRowSizer
->Add( colSizer
, 1, wxALL
, 2 );
1009 colSizer
= new wxBoxSizer( wxVERTICAL
);
1011 wxStaticBoxSizer
* sbSizer
= new wxStaticBoxSizer( new wxStaticBox(panel
,
1016 m_cbUseAnim
= new wxCheckBox(panel
, wxID_ANY
, wxT("Custom popup animation for ListView wxComboCtrl"));
1017 m_cbUseAnim
->SetValue(true);
1018 sbSizer
->Add( m_cbUseAnim
, 0, wxALL
, 3 );
1020 colSizer
->Add( sbSizer
, 0, wxEXPAND
|wxALL
, 3 );
1021 colSizer
->AddSpacer(8);
1022 colSizer
->Add( new wxStaticText(panel
, wxID_ANY
, wxT("Log Messages:")), 0, wxTOP
|wxLEFT
, 3 );
1023 colSizer
->Add( m_logWin
, 1, wxEXPAND
|wxALL
, 3 );
1025 topRowSizer
->Add( colSizer
, 1, wxEXPAND
|wxALL
, 2 );
1026 topSizer
->Add( topRowSizer
, 1, wxEXPAND
);
1028 panel
->SetSizer( topSizer
);
1029 topSizer
->SetSizeHints( panel
);
1037 void MyFrame::OnComboBoxUpdate( wxCommandEvent
& event
)
1039 // Don't show messages for the log output window (it'll crash)
1040 if ( !event
.GetEventObject()->IsKindOf(CLASSINFO(wxComboCtrl
)) )
1043 if ( event
.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED
)
1044 wxLogDebug(wxT("EVT_COMBOBOX(id=%i,selection=%i)"),event
.GetId(),event
.GetSelection());
1045 else if ( event
.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED
)
1046 wxLogDebug(wxT("EVT_TEXT(id=%i,string=\"%s\")"),event
.GetId(),event
.GetString().c_str());
1049 void MyFrame::OnShowComparison( wxCommandEvent
& WXUNUSED(event
) )
1052 // Show some wxOwnerDrawComboBoxes for comparison
1055 wxBoxSizer
* colSizer
;
1056 wxBoxSizer
* rowSizer
;
1057 wxStaticBoxSizer
* groupSizer
;
1060 wxOwnerDrawnComboBox
* odc
;
1062 const int border
= 4;
1064 wxDialog
* dlg
= new wxDialog(this,wxID_ANY
,
1065 wxT("Compare against wxComboBox"),
1066 wxDefaultPosition
,wxDefaultSize
,
1067 wxDEFAULT_DIALOG_STYLE
|wxRESIZE_BORDER
);
1069 colSizer
= new wxBoxSizer( wxVERTICAL
);
1071 rowSizer
= new wxBoxSizer(wxHORIZONTAL
);
1073 groupSizer
= new wxStaticBoxSizer(new wxStaticBox(dlg
,wxID_ANY
,wxT(" wxOwnerDrawnComboBox ")),
1076 groupSizer
->Add( new wxStaticText(dlg
,wxID_ANY
,wxT("Writable, sorted:")), 0,
1077 wxALIGN_CENTER_VERTICAL
|wxRIGHT
|wxEXPAND
, border
);
1079 odc
= new wxOwnerDrawnComboBox(dlg
,wxID_ANY
,wxEmptyString
,
1080 wxDefaultPosition
, wxDefaultSize
,
1082 wxCB_SORT
// wxNO_BORDER|wxCB_READONLY
1085 odc
->Append(wxT("H - Appended Item")); // test sorting in append
1087 odc
->SetValue(wxT("Dot Dash"));
1089 groupSizer
->Add( odc
, 1, wxALIGN_CENTER_VERTICAL
|wxEXPAND
|wxALL
, border
);
1092 // Readonly ODComboBox
1093 groupSizer
->Add( new wxStaticText(dlg
,wxID_ANY
,wxT("Read-only:")), 0,
1094 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, border
);
1096 odc
= new wxOwnerDrawnComboBox(dlg
,wxID_ANY
,wxEmptyString
,
1097 wxDefaultPosition
, wxDefaultSize
,
1099 wxCB_SORT
|wxCB_READONLY
// wxNO_BORDER|wxCB_READONLY
1102 odc
->SetValue(wxT("Dot Dash"));
1103 odc
->SetText(wxT("Dot Dash (Testing SetText)"));
1105 groupSizer
->Add( odc
, 1, wxALIGN_CENTER_VERTICAL
|wxEXPAND
|wxALL
, border
);
1108 // Disabled ODComboBox
1109 groupSizer
->Add( new wxStaticText(dlg
,wxID_ANY
,wxT("Disabled:")), 0,
1110 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, border
);
1112 odc
= new wxOwnerDrawnComboBox(dlg
,wxID_ANY
,wxEmptyString
,
1113 wxDefaultPosition
, wxDefaultSize
,
1115 wxCB_SORT
|wxCB_READONLY
// wxNO_BORDER|wxCB_READONLY
1118 odc
->SetValue(wxT("Dot Dash"));
1121 groupSizer
->Add( odc
, 1, wxALIGN_CENTER_VERTICAL
|wxEXPAND
|wxALL
, border
);
1123 rowSizer
->Add( groupSizer
, 1, wxEXPAND
|wxALL
, border
);
1126 groupSizer
= new wxStaticBoxSizer(new wxStaticBox(dlg
,wxID_ANY
,wxT(" wxComboBox ")),
1132 groupSizer
->Add( new wxStaticText(dlg
,wxID_ANY
,wxT("Writable, sorted:")), 0,
1133 wxALIGN_CENTER_VERTICAL
|wxRIGHT
|wxEXPAND
, border
);
1135 cb
= new wxComboBox(dlg
,wxID_ANY
,wxEmptyString
,
1136 wxDefaultPosition
, wxDefaultSize
,
1138 wxCB_SORT
// wxNO_BORDER|wxCB_READONLY
1141 cb
->Append(wxT("H - Appended Item")); // test sorting in append
1143 cb
->SetValue(wxT("Dot Dash"));
1145 groupSizer
->Add( cb
, 1, wxALIGN_CENTER_VERTICAL
|wxEXPAND
|wxALL
, border
);
1148 // Readonly wxComboBox
1149 groupSizer
->Add( new wxStaticText(dlg
,wxID_ANY
,wxT("Read-only:")), 0,
1150 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, border
);
1152 cb
= new wxComboBox(dlg
,wxID_ANY
,wxEmptyString
,
1153 wxDefaultPosition
, wxDefaultSize
,
1155 wxCB_SORT
|wxCB_READONLY
// wxNO_BORDER|wxCB_READONLY
1158 cb
->SetValue(wxT("Dot Dash"));
1160 groupSizer
->Add( cb
, 1, wxALIGN_CENTER_VERTICAL
|wxEXPAND
|wxALL
, border
);
1163 // Disabled wxComboBox
1164 groupSizer
->Add( new wxStaticText(dlg
,wxID_ANY
,wxT("Disabled:")), 0,
1165 wxALIGN_CENTER_VERTICAL
|wxRIGHT
, border
);
1167 cb
= new wxComboBox(dlg
,wxID_ANY
,wxEmptyString
,
1168 wxDefaultPosition
, wxDefaultSize
,
1170 wxCB_SORT
|wxCB_READONLY
// wxNO_BORDER|wxCB_READONLY
1173 cb
->SetValue(wxT("Dot Dash"));
1176 groupSizer
->Add( cb
, 1, wxALIGN_CENTER_VERTICAL
|wxEXPAND
|wxALL
, border
);
1178 rowSizer
->Add( groupSizer
, 1, wxEXPAND
|wxALL
, border
);
1180 colSizer
->Add( rowSizer
, 0, wxEXPAND
|wxALL
, border
);
1182 dlg
->SetSizer( colSizer
);
1183 colSizer
->SetSizeHints( dlg
);
1185 dlg
->SetSize(60,240);
1192 delete wxLog::SetActiveTarget(m_logOld
);
1195 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1197 // true is to force the frame to close
1201 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1203 wxMessageBox(wxString::Format(
1204 _T("Welcome to %s!\n")
1206 _T("This is the wxWidgets wxComboCtrl and wxOwnerDrawnComboBox sample\n")
1207 _T("running under %s."),
1209 wxGetOsDescription().c_str()
1211 _T("About wxComboCtrl sample"),
1212 wxOK
| wxICON_INFORMATION
,
1216 void MyFrame::OnIdle(wxIdleEvent
& event
)
1218 // This code is useful for debugging focus problems
1219 // (which are plentiful when dealing with popup windows).
1221 static wxWindow
* lastFocus
= (wxWindow
*) NULL
;
1223 wxWindow
* curFocus
= ::wxWindow::FindFocus();
1225 if ( curFocus
!= lastFocus
)
1227 const wxChar
* className
= wxT("<none>");
1229 className
= curFocus
->GetClassInfo()->GetClassName();
1230 lastFocus
= curFocus
;
1231 wxLogDebug( wxT("FOCUSED: %s %X"),
1233 (unsigned int)curFocus
);