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