added API, docs and Win32 implementation of wxDatePickerCtrl
[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 #if defined(__GNUG__) && !defined(__APPLE__)
21 #pragma implementation "calendar.cpp"
22 #pragma interface "calendar.cpp"
23 #endif
24
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
27
28 #ifdef __BORLANDC__
29 #pragma hdrstop
30 #endif
31
32 // for all others, include the necessary headers
33 #ifndef WX_PRECOMP
34 #include "wx/app.h"
35 #include "wx/log.h"
36 #include "wx/frame.h"
37 #include "wx/panel.h"
38 #include "wx/stattext.h"
39 #include "wx/menu.h"
40 #include "wx/layout.h"
41 #include "wx/msgdlg.h"
42 #endif
43
44 #include "wx/sizer.h"
45 #include "wx/textctrl.h"
46
47 #include "wx/calctrl.h"
48 #include "wx/datectrl.h"
49
50 #define wxUSE_DATEPICKERCTRL 1
51
52 // ----------------------------------------------------------------------------
53 // private classes
54 // ----------------------------------------------------------------------------
55
56 // Define a new application type, each program should derive a class from wxApp
57 class MyApp : public wxApp
58 {
59 public:
60 // override base class virtuals
61 // ----------------------------
62
63 // this one is called on application startup and is a good place for the app
64 // initialization (doing it here and not in the ctor allows to have an error
65 // return: if OnInit() returns false, the application terminates)
66 virtual bool OnInit();
67 };
68
69 class MyPanel : public wxPanel
70 {
71 public:
72 MyPanel(wxFrame *frame);
73
74 void OnCalendar(wxCalendarEvent& event);
75 void OnCalendarWeekDayClick(wxCalendarEvent& event);
76 void OnCalendarChange(wxCalendarEvent& event);
77 void OnCalMonthChange(wxCalendarEvent& event);
78 void OnCalYearChange(wxCalendarEvent& event);
79
80 wxCalendarCtrl *GetCal() const { return m_calendar; }
81
82 // turn on/off the specified style bit on the calendar control
83 void ToggleCalStyle(bool on, int style);
84
85 void HighlightSpecial(bool on);
86
87 void SetDate();
88 void Today();
89
90 private:
91 wxCalendarCtrl *m_calendar;
92 wxStaticText *m_date;
93
94 DECLARE_EVENT_TABLE()
95 };
96
97 // Define a new frame type: this is going to be our main frame
98 class MyFrame : public wxFrame
99 {
100 public:
101 // ctor(s)
102 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
103
104 // event handlers (these functions should _not_ be virtual)
105 void OnQuit(wxCommandEvent& event);
106 void OnAbout(wxCommandEvent& event);
107
108 #if wxUSE_DATEPICKERCTRL
109 void OnAskDate(wxCommandEvent& event);
110 #endif // wxUSE_DATEPICKERCTRL
111
112 void OnCalMonday(wxCommandEvent& event);
113 void OnCalHolidays(wxCommandEvent& event);
114 void OnCalSpecial(wxCommandEvent& event);
115
116 void OnCalAllowMonth(wxCommandEvent& event);
117 void OnCalAllowYear(wxCommandEvent& event);
118
119 void OnCalSeqMonth(wxCommandEvent& event);
120 void OnCalShowSurroundingWeeks(wxCommandEvent& event);
121
122 void OnSetDate(wxCommandEvent& event);
123 void OnToday(wxCommandEvent& event);
124
125 void OnAllowYearUpdate(wxUpdateUIEvent& event);
126
127 private:
128 MyPanel *m_panel;
129
130 // any class wishing to process wxWidgets events must use this macro
131 DECLARE_EVENT_TABLE()
132 };
133
134 #if wxUSE_DATEPICKERCTRL
135
136 // Define a simple modal dialog which asks the user for a date
137 class MyDialog : public wxDialog
138 {
139 public:
140 MyDialog(wxWindow *parent, const wxDateTime& dt);
141
142 wxDateTime GetDate() const { return m_datePicker->GetValue(); }
143
144 private:
145 void OnDateChange(wxDateEvent& event);
146
147
148 wxDatePickerCtrl *m_datePicker;
149 wxTextCtrl *m_text;
150
151
152 DECLARE_EVENT_TABLE()
153 };
154
155 #endif // wxUSE_DATEPICKERCTRL
156
157 // ----------------------------------------------------------------------------
158 // constants
159 // ----------------------------------------------------------------------------
160
161 // IDs for the controls and the menu commands
162 enum
163 {
164 // menu items
165 Calendar_File_About = wxID_ABOUT,
166 Calendar_File_Quit = wxID_EXIT,
167 #if wxUSE_DATEPICKERCTRL
168 Calendar_File_AskDate = 100,
169 #endif // wxUSE_DATEPICKERCTRL
170 Calendar_Cal_Monday = 200,
171 Calendar_Cal_Holidays,
172 Calendar_Cal_Special,
173 Calendar_Cal_Month,
174 Calendar_Cal_Year,
175 Calendar_Cal_SeqMonth,
176 Calendar_Cal_SurroundWeeks,
177 Calendar_Cal_SetDate,
178 Calendar_Cal_Today,
179 Calendar_CalCtrl = 1000
180 };
181
182 // ----------------------------------------------------------------------------
183 // event tables and other macros for wxWidgets
184 // ----------------------------------------------------------------------------
185
186 // the event tables connect the wxWidgets events with the functions (event
187 // handlers) which process them. It can be also done at run-time, but for the
188 // simple menu events like this the static method is much simpler.
189 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
190 EVT_MENU(Calendar_File_Quit, MyFrame::OnQuit)
191 EVT_MENU(Calendar_File_About, MyFrame::OnAbout)
192
193 #if wxUSE_DATEPICKERCTRL
194 EVT_MENU(Calendar_File_AskDate, MyFrame::OnAskDate)
195 #endif // wxUSE_DATEPICKERCTRL
196
197 EVT_MENU(Calendar_Cal_Monday, MyFrame::OnCalMonday)
198 EVT_MENU(Calendar_Cal_Holidays, MyFrame::OnCalHolidays)
199 EVT_MENU(Calendar_Cal_Special, MyFrame::OnCalSpecial)
200
201 EVT_MENU(Calendar_Cal_Month, MyFrame::OnCalAllowMonth)
202 EVT_MENU(Calendar_Cal_Year, MyFrame::OnCalAllowYear)
203
204 EVT_MENU(Calendar_Cal_SeqMonth, MyFrame::OnCalSeqMonth)
205 EVT_MENU(Calendar_Cal_SurroundWeeks, MyFrame::OnCalShowSurroundingWeeks)
206
207 EVT_MENU(Calendar_Cal_SetDate, MyFrame::OnSetDate)
208 EVT_MENU(Calendar_Cal_Today, MyFrame::OnToday)
209
210
211 EVT_UPDATE_UI(Calendar_Cal_Year, MyFrame::OnAllowYearUpdate)
212 END_EVENT_TABLE()
213
214 BEGIN_EVENT_TABLE(MyPanel, wxPanel)
215 EVT_CALENDAR (Calendar_CalCtrl, MyPanel::OnCalendar)
216 EVT_CALENDAR_MONTH (Calendar_CalCtrl, MyPanel::OnCalMonthChange)
217 EVT_CALENDAR_YEAR (Calendar_CalCtrl, MyPanel::OnCalYearChange)
218 EVT_CALENDAR_SEL_CHANGED(Calendar_CalCtrl, MyPanel::OnCalendarChange)
219 EVT_CALENDAR_WEEKDAY_CLICKED(Calendar_CalCtrl, MyPanel::OnCalendarWeekDayClick)
220 END_EVENT_TABLE()
221
222 #if wxUSE_DATEPICKERCTRL
223
224 BEGIN_EVENT_TABLE(MyDialog, wxDialog)
225 EVT_DATE_CHANGED(wxID_ANY, MyDialog::OnDateChange)
226 END_EVENT_TABLE()
227
228 #endif // wxUSE_DATEPICKERCTRL
229
230 // Create a new application object: this macro will allow wxWidgets to create
231 // the application object during program execution (it's better than using a
232 // static object for many reasons) and also declares the accessor function
233 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
234 // not wxApp)
235 IMPLEMENT_APP(MyApp)
236
237 // ============================================================================
238 // implementation
239 // ============================================================================
240
241 // ----------------------------------------------------------------------------
242 // the application class
243 // ----------------------------------------------------------------------------
244
245 // `Main program' equivalent: the program execution "starts" here
246 bool MyApp::OnInit()
247 {
248 // Create the main application window
249 MyFrame *frame = new MyFrame(_T("Calendar wxWidgets sample"),
250 wxPoint(50, 50), wxSize(450, 340));
251
252 frame->Show(true);
253
254 // success: wxApp::OnRun() will be called which will enter the main message
255 // loop and the application will run. If we returned false here, the
256 // application would exit immediately.
257 return true;
258 }
259
260 // ----------------------------------------------------------------------------
261 // main frame
262 // ----------------------------------------------------------------------------
263
264 // frame constructor
265 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
266 : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size)
267 {
268 // create a menu bar
269 wxMenu *menuFile = new wxMenu;
270
271 #if wxUSE_DATEPICKERCTRL
272 menuFile->Append(Calendar_File_AskDate, _T("&Choose date...\tCtrl-D"), _T("Show dialog with wxDatePickerCtrl"));
273 menuFile->AppendSeparator();
274 #endif // wxUSE_DATEPICKERCTRL
275
276 menuFile->Append(Calendar_File_About, _T("&About...\tCtrl-A"), _T("Show about dialog"));
277 menuFile->AppendSeparator();
278 menuFile->Append(Calendar_File_Quit, _T("E&xit\tAlt-X"), _T("Quit this program"));
279
280 wxMenu *menuCal = new wxMenu;
281 menuCal->Append(Calendar_Cal_Monday,
282 _T("Monday &first weekday\tCtrl-F"),
283 _T("Toggle between Mon and Sun as the first week day"),
284 true);
285 menuCal->Append(Calendar_Cal_Holidays, _T("Show &holidays\tCtrl-H"),
286 _T("Toggle highlighting the holidays"),
287 true);
288 menuCal->Append(Calendar_Cal_Special, _T("Highlight &special dates\tCtrl-S"),
289 _T("Test custom highlighting"),
290 true);
291 menuCal->Append(Calendar_Cal_SurroundWeeks,
292 _T("Show s&urrounding weeks\tCtrl-W"),
293 _T("Show the neighbouring weeks in the prev/next month"),
294 true);
295 menuCal->AppendSeparator();
296 menuCal->Append(Calendar_Cal_SeqMonth,
297 _T("To&ggle month selector style\tCtrl-G"),
298 _T("Use another style for the calendar controls"),
299 true);
300 menuCal->Append(Calendar_Cal_Month, _T("&Month can be changed\tCtrl-M"),
301 _T("Allow changing the month in the calendar"),
302 true);
303 menuCal->Append(Calendar_Cal_Year, _T("&Year can be changed\tCtrl-Y"),
304 _T("Allow changing the year in the calendar"),
305 true);
306 menuCal->AppendSeparator();
307 menuCal->Append(Calendar_Cal_SetDate, _T("SetDate()"), _T("Set date to 2005-12-24."));
308 menuCal->Append(Calendar_Cal_Today, _T("Today()"), _T("Set the current date."));
309
310 // now append the freshly created menu to the menu bar...
311 wxMenuBar *menuBar = new wxMenuBar;
312 menuBar->Append(menuFile, _T("&File"));
313 menuBar->Append(menuCal, _T("&Calendar"));
314
315 menuBar->Check(Calendar_Cal_Monday, true);
316 menuBar->Check(Calendar_Cal_Holidays, true);
317 menuBar->Check(Calendar_Cal_Month, true);
318 menuBar->Check(Calendar_Cal_Year, true);
319
320 // ... and attach this menu bar to the frame
321 SetMenuBar(menuBar);
322
323 m_panel = new MyPanel(this);
324
325 #if wxUSE_STATUSBAR
326 // create a status bar just for fun (by default with 1 pane only)
327 CreateStatusBar(2);
328 SetStatusText(_T("Welcome to wxWidgets!"));
329 #endif // wxUSE_STATUSBAR
330 }
331
332 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
333 {
334 // true is to force the frame to close
335 Close(true);
336 }
337
338 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
339 {
340 wxMessageBox(_T("wxCalendarCtrl sample\n(c) 2000 Vadim Zeitlin"),
341 _T("About Calendar"), wxOK | wxICON_INFORMATION, this);
342 }
343
344 void MyFrame::OnCalMonday(wxCommandEvent& event)
345 {
346 bool enable = GetMenuBar()->IsChecked(event.GetId());
347
348 m_panel->ToggleCalStyle(enable, wxCAL_MONDAY_FIRST);
349 }
350
351 void MyFrame::OnCalHolidays(wxCommandEvent& event)
352 {
353 bool enable = GetMenuBar()->IsChecked(event.GetId());
354
355 m_panel->GetCal()->EnableHolidayDisplay(enable);
356 }
357
358 void MyFrame::OnCalSpecial(wxCommandEvent& event)
359 {
360 m_panel->HighlightSpecial(GetMenuBar()->IsChecked(event.GetId()));
361 }
362
363 void MyFrame::OnCalAllowMonth(wxCommandEvent& event)
364 {
365 bool allow = GetMenuBar()->IsChecked(event.GetId());
366
367 m_panel->GetCal()->EnableMonthChange(allow);
368 }
369
370 void MyFrame::OnCalAllowYear(wxCommandEvent& event)
371 {
372 bool allow = GetMenuBar()->IsChecked(event.GetId());
373
374 m_panel->GetCal()->EnableYearChange(allow);
375 }
376
377 void MyFrame::OnCalSeqMonth(wxCommandEvent& event)
378 {
379 bool allow = GetMenuBar()->IsChecked(event.GetId());
380
381 m_panel->ToggleCalStyle(allow, wxCAL_SEQUENTIAL_MONTH_SELECTION);
382 }
383
384 void MyFrame::OnCalShowSurroundingWeeks(wxCommandEvent& event)
385 {
386 bool allow = GetMenuBar()->IsChecked(event.GetId());
387
388 m_panel->ToggleCalStyle(allow, wxCAL_SHOW_SURROUNDING_WEEKS);
389 }
390
391 void MyFrame::OnAllowYearUpdate(wxUpdateUIEvent& event)
392 {
393 event.Enable( GetMenuBar()->IsChecked(Calendar_Cal_Month));
394 }
395
396 void MyFrame::OnSetDate(wxCommandEvent &WXUNUSED(event))
397 {
398 m_panel->SetDate();
399 }
400
401 void MyFrame::OnToday(wxCommandEvent &WXUNUSED(event))
402 {
403 m_panel->Today();
404 }
405
406 #if wxUSE_DATEPICKERCTRL
407
408 void MyFrame::OnAskDate(wxCommandEvent& WXUNUSED(event))
409 {
410 MyDialog dlg(this, m_panel->GetCal()->GetDate());
411 if ( dlg.ShowModal() == wxID_OK )
412 {
413 const wxDateTime dt = dlg.GetDate(),
414 today = wxDateTime::Today();
415
416 if ( dt.GetDay() == today.GetDay() &&
417 dt.GetMonth() == today.GetMonth() )
418 {
419 wxMessageBox(_T("Happy birthday!"), _T("Calendar Sample"));
420 }
421
422 m_panel->GetCal()->SetDate(dt);
423
424 wxLogStatus(_T("Changed the date to your birthday"));
425 }
426 }
427
428 #endif // wxUSE_DATEPICKERCTRL
429
430 // ----------------------------------------------------------------------------
431 // MyPanel
432 // ----------------------------------------------------------------------------
433
434 MyPanel::MyPanel(wxFrame *frame)
435 : wxPanel(frame, wxID_ANY)
436 {
437 wxString date;
438 date.Printf(wxT("Selected date: %s"),
439 wxDateTime::Today().FormatISODate().c_str());
440 m_date = new wxStaticText(this, wxID_ANY, date);
441 m_calendar = new wxCalendarCtrl(this, Calendar_CalCtrl,
442 wxDefaultDateTime,
443 wxDefaultPosition,
444 wxDefaultSize,
445 wxCAL_MONDAY_FIRST |
446 wxCAL_SHOW_HOLIDAYS |
447 wxRAISED_BORDER);
448
449 wxBoxSizer *m_sizer = new wxBoxSizer( wxHORIZONTAL );
450
451 m_sizer->Add(m_date, 0, wxALIGN_CENTER | wxALL, 10 );
452 m_sizer->Add(m_calendar, 0, wxALIGN_CENTER | wxALIGN_LEFT);
453
454 SetSizer( m_sizer );
455 m_sizer->SetSizeHints( this );
456 }
457
458 void MyPanel::OnCalendar(wxCalendarEvent& event)
459 {
460 wxLogMessage(wxT("Selected %s from calendar"),
461 event.GetDate().FormatISODate().c_str());
462 }
463
464 void MyPanel::OnCalendarChange(wxCalendarEvent& event)
465 {
466 wxString s;
467 s.Printf(wxT("Selected date: %s"), event.GetDate().FormatISODate().c_str());
468
469 m_date->SetLabel(s);
470 }
471
472 void MyPanel::OnCalMonthChange(wxCalendarEvent& WXUNUSED(event))
473 {
474 wxLogStatus(wxT("Calendar month changed"));
475 }
476
477 void MyPanel::OnCalYearChange(wxCalendarEvent& WXUNUSED(event))
478 {
479 wxLogStatus(wxT("Calendar year changed"));
480 }
481
482 void MyPanel::OnCalendarWeekDayClick(wxCalendarEvent& event)
483 {
484 wxLogMessage(wxT("Clicked on %s"),
485 wxDateTime::GetWeekDayName(event.GetWeekDay()).c_str());
486 }
487
488 void MyPanel::ToggleCalStyle(bool on, int flag)
489 {
490 long style = m_calendar->GetWindowStyle();
491 if ( on )
492 style |= flag;
493 else
494 style &= ~flag;
495
496 m_calendar->SetWindowStyle(style);
497
498 m_calendar->Refresh();
499 }
500
501 void MyPanel::HighlightSpecial(bool on)
502 {
503 if ( on )
504 {
505 wxCalendarDateAttr
506 *attrRedCircle = new wxCalendarDateAttr(wxCAL_BORDER_ROUND, *wxRED),
507 *attrGreenSquare = new wxCalendarDateAttr(wxCAL_BORDER_SQUARE, *wxGREEN),
508 *attrHeaderLike = new wxCalendarDateAttr(*wxBLUE, *wxLIGHT_GREY);
509
510 m_calendar->SetAttr(17, attrRedCircle);
511 m_calendar->SetAttr(29, attrGreenSquare);
512 m_calendar->SetAttr(13, attrHeaderLike);
513 }
514 else // off
515 {
516 m_calendar->ResetAttr(17);
517 m_calendar->ResetAttr(29);
518 m_calendar->ResetAttr(13);
519 }
520
521 m_calendar->Refresh();
522 }
523
524 void MyPanel::SetDate()
525 {
526 wxDateTime date(24, wxDateTime::Dec, 2005, 23, 59, 59);
527 m_calendar->SetDate(date);
528 }
529
530 void MyPanel::Today()
531 {
532 m_calendar->SetDate(wxDateTime::Today());
533 }
534
535 // ----------------------------------------------------------------------------
536 // MyDialog
537 // ----------------------------------------------------------------------------
538
539 #if wxUSE_DATEPICKERCTRL
540
541 MyDialog::MyDialog(wxWindow *parent, const wxDateTime& dt)
542 : wxDialog(parent, -1, wxString(_T("Calendar: Choose a date")))
543 {
544 wxStdDialogButtonSizer *sizerBtns = new wxStdDialogButtonSizer;
545 sizerBtns->AddButton(new wxButton(this, wxID_OK));
546 sizerBtns->AddButton(new wxButton(this, wxID_CANCEL));
547 sizerBtns->Finalise();
548
549 wxSizer *sizerText = new wxBoxSizer(wxHORIZONTAL);
550 sizerText->Add(new wxStaticText(this, -1, _T("Date in ISO format: ")),
551 wxSizerFlags().Border());
552 m_text = new wxTextCtrl(this, -1);
553 sizerText->Add(m_text, wxSizerFlags().Expand().Border());
554
555 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
556 sizerTop->Add(new wxStaticText
557 (
558 this, -1,
559 _T("Enter your birthday date (not before 20th century):")
560 ),
561 wxSizerFlags().Border());
562
563 m_datePicker = new wxDatePickerCtrl(this, -1, dt);
564 m_datePicker->SetRange(wxDateTime(1, wxDateTime::Jan, 1900),
565 wxDefaultDateTime);
566 sizerTop->Add(m_datePicker, wxSizerFlags().Expand().Border());
567
568 sizerTop->AddStretchSpacer(1);
569 sizerTop->Add(sizerText);
570
571 sizerTop->Add(sizerBtns, wxSizerFlags().Centre().Border());
572
573 SetSizerAndFit(sizerTop);
574 Layout();
575 }
576
577 void MyDialog::OnDateChange(wxDateEvent& event)
578 {
579 m_text->SetValue(event.GetDate().FormatISODate());
580 }
581
582 #endif // wxUSE_DATEPICKERCTRL
583