add support for persistent controls
[wxWidgets.git] / samples / widgets / widgets.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Program: wxWidgets Widgets Sample
3 // Name: samples/widgets/widgets.cpp
4 // Purpose: Sample showing most of the simple wxWidgets widgets
5 // Author: Vadim Zeitlin
6 // Created: 27.03.01
7 // Id: $Id$
8 // Copyright: (c) 2001 Vadim Zeitlin
9 // License: wxWindows license
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
28 #ifndef WX_PRECOMP
29 #include "wx/app.h"
30 #include "wx/log.h"
31 #include "wx/frame.h"
32 #include "wx/menu.h"
33 #include "wx/image.h"
34
35 #include "wx/button.h"
36 #include "wx/checkbox.h"
37 #include "wx/listbox.h"
38 #include "wx/statbox.h"
39 #include "wx/stattext.h"
40 #include "wx/textctrl.h"
41 #include "wx/msgdlg.h"
42 #endif
43
44 #include "wx/sysopt.h"
45 #include "wx/bookctrl.h"
46 #include "wx/treebook.h"
47 #include "wx/sizer.h"
48 #include "wx/colordlg.h"
49 #include "wx/fontdlg.h"
50 #include "wx/textdlg.h"
51 #include "wx/imaglist.h"
52 #include "wx/wupdlock.h"
53
54 #include "wx/persist/toplevel.h"
55 #include "wx/persist/treebook.h"
56
57 #include "widgets.h"
58
59 #include "../sample.xpm"
60
61 // ----------------------------------------------------------------------------
62 // constants
63 // ----------------------------------------------------------------------------
64
65 // control ids
66 enum
67 {
68 Widgets_ClearLog = 100,
69 Widgets_Quit,
70
71 Widgets_BookCtrl,
72
73 #if wxUSE_TOOLTIPS
74 Widgets_SetTooltip,
75 #endif // wxUSE_TOOLTIPS
76 Widgets_SetFgColour,
77 Widgets_SetBgColour,
78 Widgets_SetFont,
79 Widgets_Enable,
80
81 Widgets_BorderNone,
82 Widgets_BorderStatic,
83 Widgets_BorderSimple,
84 Widgets_BorderRaised,
85 Widgets_BorderSunken,
86 Widgets_BorderDouble,
87 Widgets_BorderDefault,
88
89 Widgets_GlobalBusyCursor,
90 Widgets_BusyCursor,
91
92 Widgets_GoToPage,
93 Widgets_GoToPageLast = Widgets_GoToPage + 100,
94
95
96 TextEntry_Begin,
97 TextEntry_DisableAutoComplete = TextEntry_Begin,
98 TextEntry_AutoCompleteFixed,
99 TextEntry_AutoCompleteFilenames,
100 TextEntry_End
101 };
102
103 const wxChar *WidgetsCategories[MAX_PAGES] = {
104 #if defined(__WXUNIVERSAL__)
105 wxT("Universal"),
106 #else
107 wxT("Native"),
108 #endif
109 wxT("Generic"),
110 wxT("Pickers"),
111 wxT("Comboboxes"),
112 wxT("With items"),
113 wxT("Editable"),
114 wxT("Books"),
115 wxT("All controls")
116 };
117
118 // ----------------------------------------------------------------------------
119 // our classes
120 // ----------------------------------------------------------------------------
121
122 // Define a new application type, each program should derive a class from wxApp
123 class WidgetsApp : public wxApp
124 {
125 public:
126 // override base class virtuals
127 // ----------------------------
128
129 // this one is called on application startup and is a good place for the app
130 // initialization (doing it here and not in the ctor allows to have an error
131 // return: if OnInit() returns false, the application terminates)
132 virtual bool OnInit();
133 };
134
135 // Define a new frame type: this is going to be our main frame
136 class WidgetsFrame : public wxFrame
137 {
138 public:
139 // ctor(s) and dtor
140 WidgetsFrame(const wxString& title);
141 virtual ~WidgetsFrame();
142
143 protected:
144 // event handlers
145 #if USE_LOG
146 void OnButtonClearLog(wxCommandEvent& event);
147 #endif // USE_LOG
148 void OnExit(wxCommandEvent& event);
149
150 #if wxUSE_MENUS
151 void OnPageChanging(WidgetsBookCtrlEvent& event);
152 void OnPageChanged(WidgetsBookCtrlEvent& event);
153 void OnGoToPage(wxCommandEvent& event);
154
155 #if wxUSE_TOOLTIPS
156 void OnSetTooltip(wxCommandEvent& event);
157 #endif // wxUSE_TOOLTIPS
158 void OnSetFgCol(wxCommandEvent& event);
159 void OnSetBgCol(wxCommandEvent& event);
160 void OnSetFont(wxCommandEvent& event);
161 void OnEnable(wxCommandEvent& event);
162 void OnSetBorder(wxCommandEvent& event);
163
164 void OnToggleGlobalBusyCursor(wxCommandEvent& event);
165 void OnToggleBusyCursor(wxCommandEvent& event);
166
167 void OnDisableAutoComplete(wxCommandEvent& event);
168 void OnAutoCompleteFixed(wxCommandEvent& event);
169 void OnAutoCompleteFilenames(wxCommandEvent& event);
170
171 void OnUpdateTextUI(wxUpdateUIEvent& event)
172 {
173 event.Enable( CurrentPage()->GetTextEntry() != NULL );
174 }
175 #endif // wxUSE_MENUS
176
177 // initialize the book: add all pages to it
178 void InitBook();
179
180 // return the currently selected page (never NULL)
181 WidgetsPage *CurrentPage();
182
183 private:
184 // the panel containing everything
185 wxPanel *m_panel;
186
187 #if USE_LOG
188 // the listbox for logging messages
189 wxListBox *m_lboxLog;
190
191 // the log target we use to redirect messages to the listbox
192 wxLog *m_logTarget;
193 #endif // USE_LOG
194
195 // the book containing the test pages
196 WidgetsBookCtrl *m_book;
197
198 #if wxUSE_MENUS
199 // last chosen fg/bg colours and font
200 wxColour m_colFg,
201 m_colBg;
202 wxFont m_font;
203 #endif // wxUSE_MENUS
204
205 // any class wishing to process wxWidgets events must use this macro
206 DECLARE_EVENT_TABLE()
207 };
208
209 #if USE_LOG
210 // A log target which just redirects the messages to a listbox
211 class LboxLogger : public wxLog
212 {
213 public:
214 LboxLogger(wxListBox *lbox, wxLog *logOld)
215 {
216 m_lbox = lbox;
217 //m_lbox->Disable(); -- looks ugly under MSW
218 m_logOld = logOld;
219 }
220
221 virtual ~LboxLogger()
222 {
223 wxLog::SetActiveTarget(m_logOld);
224 }
225
226 private:
227 // implement sink functions
228 virtual void DoLog(wxLogLevel level, const wxString& str, time_t t)
229 {
230 // don't put trace messages into listbox or we can get into infinite
231 // recursion
232 if ( level == wxLOG_Trace )
233 {
234 if ( m_logOld )
235 {
236 // cast is needed to call protected method
237 ((LboxLogger *)m_logOld)->DoLog(level, str, t);
238 }
239 }
240 else
241 {
242 wxLog::DoLog(level, str, t);
243 }
244 }
245
246 virtual void DoLogString(const wxString& str, time_t WXUNUSED(t))
247 {
248 wxString msg;
249 TimeStamp(&msg);
250 msg += str;
251
252 #ifdef __WXUNIVERSAL__
253 m_lbox->AppendAndEnsureVisible(msg);
254 #else // other ports don't have this method yet
255 m_lbox->Append(msg);
256 m_lbox->SetFirstItem(m_lbox->GetCount() - 1);
257 #endif
258 }
259
260 // the control we use
261 wxListBox *m_lbox;
262
263 // the old log target
264 wxLog *m_logOld;
265 };
266 #endif // USE_LOG
267
268 // array of pages
269 WX_DEFINE_ARRAY_PTR(WidgetsPage *, ArrayWidgetsPage);
270
271 // ----------------------------------------------------------------------------
272 // misc macros
273 // ----------------------------------------------------------------------------
274
275 IMPLEMENT_APP(WidgetsApp)
276
277 // ----------------------------------------------------------------------------
278 // event tables
279 // ----------------------------------------------------------------------------
280
281 BEGIN_EVENT_TABLE(WidgetsFrame, wxFrame)
282 #if USE_LOG
283 EVT_BUTTON(Widgets_ClearLog, WidgetsFrame::OnButtonClearLog)
284 #endif // USE_LOG
285 EVT_BUTTON(Widgets_Quit, WidgetsFrame::OnExit)
286
287 #if wxUSE_TOOLTIPS
288 EVT_MENU(Widgets_SetTooltip, WidgetsFrame::OnSetTooltip)
289 #endif // wxUSE_TOOLTIPS
290
291 #if wxUSE_MENUS
292 EVT_WIDGETS_PAGE_CHANGING(wxID_ANY, WidgetsFrame::OnPageChanging)
293 EVT_MENU_RANGE(Widgets_GoToPage, Widgets_GoToPageLast,
294 WidgetsFrame::OnGoToPage)
295
296 EVT_MENU(Widgets_SetFgColour, WidgetsFrame::OnSetFgCol)
297 EVT_MENU(Widgets_SetBgColour, WidgetsFrame::OnSetBgCol)
298 EVT_MENU(Widgets_SetFont, WidgetsFrame::OnSetFont)
299 EVT_MENU(Widgets_Enable, WidgetsFrame::OnEnable)
300
301 EVT_MENU_RANGE(Widgets_BorderNone, Widgets_BorderDefault,
302 WidgetsFrame::OnSetBorder)
303
304 EVT_MENU(Widgets_GlobalBusyCursor, WidgetsFrame::OnToggleGlobalBusyCursor)
305 EVT_MENU(Widgets_BusyCursor, WidgetsFrame::OnToggleBusyCursor)
306
307 EVT_MENU(TextEntry_DisableAutoComplete, WidgetsFrame::OnDisableAutoComplete)
308 EVT_MENU(TextEntry_AutoCompleteFixed, WidgetsFrame::OnAutoCompleteFixed)
309 EVT_MENU(TextEntry_AutoCompleteFilenames, WidgetsFrame::OnAutoCompleteFilenames)
310
311 EVT_UPDATE_UI_RANGE(TextEntry_Begin, TextEntry_End - 1,
312 WidgetsFrame::OnUpdateTextUI)
313
314 EVT_MENU(wxID_EXIT, WidgetsFrame::OnExit)
315 #endif // wxUSE_MENUS
316 END_EVENT_TABLE()
317
318 // ============================================================================
319 // implementation
320 // ============================================================================
321
322 // ----------------------------------------------------------------------------
323 // app class
324 // ----------------------------------------------------------------------------
325
326 bool WidgetsApp::OnInit()
327 {
328 if ( !wxApp::OnInit() )
329 return false;
330
331 SetVendorName("wxWidgets_Samples");
332
333 // the reason for having these ifdef's is that I often run two copies of
334 // this sample side by side and it is useful to see which one is which
335 wxString title;
336 #if defined(__WXUNIVERSAL__)
337 title = _T("wxUniv/");
338 #endif
339
340 #if defined(__WXMSW__)
341 title += _T("wxMSW");
342 #elif defined(__WXGTK__)
343 title += _T("wxGTK");
344 #elif defined(__WXMAC__)
345 title += _T("wxMAC");
346 #elif defined(__WXMOTIF__)
347 title += _T("wxMOTIF");
348 #elif __WXPALMOS5__
349 title += _T("wxPALMOS5");
350 #elif __WXPALMOS6__
351 title += _T("wxPALMOS6");
352 #else
353 title += _T("wxWidgets");
354 #endif
355
356 wxFrame *frame = new WidgetsFrame(title + _T(" widgets demo"));
357 frame->Show();
358
359 return true;
360 }
361
362 // ----------------------------------------------------------------------------
363 // WidgetsFrame construction
364 // ----------------------------------------------------------------------------
365
366 WidgetsFrame::WidgetsFrame(const wxString& title)
367 : wxFrame(NULL, wxID_ANY, title)
368 {
369 SetName("Main");
370 const bool sizeSet = wxPersistenceManager::Get().RegisterAndRestore(this);
371
372 // set the frame icon
373 SetIcon(wxICON(sample));
374
375 // init everything
376 #if USE_LOG
377 m_lboxLog = NULL;
378 m_logTarget = NULL;
379 #endif // USE_LOG
380 m_book = NULL;
381
382 #if wxUSE_MENUS
383 // create the menubar
384 wxMenuBar *mbar = new wxMenuBar;
385 wxMenu *menuWidget = new wxMenu;
386 #if wxUSE_TOOLTIPS
387 menuWidget->Append(Widgets_SetTooltip, _T("Set &tooltip...\tCtrl-T"));
388 menuWidget->AppendSeparator();
389 #endif // wxUSE_TOOLTIPS
390 menuWidget->Append(Widgets_SetFgColour, _T("Set &foreground...\tCtrl-F"));
391 menuWidget->Append(Widgets_SetBgColour, _T("Set &background...\tCtrl-B"));
392 menuWidget->Append(Widgets_SetFont, _T("Set f&ont...\tCtrl-O"));
393 menuWidget->AppendCheckItem(Widgets_Enable, _T("&Enable/disable\tCtrl-E"));
394
395 wxMenu *menuBorders = new wxMenu;
396 menuBorders->AppendRadioItem(Widgets_BorderDefault, _T("De&fault\tCtrl-Shift-9"));
397 menuBorders->AppendRadioItem(Widgets_BorderNone, _T("&None\tCtrl-Shift-0"));
398 menuBorders->AppendRadioItem(Widgets_BorderSimple, _T("&Simple\tCtrl-Shift-1"));
399 menuBorders->AppendRadioItem(Widgets_BorderDouble, _T("&Double\tCtrl-Shift-2"));
400 menuBorders->AppendRadioItem(Widgets_BorderStatic, _T("Stati&c\tCtrl-Shift-3"));
401 menuBorders->AppendRadioItem(Widgets_BorderRaised, _T("&Raised\tCtrl-Shift-4"));
402 menuBorders->AppendRadioItem(Widgets_BorderSunken, _T("S&unken\tCtrl-Shift-5"));
403 menuWidget->AppendSubMenu(menuBorders, _T("Set &border"));
404
405 menuWidget->AppendSeparator();
406 menuWidget->AppendCheckItem(Widgets_GlobalBusyCursor,
407 _T("Toggle &global busy cursor\tCtrl-Shift-U"));
408 menuWidget->AppendCheckItem(Widgets_BusyCursor,
409 _T("Toggle b&usy cursor\tCtrl-U"));
410
411 menuWidget->AppendSeparator();
412 menuWidget->Append(wxID_EXIT, _T("&Quit\tCtrl-Q"));
413 mbar->Append(menuWidget, _T("&Widget"));
414
415 wxMenu *menuTextEntry = new wxMenu;
416 menuTextEntry->AppendRadioItem(TextEntry_DisableAutoComplete,
417 _T("&Disable auto-completion"));
418 menuTextEntry->AppendRadioItem(TextEntry_AutoCompleteFixed,
419 _T("Fixed-&list auto-completion"));
420 menuTextEntry->AppendRadioItem(TextEntry_AutoCompleteFilenames,
421 _T("&Files names auto-completion"));
422
423 mbar->Append(menuTextEntry, _T("&Text"));
424
425 SetMenuBar(mbar);
426
427 mbar->Check(Widgets_Enable, true);
428 #endif // wxUSE_MENUS
429
430 // create controls
431 m_panel = new wxPanel(this, wxID_ANY);
432
433 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
434
435 // we have 2 panes: book with pages demonstrating the controls in the
436 // upper one and the log window with some buttons in the lower
437
438 int style = wxBK_DEFAULT;
439 // Uncomment to suppress page theme (draw in solid colour)
440 //style |= wxNB_NOPAGETHEME;
441
442 m_book = new WidgetsBookCtrl(m_panel, Widgets_BookCtrl,
443 wxDefaultPosition, wxDefaultSize,
444 style, "Widgets");
445
446 InitBook();
447
448 #ifndef __WXHANDHELD__
449 // the lower one only has the log listbox and a button to clear it
450 #if USE_LOG
451 wxSizer *sizerDown = new wxStaticBoxSizer(
452 new wxStaticBox( m_panel, wxID_ANY, _T("&Log window") ),
453 wxVERTICAL);
454
455 m_lboxLog = new wxListBox(m_panel, wxID_ANY);
456 sizerDown->Add(m_lboxLog, 1, wxGROW | wxALL, 5);
457 sizerDown->SetMinSize(100, 150);
458 #else
459 wxSizer *sizerDown = new wxBoxSizer(wxVERTICAL);
460 #endif // USE_LOG
461
462 wxBoxSizer *sizerBtns = new wxBoxSizer(wxHORIZONTAL);
463 wxButton *btn;
464 #if USE_LOG
465 btn = new wxButton(m_panel, Widgets_ClearLog, _T("Clear &log"));
466 sizerBtns->Add(btn);
467 sizerBtns->Add(10, 0); // spacer
468 #endif // USE_LOG
469 btn = new wxButton(m_panel, Widgets_Quit, _T("E&xit"));
470 sizerBtns->Add(btn);
471 sizerDown->Add(sizerBtns, 0, wxALL | wxALIGN_RIGHT, 5);
472
473 // put everything together
474 sizerTop->Add(m_book, 1, wxGROW | (wxALL & ~(wxTOP | wxBOTTOM)), 10);
475 sizerTop->Add(0, 5, 0, wxGROW); // spacer in between
476 sizerTop->Add(sizerDown, 0, wxGROW | (wxALL & ~wxTOP), 10);
477
478 #else // !__WXHANDHELD__/__WXHANDHELD__
479
480 sizerTop->Add(m_book, 1, wxGROW | wxALL );
481
482 #endif // __WXHANDHELD__
483
484 m_panel->SetSizer(sizerTop);
485
486 const wxSize sizeMin = m_panel->GetBestSize();
487 if ( !sizeSet )
488 SetClientSize(sizeMin);
489 SetMinClientSize(sizeMin);
490
491 #if USE_LOG && !defined(__WXCOCOA__)
492 // wxCocoa's listbox is too flakey to use for logging right now
493 // now that everything is created we can redirect the log messages to the
494 // listbox
495 m_logTarget = new LboxLogger(m_lboxLog, wxLog::GetActiveTarget());
496 wxLog::SetActiveTarget(m_logTarget);
497 #endif
498 }
499
500 void WidgetsFrame::InitBook()
501 {
502 #if USE_ICONS_IN_BOOK
503 wxImageList *imageList = new wxImageList(ICON_SIZE, ICON_SIZE);
504
505 wxImage img(sample_xpm);
506 imageList->Add(wxBitmap(img.Scale(ICON_SIZE, ICON_SIZE)));
507 #else
508 wxImageList *imageList = NULL;
509 #endif
510
511 #if !USE_TREEBOOK
512 WidgetsBookCtrl *books[MAX_PAGES];
513 #endif
514
515 ArrayWidgetsPage pages[MAX_PAGES];
516 wxArrayString labels[MAX_PAGES];
517
518 wxMenu *menuPages = new wxMenu;
519 unsigned int nPage = 0, nFKey = 0;
520 int cat, imageId = 1;
521
522 // we need to first create all pages and only then add them to the book
523 // as we need the image list first
524 //
525 // we also construct the pages menu during this first iteration
526 for ( cat = 0; cat < MAX_PAGES; cat++ )
527 {
528 #if USE_TREEBOOK
529 nPage++; // increase for parent page
530 #else
531 books[cat] = new WidgetsBookCtrl(m_book,
532 wxID_ANY,
533 wxDefaultPosition,
534 wxDefaultSize,
535 wxBK_DEFAULT);
536 #endif
537
538 for ( WidgetsPageInfo *info = WidgetsPage::ms_widgetPages;
539 info;
540 info = info->GetNext() )
541 {
542 if( (info->GetCategories() & ( 1 << cat )) == 0)
543 continue;
544
545 WidgetsPage *page = (*info->GetCtor())(
546 #if USE_TREEBOOK
547 m_book
548 #else
549 books[cat]
550 #endif
551 , imageList);
552 pages[cat].Add(page);
553
554 labels[cat].Add(info->GetLabel());
555 if ( cat == ALL_PAGE )
556 {
557 wxString radioLabel(info->GetLabel());
558 nFKey++;
559 if ( nFKey <= 12 )
560 {
561 radioLabel << wxT("\tF" ) << nFKey;
562 }
563
564 menuPages->AppendRadioItem(
565 Widgets_GoToPage + nPage,
566 radioLabel
567 );
568 #if !USE_TREEBOOK
569 // consider only for book in book architecture
570 nPage++;
571 #endif
572 }
573
574 #if USE_TREEBOOK
575 // consider only for treebook architecture (with subpages)
576 nPage++;
577 #endif
578 }
579 }
580
581 GetMenuBar()->Append(menuPages, _T("&Page"));
582
583 #if USE_ICONS_IN_BOOK
584 m_book->AssignImageList(imageList);
585 #endif
586
587 for ( cat = 0; cat < MAX_PAGES; cat++ )
588 {
589 #if USE_TREEBOOK
590 m_book->AddPage(NULL,WidgetsCategories[cat],false,0);
591 #else
592 m_book->AddPage(books[cat],WidgetsCategories[cat],false,0);
593 #if USE_ICONS_IN_BOOK
594 books[cat]->SetImageList(imageList);
595 #endif
596 #endif
597
598 // now do add them
599 size_t count = pages[cat].GetCount();
600 for ( size_t n = 0; n < count; n++ )
601 {
602 #if USE_TREEBOOK
603 m_book->AddSubPage
604 #else
605 books[cat]->AddPage
606 #endif
607 (
608 pages[cat][n],
609 labels[cat][n],
610 false, // don't select
611 imageId++
612 );
613 }
614 }
615
616 Connect( wxID_ANY,
617 wxEVT_COMMAND_WIDGETS_PAGE_CHANGED,
618 wxWidgetsbookEventHandler(WidgetsFrame::OnPageChanged) );
619
620 const bool pageSet = wxPersistenceManager::Get().RegisterAndRestore(m_book);
621
622 #if USE_TREEBOOK
623 // for treebook page #0 is empty parent page only so select the first page
624 // with some contents
625 if ( !pageSet )
626 m_book->SetSelection(1);
627
628 // but ensure that the top of the tree is shown nevertheless
629 wxTreeCtrl * const tree = m_book->GetTreeCtrl();
630
631 wxTreeItemIdValue cookie;
632 tree->EnsureVisible(tree->GetFirstChild(tree->GetRootItem(), cookie));
633 #else
634 if ( !pageSet )
635 {
636 // for other books set selection twice to force connected event handler
637 // to force lazy creation of initial visible content
638 m_book->SetSelection(1);
639 m_book->SetSelection(0);
640 }
641 #endif // USE_TREEBOOK
642 }
643
644 WidgetsPage *WidgetsFrame::CurrentPage()
645 {
646 wxWindow *page = m_book->GetCurrentPage();
647
648 #if !USE_TREEBOOK
649 WidgetsBookCtrl *subBook = wxStaticCast(page, WidgetsBookCtrl);
650 wxCHECK_MSG( subBook, NULL, _T("no WidgetsBookCtrl?") );
651
652 page = subBook->GetCurrentPage();
653 #endif // !USE_TREEBOOK
654
655 return wxStaticCast(page, WidgetsPage);
656 }
657
658 WidgetsFrame::~WidgetsFrame()
659 {
660 #if USE_LOG
661 delete m_logTarget;
662 #endif // USE_LOG
663 }
664
665 // ----------------------------------------------------------------------------
666 // WidgetsFrame event handlers
667 // ----------------------------------------------------------------------------
668
669 void WidgetsFrame::OnExit(wxCommandEvent& WXUNUSED(event))
670 {
671 Close();
672 }
673
674 #if USE_LOG
675 void WidgetsFrame::OnButtonClearLog(wxCommandEvent& WXUNUSED(event))
676 {
677 m_lboxLog->Clear();
678 }
679 #endif // USE_LOG
680
681 #if wxUSE_MENUS
682
683 void WidgetsFrame::OnPageChanging(WidgetsBookCtrlEvent& event)
684 {
685 #if USE_TREEBOOK
686 // don't allow selection of entries without pages (categories)
687 if ( !m_book->GetPage(event.GetSelection()) )
688 event.Veto();
689 #else
690 wxUnusedVar(event);
691 #endif
692 }
693
694 void WidgetsFrame::OnPageChanged(WidgetsBookCtrlEvent& event)
695 {
696 const int sel = event.GetSelection();
697
698 // adjust "Page" menu selection
699 wxMenuItem *item = GetMenuBar()->FindItem(Widgets_GoToPage + sel);
700 if ( item )
701 item->Check();
702
703 GetMenuBar()->Check(Widgets_BusyCursor, false);
704
705 // create the pages on demand, otherwise the sample startup is too slow as
706 // it creates hundreds of controls
707 WidgetsPage *page = CurrentPage();
708 if ( page->GetChildren().empty() )
709 {
710 wxWindowUpdateLocker noUpdates(page);
711 page->CreateContent();
712 //page->Layout();
713 page->GetSizer()->Fit(page);
714
715 WidgetsBookCtrl *book = wxStaticCast(page->GetParent(), WidgetsBookCtrl);
716 wxSize size;
717 for ( size_t i = 0; i < book->GetPageCount(); ++i )
718 {
719 wxWindow *page = book->GetPage(i);
720 if ( page )
721 {
722 size.IncTo(page->GetSize());
723 }
724 }
725 page->SetSize(size);
726 }
727
728 event.Skip();
729 }
730
731 void WidgetsFrame::OnGoToPage(wxCommandEvent& event)
732 {
733 #if USE_TREEBOOK
734 m_book->SetSelection(event.GetId() - Widgets_GoToPage);
735 #else
736 m_book->SetSelection(m_book->GetPageCount()-1);
737 WidgetsBookCtrl *book = wxStaticCast(m_book->GetCurrentPage(), WidgetsBookCtrl);
738 book->SetSelection(event.GetId() - Widgets_GoToPage);
739 #endif
740 }
741
742 #if wxUSE_TOOLTIPS
743
744 void WidgetsFrame::OnSetTooltip(wxCommandEvent& WXUNUSED(event))
745 {
746 static wxString s_tip = _T("This is a tooltip");
747
748 wxTextEntryDialog dialog
749 (
750 this,
751 _T("Tooltip text (may use \\n, leave empty to remove): "),
752 _T("Widgets sample"),
753 s_tip
754 );
755
756 if ( dialog.ShowModal() != wxID_OK )
757 return;
758
759 s_tip = dialog.GetValue();
760 s_tip.Replace(_T("\\n"), _T("\n"));
761
762 WidgetsPage *page = CurrentPage();
763
764 page->GetWidget()->SetToolTip(s_tip);
765
766 wxControl *ctrl2 = page->GetWidget2();
767 if ( ctrl2 )
768 ctrl2->SetToolTip(s_tip);
769 }
770
771 #endif // wxUSE_TOOLTIPS
772
773 void WidgetsFrame::OnSetFgCol(wxCommandEvent& WXUNUSED(event))
774 {
775 #if wxUSE_COLOURDLG
776 // allow for debugging the default colour the first time this is called
777 WidgetsPage *page = CurrentPage();
778
779 if (!m_colFg.Ok())
780 m_colFg = page->GetForegroundColour();
781
782 wxColour col = wxGetColourFromUser(this, m_colFg);
783 if ( !col.Ok() )
784 return;
785
786 m_colFg = col;
787
788 page->GetWidget()->SetForegroundColour(m_colFg);
789 page->GetWidget()->Refresh();
790
791 wxControl *ctrl2 = page->GetWidget2();
792 if ( ctrl2 )
793 {
794 ctrl2->SetForegroundColour(m_colFg);
795 ctrl2->Refresh();
796 }
797 #else
798 wxLogMessage(_T("Colour selection dialog not available in current build."));
799 #endif
800 }
801
802 void WidgetsFrame::OnSetBgCol(wxCommandEvent& WXUNUSED(event))
803 {
804 #if wxUSE_COLOURDLG
805 WidgetsPage *page = CurrentPage();
806
807 if ( !m_colBg.Ok() )
808 m_colBg = page->GetBackgroundColour();
809
810 wxColour col = wxGetColourFromUser(this, m_colBg);
811 if ( !col.Ok() )
812 return;
813
814 m_colBg = col;
815
816 page->GetWidget()->SetBackgroundColour(m_colBg);
817 page->GetWidget()->Refresh();
818
819 wxControl *ctrl2 = page->GetWidget2();
820 if ( ctrl2 )
821 {
822 ctrl2->SetBackgroundColour(m_colFg);
823 ctrl2->Refresh();
824 }
825 #else
826 wxLogMessage(_T("Colour selection dialog not available in current build."));
827 #endif
828 }
829
830 void WidgetsFrame::OnSetFont(wxCommandEvent& WXUNUSED(event))
831 {
832 #if wxUSE_FONTDLG
833 WidgetsPage *page = CurrentPage();
834
835 if (!m_font.Ok())
836 m_font = page->GetFont();
837
838 wxFont font = wxGetFontFromUser(this, m_font);
839 if ( !font.Ok() )
840 return;
841
842 m_font = font;
843
844 page->GetWidget()->SetFont(m_font);
845 page->GetWidget()->Refresh();
846
847 wxControl *ctrl2 = page->GetWidget2();
848 if ( ctrl2 )
849 {
850 ctrl2->SetFont(m_font);
851 ctrl2->Refresh();
852 }
853 #else
854 wxLogMessage(_T("Font selection dialog not available in current build."));
855 #endif
856 }
857
858 void WidgetsFrame::OnEnable(wxCommandEvent& event)
859 {
860 CurrentPage()->GetWidget()->Enable(event.IsChecked());
861 if (CurrentPage()->GetWidget2())
862 CurrentPage()->GetWidget2()->Enable(event.IsChecked());
863 }
864
865 void WidgetsFrame::OnSetBorder(wxCommandEvent& event)
866 {
867 int border;
868 switch ( event.GetId() )
869 {
870 case Widgets_BorderNone: border = wxBORDER_NONE; break;
871 case Widgets_BorderStatic: border = wxBORDER_STATIC; break;
872 case Widgets_BorderSimple: border = wxBORDER_SIMPLE; break;
873 case Widgets_BorderRaised: border = wxBORDER_RAISED; break;
874 case Widgets_BorderSunken: border = wxBORDER_SUNKEN; break;
875 case Widgets_BorderDouble: border = wxBORDER_DOUBLE; break;
876
877 default:
878 wxFAIL_MSG( _T("unknown border style") );
879 // fall through
880
881 case Widgets_BorderDefault: border = wxBORDER_DEFAULT; break;
882 }
883
884 WidgetsPage::ms_defaultFlags &= ~wxBORDER_MASK;
885 WidgetsPage::ms_defaultFlags |= border;
886
887 WidgetsPage *page = CurrentPage();
888
889 page->RecreateWidget();
890 }
891
892 void WidgetsFrame::OnToggleGlobalBusyCursor(wxCommandEvent& event)
893 {
894 if ( event.IsChecked() )
895 wxBeginBusyCursor();
896 else
897 wxEndBusyCursor();
898 }
899
900 void WidgetsFrame::OnToggleBusyCursor(wxCommandEvent& event)
901 {
902 CurrentPage()->GetWidget()->SetCursor(*(event.IsChecked()
903 ? wxHOURGLASS_CURSOR
904 : wxSTANDARD_CURSOR));
905 }
906
907 void WidgetsFrame::OnDisableAutoComplete(wxCommandEvent& WXUNUSED(event))
908 {
909 wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
910 wxCHECK_RET( entry, "menu item should be disabled" );
911
912 if ( entry->AutoComplete(wxArrayString()) )
913 wxLogMessage("Disabled auto completion.");
914 else
915 wxLogMessage("AutoComplete() failed.");
916 }
917
918 void WidgetsFrame::OnAutoCompleteFixed(wxCommandEvent& WXUNUSED(event))
919 {
920 wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
921 wxCHECK_RET( entry, "menu item should be disabled" );
922
923 wxArrayString completion_choices;
924
925 // add a few strings so a completion occurs on any letter typed
926 for ( char idxc = 'a'; idxc < 'z'; ++idxc )
927 completion_choices.push_back(wxString::Format("%c%c", idxc, idxc));
928
929 completion_choices.push_back("is this string for test?");
930 completion_choices.push_back("this is a test string");
931 completion_choices.push_back("this is another test string");
932 completion_choices.push_back("this string is for test");
933
934 if ( entry->AutoComplete(completion_choices) )
935 wxLogMessage("Enabled auto completion of a set of fixed strings.");
936 else
937 wxLogMessage("AutoComplete() failed.");
938 }
939
940 void WidgetsFrame::OnAutoCompleteFilenames(wxCommandEvent& WXUNUSED(event))
941 {
942 wxTextEntryBase *entry = CurrentPage()->GetTextEntry();
943 wxCHECK_RET( entry, "menu item should be disabled" );
944
945 if ( entry->AutoCompleteFileNames() )
946 wxLogMessage("Enable auto completion of file names.");
947 else
948 wxLogMessage("AutoCompleteFileNames() failed.");
949 }
950
951 #endif // wxUSE_MENUS
952
953 // ----------------------------------------------------------------------------
954 // WidgetsPageInfo
955 // ----------------------------------------------------------------------------
956
957 WidgetsPageInfo::WidgetsPageInfo(Constructor ctor, const wxChar *label, int categories)
958 : m_label(label)
959 , m_categories(categories)
960 {
961 m_ctor = ctor;
962
963 m_next = NULL;
964
965 // dummy sorting: add and immediately sort in the list according to label
966 if ( WidgetsPage::ms_widgetPages )
967 {
968 WidgetsPageInfo *node_prev = WidgetsPage::ms_widgetPages;
969 if ( wxStrcmp(label, node_prev->GetLabel().c_str()) < 0 )
970 {
971 // add as first
972 m_next = node_prev;
973 WidgetsPage::ms_widgetPages = this;
974 }
975 else
976 {
977 WidgetsPageInfo *node_next;
978 do
979 {
980 node_next = node_prev->GetNext();
981 if ( node_next )
982 {
983 // add if between two
984 if ( wxStrcmp(label, node_next->GetLabel().c_str()) < 0 )
985 {
986 node_prev->SetNext(this);
987 m_next = node_next;
988 // force to break loop
989 node_next = NULL;
990 }
991 }
992 else
993 {
994 // add as last
995 node_prev->SetNext(this);
996 m_next = node_next;
997 }
998 node_prev = node_next;
999 }
1000 while ( node_next );
1001 }
1002 }
1003 else
1004 {
1005 // add when first
1006 WidgetsPage::ms_widgetPages = this;
1007 }
1008 }
1009
1010 // ----------------------------------------------------------------------------
1011 // WidgetsPage
1012 // ----------------------------------------------------------------------------
1013
1014 int WidgetsPage::ms_defaultFlags = wxBORDER_DEFAULT;
1015 WidgetsPageInfo *WidgetsPage::ms_widgetPages = NULL;
1016
1017 WidgetsPage::WidgetsPage(WidgetsBookCtrl *book,
1018 wxImageList *imaglist,
1019 const char *const icon[])
1020 : wxPanel(book, wxID_ANY,
1021 wxDefaultPosition, wxDefaultSize,
1022 wxNO_FULL_REPAINT_ON_RESIZE |
1023 wxCLIP_CHILDREN |
1024 wxTAB_TRAVERSAL)
1025 {
1026 #if USE_ICONS_IN_BOOK
1027 imaglist->Add(wxBitmap(wxImage(icon).Scale(ICON_SIZE, ICON_SIZE)));
1028 #else
1029 wxUnusedVar(imaglist);
1030 wxUnusedVar(icon);
1031 #endif
1032 }
1033
1034 wxSizer *WidgetsPage::CreateSizerWithText(wxControl *control,
1035 wxWindowID id,
1036 wxTextCtrl **ppText)
1037 {
1038 wxSizer *sizerRow = new wxBoxSizer(wxHORIZONTAL);
1039 wxTextCtrl *text = new wxTextCtrl(this, id, wxEmptyString,
1040 wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
1041
1042 sizerRow->Add(control, 0, wxRIGHT | wxALIGN_CENTRE_VERTICAL, 5);
1043 sizerRow->Add(text, 1, wxLEFT | wxALIGN_CENTRE_VERTICAL, 5);
1044
1045 if ( ppText )
1046 *ppText = text;
1047
1048 return sizerRow;
1049 }
1050
1051 // create a sizer containing a label and a text ctrl
1052 wxSizer *WidgetsPage::CreateSizerWithTextAndLabel(const wxString& label,
1053 wxWindowID id,
1054 wxTextCtrl **ppText)
1055 {
1056 return CreateSizerWithText(new wxStaticText(this, wxID_ANY, label),
1057 id, ppText);
1058 }
1059
1060 // create a sizer containing a button and a text ctrl
1061 wxSizer *WidgetsPage::CreateSizerWithTextAndButton(wxWindowID idBtn,
1062 const wxString& label,
1063 wxWindowID id,
1064 wxTextCtrl **ppText)
1065 {
1066 return CreateSizerWithText(new wxButton(this, idBtn, label), id, ppText);
1067 }
1068
1069 wxCheckBox *WidgetsPage::CreateCheckBoxAndAddToSizer(wxSizer *sizer,
1070 const wxString& label,
1071 wxWindowID id)
1072 {
1073 wxCheckBox *checkbox = new wxCheckBox(this, id, label);
1074 sizer->Add(checkbox, 0, wxLEFT | wxRIGHT, 5);
1075 sizer->Add(0, 2, 0, wxGROW); // spacer
1076
1077 return checkbox;
1078 }