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