1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/calctrl.cpp 
   3 // Purpose:     implementation of the wxGtkCalendarCtrl 
   4 // Author:      Marcin Wojdyr 
   6 // Copyright:   (c) 2008 Marcin Wojdyr 
   7 // Licence:     wxWindows licence 
   8 /////////////////////////////////////////////////////////////////////////////// 
  10 #include "wx/wxprec.h" 
  19 #if wxUSE_CALENDARCTRL 
  21 #include "wx/gtk/private.h" 
  22 #include "wx/calctrl.h" 
  23 #include "wx/gtk/calctrl.h" 
  28 static void gtk_day_selected_callback(GtkWidget 
*WXUNUSED(widget
), 
  29                                       wxGtkCalendarCtrl 
*cal
) 
  31     wxDateTime date 
= cal
->GetDate(); 
  32     if (cal
->m_selectedDate 
== date
) 
  35     cal
->m_selectedDate 
= date
; 
  37     cal
->GenerateEvent(wxEVT_CALENDAR_SEL_CHANGED
); 
  38     // send deprecated event 
  39     cal
->GenerateEvent(wxEVT_CALENDAR_DAY_CHANGED
); 
  42 static void gtk_day_selected_double_click_callback(GtkWidget 
*WXUNUSED(widget
), 
  43                                                    wxGtkCalendarCtrl 
*cal
) 
  45     cal
->GenerateEvent(wxEVT_CALENDAR_DOUBLECLICKED
); 
  48 static void gtk_month_changed_callback(GtkWidget 
*WXUNUSED(widget
), 
  49                                        wxGtkCalendarCtrl 
*cal
) 
  51     cal
->GenerateEvent(wxEVT_CALENDAR_PAGE_CHANGED
); 
  54 // callbacks that send deprecated events 
  56 static void gtk_prev_month_callback(GtkWidget 
*WXUNUSED(widget
), 
  57                                     wxGtkCalendarCtrl 
*cal
) 
  59     cal
->GenerateEvent(wxEVT_CALENDAR_MONTH_CHANGED
); 
  62 static void gtk_prev_year_callback(GtkWidget 
*WXUNUSED(widget
), 
  63                                     wxGtkCalendarCtrl 
*cal
) 
  65     cal
->GenerateEvent(wxEVT_CALENDAR_YEAR_CHANGED
); 
  70 // ---------------------------------------------------------------------------- 
  72 // ---------------------------------------------------------------------------- 
  75 bool wxGtkCalendarCtrl::Create(wxWindow 
*parent
, 
  77                                const wxDateTime
& date
, 
  83     if (!PreCreation(parent
, pos
, size
) || 
  84           !CreateBase(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
)) 
  86         wxFAIL_MSG(wxT("wxGtkCalendarCtrl creation failed")); 
  90     m_widget 
= gtk_calendar_new(); 
  91     g_object_ref(m_widget
); 
  92     SetDate(date
.IsValid() ? date 
: wxDateTime::Today()); 
  94     if (style 
& wxCAL_NO_MONTH_CHANGE
) 
  95         g_object_set (G_OBJECT (m_widget
), "no-month-change", true, NULL
); 
  96     if (style 
& wxCAL_SHOW_WEEK_NUMBERS
) 
  97         g_object_set (G_OBJECT (m_widget
), "show-week-numbers", true, NULL
); 
  99     g_signal_connect_after(m_widget
, "day-selected", 
 100                            G_CALLBACK (gtk_day_selected_callback
), 
 102     g_signal_connect_after(m_widget
, "day-selected-double-click", 
 103                            G_CALLBACK (gtk_day_selected_double_click_callback
), 
 105     g_signal_connect_after(m_widget
, "month-changed", 
 106                            G_CALLBACK (gtk_month_changed_callback
), 
 109     // connect callbacks that send deprecated events 
 110     g_signal_connect_after(m_widget
, "prev-month", 
 111                            G_CALLBACK (gtk_prev_month_callback
), 
 113     g_signal_connect_after(m_widget
, "next-month", 
 114                            G_CALLBACK (gtk_prev_month_callback
), 
 116     g_signal_connect_after(m_widget
, "prev-year", 
 117                            G_CALLBACK (gtk_prev_year_callback
), 
 119     g_signal_connect_after(m_widget
, "next-year", 
 120                            G_CALLBACK (gtk_prev_year_callback
), 
 123     m_parent
->DoAddChild(this); 
 130 bool wxGtkCalendarCtrl::EnableMonthChange(bool enable
) 
 132     if ( !wxCalendarCtrlBase::EnableMonthChange(enable
) ) 
 135     g_object_set (G_OBJECT (m_widget
), "no-month-change", !enable
, NULL
); 
 141 bool wxGtkCalendarCtrl::SetDate(const wxDateTime
& date
) 
 143     g_signal_handlers_block_by_func(m_widget
, 
 144         (gpointer
) gtk_day_selected_callback
, this); 
 145     g_signal_handlers_block_by_func(m_widget
, 
 146         (gpointer
) gtk_month_changed_callback
, this); 
 148     m_selectedDate 
= date
; 
 149     int year 
= date
.GetYear(); 
 150     int month 
= date
.GetMonth(); 
 151     int day 
= date
.GetDay(); 
 152     gtk_calendar_select_month(GTK_CALENDAR(m_widget
), month
, year
); 
 153     gtk_calendar_select_day(GTK_CALENDAR(m_widget
), day
); 
 155     g_signal_handlers_unblock_by_func( m_widget
, 
 156         (gpointer
) gtk_month_changed_callback
, this); 
 157     g_signal_handlers_unblock_by_func( m_widget
, 
 158         (gpointer
) gtk_day_selected_callback
, this); 
 163 wxDateTime 
wxGtkCalendarCtrl::GetDate() const 
 165     guint year
, monthGTK
, day
; 
 166     gtk_calendar_get_date(GTK_CALENDAR(m_widget
), &year
, &monthGTK
, &day
); 
 168     // GTK may return an invalid date, this happens at least when switching the 
 169     // month (or the year in case of February in a leap year) and the new month 
 170     // has fewer days than the currently selected one making the currently 
 171     // selected day invalid, e.g. just choosing May 31 and going back a month 
 172     // results in the date being (non existent) April 31 when we're called from 
 173     // gtk_prev_month_callback(). We need to manually work around this to avoid 
 174     // asserts from wxDateTime ctor. 
 175     const wxDateTime::Month month 
= static_cast<wxDateTime::Month
>(monthGTK
); 
 176     const guint dayMax 
= wxDateTime::GetNumberOfDays(month
, year
); 
 180     return wxDateTime(day
, month
, year
); 
 183 void wxGtkCalendarCtrl::Mark(size_t day
, bool mark
) 
 186         gtk_calendar_mark_day(GTK_CALENDAR(m_widget
), day
); 
 188         gtk_calendar_unmark_day(GTK_CALENDAR(m_widget
), day
); 
 191 #endif // wxUSE_CALENDARCTRL