2 * This file is part of hildon-libs
4 * Copyright (C) 2005 Nokia Corporation.
6 * Contact: Luc Pionchon <luc.pionchon@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * @shortdesc: TimeEditor is a widget for setting, getting and showing a
28 * @longdesc: The Time Editor widget is used to enter the system time
29 * (hours and minutes) in the Date/Time system plugin. It is a composite
30 * widget consisting of two GtkEntry widgets that are placed next to each
31 * other. The leftmost GtkEntry is used to enter the hours, and it accepts
32 * the values 0--23, while the rightmost GtkEntry accepts values 0--59
33 * and is used to set the minutes. Between the two GtkEntries there
34 * is a label displaying a colon.
36 * From the usability point of view, the GtkSpinbutton widget would
37 * have been a better choice than the GtkEntry widgets, but it uses
38 * floating point operations and is thus not acceptable in this
41 * @seealso: #HildonDateEditor
48 #include <pango/pango.h>
49 #include <gtk/gtkbox.h>
50 #include <gtk/gtkentry.h>
52 #include <gdk/gdkkeysyms.h>
53 #include <gtk/gtkwidget.h>
63 #include <hildon-widgets/hildon-defines.h>
64 #include <hildon-widgets/hildon-time-editor.h>
65 #include <hildon-widgets/hildon-time-picker.h>
66 #include <hildon-widgets/gtk-infoprint.h>
67 #include <hildon-widgets/hildon-input-mode-hint.h>
68 #include "hildon-composite-widget.h"
69 #include "hildon-date-editor.h"
71 #define _(String) dgettext(PACKAGE, String)
73 /* empty space on left and right side of a GtkEntry. Space needed
74 is 12, we add 4 extra pixels so that the arabic locale works
75 correctly. (With 12 only one digit would be shown in the entries).
77 #define TIME_EDITOR_LBORDER 2
78 #define TIME_EDITOR_RBORDER 1
79 #define TIME_EDITOR_HEIGHT 28
80 #define TIME_EDITOR_CLOCK_BORDER 6
81 #define ENTRY_BORDER 2
83 #define ICON_HEIGHT 26
84 #define ICON_PRESSED 4
85 #define ICON_NAME "qgn_widg_timedit"
86 #define ICON_SIZE "timepicker-size"
87 #define HILDON_TIME_EDITOR_GET_PRIVATE(obj) \
88 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
89 HILDON_TYPE_TIME_EDITOR, HildonTimeEditorPrivate));
90 #define MIN_DURATION 0
91 #define MAX_DURATION (3600 * 99) + (60 * 59) + 59
93 #define HILDON_TIME_EDITOR_TICKS_VALUE 0
94 #define HILDON_TIME_EDITOR_SHOW_SECONDS TRUE
95 #define HILDON_TIME_EDITOR_DURATION_MODE FALSE
96 #define HILDON_TIME_EDITOR_DURATION_LOWER_VALUE 0
97 #define HILDON_TIME_EDITOR_TIME_LOWER_VALUE 0
98 #define HILDON_TIME_EDITOR_TIME_UPPER_VALUE (3600 * 23) + (60 * 59) + 59
99 #define HILDON_TIME_EDITOR_DURATION_UPPER_VALUE (3600 * 99) + (60 * 59) + 59
101 #define HOURS_MAX_24 23
102 #define HOURS_MAX_12 12
103 #define HOURS_MIN_24 0
104 #define HOURS_MIN_12 1
105 #define MINUTES_MAX 59
106 #define SECONDS_MAX 59
107 #define MINUTES_MIN 0
108 #define SECONDS_MIN 0
110 static GtkContainerClass *parent_class;
112 typedef struct _HildonTimeEditorPrivate HildonTimeEditorPrivate;
125 VALIDATION_ERROR, /* should never be returned, translates as system error */
127 VALIDATION_DURATION_MAX,
128 VALIDATION_DURATION_MIN,
129 VALIDATION_TIME_HOURS,
130 VALIDATION_TIME_MINUTES,
131 VALIDATION_TIME_SECONDS,
140 hildon_time_editor_class_init(HildonTimeEditorClass * editor_class);
142 static void hildon_time_editor_init(HildonTimeEditor * editor);
144 static void hildon_time_editor_finalize(GObject * obj_self);
146 static void hildon_time_editor_set_property( GObject *object, guint param_id,
147 const GValue *value, GParamSpec *pspec );
148 static void hildon_time_editor_get_property( GObject *object, guint param_id,
149 GValue *value, GParamSpec *pspec );
152 hildon_time_editor_forall(GtkContainer * container,
153 gboolean include_internals, GtkCallback callback,
154 gpointer callback_data);
156 static void hildon_time_editor_destroy(GtkObject * self);
158 static void hildon_time_editor_add_style(void);
161 set_widget_allocation(GtkWidget * widget, GtkAllocation * alloc,
162 GtkAllocation * allocation);
169 hildon_time_editor_entry_focusout(GtkWidget * widget,
170 GdkEventFocus * event, gpointer data);
172 static gboolean hildon_time_editor_entry_focusin(GtkWidget * widget,
173 GdkEventFocus * event,
176 hildon_time_editor_mnemonic_activate(GtkWidget * widget,
177 gboolean group_cycling);
180 hildon_time_editor_ampm_clicked(GtkWidget * widget, GdkEventButton * event,
183 hildon_time_editor_icon_clicked(GtkWidget * widget, gpointer data);
186 hildon_time_editor_entry_clicked(GtkWidget * widget,
187 GdkEventButton * event, gpointer data);
190 hildon_time_editor_entry_changed(GtkWidget * widget, gpointer user_data);
194 hildon_time_editor_size_request(GtkWidget * widget,
195 GtkRequisition * requisition);
198 hildon_time_editor_size_allocate(GtkWidget * widget,
199 GtkAllocation * allocation);
202 hildon_time_editor_entry_keypress(GtkWidget * widget, GdkEventKey * event,
209 static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor);
212 void hildon_time_editor_tap_and_hold_setup(GtkWidget * widget,
215 GtkWidgetTapAndHoldFlags flags);
218 hildon_time_editor_get_max_values(HildonTimeEditor *editor,
219 guint * max_hours, guint * min_hours,
220 guint * max_minutes, guint * min_minutes,
221 guint * max_seconds, guint * min_seconds);
224 hildon_time_editor_validate (HildonTimeEditor *editor);
226 static HildonValidation
227 hildon_time_editor_validate_duration (HildonTimeEditor * editor, guint ticks);
229 static HildonValidation
230 hildon_time_editor_validate_time (HildonTimeEditor * editor,
241 convert_to_12h (guint *h, guint *m, guint *s, gboolean *am);
243 convert_to_24h (guint *h, guint *m, guint *s, gboolean am);
245 static void ticks_to_time (guint ticks,
251 struct _HildonTimeEditorPrivate {
252 guint ticks; /* Current duration in seconds */
256 GtkWidget *eventbox; /* hold entries */
257 GtkWidget *iconbutton; /* button for icon */
262 GtkWidget *label; /* between h and m */
263 GtkWidget *label2; /* between m and s */
264 GtkWidget *ampm; /* label for showing am or pm */
265 GtkWidget *icon; /* label for showing am or pm */
266 GtkWidget *frame; /* frame around the entries */
268 gboolean duration_mode; /* In HildonDurationEditor mode */
269 gboolean show_s; /* show seconds */
270 gboolean ampm_pos_after; /* is the am/pm shown after others */
271 gboolean clock_24h; /* whether to show a 24h clock */
272 gboolean am; /* TRUE == showing am, FALSE == pm */
273 gboolean valid_value; /* If entry has an valid value */
275 gboolean validated; /* If the current value has been validated */
277 /* Duration editor ranges */
282 GType hildon_time_editor_get_type(void)
284 static GType editor_type = 0;
287 static const GTypeInfo editor_info = {
288 sizeof(HildonTimeEditorClass),
289 NULL, /* base_init */
290 NULL, /* base_finalize */
291 (GClassInitFunc) hildon_time_editor_class_init,
292 NULL, /* class_finalize */
293 NULL, /* class_data */
294 sizeof(HildonTimeEditor),
296 (GInstanceInitFunc) hildon_time_editor_init,
298 editor_type = g_type_register_static(GTK_TYPE_CONTAINER,
305 static void hildon_time_editor_forall(GtkContainer * container,
306 gboolean include_internals,
307 GtkCallback callback,
308 gpointer callback_data)
310 HildonTimeEditor *editor;
311 HildonTimeEditorPrivate *priv;
313 editor = HILDON_TIME_EDITOR(container);
314 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
316 g_return_if_fail(container);
317 g_return_if_fail(callback);
319 if (!include_internals)
323 /* widget that are always shown */
324 (*callback) (priv->h_entry, callback_data);
325 (*callback) (priv->m_entry, callback_data);
326 (*callback) (priv->iconbutton, callback_data);
327 (*callback) (priv->frame, callback_data);
328 (*callback) (priv->label, callback_data);
329 (*callback) (priv->label2, callback_data);
330 (*callback) (priv->s_entry, callback_data);
331 (*callback) (priv->eventbox, callback_data);
334 static void hildon_time_editor_destroy(GtkObject * self)
336 HildonTimeEditorPrivate *priv;
338 priv = HILDON_TIME_EDITOR_GET_PRIVATE(self);
341 gtk_widget_unparent(priv->h_entry);
342 priv->h_entry = NULL;
345 gtk_widget_unparent(priv->m_entry);
346 priv->m_entry = NULL;
349 gtk_widget_unparent(priv->label);
352 if (priv->iconbutton) {
353 gtk_widget_unparent(priv->iconbutton);
354 priv->iconbutton = NULL;
357 gtk_widget_unparent(priv->frame);
360 if (priv->eventbox) {
361 gtk_widget_unparent(priv->eventbox);
362 priv->eventbox = NULL;
366 gtk_widget_unparent(priv->label2);
370 gtk_widget_unparent(priv->s_entry);
371 priv->s_entry = NULL;
374 if (GTK_OBJECT_CLASS(parent_class)->destroy)
375 GTK_OBJECT_CLASS(parent_class)->destroy(self);
380 hildon_time_editor_class_init(HildonTimeEditorClass * editor_class)
382 GObjectClass *object_class = G_OBJECT_CLASS(editor_class);
383 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class);
384 GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class);
386 parent_class = g_type_class_peek_parent(editor_class);
388 g_type_class_add_private(editor_class,
389 sizeof(HildonTimeEditorPrivate));
391 object_class->get_property = hildon_time_editor_get_property;
392 object_class->set_property = hildon_time_editor_set_property;
395 widget_class->mnemonic_activate = hildon_time_editor_mnemonic_activate;
396 widget_class->size_request = hildon_time_editor_size_request;
397 widget_class->size_allocate = hildon_time_editor_size_allocate;
398 widget_class->tap_and_hold_setup =
399 hildon_time_editor_tap_and_hold_setup;
400 widget_class->focus = hildon_composite_widget_focus;
402 container_class->forall = hildon_time_editor_forall;
403 GTK_OBJECT_CLASS(editor_class)->destroy = hildon_time_editor_destroy;
405 object_class->finalize = hildon_time_editor_finalize;
408 * HildonTimeEditor:ticks:
410 * TimeEditor current duration (or time since midnight) value.
412 g_object_class_install_property( object_class, PROP_TICKS,
413 g_param_spec_uint("ticks",
415 "Current value of duration",
417 HILDON_TIME_EDITOR_TICKS_VALUE,
418 G_PARAM_READABLE | G_PARAM_WRITABLE) );
421 * HildonTimeEditor:show_seconds:
423 * TimeEditor show_seconds property.
425 g_object_class_install_property( object_class, PROP_SHOW_SECONDS,
426 g_param_spec_boolean("show_seconds",
427 "Show seconds property",
428 "Controls whether the seconds are shown in the editor",
429 HILDON_TIME_EDITOR_SHOW_SECONDS,
430 G_PARAM_READABLE | G_PARAM_WRITABLE) );
433 * HildonTimeEditor:duration_mode:
435 * TimeEditor duration mode indicator.
437 g_object_class_install_property( object_class, PROP_DURATION_MODE,
438 g_param_spec_boolean("duration_mode",
440 "Controls whether the TimeEditor is in duration mode",
441 HILDON_TIME_EDITOR_DURATION_MODE,
442 G_PARAM_READABLE | G_PARAM_WRITABLE) );
445 * HildonTimeEditor:duration_min:
447 * TimeEditor minimum duration value.
449 g_object_class_install_property( object_class, PROP_DURATION_MIN,
450 g_param_spec_uint("duration_min",
451 "Minumum duration value",
452 "Smallest possible duration value",
454 HILDON_TIME_EDITOR_DURATION_LOWER_VALUE,
455 G_PARAM_READABLE | G_PARAM_WRITABLE) );
458 * HildonTimeEditor:duration_max:
460 * TimeEditor maximum duration value.
462 g_object_class_install_property( object_class, PROP_DURATION_MAX,
463 g_param_spec_uint("duration_max",
464 "Maximum duration value",
465 "Largest possible duration value",
467 HILDON_TIME_EDITOR_DURATION_UPPER_VALUE,
468 G_PARAM_READABLE | G_PARAM_WRITABLE) );
473 void hildon_time_editor_tap_and_hold_setup(GtkWidget * widget,
476 GtkWidgetTapAndHoldFlags flags)
478 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget);
480 gtk_widget_tap_and_hold_setup(priv->h_entry, menu, func,
481 GTK_TAP_AND_HOLD_NO_SIGNALS);
482 gtk_widget_tap_and_hold_setup(priv->m_entry, menu, func,
483 GTK_TAP_AND_HOLD_NO_SIGNALS);
484 gtk_widget_tap_and_hold_setup(priv->s_entry, menu, func,
485 GTK_TAP_AND_HOLD_NO_SIGNALS);
486 gtk_widget_tap_and_hold_setup(priv->eventbox, menu, func,
487 GTK_TAP_AND_HOLD_NO_SIGNALS);
488 gtk_widget_tap_and_hold_setup(priv->iconbutton, menu, func,
489 GTK_TAP_AND_HOLD_NONE);
492 static void hildon_time_editor_init(HildonTimeEditor * editor)
494 HildonTimeEditorPrivate *priv;
497 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
499 gtk_widget_push_composite_child();
502 priv->show_s = FALSE;
503 priv->ampm_pos_after = TRUE;
504 priv->clock_24h = TRUE;
505 priv->duration_mode = FALSE;
506 priv->iconbutton = gtk_button_new();
507 priv->h_entry = gtk_entry_new();
508 priv->m_entry = gtk_entry_new();
509 priv->s_entry = gtk_entry_new();
510 priv->ampm = gtk_label_new(NULL);
511 priv->label = gtk_label_new(_("Ecdg_ti_time_editor_separator"));
512 priv->label2 = gtk_label_new(_("Ecdg_ti_time_editor_separator"));
513 priv->icon = gtk_image_new_from_icon_name(ICON_NAME, HILDON_ICON_SIZE_26);
514 priv->frame = gtk_frame_new(NULL);
515 priv->eventbox = gtk_event_box_new();
516 priv->valid_value = TRUE;
517 priv->validated = FALSE;
519 GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW);
520 GTK_WIDGET_UNSET_FLAGS(priv->iconbutton, GTK_CAN_FOCUS);
522 gtk_event_box_set_visible_window(GTK_EVENT_BOX(priv->eventbox), FALSE);
524 gtk_container_set_border_width(GTK_CONTAINER(priv->frame), 0);
526 gtk_container_add(GTK_CONTAINER(priv->iconbutton), priv->icon);
527 gtk_container_add(GTK_CONTAINER(priv->eventbox), priv->ampm);
529 gtk_entry_set_has_frame(GTK_ENTRY(priv->h_entry), FALSE);
530 gtk_entry_set_has_frame(GTK_ENTRY(priv->m_entry), FALSE);
531 gtk_entry_set_has_frame(GTK_ENTRY(priv->s_entry), FALSE);
533 g_object_set (G_OBJECT(priv->h_entry), "input-mode",
534 HILDON_INPUT_MODE_HINT_NUMERIC, NULL);
535 g_object_set (G_OBJECT(priv->m_entry), "input-mode",
536 HILDON_INPUT_MODE_HINT_NUMERIC, NULL);
537 g_object_set (G_OBJECT(priv->s_entry), "input-mode",
538 HILDON_INPUT_MODE_HINT_NUMERIC, NULL);
541 /* clicked signal for am/pm label */
542 g_signal_connect(G_OBJECT(priv->eventbox), "button_press_event",
543 G_CALLBACK(hildon_time_editor_ampm_clicked), editor);
545 /* clicked signal for icon */
546 g_signal_connect(G_OBJECT(priv->iconbutton), "clicked",
547 G_CALLBACK(hildon_time_editor_icon_clicked), editor);
549 /* clicked signal for hour entry */
550 g_signal_connect(G_OBJECT(priv->h_entry), "button-release-event",
551 G_CALLBACK(hildon_time_editor_entry_clicked), editor);
552 g_signal_connect(G_OBJECT(priv->h_entry), "focus-in-event",
553 G_CALLBACK(hildon_time_editor_entry_focusin), editor);
555 /* clicked signal for minute entry */
556 g_signal_connect(G_OBJECT(priv->m_entry), "button-release-event",
557 G_CALLBACK(hildon_time_editor_entry_clicked), editor);
558 g_signal_connect(G_OBJECT(priv->m_entry), "focus-in-event",
559 G_CALLBACK(hildon_time_editor_entry_focusin), editor);
561 /* clicked signal for second entry */
562 g_signal_connect(G_OBJECT(priv->s_entry), "button-release-event",
563 G_CALLBACK(hildon_time_editor_entry_clicked), editor);
564 g_signal_connect(G_OBJECT(priv->s_entry), "focus-in-event",
565 G_CALLBACK(hildon_time_editor_entry_focusin), editor);
567 /* focus out events */
568 g_signal_connect(G_OBJECT(priv->h_entry), "focus-out-event",
569 G_CALLBACK(hildon_time_editor_entry_focusout),
571 g_signal_connect(G_OBJECT(priv->m_entry), "focus-out-event",
572 G_CALLBACK(hildon_time_editor_entry_focusout),
574 g_signal_connect(G_OBJECT(priv->s_entry), "focus-out-event",
575 G_CALLBACK(hildon_time_editor_entry_focusout),
578 /* key press events */
579 g_signal_connect(G_OBJECT(priv->h_entry), "key-press-event",
580 G_CALLBACK(hildon_time_editor_entry_keypress),
582 g_signal_connect(G_OBJECT(priv->m_entry), "key-press-event",
583 G_CALLBACK(hildon_time_editor_entry_keypress),
585 g_signal_connect(G_OBJECT(priv->s_entry), "key-press-event",
586 G_CALLBACK(hildon_time_editor_entry_keypress),
589 /* changed signal sets time */
590 g_signal_connect_after (G_OBJECT(priv->h_entry), "changed",
591 G_CALLBACK (hildon_time_editor_entry_changed),
593 g_signal_connect_after (G_OBJECT(priv->m_entry), "changed",
594 G_CALLBACK (hildon_time_editor_entry_changed),
596 g_signal_connect_after (G_OBJECT(priv->s_entry), "changed",
597 G_CALLBACK (hildon_time_editor_entry_changed),
600 gtk_widget_set_parent(priv->iconbutton, GTK_WIDGET(editor));
601 gtk_widget_set_parent(priv->label, GTK_WIDGET(editor));
603 gtk_widget_set_parent(priv->label2, GTK_WIDGET(editor));
604 gtk_widget_set_parent(priv->s_entry, GTK_WIDGET(editor));
605 gtk_widget_set_parent(priv->eventbox, GTK_WIDGET(editor));
606 gtk_widget_set_parent(priv->m_entry, GTK_WIDGET(editor));
607 gtk_widget_set_parent(priv->h_entry, GTK_WIDGET(editor));
609 gtk_widget_show(priv->h_entry);
610 gtk_widget_show(priv->m_entry);
611 gtk_widget_show_all(priv->iconbutton);
612 gtk_widget_show(priv->label);
614 gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor));
615 gtk_widget_show_all(priv->frame);
617 /* Check if we are in am/pm time locale */
618 if (!hildon_time_editor_check_locale(editor)) {
619 priv->clock_24h = FALSE;
620 gtk_widget_show_all(priv->eventbox);
623 { /* get current time */
628 stm = localtime(&tm);
631 ticks = stm->tm_hour * 3600;
632 ticks = ticks + stm->tm_min * 60;
633 ticks = ticks + stm->tm_sec;
637 hildon_time_editor_set_ticks (editor, ticks);
639 gtk_entry_set_max_length(GTK_ENTRY(priv->h_entry), 2);
640 gtk_entry_set_width_chars(GTK_ENTRY(priv->h_entry), 2);
641 gtk_entry_set_max_length(GTK_ENTRY(priv->m_entry), 2);
642 gtk_entry_set_width_chars(GTK_ENTRY(priv->m_entry), 2);
643 gtk_entry_set_max_length(GTK_ENTRY(priv->s_entry), 2);
644 gtk_entry_set_width_chars(GTK_ENTRY(priv->s_entry), 2);
646 hildon_time_editor_add_style();
647 gtk_widget_set_name(GTK_WIDGET(priv->iconbutton),
648 "hildon-time-editor-icon");
650 gtk_widget_pop_composite_child();
653 static void hildon_time_editor_set_property (GObject *object, guint param_id,
654 const GValue *value, GParamSpec *pspec)
656 HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object);
660 hildon_time_editor_set_ticks (time_editor, g_value_get_uint(value));
663 case PROP_SHOW_SECONDS:
664 hildon_time_editor_set_show_seconds (time_editor, g_value_get_boolean(value));
667 case PROP_DURATION_MODE:
668 hildon_time_editor_set_duration_mode (time_editor, g_value_get_boolean(value));
671 case PROP_DURATION_MIN:
672 hildon_time_editor_set_duration_min (time_editor, g_value_get_uint(value));
675 case PROP_DURATION_MAX:
676 hildon_time_editor_set_duration_max (time_editor, g_value_get_uint(value));
680 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
685 static void hildon_time_editor_get_property (GObject *object, guint param_id,
686 GValue *value, GParamSpec *pspec)
688 HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object);
693 g_value_set_uint (value, hildon_time_editor_get_ticks (time_editor));
696 case PROP_SHOW_SECONDS:
697 g_value_set_boolean (value, hildon_time_editor_get_show_seconds (time_editor));
700 case PROP_DURATION_MODE:
701 g_value_set_boolean (value, hildon_time_editor_get_duration_mode (time_editor));
704 case PROP_DURATION_MIN:
705 g_value_set_uint (value, hildon_time_editor_get_duration_min (time_editor));
708 case PROP_DURATION_MAX:
709 g_value_set_uint (value, hildon_time_editor_get_duration_max (time_editor));
713 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
720 hildon_time_editor_mnemonic_activate( GtkWidget *widget,
721 gboolean group_cycling)
723 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget);
724 gtk_widget_grab_focus( priv->h_entry );
725 gtk_editable_select_region(GTK_EDITABLE(priv->h_entry), 0, 2);
730 * hildon_time_editor_new:
732 * This function creates a new time editor.
734 * Return value: pointer to a new #HildonTimeEditor widget.
737 GtkWidget *hildon_time_editor_new(void)
739 return GTK_WIDGET(g_object_new(HILDON_TYPE_TIME_EDITOR, NULL));
742 static void hildon_time_editor_finalize(GObject * obj_self)
744 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(obj_self);
747 g_free(priv->am_symbol);
749 g_free(priv->pm_symbol);
751 if (G_OBJECT_CLASS(parent_class)->finalize)
752 G_OBJECT_CLASS(parent_class)->finalize(obj_self);
755 static void hildon_time_editor_add_style(void)
757 gtk_rc_parse_string(" style \"hildon-time-editor-icon\" {"
758 " GtkButton::default_border = { 0, 0, 0, 0 }"
761 " engine \"pixmap\" {"
767 " widget \"*.hildon-time-editor-icon\""
768 " style \"hildon-time-editor-icon\"");
771 static void ticks_to_time (guint ticks,
779 m = (ticks - h*3600) / 60;
780 s = ticks - h*3600 - m*60;
789 * hildon_time_editor_set_ticks:
790 * @self: the @HildonTimeEditor widget.
791 * @ticks: The duration to set, in seconds.
793 * Sets the current duration in seconds. This means seconds from
794 * midnight, if not in duration mode. In case of any errors, it tries
799 void hildon_time_editor_set_ticks (HildonTimeEditor * editor,
802 HildonTimeEditorPrivate *priv;
803 HildonValidation validation;
807 gchar hours[3] = "01";
808 gchar minutes[3] = "00";
809 gchar seconds[3] = "00";
811 g_return_if_fail(editor);
812 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
814 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
816 /* Validate the value if it is not already validated */
817 if (!priv->validated) {
818 if (priv->duration_mode) {
819 validation = hildon_time_editor_validate_duration (editor, ticks);
821 case VALIDATION_DURATION_MIN:
822 priv->ticks = priv->duration_min;
824 case VALIDATION_DURATION_MAX:
825 priv->ticks = priv->duration_max;
832 ticks_to_time (ticks, &h, &m, &s);
833 validation = hildon_time_editor_validate_time (editor, h, m, s, TRUE);
834 switch (validation) {
835 case VALIDATION_TIME_HOURS:
836 if (priv->clock_24h) {
837 if (h > HOURS_MAX_24) {
839 } else if (h < HOURS_MIN_24) {
843 if (h > HOURS_MAX_12) {
845 } else if (h < HOURS_MIN_12) {
849 priv->ticks = (3600 * h) + (60 * m) + s;
851 case VALIDATION_TIME_MINUTES:
852 if (m > MINUTES_MAX) {
854 } else if (m < MINUTES_MIN) {
858 case VALIDATION_TIME_SECONDS:
859 if (s > SECONDS_MAX) {
861 } else if (s < SECONDS_MIN) {
864 priv->ticks = (3600 * h) + (60 * m) + s;
875 ticks_to_time (priv->ticks, &h, &m, &s);
877 ticks_to_time (priv->ticks, &h, &m, &s);
879 if (!priv->clock_24h && !priv->duration_mode)
881 convert_to_12h (&h, &m, &s, &priv->am);
884 g_snprintf(hours, 3, "%02u", h);
885 g_snprintf(minutes, 3, "%02u", m);
886 g_snprintf(seconds, 3, "%02u", s);
887 gtk_entry_set_text(GTK_ENTRY(priv->h_entry), hours);
888 gtk_entry_set_text(GTK_ENTRY(priv->m_entry), minutes);
889 gtk_entry_set_text(GTK_ENTRY(priv->s_entry), seconds);
891 priv->valid_value = TRUE;
892 priv->validated = FALSE;
894 /* set current time (am/pm) */
895 gtk_label_set_label(GTK_LABEL(priv->ampm), priv->am ? priv->am_symbol :
898 g_object_notify (G_OBJECT (editor), "ticks");
902 * hildon_time_editor_get_ticks:
903 * @self: the @HildonTimeEditor widget.
905 * This function returns the current duration, in seconds.
906 * This means seconds from midnight, if not in duration mode.
908 * Return value: Current duration in seconds.
911 guint hildon_time_editor_get_ticks (HildonTimeEditor * editor)
913 HildonTimeEditorPrivate *priv;
915 g_return_val_if_fail(editor, 0);
916 g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0);
918 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
920 return (priv->ticks);
924 * hildon_time_editor_set_show_seconds:
925 * @editor: The #HildonTimeEditor.
926 * @enable: Enable or disable showing of seconds.
928 * This function shows or hides the seconds field.
932 void hildon_time_editor_set_show_seconds (HildonTimeEditor * editor,
933 gboolean show_seconds)
935 HildonTimeEditorPrivate *priv;
937 g_return_if_fail(editor);
939 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
941 if (!priv->show_s && show_seconds) {
944 gtk_widget_show(priv->s_entry);
945 gtk_widget_show(priv->label2);
947 } else if (priv->show_s && !show_seconds) {
949 gtk_widget_hide(priv->s_entry);
950 gtk_widget_hide(priv->label2);
952 priv->show_s = FALSE;
956 gtk_widget_queue_resize(GTK_WIDGET(editor));
958 g_object_notify (G_OBJECT (editor), "show_seconds");
962 * hildon_time_editor_get_show_seconds:
963 * @self: the @HildonTimeEditor widget.
965 * This function returns a boolean indicating the visibility of
966 * seconds in the @HildonTimeEditor
968 * Return value: TRUE if the seconds are visible.
971 gboolean hildon_time_editor_get_show_seconds (HildonTimeEditor * editor)
973 HildonTimeEditorPrivate *priv;
975 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
976 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
978 return (priv->show_s);
982 * hildon_time_editor_set_duration_mode:
983 * @editor: The #HildonTimeEditor.
984 * @enable: Enable or disable duration editor mode
986 * This function sets the duration editor mode in which the maximum hours
987 * is 99 and the #HildonTimePicker is disabled.
991 void hildon_time_editor_set_duration_mode (HildonTimeEditor * editor,
992 gboolean duration_mode)
994 HildonTimeEditorPrivate *priv;
996 g_return_if_fail(editor);
998 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1000 /* switch to duration editor mode */
1001 if (duration_mode && !priv->duration_mode) {
1002 priv->duration_mode = duration_mode;
1003 hildon_time_editor_set_duration_range(editor, MIN_DURATION,
1006 if (!priv->clock_24h)
1007 gtk_widget_hide(GTK_WIDGET(priv->ampm));
1009 gtk_widget_hide(GTK_WIDGET(priv->eventbox));
1010 gtk_widget_hide(GTK_WIDGET(priv->icon));
1012 /* Show seconds for duration editor */
1013 hildon_time_editor_set_show_seconds(editor, TRUE);
1015 /* switch to time editor mode */
1016 else if (!duration_mode && priv->duration_mode) {
1021 priv->duration_mode = duration_mode;
1023 if (!priv->clock_24h)
1024 gtk_widget_show(GTK_WIDGET(priv->ampm));
1026 gtk_widget_show(GTK_WIDGET(priv->eventbox));
1027 gtk_widget_show(GTK_WIDGET(priv->icon));
1030 /* Put the ticks to match current time, anything set in the
1031 * duration mode is bound to be invalid or useless in time mode
1035 stm = localtime(&tm);
1037 ticks = HILDON_TIME_EDITOR_TIME_LOWER_VALUE;
1040 ticks = stm->tm_hour * 3600;
1041 ticks = ticks + stm->tm_min * 60;
1042 ticks = ticks + stm->tm_sec;
1045 hildon_time_editor_set_ticks (editor, ticks);
1048 gtk_widget_queue_resize(GTK_WIDGET(editor));
1050 g_object_notify (G_OBJECT (editor), "duration_mode");
1054 * hildon_time_editor_get_duration_mode:
1055 * @self: the @HildonTimeEditor widget.
1057 * This function returns a boolean indicating whether the @HildonTimeEditor
1058 * is in the duration mode.
1060 * Return value: TRUE if the @HildonTimeEditor is in duration mode.
1063 gboolean hildon_time_editor_get_duration_mode (HildonTimeEditor * editor)
1065 HildonTimeEditorPrivate *priv;
1067 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
1068 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1070 return (priv->duration_mode);
1074 * hildon_time_editor_set_duration_min:
1075 * @self: the @HildonTimeEditor widget.
1076 * @duration_min: Mimimum allowed duration.
1078 * Sets the minimum allowed duration for the duration mode.
1079 * Note: Has no effect in time mode
1082 void hildon_time_editor_set_duration_min (HildonTimeEditor * editor,
1085 HildonTimeEditorPrivate *priv;
1087 g_return_if_fail(editor);
1088 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1090 g_return_if_fail(duration_min >= MIN_DURATION);
1092 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1094 if( !priv->duration_mode )
1097 priv->duration_min = duration_min;
1099 /* Clamp the current value to the minimum if necessary */
1100 if (priv->ticks < duration_min)
1102 hildon_time_editor_set_ticks (editor, duration_min);
1105 g_object_notify (G_OBJECT (editor), "duration_min");
1109 * hildon_time_editor_get_duration_min:
1110 * @self: the @HildonTimeEditor widget.
1112 * This function returns the smallest duration the @HildonTimeEditor
1113 * allows in the duration mode.
1115 * Return value: Mimimum allowed duration in seconds.
1118 guint hildon_time_editor_get_duration_min (HildonTimeEditor * editor)
1120 HildonTimeEditorPrivate *priv;
1122 g_return_val_if_fail(editor, 0);
1123 g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0);
1125 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1127 if( !priv->duration_mode )
1130 return (priv->duration_min);
1134 * hildon_time_editor_set_duration_max:
1135 * @self: the @HildonTimeEditor widget.
1136 * @duration_min: Maximum allowed duration in seconds.
1138 * Sets the maximum allowed duration in seconds for the duration mode.
1139 * Note: Has no effect in time mode
1143 void hildon_time_editor_set_duration_max (HildonTimeEditor * editor,
1146 HildonTimeEditorPrivate *priv;
1148 g_return_if_fail(editor);
1149 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1151 g_return_if_fail(duration_max <= MAX_DURATION);
1153 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1155 if( !priv->duration_mode )
1158 priv->duration_max = duration_max;
1160 /* Clamp the current value to the maximum if necessary */
1161 if (priv->ticks > duration_max)
1163 hildon_time_editor_set_ticks (editor, duration_max);
1166 g_object_notify (G_OBJECT (editor), "duration_max");
1170 * hildon_time_editor_get_duration_max:
1171 * @self: the @HildonTimeEditor widget.
1173 * This function returns the longest duration the @HildonTimeEditor
1174 * allows in the duration mode.
1176 * Return value: Maximum allowed duration in seconds.
1179 guint hildon_time_editor_get_duration_max (HildonTimeEditor * editor)
1181 HildonTimeEditorPrivate *priv;
1183 g_return_val_if_fail(editor, 0);
1184 g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0);
1186 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1188 if( !priv->duration_mode )
1191 return (priv->duration_max);
1196 * hildon_time_editor_set_time:
1197 * @editor: the @HildonTimeEditor widget.
1202 * This function sets the time on an existing time editor. If the
1203 * time specified by the arguments is invalid, the function returns
1204 * without doing anything else. The time is assumed to be in 24h format.
1208 void hildon_time_editor_set_time(HildonTimeEditor * editor, guint hours,
1209 guint minutes, guint seconds)
1211 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1213 hildon_time_editor_set_ticks (editor, hours * 3600 + minutes * 60 + seconds);
1218 * hildon_time_editor_get_time:
1219 * @editor: the @HildonTimeEditor widget.
1224 * Gets the time of the @HildonTimeEditor widget. The time returned is
1225 * always in 24h format.
1228 void hildon_time_editor_get_time(HildonTimeEditor * editor,
1230 guint * minutes, guint * seconds)
1232 HildonTimeEditorPrivate *priv;
1234 g_return_if_fail(editor);
1235 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1237 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1239 ticks_to_time (hildon_time_editor_get_ticks (editor),
1240 hours, minutes, seconds);
1245 * hildon_time_editor_set_duration_range:
1246 * @editor: the @HildonTimeEditor widget.
1247 * @min_seconds: minimum allowed time in seconds
1248 * @max_seconds: maximum allowed time in seconds
1250 * Sets the duration editor time range of the @HildonTimeEditor widget.
1253 void hildon_time_editor_set_duration_range(HildonTimeEditor * editor,
1257 HildonTimeEditorPrivate *priv;
1260 g_return_if_fail(editor);
1261 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1263 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1264 /* Swap values if reversed */
1265 if (min_seconds > max_seconds)
1268 max_seconds = min_seconds;
1272 hildon_time_editor_set_duration_max (editor, max_seconds);
1273 hildon_time_editor_set_duration_min (editor, min_seconds);
1275 if (priv->duration_mode) {
1276 /* Set minimum allowed value for duration editor */
1277 hildon_time_editor_set_ticks(editor, min_seconds);
1282 * hildon_time_editor_get_duration_range:
1283 * @editor: the @HildonTimeEditor widget.
1284 * @min_seconds: pointer to guint
1285 * @max_seconds: pointer to guint
1287 * Gets the duration editor time range of the @HildonTimeEditor widget.
1290 void hildon_time_editor_get_duration_range(HildonTimeEditor * editor,
1291 guint * min_seconds,
1292 guint * max_seconds)
1294 HildonTimeEditorPrivate *priv;
1296 g_return_if_fail(editor);
1297 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1299 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1301 *min_seconds = priv->duration_min;
1302 *max_seconds = priv->duration_max;
1305 static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor)
1307 HildonTimeEditorPrivate *priv;
1310 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1312 priv->am_symbol = g_strdup(nl_langinfo(AM_STR));
1313 priv->pm_symbol = g_strdup(nl_langinfo(PM_STR));
1315 if (!strcmp(priv->am_symbol, ""))
1318 t_fm = g_strdup(nl_langinfo(T_FMT_AMPM));
1319 /* Check what format am/pm time should be */
1320 if (!strncmp(t_fm, "%p", 2))
1321 priv->ampm_pos_after = FALSE;
1323 g_ascii_strdown((const gchar *) priv->am_symbol, -1);
1325 g_ascii_strdown((const gchar *) priv->pm_symbol, -1);
1331 static gboolean hildon_time_editor_entry_focusin(GtkWidget * widget,
1332 GdkEventFocus * event,
1335 if (!GTK_ENTRY(widget)->button)
1336 gtk_editable_select_region(GTK_EDITABLE(widget), 0, 2);
1343 hildon_time_editor_validate (HildonTimeEditor *editor)
1345 guint max_hours = 0;
1346 guint min_hours = 0;
1347 guint max_minutes = 0;
1348 guint min_minutes = 0;
1349 guint max_seconds = 0;
1350 guint min_seconds = 0;
1352 HildonTimeEditorPrivate *priv;
1353 HildonValidation validation;
1358 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1360 window = GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor),
1363 hildon_time_editor_get_max_values(editor,
1364 &max_hours, &min_hours,
1365 &max_minutes, &min_minutes,
1366 &max_seconds, &min_seconds);
1368 /* No empty values thank you */
1369 if (strlen(GTK_ENTRY(priv->h_entry)->text) == 0)
1371 if (!priv->duration_mode)
1373 if (priv->clock_24h)
1375 gtk_infoprintf(window,
1376 _("Ckct_ib_set_a_value_within_range"),
1381 gtk_infoprintf(window,
1382 _("Ckct_ib_set_a_value_within_range"),
1388 gtk_infoprintf(window,
1389 _("Ckct_ib_set_a_value_within_range"),
1390 min_hours, max_hours);
1392 hildon_time_editor_set_ticks (editor, priv->ticks);
1393 gtk_widget_grab_focus (priv->h_entry);
1395 else if (strlen(GTK_ENTRY(priv->m_entry)->text) == 0)
1397 if (!priv->duration_mode)
1399 gtk_infoprintf(window,
1400 _("Ckct_ib_set_a_value_within_range"),
1405 gtk_infoprintf(window,
1406 _("Ckct_ib_set_a_value_within_range"),
1407 min_minutes, max_minutes);
1409 hildon_time_editor_set_ticks (editor, priv->ticks);
1410 gtk_widget_grab_focus (priv->m_entry);
1412 else if (strlen(GTK_ENTRY(priv->s_entry)->text) == 0)
1414 if (!priv->duration_mode)
1416 gtk_infoprintf(window,
1417 _("Ckct_ib_set_a_value_within_range"),
1422 gtk_infoprintf(window,
1423 _("Ckct_ib_set_a_value_within_range"),
1424 min_seconds, max_seconds);
1426 hildon_time_editor_set_ticks (editor, priv->ticks);
1427 gtk_widget_grab_focus (priv->s_entry);
1429 /* Do the validation dance! */
1433 h = (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->h_entry)));
1434 m = (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry)));
1435 s = (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->s_entry)));
1437 if (priv->duration_mode)
1439 validation = hildon_time_editor_validate_duration (editor,
1444 case VALIDATION_DURATION_MIN:
1445 gtk_infoprintf(window,
1446 _("Ckct_ib_min_allowed_duration_hts"),
1447 min_hours, min_minutes, min_seconds);
1448 hildon_time_editor_set_ticks (editor, priv->duration_min);
1450 case VALIDATION_DURATION_MAX:
1451 gtk_infoprintf(window,
1452 _("Ckct_ib_max_allowed_duration_hts"),
1453 max_hours, max_minutes, max_seconds);
1454 hildon_time_editor_set_ticks (editor, priv->duration_max);
1457 hildon_time_editor_set_ticks (editor, h*3600 + m*60 + s);
1463 validation = hildon_time_editor_validate_time (editor, h, m, s, priv->clock_24h);
1466 case VALIDATION_TIME_HOURS:
1467 if (priv->clock_24h)
1469 if (h > HOURS_MAX_24)
1471 gtk_infoprintf(window,
1472 _("Ckct_ib_maximum_value"),
1478 gtk_infoprintf(window,
1479 _("Ckct_ib_minimum_value"),
1486 if (h > HOURS_MAX_12)
1488 gtk_infoprintf(window,
1489 _("Ckct_ib_maximum_value"),
1495 gtk_infoprintf(window,
1496 _("Ckct_ib_minimum_value"),
1501 if (!priv->clock_24h)
1502 convert_to_24h (&h, &m, &s, priv->am);
1503 hildon_time_editor_set_time (editor, h, m, s);
1504 gtk_widget_grab_focus (priv->h_entry);
1505 gtk_editable_select_region(GTK_EDITABLE(priv->h_entry), 0, 2);
1507 case VALIDATION_TIME_MINUTES:
1508 if (m > MINUTES_MAX)
1510 gtk_infoprintf(window,
1511 _("Ckct_ib_maximum_value"),
1517 gtk_infoprintf(window,
1518 _("Ckct_ib_minimum_value"),
1522 if (!priv->clock_24h)
1523 convert_to_24h (&h, &m, &s, priv->am);
1524 hildon_time_editor_set_time (editor, h, m, s);
1525 gtk_widget_grab_focus (priv->m_entry);
1526 gtk_editable_select_region(GTK_EDITABLE(priv->m_entry), 0, 2);
1528 case VALIDATION_TIME_SECONDS:
1529 if (s > SECONDS_MAX)
1531 gtk_infoprintf(window,
1532 _("Ckct_ib_maximum_value"),
1538 gtk_infoprintf(window,
1539 _("Ckct_ib_minimum_value"),
1543 if (!priv->clock_24h)
1544 convert_to_24h (&h, &m, &s, priv->am);
1545 hildon_time_editor_set_time (editor, h, m, s);
1546 gtk_widget_grab_focus (priv->s_entry);
1547 gtk_editable_select_region(GTK_EDITABLE(priv->s_entry), 0, 2);
1550 if (!priv->clock_24h)
1552 convert_to_24h (&h, &m, &s, priv->am);
1554 hildon_time_editor_set_time (editor, h, m, s);
1562 static gboolean hildon_time_editor_entry_focusout(GtkWidget * widget,
1563 GdkEventFocus * event,
1566 HildonTimeEditor *editor;
1568 editor = HILDON_TIME_EDITOR(data);
1570 hildon_time_editor_validate (editor);
1576 hildon_time_editor_ampm_clicked(GtkWidget * widget,
1577 GdkEventButton * event, gpointer data)
1579 HildonTimeEditor *editor;
1580 HildonTimeEditorPrivate *priv = NULL;
1582 g_return_val_if_fail(widget, FALSE);
1583 g_return_val_if_fail(data, FALSE);
1586 editor = HILDON_TIME_EDITOR(data);
1587 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1589 /* validate to set the time and get infoprints
1590 * if the user was editing the value
1592 hildon_time_editor_validate (editor);
1594 if (priv->ticks >= (12*3600))
1596 hildon_time_editor_set_ticks (editor, priv->ticks - 12*3600);
1599 hildon_time_editor_set_ticks (editor, priv->ticks + 12*3600);
1602 hildon_time_editor_set_ticks (editor, priv->ticks - 12*3600);
1608 hildon_time_editor_icon_clicked(GtkWidget * widget, gpointer data)
1610 HildonTimeEditor *editor;
1611 HildonTimeEditorPrivate *priv;
1614 guint h, m, s, result;
1616 g_return_val_if_fail(widget, FALSE);
1617 g_return_val_if_fail(data, FALSE);
1619 editor = HILDON_TIME_EDITOR(data);
1620 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1622 /* icon is passive in duration editor mode */
1623 if (priv->duration_mode)
1626 parent = gtk_widget_get_ancestor(GTK_WIDGET(editor), GTK_TYPE_WINDOW);
1627 picker = hildon_time_picker_new(GTK_WINDOW(parent));
1629 hildon_time_editor_get_time(editor, &h, &m, &s);
1630 hildon_time_picker_set_time(HILDON_TIME_PICKER(picker), h, m);
1632 result = gtk_dialog_run(GTK_DIALOG(picker));
1634 case GTK_RESPONSE_OK:
1635 case GTK_RESPONSE_ACCEPT:
1636 hildon_time_picker_get_time(HILDON_TIME_PICKER(picker), &h, &m);
1637 hildon_time_editor_set_time(editor, h, m, 0);
1643 gtk_widget_destroy(picker);
1647 static gboolean hildon_time_editor_entry_clicked(GtkWidget * widget,
1648 GdkEventButton * event,
1651 HildonTimeEditor *editor;
1652 HildonTimeEditorPrivate *priv;
1654 editor = HILDON_TIME_EDITOR (data);
1655 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1657 /* If the focus has been grabbed back before the "clicked"
1658 * signal gets processed, don't highlight the text
1660 if (gtk_widget_is_focus (widget))
1661 gtk_editable_select_region(GTK_EDITABLE(widget), 0, 2);
1666 static void hildon_time_editor_size_request(GtkWidget * widget,
1667 GtkRequisition * requisition)
1669 HildonTimeEditor *editor;
1670 HildonTimeEditorPrivate *priv;
1673 editor = HILDON_TIME_EDITOR(widget);
1674 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1676 gtk_widget_size_request(priv->frame, &req);
1679 requisition->width = TIME_EDITOR_LBORDER + TIME_EDITOR_RBORDER;
1681 gtk_widget_size_request(priv->h_entry, &req);
1682 requisition->width += req.width;
1684 gtk_widget_size_request(priv->m_entry, &req);
1685 requisition->width += req.width;
1687 gtk_widget_size_request(priv->label, &req);
1688 requisition->width += req.width;
1690 if (priv->iconbutton && GTK_WIDGET_VISIBLE(priv->iconbutton))
1692 gtk_widget_size_request(priv->iconbutton, &req);
1693 requisition->width += ICON_WIDTH + ICON_PRESSED +
1694 TIME_EDITOR_CLOCK_BORDER;
1698 gtk_widget_size_request(priv->s_entry, &req);
1699 requisition->width += req.width;
1701 gtk_widget_size_request(priv->label2, &req);
1702 requisition->width += req.width;
1705 if (!priv->clock_24h && !priv->duration_mode) {
1706 gtk_widget_size_request(priv->eventbox, &req);
1707 requisition->width += req.width + 4;
1710 requisition->height = TIME_EDITOR_HEIGHT + widget->style->ythickness * 2;
1713 static void set_widget_allocation(GtkWidget * widget,
1714 GtkAllocation * alloc,
1715 GtkAllocation * allocation)
1717 GtkRequisition child_requisition;
1719 gtk_widget_get_child_requisition(widget, &child_requisition);
1721 if (allocation->width + allocation->x >
1722 alloc->x + child_requisition.width)
1723 alloc->width = child_requisition.width;
1725 alloc->width = allocation->width - (alloc->x - allocation->x);
1726 if (alloc->width < 0)
1729 gtk_widget_size_allocate(widget, alloc);
1730 alloc->x += alloc->width;
1733 static void hildon_time_editor_size_allocate(GtkWidget * widget,
1734 GtkAllocation * allocation)
1736 HildonTimeEditor *editor;
1737 HildonTimeEditorPrivate *priv;
1738 GtkAllocation alloc;
1739 GtkAllocation child_alloc;
1740 GtkRequisition child_requisition;
1743 editor = HILDON_TIME_EDITOR(widget);
1744 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1746 widget->allocation = *allocation;
1748 /*Init start values*/
1749 alloc.y = widget->allocation.y + widget->style->ythickness;
1751 if (widget->allocation.height > (TIME_EDITOR_HEIGHT +
1752 widget->style->ythickness * 2)) {
1753 alloc.height = TIME_EDITOR_HEIGHT;
1755 (widget->allocation.height - TIME_EDITOR_HEIGHT) / 2;
1758 widget->allocation.height - widget->style->ythickness * 2;
1760 if (alloc.height < 0)
1763 gtk_widget_get_child_requisition(widget, &child_requisition);
1764 if (allocation->width > child_requisition.width) {
1765 mod_w = (allocation->width - child_requisition.width) / 2;
1766 alloc.x = allocation->x + mod_w;
1768 alloc.x = allocation->x;
1772 if (priv->frame && GTK_WIDGET_VISIBLE(priv->frame))
1774 alloc.width = child_requisition.width -
1775 TIME_EDITOR_CLOCK_BORDER - ICON_WIDTH - ICON_PRESSED;
1776 gtk_widget_size_allocate(priv->frame, &alloc);
1780 if (priv->iconbutton && GTK_WIDGET_VISIBLE(priv->iconbutton)) {
1781 gtk_widget_get_child_requisition(priv->iconbutton,
1782 &child_requisition);
1784 child_alloc.x = alloc.x + alloc.width + TIME_EDITOR_CLOCK_BORDER;
1786 if(alloc.height > ICON_HEIGHT)
1787 child_alloc.y = alloc.y + (alloc.height - ICON_HEIGHT) / 2 -1;
1789 child_alloc.y = alloc.y;
1790 child_alloc.height = ICON_HEIGHT + ICON_PRESSED / 2;
1791 child_alloc.width = ICON_WIDTH + ICON_PRESSED;
1792 gtk_widget_size_allocate(priv->iconbutton, &child_alloc);
1795 /* allocation of child widgets */
1796 child_alloc.x = alloc.x + TIME_EDITOR_LBORDER;
1797 child_alloc.y = alloc.y;
1798 child_alloc.height = TIME_EDITOR_HEIGHT;
1799 child_alloc.width = -1;
1801 /* am/pm label (when first) */
1802 if (!priv->duration_mode) {
1803 if (!priv->clock_24h && !priv->ampm_pos_after)
1805 set_widget_allocation(priv->eventbox, &child_alloc,
1806 &widget->allocation);
1811 if (priv->h_entry && GTK_WIDGET_VISIBLE(priv->h_entry))
1813 child_alloc.y += ENTRY_BORDER;
1814 child_alloc.height -= ENTRY_BORDER * 2;
1815 set_widget_allocation(priv->h_entry, &child_alloc,
1816 &widget->allocation);
1817 child_alloc.y -= ENTRY_BORDER;
1818 child_alloc.height += ENTRY_BORDER * 2;
1821 /* first separator label */
1822 if (priv->label && GTK_WIDGET_VISIBLE(priv->label))
1824 /* We'll have to subtract the ythickness from the labels
1825 * allocation or it'll be there twice
1827 child_alloc.y -= widget->style->ythickness;
1828 set_widget_allocation(priv->label, &child_alloc,
1829 &widget->allocation);
1830 child_alloc.y += widget->style->ythickness;
1833 if (priv->m_entry && GTK_WIDGET_VISIBLE(priv->m_entry))
1835 /* Entries have a little different allocation requirements
1836 * so we'll have to accommodate. This is done per entry
1837 * so that the "running" width value of the allocation isn't lost
1838 * FIXME: Rearrange this code so it could be done just once
1840 child_alloc.y += ENTRY_BORDER;
1841 child_alloc.height -= ENTRY_BORDER * 2;
1842 set_widget_allocation(priv->m_entry, &child_alloc,
1843 &widget->allocation);
1844 child_alloc.y -= ENTRY_BORDER;
1845 child_alloc.height += ENTRY_BORDER * 2;
1849 /* second separator label */
1852 child_alloc.y -= widget->style->ythickness;
1853 set_widget_allocation(priv->label2, &child_alloc,
1854 &widget->allocation);
1855 child_alloc.y += widget->style->ythickness;
1861 child_alloc.y += ENTRY_BORDER;
1862 child_alloc.height -= ENTRY_BORDER * 2;
1863 set_widget_allocation(priv->s_entry, &child_alloc,
1864 &widget->allocation);
1865 child_alloc.y -= ENTRY_BORDER;
1866 child_alloc.height += ENTRY_BORDER * 2;
1870 /* am/pm label (when last) */
1871 if (!priv->duration_mode) {
1872 if (!priv->clock_24h && priv->ampm_pos_after)
1874 child_alloc.y -= widget->style->ythickness;
1875 set_widget_allocation(priv->eventbox, &child_alloc,
1876 &widget->allocation);
1877 child_alloc.y += widget->style->ythickness;
1882 static gboolean hildon_time_editor_entry_keypress(GtkWidget * widget,
1883 GdkEventKey * event,
1886 HildonTimeEditor *editor;
1887 HildonTimeEditorPrivate *priv;
1890 g_return_val_if_fail(widget, FALSE);
1891 g_return_val_if_fail(event, FALSE);
1892 g_return_val_if_fail(data, FALSE);
1894 editor = HILDON_TIME_EDITOR(data);
1895 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1897 pos = gtk_editable_get_position(GTK_EDITABLE(widget));
1899 if (event->keyval == GDK_Return) {
1900 /* Check that we have correct values in entries */
1901 hildon_time_editor_validate (editor);
1902 _gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), TRUE);
1903 hildon_time_editor_icon_clicked(widget, data);
1904 _gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), FALSE);
1908 if (event->keyval == GDK_KP_Enter)
1911 /* We don't want wrap */
1912 if (event->keyval == GDK_KP_Left || event->keyval == GDK_Left) {
1913 if (pos == 0 && widget == priv->h_entry) {
1918 if (event->keyval == GDK_KP_Right || event->keyval == GDK_Right) {
1919 if (pos >= strlen(GTK_ENTRY(widget)->text)) {
1920 if ((widget == priv->m_entry
1921 && !GTK_WIDGET_REALIZED(priv->s_entry))
1922 || (widget == priv->s_entry
1923 && GTK_WIDGET_REALIZED(priv->s_entry))) {
1929 /* numeric key pressed */
1930 if (event->keyval >= GDK_0 && event->keyval <= GDK_9) {
1931 GtkWidgetClass *c = GTK_WIDGET_GET_CLASS(widget);
1933 c->key_press_event(widget, event);
1935 if (GTK_IS_ENTRY (widget))
1937 if (strlen (gtk_entry_get_text (GTK_ENTRY (widget))) == 2)
1939 hildon_time_editor_validate (editor);
1945 /* tab pressed in hour entry */
1946 else if (widget == priv->h_entry && (event->keyval == GDK_Tab ||
1947 event->keyval == GDK_KP_Tab)) {
1948 gtk_widget_grab_focus(priv->m_entry);
1951 /* tab pressed in minute entry */
1952 else if (widget == priv->m_entry && (event->keyval == GDK_Tab ||
1953 event->keyval == GDK_KP_Tab)) {
1955 gtk_widget_grab_focus(priv->s_entry);
1957 gtk_widget_grab_focus(priv->h_entry);
1960 /* tab pressed in second entry */
1961 else if (widget == priv->s_entry && (event->keyval == GDK_Tab ||
1962 event->keyval == GDK_KP_Tab)) {
1963 gtk_widget_grab_focus(priv->h_entry);
1966 /* left tab pressed in second entry */
1967 else if (widget == priv->s_entry &&
1968 event->keyval == GDK_ISO_Left_Tab) {
1969 gtk_widget_grab_focus(priv->m_entry);
1972 /* left tab pressed in minute entry */
1973 else if (widget == priv->m_entry &&
1974 event->keyval == GDK_ISO_Left_Tab) {
1975 gtk_widget_grab_focus(priv->h_entry);
1978 /* left tab pressed in hour entry */
1979 else if (widget == priv->h_entry &&
1980 event->keyval == GDK_ISO_Left_Tab) {
1982 gtk_widget_grab_focus(priv->s_entry);
1984 gtk_widget_grab_focus(priv->m_entry);
1987 /* right arrow pressed in hour entry */
1988 else if (widget == priv->h_entry &&
1989 (event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
1990 && pos >= GTK_ENTRY(priv->h_entry)->text_length) {
1991 gtk_widget_grab_focus(priv->m_entry);
1992 gtk_editable_set_position(GTK_EDITABLE(priv->m_entry), 0);
1995 /* right arrow pressed in minute entry */
1996 else if (widget == priv->m_entry &&
1997 (event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
1998 && pos >= GTK_ENTRY(priv->m_entry)->text_length) {
2000 gtk_widget_grab_focus(priv->s_entry);
2001 gtk_editable_set_position(GTK_EDITABLE(priv->s_entry), 0);
2003 gtk_widget_grab_focus(priv->h_entry);
2004 gtk_editable_set_position(GTK_EDITABLE(priv->h_entry), 0);
2008 /* right arrow pressed in second entry */
2009 else if (widget == priv->s_entry &&
2010 (event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
2011 && pos >= GTK_ENTRY(priv->s_entry)->text_length) {
2012 gtk_widget_grab_focus(priv->h_entry);
2013 gtk_editable_set_position(GTK_EDITABLE(priv->h_entry), 0);
2016 /* left arrow key pressed in hour entry */
2017 else if (widget == priv->h_entry &&
2018 (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) &&
2021 gtk_widget_grab_focus(priv->s_entry);
2022 gtk_editable_set_position(GTK_EDITABLE(priv->s_entry), -1);
2024 gtk_widget_grab_focus(priv->m_entry);
2025 gtk_editable_set_position(GTK_EDITABLE(priv->m_entry), -1);
2029 /* left arrow key pressed in minute entry */
2030 else if (widget == priv->m_entry &&
2031 (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) &&
2033 gtk_widget_grab_focus(priv->h_entry);
2034 gtk_editable_set_position(GTK_EDITABLE(priv->h_entry), -1);
2037 /* left arrow key pressed in seconds entry */
2038 else if (widget == priv->s_entry &&
2039 (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) &&
2041 gtk_widget_grab_focus(priv->m_entry);
2042 gtk_editable_set_position(GTK_EDITABLE(priv->m_entry), -1);
2045 /* pass other arrow key presses and backspace and del onwards */
2046 else if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left ||
2047 event->keyval == GDK_Right || event->keyval == GDK_KP_Right ||
2048 event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
2049 event->keyval == GDK_Down || event->keyval == GDK_KP_Down ||
2050 event->keyval == GDK_BackSpace || event->keyval == GDK_Delete
2051 || event->keyval == GDK_KP_Delete)
2052 return FALSE; /* pass the keypress on */
2054 /* ingore other keys */
2058 static HildonValidation
2059 hildon_time_editor_validate_duration (HildonTimeEditor * editor, guint ticks)
2061 HildonTimeEditorPrivate *priv;
2063 g_return_val_if_fail (editor, VALIDATION_ERROR);
2065 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
2067 if (ticks > priv->duration_max)
2068 return VALIDATION_DURATION_MAX;
2070 if (ticks < priv->duration_min)
2071 return VALIDATION_DURATION_MIN;
2073 return (VALIDATION_OK);
2077 static HildonValidation
2078 hildon_time_editor_validate_time (HildonTimeEditor * editor,
2084 HildonTimeEditorPrivate *priv;
2086 g_return_val_if_fail (editor, VALIDATION_ERROR);
2088 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
2090 priv->validated = FALSE;
2093 if (hours < HOURS_MIN_24 || hours > HOURS_MAX_24)
2094 return VALIDATION_TIME_HOURS;
2096 if (hours < HOURS_MIN_12 || hours > HOURS_MAX_12)
2097 return VALIDATION_TIME_HOURS;
2100 if (minutes < MINUTES_MIN || minutes > MINUTES_MAX)
2101 return VALIDATION_TIME_MINUTES;
2103 if (seconds < SECONDS_MIN || seconds > SECONDS_MAX)
2104 return VALIDATION_TIME_SECONDS;
2106 priv->validated = TRUE;
2107 return (VALIDATION_OK);
2111 hildon_time_editor_entry_changed(GtkWidget * widget, gpointer user_data)
2113 HildonTimeEditor *editor;
2115 editor = HILDON_TIME_EDITOR(user_data);
2117 /* hildon_time_editor_validate (editor);*/
2120 /* NOTE: This function is mostly broken for the duration mode */
2122 hildon_time_editor_get_max_values(HildonTimeEditor *editor,
2123 guint * pmax_hours, guint * pmin_hours,
2124 guint * pmax_minutes, guint * pmin_minutes,
2125 guint * pmax_seconds, guint * pmin_seconds)
2134 HildonTimeEditorPrivate *priv;
2136 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
2138 max_hours = priv->duration_max / 3600;
2139 max_minutes = (priv->duration_max - (max_hours * 3600)) / 60;
2140 max_seconds = priv->duration_max - (max_hours * 3600) - (max_minutes * 60);
2141 min_hours = priv->duration_min / 3600;
2142 min_minutes = (priv->duration_min - (min_hours * 3600)) / 60;
2143 min_seconds = priv->duration_min - (min_hours * 3600) - (min_minutes * 60);
2145 /* Determine max and min values for duration mode */
2146 if (priv->duration_mode)
2148 /* if the widget has focus, the value could be out of range, so
2149 use the calculated values then
2151 if (!gtk_widget_is_focus (priv->h_entry))
2153 if ((guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->h_entry))) < max_hours)
2158 if ((guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->h_entry))) > min_hours)
2164 if (!gtk_widget_is_focus (priv->m_entry))
2166 if ((guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry))) < max_minutes)
2170 if ((guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry))) > min_minutes)
2176 /* 24h clock mode */
2177 else if (priv->clock_24h) {
2179 max_seconds = max_minutes = 59;
2180 min_seconds = min_minutes = min_hours = 0;
2182 /* 12h clock mode */
2186 max_seconds = max_minutes = 59;
2187 min_seconds = min_minutes = 0;
2190 *pmax_hours = max_hours;
2191 *pmax_minutes = max_minutes;
2192 *pmax_seconds = max_seconds;
2193 *pmin_hours = min_hours;
2194 *pmin_minutes = min_minutes;
2195 *pmin_seconds = min_seconds;
2204 convert_to_12h (guint *h, guint *m, guint *s, gboolean *am)
2206 /* Official time hack: As 12am and 12pm are technically invalid
2207 times, we add a minute to 24h time 00:00 and subtract one from
2208 24h time 12:00 when in 12h mode. This is a custom in railroads
2209 airlines and insurance companies.
2211 if (*h == 0 && *m == 0 && *s == 0)
2215 else if (*h == 12 && *m == 0 && *s == 0)
2232 else if (*h >= 1 && *h < 12)
2239 else if (*h >= 12 && *h < 13)
2246 else if (*h >= 13 && *h < 24 )
2254 convert_to_24h (guint *h, guint *m, guint *s, gboolean am)
2256 /* Official time hack: As 12am and 12pm are technically invalid
2257 times, we add a minute to 24h time 00:00 and subtract one from
2258 24h time 12:00 when in 12h mode. This is a custom in railroads
2259 airlines and insurance companies.
2261 if (am && *h == 12 && *m == 0 && *s == 0)
2265 else if (!am && *h == 12 && *m == 0 && *s == 0)
2271 /* 12 midnight - 12:59 AM
2278 /* 1:00 PM - 11:59 AM
2281 else if (!am && *h >= 1 && *h < 12)
2288 * Deprecated functions
2292 #ifndef HILDON_DISABLE_DEPRECATED
2295 * hildon_time_editor_show_seconds:
2296 * @editor: The #HildonTimeEditor.
2297 * @enable: Enable or disable showing of seconds.
2299 * This function is deprecated, use @hildon_time_editor_set_show_seconds instead.
2302 void hildon_time_editor_show_seconds(HildonTimeEditor * editor,
2305 hildon_time_editor_set_show_seconds (editor, enable);
2308 * hildon_time_editor_enable_duration_mode:
2309 * @editor: The #HildonTimeEditor.
2310 * @enable: Enable or disable duration editor mode
2312 * This function is deprecated, use @hildon_time_editor_set_duration_mode instead.
2315 void hildon_time_editor_enable_duration_mode(HildonTimeEditor * editor,
2318 hildon_time_editor_set_duration_mode (editor, enable);
2321 #endif /* HILDON_DISABLE_DEPRECATED */