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