temp ugly hack around the bug under GTK
[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 #ifdef __GNUG__
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/frame.h"
36 #include "wx/panel.h"
37 #include "wx/stattext.h"
38 #include "wx/menu.h"
39 #include "wx/layout.h"
40 #include "wx/msgdlg.h"
41 #endif
42
43 #include "wx/calctrl.h"
44
45 // ----------------------------------------------------------------------------
46 // private classes
47 // ----------------------------------------------------------------------------
48
49 // Define a new application type, each program should derive a class from wxApp
50 class MyApp : public wxApp
51 {
52 public:
53 // override base class virtuals
54 // ----------------------------
55
56 // this one is called on application startup and is a good place for the app
57 // initialization (doing it here and not in the ctor allows to have an error
58 // return: if OnInit() returns false, the application terminates)
59 virtual bool OnInit();
60 };
61
62 class MyPanel : public wxPanel
63 {
64 public:
65 MyPanel(wxFrame *frame);
66
67 void OnCalendar(wxCalendarEvent& event);
68 void OnCalendarWeekDayClick(wxCalendarEvent& event);
69 void OnCalendarChange(wxCalendarEvent& event);
70 void OnCalMonthChange(wxCalendarEvent& event);
71 void OnCalYearChange(wxCalendarEvent& event);
72
73 wxCalendarCtrl *GetCal() const { return m_calendar; }
74
75 void StartWithMonday(bool on);
76 void HighlightSpecial(bool on);
77
78 private:
79 wxCalendarCtrl *m_calendar;
80 wxStaticText *m_date;
81
82 DECLARE_EVENT_TABLE()
83 };
84
85 // Define a new frame type: this is going to be our main frame
86 class MyFrame : public wxFrame
87 {
88 public:
89 // ctor(s)
90 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
91
92 // event handlers (these functions should _not_ be virtual)
93 void OnQuit(wxCommandEvent& event);
94 void OnAbout(wxCommandEvent& event);
95
96 void OnCalMonday(wxCommandEvent& event);
97 void OnCalHolidays(wxCommandEvent& event);
98 void OnCalSpecial(wxCommandEvent& event);
99
100 void OnCalAllowMonth(wxCommandEvent& event);
101 void OnCalAllowYear(wxCommandEvent& event);
102
103 void OnAllowYearUpdate(wxUpdateUIEvent& event);
104
105 private:
106 MyPanel *m_panel;
107
108 // any class wishing to process wxWindows events must use this macro
109 DECLARE_EVENT_TABLE()
110 };
111
112 // ----------------------------------------------------------------------------
113 // constants
114 // ----------------------------------------------------------------------------
115
116 // IDs for the controls and the menu commands
117 enum
118 {
119 // menu items
120 Calendar_File_About = 100,
121 Calendar_File_Quit,
122 Calendar_Cal_Monday = 200,
123 Calendar_Cal_Holidays,
124 Calendar_Cal_Special,
125 Calendar_Cal_Month,
126 Calendar_Cal_Year,
127 Calendar_CalCtrl = 1000,
128 };
129
130 // ----------------------------------------------------------------------------
131 // event tables and other macros for wxWindows
132 // ----------------------------------------------------------------------------
133
134 // the event tables connect the wxWindows events with the functions (event
135 // handlers) which process them. It can be also done at run-time, but for the
136 // simple menu events like this the static method is much simpler.
137 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
138 EVT_MENU(Calendar_File_Quit, MyFrame::OnQuit)
139 EVT_MENU(Calendar_File_About, MyFrame::OnAbout)
140
141 EVT_MENU(Calendar_Cal_Monday, MyFrame::OnCalMonday)
142 EVT_MENU(Calendar_Cal_Holidays, MyFrame::OnCalHolidays)
143 EVT_MENU(Calendar_Cal_Special, MyFrame::OnCalSpecial)
144
145 EVT_MENU(Calendar_Cal_Month, MyFrame::OnCalAllowMonth)
146 EVT_MENU(Calendar_Cal_Year, MyFrame::OnCalAllowYear)
147
148 EVT_UPDATE_UI(Calendar_Cal_Year, MyFrame::OnAllowYearUpdate)
149 END_EVENT_TABLE()
150
151 BEGIN_EVENT_TABLE(MyPanel, wxPanel)
152 EVT_CALENDAR (Calendar_CalCtrl, MyPanel::OnCalendar)
153 EVT_CALENDAR_MONTH (Calendar_CalCtrl, MyPanel::OnCalMonthChange)
154 EVT_CALENDAR_YEAR (Calendar_CalCtrl, MyPanel::OnCalYearChange)
155 EVT_CALENDAR_SEL_CHANGED(Calendar_CalCtrl, MyPanel::OnCalendarChange)
156 EVT_CALENDAR_WEEKDAY_CLICKED(Calendar_CalCtrl, MyPanel::OnCalendarWeekDayClick)
157 END_EVENT_TABLE()
158
159 // Create a new application object: this macro will allow wxWindows to create
160 // the application object during program execution (it's better than using a
161 // static object for many reasons) and also declares the accessor function
162 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
163 // not wxApp)
164 IMPLEMENT_APP(MyApp)
165
166 // ============================================================================
167 // implementation
168 // ============================================================================
169
170 // ----------------------------------------------------------------------------
171 // the application class
172 // ----------------------------------------------------------------------------
173
174 // `Main program' equivalent: the program execution "starts" here
175 bool MyApp::OnInit()
176 {
177 // Create the main application window
178 MyFrame *frame = new MyFrame("Calendar wxWindows sample",
179 wxPoint(50, 50), wxSize(450, 340));
180
181 // Show it and tell the application that it's our main window
182 // @@@ what does it do exactly, in fact? is it necessary here?
183 frame->Show(TRUE);
184 SetTopWindow(frame);
185
186 // success: wxApp::OnRun() will be called which will enter the main message
187 // loop and the application will run. If we returned FALSE here, the
188 // application would exit immediately.
189 return TRUE;
190 }
191
192 // ----------------------------------------------------------------------------
193 // main frame
194 // ----------------------------------------------------------------------------
195
196 // frame constructor
197 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
198 : wxFrame((wxFrame *)NULL, -1, title, pos, size)
199 {
200 // create a menu bar
201 wxMenu *menuFile = new wxMenu;
202
203 menuFile->Append(Calendar_File_About, "&About...\tCtrl-A", "Show about dialog");
204 menuFile->AppendSeparator();
205 menuFile->Append(Calendar_File_Quit, "E&xit\tAlt-X", "Quit this program");
206
207 wxMenu *menuCal = new wxMenu;
208 menuCal->Append(Calendar_Cal_Monday,
209 "Monday &first weekday\tCtrl-F",
210 "Toggle between Mon and Sun as the first week day",
211 TRUE);
212 menuCal->Append(Calendar_Cal_Holidays, "Show &holidays\tCtrl-H",
213 "Toggle highlighting the holidays",
214 TRUE);
215 menuCal->Append(Calendar_Cal_Special, "Highlight &special dates\tCtrl-S",
216 "Test custom highlighting",
217 TRUE);
218 menuCal->AppendSeparator();
219 menuCal->Append(Calendar_Cal_Month, "&Month can be changed\tCtrl-M",
220 "Allow changing the month in the calendar",
221 TRUE);
222 menuCal->Append(Calendar_Cal_Year, "&Year can be changed\tCtrl-Y",
223 "Allow changing the year in the calendar",
224 TRUE);
225
226 // now append the freshly created menu to the menu bar...
227 wxMenuBar *menuBar = new wxMenuBar;
228 menuBar->Append(menuFile, "&File");
229 menuBar->Append(menuCal, "&Calendar");
230
231 menuBar->Check(Calendar_Cal_Monday, TRUE);
232 menuBar->Check(Calendar_Cal_Holidays, TRUE);
233 menuBar->Check(Calendar_Cal_Month, TRUE);
234 menuBar->Check(Calendar_Cal_Year, TRUE);
235
236 // ... and attach this menu bar to the frame
237 SetMenuBar(menuBar);
238
239 m_panel = new MyPanel(this);
240
241 #if wxUSE_STATUSBAR
242 // create a status bar just for fun (by default with 1 pane only)
243 CreateStatusBar(2);
244 SetStatusText("Welcome to wxWindows!");
245 #endif // wxUSE_STATUSBAR
246 }
247
248 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
249 {
250 // TRUE is to force the frame to close
251 Close(TRUE);
252 }
253
254 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
255 {
256 wxMessageBox(_T("wxCalendarCtrl sample\n© 2000 Vadim Zeitlin"),
257 _T("About Calendar"), wxOK | wxICON_INFORMATION, this);
258 }
259
260 void MyFrame::OnCalMonday(wxCommandEvent& event)
261 {
262 m_panel->StartWithMonday(GetMenuBar()->IsChecked(event.GetInt()));
263 }
264
265 void MyFrame::OnCalHolidays(wxCommandEvent& event)
266 {
267 bool enable = GetMenuBar()->IsChecked(event.GetInt());
268 m_panel->GetCal()->EnableHolidayDisplay(enable);
269 }
270
271 void MyFrame::OnCalSpecial(wxCommandEvent& event)
272 {
273 m_panel->HighlightSpecial(GetMenuBar()->IsChecked(event.GetInt()));
274 }
275
276 void MyFrame::OnCalAllowMonth(wxCommandEvent& event)
277 {
278 bool allow = GetMenuBar()->IsChecked(event.GetInt());
279
280 m_panel->GetCal()->EnableMonthChange(allow);
281 }
282
283 void MyFrame::OnCalAllowYear(wxCommandEvent& event)
284 {
285 bool allow = GetMenuBar()->IsChecked(event.GetInt());
286
287 m_panel->GetCal()->EnableYearChange(allow);
288 }
289
290 void MyFrame::OnAllowYearUpdate(wxUpdateUIEvent& event)
291 {
292 event.Enable( GetMenuBar()->IsChecked(Calendar_Cal_Month));
293 }
294
295 // ----------------------------------------------------------------------------
296 // MyPanel
297 // ----------------------------------------------------------------------------
298
299 MyPanel::MyPanel(wxFrame *frame)
300 : wxPanel(frame, -1)
301 {
302 // using constraints doesn't work under GTK - the calendar window is never
303 // repainted after it had been moved at least once!
304 #if 0
305 SetAutoLayout(TRUE);
306
307 wxString date;
308 date.Printf("Selected date: %s",
309 wxDateTime::Today().FormatISODate().c_str());
310 m_date = new wxStaticText(this, -1, date);
311 m_calendar = new wxCalendarCtrl(this, Calendar_CalCtrl,
312 wxDefaultDateTime,
313 wxDefaultPosition,
314 wxDefaultSize,
315 wxCAL_MONDAY_FIRST |
316 wxCAL_SHOW_HOLIDAYS |
317 wxRAISED_BORDER);
318
319 wxLayoutConstraints *c = new wxLayoutConstraints;
320 c->left.SameAs(this, wxLeft, 10);
321 c->centreY.SameAs(this, wxCentreY);
322 c->height.AsIs();
323 c->width.AsIs();
324
325 m_date->SetConstraints(c);
326
327 c = new wxLayoutConstraints;
328 c->left.SameAs(m_date, wxRight, 20);
329 c->centreY.SameAs(this, wxCentreY);
330 c->height.AsIs();
331 c->width.AsIs();
332
333 m_calendar->SetConstraints(c);
334 #else
335 wxString date;
336 date.Printf("Selected date: %s",
337 wxDateTime::Today().FormatISODate().c_str());
338 m_date = new wxStaticText(this, -1, date, wxPoint(10, 100));
339 m_calendar = new wxCalendarCtrl(this, Calendar_CalCtrl,
340 wxDefaultDateTime,
341 wxPoint(200, 20),
342 wxDefaultSize,
343 wxCAL_MONDAY_FIRST |
344 wxCAL_SHOW_HOLIDAYS |
345 wxRAISED_BORDER);
346 #endif
347 }
348
349 void MyPanel::OnCalendar(wxCalendarEvent& event)
350 {
351 wxLogMessage("Selected %s from calendar",
352 event.GetDate().FormatISODate().c_str());
353 }
354
355 void MyPanel::OnCalendarChange(wxCalendarEvent& event)
356 {
357 wxString s;
358 s.Printf("Selected date: %s", event.GetDate().FormatISODate().c_str());
359
360 m_date->SetLabel(s);
361 }
362
363 void MyPanel::OnCalMonthChange(wxCalendarEvent& WXUNUSED(event))
364 {
365 wxLogStatus("Calendar month changed");
366 }
367
368 void MyPanel::OnCalYearChange(wxCalendarEvent& WXUNUSED(event))
369 {
370 wxLogStatus("Calendar year changed");
371 }
372
373 void MyPanel::OnCalendarWeekDayClick(wxCalendarEvent& event)
374 {
375 wxLogMessage("Clicked on %s",
376 wxDateTime::GetWeekDayName(event.GetWeekDay()).c_str());
377 }
378
379 void MyPanel::StartWithMonday(bool on)
380 {
381 long style = m_calendar->GetWindowStyle();
382 if ( on )
383 style |= wxCAL_MONDAY_FIRST;
384 else
385 style &= ~wxCAL_MONDAY_FIRST;
386
387 m_calendar->SetWindowStyle(style);
388
389 m_calendar->Refresh();
390 }
391
392 void MyPanel::HighlightSpecial(bool on)
393 {
394 if ( on )
395 {
396 wxCalendarDateAttr
397 *attrRedCircle = new wxCalendarDateAttr(wxCAL_BORDER_ROUND, *wxRED),
398 *attrGreenSquare = new wxCalendarDateAttr(wxCAL_BORDER_SQUARE, *wxGREEN),
399 *attrHeaderLike = new wxCalendarDateAttr(*wxBLUE, *wxLIGHT_GREY);
400
401 m_calendar->SetAttr(17, attrRedCircle);
402 m_calendar->SetAttr(29, attrGreenSquare);
403 m_calendar->SetAttr(13, attrHeaderLike);
404 }
405 else // off
406 {
407 m_calendar->ResetAttr(17);
408 m_calendar->ResetAttr(29);
409 m_calendar->ResetAttr(13);
410 }
411
412 m_calendar->Refresh();
413 }
414