1///////////////////////////////////////////////////////////////////////////////
2// Name:        generic/calctrl.h
3// Purpose:     generic implementation of date-picker control
4// Author:      Vadim Zeitlin
5// Modified by:
6// Created:     29.12.99
7// RCS-ID:      $Id: calctrl.h 61872 2009-09-09 22:37:05Z VZ $
8// Copyright:   (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence:     wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12#ifndef _WX_GENERIC_CALCTRL_H
13#define _WX_GENERIC_CALCTRL_H
14
15#include "wx/control.h"         // the base class
16#include "wx/dcclient.h"        // for wxPaintDC
17
18class WXDLLIMPEXP_FWD_CORE wxComboBox;
19class WXDLLIMPEXP_FWD_CORE wxStaticText;
20class WXDLLIMPEXP_FWD_CORE wxSpinCtrl;
21
22#define wxCalendarNameStr wxT("CalendarCtrl")
23
24// ----------------------------------------------------------------------------
25// wxCalendarCtrl: a control allowing the user to pick a date interactively
26// ----------------------------------------------------------------------------
27
28class WXDLLIMPEXP_ADV wxCalendarCtrl : public wxControl
29{
30public:
31    // construction
32    wxCalendarCtrl() { Init(); }
33    wxCalendarCtrl(wxWindow *parent,
34                   wxWindowID id,
35                   const wxDateTime& date = wxDefaultDateTime,
36                   const wxPoint& pos = wxDefaultPosition,
37                   const wxSize& size = wxDefaultSize,
38                   long style = wxCAL_SHOW_HOLIDAYS | wxWANTS_CHARS,
39                   const wxString& name = wxCalendarNameStr);
40
41    bool Create(wxWindow *parent,
42                wxWindowID id,
43                const wxDateTime& date = wxDefaultDateTime,
44                const wxPoint& pos = wxDefaultPosition,
45                const wxSize& size = wxDefaultSize,
46                long style = wxCAL_SHOW_HOLIDAYS | wxWANTS_CHARS,
47                const wxString& name = wxCalendarNameStr);
48
49    virtual ~wxCalendarCtrl();
50
51    virtual bool Destroy();
52
53    // set/get the current date
54    // ------------------------
55
56    bool SetDate(const wxDateTime& date); // we need to be able to control if the event should be sent in SetDateAndNotify(...)
57    const wxDateTime& GetDate() const { return m_date; }
58
59    // set/get the range in which selection can occur
60    // ---------------------------------------------
61
62    bool SetLowerDateLimit(const wxDateTime& date = wxDefaultDateTime);
63    const wxDateTime& GetLowerDateLimit() const { return m_lowdate; }
64    bool SetUpperDateLimit(const wxDateTime& date = wxDefaultDateTime);
65    const wxDateTime& GetUpperDateLimit() const { return m_highdate; }
66
67    bool SetDateRange(const wxDateTime& lowerdate = wxDefaultDateTime, const wxDateTime& upperdate = wxDefaultDateTime);
68
69    // calendar mode
70    // -------------
71
72    // some calendar styles can't be changed after the control creation by
73    // just using SetWindowStyle() and Refresh() and the functions below
74    // should be used instead for them
75
76    // corresponds to wxCAL_NO_YEAR_CHANGE bit
77    void EnableYearChange(bool enable = true);
78
79    // corresponds to wxCAL_NO_MONTH_CHANGE bit
80    void EnableMonthChange(bool enable = true);
81
82    // corresponds to wxCAL_SHOW_HOLIDAYS bit
83    void EnableHolidayDisplay(bool display = true);
84
85    // customization
86    // -------------
87
88    // header colours are used for painting the weekdays at the top
89    void SetHeaderColours(const wxColour& colFg, const wxColour& colBg)
90    {
91        m_colHeaderFg = colFg;
92        m_colHeaderBg = colBg;
93    }
94
95    const wxColour& GetHeaderColourFg() const { return m_colHeaderFg; }
96    const wxColour& GetHeaderColourBg() const { return m_colHeaderBg; }
97
98    // highlight colour is used for the currently selected date
99    void SetHighlightColours(const wxColour& colFg, const wxColour& colBg)
100    {
101        m_colHighlightFg = colFg;
102        m_colHighlightBg = colBg;
103    }
104
105    const wxColour& GetHighlightColourFg() const { return m_colHighlightFg; }
106    const wxColour& GetHighlightColourBg() const { return m_colHighlightBg; }
107
108    // holiday colour is used for the holidays (if style & wxCAL_SHOW_HOLIDAYS)
109    void SetHolidayColours(const wxColour& colFg, const wxColour& colBg)
110    {
111        m_colHolidayFg = colFg;
112        m_colHolidayBg = colBg;
113    }
114
115    const wxColour& GetHolidayColourFg() const { return m_colHolidayFg; }
116    const wxColour& GetHolidayColourBg() const { return m_colHolidayBg; }
117
118    // an item without custom attributes is drawn with the default colours and
119    // font and without border, setting custom attributes allows to modify this
120    //
121    // the day parameter should be in 1..31 range, for days 29, 30, 31 the
122    // corresponding attribute is just unused if there is no such day in the
123    // current month
124
125    wxCalendarDateAttr *GetAttr(size_t day) const
126    {
127        wxCHECK_MSG( day > 0 && day < 32, NULL, wxT("invalid day") );
128
129        return m_attrs[day - 1];
130    }
131
132    void SetAttr(size_t day, wxCalendarDateAttr *attr)
133    {
134        wxCHECK_RET( day > 0 && day < 32, wxT("invalid day") );
135
136        delete m_attrs[day - 1];
137        m_attrs[day - 1] = attr;
138    }
139
140    void SetHoliday(size_t day);
141
142    void ResetAttr(size_t day) { SetAttr(day, (wxCalendarDateAttr *)NULL); }
143
144    // returns one of wxCAL_HITTEST_XXX constants and fills either date or wd
145    // with the corresponding value (none for NOWHERE, the date for DAY and wd
146    // for HEADER)
147    wxCalendarHitTestResult HitTest(const wxPoint& pos,
148                                    wxDateTime *date = NULL,
149                                    wxDateTime::WeekDay *wd = NULL);
150
151    // implementation only from now on
152    // -------------------------------
153
154    // forward these functions to all subcontrols
155    virtual bool Enable(bool enable = true);
156    virtual bool Show(bool show = true);
157
158    virtual void SetWindowStyleFlag(long style);
159
160    virtual wxVisualAttributes GetDefaultAttributes() const
161        { return GetClassDefaultAttributes(GetWindowVariant()); }
162
163    static wxVisualAttributes
164    GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
165
166    void OnSysColourChanged(wxSysColourChangedEvent& event);
167
168protected:
169    // override some base class virtuals
170    virtual wxSize DoGetBestSize() const;
171    virtual void DoGetPosition(int *x, int *y) const;
172    virtual void DoGetSize(int *width, int *height) const;
173    virtual void DoSetSize(int x, int y, int width, int height, int sizeFlags);
174    virtual void DoMoveWindow(int x, int y, int width, int height);
175
176private:
177    // common part of all ctors
178    void Init();
179
180    // startup colours and reinitialization after colour changes in system
181    void InitColours();
182
183    // event handlers
184    void OnPaint(wxPaintEvent& event);
185    void OnClick(wxMouseEvent& event);
186    void OnDClick(wxMouseEvent& event);
187    void OnChar(wxKeyEvent& event);
188    void OnMonthChange(wxCommandEvent& event);
189    void OnYearChange(wxCommandEvent& event);
190    void OnYearTextChange(wxCommandEvent& event);
191
192    // (re)calc m_widthCol and m_heightRow
193    void RecalcGeometry();
194
195    // set the date and send the notification
196    void SetDateAndNotify(const wxDateTime& date);
197
198    // get the week (row, in range 1..6) for the given date
199    size_t GetWeek(const wxDateTime& date) const;
200
201    // get the date from which we start drawing days
202    wxDateTime GetStartDate() const;
203
204    // is this date shown?
205    bool IsDateShown(const wxDateTime& date) const;
206
207    // is this date in the given range?
208    bool IsDateInRange(const wxDateTime& date) const;
209
210    // range helpers
211    bool ChangeYear(wxDateTime* target) const;
212    bool ChangeMonth(wxDateTime* target) const;
213
214    // redraw the given date
215    void RefreshDate(const wxDateTime& date);
216
217    // change the date inside the same month/year
218    void ChangeDay(const wxDateTime& date);
219
220    // set the attributes for the holidays if needed
221    void SetHolidayAttrs();
222
223    // reset all holidays
224    void ResetHolidayAttrs();
225
226    // generate the given calendar event(s)
227    void GenerateEvent(wxEventType type)
228    {
229        wxCalendarEvent event(this, type);
230        (void)GetEventHandler()->ProcessEvent(event);
231    }
232
233    void GenerateEvents(wxEventType type1, wxEventType type2)
234    {
235        GenerateEvent(type1);
236        GenerateEvent(type2);
237    }
238
239    // do we allow changing the month/year?
240    bool AllowMonthChange() const
241    {
242        return (GetWindowStyle() & wxCAL_NO_MONTH_CHANGE)
243                != wxCAL_NO_MONTH_CHANGE;
244    }
245    bool AllowYearChange() const
246    {
247        return !(GetWindowStyle() & wxCAL_NO_YEAR_CHANGE);
248    }
249
250    // show the correct controls
251    void ShowCurrentControls();
252
253    // create the month combo and year spin controls
254    void CreateMonthComboBox();
255    void CreateYearSpinCtrl();
256
257public:
258    // get the currently shown control for month/year
259    wxControl *GetMonthControl() const;
260    wxControl *GetYearControl() const;
261
262private:
263    // OnPaint helper-methods
264
265    // Highlight the [fromdate : todate] range using pen and brush
266    void HighlightRange(wxPaintDC* dc, const wxDateTime& fromdate, const wxDateTime& todate, const wxPen* pen, const wxBrush* brush);
267
268    // Get the "coordinates" for the date relative to the month currently displayed.
269    // using (day, week): upper left coord is (1, 1), lower right coord is (7, 6)
270    // if the date isn't visible (-1, -1) is put in (day, week) and false is returned
271    bool GetDateCoord(const wxDateTime& date, int *day, int *week) const;
272
273    // Set the flag for SetDate(): otherwise it would overwrite the year
274    // typed in by the user
275    void SetUserChangedYear() { m_userChangedYear = true; }
276
277    // the subcontrols
278    wxStaticText *m_staticMonth;
279    wxComboBox *m_comboMonth;
280
281    wxStaticText *m_staticYear;
282    wxSpinCtrl *m_spinYear;
283
284    // the current selection
285    wxDateTime m_date;
286
287    // the date-range
288    wxDateTime m_lowdate;
289    wxDateTime m_highdate;
290
291    // default attributes
292    wxColour m_colHighlightFg,
293             m_colHighlightBg,
294             m_colHolidayFg,
295             m_colHolidayBg,
296             m_colHeaderFg,
297             m_colHeaderBg,
298             m_colBackground,
299             m_colSorrounding;
300
301    // the attributes for each of the month days
302    wxCalendarDateAttr *m_attrs[31];
303
304    // the width and height of one column/row in the calendar
305    wxCoord m_widthCol,
306            m_heightRow,
307            m_rowOffset;
308
309    wxRect m_leftArrowRect,
310           m_rightArrowRect;
311
312    // the week day names
313    wxString m_weekdays[7];
314
315    // true if SetDate() is being called as the result of changing the year in
316    // the year control
317    bool m_userChangedYear;
318
319    DECLARE_DYNAMIC_CLASS(wxCalendarCtrl)
320    DECLARE_EVENT_TABLE()
321    DECLARE_NO_COPY_CLASS(wxCalendarCtrl)
322};
323
324#endif // _WX_GENERIC_CALCTRL_H
325