]> git.saurik.com Git - wxWidgets.git/blame_incremental - samples/calendar/calendar.cpp
Support using GetTextExtent() with empty string to get descent in wxOSX.
[wxWidgets.git] / samples / calendar / calendar.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: calendar.cpp
3// Purpose: wxCalendarCtrl sample
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 02.01.00
7// RCS-ID: $Id$
8// Copyright: (c) Vadim Zeitlin
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx/wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27// for all others, include the necessary headers
28#ifndef WX_PRECOMP
29 #include "wx/app.h"
30 #include "wx/log.h"
31 #include "wx/frame.h"
32 #include "wx/panel.h"
33 #include "wx/stattext.h"
34 #include "wx/menu.h"
35 #include "wx/layout.h"
36 #include "wx/msgdlg.h"
37 #include "wx/icon.h"
38 #include "wx/button.h"
39 #include "wx/sizer.h"
40 #include "wx/textctrl.h"
41 #include "wx/settings.h"
42#endif
43
44#include "wx/calctrl.h"
45#include "wx/splitter.h"
46
47#if wxUSE_DATEPICKCTRL
48 #include "wx/datectrl.h"
49 #if wxUSE_DATEPICKCTRL_GENERIC
50 #include "wx/generic/datectrl.h"
51 #endif // wxUSE_DATEPICKCTRL_GENERIC
52#endif // wxUSE_DATEPICKCTRL
53
54#if wxUSE_TIMEPICKCTRL
55 #include "wx/timectrl.h"
56 #if wxUSE_TIMEPICKCTRL_GENERIC
57 #include "wx/generic/timectrl.h"
58 #endif // wxUSE_TIMEPICKCTRL_GENERIC
59#endif // wxUSE_TIMEPICKCTRL
60
61#include "../sample.xpm"
62
63#ifdef wxHAS_NATIVE_CALENDARCTRL
64 #include "wx/generic/calctrlg.h"
65#endif
66
67// ----------------------------------------------------------------------------
68// private classes
69// ----------------------------------------------------------------------------
70
71// Define a new application type, each program should derive a class from wxApp
72class MyApp : public wxApp
73{
74public:
75 // override base class virtuals
76 // ----------------------------
77
78 // this one is called on application startup and is a good place for the app
79 // initialization (doing it here and not in the ctor allows to have an error
80 // return: if OnInit() returns false, the application terminates)
81 virtual bool OnInit();
82};
83
84class MyPanel : public wxPanel
85{
86public:
87 MyPanel(wxWindow *parent);
88
89 void OnCalendar(wxCalendarEvent& event);
90 void OnCalendarWeekDayClick(wxCalendarEvent& event);
91 void OnCalendarWeekClick(wxCalendarEvent& event);
92 void OnCalendarChange(wxCalendarEvent& event);
93 void OnCalMonthChange(wxCalendarEvent& event);
94
95 wxCalendarCtrlBase *GetCal() const { return m_calendar; }
96
97 // turn on/off the specified style bit on the calendar control
98 void ToggleCalStyle(bool on, int style);
99
100 bool IsUsingGeneric() const { return m_usingGeneric; }
101 void ToggleUseGeneric()
102 {
103 m_usingGeneric = !m_usingGeneric;
104 RecreateCalendar(m_calendar->GetWindowStyle());
105 }
106
107 void HighlightSpecial(bool on);
108 void LimitDateRange(bool on);
109
110 wxDateTime GetDate() const { return m_calendar->GetDate(); }
111 void SetDate(const wxDateTime& dt) { m_calendar->SetDate(dt); }
112
113private:
114 wxCalendarCtrlBase *DoCreateCalendar(const wxDateTime& dt, long style);
115
116 void RecreateCalendar(long style);
117
118 wxCalendarCtrlBase *m_calendar;
119 wxStaticText *m_date;
120 wxSizer *m_sizer;
121
122 bool m_usingGeneric;
123
124
125 DECLARE_EVENT_TABLE()
126};
127
128// Define a new frame type: this is going to be our main frame
129class MyFrame : public wxFrame
130{
131public:
132 // ctor(s)
133 MyFrame(const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize);
134
135 // event handlers (these functions should _not_ be virtual)
136 void OnAbout(wxCommandEvent& event);
137 void OnClearLog(wxCommandEvent& event);
138 void OnQuit(wxCommandEvent& event);
139
140#if wxUSE_DATEPICKCTRL
141 void OnAskDate(wxCommandEvent& event);
142
143 void OnUpdateUIStartWithNone(wxUpdateUIEvent& event);
144#endif // wxUSE_DATEPICKCTRL
145
146#if wxUSE_TIMEPICKCTRL
147 void OnAskTime(wxCommandEvent& event);
148#endif // wxUSE_TIMEPICKCTRL
149
150#ifdef wxHAS_NATIVE_CALENDARCTRL
151 void OnCalGeneric(wxCommandEvent& WXUNUSED(event))
152 {
153 m_panel->ToggleUseGeneric();
154 }
155#endif // wxHAS_NATIVE_CALENDARCTRL
156
157 void OnCalMonday(wxCommandEvent& event);
158 void OnCalHolidays(wxCommandEvent& event);
159 void OnCalSpecial(wxCommandEvent& event);
160
161 void OnCalAllowMonth(wxCommandEvent& event);
162 void OnCalLimitDates(wxCommandEvent& event);
163 void OnCalSeqMonth(wxCommandEvent& event);
164 void OnCalShowSurroundingWeeks(wxCommandEvent& event);
165 void OnCalShowWeekNumbers(wxCommandEvent& event);
166
167 void OnSetDate(wxCommandEvent& event);
168 void OnToday(wxCommandEvent& event);
169 void OnBeginDST(wxCommandEvent& event);
170
171 void OnCalToggleResizable(wxCommandEvent& event);
172
173 void OnUpdateUIGenericOnly(wxUpdateUIEvent& event)
174 {
175 event.Enable(m_panel->IsUsingGeneric());
176 }
177
178 void OnCalRClick(wxMouseEvent& event);
179
180private:
181 MyPanel *m_panel;
182 wxTextCtrl *m_logWindow;
183
184 // any class wishing to process wxWidgets events must use this macro
185 DECLARE_EVENT_TABLE()
186};
187
188#if wxUSE_DATEPICKCTRL
189
190// Define a simple modal dialog which asks the user for a date
191class MyDateDialog : public wxDialog
192{
193public:
194 MyDateDialog(wxWindow *parent, const wxDateTime& dt, int dtpStyle);
195
196 wxDateTime GetDate() const { return m_datePicker->GetValue(); }
197
198private:
199 void OnDateChange(wxDateEvent& event);
200
201
202 wxDatePickerCtrlBase *m_datePicker;
203 wxStaticText *m_dateText;
204
205
206 DECLARE_EVENT_TABLE()
207};
208
209#endif // wxUSE_DATEPICKCTRL
210
211#if wxUSE_TIMEPICKCTRL
212
213// Another simple dialog, this one asking for time.
214class MyTimeDialog : public wxDialog
215{
216public:
217 MyTimeDialog(wxWindow* parent);
218
219 wxDateTime GetTime() const { return m_timePicker->GetValue(); }
220
221private:
222 void OnTimeChange(wxDateEvent& event);
223
224 wxTimePickerCtrlBase* m_timePicker;
225 wxStaticText* m_timeText;
226
227 wxDECLARE_EVENT_TABLE();
228};
229
230#endif // wxUSE_TIMEPICKCTRL
231
232// ----------------------------------------------------------------------------
233// constants
234// ----------------------------------------------------------------------------
235
236// IDs for the controls and the menu commands
237enum
238{
239 // menu items
240 Calendar_File_About = wxID_ABOUT,
241 Calendar_File_ClearLog = wxID_CLEAR,
242 Calendar_File_Quit = wxID_EXIT,
243 Calendar_Cal_Generic = 200,
244 Calendar_Cal_Monday,
245 Calendar_Cal_Holidays,
246 Calendar_Cal_Special,
247 Calendar_Cal_Month,
248 Calendar_Cal_LimitDates,
249 Calendar_Cal_SeqMonth,
250 Calendar_Cal_SurroundWeeks,
251 Calendar_Cal_WeekNumbers,
252 Calendar_Cal_SetDate,
253 Calendar_Cal_Today,
254 Calendar_Cal_BeginDST,
255 Calendar_Cal_Resizable,
256#if wxUSE_DATEPICKCTRL
257 Calendar_DatePicker_AskDate = 300,
258 Calendar_DatePicker_ShowCentury,
259 Calendar_DatePicker_DropDown,
260 Calendar_DatePicker_AllowNone,
261 Calendar_DatePicker_StartWithNone,
262#if wxUSE_DATEPICKCTRL_GENERIC
263 Calendar_DatePicker_Generic,
264#endif // wxUSE_DATEPICKCTRL_GENERIC
265#endif // wxUSE_DATEPICKCTRL
266#if wxUSE_TIMEPICKCTRL
267 Calendar_TimePicker_AskTime = 400,
268#if wxUSE_TIMEPICKCTRL_GENERIC
269 Calendar_TimePicker_Generic,
270#endif // wxUSE_TIMEPICKCTRL_GENERIC
271#endif // wxUSE_TIMEPICKCTRL
272 Calendar_CalCtrl = 1000
273};
274
275// ----------------------------------------------------------------------------
276// event tables and other macros for wxWidgets
277// ----------------------------------------------------------------------------
278
279// the event tables connect the wxWidgets events with the functions (event
280// handlers) which process them. It can be also done at run-time, but for the
281// simple menu events like this the static method is much simpler.
282BEGIN_EVENT_TABLE(MyFrame, wxFrame)
283 EVT_MENU(Calendar_File_About, MyFrame::OnAbout)
284 EVT_MENU(Calendar_File_ClearLog, MyFrame::OnClearLog)
285 EVT_MENU(Calendar_File_Quit, MyFrame::OnQuit)
286
287#if wxUSE_DATEPICKCTRL
288 EVT_MENU(Calendar_DatePicker_AskDate, MyFrame::OnAskDate)
289
290 EVT_UPDATE_UI(Calendar_DatePicker_StartWithNone,
291 MyFrame::OnUpdateUIStartWithNone)
292#endif // wxUSE_DATEPICKCTRL
293
294#if wxUSE_TIMEPICKCTRL
295 EVT_MENU(Calendar_TimePicker_AskTime, MyFrame::OnAskTime)
296#endif // wxUSE_TIMEPICKCTRL
297
298#ifdef wxHAS_NATIVE_CALENDARCTRL
299 EVT_MENU(Calendar_Cal_Generic, MyFrame::OnCalGeneric)
300#endif // wxHAS_NATIVE_CALENDARCTRL
301
302 EVT_MENU(Calendar_Cal_Monday, MyFrame::OnCalMonday)
303 EVT_MENU(Calendar_Cal_Holidays, MyFrame::OnCalHolidays)
304 EVT_MENU(Calendar_Cal_Special, MyFrame::OnCalSpecial)
305
306 EVT_MENU(Calendar_Cal_Month, MyFrame::OnCalAllowMonth)
307
308 EVT_MENU(Calendar_Cal_LimitDates, MyFrame::OnCalLimitDates)
309
310 EVT_MENU(Calendar_Cal_SeqMonth, MyFrame::OnCalSeqMonth)
311 EVT_MENU(Calendar_Cal_SurroundWeeks, MyFrame::OnCalShowSurroundingWeeks)
312 EVT_MENU(Calendar_Cal_WeekNumbers, MyFrame::OnCalShowWeekNumbers)
313
314 EVT_MENU(Calendar_Cal_SetDate, MyFrame::OnSetDate)
315 EVT_MENU(Calendar_Cal_Today, MyFrame::OnToday)
316 EVT_MENU(Calendar_Cal_BeginDST, MyFrame::OnBeginDST)
317
318 EVT_MENU(Calendar_Cal_Resizable, MyFrame::OnCalToggleResizable)
319
320
321 EVT_UPDATE_UI(Calendar_Cal_SeqMonth, MyFrame::OnUpdateUIGenericOnly)
322#ifdef __WXGTK20__
323 EVT_UPDATE_UI(Calendar_Cal_Monday, MyFrame::OnUpdateUIGenericOnly)
324 EVT_UPDATE_UI(Calendar_Cal_Holidays, MyFrame::OnUpdateUIGenericOnly)
325#endif
326 EVT_UPDATE_UI(Calendar_Cal_Special, MyFrame::OnUpdateUIGenericOnly)
327 EVT_UPDATE_UI(Calendar_Cal_SurroundWeeks, MyFrame::OnUpdateUIGenericOnly)
328END_EVENT_TABLE()
329
330BEGIN_EVENT_TABLE(MyPanel, wxPanel)
331 EVT_CALENDAR(Calendar_CalCtrl, MyPanel::OnCalendar)
332 EVT_CALENDAR_PAGE_CHANGED(Calendar_CalCtrl, MyPanel::OnCalMonthChange)
333 EVT_CALENDAR_SEL_CHANGED(Calendar_CalCtrl, MyPanel::OnCalendarChange)
334 EVT_CALENDAR_WEEKDAY_CLICKED(Calendar_CalCtrl, MyPanel::OnCalendarWeekDayClick)
335 EVT_CALENDAR_WEEK_CLICKED(Calendar_CalCtrl, MyPanel::OnCalendarWeekClick)
336END_EVENT_TABLE()
337
338// Create a new application object: this macro will allow wxWidgets to create
339// the application object during program execution (it's better than using a
340// static object for many reasons) and also declares the accessor function
341// wxGetApp() which will return the reference of the right type (i.e. MyApp and
342// not wxApp)
343IMPLEMENT_APP(MyApp)
344
345// ============================================================================
346// implementation
347// ============================================================================
348
349// ----------------------------------------------------------------------------
350// the application class
351// ----------------------------------------------------------------------------
352
353// `Main program' equivalent: the program execution "starts" here
354bool MyApp::OnInit()
355{
356 if ( !wxApp::OnInit() )
357 return false;
358
359 // Create the main application window
360 MyFrame *frame = new MyFrame(wxT("Calendar wxWidgets sample")
361#ifndef __WXWINCE__
362 ,wxPoint(50, 50), wxSize(450, 340)
363#endif
364 );
365
366 frame->Show(true);
367
368 // success: wxApp::OnRun() will be called which will enter the main message
369 // loop and the application will run. If we returned false here, the
370 // application would exit immediately.
371 return true;
372}
373
374// ----------------------------------------------------------------------------
375// main frame
376// ----------------------------------------------------------------------------
377
378// frame constructor
379MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
380 : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size)
381{
382 // set the frame icon
383 SetIcon(wxICON(sample));
384
385 // create a menu bar
386 wxMenuBar *menuBar = new wxMenuBar;
387
388 wxMenu *menuFile = new wxMenu;
389 menuFile->Append(Calendar_File_About, wxT("&About\tCtrl-A"), wxT("Show about dialog"));
390 menuFile->AppendSeparator();
391 menuFile->Append(Calendar_File_ClearLog, wxT("&Clear log\tCtrl-L"));
392 menuFile->AppendSeparator();
393 menuFile->Append(Calendar_File_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
394 menuBar->Append(menuFile, wxT("&File"));
395
396 wxMenu *menuCal = new wxMenu;
397#ifdef wxHAS_NATIVE_CALENDARCTRL
398 menuCal->AppendCheckItem(Calendar_Cal_Generic, "Use &generic version\tCtrl-G",
399 "Toggle between native and generic control");
400 menuCal->AppendSeparator();
401#endif // wxHAS_NATIVE_CALENDARCTRL
402 menuCal->Append(Calendar_Cal_Monday,
403 wxT("Monday &first weekday\tCtrl-F"),
404 wxT("Toggle between Mon and Sun as the first week day"),
405 true);
406 menuCal->Append(Calendar_Cal_Holidays, wxT("Show &holidays\tCtrl-H"),
407 wxT("Toggle highlighting the holidays"),
408 true);
409 menuCal->Append(Calendar_Cal_Special, wxT("Highlight &special dates\tCtrl-S"),
410 wxT("Test custom highlighting"),
411 true);
412 menuCal->Append(Calendar_Cal_SurroundWeeks,
413 wxT("Show s&urrounding weeks\tCtrl-W"),
414 wxT("Show the neighbouring weeks in the prev/next month"),
415 true);
416 menuCal->Append(Calendar_Cal_WeekNumbers,
417 wxT("Show &week numbers"),
418 wxT("Toggle week numbers"),
419 true);
420 menuCal->AppendSeparator();
421 menuCal->Append(Calendar_Cal_SeqMonth,
422 wxT("Toggle month selector st&yle\tCtrl-Y"),
423 wxT("Use another style for the calendar controls"),
424 true);
425 menuCal->Append(Calendar_Cal_Month, wxT("&Month can be changed\tCtrl-M"),
426 wxT("Allow changing the month in the calendar"),
427 true);
428 menuCal->AppendCheckItem(Calendar_Cal_LimitDates, wxT("Toggle date ra&nge\tCtrl-N"),
429 wxT("Limit the valid dates"));
430 menuCal->AppendSeparator();
431 menuCal->Append(Calendar_Cal_SetDate, wxT("Call &SetDate(2005-12-24)"), wxT("Set date to 2005-12-24."));
432 menuCal->Append(Calendar_Cal_Today, wxT("Call &Today()"), wxT("Set to the current date."));
433 menuCal->Append(Calendar_Cal_BeginDST, "Call SetDate(GetBeginDST())");
434 menuCal->AppendSeparator();
435 menuCal->AppendCheckItem(Calendar_Cal_Resizable, wxT("Make &resizable\tCtrl-R"));
436 menuBar->Append(menuCal, wxT("&Calendar"));
437
438#if wxUSE_DATEPICKCTRL
439 wxMenu *menuDate = new wxMenu;
440 menuDate->AppendCheckItem(Calendar_DatePicker_ShowCentury,
441 wxT("Al&ways show century"));
442 menuDate->AppendCheckItem(Calendar_DatePicker_DropDown,
443 wxT("Use &drop down control"));
444 menuDate->AppendCheckItem(Calendar_DatePicker_AllowNone,
445 wxT("Allow &no date"));
446 menuDate->AppendCheckItem(Calendar_DatePicker_StartWithNone,
447 wxT("Start &with no date"));
448#if wxUSE_DATEPICKCTRL_GENERIC
449 menuDate->AppendCheckItem(Calendar_DatePicker_Generic,
450 wxT("Use &generic version of the control"));
451#endif // wxUSE_DATEPICKCTRL_GENERIC
452 menuDate->AppendSeparator();
453 menuDate->Append(Calendar_DatePicker_AskDate, wxT("&Choose date...\tCtrl-D"), wxT("Show dialog with wxDatePickerCtrl"));
454 menuBar->Append(menuDate, wxT("&Date picker"));
455#endif // wxUSE_DATEPICKCTRL
456
457#if wxUSE_TIMEPICKCTRL
458 wxMenu *menuTime = new wxMenu;
459#if wxUSE_TIMEPICKCTRL_GENERIC
460 menuTime->AppendCheckItem(Calendar_TimePicker_Generic,
461 wxT("Use &generic version of the control"));
462 menuTime->AppendSeparator();
463#endif // wxUSE_TIMEPICKCTRL_GENERIC
464 menuTime->Append(Calendar_TimePicker_AskTime, wxT("&Choose time...\tCtrl-T"), wxT("Show dialog with wxTimePickerCtrl"));
465 menuBar->Append(menuTime, wxT("&Time picker"));
466#endif // wxUSE_TIMEPICKCTRL
467
468 menuBar->Check(Calendar_Cal_Monday, true);
469 menuBar->Check(Calendar_Cal_Holidays, true);
470 menuBar->Check(Calendar_Cal_Month, true);
471 menuBar->Check(Calendar_Cal_LimitDates, false);
472
473#if wxUSE_DATEPICKCTRL
474 menuBar->Check(Calendar_DatePicker_ShowCentury, true);
475#endif // wxUSE_DATEPICKCTRL
476
477 // ... and attach this menu bar to the frame
478 SetMenuBar(menuBar);
479
480 wxSplitterWindow *splitter = new wxSplitterWindow(this, wxID_ANY,
481 wxDefaultPosition, wxDefaultSize,
482 wxSP_NOBORDER);
483 m_panel = new MyPanel(splitter);
484 m_logWindow = new wxTextCtrl(splitter, wxID_ANY, wxEmptyString,
485 wxDefaultPosition, wxDefaultSize,
486 wxTE_READONLY | wxTE_MULTILINE);
487 splitter->SplitHorizontally(m_panel, m_logWindow);
488 splitter->SetMinimumPaneSize(20);
489 wxLog::SetActiveTarget(new wxLogTextCtrl(m_logWindow));
490}
491
492void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
493{
494 // true is to force the frame to close
495 Close(true);
496}
497
498void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
499{
500 wxMessageBox(wxT("wxCalendarCtrl sample\n(c) 2000--2008 Vadim Zeitlin"),
501 wxT("About Calendar"), wxOK | wxICON_INFORMATION, this);
502}
503
504void MyFrame::OnClearLog(wxCommandEvent& WXUNUSED(event))
505{
506 m_logWindow->Clear();
507}
508
509void MyFrame::OnCalMonday(wxCommandEvent& event)
510{
511 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_MONDAY_FIRST);
512}
513
514void MyFrame::OnCalHolidays(wxCommandEvent& event)
515{
516 m_panel->GetCal()->EnableHolidayDisplay(event.IsChecked());
517}
518
519void MyFrame::OnCalSpecial(wxCommandEvent& event)
520{
521 m_panel->HighlightSpecial(GetMenuBar()->IsChecked(event.GetId()));
522}
523
524void MyFrame::OnCalLimitDates(wxCommandEvent& event)
525{
526 m_panel->LimitDateRange(GetMenuBar()->IsChecked(event.GetId()));
527}
528
529void MyFrame::OnCalAllowMonth(wxCommandEvent& event)
530{
531 m_panel->GetCal()->EnableMonthChange(event.IsChecked());
532}
533
534void MyFrame::OnCalSeqMonth(wxCommandEvent& event)
535{
536 m_panel->ToggleCalStyle(event.IsChecked(),
537 wxCAL_SEQUENTIAL_MONTH_SELECTION);
538}
539
540void MyFrame::OnCalShowSurroundingWeeks(wxCommandEvent& event)
541{
542 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SHOW_SURROUNDING_WEEKS);
543}
544
545void MyFrame::OnCalShowWeekNumbers(wxCommandEvent& event)
546{
547 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SHOW_WEEK_NUMBERS);
548}
549
550void MyFrame::OnSetDate(wxCommandEvent &WXUNUSED(event))
551{
552 m_panel->SetDate(wxDateTime(24, wxDateTime::Dec, 2005, 22, 00, 00));
553}
554
555void MyFrame::OnToday(wxCommandEvent &WXUNUSED(event))
556{
557 m_panel->SetDate(wxDateTime::Today());
558}
559
560void MyFrame::OnBeginDST(wxCommandEvent &WXUNUSED(event))
561{
562 m_panel->SetDate(wxDateTime::GetBeginDST(m_panel->GetDate().GetYear()));
563}
564
565void MyFrame::OnCalToggleResizable(wxCommandEvent& event)
566{
567 wxSizer * const sizer = m_panel->GetSizer();
568 wxSizerItem * const item = sizer->GetItem(m_panel->GetCal());
569 if ( event.IsChecked() )
570 {
571 item->SetProportion(1);
572 item->SetFlag(wxEXPAND);
573 }
574 else // not resizable
575 {
576 item->SetProportion(0);
577 item->SetFlag(wxALIGN_CENTER);
578 }
579
580 sizer->Layout();
581}
582
583void MyFrame::OnCalRClick(wxMouseEvent& event)
584{
585 wxDateTime dt;
586 wxDateTime::WeekDay wd;
587
588 const wxPoint pt = event.GetPosition();
589 wxString msg = wxString::Format("Point (%d, %d) is ", pt.x, pt.y);
590
591 switch ( m_panel->GetCal()->HitTest(pt, &dt, &wd) )
592 {
593 default:
594 wxFAIL_MSG( "unexpected" );
595 // fall through
596
597 case wxCAL_HITTEST_NOWHERE:
598 msg += "nowhere";
599 break;
600
601 case wxCAL_HITTEST_HEADER:
602 msg += wxString::Format("over %s", wxDateTime::GetWeekDayName(wd));
603 break;
604
605 case wxCAL_HITTEST_DAY:
606 msg += wxString::Format("over %s", dt.FormatISODate());
607 break;
608
609 case wxCAL_HITTEST_INCMONTH:
610 msg += "over next month button";
611 break;
612
613 case wxCAL_HITTEST_DECMONTH:
614 msg += "over previous month button";
615 break;
616
617 case wxCAL_HITTEST_SURROUNDING_WEEK:
618 msg += "over a day from another month";
619 break;
620 }
621
622 wxLogMessage("%s", msg);
623}
624
625#if wxUSE_DATEPICKCTRL
626
627void MyFrame::OnUpdateUIStartWithNone(wxUpdateUIEvent& event)
628{
629 // it only makes sense to start with invalid date if we can have no date
630 event.Enable( GetMenuBar()->IsChecked(Calendar_DatePicker_AllowNone) );
631}
632
633void MyFrame::OnAskDate(wxCommandEvent& WXUNUSED(event))
634{
635 wxDateTime dt = m_panel->GetCal()->GetDate();
636
637 int style = wxDP_DEFAULT;
638 if ( GetMenuBar()->IsChecked(Calendar_DatePicker_ShowCentury) )
639 style |= wxDP_SHOWCENTURY;
640 if ( GetMenuBar()->IsChecked(Calendar_DatePicker_DropDown) )
641 style |= wxDP_DROPDOWN;
642 if ( GetMenuBar()->IsChecked(Calendar_DatePicker_AllowNone) )
643 {
644 style |= wxDP_ALLOWNONE;
645
646 if ( GetMenuBar()->IsChecked(Calendar_DatePicker_StartWithNone) )
647 dt = wxDefaultDateTime;
648 }
649
650 MyDateDialog dlg(this, dt, style);
651 if ( dlg.ShowModal() == wxID_OK )
652 {
653 dt = dlg.GetDate();
654 if ( dt.IsValid() )
655 {
656 const wxDateTime today = wxDateTime::Today();
657
658 if ( dt.GetDay() == today.GetDay() &&
659 dt.GetMonth() == today.GetMonth() )
660 {
661 wxMessageBox(wxT("Happy birthday!"), wxT("Calendar Sample"));
662 }
663
664 m_panel->SetDate(dt);
665
666 wxLogStatus(wxT("Changed the date to your input"));
667 }
668 else
669 {
670 wxLogStatus(wxT("No date entered"));
671 }
672 }
673}
674
675#endif // wxUSE_DATEPICKCTRL
676
677#if wxUSE_TIMEPICKCTRL
678
679void MyFrame::OnAskTime(wxCommandEvent& WXUNUSED(event))
680{
681 MyTimeDialog dlg(this);
682 if ( dlg.ShowModal() == wxID_OK )
683 {
684 wxLogMessage("You entered %s", dlg.GetTime().FormatISOTime());
685 }
686}
687
688#endif // wxUSE_TIMEPICKCTRL
689
690// ----------------------------------------------------------------------------
691// MyPanel
692// ----------------------------------------------------------------------------
693
694MyPanel::MyPanel(wxWindow *parent)
695 : wxPanel(parent, wxID_ANY)
696{
697#ifdef wxHAS_NATIVE_CALENDARCTRL
698 m_usingGeneric = false;
699#else
700 m_usingGeneric = true;
701#endif
702
703 wxString date;
704 date.Printf(wxT("Selected date: %s"),
705 wxDateTime::Today().FormatISODate().c_str());
706 m_date = new wxStaticText(this, wxID_ANY, date);
707 m_calendar = DoCreateCalendar(wxDefaultDateTime,
708 wxCAL_MONDAY_FIRST | wxCAL_SHOW_HOLIDAYS);
709
710 // adjust to vertical/horizontal display, check mostly dedicated to WinCE
711 bool horizontal = ( wxSystemSettings::GetMetric(wxSYS_SCREEN_X) > wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) );
712 m_sizer = new wxBoxSizer( horizontal ? wxHORIZONTAL : wxVERTICAL );
713
714 m_sizer->Add(m_date, 0, wxALIGN_CENTER | wxALL, 10 );
715 m_sizer->Add(m_calendar, 0, wxALIGN_CENTER | wxALIGN_LEFT);
716
717 SetSizer( m_sizer );
718 m_sizer->SetSizeHints( this );
719}
720
721void MyPanel::OnCalendar(wxCalendarEvent& event)
722{
723 // clicking the same date twice unmarks it (convenient for testing)
724 static wxDateTime s_dateLast;
725 const bool mark = !s_dateLast.IsValid() || event.GetDate() != s_dateLast;
726
727 s_dateLast = event.GetDate();
728
729 m_calendar->Mark(event.GetDate().GetDay(), mark);
730 wxLogMessage(wxT("Selected (and %smarked) %s from calendar."),
731 mark ? "" : "un", s_dateLast.FormatISODate().c_str());
732}
733
734void MyPanel::OnCalendarChange(wxCalendarEvent& event)
735{
736 wxString s;
737 s.Printf(wxT("Selected date: %s"), event.GetDate().FormatISODate().c_str());
738
739 m_date->SetLabel(s);
740 wxLogStatus(s);
741}
742
743void MyPanel::OnCalMonthChange(wxCalendarEvent& event)
744{
745 wxLogStatus(wxT("Calendar month changed to %s %d"),
746 wxDateTime::GetMonthName(event.GetDate().GetMonth()),
747 event.GetDate().GetYear());
748}
749
750void MyPanel::OnCalendarWeekDayClick(wxCalendarEvent& event)
751{
752 wxLogMessage(wxT("Clicked on %s"),
753 wxDateTime::GetWeekDayName(event.GetWeekDay()).c_str());
754}
755
756void MyPanel::OnCalendarWeekClick(wxCalendarEvent& event)
757{
758 wxLogMessage(wxT("Clicked on week %d"), event.GetDate().GetWeekOfYear());
759}
760
761wxCalendarCtrlBase *MyPanel::DoCreateCalendar(const wxDateTime& dt, long style)
762{
763 wxCalendarCtrlBase *calendar;
764#ifdef wxHAS_NATIVE_CALENDARCTRL
765 if ( m_usingGeneric )
766 calendar = new wxGenericCalendarCtrl(this, Calendar_CalCtrl,
767 dt,
768 wxDefaultPosition,
769 wxDefaultSize,
770 style);
771 else
772#endif // wxHAS_NATIVE_CALENDARCTRL
773 calendar = new wxCalendarCtrl(this, Calendar_CalCtrl,
774 dt,
775 wxDefaultPosition,
776 wxDefaultSize,
777 style);
778
779 calendar->Connect(wxEVT_RIGHT_DOWN,
780 wxMouseEventHandler(MyFrame::OnCalRClick),
781 NULL,
782 ( MyFrame * )wxGetTopLevelParent(this));
783
784 return calendar;
785}
786
787void MyPanel::RecreateCalendar(long style)
788{
789 wxCalendarCtrlBase *calendar = DoCreateCalendar(m_calendar->GetDate(), style);
790
791 m_sizer->Replace(m_calendar, calendar);
792 delete m_calendar;
793 m_calendar = calendar;
794
795 m_sizer->Layout();
796}
797
798void MyPanel::ToggleCalStyle(bool on, int flag)
799{
800 long style = m_calendar->GetWindowStyle();
801 if ( on )
802 style |= flag;
803 else
804 style &= ~flag;
805
806 if ( flag == wxCAL_SEQUENTIAL_MONTH_SELECTION
807 || flag == wxCAL_SHOW_WEEK_NUMBERS)
808 {
809 // changing this style requires recreating the control
810 RecreateCalendar(style);
811 }
812 else // just changing the style is enough
813 {
814 m_calendar->SetWindowStyle(style);
815
816 m_calendar->Refresh();
817 }
818}
819
820void MyPanel::HighlightSpecial(bool on)
821{
822 if ( on )
823 {
824 wxCalendarDateAttr
825 *attrRedCircle = new wxCalendarDateAttr(wxCAL_BORDER_ROUND, *wxRED),
826 *attrGreenSquare = new wxCalendarDateAttr(wxCAL_BORDER_SQUARE, *wxGREEN),
827 *attrHeaderLike = new wxCalendarDateAttr(*wxBLUE, *wxLIGHT_GREY);
828
829 m_calendar->SetAttr(17, attrRedCircle);
830 m_calendar->SetAttr(29, attrGreenSquare);
831 m_calendar->SetAttr(13, attrHeaderLike);
832 }
833 else // off
834 {
835 m_calendar->ResetAttr(17);
836 m_calendar->ResetAttr(29);
837 m_calendar->ResetAttr(13);
838 }
839
840 m_calendar->Refresh();
841}
842
843// Toggle a restricted date range to the six months centered on today's date.
844void MyPanel::LimitDateRange(bool on)
845{
846 if ( on )
847 {
848 // limit the choice of date to 3 months around today
849 const wxDateSpan diff = wxDateSpan::Months(3);
850 const wxDateTime today = wxDateTime::Today();
851
852 // Set the restricted date range.
853 if ( m_calendar->SetDateRange(today - diff, today + diff) )
854 {
855 wxLogStatus("Date range limited to 3 months around today.");
856 wxDateTime firstValidDate;
857 wxDateTime lastValidDate;
858 if ( m_calendar->GetDateRange(&firstValidDate, &lastValidDate) )
859 {
860 wxLogMessage("First valid date: %s, last valid date: %s",
861 firstValidDate.FormatISODate(),
862 lastValidDate.FormatISODate());
863 }
864 else
865 {
866 wxLogWarning("Failed to get back the valid dates range.");
867 }
868 }
869 else
870 {
871 wxLogWarning("Date range not supported.");
872 }
873 }
874 else // off
875 {
876 // Remove the date restrictions.
877 if ( m_calendar->SetDateRange() )
878 {
879 wxLogStatus("Date choice is unlimited now.");
880 }
881 else
882 {
883 wxLogWarning("Date range not supported.");
884 }
885 }
886
887 m_calendar->Refresh();
888}
889
890// ----------------------------------------------------------------------------
891// MyDateDialog
892// ----------------------------------------------------------------------------
893
894#if wxUSE_DATEPICKCTRL
895
896BEGIN_EVENT_TABLE(MyDateDialog, wxDialog)
897 EVT_DATE_CHANGED(wxID_ANY, MyDateDialog::OnDateChange)
898END_EVENT_TABLE()
899
900MyDateDialog::MyDateDialog(wxWindow *parent, const wxDateTime& dt, int dtpStyle)
901 : wxDialog(parent, wxID_ANY, wxString(wxT("Calendar: Choose a date")))
902{
903#if wxUSE_DATEPICKCTRL_GENERIC
904 wxFrame *frame = (wxFrame *)wxGetTopLevelParent(parent);
905 if ( frame && frame->GetMenuBar()->IsChecked(Calendar_DatePicker_Generic) )
906 m_datePicker = new wxDatePickerCtrlGeneric(this, wxID_ANY, dt,
907 wxDefaultPosition,
908 wxDefaultSize,
909 dtpStyle);
910 else
911#endif // wxUSE_DATEPICKCTRL_GENERIC
912 m_datePicker = new wxDatePickerCtrl(this, wxID_ANY, dt,
913 wxDefaultPosition, wxDefaultSize,
914 dtpStyle);
915 m_datePicker->SetRange(wxDateTime(1, wxDateTime::Jan, 1900),
916 wxDefaultDateTime);
917 m_dateText = new wxStaticText(this, wxID_ANY,
918 dt.IsValid() ? dt.FormatISODate()
919 : wxString());
920
921 const wxSizerFlags flags = wxSizerFlags().Centre().Border();
922 wxFlexGridSizer* const sizerMain = new wxFlexGridSizer(2);
923 sizerMain->Add(new wxStaticText(this, wxID_ANY, "Enter &date:"), flags);
924 sizerMain->Add(m_datePicker, flags);
925
926 sizerMain->Add(new wxStaticText(this, wxID_ANY, "Date in ISO format:"),
927 flags);
928 sizerMain->Add(m_dateText, flags);
929
930 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
931 sizerTop->Add(sizerMain, flags);
932 sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), flags);
933
934 SetSizerAndFit(sizerTop);
935}
936
937void MyDateDialog::OnDateChange(wxDateEvent& event)
938{
939 const wxDateTime dt = event.GetDate();
940 if ( dt.IsValid() )
941 m_dateText->SetLabel(dt.FormatISODate());
942 else
943 m_dateText->SetLabel(wxEmptyString);
944}
945
946#endif // wxUSE_DATEPICKCTRL
947
948// ----------------------------------------------------------------------------
949// MyTimeDialog
950// ----------------------------------------------------------------------------
951
952#if wxUSE_TIMEPICKCTRL
953
954BEGIN_EVENT_TABLE(MyTimeDialog, wxDialog)
955 EVT_TIME_CHANGED(wxID_ANY, MyTimeDialog::OnTimeChange)
956END_EVENT_TABLE()
957
958MyTimeDialog::MyTimeDialog(wxWindow *parent)
959 : wxDialog(parent, wxID_ANY, wxString(wxT("Calendar: Choose time")))
960{
961#if wxUSE_TIMEPICKCTRL_GENERIC
962 wxFrame *frame = (wxFrame *)wxGetTopLevelParent(parent);
963 if ( frame && frame->GetMenuBar()->IsChecked(Calendar_TimePicker_Generic) )
964 m_timePicker = new wxTimePickerCtrlGeneric(this, wxID_ANY);
965 else
966#endif // wxUSE_TIMEPICKCTRL_GENERIC
967 m_timePicker = new wxTimePickerCtrl(this, wxID_ANY);
968 m_timeText = new wxStaticText(this, wxID_ANY,
969 m_timePicker->GetValue().FormatISOTime());
970
971 const wxSizerFlags flags = wxSizerFlags().Centre().Border();
972 wxFlexGridSizer* const sizerMain = new wxFlexGridSizer(2);
973 sizerMain->Add(new wxStaticText(this, wxID_ANY, "Enter &time:"), flags);
974 sizerMain->Add(m_timePicker, flags);
975
976 sizerMain->Add(new wxStaticText(this, wxID_ANY, "Time in ISO format:"),
977 flags);
978 sizerMain->Add(m_timeText, flags);
979
980 wxSizer* sizerTop = new wxBoxSizer(wxVERTICAL);
981 sizerTop->Add(sizerMain, flags);
982 sizerTop->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), flags);
983
984 SetSizerAndFit(sizerTop);
985}
986
987void MyTimeDialog::OnTimeChange(wxDateEvent& event)
988{
989 m_timeText->SetLabel(event.GetDate().FormatISOTime());
990}
991
992#endif // wxUSE_TIMEPICKCTRL