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