]> git.saurik.com Git - wxWidgets.git/blob - samples/combo/combo.cpp
Fix problems with reference counting in wxActiveXContainer.
[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_BLEND);
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,
747 wxID_ANY,
748 "List View wxComboCtrl (custom animation):"),
749 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
750 rowSizer->Add( new wxStaticText(panel,wxID_ANY,wxT("Tree Ctrl wxComboCtrl:")), 1,
751 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
752 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
753
754 rowSizer = new wxBoxSizer( wxHORIZONTAL );
755 cc = new wxComboCtrlWithCustomPopupAnim();
756
757 // Let's set a custom style for the contained wxTextCtrl. We need to
758 // use two-step creation for it to work properly.
759 cc->SetTextCtrlStyle(wxTE_RIGHT);
760
761 cc->Create(panel, wxID_ANY, wxEmptyString);
762
763 // Make sure we use popup that allows focusing the listview.
764 cc->UseAltPopupWindow();
765
766 cc->SetPopupMinWidth(300);
767
768 ListViewComboPopup* iface = new ListViewComboPopup();
769 cc->SetPopupControl(iface);
770
771 int i;
772 for ( i=0; i<100; i++ )
773 iface->AddSelection( wxString::Format(wxT("Item %02i"),i));
774
775 rowSizer->Add( cc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
776
777
778 //
779 // Tree Ctrl wxComboCtrl
780 //
781
782 // Note that we test that wxGenericComboCtrl works
783 gcc = new wxGenericComboCtrl(panel,wxID_ANY,wxEmptyString,
784 wxDefaultPosition, wxDefaultSize);
785
786 // Make sure we use popup that allows focusing the treectrl.
787 gcc->UseAltPopupWindow();
788
789 // Set popup interface right away, otherwise some of the calls
790 // below may fail
791 TreeCtrlComboPopup* tcPopup = new TreeCtrlComboPopup();
792 gcc->SetPopupControl(tcPopup);
793
794 // Add items using wxTreeCtrl methods directly
795 wxTreeItemId rootId = tcPopup->AddRoot(wxT("<hidden_root>"));
796
797 wxTreeItemId groupId;
798
799 for ( i=0; i<4; i++ )
800 {
801 groupId = tcPopup->AppendItem(rootId,
802 wxString::Format(wxT("Branch %02i"),i));
803
804 int n;
805 for ( n=0; n<25; n++ )
806 tcPopup->AppendItem(groupId,
807 wxString::Format(wxT("Subitem %02i"),(i*25)+n));
808 }
809
810 gcc->SetValue(wxT("Subitem 05"));
811
812 // Move button to left - it makes more sense for a tree ctrl
813 gcc->SetButtonPosition(-1, // button width
814 -1, // button height
815 wxLEFT, // side
816 0 // horizontal spacing
817 );
818
819 rowSizer->Add( gcc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
820
821 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
822
823 #if wxUSE_IMAGE
824 wxInitAllImageHandlers();
825
826 //
827 // Custom Dropbutton Bitmaps
828 // (second one uses blank button background)
829 //
830 rowSizer = new wxBoxSizer( wxHORIZONTAL );
831 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
832 wxT("OwnerDrawnComboBox with simple dropbutton graphics:")), 1,
833 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
834
835 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
836
837 rowSizer = new wxBoxSizer( wxHORIZONTAL );
838
839 odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
840 wxDefaultPosition, wxDefaultSize,
841 m_arrItems,
842 (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
843 );
844
845 wxOwnerDrawnComboBox* odc2;
846 odc2 = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
847 wxDefaultPosition, wxDefaultSize,
848 m_arrItems,
849 (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
850 );
851
852 // Load images from disk
853 wxImage imgNormal(wxT("dropbutn.png"));
854 wxImage imgPressed(wxT("dropbutp.png"));
855 wxImage imgHover(wxT("dropbuth.png"));
856
857 if ( imgNormal.IsOk() && imgPressed.IsOk() && imgHover.IsOk() )
858 {
859 wxBitmap bmpNormal(imgNormal);
860 wxBitmap bmpPressed(imgPressed);
861 wxBitmap bmpHover(imgHover);
862 odc->SetButtonBitmaps(bmpNormal,false,bmpPressed,bmpHover);
863 odc2->SetButtonBitmaps(bmpNormal,true,bmpPressed,bmpHover);
864 }
865 else
866 wxLogError(wxT("Dropbutton images not found"));
867
868 //odc2->SetButtonPosition(0, // width adjustment
869 // 0, // height adjustment
870 // wxLEFT, // side
871 // 0 // horizontal spacing
872 // );
873
874 rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
875 rowSizer->Add( odc2, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
876 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
877 #endif
878
879
880 //
881 // wxComboCtrl with totally custom button action (open file dialog)
882 //
883 rowSizer = new wxBoxSizer( wxHORIZONTAL );
884 rowSizer->Add( new wxStaticText(panel,wxID_ANY,
885 wxT("wxComboCtrl with custom button action:")), 1,
886 wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
887
888
889 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
890
891 rowSizer = new wxBoxSizer( wxHORIZONTAL );
892 wxFileSelectorCombo* fsc;
893
894 fsc = new wxFileSelectorCombo(panel,wxID_ANY,wxEmptyString,
895 wxDefaultPosition, wxDefaultSize,
896 (long)0
897 );
898
899 rowSizer->Add( fsc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
900 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
901
902
903 // Make sure GetFeatures is implemented
904 wxComboCtrl::GetFeatures();
905
906
907 topRowSizer->Add( colSizer, 1, wxALL, 2 );
908
909 colSizer = new wxBoxSizer( wxVERTICAL );
910
911 colSizer->AddSpacer(8);
912 colSizer->Add( new wxStaticText(panel, wxID_ANY, wxT("Log Messages:")), 0, wxTOP|wxLEFT, 3 );
913 colSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 3 );
914
915 topRowSizer->Add( colSizer, 1, wxEXPAND|wxALL, 2 );
916 topSizer->Add( topRowSizer, 1, wxEXPAND );
917
918 panel->SetSizer( topSizer );
919 topSizer->SetSizeHints( panel );
920
921 SetSize(740,400);
922 Centre();
923 }
924
925 // event handlers
926
927 void MyFrame::OnComboBoxUpdate( wxCommandEvent& event )
928 {
929 // Don't show messages for the log output window (it'll crash)
930 if ( !event.GetEventObject()->IsKindOf(CLASSINFO(wxComboCtrl)) )
931 return;
932
933 if ( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED )
934 {
935 wxLogDebug(wxT("EVT_COMBOBOX(id=%i,selection=%i)"),event.GetId(),event.GetSelection());
936 }
937 else if ( event.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED )
938 {
939 wxLogDebug(wxT("EVT_TEXT(id=%i,string=\"%s\")"),event.GetId(),event.GetString().c_str());
940 }
941 }
942
943 void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
944 {
945 //
946 // Show some wxOwnerDrawComboBoxes for comparison
947 //
948
949 wxBoxSizer* colSizer;
950 wxBoxSizer* rowSizer;
951 wxStaticBoxSizer* groupSizer;
952
953 wxComboBox* cb;
954 wxOwnerDrawnComboBox* odc;
955
956 const int border = 4;
957
958 wxDialog* dlg = new wxDialog(this,wxID_ANY,
959 wxT("Compare against wxComboBox"),
960 wxDefaultPosition,wxDefaultSize,
961 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
962
963 colSizer = new wxBoxSizer( wxVERTICAL );
964
965 rowSizer = new wxBoxSizer(wxHORIZONTAL);
966
967 groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxOwnerDrawnComboBox ")),
968 wxVERTICAL);
969
970 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
971 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
972
973 odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
974 wxDefaultPosition, wxDefaultSize,
975 m_arrItems,
976 wxCB_SORT // wxNO_BORDER|wxCB_READONLY
977 );
978
979 odc->Append(wxT("H - Appended Item")); // test sorting in append
980
981 odc->SetValue(wxT("Dot Dash"));
982
983 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
984
985 //
986 // Readonly ODComboBox
987 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
988 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
989
990 odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
991 wxDefaultPosition, wxDefaultSize,
992 m_arrItems,
993 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
994 );
995
996 odc->SetValue(wxT("Dot Dash"));
997 odc->SetText(wxT("Dot Dash (Testing SetText)"));
998
999 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1000
1001 //
1002 // Disabled ODComboBox
1003 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Disabled:")), 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->SetValue(wxT("Dot Dash"));
1013 odc->Enable(false);
1014
1015 groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1016
1017 rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
1018
1019
1020 groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxComboBox ")),
1021 wxVERTICAL);
1022
1023 //
1024 // wxComboBox
1025 //
1026 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
1027 wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
1028
1029 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
1030 wxDefaultPosition, wxDefaultSize,
1031 m_arrItems,
1032 wxCB_SORT // wxNO_BORDER|wxCB_READONLY
1033 );
1034
1035 cb->Append(wxT("H - Appended Item")); // test sorting in append
1036
1037 cb->SetValue(wxT("Dot Dash"));
1038
1039 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1040
1041 //
1042 // Readonly wxComboBox
1043 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
1044 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
1045
1046 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
1047 wxDefaultPosition, wxDefaultSize,
1048 m_arrItems,
1049 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
1050 );
1051
1052 cb->SetValue(wxT("Dot Dash"));
1053
1054 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1055
1056 //
1057 // Disabled wxComboBox
1058 groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Disabled:")), 0,
1059 wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
1060
1061 cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
1062 wxDefaultPosition, wxDefaultSize,
1063 m_arrItems,
1064 wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
1065 );
1066
1067 cb->SetValue(wxT("Dot Dash"));
1068 cb->Enable(false);
1069
1070 groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
1071
1072 rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
1073
1074 colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, border );
1075
1076 dlg->SetSizer( colSizer );
1077 colSizer->SetSizeHints( dlg );
1078
1079 dlg->SetSize(60,240);
1080 dlg->Centre();
1081 dlg->ShowModal();
1082 }
1083
1084 MyFrame::~MyFrame()
1085 {
1086 delete wxLog::SetActiveTarget(m_logOld);
1087 }
1088
1089 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1090 {
1091 // true is to force the frame to close
1092 Close(true);
1093 }
1094
1095 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1096 {
1097 wxMessageBox(wxString::Format(
1098 wxT("Welcome to %s!\n")
1099 wxT("\n")
1100 wxT("This is the wxWidgets wxComboCtrl and wxOwnerDrawnComboBox sample\n")
1101 wxT("running under %s."),
1102 wxVERSION_STRING,
1103 wxGetOsDescription().c_str()
1104 ),
1105 wxT("About wxComboCtrl sample"),
1106 wxOK | wxICON_INFORMATION,
1107 this);
1108 }
1109
1110 void MyFrame::OnIdle(wxIdleEvent& event)
1111 {
1112 // This code is useful for debugging focus problems
1113 // (which are plentiful when dealing with popup windows).
1114 #if 0
1115 static wxWindow* lastFocus = (wxWindow*) NULL;
1116
1117 wxWindow* curFocus = ::wxWindow::FindFocus();
1118
1119 if ( curFocus != lastFocus )
1120 {
1121 const wxChar* className = wxT("<none>");
1122 if ( curFocus )
1123 className = curFocus->GetClassInfo()->GetClassName();
1124 lastFocus = curFocus;
1125 wxLogDebug( wxT("FOCUSED: %s %X"),
1126 className,
1127 (unsigned int)curFocus);
1128 }
1129 #endif
1130
1131 event.Skip();
1132 }