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