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