]> git.saurik.com Git - wxWidgets.git/blob - samples/calendar/calendar.cpp
Don't enter an infinite loop if a spacer with min size of -1 is used.
[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 EVT_UPDATE_UI(Calendar_Cal_LimitDates, MyFrame::OnUpdateUIGenericOnly)
284 #endif
285 EVT_UPDATE_UI(Calendar_Cal_Special, MyFrame::OnUpdateUIGenericOnly)
286 EVT_UPDATE_UI(Calendar_Cal_SurroundWeeks, MyFrame::OnUpdateUIGenericOnly)
287 END_EVENT_TABLE()
288
289 BEGIN_EVENT_TABLE(MyPanel, wxPanel)
290 EVT_CALENDAR(Calendar_CalCtrl, MyPanel::OnCalendar)
291 EVT_CALENDAR_PAGE_CHANGED(Calendar_CalCtrl, MyPanel::OnCalMonthChange)
292 EVT_CALENDAR_SEL_CHANGED(Calendar_CalCtrl, MyPanel::OnCalendarChange)
293 EVT_CALENDAR_WEEKDAY_CLICKED(Calendar_CalCtrl, MyPanel::OnCalendarWeekDayClick)
294 EVT_CALENDAR_WEEK_CLICKED(Calendar_CalCtrl, MyPanel::OnCalendarWeekClick)
295 END_EVENT_TABLE()
296
297 #if wxUSE_DATEPICKCTRL
298
299 BEGIN_EVENT_TABLE(MyDialog, wxDialog)
300 EVT_DATE_CHANGED(wxID_ANY, MyDialog::OnDateChange)
301 END_EVENT_TABLE()
302
303 #endif // wxUSE_DATEPICKCTRL
304
305 // Create a new application object: this macro will allow wxWidgets to create
306 // the application object during program execution (it's better than using a
307 // static object for many reasons) and also declares the accessor function
308 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
309 // not wxApp)
310 IMPLEMENT_APP(MyApp)
311
312 // ============================================================================
313 // implementation
314 // ============================================================================
315
316 // ----------------------------------------------------------------------------
317 // the application class
318 // ----------------------------------------------------------------------------
319
320 // `Main program' equivalent: the program execution "starts" here
321 bool MyApp::OnInit()
322 {
323 if ( !wxApp::OnInit() )
324 return false;
325
326 // Create the main application window
327 MyFrame *frame = new MyFrame(wxT("Calendar wxWidgets sample")
328 #ifndef __WXWINCE__
329 ,wxPoint(50, 50), wxSize(450, 340)
330 #endif
331 );
332
333 frame->Show(true);
334
335 // success: wxApp::OnRun() will be called which will enter the main message
336 // loop and the application will run. If we returned false here, the
337 // application would exit immediately.
338 return true;
339 }
340
341 // ----------------------------------------------------------------------------
342 // main frame
343 // ----------------------------------------------------------------------------
344
345 // frame constructor
346 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
347 : wxFrame((wxFrame *)NULL, wxID_ANY, title, pos, size)
348 {
349 // set the frame icon
350 SetIcon(wxIcon(sample_xpm));
351
352 // create a menu bar
353 wxMenu *menuFile = new wxMenu;
354 menuFile->Append(Calendar_File_About, wxT("&About...\tCtrl-A"), wxT("Show about dialog"));
355 menuFile->AppendSeparator();
356 menuFile->Append(Calendar_File_ClearLog, wxT("&Clear log\tCtrl-L"));
357 menuFile->AppendSeparator();
358 menuFile->Append(Calendar_File_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
359
360 wxMenu *menuCal = new wxMenu;
361 #ifdef wxHAS_NATIVE_CALENDARCTRL
362 menuCal->AppendCheckItem(Calendar_Cal_Generic, "Use &generic version\tCtrl-G",
363 "Toggle between native and generic control");
364 menuCal->AppendSeparator();
365 #endif // wxHAS_NATIVE_CALENDARCTRL
366 menuCal->Append(Calendar_Cal_Monday,
367 wxT("Monday &first weekday\tCtrl-F"),
368 wxT("Toggle between Mon and Sun as the first week day"),
369 true);
370 menuCal->Append(Calendar_Cal_Holidays, wxT("Show &holidays\tCtrl-H"),
371 wxT("Toggle highlighting the holidays"),
372 true);
373 menuCal->Append(Calendar_Cal_Special, wxT("Highlight &special dates\tCtrl-S"),
374 wxT("Test custom highlighting"),
375 true);
376 menuCal->Append(Calendar_Cal_SurroundWeeks,
377 wxT("Show s&urrounding weeks\tCtrl-W"),
378 wxT("Show the neighbouring weeks in the prev/next month"),
379 true);
380 menuCal->Append(Calendar_Cal_WeekNumbers,
381 wxT("Show &week numbers"),
382 wxT("Toggle week numbers"),
383 true);
384 menuCal->AppendSeparator();
385 menuCal->Append(Calendar_Cal_SeqMonth,
386 wxT("Toggle month selector st&yle\tCtrl-Y"),
387 wxT("Use another style for the calendar controls"),
388 true);
389 menuCal->Append(Calendar_Cal_Month, wxT("&Month can be changed\tCtrl-M"),
390 wxT("Allow changing the month in the calendar"),
391 true);
392 menuCal->AppendCheckItem(Calendar_Cal_LimitDates, wxT("Toggle date ra&nge\tCtrl-N"),
393 wxT("Limit the valid dates"));
394 menuCal->AppendSeparator();
395 menuCal->Append(Calendar_Cal_SetDate, wxT("Call &SetDate(2005-12-24)"), wxT("Set date to 2005-12-24."));
396 menuCal->Append(Calendar_Cal_Today, wxT("Call &Today()"), wxT("Set to the current date."));
397 menuCal->Append(Calendar_Cal_BeginDST, "Call SetDate(GetBeginDST())");
398 menuCal->AppendSeparator();
399 menuCal->AppendCheckItem(Calendar_Cal_Resizable, wxT("Make &resizable\tCtrl-R"));
400
401 #if wxUSE_DATEPICKCTRL
402 wxMenu *menuDate = new wxMenu;
403 menuDate->AppendCheckItem(Calendar_DatePicker_ShowCentury,
404 wxT("Al&ways show century"));
405 menuDate->AppendCheckItem(Calendar_DatePicker_DropDown,
406 wxT("Use &drop down control"));
407 menuDate->AppendCheckItem(Calendar_DatePicker_AllowNone,
408 wxT("Allow &no date"));
409 menuDate->AppendCheckItem(Calendar_DatePicker_StartWithNone,
410 wxT("Start &with no date"));
411 #if wxUSE_DATEPICKCTRL_GENERIC
412 menuDate->AppendCheckItem(Calendar_DatePicker_Generic,
413 wxT("Use &generic version of the control"));
414 #endif // wxUSE_DATEPICKCTRL_GENERIC
415 menuDate->AppendSeparator();
416 menuDate->Append(Calendar_DatePicker_AskDate, wxT("&Choose date...\tCtrl-D"), wxT("Show dialog with wxDatePickerCtrl"));
417 #endif // wxUSE_DATEPICKCTRL
418
419 // now append the freshly created menu to the menu bar...
420 wxMenuBar *menuBar = new wxMenuBar;
421 menuBar->Append(menuFile, wxT("&File"));
422 menuBar->Append(menuCal, wxT("&Calendar"));
423 #if wxUSE_DATEPICKCTRL
424 menuBar->Append(menuDate, wxT("&Date picker"));
425 #endif // wxUSE_DATEPICKCTRL
426
427 menuBar->Check(Calendar_Cal_Monday, true);
428 menuBar->Check(Calendar_Cal_Holidays, true);
429 menuBar->Check(Calendar_Cal_Month, true);
430 menuBar->Check(Calendar_Cal_LimitDates, false);
431
432 #if wxUSE_DATEPICKCTRL
433 menuBar->Check(Calendar_DatePicker_ShowCentury, true);
434 #endif // wxUSE_DATEPICKCTRL
435
436 // ... and attach this menu bar to the frame
437 SetMenuBar(menuBar);
438
439 wxSplitterWindow *splitter = new wxSplitterWindow(this, wxID_ANY,
440 wxDefaultPosition, wxDefaultSize,
441 wxSP_NOBORDER);
442 m_panel = new MyPanel(splitter);
443 m_logWindow = new wxTextCtrl(splitter, wxID_ANY, wxEmptyString,
444 wxDefaultPosition, wxDefaultSize,
445 wxTE_READONLY | wxTE_MULTILINE);
446 splitter->SplitHorizontally(m_panel, m_logWindow);
447 splitter->SetMinimumPaneSize(20);
448 wxLog::SetActiveTarget(new wxLogTextCtrl(m_logWindow));
449 }
450
451 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
452 {
453 // true is to force the frame to close
454 Close(true);
455 }
456
457 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
458 {
459 wxMessageBox(wxT("wxCalendarCtrl sample\n(c) 2000--2008 Vadim Zeitlin"),
460 wxT("About Calendar"), wxOK | wxICON_INFORMATION, this);
461 }
462
463 void MyFrame::OnClearLog(wxCommandEvent& WXUNUSED(event))
464 {
465 m_logWindow->Clear();
466 }
467
468 void MyFrame::OnCalMonday(wxCommandEvent& event)
469 {
470 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_MONDAY_FIRST);
471 }
472
473 void MyFrame::OnCalHolidays(wxCommandEvent& event)
474 {
475 m_panel->GetCal()->EnableHolidayDisplay(event.IsChecked());
476 }
477
478 void MyFrame::OnCalSpecial(wxCommandEvent& event)
479 {
480 m_panel->HighlightSpecial(GetMenuBar()->IsChecked(event.GetId()));
481 }
482
483 void MyFrame::OnCalLimitDates(wxCommandEvent& event)
484 {
485 m_panel->LimitDateRange(GetMenuBar()->IsChecked(event.GetId()));
486 }
487
488 void MyFrame::OnCalAllowMonth(wxCommandEvent& event)
489 {
490 m_panel->GetCal()->EnableMonthChange(event.IsChecked());
491 }
492
493 void MyFrame::OnCalSeqMonth(wxCommandEvent& event)
494 {
495 m_panel->ToggleCalStyle(event.IsChecked(),
496 wxCAL_SEQUENTIAL_MONTH_SELECTION);
497 }
498
499 void MyFrame::OnCalShowSurroundingWeeks(wxCommandEvent& event)
500 {
501 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SHOW_SURROUNDING_WEEKS);
502 }
503
504 void MyFrame::OnCalShowWeekNumbers(wxCommandEvent& event)
505 {
506 m_panel->ToggleCalStyle(event.IsChecked(), wxCAL_SHOW_WEEK_NUMBERS);
507 }
508
509 void MyFrame::OnSetDate(wxCommandEvent &WXUNUSED(event))
510 {
511 m_panel->SetDate(wxDateTime(24, wxDateTime::Dec, 2005, 22, 00, 00));
512 }
513
514 void MyFrame::OnToday(wxCommandEvent &WXUNUSED(event))
515 {
516 m_panel->SetDate(wxDateTime::Today());
517 }
518
519 void MyFrame::OnBeginDST(wxCommandEvent &WXUNUSED(event))
520 {
521 m_panel->SetDate(wxDateTime::GetBeginDST(m_panel->GetDate().GetYear()));
522 }
523
524 void MyFrame::OnCalToggleResizable(wxCommandEvent& event)
525 {
526 wxSizer * const sizer = m_panel->GetSizer();
527 wxSizerItem * const item = sizer->GetItem(m_panel->GetCal());
528 if ( event.IsChecked() )
529 {
530 item->SetProportion(1);
531 item->SetFlag(wxEXPAND);
532 }
533 else // not resizable
534 {
535 item->SetProportion(0);
536 item->SetFlag(wxALIGN_CENTER);
537 }
538
539 sizer->Layout();
540 }
541
542 void MyFrame::OnCalRClick(wxMouseEvent& event)
543 {
544 wxDateTime dt;
545 wxDateTime::WeekDay wd;
546
547 const wxPoint pt = event.GetPosition();
548 wxString msg = wxString::Format("Point (%d, %d) is ", pt.x, pt.y);
549
550 switch ( m_panel->GetCal()->HitTest(pt, &dt, &wd) )
551 {
552 default:
553 wxFAIL_MSG( "unexpected" );
554 // fall through
555
556 case wxCAL_HITTEST_NOWHERE:
557 msg += "nowhere";
558 break;
559
560 case wxCAL_HITTEST_HEADER:
561 msg += wxString::Format("over %s", wxDateTime::GetWeekDayName(wd));
562 break;
563
564 case wxCAL_HITTEST_DAY:
565 msg += wxString::Format("over %s", dt.FormatISODate());
566 break;
567
568 case wxCAL_HITTEST_INCMONTH:
569 msg += "over next month button";
570 break;
571
572 case wxCAL_HITTEST_DECMONTH:
573 msg += "over previous month button";
574 break;
575
576 case wxCAL_HITTEST_SURROUNDING_WEEK:
577 msg += "over a day from another month";
578 break;
579 }
580
581 wxLogMessage("%s", msg);
582 }
583
584 #if wxUSE_DATEPICKCTRL
585
586 void MyFrame::OnUpdateUIStartWithNone(wxUpdateUIEvent& event)
587 {
588 // it only makes sense to start with invalid date if we can have no date
589 event.Enable( GetMenuBar()->IsChecked(Calendar_DatePicker_AllowNone) );
590 }
591
592 void MyFrame::OnAskDate(wxCommandEvent& WXUNUSED(event))
593 {
594 wxDateTime dt = m_panel->GetCal()->GetDate();
595
596 int style = wxDP_DEFAULT;
597 if ( GetMenuBar()->IsChecked(Calendar_DatePicker_ShowCentury) )
598 style |= wxDP_SHOWCENTURY;
599 if ( GetMenuBar()->IsChecked(Calendar_DatePicker_DropDown) )
600 style |= wxDP_DROPDOWN;
601 if ( GetMenuBar()->IsChecked(Calendar_DatePicker_AllowNone) )
602 {
603 style |= wxDP_ALLOWNONE;
604
605 if ( GetMenuBar()->IsChecked(Calendar_DatePicker_StartWithNone) )
606 dt = wxDefaultDateTime;
607 }
608
609 MyDialog dlg(this, dt, style);
610 if ( dlg.ShowModal() == wxID_OK )
611 {
612 dt = dlg.GetDate();
613 if ( dt.IsValid() )
614 {
615 const wxDateTime today = wxDateTime::Today();
616
617 if ( dt.GetDay() == today.GetDay() &&
618 dt.GetMonth() == today.GetMonth() )
619 {
620 wxMessageBox(wxT("Happy birthday!"), wxT("Calendar Sample"));
621 }
622
623 m_panel->SetDate(dt);
624
625 wxLogStatus(wxT("Changed the date to your input"));
626 }
627 else
628 {
629 wxLogStatus(wxT("No date entered"));
630 }
631 }
632 }
633
634 #endif // wxUSE_DATEPICKCTRL
635
636 // ----------------------------------------------------------------------------
637 // MyPanel
638 // ----------------------------------------------------------------------------
639
640 MyPanel::MyPanel(wxWindow *parent)
641 : wxPanel(parent, wxID_ANY)
642 {
643 #ifdef wxHAS_NATIVE_CALENDARCTRL
644 m_usingGeneric = false;
645 #else
646 m_usingGeneric = true;
647 #endif
648
649 wxString date;
650 date.Printf(wxT("Selected date: %s"),
651 wxDateTime::Today().FormatISODate().c_str());
652 m_date = new wxStaticText(this, wxID_ANY, date);
653 m_calendar = DoCreateCalendar(wxDefaultDateTime,
654 wxCAL_MONDAY_FIRST | wxCAL_SHOW_HOLIDAYS);
655
656 // adjust to vertical/horizontal display, check mostly dedicated to WinCE
657 bool horizontal = ( wxSystemSettings::GetMetric(wxSYS_SCREEN_X) > wxSystemSettings::GetMetric(wxSYS_SCREEN_Y) );
658 m_sizer = new wxBoxSizer( horizontal ? wxHORIZONTAL : wxVERTICAL );
659
660 m_sizer->Add(m_date, 0, wxALIGN_CENTER | wxALL, 10 );
661 m_sizer->Add(m_calendar, 0, wxALIGN_CENTER | wxALIGN_LEFT);
662
663 SetSizer( m_sizer );
664 m_sizer->SetSizeHints( this );
665 }
666
667 void MyPanel::OnCalendar(wxCalendarEvent& event)
668 {
669 // clicking the same date twice unmarks it (convenient for testing)
670 static wxDateTime s_dateLast;
671 const bool mark = !s_dateLast.IsValid() || event.GetDate() != s_dateLast;
672
673 s_dateLast = event.GetDate();
674
675 m_calendar->Mark(event.GetDate().GetDay(), mark);
676 wxLogMessage(wxT("Selected (and %smarked) %s from calendar."),
677 mark ? "" : "un", s_dateLast.FormatISODate().c_str());
678 }
679
680 void MyPanel::OnCalendarChange(wxCalendarEvent& event)
681 {
682 wxString s;
683 s.Printf(wxT("Selected date: %s"), event.GetDate().FormatISODate().c_str());
684
685 m_date->SetLabel(s);
686 wxLogStatus(s);
687 }
688
689 void MyPanel::OnCalMonthChange(wxCalendarEvent& event)
690 {
691 wxLogStatus(wxT("Calendar month changed to %s %d"),
692 wxDateTime::GetMonthName(event.GetDate().GetMonth()),
693 event.GetDate().GetYear());
694 }
695
696 void MyPanel::OnCalendarWeekDayClick(wxCalendarEvent& event)
697 {
698 wxLogMessage(wxT("Clicked on %s"),
699 wxDateTime::GetWeekDayName(event.GetWeekDay()).c_str());
700 }
701
702 void MyPanel::OnCalendarWeekClick(wxCalendarEvent& event)
703 {
704 wxLogMessage(wxT("Clicked on week %d"), event.GetDate().GetWeekOfYear());
705 }
706
707 wxCalendarCtrlBase *MyPanel::DoCreateCalendar(const wxDateTime& dt, long style)
708 {
709 wxCalendarCtrlBase *calendar;
710 #ifdef wxHAS_NATIVE_CALENDARCTRL
711 if ( m_usingGeneric )
712 calendar = new wxGenericCalendarCtrl(this, Calendar_CalCtrl,
713 dt,
714 wxDefaultPosition,
715 wxDefaultSize,
716 style);
717 else
718 #endif // wxHAS_NATIVE_CALENDARCTRL
719 calendar = new wxCalendarCtrl(this, Calendar_CalCtrl,
720 dt,
721 wxDefaultPosition,
722 wxDefaultSize,
723 style);
724
725 calendar->Connect(wxEVT_RIGHT_DOWN,
726 wxMouseEventHandler(MyFrame::OnCalRClick),
727 NULL,
728 ( MyFrame * )wxGetTopLevelParent(this));
729
730 return calendar;
731 }
732
733 void MyPanel::RecreateCalendar(long style)
734 {
735 wxCalendarCtrlBase *calendar = DoCreateCalendar(m_calendar->GetDate(), style);
736
737 m_sizer->Replace(m_calendar, calendar);
738 delete m_calendar;
739 m_calendar = calendar;
740
741 m_sizer->Layout();
742 }
743
744 void MyPanel::ToggleCalStyle(bool on, int flag)
745 {
746 long style = m_calendar->GetWindowStyle();
747 if ( on )
748 style |= flag;
749 else
750 style &= ~flag;
751
752 if ( flag == wxCAL_SEQUENTIAL_MONTH_SELECTION
753 || flag == wxCAL_SHOW_WEEK_NUMBERS)
754 {
755 // changing this style requires recreating the control
756 RecreateCalendar(style);
757 }
758 else // just changing the style is enough
759 {
760 m_calendar->SetWindowStyle(style);
761
762 m_calendar->Refresh();
763 }
764 }
765
766 void MyPanel::HighlightSpecial(bool on)
767 {
768 if ( on )
769 {
770 wxCalendarDateAttr
771 *attrRedCircle = new wxCalendarDateAttr(wxCAL_BORDER_ROUND, *wxRED),
772 *attrGreenSquare = new wxCalendarDateAttr(wxCAL_BORDER_SQUARE, *wxGREEN),
773 *attrHeaderLike = new wxCalendarDateAttr(*wxBLUE, *wxLIGHT_GREY);
774
775 m_calendar->SetAttr(17, attrRedCircle);
776 m_calendar->SetAttr(29, attrGreenSquare);
777 m_calendar->SetAttr(13, attrHeaderLike);
778 }
779 else // off
780 {
781 m_calendar->ResetAttr(17);
782 m_calendar->ResetAttr(29);
783 m_calendar->ResetAttr(13);
784 }
785
786 m_calendar->Refresh();
787 }
788
789 // Toggle a restricted date range to the six months centered on today's date.
790 void MyPanel::LimitDateRange(bool on)
791 {
792 if ( on )
793 {
794 // limit the choice of date to 3 months around today
795 const wxDateSpan diff = wxDateSpan::Months(3);
796 const wxDateTime today = wxDateTime::Today();
797
798 // Set the restricted date range.
799 if ( m_calendar->SetDateRange(today - diff, today + diff) )
800 {
801 wxLogStatus("Date range limited to 3 months around today.");
802 wxDateTime firstValidDate;
803 wxDateTime lastValidDate;
804 if ( m_calendar->GetDateRange(&firstValidDate, &lastValidDate) )
805 {
806 wxLogMessage("First valid date: %s, last valid date: %s",
807 firstValidDate.FormatISODate(),
808 lastValidDate.FormatISODate());
809 }
810 else
811 {
812 wxLogWarning("Failed to get back the valid dates range.");
813 }
814 }
815 else
816 {
817 wxLogWarning("Date range not supported.");
818 }
819 }
820 else // off
821 {
822 // Remove the date restrictions.
823 if ( m_calendar->SetDateRange() )
824 {
825 wxLogStatus("Date choice is unlimited now.");
826 }
827 else
828 {
829 wxLogWarning("Date range not supported.");
830 }
831 }
832
833 m_calendar->Refresh();
834 }
835
836 // ----------------------------------------------------------------------------
837 // MyDialog
838 // ----------------------------------------------------------------------------
839
840 #if wxUSE_DATEPICKCTRL
841
842 MyDialog::MyDialog(wxWindow *parent, const wxDateTime& dt, int dtpStyle)
843 : wxDialog(parent, wxID_ANY, wxString(wxT("Calendar: Choose a date")))
844 {
845 wxStdDialogButtonSizer *sizerBtns = new wxStdDialogButtonSizer;
846 sizerBtns->AddButton(new wxButton(this, wxID_OK));
847 sizerBtns->AddButton(new wxButton(this, wxID_CANCEL));
848 sizerBtns->Realize();
849
850 wxSizer *sizerText = new wxBoxSizer(wxHORIZONTAL);
851 sizerText->Add(new wxStaticText(this, wxID_ANY, wxT("Date in ISO format: ")),
852 wxSizerFlags().Border().Align(wxALIGN_CENTRE_VERTICAL));
853 m_text = new wxTextCtrl(this, wxID_ANY);
854 sizerText->Add(m_text, wxSizerFlags().
855 Expand().Border().Align(wxALIGN_CENTRE_VERTICAL));
856
857 wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
858 sizerTop->Add(new wxStaticText
859 (
860 this, wxID_ANY,
861 wxT("Enter your birthday date (not before 20th century):")
862 ),
863 wxSizerFlags().Border());
864
865 #if wxUSE_DATEPICKCTRL_GENERIC
866 wxFrame *frame = (wxFrame *)wxGetTopLevelParent(parent);
867 if ( frame && frame->GetMenuBar()->IsChecked(Calendar_DatePicker_Generic) )
868 m_datePicker = new wxDatePickerCtrlGeneric(this, wxID_ANY, dt,
869 wxDefaultPosition,
870 wxDefaultSize,
871 dtpStyle);
872 else
873 #endif // wxUSE_DATEPICKCTRL_GENERIC
874 m_datePicker = new wxDatePickerCtrl(this, wxID_ANY, dt,
875 wxDefaultPosition, wxDefaultSize,
876 dtpStyle);
877 m_datePicker->SetRange(wxDateTime(1, wxDateTime::Jan, 1900),
878 wxDefaultDateTime);
879 sizerTop->Add(m_datePicker, wxSizerFlags().Expand().Border());
880
881 sizerTop->AddStretchSpacer(1);
882 sizerTop->Add(sizerText);
883
884 sizerTop->Add(sizerBtns, wxSizerFlags().Centre().Border());
885
886 SetSizerAndFit(sizerTop);
887 Layout();
888 }
889
890 void MyDialog::OnDateChange(wxDateEvent& event)
891 {
892 const wxDateTime dt = event.GetDate();
893 if ( dt.IsValid() )
894 m_text->SetValue(dt.FormatISODate());
895 else
896 m_text->SetValue(wxEmptyString);
897 }
898
899 #endif // wxUSE_DATEPICKCTRL