]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/calctrl.cpp
supporting full style mask
[wxWidgets.git] / src / gtk / calctrl.cpp
CommitLineData
628e155d
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/gtk/calctrl.cpp
3// Purpose: implementation of the wxGtkCalendarCtrl
4// Author: Marcin Wojdyr
5// RCS-ID: $Id$
6// Copyright: (c) 2008 Marcin Wojdyr
7// Licence: wxWindows licence
8///////////////////////////////////////////////////////////////////////////////
9
10#include "wx/wxprec.h"
11
12#ifdef __BORLANDC__
13 #pragma hdrstop
14#endif
15
16#ifndef WX_PRECOMP
17#endif //WX_PRECOMP
18
19#if wxUSE_CALENDARCTRL
20
21#include "wx/gtk/private.h"
22#include "wx/calctrl.h"
23#include "wx/gtk/calctrl.h"
24
25
26extern "C" {
27
28static void gtk_day_selected_callback(GtkWidget *WXUNUSED(widget),
29 wxGtkCalendarCtrl *cal)
30{
106f0d98 31 cal->GTKGenerateEvent(wxEVT_CALENDAR_SEL_CHANGED);
628e155d
VZ
32}
33
34static void gtk_day_selected_double_click_callback(GtkWidget *WXUNUSED(widget),
35 wxGtkCalendarCtrl *cal)
36{
106f0d98 37 cal->GTKGenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED);
628e155d
VZ
38}
39
40static void gtk_month_changed_callback(GtkWidget *WXUNUSED(widget),
41 wxGtkCalendarCtrl *cal)
42{
106f0d98 43 cal->GTKGenerateEvent(wxEVT_CALENDAR_PAGE_CHANGED);
628e155d
VZ
44}
45
46// callbacks that send deprecated events
47
48static void gtk_prev_month_callback(GtkWidget *WXUNUSED(widget),
49 wxGtkCalendarCtrl *cal)
50{
106f0d98 51 cal->GTKGenerateEvent(wxEVT_CALENDAR_MONTH_CHANGED);
628e155d
VZ
52}
53
54static void gtk_prev_year_callback(GtkWidget *WXUNUSED(widget),
55 wxGtkCalendarCtrl *cal)
56{
106f0d98 57 cal->GTKGenerateEvent(wxEVT_CALENDAR_YEAR_CHANGED);
628e155d
VZ
58}
59
60}
61
62// ----------------------------------------------------------------------------
63// wxGtkCalendarCtrl
64// ----------------------------------------------------------------------------
65
66
67bool wxGtkCalendarCtrl::Create(wxWindow *parent,
68 wxWindowID id,
69 const wxDateTime& date,
70 const wxPoint& pos,
71 const wxSize& size,
72 long style,
73 const wxString& name)
74{
75 if (!PreCreation(parent, pos, size) ||
76 !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name))
77 {
78 wxFAIL_MSG(wxT("wxGtkCalendarCtrl creation failed"));
79 return false;
80 }
81
82 m_widget = gtk_calendar_new();
9ff9d30c 83 g_object_ref(m_widget);
628e155d
VZ
84 SetDate(date.IsValid() ? date : wxDateTime::Today());
85
86 if (style & wxCAL_NO_MONTH_CHANGE)
87 g_object_set (G_OBJECT (m_widget), "no-month-change", true, NULL);
7b0ccb8a
RR
88 if (style & wxCAL_SHOW_WEEK_NUMBERS)
89 g_object_set (G_OBJECT (m_widget), "show-week-numbers", true, NULL);
628e155d
VZ
90
91 g_signal_connect_after(m_widget, "day-selected",
92 G_CALLBACK (gtk_day_selected_callback),
93 this);
94 g_signal_connect_after(m_widget, "day-selected-double-click",
95 G_CALLBACK (gtk_day_selected_double_click_callback),
96 this);
97 g_signal_connect_after(m_widget, "month-changed",
98 G_CALLBACK (gtk_month_changed_callback),
99 this);
100
101 // connect callbacks that send deprecated events
102 g_signal_connect_after(m_widget, "prev-month",
103 G_CALLBACK (gtk_prev_month_callback),
104 this);
105 g_signal_connect_after(m_widget, "next-month",
106 G_CALLBACK (gtk_prev_month_callback),
107 this);
108 g_signal_connect_after(m_widget, "prev-year",
109 G_CALLBACK (gtk_prev_year_callback),
110 this);
111 g_signal_connect_after(m_widget, "next-year",
112 G_CALLBACK (gtk_prev_year_callback),
113 this);
114
115 m_parent->DoAddChild(this);
116
117 PostCreation(size);
118
119 return true;
120}
121
106f0d98
VZ
122void wxGtkCalendarCtrl::GTKGenerateEvent(wxEventType type)
123{
124 // First check if the new date is in the specified range.
125 wxDateTime dt = GetDate();
126 if ( !IsInValidRange(dt) )
127 {
128 if ( m_validStart.IsValid() && dt < m_validStart )
129 dt = m_validStart;
130 else
131 dt = m_validEnd;
132
133 SetDate(dt);
134
135 return;
136 }
137
138 if ( type == wxEVT_CALENDAR_SEL_CHANGED )
139 {
140 // Don't generate this event if the new date is the same as the old
141 // one.
142 if ( m_selectedDate == dt )
143 return;
144
145 m_selectedDate = dt;
146
147 GenerateEvent(type);
148
149 // Also send the deprecated event together with the new one.
150 GenerateEvent(wxEVT_CALENDAR_DAY_CHANGED);
151 }
152 else
153 {
154 GenerateEvent(type);
155 }
156}
157
158bool wxGtkCalendarCtrl::IsInValidRange(const wxDateTime& dt) const
159{
160 return (!m_validStart.IsValid() || m_validStart <= dt) &&
161 (!m_validEnd.IsValid() || dt <= m_validEnd);
162}
163
164bool
165wxGtkCalendarCtrl::SetDateRange(const wxDateTime& lowerdate,
166 const wxDateTime& upperdate)
167{
168 if ( lowerdate.IsValid() && upperdate.IsValid() && lowerdate >= upperdate )
169 return false;
170
171 m_validStart = lowerdate;
172 m_validEnd = upperdate;
173
174 return true;
175}
176
177bool
178wxGtkCalendarCtrl::GetDateRange(wxDateTime *lowerdate,
179 wxDateTime *upperdate) const
180{
181 if ( lowerdate )
182 *lowerdate = m_validStart;
183 if ( upperdate )
184 *upperdate = m_validEnd;
185
186 return m_validStart.IsValid() || m_validEnd.IsValid();
187}
188
189
628e155d
VZ
190bool wxGtkCalendarCtrl::EnableMonthChange(bool enable)
191{
192 if ( !wxCalendarCtrlBase::EnableMonthChange(enable) )
193 return false;
194
195 g_object_set (G_OBJECT (m_widget), "no-month-change", !enable, NULL);
196
197 return true;
198}
199
7b0ccb8a 200
628e155d
VZ
201bool wxGtkCalendarCtrl::SetDate(const wxDateTime& date)
202{
106f0d98
VZ
203 if ( date.IsValid() && !IsInValidRange(date) )
204 return false;
205
7b0ccb8a
RR
206 g_signal_handlers_block_by_func(m_widget,
207 (gpointer) gtk_day_selected_callback, this);
6c1de056
VZ
208 g_signal_handlers_block_by_func(m_widget,
209 (gpointer) gtk_month_changed_callback, this);
03647350 210
7b0ccb8a 211 m_selectedDate = date;
628e155d
VZ
212 int year = date.GetYear();
213 int month = date.GetMonth();
214 int day = date.GetDay();
215 gtk_calendar_select_month(GTK_CALENDAR(m_widget), month, year);
216 gtk_calendar_select_day(GTK_CALENDAR(m_widget), day);
03647350 217
6c1de056
VZ
218 g_signal_handlers_unblock_by_func( m_widget,
219 (gpointer) gtk_month_changed_callback, this);
7b0ccb8a
RR
220 g_signal_handlers_unblock_by_func( m_widget,
221 (gpointer) gtk_day_selected_callback, this);
03647350 222
628e155d
VZ
223 return true;
224}
225
226wxDateTime wxGtkCalendarCtrl::GetDate() const
227{
8ea26eed
VZ
228 guint year, monthGTK, day;
229 gtk_calendar_get_date(GTK_CALENDAR(m_widget), &year, &monthGTK, &day);
230
231 // GTK may return an invalid date, this happens at least when switching the
232 // month (or the year in case of February in a leap year) and the new month
233 // has fewer days than the currently selected one making the currently
234 // selected day invalid, e.g. just choosing May 31 and going back a month
235 // results in the date being (non existent) April 31 when we're called from
236 // gtk_prev_month_callback(). We need to manually work around this to avoid
237 // asserts from wxDateTime ctor.
238 const wxDateTime::Month month = static_cast<wxDateTime::Month>(monthGTK);
239 const guint dayMax = wxDateTime::GetNumberOfDays(month, year);
240 if ( day > dayMax )
241 day = dayMax;
242
243 return wxDateTime(day, month, year);
628e155d
VZ
244}
245
246void wxGtkCalendarCtrl::Mark(size_t day, bool mark)
247{
248 if (mark)
249 gtk_calendar_mark_day(GTK_CALENDAR(m_widget), day);
250 else
251 gtk_calendar_unmark_day(GTK_CALENDAR(m_widget), day);
252}
253
628e155d 254#endif // wxUSE_CALENDARCTRL