]> git.saurik.com Git - wxWidgets.git/blob - samples/calendar/calendar.cpp
supporting alignment in single line controls, see #14452
[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 #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
72 class MyApp : public wxApp
73 {
74 public:
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
84 class MyPanel : public wxPanel
85 {
86 public:
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
113 private:
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
129 class MyFrame : public wxFrame
130 {
131 public:
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
180 private:
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
191 class MyDateDialog : public wxDialog
192 {
193 public:
194 MyDateDialog(wxWindow *parent, const wxDateTime& dt, int dtpStyle);
195
196 wxDateTime GetDate() const { return m_datePicker->GetValue(); }
197
198 private:
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.
214 class MyTimeDialog : public wxDialog
215 {
216 public:
217 MyTimeDialog(wxWindow* parent);
218
219 wxDateTime GetTime() const { return m_timePicker->GetValue(); }
220
221 private:
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
237 enum
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.
282 BEGIN_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)
328 END_EVENT_TABLE()
329
330 BEGIN_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)
336 END_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)
343 IMPLEMENT_APP(MyApp)
344
345 // ============================================================================
346 // implementation
347 // ============================================================================
348
349 // ----------------------------------------------------------------------------
350 // the application class
351 // ----------------------------------------------------------------------------
352
353 // `Main program' equivalent: the program execution "starts" here
354 bool 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
379 MyFrame::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
492 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
493 {
494 // true is to force the frame to close
495 Close(true);
496 }
497
498 void 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
504 void MyFrame::OnClearLog(wxCommandEvent& WXUNUSED(event))
505 {
506 m_logWindow->Clear();
507 }
508
509 void MyFrame::OnCalMonday(wxCommandEvent& event)
510 {
511 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_MONDAY_FIRST);
512 }
513
514 void MyFrame::OnCalHolidays(wxCommandEvent& event)
515 {
516 m_panel->GetCal()->EnableHolidayDisplay(event.IsChecked());
517 }
518
519 void MyFrame::OnCalSpecial(wxCommandEvent& event)
520 {
521 m_panel->HighlightSpecial(GetMenuBar()->IsChecked(event.GetId()));
522 }
523
524 void MyFrame::OnCalLimitDates(wxCommandEvent& event)
525 {
526 m_panel->LimitDateRange(GetMenuBar()->IsChecked(event.GetId()));
527 }
528
529 void MyFrame::OnCalAllowMonth(wxCommandEvent& event)
530 {
531 m_panel->GetCal()->EnableMonthChange(event.IsChecked());
532 }
533
534 void MyFrame::OnCalSeqMonth(wxCommandEvent& event)
535 {
536 m_panel->ToggleCalStyle(event.IsChecked(),
537 wxCAL_SEQUENTIAL_MONTH_SELECTION);
538 }
539
540 void MyFrame::OnCalShowSurroundingWeeks(wxCommandEvent& event)
541 {
542 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SHOW_SURROUNDING_WEEKS);
543 }
544
545 void MyFrame::OnCalShowWeekNumbers(wxCommandEvent& event)
546 {
547 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SHOW_WEEK_NUMBERS);
548 }
549
550 void MyFrame::OnSetDate(wxCommandEvent &WXUNUSED(event))
551 {
552 m_panel->SetDate(wxDateTime(24, wxDateTime::Dec, 2005, 22, 00, 00));
553 }
554
555 void MyFrame::OnToday(wxCommandEvent &WXUNUSED(event))
556 {
557 m_panel->SetDate(wxDateTime::Today());
558 }
559
560 void MyFrame::OnBeginDST(wxCommandEvent &WXUNUSED(event))
561 {
562 m_panel->SetDate(wxDateTime::GetBeginDST(m_panel->GetDate().GetYear()));
563 }
564
565 void 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
583 void 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
627 void 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
633 void 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
679 void 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
694 MyPanel::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
721 void 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
734 void 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
743 void 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
750 void MyPanel::OnCalendarWeekDayClick(wxCalendarEvent& event)
751 {
752 wxLogMessage(wxT("Clicked on %s"),
753 wxDateTime::GetWeekDayName(event.GetWeekDay()).c_str());
754 }
755
756 void MyPanel::OnCalendarWeekClick(wxCalendarEvent& event)
757 {
758 wxLogMessage(wxT("Clicked on week %d"), event.GetDate().GetWeekOfYear());
759 }
760
761 wxCalendarCtrlBase *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
787 void 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
798 void 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
820 void 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.
844 void 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
896 BEGIN_EVENT_TABLE(MyDateDialog, wxDialog)
897 EVT_DATE_CHANGED(wxID_ANY, MyDateDialog::OnDateChange)
898 END_EVENT_TABLE()
899
900 MyDateDialog::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, wxString());
918
919 const wxSizerFlags flags = wxSizerFlags().Centre().Border();
920 wxFlexGridSizer* const sizerMain = new wxFlexGridSizer(2);
921 sizerMain->Add(new wxStaticText(this, wxID_ANY, "Enter &date:"), flags);
922 sizerMain->Add(m_datePicker, flags);
923
924 sizerMain->Add(new wxStaticText(this, wxID_ANY, "Date in ISO format:"),
925 flags);
926 sizerMain->Add(m_dateText, flags);
927
928 wxStdDialogButtonSizer *sizerBtns = new wxStdDialogButtonSizer;
929 sizerBtns->AddButton(new wxButton(this, wxID_OK));
930 sizerBtns->AddButton(new wxButton(this, wxID_CANCEL));
931 sizerBtns->Realize();
932
933 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
934 sizerTop->Add(sizerMain, flags);
935 sizerTop->Add(sizerBtns, flags);
936
937 SetSizerAndFit(sizerTop);
938 }
939
940 void MyDateDialog::OnDateChange(wxDateEvent& event)
941 {
942 const wxDateTime dt = event.GetDate();
943 if ( dt.IsValid() )
944 m_dateText->SetLabel(dt.FormatISODate());
945 else
946 m_dateText->SetLabel(wxEmptyString);
947 }
948
949 #endif // wxUSE_DATEPICKCTRL
950
951 // ----------------------------------------------------------------------------
952 // MyTimeDialog
953 // ----------------------------------------------------------------------------
954
955 #if wxUSE_TIMEPICKCTRL
956
957 BEGIN_EVENT_TABLE(MyTimeDialog, wxDialog)
958 EVT_TIME_CHANGED(wxID_ANY, MyTimeDialog::OnTimeChange)
959 END_EVENT_TABLE()
960
961 MyTimeDialog::MyTimeDialog(wxWindow *parent)
962 : wxDialog(parent, wxID_ANY, wxString(wxT("Calendar: Choose time")))
963 {
964 #if wxUSE_TIMEPICKCTRL_GENERIC
965 wxFrame *frame = (wxFrame *)wxGetTopLevelParent(parent);
966 if ( frame && frame->GetMenuBar()->IsChecked(Calendar_TimePicker_Generic) )
967 m_timePicker = new wxTimePickerCtrlGeneric(this, wxID_ANY);
968 else
969 #endif // wxUSE_TIMEPICKCTRL_GENERIC
970 m_timePicker = new wxTimePickerCtrl(this, wxID_ANY);
971 m_timeText = new wxStaticText(this, wxID_ANY, wxString());
972
973 const wxSizerFlags flags = wxSizerFlags().Centre().Border();
974 wxFlexGridSizer* const sizerMain = new wxFlexGridSizer(2);
975 sizerMain->Add(new wxStaticText(this, wxID_ANY, "Enter &time:"), flags);
976 sizerMain->Add(m_timePicker, flags);
977
978 sizerMain->Add(new wxStaticText(this, wxID_ANY, "Time in ISO format:"),
979 flags);
980 sizerMain->Add(m_timeText, flags);
981
982 wxStdDialogButtonSizer* sizerBtns = new wxStdDialogButtonSizer;
983 sizerBtns->AddButton(new wxButton(this, wxID_OK));
984 sizerBtns->AddButton(new wxButton(this, wxID_CANCEL));
985 sizerBtns->Realize();
986
987 wxSizer* sizerTop = new wxBoxSizer(wxVERTICAL);
988 sizerTop->Add(sizerMain, flags);
989 sizerTop->Add(sizerBtns, flags);
990
991 SetSizerAndFit(sizerTop);
992 }
993
994 void MyTimeDialog::OnTimeChange(wxDateEvent& event)
995 {
996 m_timeText->SetLabel(event.GetDate().FormatISOTime());
997 }
998
999 #endif // wxUSE_TIMEPICKCTRL