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
8 // Copyright: (c) 2001 Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // for compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
27 // for all others, include the necessary headers
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"
44 #include "wx/sysopt.h"
45 #include "wx/bookctrl.h"
46 #include "wx/treebook.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 #include "wx/textcompleter.h"
55 #include "wx/persist/toplevel.h"
56 #include "wx/persist/treebook.h"
60 #include "../sample.xpm"
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
69 Widgets_ClearLog
= 100,
76 #endif // wxUSE_TOOLTIPS
89 Widgets_BorderDefault
,
91 Widgets_LayoutDirection
,
93 Widgets_GlobalBusyCursor
,
97 Widgets_GoToPageLast
= Widgets_GoToPage
+ 100,
101 TextEntry_DisableAutoComplete
= TextEntry_Begin
,
102 TextEntry_AutoCompleteFixed
,
103 TextEntry_AutoCompleteFilenames
,
104 TextEntry_AutoCompleteDirectories
,
105 TextEntry_AutoCompleteCustom
,
111 const wxChar
*WidgetsCategories
[MAX_PAGES
] = {
112 #if defined(__WXUNIVERSAL__)
126 // ----------------------------------------------------------------------------
128 // ----------------------------------------------------------------------------
130 // Define a new application type, each program should derive a class from wxApp
131 class WidgetsApp
: public wxApp
134 // override base class virtuals
135 // ----------------------------
137 // this one is called on application startup and is a good place for the app
138 // initialization (doing it here and not in the ctor allows to have an error
139 // return: if OnInit() returns false, the application terminates)
140 virtual bool OnInit();
143 // Define a new frame type: this is going to be our main frame
144 class WidgetsFrame
: public wxFrame
148 WidgetsFrame(const wxString
& title
);
149 virtual ~WidgetsFrame();
154 void OnButtonClearLog(wxCommandEvent
& event
);
156 void OnExit(wxCommandEvent
& event
);
159 void OnPageChanging(WidgetsBookCtrlEvent
& event
);
160 void OnPageChanged(WidgetsBookCtrlEvent
& event
);
161 void OnGoToPage(wxCommandEvent
& event
);
164 void OnSetTooltip(wxCommandEvent
& event
);
165 #endif // wxUSE_TOOLTIPS
166 void OnSetFgCol(wxCommandEvent
& event
);
167 void OnSetBgCol(wxCommandEvent
& event
);
168 void OnSetPageBg(wxCommandEvent
& event
);
169 void OnSetFont(wxCommandEvent
& event
);
170 void OnEnable(wxCommandEvent
& event
);
171 void OnSetBorder(wxCommandEvent
& event
);
173 void OnToggleLayoutDirection(wxCommandEvent
& event
);
175 void OnToggleGlobalBusyCursor(wxCommandEvent
& event
);
176 void OnToggleBusyCursor(wxCommandEvent
& event
);
178 // wxTextEntry-specific tests
179 void OnDisableAutoComplete(wxCommandEvent
& event
);
180 void OnAutoCompleteFixed(wxCommandEvent
& event
);
181 void OnAutoCompleteFilenames(wxCommandEvent
& event
);
182 void OnAutoCompleteDirectories(wxCommandEvent
& event
);
183 void OnAutoCompleteCustom(wxCommandEvent
& event
);
185 void OnSetHint(wxCommandEvent
& event
);
187 void OnUpdateTextUI(wxUpdateUIEvent
& event
)
189 event
.Enable( CurrentPage()->GetTextEntry() != NULL
);
191 #endif // wxUSE_MENUS
193 // initialize the book: add all pages to it
196 // return the currently selected page (never NULL)
197 WidgetsPage
*CurrentPage();
200 // the panel containing everything
204 // the listbox for logging messages
205 wxListBox
*m_lboxLog
;
207 // the log target we use to redirect messages to the listbox
211 // the book containing the test pages
212 WidgetsBookCtrl
*m_book
;
215 // last chosen fg/bg colours and font
219 #endif // wxUSE_MENUS
221 // any class wishing to process wxWidgets events must use this macro
222 DECLARE_EVENT_TABLE()
226 // A log target which just redirects the messages to a listbox
227 class LboxLogger
: public wxLog
230 LboxLogger(wxListBox
*lbox
, wxLog
*logOld
)
233 //m_lbox->Disable(); -- looks ugly under MSW
237 virtual ~LboxLogger()
239 wxLog::SetActiveTarget(m_logOld
);
243 // implement sink functions
244 virtual void DoLogTextAtLevel(wxLogLevel level
, const wxString
& msg
)
246 if ( level
== wxLOG_Trace
)
249 m_logOld
->LogTextAtLevel(level
, msg
);
253 #ifdef __WXUNIVERSAL__
254 m_lbox
->AppendAndEnsureVisible(msg
);
255 #else // other ports don't have this method yet
257 m_lbox
->SetFirstItem(m_lbox
->GetCount() - 1);
261 // the control we use
264 // the old log target
270 WX_DEFINE_ARRAY_PTR(WidgetsPage
*, ArrayWidgetsPage
);
272 // ----------------------------------------------------------------------------
274 // ----------------------------------------------------------------------------
276 IMPLEMENT_APP(WidgetsApp
)
278 // ----------------------------------------------------------------------------
280 // ----------------------------------------------------------------------------
282 BEGIN_EVENT_TABLE(WidgetsFrame
, wxFrame
)
284 EVT_BUTTON(Widgets_ClearLog
, WidgetsFrame::OnButtonClearLog
)
286 EVT_BUTTON(Widgets_Quit
, WidgetsFrame::OnExit
)
289 EVT_MENU(Widgets_SetTooltip
, WidgetsFrame::OnSetTooltip
)
290 #endif // wxUSE_TOOLTIPS
293 EVT_WIDGETS_PAGE_CHANGING(wxID_ANY
, WidgetsFrame::OnPageChanging
)
294 EVT_MENU_RANGE(Widgets_GoToPage
, Widgets_GoToPageLast
,
295 WidgetsFrame::OnGoToPage
)
297 EVT_MENU(Widgets_SetFgColour
, WidgetsFrame::OnSetFgCol
)
298 EVT_MENU(Widgets_SetBgColour
, WidgetsFrame::OnSetBgCol
)
299 EVT_MENU(Widgets_SetPageBg
, WidgetsFrame::OnSetPageBg
)
300 EVT_MENU(Widgets_SetFont
, WidgetsFrame::OnSetFont
)
301 EVT_MENU(Widgets_Enable
, WidgetsFrame::OnEnable
)
303 EVT_MENU_RANGE(Widgets_BorderNone
, Widgets_BorderDefault
,
304 WidgetsFrame::OnSetBorder
)
306 EVT_MENU(Widgets_LayoutDirection
, WidgetsFrame::OnToggleLayoutDirection
)
308 EVT_MENU(Widgets_GlobalBusyCursor
, WidgetsFrame::OnToggleGlobalBusyCursor
)
309 EVT_MENU(Widgets_BusyCursor
, WidgetsFrame::OnToggleBusyCursor
)
311 EVT_MENU(TextEntry_DisableAutoComplete
, WidgetsFrame::OnDisableAutoComplete
)
312 EVT_MENU(TextEntry_AutoCompleteFixed
, WidgetsFrame::OnAutoCompleteFixed
)
313 EVT_MENU(TextEntry_AutoCompleteFilenames
, WidgetsFrame::OnAutoCompleteFilenames
)
314 EVT_MENU(TextEntry_AutoCompleteDirectories
, WidgetsFrame::OnAutoCompleteDirectories
)
315 EVT_MENU(TextEntry_AutoCompleteCustom
, WidgetsFrame::OnAutoCompleteCustom
)
317 EVT_MENU(TextEntry_SetHint
, WidgetsFrame::OnSetHint
)
319 EVT_UPDATE_UI_RANGE(TextEntry_Begin
, TextEntry_End
- 1,
320 WidgetsFrame::OnUpdateTextUI
)
322 EVT_MENU(wxID_EXIT
, WidgetsFrame::OnExit
)
323 #endif // wxUSE_MENUS
326 // ============================================================================
328 // ============================================================================
330 // ----------------------------------------------------------------------------
332 // ----------------------------------------------------------------------------
334 bool WidgetsApp::OnInit()
336 if ( !wxApp::OnInit() )
339 SetVendorName("wxWidgets_Samples");
341 // the reason for having these ifdef's is that I often run two copies of
342 // this sample side by side and it is useful to see which one is which
344 #if defined(__WXUNIVERSAL__)
345 title
= wxT("wxUniv/");
348 #if defined(__WXMSW__)
349 title
+= wxT("wxMSW");
350 #elif defined(__WXGTK__)
351 title
+= wxT("wxGTK");
352 #elif defined(__WXMAC__)
353 title
+= wxT("wxMAC");
354 #elif defined(__WXMOTIF__)
355 title
+= wxT("wxMOTIF");
357 title
+= wxT("wxWidgets");
360 wxFrame
*frame
= new WidgetsFrame(title
+ wxT(" widgets demo"));
366 // ----------------------------------------------------------------------------
367 // WidgetsFrame construction
368 // ----------------------------------------------------------------------------
370 WidgetsFrame::WidgetsFrame(const wxString
& title
)
371 : wxFrame(NULL
, wxID_ANY
, title
)
373 const bool sizeSet
= wxPersistentRegisterAndRestore(this, "Main");
375 // set the frame icon
376 SetIcon(wxICON(sample
));
386 // create the menubar
387 wxMenuBar
*mbar
= new wxMenuBar
;
388 wxMenu
*menuWidget
= new wxMenu
;
390 menuWidget
->Append(Widgets_SetTooltip
, wxT("Set &tooltip...\tCtrl-T"));
391 menuWidget
->AppendSeparator();
392 #endif // wxUSE_TOOLTIPS
393 menuWidget
->Append(Widgets_SetFgColour
, wxT("Set &foreground...\tCtrl-F"));
394 menuWidget
->Append(Widgets_SetBgColour
, wxT("Set &background...\tCtrl-B"));
395 menuWidget
->Append(Widgets_SetPageBg
, wxT("Set &page background...\tShift-Ctrl-B"));
396 menuWidget
->Append(Widgets_SetFont
, wxT("Set f&ont...\tCtrl-O"));
397 menuWidget
->AppendCheckItem(Widgets_Enable
, wxT("&Enable/disable\tCtrl-E"));
399 wxMenu
*menuBorders
= new wxMenu
;
400 menuBorders
->AppendRadioItem(Widgets_BorderDefault
, wxT("De&fault\tCtrl-Shift-9"));
401 menuBorders
->AppendRadioItem(Widgets_BorderNone
, wxT("&None\tCtrl-Shift-0"));
402 menuBorders
->AppendRadioItem(Widgets_BorderSimple
, wxT("&Simple\tCtrl-Shift-1"));
403 menuBorders
->AppendRadioItem(Widgets_BorderDouble
, wxT("&Double\tCtrl-Shift-2"));
404 menuBorders
->AppendRadioItem(Widgets_BorderStatic
, wxT("Stati&c\tCtrl-Shift-3"));
405 menuBorders
->AppendRadioItem(Widgets_BorderRaised
, wxT("&Raised\tCtrl-Shift-4"));
406 menuBorders
->AppendRadioItem(Widgets_BorderSunken
, wxT("S&unken\tCtrl-Shift-5"));
407 menuWidget
->AppendSubMenu(menuBorders
, wxT("Set &border"));
409 menuWidget
->AppendSeparator();
410 menuWidget
->AppendCheckItem(Widgets_LayoutDirection
,
411 "Toggle &layout direction\tCtrl-L");
413 menuWidget
->AppendSeparator();
414 menuWidget
->AppendCheckItem(Widgets_GlobalBusyCursor
,
415 wxT("Toggle &global busy cursor\tCtrl-Shift-U"));
416 menuWidget
->AppendCheckItem(Widgets_BusyCursor
,
417 wxT("Toggle b&usy cursor\tCtrl-U"));
419 menuWidget
->AppendSeparator();
420 menuWidget
->Append(wxID_EXIT
, wxT("&Quit\tCtrl-Q"));
421 mbar
->Append(menuWidget
, wxT("&Widget"));
423 wxMenu
*menuTextEntry
= new wxMenu
;
424 menuTextEntry
->AppendRadioItem(TextEntry_DisableAutoComplete
,
425 wxT("&Disable auto-completion"));
426 menuTextEntry
->AppendRadioItem(TextEntry_AutoCompleteFixed
,
427 wxT("Fixed-&list auto-completion"));
428 menuTextEntry
->AppendRadioItem(TextEntry_AutoCompleteFilenames
,
429 wxT("&Files names auto-completion"));
430 menuTextEntry
->AppendRadioItem(TextEntry_AutoCompleteDirectories
,
431 wxT("&Directories names auto-completion"));
432 menuTextEntry
->AppendRadioItem(TextEntry_AutoCompleteCustom
,
433 wxT("&Custom auto-completion"));
434 menuTextEntry
->AppendSeparator();
435 menuTextEntry
->Append(TextEntry_SetHint
, "Set help &hint");
437 mbar
->Append(menuTextEntry
, wxT("&Text"));
441 mbar
->Check(Widgets_Enable
, true);
442 #endif // wxUSE_MENUS
445 m_panel
= new wxPanel(this, wxID_ANY
);
447 wxSizer
*sizerTop
= new wxBoxSizer(wxVERTICAL
);
449 // we have 2 panes: book with pages demonstrating the controls in the
450 // upper one and the log window with some buttons in the lower
452 int style
= wxBK_DEFAULT
;
453 // Uncomment to suppress page theme (draw in solid colour)
454 //style |= wxNB_NOPAGETHEME;
456 m_book
= new WidgetsBookCtrl(m_panel
, Widgets_BookCtrl
,
457 wxDefaultPosition
, wxDefaultSize
,
462 #ifndef __WXHANDHELD__
463 // the lower one only has the log listbox and a button to clear it
465 wxSizer
*sizerDown
= new wxStaticBoxSizer(
466 new wxStaticBox( m_panel
, wxID_ANY
, wxT("&Log window") ),
469 m_lboxLog
= new wxListBox(m_panel
, wxID_ANY
);
470 sizerDown
->Add(m_lboxLog
, 1, wxGROW
| wxALL
, 5);
471 sizerDown
->SetMinSize(100, 150);
473 wxSizer
*sizerDown
= new wxBoxSizer(wxVERTICAL
);
476 wxBoxSizer
*sizerBtns
= new wxBoxSizer(wxHORIZONTAL
);
479 btn
= new wxButton(m_panel
, Widgets_ClearLog
, wxT("Clear &log"));
481 sizerBtns
->Add(10, 0); // spacer
483 btn
= new wxButton(m_panel
, Widgets_Quit
, wxT("E&xit"));
485 sizerDown
->Add(sizerBtns
, 0, wxALL
| wxALIGN_RIGHT
, 5);
487 // put everything together
488 sizerTop
->Add(m_book
, 1, wxGROW
| (wxALL
& ~(wxTOP
| wxBOTTOM
)), 10);
489 sizerTop
->Add(0, 5, 0, wxGROW
); // spacer in between
490 sizerTop
->Add(sizerDown
, 0, wxGROW
| (wxALL
& ~wxTOP
), 10);
492 #else // !__WXHANDHELD__/__WXHANDHELD__
494 sizerTop
->Add(m_book
, 1, wxGROW
| wxALL
);
496 #endif // __WXHANDHELD__
498 m_panel
->SetSizer(sizerTop
);
500 const wxSize sizeMin
= m_panel
->GetBestSize();
502 SetClientSize(sizeMin
);
503 SetMinClientSize(sizeMin
);
505 #if USE_LOG && !defined(__WXCOCOA__)
506 // wxCocoa's listbox is too flakey to use for logging right now
507 // now that everything is created we can redirect the log messages to the
509 m_logTarget
= new LboxLogger(m_lboxLog
, wxLog::GetActiveTarget());
510 wxLog::SetActiveTarget(m_logTarget
);
514 void WidgetsFrame::InitBook()
516 #if USE_ICONS_IN_BOOK
517 wxImageList
*imageList
= new wxImageList(ICON_SIZE
, ICON_SIZE
);
519 wxImage
img(sample_xpm
);
520 imageList
->Add(wxBitmap(img
.Scale(ICON_SIZE
, ICON_SIZE
)));
522 wxImageList
*imageList
= NULL
;
526 WidgetsBookCtrl
*books
[MAX_PAGES
];
529 ArrayWidgetsPage pages
[MAX_PAGES
];
530 wxArrayString labels
[MAX_PAGES
];
532 wxMenu
*menuPages
= new wxMenu
;
533 unsigned int nPage
= 0, nFKey
= 0;
534 int cat
, imageId
= 1;
536 // we need to first create all pages and only then add them to the book
537 // as we need the image list first
539 // we also construct the pages menu during this first iteration
540 for ( cat
= 0; cat
< MAX_PAGES
; cat
++ )
543 nPage
++; // increase for parent page
545 books
[cat
] = new WidgetsBookCtrl(m_book
,
552 for ( WidgetsPageInfo
*info
= WidgetsPage::ms_widgetPages
;
554 info
= info
->GetNext() )
556 if( (info
->GetCategories() & ( 1 << cat
)) == 0)
559 WidgetsPage
*page
= (*info
->GetCtor())(
566 pages
[cat
].Add(page
);
568 labels
[cat
].Add(info
->GetLabel());
569 if ( cat
== ALL_PAGE
)
571 wxString
radioLabel(info
->GetLabel());
575 radioLabel
<< wxT("\tF" ) << nFKey
;
578 menuPages
->AppendRadioItem(
579 Widgets_GoToPage
+ nPage
,
583 // consider only for book in book architecture
589 // consider only for treebook architecture (with subpages)
595 GetMenuBar()->Append(menuPages
, wxT("&Page"));
597 #if USE_ICONS_IN_BOOK
598 m_book
->AssignImageList(imageList
);
601 for ( cat
= 0; cat
< MAX_PAGES
; cat
++ )
604 m_book
->AddPage(NULL
,WidgetsCategories
[cat
],false,0);
606 m_book
->AddPage(books
[cat
],WidgetsCategories
[cat
],false,0);
607 #if USE_ICONS_IN_BOOK
608 books
[cat
]->SetImageList(imageList
);
613 size_t count
= pages
[cat
].GetCount();
614 for ( size_t n
= 0; n
< count
; n
++ )
624 false, // don't select
631 wxEVT_COMMAND_WIDGETS_PAGE_CHANGED
,
632 wxWidgetsbookEventHandler(WidgetsFrame::OnPageChanged
) );
634 const bool pageSet
= wxPersistentRegisterAndRestore(m_book
);
637 // for treebook page #0 is empty parent page only so select the first page
638 // with some contents
640 m_book
->SetSelection(1);
642 // but ensure that the top of the tree is shown nevertheless
643 wxTreeCtrl
* const tree
= m_book
->GetTreeCtrl();
645 wxTreeItemIdValue cookie
;
646 tree
->EnsureVisible(tree
->GetFirstChild(tree
->GetRootItem(), cookie
));
650 // for other books set selection twice to force connected event handler
651 // to force lazy creation of initial visible content
652 m_book
->SetSelection(1);
653 m_book
->SetSelection(0);
655 #endif // USE_TREEBOOK
658 WidgetsPage
*WidgetsFrame::CurrentPage()
660 wxWindow
*page
= m_book
->GetCurrentPage();
663 WidgetsBookCtrl
*subBook
= wxStaticCast(page
, WidgetsBookCtrl
);
664 wxCHECK_MSG( subBook
, NULL
, wxT("no WidgetsBookCtrl?") );
666 page
= subBook
->GetCurrentPage();
667 #endif // !USE_TREEBOOK
669 return wxStaticCast(page
, WidgetsPage
);
672 WidgetsFrame::~WidgetsFrame()
679 // ----------------------------------------------------------------------------
680 // WidgetsFrame event handlers
681 // ----------------------------------------------------------------------------
683 void WidgetsFrame::OnExit(wxCommandEvent
& WXUNUSED(event
))
689 void WidgetsFrame::OnButtonClearLog(wxCommandEvent
& WXUNUSED(event
))
697 void WidgetsFrame::OnPageChanging(WidgetsBookCtrlEvent
& event
)
700 // don't allow selection of entries without pages (categories)
701 if ( !m_book
->GetPage(event
.GetSelection()) )
708 void WidgetsFrame::OnPageChanged(WidgetsBookCtrlEvent
& event
)
710 const int sel
= event
.GetSelection();
712 // adjust "Page" menu selection
713 wxMenuItem
*item
= GetMenuBar()->FindItem(Widgets_GoToPage
+ sel
);
717 GetMenuBar()->Check(Widgets_BusyCursor
, false);
719 // create the pages on demand, otherwise the sample startup is too slow as
720 // it creates hundreds of controls
721 WidgetsPage
*page
= CurrentPage();
722 if ( page
->GetChildren().empty() )
724 wxWindowUpdateLocker
noUpdates(page
);
725 page
->CreateContent();
727 page
->GetSizer()->Fit(page
);
729 WidgetsBookCtrl
*book
= wxStaticCast(page
->GetParent(), WidgetsBookCtrl
);
731 for ( size_t i
= 0; i
< book
->GetPageCount(); ++i
)
733 wxWindow
*page
= book
->GetPage(i
);
736 size
.IncTo(page
->GetSize());
745 void WidgetsFrame::OnGoToPage(wxCommandEvent
& event
)
748 m_book
->SetSelection(event
.GetId() - Widgets_GoToPage
);
750 m_book
->SetSelection(m_book
->GetPageCount()-1);
751 WidgetsBookCtrl
*book
= wxStaticCast(m_book
->GetCurrentPage(), WidgetsBookCtrl
);
752 book
->SetSelection(event
.GetId() - Widgets_GoToPage
);
758 void WidgetsFrame::OnSetTooltip(wxCommandEvent
& WXUNUSED(event
))
760 static wxString s_tip
= wxT("This is a tooltip");
762 wxTextEntryDialog dialog
765 wxT("Tooltip text (may use \\n, leave empty to remove): "),
766 wxT("Widgets sample"),
770 if ( dialog
.ShowModal() != wxID_OK
)
773 s_tip
= dialog
.GetValue();
774 s_tip
.Replace(wxT("\\n"), wxT("\n"));
776 WidgetsPage
*page
= CurrentPage();
778 const Widgets widgets
= page
->GetWidgets();
779 for ( Widgets::const_iterator it
= widgets
.begin();
783 (*it
)->SetToolTip(s_tip
);
787 #endif // wxUSE_TOOLTIPS
792 // Trivial wrapper for wxGetColourFromUser() which also does something even if
793 // the colour dialog is not available in the current build (which may happen
794 // for the ports in development and it is still useful to see how colours work)
795 wxColour
GetColourFromUser(wxWindow
*parent
, const wxColour
& colDefault
)
798 return wxGetColourFromUser(parent
, colDefault
);
799 #else // !wxUSE_COLOURDLG
800 if ( colDefault
== *wxBLACK
)
804 #endif // wxUSE_COLOURDLG/!wxUSE_COLOURDLG
807 } // anonymous namespace
809 void WidgetsFrame::OnSetFgCol(wxCommandEvent
& WXUNUSED(event
))
811 // allow for debugging the default colour the first time this is called
812 WidgetsPage
*page
= CurrentPage();
815 m_colFg
= page
->GetForegroundColour();
817 wxColour col
= GetColourFromUser(this, m_colFg
);
823 const Widgets widgets
= page
->GetWidgets();
824 for ( Widgets::const_iterator it
= widgets
.begin();
828 (*it
)->SetForegroundColour(m_colFg
);
833 void WidgetsFrame::OnSetBgCol(wxCommandEvent
& WXUNUSED(event
))
835 WidgetsPage
*page
= CurrentPage();
837 if ( !m_colBg
.IsOk() )
838 m_colBg
= page
->GetBackgroundColour();
840 wxColour col
= GetColourFromUser(this, m_colBg
);
846 const Widgets widgets
= page
->GetWidgets();
847 for ( Widgets::const_iterator it
= widgets
.begin();
851 (*it
)->SetBackgroundColour(m_colBg
);
856 void WidgetsFrame::OnSetPageBg(wxCommandEvent
& WXUNUSED(event
))
858 wxColour col
= GetColourFromUser(this, GetBackgroundColour());
862 CurrentPage()->SetBackgroundColour(col
);
863 CurrentPage()->Refresh();
866 void WidgetsFrame::OnSetFont(wxCommandEvent
& WXUNUSED(event
))
869 WidgetsPage
*page
= CurrentPage();
872 m_font
= page
->GetFont();
874 wxFont font
= wxGetFontFromUser(this, m_font
);
880 const Widgets widgets
= page
->GetWidgets();
881 for ( Widgets::const_iterator it
= widgets
.begin();
885 (*it
)->SetFont(m_font
);
889 // The best size of the widget could have changed after changing its font,
890 // so re-layout to show it correctly.
893 wxLogMessage(wxT("Font selection dialog not available in current build."));
897 void WidgetsFrame::OnEnable(wxCommandEvent
& event
)
899 const Widgets widgets
= CurrentPage()->GetWidgets();
900 for ( Widgets::const_iterator it
= widgets
.begin();
904 (*it
)->Enable(event
.IsChecked());
908 void WidgetsFrame::OnSetBorder(wxCommandEvent
& event
)
911 switch ( event
.GetId() )
913 case Widgets_BorderNone
: border
= wxBORDER_NONE
; break;
914 case Widgets_BorderStatic
: border
= wxBORDER_STATIC
; break;
915 case Widgets_BorderSimple
: border
= wxBORDER_SIMPLE
; break;
916 case Widgets_BorderRaised
: border
= wxBORDER_RAISED
; break;
917 case Widgets_BorderSunken
: border
= wxBORDER_SUNKEN
; break;
918 case Widgets_BorderDouble
: border
= wxBORDER_DOUBLE
; break;
921 wxFAIL_MSG( wxT("unknown border style") );
924 case Widgets_BorderDefault
: border
= wxBORDER_DEFAULT
; break;
927 WidgetsPage::ms_defaultFlags
&= ~wxBORDER_MASK
;
928 WidgetsPage::ms_defaultFlags
|= border
;
930 WidgetsPage
*page
= CurrentPage();
932 page
->RecreateWidget();
935 void WidgetsFrame::OnToggleLayoutDirection(wxCommandEvent
& event
)
937 wxLayoutDirection dir
= event
.IsChecked() ? wxLayout_RightToLeft
938 : wxLayout_LeftToRight
;
940 const Widgets widgets
= CurrentPage()->GetWidgets();
941 for ( Widgets::const_iterator it
= widgets
.begin();
945 (*it
)->SetLayoutDirection(dir
);
950 void WidgetsFrame::OnToggleGlobalBusyCursor(wxCommandEvent
& event
)
952 if ( event
.IsChecked() )
958 void WidgetsFrame::OnToggleBusyCursor(wxCommandEvent
& event
)
960 wxCursor
cursor(*(event
.IsChecked() ? wxHOURGLASS_CURSOR
961 : wxSTANDARD_CURSOR
));
963 const Widgets widgets
= CurrentPage()->GetWidgets();
964 for ( Widgets::const_iterator it
= widgets
.begin();
968 (*it
)->SetCursor(cursor
);
972 void WidgetsFrame::OnDisableAutoComplete(wxCommandEvent
& WXUNUSED(event
))
974 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
975 wxCHECK_RET( entry
, "menu item should be disabled" );
977 if ( entry
->AutoComplete(wxArrayString()) )
979 wxLogMessage("Disabled auto completion.");
983 wxLogMessage("AutoComplete() failed.");
987 void WidgetsFrame::OnAutoCompleteFixed(wxCommandEvent
& WXUNUSED(event
))
989 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
990 wxCHECK_RET( entry
, "menu item should be disabled" );
992 wxArrayString completion_choices
;
994 // add a few strings so a completion occurs on any letter typed
995 for ( char idxc
= 'a'; idxc
< 'z'; ++idxc
)
996 completion_choices
.push_back(wxString::Format("%c%c", idxc
, idxc
));
998 completion_choices
.push_back("is this string for test?");
999 completion_choices
.push_back("this is a test string");
1000 completion_choices
.push_back("this is another test string");
1001 completion_choices
.push_back("this string is for test");
1003 if ( entry
->AutoComplete(completion_choices
) )
1005 wxLogMessage("Enabled auto completion of a set of fixed strings.");
1009 wxLogMessage("AutoComplete() failed.");
1013 void WidgetsFrame::OnAutoCompleteFilenames(wxCommandEvent
& WXUNUSED(event
))
1015 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
1016 wxCHECK_RET( entry
, "menu item should be disabled" );
1018 if ( entry
->AutoCompleteFileNames() )
1020 wxLogMessage("Enabled auto completion of file names.");
1024 wxLogMessage("AutoCompleteFileNames() failed.");
1028 void WidgetsFrame::OnAutoCompleteDirectories(wxCommandEvent
& WXUNUSED(event
))
1030 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
1031 wxCHECK_RET( entry
, "menu item should be disabled" );
1033 if ( entry
->AutoCompleteDirectories() )
1035 wxLogMessage("Enabled auto completion of directories.");
1039 wxLogMessage("AutoCompleteDirectories() failed.");
1043 void WidgetsFrame::OnAutoCompleteCustom(wxCommandEvent
& WXUNUSED(event
))
1045 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
1046 wxCHECK_RET( entry
, "menu item should be disabled" );
1048 // This is a simple (and hence rather useless) example of a custom
1049 // completer class that completes the first word (only) initially and only
1050 // build the list of the possible second words once the first word is
1051 // known. This allows to avoid building the full 676000 item list of
1052 // possible strings all at once as the we have 1000 possibilities for the
1053 // first word (000..999) and 676 (aa..zz) for the second one.
1054 class CustomTextCompleter
: public wxTextCompleterSimple
1057 virtual void GetCompletions(const wxString
& prefix
, wxArrayString
& res
)
1059 // This is used for illustrative purposes only and shows how many
1060 // completions we return every time when we're called.
1061 class LogCompletions
1064 LogCompletions(const wxString
& prefix
, const wxArrayString
& res
)
1072 wxLogMessage("Returning %lu possible completions for "
1074 m_res
.size(), m_prefix
);
1078 const wxString
& m_prefix
;
1079 const wxArrayString
& m_res
;
1080 } logCompletions(prefix
, res
);
1083 // Normally it doesn't make sense to complete empty control, there
1084 // are too many choices and listing them all wouldn't be helpful.
1085 if ( prefix
.empty() )
1088 // The only valid strings start with 3 digits so check for their
1089 // presence proposing to complete the remaining ones.
1090 if ( !wxIsdigit(prefix
[0]) )
1093 if ( prefix
.length() == 1 )
1095 for ( int i
= 0; i
< 10; i
++ )
1096 for ( int j
= 0; j
< 10; j
++ )
1097 res
.push_back(wxString::Format("%s%02d",
1101 else if ( !wxIsdigit(prefix
[1]) )
1104 if ( prefix
.length() == 2 )
1106 for ( int i
= 0; i
< 10; i
++ )
1107 res
.push_back(wxString::Format("%s%d", prefix
, i
));
1110 else if ( !wxIsdigit(prefix
[2]) )
1113 // Next we must have a space and two letters.
1114 wxString
prefix2(prefix
);
1115 if ( prefix
.length() == 3 )
1117 else if ( prefix
[3] != ' ' )
1120 if ( prefix2
.length() == 4 )
1122 for ( char c
= 'a'; c
<= 'z'; c
++ )
1123 for ( char d
= 'a'; d
<= 'z'; d
++ )
1124 res
.push_back(wxString::Format("%s%c%c", prefix2
, c
, d
));
1127 else if ( !wxIslower(prefix
[4]) )
1130 if ( prefix
.length() == 5 )
1132 for ( char c
= 'a'; c
<= 'z'; c
++ )
1133 res
.push_back(prefix
+ c
);
1138 if ( entry
->AutoComplete(new CustomTextCompleter
) )
1140 wxLogMessage("Enabled custom auto completer for \"NNN XX\" items "
1141 "(where N is a digit and X is a letter).");
1145 wxLogMessage("AutoComplete() failed.");
1149 void WidgetsFrame::OnSetHint(wxCommandEvent
& WXUNUSED(event
))
1151 wxTextEntryBase
*entry
= CurrentPage()->GetTextEntry();
1152 wxCHECK_RET( entry
, "menu item should be disabled" );
1154 static wxString
s_hint("Type here");
1156 hint
= wxGetTextFromUser("Text hint:", "Widgets sample", s_hint
, this);
1162 if ( entry
->SetHint(hint
) )
1164 wxLogMessage("Set hint to \"%s\".", hint
);
1168 wxLogMessage("Text hints not supported.");
1172 #endif // wxUSE_MENUS
1174 // ----------------------------------------------------------------------------
1176 // ----------------------------------------------------------------------------
1178 WidgetsPageInfo::WidgetsPageInfo(Constructor ctor
, const wxChar
*label
, int categories
)
1180 , m_categories(categories
)
1186 // dummy sorting: add and immediately sort in the list according to label
1187 if ( WidgetsPage::ms_widgetPages
)
1189 WidgetsPageInfo
*node_prev
= WidgetsPage::ms_widgetPages
;
1190 if ( wxStrcmp(label
, node_prev
->GetLabel().c_str()) < 0 )
1194 WidgetsPage::ms_widgetPages
= this;
1198 WidgetsPageInfo
*node_next
;
1201 node_next
= node_prev
->GetNext();
1204 // add if between two
1205 if ( wxStrcmp(label
, node_next
->GetLabel().c_str()) < 0 )
1207 node_prev
->SetNext(this);
1209 // force to break loop
1216 node_prev
->SetNext(this);
1219 node_prev
= node_next
;
1221 while ( node_next
);
1227 WidgetsPage::ms_widgetPages
= this;
1231 // ----------------------------------------------------------------------------
1233 // ----------------------------------------------------------------------------
1235 int WidgetsPage::ms_defaultFlags
= wxBORDER_DEFAULT
;
1236 WidgetsPageInfo
*WidgetsPage::ms_widgetPages
= NULL
;
1238 WidgetsPage::WidgetsPage(WidgetsBookCtrl
*book
,
1239 wxImageList
*imaglist
,
1240 const char *const icon
[])
1241 : wxPanel(book
, wxID_ANY
,
1242 wxDefaultPosition
, wxDefaultSize
,
1243 wxNO_FULL_REPAINT_ON_RESIZE
|
1247 #if USE_ICONS_IN_BOOK
1248 imaglist
->Add(wxBitmap(wxImage(icon
).Scale(ICON_SIZE
, ICON_SIZE
)));
1250 wxUnusedVar(imaglist
);
1255 wxSizer
*WidgetsPage::CreateSizerWithText(wxControl
*control
,
1257 wxTextCtrl
**ppText
)
1259 wxSizer
*sizerRow
= new wxBoxSizer(wxHORIZONTAL
);
1260 wxTextCtrl
*text
= new wxTextCtrl(this, id
, wxEmptyString
,
1261 wxDefaultPosition
, wxDefaultSize
, wxTE_PROCESS_ENTER
);
1263 sizerRow
->Add(control
, 0, wxRIGHT
| wxALIGN_CENTRE_VERTICAL
, 5);
1264 sizerRow
->Add(text
, 1, wxLEFT
| wxALIGN_CENTRE_VERTICAL
, 5);
1272 // create a sizer containing a label and a text ctrl
1273 wxSizer
*WidgetsPage::CreateSizerWithTextAndLabel(const wxString
& label
,
1275 wxTextCtrl
**ppText
)
1277 return CreateSizerWithText(new wxStaticText(this, wxID_ANY
, label
),
1281 // create a sizer containing a button and a text ctrl
1282 wxSizer
*WidgetsPage::CreateSizerWithTextAndButton(wxWindowID idBtn
,
1283 const wxString
& label
,
1285 wxTextCtrl
**ppText
)
1287 return CreateSizerWithText(new wxButton(this, idBtn
, label
), id
, ppText
);
1290 wxCheckBox
*WidgetsPage::CreateCheckBoxAndAddToSizer(wxSizer
*sizer
,
1291 const wxString
& label
,
1294 wxCheckBox
*checkbox
= new wxCheckBox(this, id
, label
);
1295 sizer
->Add(checkbox
, 0, wxLEFT
| wxRIGHT
, 5);
1296 sizer
->Add(0, 2, 0, wxGROW
); // spacer