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
7 // Copyright: (c) 2001 Vadim Zeitlin
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ============================================================================
13 // ============================================================================
15 // ----------------------------------------------------------------------------
17 // ----------------------------------------------------------------------------
19 // for compilers that support precompilation, includes "wx/wx.h".
20 #include "wx/wxprec.h"
26 // for all others, include the necessary headers
34 #include "wx/button.h"
35 #include "wx/checkbox.h"
36 #include "wx/listbox.h"
37 #include "wx/statbox.h"
38 #include "wx/stattext.h"
39 #include "wx/textctrl.h"
40 #include "wx/msgdlg.h"
43 #include "wx/sysopt.h"
44 #include "wx/bookctrl.h"
45 #include "wx/treebook.h"
47 #include "wx/colordlg.h"
48 #include "wx/fontdlg.h"
49 #include "wx/textdlg.h"
50 #include "wx/imaglist.h"
51 #include "wx/wupdlock.h"
52 #include "wx/textcompleter.h"
54 #include "wx/persist/toplevel.h"
55 #include "wx/persist/treebook.h"
59 #include "../sample.xpm"
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
68 Widgets_ClearLog
= 100,
75 #endif // wxUSE_TOOLTIPS
88 Widgets_BorderDefault
,
90 Widgets_LayoutDirection
,
92 Widgets_GlobalBusyCursor
,
96 Widgets_GoToPageLast
= Widgets_GoToPage
+ 100,
100 TextEntry_DisableAutoComplete
= TextEntry_Begin
,
101 TextEntry_AutoCompleteFixed
,
102 TextEntry_AutoCompleteFilenames
,
103 TextEntry_AutoCompleteDirectories
,
104 TextEntry_AutoCompleteCustom
,
110 const wxChar
*WidgetsCategories
[MAX_PAGES
] = {
111 #if defined(__WXUNIVERSAL__)
125 // ----------------------------------------------------------------------------
127 // ----------------------------------------------------------------------------
129 // Define a new application type, each program should derive a class from wxApp
130 class WidgetsApp
: public wxApp
133 // override base class virtuals
134 // ----------------------------
136 // this one is called on application startup and is a good place for the app
137 // initialization (doing it here and not in the ctor allows to have an error
138 // return: if OnInit() returns false, the application terminates)
139 virtual bool OnInit();
142 // Define a new frame type: this is going to be our main frame
143 class WidgetsFrame
: public wxFrame
147 WidgetsFrame(const wxString
& title
);
148 virtual ~WidgetsFrame();
153 void OnButtonClearLog(wxCommandEvent
& event
);
155 void OnExit(wxCommandEvent
& event
);
158 void OnPageChanging(WidgetsBookCtrlEvent
& event
);
159 void OnPageChanged(WidgetsBookCtrlEvent
& event
);
160 void OnGoToPage(wxCommandEvent
& event
);
163 void OnSetTooltip(wxCommandEvent
& event
);
164 #endif // wxUSE_TOOLTIPS
165 void OnSetFgCol(wxCommandEvent
& event
);
166 void OnSetBgCol(wxCommandEvent
& event
);
167 void OnSetPageBg(wxCommandEvent
& event
);
168 void OnSetFont(wxCommandEvent
& event
);
169 void OnEnable(wxCommandEvent
& event
);
170 void OnSetBorder(wxCommandEvent
& event
);
172 void OnToggleLayoutDirection(wxCommandEvent
& event
);
174 void OnToggleGlobalBusyCursor(wxCommandEvent
& event
);
175 void OnToggleBusyCursor(wxCommandEvent
& event
);
177 // wxTextEntry-specific tests
178 void OnDisableAutoComplete(wxCommandEvent
& event
);
179 void OnAutoCompleteFixed(wxCommandEvent
& event
);
180 void OnAutoCompleteFilenames(wxCommandEvent
& event
);
181 void OnAutoCompleteDirectories(wxCommandEvent
& event
);
182 void OnAutoCompleteCustom(wxCommandEvent
& event
);
184 void OnSetHint(wxCommandEvent
& event
);
186 void OnUpdateTextUI(wxUpdateUIEvent
& event
)
188 event
.Enable( CurrentPage()->GetTextEntry() != NULL
);
190 #endif // wxUSE_MENUS
192 // initialize the book: add all pages to it
195 // return the currently selected page (never NULL)
196 WidgetsPage
*CurrentPage();
199 // the panel containing everything
203 // the listbox for logging messages
204 wxListBox
*m_lboxLog
;
206 // the log target we use to redirect messages to the listbox
210 // the book containing the test pages
211 WidgetsBookCtrl
*m_book
;
214 // last chosen fg/bg colours and font
218 #endif // wxUSE_MENUS
220 // any class wishing to process wxWidgets events must use this macro
221 DECLARE_EVENT_TABLE()
225 // A log target which just redirects the messages to a listbox
226 class LboxLogger
: public wxLog
229 LboxLogger(wxListBox
*lbox
, wxLog
*logOld
)
232 //m_lbox->Disable(); -- looks ugly under MSW
236 virtual ~LboxLogger()
238 wxLog::SetActiveTarget(m_logOld
);
242 // implement sink functions
243 virtual void DoLogTextAtLevel(wxLogLevel level
, const wxString
& msg
)
245 if ( level
== wxLOG_Trace
)
248 m_logOld
->LogTextAtLevel(level
, msg
);
252 #ifdef __WXUNIVERSAL__
253 m_lbox
->AppendAndEnsureVisible(msg
);
254 #else // other ports don't have this method yet
256 m_lbox
->SetFirstItem(m_lbox
->GetCount() - 1);
260 // the control we use
263 // the old log target
269 WX_DEFINE_ARRAY_PTR(WidgetsPage
*, ArrayWidgetsPage
);
271 // ----------------------------------------------------------------------------
273 // ----------------------------------------------------------------------------
275 IMPLEMENT_APP(WidgetsApp
)
277 // ----------------------------------------------------------------------------
279 // ----------------------------------------------------------------------------
281 BEGIN_EVENT_TABLE(WidgetsFrame
, wxFrame
)
283 EVT_BUTTON(Widgets_ClearLog
, WidgetsFrame::OnButtonClearLog
)
285 EVT_BUTTON(Widgets_Quit
, WidgetsFrame::OnExit
)
288 EVT_MENU(Widgets_SetTooltip
, WidgetsFrame::OnSetTooltip
)
289 #endif // wxUSE_TOOLTIPS
292 EVT_WIDGETS_PAGE_CHANGING(wxID_ANY
, WidgetsFrame::OnPageChanging
)
293 EVT_MENU_RANGE(Widgets_GoToPage
, Widgets_GoToPageLast
,
294 WidgetsFrame::OnGoToPage
)
296 EVT_MENU(Widgets_SetFgColour
, WidgetsFrame::OnSetFgCol
)
297 EVT_MENU(Widgets_SetBgColour
, WidgetsFrame::OnSetBgCol
)
298 EVT_MENU(Widgets_SetPageBg
, WidgetsFrame::OnSetPageBg
)
299 EVT_MENU(Widgets_SetFont
, WidgetsFrame::OnSetFont
)
300 EVT_MENU(Widgets_Enable
, WidgetsFrame::OnEnable
)
302 EVT_MENU_RANGE(Widgets_BorderNone
, Widgets_BorderDefault
,
303 WidgetsFrame::OnSetBorder
)
305 EVT_MENU(Widgets_LayoutDirection
, WidgetsFrame::OnToggleLayoutDirection
)
307 EVT_MENU(Widgets_GlobalBusyCursor
, WidgetsFrame::OnToggleGlobalBusyCursor
)
308 EVT_MENU(Widgets_BusyCursor
, WidgetsFrame::OnToggleBusyCursor
)
310 EVT_MENU(TextEntry_DisableAutoComplete
, WidgetsFrame::OnDisableAutoComplete
)
311 EVT_MENU(TextEntry_AutoCompleteFixed
, WidgetsFrame::OnAutoCompleteFixed
)
312 EVT_MENU(TextEntry_AutoCompleteFilenames
, WidgetsFrame::OnAutoCompleteFilenames
)
313 EVT_MENU(TextEntry_AutoCompleteDirectories
, WidgetsFrame::OnAutoCompleteDirectories
)
314 EVT_MENU(TextEntry_AutoCompleteCustom
, WidgetsFrame::OnAutoCompleteCustom
)
316 EVT_MENU(TextEntry_SetHint
, WidgetsFrame::OnSetHint
)
318 EVT_UPDATE_UI_RANGE(TextEntry_Begin
, TextEntry_End
- 1,
319 WidgetsFrame::OnUpdateTextUI
)
321 EVT_MENU(wxID_EXIT
, WidgetsFrame::OnExit
)
322 #endif // wxUSE_MENUS
325 // ============================================================================
327 // ============================================================================
329 // ----------------------------------------------------------------------------
331 // ----------------------------------------------------------------------------
333 bool WidgetsApp::OnInit()
335 if ( !wxApp::OnInit() )
338 SetVendorName("wxWidgets_Samples");
340 // the reason for having these ifdef's is that I often run two copies of
341 // this sample side by side and it is useful to see which one is which
343 #if defined(__WXUNIVERSAL__)
344 title
= wxT("wxUniv/");
347 #if defined(__WXMSW__)
348 title
+= wxT("wxMSW");
349 #elif defined(__WXGTK__)
350 title
+= wxT("wxGTK");
351 #elif defined(__WXMAC__)
352 title
+= wxT("wxMAC");
353 #elif defined(__WXMOTIF__)
354 title
+= wxT("wxMOTIF");
356 title
+= wxT("wxWidgets");
359 wxFrame
*frame
= new WidgetsFrame(title
+ wxT(" widgets demo"));
365 // ----------------------------------------------------------------------------
366 // WidgetsFrame construction
367 // ----------------------------------------------------------------------------
369 WidgetsFrame::WidgetsFrame(const wxString
& title
)
370 : wxFrame(NULL
, wxID_ANY
, title
)
372 const bool sizeSet
= wxPersistentRegisterAndRestore(this, "Main");
374 // set the frame icon
375 SetIcon(wxICON(sample
));
385 // create the menubar
386 wxMenuBar
*mbar
= new wxMenuBar
;
387 wxMenu
*menuWidget
= new wxMenu
;
389 menuWidget
->Append(Widgets_SetTooltip
, wxT("Set &tooltip...\tCtrl-T"));
390 menuWidget
->AppendSeparator();
391 #endif // wxUSE_TOOLTIPS
392 menuWidget
->Append(Widgets_SetFgColour
, wxT("Set &foreground...\tCtrl-F"));
393 menuWidget
->Append(Widgets_SetBgColour
, wxT("Set &background...\tCtrl-B"));
394 menuWidget
->Append(Widgets_SetPageBg
, wxT("Set &page background...\tShift-Ctrl-B"));
395 menuWidget
->Append(Widgets_SetFont
, wxT("Set f&ont...\tCtrl-O"));
396 menuWidget
->AppendCheckItem(Widgets_Enable
, wxT("&Enable/disable\tCtrl-E"));
398 wxMenu
*menuBorders
= new wxMenu
;
399 menuBorders
->AppendRadioItem(Widgets_BorderDefault
, wxT("De&fault\tCtrl-Shift-9"));
400 menuBorders
->AppendRadioItem(Widgets_BorderNone
, wxT("&None\tCtrl-Shift-0"));
401 menuBorders
->AppendRadioItem(Widgets_BorderSimple
, wxT("&Simple\tCtrl-Shift-1"));
402 menuBorders
->AppendRadioItem(Widgets_BorderDouble
, wxT("&Double\tCtrl-Shift-2"));
403 menuBorders
->AppendRadioItem(Widgets_BorderStatic
, wxT("Stati&c\tCtrl-Shift-3"));
404 menuBorders
->AppendRadioItem(Widgets_BorderRaised
, wxT("&Raised\tCtrl-Shift-4"));
405 menuBorders
->AppendRadioItem(Widgets_BorderSunken
, wxT("S&unken\tCtrl-Shift-5"));
406 menuWidget
->AppendSubMenu(menuBorders
, wxT("Set &border"));
408 menuWidget
->AppendSeparator();
409 menuWidget
->AppendCheckItem(Widgets_LayoutDirection
,
410 "Toggle &layout direction\tCtrl-L");
412 menuWidget
->AppendSeparator();
413 menuWidget
->AppendCheckItem(Widgets_GlobalBusyCursor
,
414 wxT("Toggle &global busy cursor\tCtrl-Shift-U"));
415 menuWidget
->AppendCheckItem(Widgets_BusyCursor
,
416 wxT("Toggle b&usy cursor\tCtrl-U"));
418 menuWidget
->AppendSeparator();
419 menuWidget
->Append(wxID_EXIT
, wxT("&Quit\tCtrl-Q"));
420 mbar
->Append(menuWidget
, wxT("&Widget"));
422 wxMenu
*menuTextEntry
= new wxMenu
;
423 menuTextEntry
->AppendRadioItem(TextEntry_DisableAutoComplete
,
424 wxT("&Disable auto-completion"));
425 menuTextEntry
->AppendRadioItem(TextEntry_AutoCompleteFixed
,
426 wxT("Fixed-&list auto-completion"));
427 menuTextEntry
->AppendRadioItem(TextEntry_AutoCompleteFilenames
,
428 wxT("&Files names auto-completion"));
429 menuTextEntry
->AppendRadioItem(TextEntry_AutoCompleteDirectories
,
430 wxT("&Directories names auto-completion"));
431 menuTextEntry
->AppendRadioItem(TextEntry_AutoCompleteCustom
,
432 wxT("&Custom auto-completion"));
433 menuTextEntry
->AppendSeparator();
434 menuTextEntry
->Append(TextEntry_SetHint
, "Set help &hint");
436 mbar
->Append(menuTextEntry
, wxT("&Text"));
440 mbar
->Check(Widgets_Enable
, true);
441 #endif // wxUSE_MENUS
444 m_panel
= new wxPanel(this, wxID_ANY
);
446 wxSizer
*sizerTop
= new wxBoxSizer(wxVERTICAL
);
448 // we have 2 panes: book with pages demonstrating the controls in the
449 // upper one and the log window with some buttons in the lower
451 int style
= wxBK_DEFAULT
;
452 // Uncomment to suppress page theme (draw in solid colour)
453 //style |= wxNB_NOPAGETHEME;
455 m_book
= new WidgetsBookCtrl(m_panel
, Widgets_BookCtrl
,
456 wxDefaultPosition
, wxDefaultSize
,
461 #ifndef __WXHANDHELD__
462 // the lower one only has the log listbox and a button to clear it
464 wxSizer
*sizerDown
= new wxStaticBoxSizer(
465 new wxStaticBox( m_panel
, wxID_ANY
, wxT("&Log window") ),
468 m_lboxLog
= new wxListBox(m_panel
, wxID_ANY
);
469 sizerDown
->Add(m_lboxLog
, 1, wxGROW
| wxALL
, 5);
470 sizerDown
->SetMinSize(100, 150);
472 wxSizer
*sizerDown
= new wxBoxSizer(wxVERTICAL
);
475 wxBoxSizer
*sizerBtns
= new wxBoxSizer(wxHORIZONTAL
);
478 btn
= new wxButton(m_panel
, Widgets_ClearLog
, wxT("Clear &log"));
480 sizerBtns
->Add(10, 0); // spacer
482 btn
= new wxButton(m_panel
, Widgets_Quit
, wxT("E&xit"));
484 sizerDown
->Add(sizerBtns
, 0, wxALL
| wxALIGN_RIGHT
, 5);
486 // put everything together
487 sizerTop
->Add(m_book
, 1, wxGROW
| (wxALL
& ~(wxTOP
| wxBOTTOM
)), 10);
488 sizerTop
->Add(0, 5, 0, wxGROW
); // spacer in between
489 sizerTop
->Add(sizerDown
, 0, wxGROW
| (wxALL
& ~wxTOP
), 10);
491 #else // !__WXHANDHELD__/__WXHANDHELD__
493 sizerTop
->Add(m_book
, 1, wxGROW
| wxALL
);
495 #endif // __WXHANDHELD__
497 m_panel
->SetSizer(sizerTop
);
499 const wxSize sizeMin
= m_panel
->GetBestSize();
501 SetClientSize(sizeMin
);
502 SetMinClientSize(sizeMin
);
504 #if USE_LOG && !defined(__WXCOCOA__)
505 // wxCocoa's listbox is too flakey to use for logging right now
506 // now that everything is created we can redirect the log messages to the
508 m_logTarget
= new LboxLogger(m_lboxLog
, wxLog::GetActiveTarget());
509 wxLog::SetActiveTarget(m_logTarget
);
513 void WidgetsFrame::InitBook()
515 #if USE_ICONS_IN_BOOK
516 wxImageList
*imageList
= new wxImageList(ICON_SIZE
, ICON_SIZE
);
518 wxImage
img(sample_xpm
);
519 imageList
->Add(wxBitmap(img
.Scale(ICON_SIZE
, ICON_SIZE
)));
521 wxImageList
*imageList
= NULL
;
525 WidgetsBookCtrl
*books
[MAX_PAGES
];
528 ArrayWidgetsPage pages
[MAX_PAGES
];
529 wxArrayString labels
[MAX_PAGES
];
531 wxMenu
*menuPages
= new wxMenu
;
532 unsigned int nPage
= 0, nFKey
= 0;
533 int cat
, imageId
= 1;
535 // we need to first create all pages and only then add them to the book
536 // as we need the image list first
538 // we also construct the pages menu during this first iteration
539 for ( cat
= 0; cat
< MAX_PAGES
; cat
++ )
542 nPage
++; // increase for parent page
544 books
[cat
] = new WidgetsBookCtrl(m_book
,
551 for ( WidgetsPageInfo
*info
= WidgetsPage::ms_widgetPages
;
553 info
= info
->GetNext() )
555 if( (info
->GetCategories() & ( 1 << cat
)) == 0)
558 WidgetsPage
*page
= (*info
->GetCtor())(
565 pages
[cat
].Add(page
);
567 labels
[cat
].Add(info
->GetLabel());
568 if ( cat
== ALL_PAGE
)
570 wxString
radioLabel(info
->GetLabel());
574 radioLabel
<< wxT("\tF" ) << nFKey
;
577 menuPages
->AppendRadioItem(
578 Widgets_GoToPage
+ nPage
,
582 // consider only for book in book architecture
588 // consider only for treebook architecture (with subpages)
594 GetMenuBar()->Append(menuPages
, wxT("&Page"));
596 #if USE_ICONS_IN_BOOK
597 m_book
->AssignImageList(imageList
);
600 for ( cat
= 0; cat
< MAX_PAGES
; cat
++ )
603 m_book
->AddPage(NULL
,WidgetsCategories
[cat
],false,0);
605 m_book
->AddPage(books
[cat
],WidgetsCategories
[cat
],false,0);
606 #if USE_ICONS_IN_BOOK
607 books
[cat
]->SetImageList(imageList
);
612 size_t count
= pages
[cat
].GetCount();
613 for ( size_t n
= 0; n
< count
; n
++ )
623 false, // don't select
630 wxEVT_COMMAND_WIDGETS_PAGE_CHANGED
,
631 wxWidgetsbookEventHandler(WidgetsFrame::OnPageChanged
) );
633 const bool pageSet
= wxPersistentRegisterAndRestore(m_book
);
636 // for treebook page #0 is empty parent page only so select the first page
637 // with some contents
639 m_book
->SetSelection(1);
641 // but ensure that the top of the tree is shown nevertheless
642 wxTreeCtrl
* const tree
= m_book
->GetTreeCtrl();
644 wxTreeItemIdValue cookie
;
645 tree
->EnsureVisible(tree
->GetFirstChild(tree
->GetRootItem(), cookie
));
649 // for other books set selection twice to force connected event handler
650 // to force lazy creation of initial visible content
651 m_book
->SetSelection(1);
652 m_book
->SetSelection(0);
654 #endif // USE_TREEBOOK
657 WidgetsPage
*WidgetsFrame::CurrentPage()
659 wxWindow
*page
= m_book
->GetCurrentPage();
662 WidgetsBookCtrl
*subBook
= wxStaticCast(page
, WidgetsBookCtrl
);
663 wxCHECK_MSG( subBook
, NULL
, wxT("no WidgetsBookCtrl?") );
665 page
= subBook
->GetCurrentPage();
666 #endif // !USE_TREEBOOK
668 return wxStaticCast(page
, WidgetsPage
);
671 WidgetsFrame::~WidgetsFrame()
678 // ----------------------------------------------------------------------------
679 // WidgetsFrame event handlers
680 // ----------------------------------------------------------------------------
682 void WidgetsFrame::OnExit(wxCommandEvent
& WXUNUSED(event
))
688 void WidgetsFrame::OnButtonClearLog(wxCommandEvent
& WXUNUSED(event
))
696 void WidgetsFrame::OnPageChanging(WidgetsBookCtrlEvent
& event
)
699 // don't allow selection of entries without pages (categories)
700 if ( !m_book
->GetPage(event
.GetSelection()) )
707 void WidgetsFrame::OnPageChanged(WidgetsBookCtrlEvent
& event
)
709 const int sel
= event
.GetSelection();
711 // adjust "Page" menu selection
712 wxMenuItem
*item
= GetMenuBar()->FindItem(Widgets_GoToPage
+ sel
);
716 GetMenuBar()->Check(Widgets_BusyCursor
, false);
718 // create the pages on demand, otherwise the sample startup is too slow as
719 // it creates hundreds of controls
720 WidgetsPage
*page
= CurrentPage();
721 if ( page
->GetChildren().empty() )
723 wxWindowUpdateLocker
noUpdates(page
);
724 page
->CreateContent();
726 page
->GetSizer()->Fit(page
);
728 WidgetsBookCtrl
*book
= wxStaticCast(page
->GetParent(), WidgetsBookCtrl
);
730 for ( size_t i
= 0; i
< book
->GetPageCount(); ++i
)
732 wxWindow
*page
= book
->GetPage(i
);
735 size
.IncTo(page
->GetSize());
744 void WidgetsFrame::OnGoToPage(wxCommandEvent
& event
)
747 m_book
->SetSelection(event
.GetId() - Widgets_GoToPage
);
749 m_book
->SetSelection(m_book
->GetPageCount()-1);
750 WidgetsBookCtrl
*book
= wxStaticCast(m_book
->GetCurrentPage(), WidgetsBookCtrl
);
751 book
->SetSelection(event
.GetId() - Widgets_GoToPage
);
757 void WidgetsFrame::OnSetTooltip(wxCommandEvent
& WXUNUSED(event
))
759 static wxString s_tip
= wxT("This is a tooltip");
761 wxTextEntryDialog dialog
764 wxT("Tooltip text (may use \\n, leave empty to remove): "),
765 wxT("Widgets sample"),
769 if ( dialog
.ShowModal() != wxID_OK
)
772 s_tip
= dialog
.GetValue();
773 s_tip
.Replace(wxT("\\n"), wxT("\n"));
775 WidgetsPage
*page
= CurrentPage();
777 const Widgets widgets
= page
->GetWidgets();
778 for ( Widgets::const_iterator it
= widgets
.begin();
782 (*it
)->SetToolTip(s_tip
);
786 #endif // wxUSE_TOOLTIPS
791 // Trivial wrapper for wxGetColourFromUser() which also does something even if
792 // the colour dialog is not available in the current build (which may happen
793 // for the ports in development and it is still useful to see how colours work)
794 wxColour
GetColourFromUser(wxWindow
*parent
, const wxColour
& colDefault
)
797 return wxGetColourFromUser(parent
, colDefault
);
798 #else // !wxUSE_COLOURDLG
799 if ( colDefault
== *wxBLACK
)
803 #endif // wxUSE_COLOURDLG/!wxUSE_COLOURDLG
806 } // anonymous namespace
808 void WidgetsFrame::OnSetFgCol(wxCommandEvent
& WXUNUSED(event
))
810 // allow for debugging the default colour the first time this is called
811 WidgetsPage
*page
= CurrentPage();
814 m_colFg
= page
->GetForegroundColour();
816 wxColour col
= GetColourFromUser(this, m_colFg
);
822 const Widgets widgets
= page
->GetWidgets();
823 for ( Widgets::const_iterator it
= widgets
.begin();
827 (*it
)->SetForegroundColour(m_colFg
);
832 void WidgetsFrame::OnSetBgCol(wxCommandEvent
& WXUNUSED(event
))
834 WidgetsPage
*page
= CurrentPage();
836 if ( !m_colBg
.IsOk() )
837 m_colBg
= page
->GetBackgroundColour();
839 wxColour col
= GetColourFromUser(this, m_colBg
);
845 const Widgets widgets
= page
->GetWidgets();
846 for ( Widgets::const_iterator it
= widgets
.begin();
850 (*it
)->SetBackgroundColour(m_colBg
);
855 void WidgetsFrame::OnSetPageBg(wxCommandEvent
& WXUNUSED(event
))
857 wxColour col
= GetColourFromUser(this, GetBackgroundColour());
861 CurrentPage()->SetBackgroundColour(col
);
862 CurrentPage()->Refresh();
865 void WidgetsFrame::OnSetFont(wxCommandEvent
& WXUNUSED(event
))
868 WidgetsPage
*page
= CurrentPage();
871 m_font
= page
->GetFont();
873 wxFont font
= wxGetFontFromUser(this, m_font
);
879 const Widgets widgets
= page
->GetWidgets();
880 for ( Widgets::const_iterator it
= widgets
.begin();
884 (*it
)->SetFont(m_font
);
888 // The best size of the widget could have changed after changing its font,
889 // so re-layout to show it correctly.
892 wxLogMessage(wxT("Font selection dialog not available in current build."));
896 void WidgetsFrame::OnEnable(wxCommandEvent
& event
)
898 const Widgets widgets
= CurrentPage()->GetWidgets();
899 for ( Widgets::const_iterator it
= widgets
.begin();
903 (*it
)->Enable(event
.IsChecked());
907 void WidgetsFrame::OnSetBorder(wxCommandEvent
& event
)
910 switch ( event
.GetId() )
912 case Widgets_BorderNone
: border
= wxBORDER_NONE
; break;
913 case Widgets_BorderStatic
: border
= wxBORDER_STATIC
; break;
914 case Widgets_BorderSimple
: border
= wxBORDER_SIMPLE
; break;
915 case Widgets_BorderRaised
: border
= wxBORDER_RAISED
; break;
916 case Widgets_BorderSunken
: border
= wxBORDER_SUNKEN
; break;
917 case Widgets_BorderDouble
: border
= wxBORDER_DOUBLE
; break;
920 wxFAIL_MSG( wxT("unknown border style") );
923 case Widgets_BorderDefault
: border
= wxBORDER_DEFAULT
; break;
926 WidgetsPage::ms_defaultFlags
&= ~wxBORDER_MASK
;
927 WidgetsPage::ms_defaultFlags
|= border
;
929 WidgetsPage
*page
= CurrentPage();
931 page
->RecreateWidget();
934 void WidgetsFrame::OnToggleLayoutDirection(wxCommandEvent
& event
)
936 wxLayoutDirection dir
= event
.IsChecked() ? wxLayout_RightToLeft
937 : wxLayout_LeftToRight
;
939 const Widgets widgets
= CurrentPage()->GetWidgets();
940 for ( Widgets::const_iterator it
= widgets
.begin();
944 (*it
)->SetLayoutDirection(dir
);
949 void WidgetsFrame::OnToggleGlobalBusyCursor(wxCommandEvent
& event
)
951 if ( event
.IsChecked() )
957 void WidgetsFrame::OnToggleBusyCursor(wxCommandEvent
& event
)
959 wxCursor
cursor(*(event
.IsChecked() ? wxHOURGLASS_CURSOR
960 : wxSTANDARD_CURSOR
));
962 const Widgets widgets
= CurrentPage()->GetWidgets();
963 for ( Widgets::const_iterator it
= widgets
.begin();
967 (*it
)->SetCursor(cursor
);
971 void WidgetsFrame::OnDisableAutoComplete(wxCommandEvent
& WXUNUSED(event
))
973 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
974 wxCHECK_RET( entry
, "menu item should be disabled" );
976 if ( entry
->AutoComplete(wxArrayString()) )
978 wxLogMessage("Disabled auto completion.");
982 wxLogMessage("AutoComplete() failed.");
986 void WidgetsFrame::OnAutoCompleteFixed(wxCommandEvent
& WXUNUSED(event
))
988 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
989 wxCHECK_RET( entry
, "menu item should be disabled" );
991 wxArrayString completion_choices
;
993 // add a few strings so a completion occurs on any letter typed
994 for ( char idxc
= 'a'; idxc
< 'z'; ++idxc
)
995 completion_choices
.push_back(wxString::Format("%c%c", idxc
, idxc
));
997 completion_choices
.push_back("is this string for test?");
998 completion_choices
.push_back("this is a test string");
999 completion_choices
.push_back("this is another test string");
1000 completion_choices
.push_back("this string is for test");
1002 if ( entry
->AutoComplete(completion_choices
) )
1004 wxLogMessage("Enabled auto completion of a set of fixed strings.");
1008 wxLogMessage("AutoComplete() failed.");
1012 void WidgetsFrame::OnAutoCompleteFilenames(wxCommandEvent
& WXUNUSED(event
))
1014 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
1015 wxCHECK_RET( entry
, "menu item should be disabled" );
1017 if ( entry
->AutoCompleteFileNames() )
1019 wxLogMessage("Enabled auto completion of file names.");
1023 wxLogMessage("AutoCompleteFileNames() failed.");
1027 void WidgetsFrame::OnAutoCompleteDirectories(wxCommandEvent
& WXUNUSED(event
))
1029 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
1030 wxCHECK_RET( entry
, "menu item should be disabled" );
1032 if ( entry
->AutoCompleteDirectories() )
1034 wxLogMessage("Enabled auto completion of directories.");
1038 wxLogMessage("AutoCompleteDirectories() failed.");
1042 void WidgetsFrame::OnAutoCompleteCustom(wxCommandEvent
& WXUNUSED(event
))
1044 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
1045 wxCHECK_RET( entry
, "menu item should be disabled" );
1047 // This is a simple (and hence rather useless) example of a custom
1048 // completer class that completes the first word (only) initially and only
1049 // build the list of the possible second words once the first word is
1050 // known. This allows to avoid building the full 676000 item list of
1051 // possible strings all at once as the we have 1000 possibilities for the
1052 // first word (000..999) and 676 (aa..zz) for the second one.
1053 class CustomTextCompleter
: public wxTextCompleterSimple
1056 virtual void GetCompletions(const wxString
& prefix
, wxArrayString
& res
)
1058 // This is used for illustrative purposes only and shows how many
1059 // completions we return every time when we're called.
1060 class LogCompletions
1063 LogCompletions(const wxString
& prefix
, const wxArrayString
& res
)
1071 wxLogMessage("Returning %lu possible completions for "
1073 m_res
.size(), m_prefix
);
1077 const wxString
& m_prefix
;
1078 const wxArrayString
& m_res
;
1079 } logCompletions(prefix
, res
);
1082 // Normally it doesn't make sense to complete empty control, there
1083 // are too many choices and listing them all wouldn't be helpful.
1084 if ( prefix
.empty() )
1087 // The only valid strings start with 3 digits so check for their
1088 // presence proposing to complete the remaining ones.
1089 if ( !wxIsdigit(prefix
[0]) )
1092 if ( prefix
.length() == 1 )
1094 for ( int i
= 0; i
< 10; i
++ )
1095 for ( int j
= 0; j
< 10; j
++ )
1096 res
.push_back(wxString::Format("%s%02d",
1100 else if ( !wxIsdigit(prefix
[1]) )
1103 if ( prefix
.length() == 2 )
1105 for ( int i
= 0; i
< 10; i
++ )
1106 res
.push_back(wxString::Format("%s%d", prefix
, i
));
1109 else if ( !wxIsdigit(prefix
[2]) )
1112 // Next we must have a space and two letters.
1113 wxString
prefix2(prefix
);
1114 if ( prefix
.length() == 3 )
1116 else if ( prefix
[3] != ' ' )
1119 if ( prefix2
.length() == 4 )
1121 for ( char c
= 'a'; c
<= 'z'; c
++ )
1122 for ( char d
= 'a'; d
<= 'z'; d
++ )
1123 res
.push_back(wxString::Format("%s%c%c", prefix2
, c
, d
));
1126 else if ( !wxIslower(prefix
[4]) )
1129 if ( prefix
.length() == 5 )
1131 for ( char c
= 'a'; c
<= 'z'; c
++ )
1132 res
.push_back(prefix
+ c
);
1137 if ( entry
->AutoComplete(new CustomTextCompleter
) )
1139 wxLogMessage("Enabled custom auto completer for \"NNN XX\" items "
1140 "(where N is a digit and X is a letter).");
1144 wxLogMessage("AutoComplete() failed.");
1148 void WidgetsFrame::OnSetHint(wxCommandEvent
& WXUNUSED(event
))
1150 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
1151 wxCHECK_RET( entry
, "menu item should be disabled" );
1153 static wxString
s_hint("Type here");
1155 hint
= wxGetTextFromUser("Text hint:", "Widgets sample", s_hint
, this);
1161 if ( entry
->SetHint(hint
) )
1163 wxLogMessage("Set hint to \"%s\".", hint
);
1167 wxLogMessage("Text hints not supported.");
1171 #endif // wxUSE_MENUS
1173 // ----------------------------------------------------------------------------
1175 // ----------------------------------------------------------------------------
1177 WidgetsPageInfo::WidgetsPageInfo(Constructor ctor
, const wxChar
*label
, int categories
)
1179 , m_categories(categories
)
1185 // dummy sorting: add and immediately sort in the list according to label
1186 if ( WidgetsPage::ms_widgetPages
)
1188 WidgetsPageInfo
*node_prev
= WidgetsPage::ms_widgetPages
;
1189 if ( wxStrcmp(label
, node_prev
->GetLabel().c_str()) < 0 )
1193 WidgetsPage::ms_widgetPages
= this;
1197 WidgetsPageInfo
*node_next
;
1200 node_next
= node_prev
->GetNext();
1203 // add if between two
1204 if ( wxStrcmp(label
, node_next
->GetLabel().c_str()) < 0 )
1206 node_prev
->SetNext(this);
1208 // force to break loop
1215 node_prev
->SetNext(this);
1218 node_prev
= node_next
;
1220 while ( node_next
);
1226 WidgetsPage::ms_widgetPages
= this;
1230 // ----------------------------------------------------------------------------
1232 // ----------------------------------------------------------------------------
1234 int WidgetsPage::ms_defaultFlags
= wxBORDER_DEFAULT
;
1235 WidgetsPageInfo
*WidgetsPage::ms_widgetPages
= NULL
;
1237 WidgetsPage::WidgetsPage(WidgetsBookCtrl
*book
,
1238 wxImageList
*imaglist
,
1239 const char *const icon
[])
1240 : wxPanel(book
, wxID_ANY
,
1241 wxDefaultPosition
, wxDefaultSize
,
1242 wxNO_FULL_REPAINT_ON_RESIZE
|
1246 #if USE_ICONS_IN_BOOK
1247 imaglist
->Add(wxBitmap(wxImage(icon
).Scale(ICON_SIZE
, ICON_SIZE
)));
1249 wxUnusedVar(imaglist
);
1254 wxSizer
*WidgetsPage::CreateSizerWithText(wxControl
*control
,
1256 wxTextCtrl
**ppText
)
1258 wxSizer
*sizerRow
= new wxBoxSizer(wxHORIZONTAL
);
1259 wxTextCtrl
*text
= new wxTextCtrl(this, id
, wxEmptyString
,
1260 wxDefaultPosition
, wxDefaultSize
, wxTE_PROCESS_ENTER
);
1262 sizerRow
->Add(control
, 0, wxRIGHT
| wxALIGN_CENTRE_VERTICAL
, 5);
1263 sizerRow
->Add(text
, 1, wxLEFT
| wxALIGN_CENTRE_VERTICAL
, 5);
1271 // create a sizer containing a label and a text ctrl
1272 wxSizer
*WidgetsPage::CreateSizerWithTextAndLabel(const wxString
& label
,
1274 wxTextCtrl
**ppText
)
1276 return CreateSizerWithText(new wxStaticText(this, wxID_ANY
, label
),
1280 // create a sizer containing a button and a text ctrl
1281 wxSizer
*WidgetsPage::CreateSizerWithTextAndButton(wxWindowID idBtn
,
1282 const wxString
& label
,
1284 wxTextCtrl
**ppText
)
1286 return CreateSizerWithText(new wxButton(this, idBtn
, label
), id
, ppText
);
1289 wxCheckBox
*WidgetsPage::CreateCheckBoxAndAddToSizer(wxSizer
*sizer
,
1290 const wxString
& label
,
1293 wxCheckBox
*checkbox
= new wxCheckBox(this, id
, label
);
1294 sizer
->Add(checkbox
, 0, wxLEFT
| wxRIGHT
, 5);
1295 sizer
->Add(0, 2, 0, wxGROW
); // spacer