]> git.saurik.com Git - wxWidgets.git/blob - samples/combo/combo.cpp
b5f4705b4713b489c29b387362904e349ef62780
[wxWidgets.git] / samples / combo / combo.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: combo.cpp
3 // Purpose: wxComboCtrl sample
4 // Author: Jaakko Salli
5 // Modified by:
6 // Created: Apr-30-2006
7 // RCS-ID: $Id$
8 // Copyright: (c) Jaakko Salli
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers)
29 #ifndef WX_PRECOMP
30 #include "wx/wx.h"
31 #endif
32
33 #if !wxUSE_COMBOCTRL
34 #error "Please set wxUSE_COMBOCTRL to 1 and rebuild the library."
35 #endif
36
37 #include "wx/image.h"
38
39 #include "wx/combo.h"
40 #include "wx/odcombo.h"
41
42 // ----------------------------------------------------------------------------
43 // resources
44 // ----------------------------------------------------------------------------
45
46 // the application icon (under Windows and OS/2 it is in resources and even
47 // though we could still include the XPM here it would be unused)
48 #if !defined(__WXMSW__) && !defined(__WXPM__)
49 #include "../sample.xpm"
50 #endif
51
52 // ----------------------------------------------------------------------------
53 // private classes
54 // ----------------------------------------------------------------------------
55
56 // Define a new application type, each program should derive a class from wxApp
57 class MyApp : public wxApp
58 {
59 public:
60 // override base class virtuals
61 // ----------------------------
62
63 // this one is called on application startup and is a good place for the app
64 // initialization (doing it here and not in the ctor allows to have an error
65 // return: if OnInit() returns false, the application terminates)
66 virtual bool OnInit();
67 };
68
69 // Define a new frame type: this is going to be our main frame
70 class MyFrame : public wxFrame
71 {
72 public:
73 // ctor and dtor
74 MyFrame(const wxString& title);
75 ~MyFrame();
76
77 // event handlers (these functions should _not_ be virtual)
78 void OnQuit(wxCommandEvent& event);
79 void OnAbout(wxCommandEvent& event);
80
81 void OnShowComparison( wxCommandEvent& event );
82
83 // log wxComboCtrl events
84 void OnComboBoxUpdate( wxCommandEvent& event );
85
86 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_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 int penStyle = wxSOLID;
192 if ( item == 1 )
193 penStyle = wxTRANSPARENT;
194 else if ( item == 2 )
195 penStyle = wxDOT;
196 else if ( item == 3 )
197 penStyle = wxLONG_DASH;
198 else if ( item == 4 )
199 penStyle = wxSHORT_DASH;
200 else if ( item == 5 )
201 penStyle = wxDOT_DASH;
202 else if ( item == 6 )
203 penStyle = wxBDIAGONAL_HATCH;
204 else if ( item == 7 )
205 penStyle = wxCROSSDIAG_HATCH;
206 else if ( item == 8 )
207 penStyle = wxFDIAGONAL_HATCH;
208 else if ( item == 9 )
209 penStyle = wxCROSS_HATCH;
210 else if ( item == 10 )
211 penStyle = wxHORIZONTAL_HATCH;
212 else if ( item == 11 )
213 penStyle = wxVERTICAL_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
380 virtual bool Create( wxWindow* parent )
381 {
382 return wxTreeCtrl::Create(parent,1,
383 wxPoint(0,0),wxDefaultSize,
384 wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT | wxSIMPLE_BORDER );
385 }
386
387 virtual void OnShow()
388 {
389 // make sure selected item is visible
390 if ( m_value.IsOk() )
391 EnsureVisible(m_value);
392 }
393
394 virtual wxSize GetAdjustedSize( int minWidth,
395 int WXUNUSED(prefHeight),
396 int maxHeight )
397 {
398 return wxSize(wxMax(300,minWidth),wxMin(250,maxHeight));
399 }
400
401 virtual wxWindow *GetControl() { return this; }
402
403 // Needed by SetStringValue
404 wxTreeItemId FindItemByText( wxTreeItemId parent, const wxString& text )
405 {
406 wxTreeItemIdValue cookie;
407 wxTreeItemId child = GetFirstChild(parent,cookie);
408 while ( child.IsOk() )
409 {
410 if ( GetItemText(child) == text )
411 {
412 return child;
413 }
414 if ( ItemHasChildren(child) )
415 {
416 wxTreeItemId found = FindItemByText(child,text);
417 if ( found.IsOk() )
418 return found;
419 }
420 child = GetNextChild(parent,cookie);
421 }
422 return wxTreeItemId();
423 }
424
425 virtual void SetStringValue( const wxString& s )
426 {
427 wxTreeItemId root = GetRootItem();
428 if ( !root.IsOk() )
429 return;
430
431 wxTreeItemId found = FindItemByText(root,s);
432 if ( found.IsOk() )
433 {
434 m_value = m_itemHere = found;
435 wxTreeCtrl::SelectItem(found);
436 }
437 }
438
439 virtual wxString GetStringValue() const
440 {
441 if ( m_value.IsOk() )
442 return wxTreeCtrl::GetItemText(m_value);
443 return wxEmptyString;
444 }
445
446 //
447 // Popup event handlers
448 //
449
450 // Mouse hot-tracking
451 void OnMouseMove(wxMouseEvent& event)
452 {
453 int resFlags;
454 wxTreeItemId itemHere = HitTest(event.GetPosition(),resFlags);
455 if ( itemHere.IsOk() && (resFlags & wxTREE_HITTEST_ONITEMLABEL) )
456 {
457 wxTreeCtrl::SelectItem(itemHere,true);
458 m_itemHere = itemHere;
459 }
460 event.Skip();
461 }
462
463 // On mouse left, set the value and close the popup
464 void OnMouseClick(wxMouseEvent& event)
465 {
466 int resFlags;
467 wxTreeItemId itemHere = HitTest(event.GetPosition(),resFlags);
468 if ( itemHere.IsOk() && (resFlags & wxTREE_HITTEST_ONITEMLABEL) )
469 {
470 m_itemHere = itemHere;
471 m_value = itemHere;
472 Dismiss();
473 // TODO: Send event
474 }
475 event.Skip();
476 }
477
478 protected:
479
480 wxTreeItemId m_value; // current item index
481 wxTreeItemId m_itemHere; // hot item in popup
482
483 private:
484 DECLARE_EVENT_TABLE()
485 };
486
487 BEGIN_EVENT_TABLE(TreeCtrlComboPopup, wxTreeCtrl)
488 EVT_MOTION(TreeCtrlComboPopup::OnMouseMove)
489 // NOTE: Left down event is used instead of left up right now
490 // since MSW wxTreeCtrl doesn't seem to emit left ups
491 // consistently.
492 EVT_LEFT_DOWN(TreeCtrlComboPopup::OnMouseClick)
493 END_EVENT_TABLE()
494
495 // ----------------------------------------------------------------------------
496 // wxComboCtrl with custom popup animation, using wxWindow::ShowWithEffect().
497 // ----------------------------------------------------------------------------
498
499 class wxComboCtrlWithCustomPopupAnim : public wxComboCtrl
500 {
501 protected:
502 virtual bool AnimateShow( const wxRect& rect, int WXUNUSED(flags) )
503 {
504 wxWindow* win = GetPopupWindow();
505 win->SetSize(rect);
506 win->Raise(); // This is needed
507 win->ShowWithEffect(wxSHOW_EFFECT_SLIDE_TO_BOTTOM);
508 return true;
509 }
510 };
511
512 // ----------------------------------------------------------------------------
513 // wxComboCtrl with entirely custom button action (opens file dialog)
514 // ----------------------------------------------------------------------------
515
516 class wxFileSelectorCombo : public wxComboCtrl
517 {
518 public:
519 wxFileSelectorCombo() : wxComboCtrl() { Init(); }
520
521 wxFileSelectorCombo(wxWindow *parent,
522 wxWindowID id = wxID_ANY,
523 const wxString& value = wxEmptyString,
524 const wxPoint& pos = wxDefaultPosition,
525 const wxSize& size = wxDefaultSize,
526 long style = 0,
527 const wxValidator& validator = wxDefaultValidator,
528 const wxString& name = wxComboBoxNameStr)
529 : wxComboCtrl()
530 {
531 Init();
532 Create(parent,id,value,
533 pos,size,
534 // Style flag wxCC_STD_BUTTON makes the button
535 // behave more like a standard push button.
536 style | wxCC_STD_BUTTON,
537 validator,name);
538
539 //
540 // Prepare custom button bitmap (just '...' text)
541 wxMemoryDC dc;
542 wxBitmap bmp(12,16);
543 dc.SelectObject(bmp);
544
545 // Draw transparent background
546 wxColour magic(255,0,255);
547 wxBrush magicBrush(magic);
548 dc.SetBrush( magicBrush );
549 dc.SetPen( *wxTRANSPARENT_PEN );
550 dc.DrawRectangle(0,0,bmp.GetWidth(),bmp.GetHeight());
551
552 // Draw text
553 wxString str = wxT("...");
554 int w,h;
555 dc.GetTextExtent(str, &w, &h, 0, 0);
556 dc.DrawText(str, (bmp.GetWidth()-w)/2, (bmp.GetHeight()-h)/2);
557
558 dc.SelectObject( wxNullBitmap );
559
560 // Finalize transparency with a mask
561 wxMask *mask = new wxMask( bmp, magic );
562 bmp.SetMask( mask );
563
564 SetButtonBitmaps(bmp,true);
565 }
566
567 virtual void OnButtonClick()
568 {
569 // Show standard wxFileDialog on button click
570
571 wxFileDialog dlg(this,
572 wxT("Choose File"),
573 wxEmptyString,
574 GetValue(),
575 wxT("All files (*.*)|*.*"),
576 wxFD_OPEN);
577
578 if ( dlg.ShowModal() == wxID_OK )
579 {
580 SetValue(dlg.GetPath());
581 }
582 }
583
584 // Implement empty DoSetPopupControl to prevent assertion failure.
585 virtual void DoSetPopupControl(wxComboPopup* WXUNUSED(popup))
586 {
587 }
588
589 private:
590 void Init()
591 {
592 // Initialize member variables here
593 }
594 };
595
596 // ----------------------------------------------------------------------------
597 // main frame
598 // ----------------------------------------------------------------------------
599
600 // frame constructor
601 MyFrame::MyFrame(const wxString& title)
602 : wxFrame(NULL, wxID_ANY, title)
603 {
604 wxBoxSizer* topSizer;
605 wxBoxSizer* topRowSizer;
606 wxBoxSizer* colSizer;
607 wxBoxSizer* rowSizer;
608
609 // set the frame icon
610 SetIcon(wxICON(sample));
611
612 #if wxUSE_MENUS
613 // create a menu bar
614 wxMenu *fileMenu = new wxMenu;
615
616 // the "About" item should be in the help menu
617 wxMenu *helpMenu = new wxMenu;
618 helpMenu->Append(ComboCtrl_About, wxT("&About...\tF1"), wxT("Show about dialog"));
619
620 fileMenu->Append(ComboCtrl_Compare, wxT("&Compare against wxComboBox..."),
621 wxT("Show some wxOwnerDrawnComboBoxes side-by-side with native wxComboBoxes."));
622 fileMenu->AppendSeparator();
623 fileMenu->Append(ComboCtrl_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
624
625 // now append the freshly created menu to the menu bar...
626 wxMenuBar *menuBar = new wxMenuBar();
627 menuBar->Append(fileMenu, wxT("&File"));
628 menuBar->Append(helpMenu, wxT("&Help"));
629
630 // ... and attach this menu bar to the frame
631 SetMenuBar(menuBar);
632 #endif // wxUSE_MENUS
633
634 wxPanel* panel = new wxPanel(this);
635
636 // Prepare log window right away since it shows EVT_TEXTs
637 m_logWin = new wxTextCtrl(panel, 105, wxEmptyString,
638 wxDefaultPosition,
639 wxSize(-1, 125),
640 wxTE_MULTILINE);
641 wxLogTextCtrl* logger = new wxLogTextCtrl(m_logWin);
642 m_logOld = logger->SetActiveTarget(logger);
643 logger->DisableTimestamp();
644
645
646 topSizer = new wxBoxSizer( wxVERTICAL );
647
648 topRowSizer = new wxBoxSizer( wxHORIZONTAL );
649
650 colSizer = new wxBoxSizer( wxVERTICAL );
651
652
653 wxComboCtrl* cc;
654 wxGenericComboCtrl* gcc;
655 wxOwnerDrawnComboBox* odc;
656
657 // Create common strings array
658 m_arrItems.Add( wxT("Solid") );
659 m_arrItems.Add( wxT("Transparent") );
660 m_arrItems.Add( wxT("Dot") );
661 m_arrItems.Add( wxT("Long Dash") );
662 m_arrItems.Add( wxT("Short Dash") );
663 m_arrItems.Add( wxT("Dot Dash") );
664 m_arrItems.Add( wxT("Backward Diagonal Hatch") );
665 m_arrItems.Add( wxT("Cross-diagonal Hatch") );
666 m_arrItems.Add( wxT("Forward Diagonal Hatch") );
667 m_arrItems.Add( wxT("Cross Hatch") );
668 m_arrItems.Add( wxT("Horizontal Hatch") );
669 m_arrItems.Add( wxT("Vertical Hatch") );
670
671
672 //
673 // Create pen selector ODComboBox with owner-drawn items
674 //
675 rowSizer = new wxBoxSizer( wxHORIZONTAL );
676 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
677 wxT("OwnerDrawnComboBox with owner-drawn items:")), 1,
678 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
679 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
680
681 rowSizer = new wxBoxSizer( wxHORIZONTAL );
682
683
684 // When defining derivative class for callbacks, we need
685 // to use two-stage creation (or redefine the common wx
686 // constructor).
687 odc = new wxPenStyleComboBox();
688 odc->Create(panel,wxID_ANY,wxEmptyString,
689 wxDefaultPosition, wxDefaultSize,
690 m_arrItems,
691 wxCB_READONLY //wxNO_BORDER | wxCB_READONLY
692 );
693
694
695 odc->SetSelection(0);
696
697 rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
698 rowSizer->AddStretchSpacer(1);
699 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
700
701
702
703 //
704 // Same but with changed button position
705 //
706 rowSizer = new wxBoxSizer( wxHORIZONTAL );
707 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
708 wxT("OwnerDrawnComboBox with owner-drawn items and button on the left:")), 1,
709 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
710 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
711
712 rowSizer = new wxBoxSizer( wxHORIZONTAL );
713
714
715 // When defining derivative class for callbacks, we need
716 // to use two-stage creation (or redefine the common wx
717 // constructor).
718 odc = new wxPenStyleComboBox();
719 odc->Create(panel,wxID_ANY,wxEmptyString,
720 wxDefaultPosition, wxDefaultSize,
721 m_arrItems,
722 wxCB_READONLY //wxNO_BORDER | wxCB_READONLY
723 );
724
725
726 odc->SetSelection(0);
727
728 // Use button size that is slightly smaller than the default.
729 wxSize butSize = odc->GetButtonSize();
730 odc->SetButtonPosition(butSize.x - 2, // button width
731 butSize.y - 6, // button height
732 wxLEFT, // side
733 2 // horizontal spacing
734 );
735
736 rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
737 rowSizer->AddStretchSpacer(1);
738 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
739
740
741 //
742 // List View wxComboCtrl
743 //
744
745 rowSizer = new wxBoxSizer( wxHORIZONTAL );
746 rowSizer->Add( new wxStaticText(panel,wxID_ANY,wxT("List View wxComboCtrl:")), 1,
747 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
748 rowSizer->Add( new wxStaticText(panel,wxID_ANY,wxT("Tree Ctrl wxComboCtrl:")), 1,
749 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
750 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
751
752 rowSizer = new wxBoxSizer( wxHORIZONTAL );
753 cc = new wxComboCtrlWithCustomPopupAnim();
754 cc->Create(panel, wxID_ANY, wxEmptyString);
755
756 // Make sure we use popup that allows focusing the listview.
757 cc->UseAltPopupWindow();
758
759 cc->SetPopupMinWidth(300);
760
761 ListViewComboPopup* iface = new ListViewComboPopup();
762 cc->SetPopupControl(iface);
763
764 int i;
765 for ( i=0; i<100; i++ )
766 iface->AddSelection( wxString::Format(wxT("Item %02i"),i));
767
768 rowSizer->Add( cc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
769
770
771 //
772 // Tree Ctrl wxComboCtrl
773 //
774
775 // Note that we test that wxGenericComboCtrl works
776 gcc = new wxGenericComboCtrl(panel,wxID_ANY,wxEmptyString,
777 wxDefaultPosition, wxDefaultSize);
778
779 // Make sure we use popup that allows focusing the treectrl.
780 gcc->UseAltPopupWindow();
781
782 // Set popup interface right away, otherwise some of the calls
783 // below may fail
784 TreeCtrlComboPopup* tcPopup = new TreeCtrlComboPopup();
785 gcc->SetPopupControl(tcPopup);
786
787 // Add items using wxTreeCtrl methods directly
788 wxTreeItemId rootId = tcPopup->AddRoot(wxT("<hidden_root>"));
789
790 wxTreeItemId groupId;
791
792 for ( i=0; i<4; i++ )
793 {
794 groupId = tcPopup->AppendItem(rootId,
795 wxString::Format(wxT("Branch %02i"),i));
796
797 int n;
798 for ( n=0; n<25; n++ )
799 tcPopup->AppendItem(groupId,
800 wxString::Format(wxT("Subitem %02i"),(i*25)+n));
801 }
802
803 gcc->SetValue(wxT("Subitem 05"));
804
805 // Move button to left - it makes more sense for a tree ctrl
806 gcc->SetButtonPosition(-1, // button width
807 -1, // button height
808 wxLEFT, // side
809 0 // horizontal spacing
810 );
811
812 rowSizer->Add( gcc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
813
814 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
815
816 #if wxUSE_IMAGE
817 wxInitAllImageHandlers();
818
819 //
820 // Custom Dropbutton Bitmaps
821 // (second one uses blank button background)
822 //
823 rowSizer = new wxBoxSizer( wxHORIZONTAL );
824 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
825 wxT("OwnerDrawnComboBox with simple dropbutton graphics:")), 1,
826 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
827
828 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
829
830 rowSizer = new wxBoxSizer( wxHORIZONTAL );
831
832 odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
833 wxDefaultPosition, wxDefaultSize,
834 m_arrItems,
835 (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
836 );
837
838 wxOwnerDrawnComboBox* odc2;
839 odc2 = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
840 wxDefaultPosition, wxDefaultSize,
841 m_arrItems,
842 (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
843 );
844
845 // Load images from disk
846 wxImage imgNormal(wxT("dropbutn.png"));
847 wxImage imgPressed(wxT("dropbutp.png"));
848 wxImage imgHover(wxT("dropbuth.png"));
849
850 if ( imgNormal.IsOk() && imgPressed.IsOk() && imgHover.IsOk() )
851 {
852 wxBitmap bmpNormal(imgNormal);
853 wxBitmap bmpPressed(imgPressed);
854 wxBitmap bmpHover(imgHover);
855 odc->SetButtonBitmaps(bmpNormal,false,bmpPressed,bmpHover);
856 odc2->SetButtonBitmaps(bmpNormal,true,bmpPressed,bmpHover);
857 }
858 else
859 wxLogError(wxT("Dropbutton images not found"));
860
861 //odc2->SetButtonPosition(0, // width adjustment
862 // 0, // height adjustment
863 // wxLEFT, // side
864 // 0 // horizontal spacing
865 // );
866
867 rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
868 rowSizer->Add( odc2, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
869 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
870 #endif
871
872
873 //
874 // wxComboCtrl with totally custom button action (open file dialog)
875 //
876 rowSizer = new wxBoxSizer( wxHORIZONTAL );
877 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
878 wxT("wxComboCtrl with custom button action:")), 1,
879 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
880
881
882 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
883
884 rowSizer = new wxBoxSizer( wxHORIZONTAL );
885 wxFileSelectorCombo* fsc;
886
887 fsc = new wxFileSelectorCombo(panel,wxID_ANY,wxEmptyString,
888 wxDefaultPosition, wxDefaultSize,
889 (long)0
890 );
891
892 rowSizer->Add( fsc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
893 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
894
895
896 // Make sure GetFeatures is implemented
897 wxComboCtrl::GetFeatures();
898
899
900 topRowSizer->Add( colSizer, 1, wxALL, 2 );
901
902 colSizer = new wxBoxSizer( wxVERTICAL );
903
904 colSizer->AddSpacer(8);
905 colSizer->Add( new wxStaticText(panel, wxID_ANY, wxT("Log Messages:")), 0, wxTOP|wxLEFT, 3 );
906 colSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 3 );
907
908 topRowSizer->Add( colSizer, 1, wxEXPAND|wxALL, 2 );
909 topSizer->Add( topRowSizer, 1, wxEXPAND );
910
911 panel->SetSizer( topSizer );
912 topSizer->SetSizeHints( panel );
913
914 SetSize(740,400);
915 Centre();
916 }
917
918 // event handlers
919
920 void MyFrame::OnComboBoxUpdate( wxCommandEvent& event )
921 {
922 // Don't show messages for the log output window (it'll crash)
923 if ( !event.GetEventObject()->IsKindOf(CLASSINFO(wxComboCtrl)) )
924 return;
925
926 if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
927 {
928 wxLogDebug(wxT("EVT_COMBOBOX(id=%i,selection=%i)"),event.GetId(),event.GetSelection());
929 }
930 else if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED )
931 {
932 wxLogDebug(wxT("EVT_TEXT(id=%i,string=\"%s\")"),event.GetId(),event.GetString().c_str());
933 }
934 }
935
936 void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
937 {
938 //
939 // Show some wxOwnerDrawComboBoxes for comparison
940 //
941
942 wxBoxSizer* colSizer;
943 wxBoxSizer* rowSizer;
944 wxStaticBoxSizer* groupSizer;
945
946 wxComboBox* cb;
947 wxOwnerDrawnComboBox* odc;
948
949 const int border = 4;
950
951 wxDialog* dlg = new wxDialog(this,wxID_ANY,
952 wxT("Compare against wxComboBox"),
953 wxDefaultPosition,wxDefaultSize,
954 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
955
956 colSizer = new wxBoxSizer( wxVERTICAL );
957
958 rowSizer = new wxBoxSizer(wxHORIZONTAL);
959
960 groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxOwnerDrawnComboBox ")),
961 wxVERTICAL);
962
963 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
964 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
965
966 odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
967 wxDefaultPosition, wxDefaultSize,
968 m_arrItems,
969 wxCB_SORT // wxNO_BORDER|wxCB_READONLY
970 );
971
972 odc->Append(wxT("H - Appended Item")); // test sorting in append
973
974 odc->SetValue(wxT("Dot Dash"));
975
976 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
977
978 //
979 // Readonly ODComboBox
980 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
981 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
982
983 odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
984 wxDefaultPosition, wxDefaultSize,
985 m_arrItems,
986 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
987 );
988
989 odc->SetValue(wxT("Dot Dash"));
990 odc->SetText(wxT("Dot Dash (Testing SetText)"));
991
992 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
993
994 //
995 // Disabled ODComboBox
996 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Disabled:")), 0,
997 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
998
999 odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
1000 wxDefaultPosition, wxDefaultSize,
1001 m_arrItems,
1002 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
1003 );
1004
1005 odc->SetValue(wxT("Dot Dash"));
1006 odc->Enable(false);
1007
1008 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1009
1010 rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
1011
1012
1013 groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxComboBox ")),
1014 wxVERTICAL);
1015
1016 //
1017 // wxComboBox
1018 //
1019 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
1020 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
1021
1022 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
1023 wxDefaultPosition, wxDefaultSize,
1024 m_arrItems,
1025 wxCB_SORT // wxNO_BORDER|wxCB_READONLY
1026 );
1027
1028 cb->Append(wxT("H - Appended Item")); // test sorting in append
1029
1030 cb->SetValue(wxT("Dot Dash"));
1031
1032 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1033
1034 //
1035 // Readonly wxComboBox
1036 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
1037 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
1038
1039 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
1040 wxDefaultPosition, wxDefaultSize,
1041 m_arrItems,
1042 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
1043 );
1044
1045 cb->SetValue(wxT("Dot Dash"));
1046
1047 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1048
1049 //
1050 // Disabled wxComboBox
1051 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Disabled:")), 0,
1052 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
1053
1054 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
1055 wxDefaultPosition, wxDefaultSize,
1056 m_arrItems,
1057 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
1058 );
1059
1060 cb->SetValue(wxT("Dot Dash"));
1061 cb->Enable(false);
1062
1063 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1064
1065 rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
1066
1067 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, border );
1068
1069 dlg->SetSizer( colSizer );
1070 colSizer->SetSizeHints( dlg );
1071
1072 dlg->SetSize(60,240);
1073 dlg->Centre();
1074 dlg->ShowModal();
1075 }
1076
1077 MyFrame::~MyFrame()
1078 {
1079 delete wxLog::SetActiveTarget(m_logOld);
1080 }
1081
1082 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1083 {
1084 // true is to force the frame to close
1085 Close(true);
1086 }
1087
1088 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1089 {
1090 wxMessageBox(wxString::Format(
1091 wxT("Welcome to %s!\n")
1092 wxT("\n")
1093 wxT("This is the wxWidgets wxComboCtrl and wxOwnerDrawnComboBox sample\n")
1094 wxT("running under %s."),
1095 wxVERSION_STRING,
1096 wxGetOsDescription().c_str()
1097 ),
1098 wxT("About wxComboCtrl sample"),
1099 wxOK | wxICON_INFORMATION,
1100 this);
1101 }
1102
1103 void MyFrame::OnIdle(wxIdleEvent& event)
1104 {
1105 // This code is useful for debugging focus problems
1106 // (which are plentiful when dealing with popup windows).
1107 #if 0
1108 static wxWindow* lastFocus = (wxWindow*) NULL;
1109
1110 wxWindow* curFocus = ::wxWindow::FindFocus();
1111
1112 if ( curFocus != lastFocus )
1113 {
1114 const wxChar* className = wxT("<none>");
1115 if ( curFocus )
1116 className = curFocus->GetClassInfo()->GetClassName();
1117 lastFocus = curFocus;
1118 wxLogDebug( wxT("FOCUSED: %s %X"),
1119 className,
1120 (unsigned int)curFocus);
1121 }
1122 #endif
1123
1124 event.Skip();
1125 }