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