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