GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnucash-date-picker.c
1 /********************************************************************\
2  * gnucash-date-picker.c -- A popup date picker using gtk_calendar *
3  * *
4  * This program is free software; you can redistribute it and/or *
5  * modify it under the terms of the GNU General Public License as *
6  * published by the Free Software Foundation; either version 2 of *
7  * the License, or (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License*
15  * along with this program; if not, contact: *
16  * *
17  * Free Software Foundation Voice: +1-617-542-5942 *
18  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
19  * Boston, MA 02110-1301, USA [email protected] *
20  * *
21 \********************************************************************/
22 
23 /*
24  * A popup date picker for the canvas using gtk_calendar.
25  */
26 
27 #include "config.h"
28 #include <libgnomecanvas/libgnomecanvas.h>
29 #include <gdk/gdkkeysyms.h>
30 #include "gnucash-date-picker.h"
31 
32 
33 /* Item list signals */
34 enum
35 {
36  DATE_SELECTED,
37  DATE_PICKED,
38  KEY_PRESS_EVENT,
39  LAST_SIGNAL
40 };
41 
42 static GnomeCanvasWidgetClass *gnc_date_picker_parent_class;
43 static guint gnc_date_picker_signals[LAST_SIGNAL];
44 
45 
46 void
47 gnc_date_picker_set_date (GNCDatePicker *date_picker,
48  guint day, guint mon, guint year)
49 {
50  g_return_if_fail (IS_GNC_DATE_PICKER (date_picker));
51  g_return_if_fail (date_picker->calendar != NULL);
52 
53  gtk_calendar_select_day (date_picker->calendar, 1);
54  gtk_calendar_select_month (date_picker->calendar, mon, year);
55  gtk_calendar_select_day (date_picker->calendar, day);
56 }
57 
58 void
59 gnc_date_picker_get_date (GNCDatePicker *date_picker,
60  guint *day, guint *mon, guint *year)
61 {
62  g_return_if_fail (IS_GNC_DATE_PICKER (date_picker));
63  g_return_if_fail (date_picker->calendar != NULL);
64 
65  gtk_calendar_get_date (date_picker->calendar, year, mon, day);
66 }
67 
68 static void
69 gnc_date_picker_init (GNCDatePicker *date_picker)
70 {
71  date_picker->calendar = NULL;
72 }
73 
74 static gboolean
75 gnc_date_picker_button_event (GtkWidget *widget, GdkEventButton *event,
76  gpointer data)
77 {
78  /* So the sheet doesn't use it. */
79  g_signal_stop_emission_by_name (widget, "button_press_event");
80 
81  return TRUE;
82 }
83 
84 static gboolean
85 gnc_date_picker_key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
86 {
87  GNCDatePicker *date_picker = GNC_DATE_PICKER (data);
88 
89  switch (event->keyval)
90  {
91  case GDK_KEY_Return:
92  case GDK_KEY_KP_Enter:
93  g_signal_emit (date_picker, gnc_date_picker_signals[DATE_PICKED], 0);
94  g_signal_stop_emission_by_name (widget, "key_press_event");
95 
96  return TRUE;
97 
98  case GDK_KEY_Up:
99  case GDK_KEY_Down:
100  case GDK_KEY_Left:
101  case GDK_KEY_Right:
102  case GDK_KEY_space:
103  /* these go to the calendar */
104  return FALSE;
105 
106  default:
107  break;
108  }
109 
110  /* These go to the sheet */
111  g_signal_stop_emission_by_name (widget, "key_press_event");
112 
113  g_signal_emit (date_picker,
114  gnc_date_picker_signals[KEY_PRESS_EVENT], 0, event);
115 
116  return TRUE;
117 }
118 
119 static void
120 gnc_date_picker_class_init (GNCDatePickerClass *date_picker_class)
121 {
122  GtkObjectClass *object_class;
123 
124  gnc_date_picker_parent_class =
125  g_type_class_peek_parent (date_picker_class);
126 
127  object_class = GTK_OBJECT_CLASS (date_picker_class);
128 
129  gnc_date_picker_signals[DATE_SELECTED] =
130  g_signal_new("date_selected",
131  G_TYPE_FROM_CLASS(object_class),
132  G_SIGNAL_RUN_LAST,
133  G_STRUCT_OFFSET(GNCDatePickerClass, date_selected),
134  NULL, NULL,
135  g_cclosure_marshal_VOID__VOID,
136  G_TYPE_NONE, 0);
137 
138  gnc_date_picker_signals[DATE_PICKED] =
139  g_signal_new("date_picked",
140  G_TYPE_FROM_CLASS(object_class),
141  G_SIGNAL_RUN_LAST,
142  G_STRUCT_OFFSET(GNCDatePickerClass, date_picked),
143  NULL, NULL,
144  g_cclosure_marshal_VOID__VOID,
145  G_TYPE_NONE, 0);
146 
147  gnc_date_picker_signals[KEY_PRESS_EVENT] =
148  g_signal_new ("key_press_event",
149  G_TYPE_FROM_CLASS(object_class),
150  G_SIGNAL_RUN_LAST,
151  G_STRUCT_OFFSET(GNCDatePickerClass, key_press_event),
152  NULL, NULL,
153  g_cclosure_marshal_VOID__BOXED,
154  G_TYPE_NONE, 1,
155  GDK_TYPE_EVENT);
156 
157  date_picker_class->date_selected = NULL;
158  date_picker_class->date_picked = NULL;
159  date_picker_class->key_press_event = NULL;
160 }
161 
162 GType
163 gnc_date_picker_get_type (void)
164 {
165  static GType gnc_date_picker_type = 0;
166 
167  if (gnc_date_picker_type == 0)
168  {
169  GTypeInfo type_info =
170  {
171  sizeof(GNCDatePickerClass), /* class_size */
172  NULL, /* base_init */
173  NULL, /* base_finalize */
174  (GClassInitFunc)gnc_date_picker_class_init,
175  NULL, /* class_finalize */
176  NULL, /* class_data */
177  sizeof(GNCDatePicker), /* */
178  0, /* n_preallocs */
179  (GInstanceInitFunc)gnc_date_picker_init,
180  };
181 
182  gnc_date_picker_type =
183  g_type_register_static (gnome_canvas_widget_get_type(),
184  "GNCDatePicker",
185  &type_info, 0);
186  }
187 
188  return gnc_date_picker_type;
189 }
190 
191 
192 static void
193 day_selected (GtkCalendar *calendar, GNCDatePicker *gdp)
194 {
195  g_signal_emit (gdp, gnc_date_picker_signals [DATE_SELECTED], 0);
196 }
197 
198 static void
199 day_selected_double_click (GtkCalendar *calendar, GNCDatePicker *gdp)
200 {
201  g_signal_emit (gdp, gnc_date_picker_signals [DATE_PICKED], 0);
202 }
203 
204 
205 GnomeCanvasItem *
206 gnc_date_picker_new (GnomeCanvasGroup *parent)
207 {
208  GtkWidget *calendar;
209  GnomeCanvasItem *item;
210  GNCDatePicker *date_picker;
211 
212  calendar = gtk_calendar_new ();
213 
214  {
215  GtkWidget *hbox;
216  GtkAllocation allocation;
217  GtkRequisition requisition;
218 
219  hbox = gtk_hbox_new (FALSE, 0);
220 
221  gtk_widget_set_direction (hbox, GTK_TEXT_DIR_LTR);
222  gtk_box_pack_start (GTK_BOX(hbox), calendar, TRUE, TRUE, 0);
223 
224  item = gnome_canvas_item_new (parent, gnc_date_picker_get_type (),
225  "widget", hbox,
226  "size_pixels", TRUE,
227  "x", -10000.0,
228  "y", -10000.0,
229  NULL);
230  gtk_widget_show_all( hbox );
231 
232  gtk_widget_size_request (calendar, &requisition);
233 
234  allocation.x = 0;
235  allocation.y = 0;
236  allocation.width = requisition.width;
237  allocation.height = requisition.height;
238 
239  gtk_widget_size_allocate (calendar, &allocation);
240  }
241 
242  date_picker = GNC_DATE_PICKER (item);
243 
244  date_picker->calendar = GTK_CALENDAR (calendar);
245 
246  g_signal_connect_after (calendar, "button_press_event",
247  G_CALLBACK (gnc_date_picker_button_event),
248  date_picker);
249 
250  g_signal_connect (calendar, "key_press_event",
251  G_CALLBACK (gnc_date_picker_key_event),
252  date_picker);
253 
254  g_signal_connect (calendar, "day_selected",
255  G_CALLBACK (day_selected),
256  date_picker);
257 
258  g_signal_connect (calendar, "day_selected_double_click",
259  G_CALLBACK (day_selected_double_click),
260  date_picker);
261 
262  return item;
263 }