combo.cpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: combo.cpp
  3. // Purpose: wxComboCtrl sample
  4. // Author: Jaakko Salli
  5. // Modified by:
  6. // Created: Apr-30-2006
  7. // Copyright: (c) Jaakko Salli
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. // ============================================================================
  11. // declarations
  12. // ============================================================================
  13. // ----------------------------------------------------------------------------
  14. // headers
  15. // ----------------------------------------------------------------------------
  16. // For compilers that support precompilation, includes "wx/wx.h".
  17. #include "wx/wxprec.h"
  18. #ifdef __BORLANDC__
  19. #pragma hdrstop
  20. #endif
  21. // for all others, include the necessary headers (this file is usually all you
  22. // need because it includes almost all "standard" wxWidgets headers)
  23. #ifndef WX_PRECOMP
  24. #include "wx/wx.h"
  25. #endif
  26. #if !wxUSE_COMBOCTRL
  27. #error "Please set wxUSE_COMBOCTRL to 1 and rebuild the library."
  28. #endif
  29. #include "wx/image.h"
  30. #include "wx/combo.h"
  31. #include "wx/odcombo.h"
  32. // ----------------------------------------------------------------------------
  33. // resources
  34. // ----------------------------------------------------------------------------
  35. // the application icon (under Windows and OS/2 it is in resources and even
  36. // though we could still include the XPM here it would be unused)
  37. #ifndef wxHAS_IMAGES_IN_RESOURCES
  38. #include "../sample.xpm"
  39. #endif
  40. // ----------------------------------------------------------------------------
  41. // private classes
  42. // ----------------------------------------------------------------------------
  43. // Define a new application type, each program should derive a class from wxApp
  44. class MyApp : public wxApp
  45. {
  46. public:
  47. // override base class virtuals
  48. // ----------------------------
  49. // this one is called on application startup and is a good place for the app
  50. // initialization (doing it here and not in the ctor allows to have an error
  51. // return: if OnInit() returns false, the application terminates)
  52. virtual bool OnInit();
  53. };
  54. // Define a new frame type: this is going to be our main frame
  55. class MyFrame : public wxFrame
  56. {
  57. public:
  58. // ctor and dtor
  59. MyFrame(const wxString& title);
  60. ~MyFrame();
  61. // event handlers (these functions should _not_ be virtual)
  62. void OnQuit(wxCommandEvent& event);
  63. void OnAbout(wxCommandEvent& event);
  64. void OnShowComparison( wxCommandEvent& event );
  65. // log wxComboCtrl events
  66. void OnComboBoxUpdate( wxCommandEvent& event );
  67. void OnIdle( wxIdleEvent& event );
  68. protected:
  69. wxTextCtrl* m_logWin;
  70. wxLog* m_logOld;
  71. // Common list of items for all dialogs.
  72. wxArrayString m_arrItems;
  73. private:
  74. // any class wishing to process wxWidgets events must use this macro
  75. wxDECLARE_EVENT_TABLE();
  76. };
  77. // ----------------------------------------------------------------------------
  78. // constants
  79. // ----------------------------------------------------------------------------
  80. // IDs for the controls and the menu commands
  81. enum
  82. {
  83. ComboCtrl_Compare = wxID_HIGHEST,
  84. // menu items
  85. ComboCtrl_Quit = wxID_EXIT,
  86. // it is important for the id corresponding to the "About" command to have
  87. // this standard value as otherwise it won't be handled properly under Mac
  88. // (where it is special and put into the "Apple" menu)
  89. ComboCtrl_About = wxID_ABOUT
  90. };
  91. // ----------------------------------------------------------------------------
  92. // event tables and other macros for wxWidgets
  93. // ----------------------------------------------------------------------------
  94. // the event tables connect the wxWidgets events with the functions (event
  95. // handlers) which process them. It can be also done at run-time, but for the
  96. // simple menu events like this the static method is much simpler.
  97. wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
  98. EVT_TEXT(wxID_ANY,MyFrame::OnComboBoxUpdate)
  99. EVT_TEXT_ENTER(wxID_ANY,MyFrame::OnComboBoxUpdate)
  100. EVT_COMBOBOX(wxID_ANY,MyFrame::OnComboBoxUpdate)
  101. EVT_MENU(ComboCtrl_Compare, MyFrame::OnShowComparison)
  102. EVT_MENU(ComboCtrl_Quit, MyFrame::OnQuit)
  103. EVT_MENU(ComboCtrl_About, MyFrame::OnAbout)
  104. EVT_IDLE(MyFrame::OnIdle)
  105. wxEND_EVENT_TABLE()
  106. // Create a new application object: this macro will allow wxWidgets to create
  107. // the application object during program execution (it's better than using a
  108. // static object for many reasons) and also implements the accessor function
  109. // wxGetApp() which will return the reference of the right type (i.e. MyApp and
  110. // not wxApp)
  111. IMPLEMENT_APP(MyApp)
  112. // ============================================================================
  113. // implementation
  114. // ============================================================================
  115. // ----------------------------------------------------------------------------
  116. // the application class
  117. // ----------------------------------------------------------------------------
  118. // 'Main program' equivalent: the program execution "starts" here
  119. bool MyApp::OnInit()
  120. {
  121. if ( !wxApp::OnInit() )
  122. return false;
  123. // create the main application window
  124. MyFrame *frame = new MyFrame(wxT("wxComboCtrl and wxOwnerDrawnComboBox Sample"));
  125. // and show it (the frames, unlike simple controls, are not shown when
  126. // created initially)
  127. frame->Show(true);
  128. // success: wxApp::OnRun() will be called which will enter the main message
  129. // loop and the application will run. If we returned false here, the
  130. // application would exit immediately.
  131. return true;
  132. }
  133. // ----------------------------------------------------------------------------
  134. // wxOwnerDrawnComboBox with custom paint list items
  135. // ----------------------------------------------------------------------------
  136. class wxPenStyleComboBox : public wxOwnerDrawnComboBox
  137. {
  138. public:
  139. virtual void OnDrawItem( wxDC& dc,
  140. const wxRect& rect,
  141. int item,
  142. int flags ) const
  143. {
  144. if ( item == wxNOT_FOUND )
  145. return;
  146. wxRect r(rect);
  147. r.Deflate(3);
  148. r.height -= 2;
  149. wxPenStyle penStyle = wxPENSTYLE_SOLID;
  150. if ( item == 1 )
  151. penStyle = wxPENSTYLE_TRANSPARENT;
  152. else if ( item == 2 )
  153. penStyle = wxPENSTYLE_DOT;
  154. else if ( item == 3 )
  155. penStyle = wxPENSTYLE_LONG_DASH;
  156. else if ( item == 4 )
  157. penStyle = wxPENSTYLE_SHORT_DASH;
  158. else if ( item == 5 )
  159. penStyle = wxPENSTYLE_DOT_DASH;
  160. else if ( item == 6 )
  161. penStyle = wxPENSTYLE_BDIAGONAL_HATCH;
  162. else if ( item == 7 )
  163. penStyle = wxPENSTYLE_CROSSDIAG_HATCH;
  164. else if ( item == 8 )
  165. penStyle = wxPENSTYLE_FDIAGONAL_HATCH;
  166. else if ( item == 9 )
  167. penStyle = wxPENSTYLE_CROSS_HATCH;
  168. else if ( item == 10 )
  169. penStyle = wxPENSTYLE_HORIZONTAL_HATCH;
  170. else if ( item == 11 )
  171. penStyle = wxPENSTYLE_VERTICAL_HATCH;
  172. wxPen pen( dc.GetTextForeground(), 3, penStyle );
  173. // Get text colour as pen colour
  174. dc.SetPen( pen );
  175. if ( !(flags & wxODCB_PAINTING_CONTROL) )
  176. {
  177. dc.DrawText(GetString( item ),
  178. r.x + 3,
  179. (r.y + 0) + ( (r.height/2) - dc.GetCharHeight() )/2
  180. );
  181. dc.DrawLine( r.x+5, r.y+((r.height/4)*3), r.x+r.width - 5, r.y+((r.height/4)*3) );
  182. }
  183. else
  184. {
  185. dc.DrawLine( r.x+5, r.y+r.height/2, r.x+r.width - 5, r.y+r.height/2 );
  186. }
  187. }
  188. virtual void OnDrawBackground( wxDC& dc, const wxRect& rect,
  189. int item, int flags ) const
  190. {
  191. // If item is selected or even, or we are painting the
  192. // combo control itself, use the default rendering.
  193. if ( (flags & (wxODCB_PAINTING_CONTROL|wxODCB_PAINTING_SELECTED)) ||
  194. (item & 1) == 0 )
  195. {
  196. wxOwnerDrawnComboBox::OnDrawBackground(dc,rect,item,flags);
  197. return;
  198. }
  199. // Otherwise, draw every other background with different colour.
  200. wxColour bgCol(240,240,250);
  201. dc.SetBrush(wxBrush(bgCol));
  202. dc.SetPen(wxPen(bgCol));
  203. dc.DrawRectangle(rect);
  204. }
  205. virtual wxCoord OnMeasureItem( size_t item ) const
  206. {
  207. // Simply demonstrate the ability to have variable-height items
  208. if ( item & 1 )
  209. return 36;
  210. else
  211. return 24;
  212. }
  213. virtual wxCoord OnMeasureItemWidth( size_t WXUNUSED(item) ) const
  214. {
  215. return -1; // default - will be measured from text width
  216. }
  217. };
  218. // ----------------------------------------------------------------------------
  219. // wxListView Custom popup interface
  220. // ----------------------------------------------------------------------------
  221. #include <wx/listctrl.h>
  222. class ListViewComboPopup : public wxListView, public wxComboPopup
  223. {
  224. public:
  225. virtual void Init()
  226. {
  227. m_value = -1;
  228. m_itemHere = -1; // hot item in list
  229. }
  230. virtual bool Create( wxWindow* parent )
  231. {
  232. return wxListView::Create(parent,1,
  233. wxPoint(0,0),wxDefaultSize,
  234. wxLC_LIST|wxLC_SINGLE_SEL|
  235. wxLC_SORT_ASCENDING|wxSIMPLE_BORDER);
  236. }
  237. virtual wxWindow *GetControl() { return this; }
  238. virtual void SetStringValue( const wxString& s )
  239. {
  240. int n = wxListView::FindItem(-1,s);
  241. if ( n >= 0 && n < GetItemCount() )
  242. wxListView::Select(n);
  243. }
  244. virtual wxString GetStringValue() const
  245. {
  246. if ( m_value >= 0 )
  247. return wxListView::GetItemText(m_value);
  248. return wxEmptyString;
  249. }
  250. //
  251. // Popup event handlers
  252. //
  253. // Mouse hot-tracking
  254. void OnMouseMove(wxMouseEvent& event)
  255. {
  256. // Move selection to cursor if it is inside the popup
  257. int resFlags;
  258. int itemHere = HitTest(event.GetPosition(),resFlags);
  259. if ( itemHere >= 0 )
  260. {
  261. wxListView::Select(itemHere,true);
  262. m_itemHere = itemHere;
  263. }
  264. event.Skip();
  265. }
  266. // On mouse left, set the value and close the popup
  267. void OnMouseClick(wxMouseEvent& WXUNUSED(event))
  268. {
  269. m_value = m_itemHere;
  270. // TODO: Send event
  271. Dismiss();
  272. }
  273. //
  274. // Utilies for item manipulation
  275. //
  276. void AddSelection( const wxString& selstr )
  277. {
  278. wxListView::InsertItem(GetItemCount(),selstr);
  279. }
  280. protected:
  281. int m_value; // current item index
  282. int m_itemHere; // hot item in popup
  283. private:
  284. wxDECLARE_EVENT_TABLE();
  285. };
  286. wxBEGIN_EVENT_TABLE(ListViewComboPopup, wxListView)
  287. EVT_MOTION(ListViewComboPopup::OnMouseMove)
  288. // NOTE: Left down event is used instead of left up right now
  289. // since MSW wxListCtrl doesn't seem to emit left ups
  290. // consistently.
  291. EVT_LEFT_DOWN(ListViewComboPopup::OnMouseClick)
  292. wxEND_EVENT_TABLE()
  293. // ----------------------------------------------------------------------------
  294. // wxTreeCtrl Custom popup interface
  295. // ----------------------------------------------------------------------------
  296. #include <wx/treectrl.h>
  297. class TreeCtrlComboPopup : public wxTreeCtrl, public wxComboPopup
  298. {
  299. public:
  300. virtual void Init()
  301. {
  302. }
  303. virtual ~TreeCtrlComboPopup()
  304. {
  305. if (!m_isBeingDeleted)
  306. {
  307. wxMessageBox("error wxTreeCtrl::Destroy() was not called");
  308. }
  309. SendDestroyEvent();
  310. }
  311. virtual bool Create( wxWindow* parent )
  312. {
  313. return wxTreeCtrl::Create(parent,1,
  314. wxPoint(0,0),wxDefaultSize,
  315. wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT | wxSIMPLE_BORDER );
  316. }
  317. virtual void OnShow()
  318. {
  319. // make sure selected item is visible
  320. if ( m_value.IsOk() )
  321. EnsureVisible(m_value);
  322. }
  323. virtual wxSize GetAdjustedSize( int minWidth,
  324. int WXUNUSED(prefHeight),
  325. int maxHeight )
  326. {
  327. return wxSize(wxMax(300,minWidth),wxMin(250,maxHeight));
  328. }
  329. virtual wxWindow *GetControl() { return this; }
  330. // Needed by SetStringValue
  331. wxTreeItemId FindItemByText( wxTreeItemId parent, const wxString& text )
  332. {
  333. wxTreeItemIdValue cookie;
  334. wxTreeItemId child = GetFirstChild(parent,cookie);
  335. while ( child.IsOk() )
  336. {
  337. if ( GetItemText(child) == text )
  338. {
  339. return child;
  340. }
  341. if ( ItemHasChildren(child) )
  342. {
  343. wxTreeItemId found = FindItemByText(child,text);
  344. if ( found.IsOk() )
  345. return found;
  346. }
  347. child = GetNextChild(parent,cookie);
  348. }
  349. return wxTreeItemId();
  350. }
  351. virtual void SetStringValue( const wxString& s )
  352. {
  353. wxTreeItemId root = GetRootItem();
  354. if ( !root.IsOk() )
  355. return;
  356. wxTreeItemId found = FindItemByText(root,s);
  357. if ( found.IsOk() )
  358. {
  359. m_value = m_itemHere = found;
  360. wxTreeCtrl::SelectItem(found);
  361. }
  362. }
  363. virtual wxString GetStringValue() const
  364. {
  365. if ( m_value.IsOk() )
  366. return wxTreeCtrl::GetItemText(m_value);
  367. return wxEmptyString;
  368. }
  369. //
  370. // Popup event handlers
  371. //
  372. // Mouse hot-tracking
  373. void OnMouseMove(wxMouseEvent& event)
  374. {
  375. int resFlags;
  376. wxTreeItemId itemHere = HitTest(event.GetPosition(),resFlags);
  377. if ( itemHere.IsOk() && (resFlags & wxTREE_HITTEST_ONITEMLABEL) )
  378. {
  379. wxTreeCtrl::SelectItem(itemHere,true);
  380. m_itemHere = itemHere;
  381. }
  382. event.Skip();
  383. }
  384. // On mouse left, set the value and close the popup
  385. void OnMouseClick(wxMouseEvent& event)
  386. {
  387. int resFlags;
  388. wxTreeItemId itemHere = HitTest(event.GetPosition(),resFlags);
  389. if ( itemHere.IsOk() && (resFlags & wxTREE_HITTEST_ONITEMLABEL) )
  390. {
  391. m_itemHere = itemHere;
  392. m_value = itemHere;
  393. Dismiss();
  394. // TODO: Send event
  395. }
  396. event.Skip();
  397. }
  398. protected:
  399. wxTreeItemId m_value; // current item index
  400. wxTreeItemId m_itemHere; // hot item in popup
  401. private:
  402. wxDECLARE_EVENT_TABLE();
  403. };
  404. wxBEGIN_EVENT_TABLE(TreeCtrlComboPopup, wxTreeCtrl)
  405. EVT_MOTION(TreeCtrlComboPopup::OnMouseMove)
  406. // NOTE: Left down event is used instead of left up right now
  407. // since MSW wxTreeCtrl doesn't seem to emit left ups
  408. // consistently.
  409. EVT_LEFT_DOWN(TreeCtrlComboPopup::OnMouseClick)
  410. wxEND_EVENT_TABLE()
  411. // ----------------------------------------------------------------------------
  412. // wxComboCtrl with custom popup animation, using wxWindow::ShowWithEffect().
  413. // ----------------------------------------------------------------------------
  414. class wxComboCtrlWithCustomPopupAnim : public wxComboCtrl
  415. {
  416. protected:
  417. virtual bool AnimateShow( const wxRect& rect, int WXUNUSED(flags) )
  418. {
  419. wxWindow* win = GetPopupWindow();
  420. win->SetSize(rect);
  421. win->Raise(); // This is needed
  422. win->ShowWithEffect(wxSHOW_EFFECT_BLEND);
  423. return true;
  424. }
  425. };
  426. // ----------------------------------------------------------------------------
  427. // wxComboCtrl with entirely custom button action (opens file dialog)
  428. // ----------------------------------------------------------------------------
  429. class wxFileSelectorCombo : public wxComboCtrl
  430. {
  431. public:
  432. wxFileSelectorCombo() : wxComboCtrl() { Init(); }
  433. wxFileSelectorCombo(wxWindow *parent,
  434. wxWindowID id = wxID_ANY,
  435. const wxString& value = wxEmptyString,
  436. const wxPoint& pos = wxDefaultPosition,
  437. const wxSize& size = wxDefaultSize,
  438. long style = 0,
  439. const wxValidator& validator = wxDefaultValidator,
  440. const wxString& name = wxComboBoxNameStr)
  441. : wxComboCtrl()
  442. {
  443. Init();
  444. Create(parent,id,value,
  445. pos,size,
  446. // Style flag wxCC_STD_BUTTON makes the button
  447. // behave more like a standard push button.
  448. style | wxCC_STD_BUTTON,
  449. validator,name);
  450. //
  451. // Prepare custom button bitmap (just '...' text)
  452. wxMemoryDC dc;
  453. wxBitmap bmp(12,16);
  454. dc.SelectObject(bmp);
  455. // Draw transparent background
  456. wxColour magic(255,0,255);
  457. wxBrush magicBrush(magic);
  458. dc.SetBrush( magicBrush );
  459. dc.SetPen( *wxTRANSPARENT_PEN );
  460. dc.DrawRectangle(0,0,bmp.GetWidth(),bmp.GetHeight());
  461. // Draw text
  462. wxString str = wxT("...");
  463. int w,h;
  464. dc.GetTextExtent(str, &w, &h, 0, 0);
  465. dc.DrawText(str, (bmp.GetWidth()-w)/2, (bmp.GetHeight()-h)/2);
  466. dc.SelectObject( wxNullBitmap );
  467. // Finalize transparency with a mask
  468. wxMask *mask = new wxMask( bmp, magic );
  469. bmp.SetMask( mask );
  470. SetButtonBitmaps(bmp,true);
  471. }
  472. virtual void OnButtonClick()
  473. {
  474. // Show standard wxFileDialog on button click
  475. wxFileDialog dlg(this,
  476. wxT("Choose File"),
  477. wxEmptyString,
  478. GetValue(),
  479. wxT("All files (*.*)|*.*"),
  480. wxFD_OPEN);
  481. if ( dlg.ShowModal() == wxID_OK )
  482. {
  483. SetValue(dlg.GetPath());
  484. }
  485. }
  486. // Implement empty DoSetPopupControl to prevent assertion failure.
  487. virtual void DoSetPopupControl(wxComboPopup* WXUNUSED(popup))
  488. {
  489. }
  490. private:
  491. void Init()
  492. {
  493. // Initialize member variables here
  494. }
  495. };
  496. // ----------------------------------------------------------------------------
  497. // main frame
  498. // ----------------------------------------------------------------------------
  499. // frame constructor
  500. MyFrame::MyFrame(const wxString& title)
  501. : wxFrame(NULL, wxID_ANY, title)
  502. {
  503. wxBoxSizer* topSizer;
  504. wxBoxSizer* topRowSizer;
  505. wxBoxSizer* colSizer;
  506. wxBoxSizer* rowSizer;
  507. // set the frame icon
  508. SetIcon(wxICON(sample));
  509. #if wxUSE_MENUS
  510. // create a menu bar
  511. wxMenu *fileMenu = new wxMenu;
  512. // the "About" item should be in the help menu
  513. wxMenu *helpMenu = new wxMenu;
  514. helpMenu->Append(ComboCtrl_About, wxT("&About\tF1"), wxT("Show about dialog"));
  515. fileMenu->Append(ComboCtrl_Compare, wxT("&Compare against wxComboBox..."),
  516. wxT("Show some wxOwnerDrawnComboBoxes side-by-side with native wxComboBoxes."));
  517. fileMenu->AppendSeparator();
  518. fileMenu->Append(ComboCtrl_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
  519. // now append the freshly created menu to the menu bar...
  520. wxMenuBar *menuBar = new wxMenuBar();
  521. menuBar->Append(fileMenu, wxT("&File"));
  522. menuBar->Append(helpMenu, wxT("&Help"));
  523. // ... and attach this menu bar to the frame
  524. SetMenuBar(menuBar);
  525. #endif // wxUSE_MENUS
  526. wxPanel* panel = new wxPanel(this);
  527. // Prepare log window right away since it shows EVT_TEXTs
  528. m_logWin = new wxTextCtrl(panel, 105, wxEmptyString,
  529. wxDefaultPosition,
  530. wxSize(-1, 125),
  531. wxTE_MULTILINE);
  532. wxLogTextCtrl* logger = new wxLogTextCtrl(m_logWin);
  533. m_logOld = logger->SetActiveTarget(logger);
  534. logger->DisableTimestamp();
  535. topSizer = new wxBoxSizer( wxVERTICAL );
  536. topRowSizer = new wxBoxSizer( wxHORIZONTAL );
  537. colSizer = new wxBoxSizer( wxVERTICAL );
  538. wxComboCtrl* cc;
  539. wxGenericComboCtrl* gcc;
  540. wxOwnerDrawnComboBox* odc;
  541. // Create common strings array
  542. m_arrItems.Add( wxT("Solid") );
  543. m_arrItems.Add( wxT("Transparent") );
  544. m_arrItems.Add( wxT("Dot") );
  545. m_arrItems.Add( wxT("Long Dash") );
  546. m_arrItems.Add( wxT("Short Dash") );
  547. m_arrItems.Add( wxT("Dot Dash") );
  548. m_arrItems.Add( wxT("Backward Diagonal Hatch") );
  549. m_arrItems.Add( wxT("Cross-diagonal Hatch") );
  550. m_arrItems.Add( wxT("Forward Diagonal Hatch") );
  551. m_arrItems.Add( wxT("Cross Hatch") );
  552. m_arrItems.Add( wxT("Horizontal Hatch") );
  553. m_arrItems.Add( wxT("Vertical Hatch") );
  554. //
  555. // Create pen selector ODComboBox with owner-drawn items
  556. //
  557. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  558. rowSizer->Add( new wxStaticText(panel,wxID_ANY,
  559. wxT("OwnerDrawnComboBox with owner-drawn items:")), 1,
  560. wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
  561. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  562. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  563. // When defining derivative class for callbacks, we need
  564. // to use two-stage creation (or redefine the common wx
  565. // constructor).
  566. odc = new wxPenStyleComboBox();
  567. odc->Create(panel,wxID_ANY,wxEmptyString,
  568. wxDefaultPosition, wxDefaultSize,
  569. m_arrItems,
  570. wxCB_READONLY //wxNO_BORDER | wxCB_READONLY
  571. );
  572. odc->SetSelection(0);
  573. rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
  574. rowSizer->AddStretchSpacer(1);
  575. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  576. //
  577. // Same but with changed button position
  578. //
  579. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  580. rowSizer->Add( new wxStaticText(panel,wxID_ANY,
  581. wxT("OwnerDrawnComboBox with owner-drawn items and button on the left:")), 1,
  582. wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
  583. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  584. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  585. // When defining derivative class for callbacks, we need
  586. // to use two-stage creation (or redefine the common wx
  587. // constructor).
  588. odc = new wxPenStyleComboBox();
  589. odc->Create(panel,wxID_ANY,wxEmptyString,
  590. wxDefaultPosition, wxDefaultSize,
  591. m_arrItems,
  592. wxCB_READONLY //wxNO_BORDER | wxCB_READONLY
  593. );
  594. odc->SetSelection(0);
  595. // Use button size that is slightly smaller than the default.
  596. wxSize butSize = odc->GetButtonSize();
  597. odc->SetButtonPosition(butSize.x - 2, // button width
  598. butSize.y - 6, // button height
  599. wxLEFT, // side
  600. 2 // horizontal spacing
  601. );
  602. rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
  603. rowSizer->AddStretchSpacer(1);
  604. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  605. //
  606. // List View wxComboCtrl
  607. //
  608. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  609. rowSizer->Add( new wxStaticText(panel,
  610. wxID_ANY,
  611. "List View wxComboCtrl (custom animation):"),
  612. 1, wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
  613. rowSizer->Add( new wxStaticText(panel,wxID_ANY,wxT("Tree Ctrl wxComboCtrl:")), 1,
  614. wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
  615. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  616. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  617. cc = new wxComboCtrlWithCustomPopupAnim();
  618. // Let's set a custom style for the contained wxTextCtrl. We need to
  619. // use two-step creation for it to work properly.
  620. cc->SetTextCtrlStyle(wxTE_RIGHT);
  621. cc->Create(panel, wxID_ANY, wxEmptyString);
  622. // Make sure we use popup that allows focusing the listview.
  623. cc->UseAltPopupWindow();
  624. cc->SetPopupMinWidth(300);
  625. ListViewComboPopup* iface = new ListViewComboPopup();
  626. cc->SetPopupControl(iface);
  627. int i;
  628. for ( i=0; i<100; i++ )
  629. iface->AddSelection( wxString::Format(wxT("Item %02i"),i));
  630. rowSizer->Add( cc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
  631. //
  632. // Tree Ctrl wxComboCtrl
  633. //
  634. // Note that we test that wxGenericComboCtrl works
  635. gcc = new wxGenericComboCtrl(panel,wxID_ANY,wxEmptyString,
  636. wxDefaultPosition, wxDefaultSize);
  637. // Make sure we use popup that allows focusing the treectrl.
  638. gcc->UseAltPopupWindow();
  639. // Set popup interface right away, otherwise some of the calls
  640. // below may fail
  641. TreeCtrlComboPopup* tcPopup = new TreeCtrlComboPopup();
  642. gcc->SetPopupControl(tcPopup);
  643. // Add items using wxTreeCtrl methods directly
  644. wxTreeItemId rootId = tcPopup->AddRoot(wxT("<hidden_root>"));
  645. wxTreeItemId groupId;
  646. for ( i=0; i<4; i++ )
  647. {
  648. groupId = tcPopup->AppendItem(rootId,
  649. wxString::Format(wxT("Branch %02i"),i));
  650. int n;
  651. for ( n=0; n<25; n++ )
  652. tcPopup->AppendItem(groupId,
  653. wxString::Format(wxT("Subitem %02i"),(i*25)+n));
  654. }
  655. gcc->SetValue(wxT("Subitem 05"));
  656. // Move button to left - it makes more sense for a tree ctrl
  657. gcc->SetButtonPosition(-1, // button width
  658. -1, // button height
  659. wxLEFT, // side
  660. 0 // horizontal spacing
  661. );
  662. rowSizer->Add( gcc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
  663. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  664. #if wxUSE_IMAGE
  665. wxInitAllImageHandlers();
  666. //
  667. // Custom Dropbutton Bitmaps
  668. // (second one uses blank button background)
  669. //
  670. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  671. rowSizer->Add( new wxStaticText(panel,wxID_ANY,
  672. wxT("OwnerDrawnComboBox with simple dropbutton graphics:")), 1,
  673. wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
  674. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  675. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  676. odc = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
  677. wxDefaultPosition, wxDefaultSize,
  678. m_arrItems,
  679. (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
  680. );
  681. wxOwnerDrawnComboBox* odc2;
  682. odc2 = new wxOwnerDrawnComboBox(panel,wxID_ANY,wxEmptyString,
  683. wxDefaultPosition, wxDefaultSize,
  684. m_arrItems,
  685. (long)0 // wxCB_SORT // wxNO_BORDER | wxCB_READONLY
  686. );
  687. // Load images from disk
  688. wxImage imgNormal(wxT("dropbutn.png"));
  689. wxImage imgPressed(wxT("dropbutp.png"));
  690. wxImage imgHover(wxT("dropbuth.png"));
  691. if ( imgNormal.IsOk() && imgPressed.IsOk() && imgHover.IsOk() )
  692. {
  693. wxBitmap bmpNormal(imgNormal);
  694. wxBitmap bmpPressed(imgPressed);
  695. wxBitmap bmpHover(imgHover);
  696. odc->SetButtonBitmaps(bmpNormal,false,bmpPressed,bmpHover);
  697. odc2->SetButtonBitmaps(bmpNormal,true,bmpPressed,bmpHover);
  698. }
  699. else
  700. wxLogError(wxT("Dropbutton images not found"));
  701. //odc2->SetButtonPosition(0, // width adjustment
  702. // 0, // height adjustment
  703. // wxLEFT, // side
  704. // 0 // horizontal spacing
  705. // );
  706. rowSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
  707. rowSizer->Add( odc2, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
  708. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  709. #endif
  710. //
  711. // wxComboCtrl with totally custom button action (open file dialog)
  712. //
  713. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  714. rowSizer->Add( new wxStaticText(panel,wxID_ANY,
  715. wxT("wxComboCtrl with custom button action:")), 1,
  716. wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
  717. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  718. rowSizer = new wxBoxSizer( wxHORIZONTAL );
  719. wxFileSelectorCombo* fsc;
  720. fsc = new wxFileSelectorCombo(panel,wxID_ANY,wxEmptyString,
  721. wxDefaultPosition, wxDefaultSize,
  722. (long)0
  723. );
  724. rowSizer->Add( fsc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
  725. colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
  726. // Make sure GetFeatures is implemented
  727. wxComboCtrl::GetFeatures();
  728. topRowSizer->Add( colSizer, 1, wxALL, 2 );
  729. colSizer = new wxBoxSizer( wxVERTICAL );
  730. colSizer->AddSpacer(8);
  731. colSizer->Add( new wxStaticText(panel, wxID_ANY, wxT("Log Messages:")), 0, wxTOP|wxLEFT, 3 );
  732. colSizer->Add( m_logWin, 1, wxEXPAND|wxALL, 3 );
  733. topRowSizer->Add( colSizer, 1, wxEXPAND|wxALL, 2 );
  734. topSizer->Add( topRowSizer, 1, wxEXPAND );
  735. panel->SetSizer( topSizer );
  736. topSizer->SetSizeHints( panel );
  737. Fit();
  738. Centre();
  739. }
  740. // event handlers
  741. void MyFrame::OnComboBoxUpdate( wxCommandEvent& event )
  742. {
  743. // Don't show messages for the log output window (it'll crash)
  744. if ( !event.GetEventObject()->IsKindOf(CLASSINFO(wxComboCtrl)) )
  745. return;
  746. if ( event.GetEventType() == wxEVT_COMBOBOX )
  747. {
  748. wxLogDebug(wxT("EVT_COMBOBOX(id=%i,selection=%i)"),event.GetId(),event.GetSelection());
  749. }
  750. else if ( event.GetEventType() == wxEVT_TEXT )
  751. {
  752. wxLogDebug(wxT("EVT_TEXT(id=%i,string=\"%s\")"),event.GetId(),event.GetString().c_str());
  753. }
  754. else if ( event.GetEventType() == wxEVT_TEXT_ENTER )
  755. {
  756. wxLogDebug("EVT_TEXT_ENTER(id=%i,string=\"%s\")",
  757. event.GetId(), event.GetString().c_str());
  758. }
  759. }
  760. void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
  761. {
  762. //
  763. // Show some wxOwnerDrawComboBoxes for comparison
  764. //
  765. wxBoxSizer* colSizer;
  766. wxBoxSizer* rowSizer;
  767. wxStaticBoxSizer* groupSizer;
  768. wxComboBox* cb;
  769. wxOwnerDrawnComboBox* odc;
  770. const int border = 4;
  771. wxDialog* dlg = new wxDialog(this,wxID_ANY,
  772. wxT("Compare against wxComboBox"),
  773. wxDefaultPosition,wxDefaultSize,
  774. wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
  775. colSizer = new wxBoxSizer( wxVERTICAL );
  776. rowSizer = new wxBoxSizer(wxHORIZONTAL);
  777. groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxOwnerDrawnComboBox ")),
  778. wxVERTICAL);
  779. groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
  780. wxT("Writable, with margins, sorted:")), 0,
  781. wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
  782. odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
  783. wxDefaultPosition, wxDefaultSize,
  784. m_arrItems,
  785. wxCB_SORT // wxNO_BORDER|wxCB_READONLY
  786. );
  787. odc->Append(wxT("H - Appended Item")); // test sorting in append
  788. odc->SetValue(wxT("Dot Dash"));
  789. odc->SetMargins(15, 10);
  790. groupSizer->Add( odc, 0, wxALIGN_CENTER_VERTICAL|wxALL, border );
  791. groupSizer->AddStretchSpacer();
  792. //
  793. // Readonly ODComboBox
  794. groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
  795. wxT("Read-only, big font:")), 0,
  796. wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
  797. odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
  798. wxDefaultPosition, wxDefaultSize,
  799. m_arrItems,
  800. wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
  801. );
  802. odc->SetFont(odc->GetFont().Scale(1.5));
  803. odc->SetValue(wxT("Dot Dash"));
  804. odc->SetText(wxT("Dot Dash (Testing SetText)"));
  805. groupSizer->Add( odc, 0, wxALL, border );
  806. groupSizer->AddStretchSpacer();
  807. //
  808. // Disabled ODComboBox
  809. groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Disabled:")), 0,
  810. wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
  811. odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
  812. wxDefaultPosition, wxDefaultSize,
  813. m_arrItems,
  814. wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
  815. );
  816. odc->SetValue(wxT("Dot Dash"));
  817. odc->Enable(false);
  818. groupSizer->Add( odc, 3, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
  819. rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
  820. groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxComboBox ")),
  821. wxVERTICAL);
  822. //
  823. // wxComboBox
  824. //
  825. groupSizer->Add( new wxStaticText(dlg,wxID_ANY,
  826. wxT("Writable, with margins, sorted:")), 0,
  827. wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
  828. cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
  829. wxDefaultPosition, wxDefaultSize,
  830. m_arrItems,
  831. wxCB_SORT // wxNO_BORDER|wxCB_READONLY
  832. );
  833. cb->Append(wxT("H - Appended Item")); // test sorting in append
  834. cb->SetValue(wxT("Dot Dash"));
  835. cb->SetMargins(15, 10);
  836. groupSizer->Add( cb, 0, wxALIGN_CENTER_VERTICAL|wxALL, border );
  837. groupSizer->AddStretchSpacer();
  838. //
  839. // Readonly wxComboBox
  840. groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
  841. wxT("Read-only, big font:")), 0,
  842. wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
  843. cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
  844. wxDefaultPosition, wxDefaultSize,
  845. m_arrItems,
  846. wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
  847. );
  848. cb->SetFont(cb->GetFont().Scale(1.5));
  849. cb->SetValue(wxT("Dot Dash"));
  850. groupSizer->Add( cb, 0, wxALL, border );
  851. groupSizer->AddStretchSpacer();
  852. //
  853. // Disabled wxComboBox
  854. groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Disabled:")), 0,
  855. wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
  856. cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
  857. wxDefaultPosition, wxDefaultSize,
  858. m_arrItems,
  859. wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
  860. );
  861. cb->SetValue(wxT("Dot Dash"));
  862. cb->Enable(false);
  863. groupSizer->Add( cb, 3, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
  864. rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
  865. colSizer->Add( rowSizer, 1, wxEXPAND|wxALL, border );
  866. dlg->SetSizer( colSizer );
  867. colSizer->SetSizeHints( dlg );
  868. dlg->SetSize(60,240);
  869. dlg->Centre();
  870. dlg->ShowModal();
  871. }
  872. MyFrame::~MyFrame()
  873. {
  874. delete wxLog::SetActiveTarget(m_logOld);
  875. }
  876. void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
  877. {
  878. // true is to force the frame to close
  879. Close(true);
  880. }
  881. void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
  882. {
  883. wxMessageBox(wxString::Format(
  884. wxT("Welcome to %s!\n")
  885. wxT("\n")
  886. wxT("This is the wxWidgets wxComboCtrl and wxOwnerDrawnComboBox sample\n")
  887. wxT("running under %s."),
  888. wxVERSION_STRING,
  889. wxGetOsDescription().c_str()
  890. ),
  891. wxT("About wxComboCtrl sample"),
  892. wxOK | wxICON_INFORMATION,
  893. this);
  894. }
  895. void MyFrame::OnIdle(wxIdleEvent& event)
  896. {
  897. // This code is useful for debugging focus problems
  898. // (which are plentiful when dealing with popup windows).
  899. #if 0
  900. static wxWindow* lastFocus = (wxWindow*) NULL;
  901. wxWindow* curFocus = ::wxWindow::FindFocus();
  902. if ( curFocus != lastFocus )
  903. {
  904. const wxChar* className = wxT("<none>");
  905. if ( curFocus )
  906. className = curFocus->GetClassInfo()->GetClassName();
  907. lastFocus = curFocus;
  908. wxLogDebug( wxT("FOCUSED: %s %X"),
  909. className,
  910. (unsigned int)curFocus);
  911. }
  912. #endif
  913. event.Skip();
  914. }