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 
18 class WXDLLIMPEXP_FWD_CORE wxComboBox;
19 class WXDLLIMPEXP_FWD_CORE wxStaticText;
20 class 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 
28 class WXDLLIMPEXP_ADV wxCalendarCtrl : public wxControl
29 {
30 public:
31     // construction
wxCalendarCtrl()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(...)
GetDate()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);
GetLowerDateLimit()63     const wxDateTime& GetLowerDateLimit() const { return m_lowdate; }
64     bool SetUpperDateLimit(const wxDateTime& date = wxDefaultDateTime);
GetUpperDateLimit()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
SetHeaderColours(const wxColour & colFg,const wxColour & colBg)89     void SetHeaderColours(const wxColour& colFg, const wxColour& colBg)
90     {
91         m_colHeaderFg = colFg;
92         m_colHeaderBg = colBg;
93     }
94 
GetHeaderColourFg()95     const wxColour& GetHeaderColourFg() const { return m_colHeaderFg; }
GetHeaderColourBg()96     const wxColour& GetHeaderColourBg() const { return m_colHeaderBg; }
97 
98     // highlight colour is used for the currently selected date
SetHighlightColours(const wxColour & colFg,const wxColour & colBg)99     void SetHighlightColours(const wxColour& colFg, const wxColour& colBg)
100     {
101         m_colHighlightFg = colFg;
102         m_colHighlightBg = colBg;
103     }
104 
GetHighlightColourFg()105     const wxColour& GetHighlightColourFg() const { return m_colHighlightFg; }
GetHighlightColourBg()106     const wxColour& GetHighlightColourBg() const { return m_colHighlightBg; }
107 
108     // holiday colour is used for the holidays (if style & wxCAL_SHOW_HOLIDAYS)
SetHolidayColours(const wxColour & colFg,const wxColour & colBg)109     void SetHolidayColours(const wxColour& colFg, const wxColour& colBg)
110     {
111         m_colHolidayFg = colFg;
112         m_colHolidayBg = colBg;
113     }
114 
GetHolidayColourFg()115     const wxColour& GetHolidayColourFg() const { return m_colHolidayFg; }
GetHolidayColourBg()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 
GetAttr(size_t day)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 
SetAttr(size_t day,wxCalendarDateAttr * attr)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 
ResetAttr(size_t day)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 
GetDefaultAttributes()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 
168 protected:
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 
176 private:
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)
GenerateEvent(wxEventType type)227     void GenerateEvent(wxEventType type)
228     {
229         wxCalendarEvent event(this, type);
230         (void)GetEventHandler()->ProcessEvent(event);
231     }
232 
GenerateEvents(wxEventType type1,wxEventType type2)233     void GenerateEvents(wxEventType type1, wxEventType type2)
234     {
235         GenerateEvent(type1);
236         GenerateEvent(type2);
237     }
238 
239     // do we allow changing the month/year?
AllowMonthChange()240     bool AllowMonthChange() const
241     {
242         return (GetWindowStyle() & wxCAL_NO_MONTH_CHANGE)
243                 != wxCAL_NO_MONTH_CHANGE;
244     }
AllowYearChange()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 
257 public:
258     // get the currently shown control for month/year
259     wxControl *GetMonthControl() const;
260     wxControl *GetYearControl() const;
261 
262 private:
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
SetUserChangedYear()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