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 * SECTION:hildon-time-editor
27 * @short_description: A widget used to enter time or duration in hours, minutes,
28 * and optional seconds
29 * @see_also: #HildonTimePicker
31 * HildonTimeEditor is used to edit time or duration. Time mode is
32 * restricted to normal 24 hour cycle, but Duration mode can select any
33 * amount of time up to 99 hours. It consists of entries for hours,
34 * minutes and seconds, and pm/am indicator as well as a button which
35 * popups a #HildonTimePicker dialog.
42 #include <gtk/gtkhbox.h>
43 #include <gtk/gtkeventbox.h>
44 #include <gtk/gtkentry.h>
45 #include <gtk/gtkbutton.h>
46 #include <gtk/gtklabel.h>
47 #include <gtk/gtkframe.h>
48 #include <gdk/gdkkeysyms.h>
56 #include <hildon-widgets/hildon-defines.h>
57 #include <hildon-widgets/hildon-time-editor.h>
58 #include <hildon-widgets/hildon-time-picker.h>
59 #include <hildon-widgets/hildon-banner.h>
60 #include <hildon-widgets/hildon-input-mode-hint.h>
61 #include "hildon-composite-widget.h"
63 #define _(String) dgettext(PACKAGE, String)
65 #define HILDON_TIME_EDITOR_GET_PRIVATE(obj) \
66 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
67 HILDON_TYPE_TIME_EDITOR, HildonTimeEditorPrivate));
69 #define TICKS(h,m,s) ((h) * 3600 + (m) * 60 + (s))
71 #define TIME_EDITOR_HEIGHT 30
72 #define ICON_PRESSED 4
73 #define ICON_NAME "qgn_widg_timedit"
74 #define ICON_SIZE "timepicker-size"
75 #define MIN_DURATION 0
76 #define MAX_DURATION TICKS(99, 59, 59)
78 /* Default values for properties */
79 #define HILDON_TIME_EDITOR_TICKS_VALUE 0
80 #define HILDON_TIME_EDITOR_DURATION_MODE FALSE
81 #define HILDON_TIME_EDITOR_DURATION_LOWER_VALUE 0
82 #define HILDON_TIME_EDITOR_DURATION_UPPER_VALUE TICKS(99, 59, 59)
84 #define HOURS_MAX_24 23
85 #define HOURS_MAX_12 12
86 #define HOURS_MIN_24 0
87 #define HOURS_MIN_12 1
88 #define MINUTES_MAX 59
89 #define SECONDS_MAX 59
93 static GtkContainerClass *parent_class;
95 typedef struct _HildonTimeEditorPrivate HildonTimeEditorPrivate;
115 struct _HildonTimeEditorPrivate {
116 guint ticks; /* Current duration in seconds */
121 gchar *hm_sep_symbol; /* hours/minutes separator */
122 gchar *ms_sep_symbol; /* minutes/seconds separator */
124 GtkWidget *eventbox; /* hold entries */
125 GtkWidget *iconbutton; /* button for icon */
127 GtkWidget *frame; /* frame around the entries */
128 GtkWidget *entries[ENTRY_COUNT]; /* h, m, s entries */
129 GtkWidget *hm_label; /* between hour and minute */
130 GtkWidget *sec_label; /* between minute and second */
131 GtkWidget *ampm_label; /* label for showing am or pm */
133 GtkWidget *error_widget; /* field to highlight in idle */
136 gboolean duration_mode; /* In HildonDurationEditor mode */
137 gboolean show_seconds; /* show seconds */
138 gboolean show_hours; /* show hours */
140 gboolean ampm_pos_after; /* is am/pm shown after others */
141 gboolean clock_24h; /* whether to show a 24h clock */
142 gboolean am; /* TRUE == am, FALSE == pm */
144 guint duration_min; /* duration editor ranges */
145 guint duration_max; /* duration editor ranges */
147 guint highlight_idle;
154 static void hildon_time_editor_class_init (HildonTimeEditorClass *editor_class);
155 static void hildon_time_editor_init (HildonTimeEditor *editor);
157 static void hildon_time_editor_finalize (GObject *obj_self);
159 static void hildon_time_editor_set_property(GObject *object,
164 static void hildon_time_editor_get_property(GObject *object,
169 static void hildon_time_editor_forall(GtkContainer *container,
170 gboolean include_internals,
171 GtkCallback callback,
172 gpointer callback_data);
174 static void hildon_time_editor_destroy(GtkObject * self);
180 static gboolean hildon_time_editor_entry_focusout(GtkWidget *widget,
181 GdkEventFocus *event,
184 static gboolean hildon_time_editor_entry_focusin(GtkWidget *widget,
185 GdkEventFocus *event,
188 static gboolean hildon_time_editor_ampm_clicked(GtkWidget *widget,
189 GdkEventButton *event,
192 static gboolean hildon_time_editor_icon_clicked(GtkWidget *widget,
195 static gboolean hildon_time_editor_entry_clicked(GtkWidget *widget,
196 GdkEventButton *event,
199 static void hildon_time_editor_size_request(GtkWidget *widget,
200 GtkRequisition *requisition);
202 static void hildon_time_editor_size_allocate(GtkWidget *widget,
203 GtkAllocation *allocation);
205 static gboolean hildon_time_editor_entry_keypress(GtkWidget *widget,
213 static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor);
216 void hildon_time_editor_tap_and_hold_setup(GtkWidget * widget,
219 GtkWidgetTapAndHoldFlags flags);
221 hildon_time_editor_validate (HildonTimeEditor *editor, gboolean allow_intermediate);
223 static void hildon_time_editor_set_to_current_time (HildonTimeEditor * editor);
229 static void convert_to_12h (guint *h, guint *m, guint *s, gboolean *am);
230 static void convert_to_24h (guint *h, guint *m, guint *s, gboolean am);
232 static void ticks_to_time (guint ticks,
238 GType hildon_time_editor_get_type(void)
240 static GType editor_type = 0;
243 static const GTypeInfo editor_info = {
244 sizeof(HildonTimeEditorClass),
245 NULL, /* base_init */
246 NULL, /* base_finalize */
247 (GClassInitFunc) hildon_time_editor_class_init,
248 NULL, /* class_finalize */
249 NULL, /* class_data */
250 sizeof(HildonTimeEditor),
252 (GInstanceInitFunc) hildon_time_editor_init,
254 editor_type = g_type_register_static(GTK_TYPE_CONTAINER,
261 static void hildon_time_editor_forall(GtkContainer * container,
262 gboolean include_internals,
263 GtkCallback callback,
264 gpointer callback_data)
266 HildonTimeEditor *editor;
267 HildonTimeEditorPrivate *priv;
269 g_assert(HILDON_IS_TIME_EDITOR(container));
270 g_assert(callback != NULL);
272 editor = HILDON_TIME_EDITOR(container);
273 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
275 if (!include_internals)
278 /* widget that are always shown */
279 (*callback) (priv->iconbutton, callback_data);
280 (*callback) (priv->frame, callback_data);
283 static void hildon_time_editor_destroy(GtkObject * self)
285 HildonTimeEditorPrivate *priv;
287 priv = HILDON_TIME_EDITOR_GET_PRIVATE(self);
289 if (priv->iconbutton) {
290 gtk_widget_unparent(priv->iconbutton);
291 priv->iconbutton = NULL;
294 gtk_widget_unparent(priv->frame);
298 if (GTK_OBJECT_CLASS(parent_class)->destroy)
299 GTK_OBJECT_CLASS(parent_class)->destroy(self);
304 hildon_time_editor_class_init(HildonTimeEditorClass * editor_class)
306 GObjectClass *object_class = G_OBJECT_CLASS(editor_class);
307 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class);
308 GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class);
310 parent_class = g_type_class_peek_parent(editor_class);
312 g_type_class_add_private(editor_class,
313 sizeof(HildonTimeEditorPrivate));
315 object_class->get_property = hildon_time_editor_get_property;
316 object_class->set_property = hildon_time_editor_set_property;
317 widget_class->size_request = hildon_time_editor_size_request;
318 widget_class->size_allocate = hildon_time_editor_size_allocate;
319 widget_class->tap_and_hold_setup =
320 hildon_time_editor_tap_and_hold_setup;
321 widget_class->focus = hildon_composite_widget_focus;
323 container_class->forall = hildon_time_editor_forall;
324 GTK_OBJECT_CLASS(editor_class)->destroy = hildon_time_editor_destroy;
326 object_class->finalize = hildon_time_editor_finalize;
329 * HildonTimeEditor:ticks:
331 * If editor is in duration mode, contains the duration seconds.
332 * If not, contains seconds since midnight.
334 g_object_class_install_property( object_class, PROP_TICKS,
335 g_param_spec_uint("ticks",
337 "Current value of duration",
339 HILDON_TIME_EDITOR_TICKS_VALUE,
340 G_PARAM_READABLE | G_PARAM_WRITABLE) );
343 * HildonTimeEditor:show_seconds:
345 * Controls whether seconds are shown in the editor
347 g_object_class_install_property( object_class, PROP_SHOW_SECONDS,
348 g_param_spec_boolean("show_seconds",
349 "Show seconds property",
350 "Controls whether the seconds are shown in the editor",
352 G_PARAM_READABLE | G_PARAM_WRITABLE) );
355 * HildonTimeEditor:show_hours:
357 * Controls whether hours are shown in the editor
359 g_object_class_install_property( object_class, PROP_SHOW_HOURS,
360 g_param_spec_boolean("show_hours",
362 "Controls whether the hours field is shown in the editor",
364 G_PARAM_READABLE | G_PARAM_WRITABLE) );
367 * HildonTimeEditor:duration_mode:
369 * Controls whether the TimeEditor is in duration mode
371 g_object_class_install_property( object_class, PROP_DURATION_MODE,
372 g_param_spec_boolean("duration_mode",
374 "Controls whether the TimeEditor is in duration mode",
375 HILDON_TIME_EDITOR_DURATION_MODE,
376 G_PARAM_READABLE | G_PARAM_WRITABLE) );
379 * HildonTimeEditor:duration_min:
381 * Minimum allowed duration value.
383 g_object_class_install_property( object_class, PROP_DURATION_MIN,
384 g_param_spec_uint("duration_min",
385 "Minumum duration value",
386 "Smallest possible duration value",
387 MIN_DURATION, MAX_DURATION,
388 HILDON_TIME_EDITOR_DURATION_LOWER_VALUE,
389 G_PARAM_READABLE | G_PARAM_WRITABLE) );
392 * HildonTimeEditor:duration_max:
394 * Maximum allowed duration value.
396 g_object_class_install_property( object_class, PROP_DURATION_MAX,
397 g_param_spec_uint("duration_max",
398 "Maximum duration value",
399 "Largest possible duration value",
401 HILDON_TIME_EDITOR_DURATION_UPPER_VALUE,
402 G_PARAM_READABLE | G_PARAM_WRITABLE) );
406 void hildon_time_editor_tap_and_hold_setup(GtkWidget * widget,
409 GtkWidgetTapAndHoldFlags flags)
411 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget);
414 /* Forward this tap_and_hold_setup signal to all our child widgets */
415 for (i = 0; i < ENTRY_COUNT; i++)
417 gtk_widget_tap_and_hold_setup(priv->entries[i], menu, func,
418 GTK_TAP_AND_HOLD_NO_SIGNALS);
420 gtk_widget_tap_and_hold_setup(priv->eventbox, menu, func,
421 GTK_TAP_AND_HOLD_NO_SIGNALS);
422 gtk_widget_tap_and_hold_setup(priv->iconbutton, menu, func,
423 GTK_TAP_AND_HOLD_NONE);
426 static void hildon_time_editor_entry_changed(GtkWidget *widget, gpointer data)
428 g_assert(HILDON_IS_TIME_EDITOR(data));
429 hildon_time_editor_validate(HILDON_TIME_EDITOR(data), TRUE);
432 static void hildon_time_editor_init(HildonTimeEditor * editor)
434 HildonTimeEditorPrivate *priv;
435 GtkWidget *hbox, *icon;
438 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
440 gtk_widget_push_composite_child();
442 /* Setup defaults and create widgets */
444 priv->show_seconds = FALSE;
445 priv->show_hours = TRUE;
446 priv->ampm_pos_after = TRUE;
447 priv->clock_24h = TRUE;
448 priv->duration_mode = FALSE;
449 priv->iconbutton = gtk_button_new();
450 priv->ampm_label = gtk_label_new(NULL);
451 priv->hm_label = gtk_label_new(NULL);
452 priv->sec_label = gtk_label_new(NULL);
453 priv->frame = gtk_frame_new(NULL);
454 priv->eventbox = gtk_event_box_new();
456 icon = gtk_image_new_from_icon_name(ICON_NAME, HILDON_ICON_SIZE_WIDG);
457 hbox = gtk_hbox_new(FALSE, 0);
459 GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW);
460 GTK_WIDGET_UNSET_FLAGS(priv->iconbutton, GTK_CAN_FOCUS | GTK_CAN_DEFAULT);
462 gtk_event_box_set_visible_window(GTK_EVENT_BOX(priv->eventbox), FALSE);
464 gtk_container_set_border_width(GTK_CONTAINER(priv->frame), 0);
466 gtk_container_add(GTK_CONTAINER(priv->iconbutton), icon);
467 gtk_container_add(GTK_CONTAINER(priv->eventbox), priv->ampm_label);
469 /* Create hour, minute and second entries */
470 for (i = 0; i < ENTRY_COUNT; i++)
472 priv->entries[i] = gtk_entry_new();
474 /* No frames for entries, so that they all appear to be inside one long entry */
475 gtk_entry_set_has_frame(GTK_ENTRY(priv->entries[i]), FALSE);
477 /* Set the entries to accept only numeric characters */
478 g_object_set (priv->entries[i], "input-mode",
479 HILDON_INPUT_MODE_HINT_NUMERIC, NULL);
481 /* The entry fields all take exactly two characters */
482 gtk_entry_set_max_length (GTK_ENTRY(priv->entries[i]), 2);
483 gtk_entry_set_width_chars (GTK_ENTRY(priv->entries[i]), 2);
485 /* Connect signals */
486 g_signal_connect(priv->entries[i], "button-release-event",
487 G_CALLBACK(hildon_time_editor_entry_clicked), editor);
488 g_signal_connect(priv->entries[i], "focus-in-event",
489 G_CALLBACK(hildon_time_editor_entry_focusin), editor);
490 g_signal_connect(priv->entries[i], "focus-out-event",
491 G_CALLBACK(hildon_time_editor_entry_focusout), editor);
492 g_signal_connect(priv->entries[i], "key-press-event",
493 G_CALLBACK(hildon_time_editor_entry_keypress), editor);
494 g_signal_connect(priv->entries[i], "changed",
495 G_CALLBACK(hildon_time_editor_entry_changed), editor);
498 /* clicked signal for am/pm label */
499 g_signal_connect(G_OBJECT(priv->eventbox), "button_press_event",
500 G_CALLBACK(hildon_time_editor_ampm_clicked), editor);
502 /* clicked signal for icon */
503 g_signal_connect(G_OBJECT(priv->iconbutton), "clicked",
504 G_CALLBACK(hildon_time_editor_icon_clicked), editor);
506 /* Set ourself as the parent of all the widgets we created */
507 gtk_widget_set_parent(priv->iconbutton, GTK_WIDGET(editor));
508 gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_HOURS], FALSE, FALSE, 0);
509 gtk_box_pack_start(GTK_BOX(hbox), priv->hm_label, FALSE, FALSE, 0);
510 gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_MINS], FALSE, FALSE, 0);
511 gtk_box_pack_start(GTK_BOX(hbox), priv->sec_label, FALSE, FALSE, 0);
512 gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_SECS], FALSE, FALSE, 0);
513 gtk_box_pack_start(GTK_BOX(hbox), priv->eventbox, FALSE, FALSE, 0);
515 gtk_container_add(GTK_CONTAINER(priv->frame), hbox);
517 /* Show created widgets */
518 gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor));
519 gtk_widget_show_all(priv->frame);
520 gtk_widget_show_all(priv->iconbutton);
522 /* Update AM/PM and time separators settings from locale */
523 if (!hildon_time_editor_check_locale(editor)) {
524 /* Using 12h clock */
525 priv->clock_24h = FALSE;
527 gtk_widget_hide(priv->eventbox);
530 /* Set time separators labels */
531 gtk_label_set_label(GTK_LABEL(priv->hm_label), priv->hm_sep_symbol); /* priv-> set by ..._chech_locale()*/
532 gtk_label_set_label(GTK_LABEL(priv->sec_label), priv->ms_sep_symbol);
534 if (!priv->show_seconds) {
535 gtk_widget_hide(priv->sec_label);
536 gtk_widget_hide(priv->entries[ENTRY_SECS]);
539 /* set the default time to current time. */
540 hildon_time_editor_set_to_current_time (editor);
542 gtk_widget_pop_composite_child();
545 static void hildon_time_editor_set_property (GObject *object,
550 HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object);
554 hildon_time_editor_set_ticks (time_editor, g_value_get_uint(value));
557 case PROP_SHOW_SECONDS:
558 hildon_time_editor_set_show_seconds (time_editor, g_value_get_boolean(value));
561 case PROP_SHOW_HOURS:
562 hildon_time_editor_set_show_hours (time_editor, g_value_get_boolean(value));
565 case PROP_DURATION_MODE:
566 hildon_time_editor_set_duration_mode (time_editor, g_value_get_boolean(value));
569 case PROP_DURATION_MIN:
570 hildon_time_editor_set_duration_min (time_editor, g_value_get_uint(value));
573 case PROP_DURATION_MAX:
574 hildon_time_editor_set_duration_max (time_editor, g_value_get_uint(value));
578 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
583 static void hildon_time_editor_get_property (GObject *object,
588 HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object);
593 g_value_set_uint (value, hildon_time_editor_get_ticks (time_editor));
596 case PROP_SHOW_SECONDS:
597 g_value_set_boolean (value, hildon_time_editor_get_show_seconds (time_editor));
600 case PROP_SHOW_HOURS:
601 g_value_set_boolean (value, hildon_time_editor_get_show_hours (time_editor));
604 case PROP_DURATION_MODE:
605 g_value_set_boolean (value, hildon_time_editor_get_duration_mode (time_editor));
608 case PROP_DURATION_MIN:
609 g_value_set_uint (value, hildon_time_editor_get_duration_min (time_editor));
612 case PROP_DURATION_MAX:
613 g_value_set_uint (value, hildon_time_editor_get_duration_max (time_editor));
617 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
623 * hildon_time_editor_new:
625 * This function creates a new time editor.
627 * Returns: pointer to a new #HildonTimeEditor widget
630 GtkWidget *hildon_time_editor_new(void)
632 return GTK_WIDGET(g_object_new(HILDON_TYPE_TIME_EDITOR, NULL));
635 static void hildon_time_editor_finalize(GObject * obj_self)
637 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(obj_self);
639 g_free(priv->am_symbol);
640 g_free(priv->pm_symbol);
642 if (priv->hm_sep_symbol)
643 g_free(priv->hm_sep_symbol);
645 if (priv->ms_sep_symbol)
646 g_free(priv->ms_sep_symbol);
648 if (priv->highlight_idle)
649 g_source_remove(priv->highlight_idle);
651 if (G_OBJECT_CLASS(parent_class)->finalize)
652 G_OBJECT_CLASS(parent_class)->finalize(obj_self);
656 * Gets hour-minute separator and minute-second separator
657 * from current locale
659 static void get_time_separators(HildonTimeEditorPrivate *priv)
662 GDate locale_test_date;
665 /* Get localized time string */
666 g_date_set_dmy(&locale_test_date, 1, 2, 1970);
667 (void) g_date_strftime(buffer, sizeof(buffer), "%X", &locale_test_date);
669 /* Find h-m separator */
671 while (*iter && g_ascii_isdigit(*iter)) iter++;
673 /* Extract h-m separator*/
675 while (*endp && !g_ascii_isdigit(*endp)) endp++;
676 priv->hm_sep_symbol = g_strndup(iter, endp - iter);
678 /* Find m-s separator */
680 while (*iter && g_ascii_isdigit(*iter)) iter++;
682 /* Extract m-s separator*/
684 while (*endp && !g_ascii_isdigit(*endp)) endp++;
685 priv->ms_sep_symbol = g_strndup(iter, endp - iter);
688 /* Convert ticks to H:M:S. Ticks = seconds since 00:00:00. */
689 static void ticks_to_time (guint ticks,
696 *hours = ticks / 3600;
698 *minutes = left / 60;
699 *seconds = left % 60;
703 * hildon_time_editor_set_ticks:
704 * @editor: the #HildonTimeEditor widget
705 * @ticks: the duration to set, in seconds
707 * Sets the current duration in seconds. This means seconds from
708 * midnight, if not in duration mode. In case of any errors, it tries
712 void hildon_time_editor_set_ticks (HildonTimeEditor * editor,
715 HildonTimeEditorPrivate *priv;
719 g_assert(HILDON_IS_TIME_EDITOR(editor));
721 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
723 /* Validate ticks. If it's too low or too high, set it to
724 min/max value for the current mode. */
725 if (priv->duration_mode)
726 priv->ticks = CLAMP(ticks, priv->duration_min, priv->duration_max);
728 /* Check that ticks value is valid. We only need to check that hours
730 ticks_to_time (ticks, &h, &m, &s);
731 if (h > HOURS_MAX_24)
732 ticks = TICKS(HOURS_MAX_24, m, s);
737 /* Get the time in H:M:S. */
738 ticks_to_time (priv->ticks, &h, &m, &s);
740 if (!priv->clock_24h && !priv->duration_mode)
742 /* Convert 24h H:M:S values to 12h mode, and update AM/PM state */
743 convert_to_12h (&h, &m, &s, &priv->am);
746 /* Set H:M:S values to entries. We do not want to invoke validation
747 callbacks (since they can cause new call to this function), so we
748 block signals while setting values. */
749 for (i = 0; i < ENTRY_COUNT; i++)
751 g_signal_handlers_block_by_func(priv->entries[i],
752 (gpointer) hildon_time_editor_entry_changed, editor);
755 g_snprintf(str, sizeof(str), "%02u", h);
756 gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_HOURS]), str);
758 g_snprintf(str, sizeof(str), "%02u", m);
759 gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_MINS]), str);
761 g_snprintf(str, sizeof(str), "%02u", s);
762 gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_SECS]), str);
764 for (i = 0; i < ENTRY_COUNT; i++)
766 g_signal_handlers_unblock_by_func(priv->entries[i],
767 (gpointer) hildon_time_editor_entry_changed, editor);
770 /* Update AM/PM label in case we're in 12h mode */
771 gtk_label_set_label(GTK_LABEL(priv->ampm_label),
772 priv->am ? priv->am_symbol : priv->pm_symbol);
774 g_object_notify (G_OBJECT (editor), "ticks");
778 hildon_time_editor_set_to_current_time (HildonTimeEditor * editor)
784 tm = localtime(&now);
787 hildon_time_editor_set_time(editor, tm->tm_hour, tm->tm_min, tm->tm_sec);
791 * hildon_time_editor_get_ticks:
792 * @editor: the #HildonTimeEditor widget
794 * This function returns the current duration, in seconds.
795 * This means seconds from midnight, if not in duration mode.
797 * Returns: current duration in seconds
800 guint hildon_time_editor_get_ticks (HildonTimeEditor * editor)
802 HildonTimeEditorPrivate *priv;
804 g_return_val_if_fail(editor, 0);
805 g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0);
807 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
809 return (priv->ticks);
813 * hildon_time_editor_set_show_seconds:
814 * @editor: the #HildonTimeEditor
815 * @show_seconds: enable or disable showing of seconds
817 * This function shows or hides the seconds field.
820 void hildon_time_editor_set_show_seconds (HildonTimeEditor * editor,
821 gboolean show_seconds)
823 HildonTimeEditorPrivate *priv;
825 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
827 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
829 if (show_seconds != priv->show_seconds) {
830 priv->show_seconds = show_seconds;
832 /* show/hide seconds field and its ':' label if the value changed. */
834 gtk_widget_show(priv->entries[ENTRY_SECS]);
835 gtk_widget_show(priv->sec_label);
837 gtk_widget_hide(priv->entries[ENTRY_SECS]);
838 gtk_widget_hide(priv->sec_label);
841 g_object_notify (G_OBJECT (editor), "show_seconds");
846 * hildon_time_editor_get_show_seconds:
847 * @editor: the #HildonTimeEditor widget
849 * This function returns a boolean indicating the visibility of
850 * seconds in the #HildonTimeEditor
852 * Returns: TRUE if the seconds are visible
855 gboolean hildon_time_editor_get_show_seconds (HildonTimeEditor * editor)
857 HildonTimeEditorPrivate *priv;
859 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
860 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
862 return (priv->show_seconds);
866 * hildon_time_editor_set_duration_mode:
867 * @editor: the #HildonTimeEditor
868 * @duration_mode: enable or disable duration editor mode
870 * This function sets the duration editor mode in which the maximum hours
874 void hildon_time_editor_set_duration_mode (HildonTimeEditor * editor,
875 gboolean duration_mode)
877 HildonTimeEditorPrivate *priv;
879 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
881 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
883 if (duration_mode != priv->duration_mode) {
884 priv->duration_mode = duration_mode;
887 /* FIXME: Why do we reset the duration range here?
888 Would change API, so won't touch this for now. */
889 hildon_time_editor_set_duration_range(editor, MIN_DURATION,
891 /* There's no AM/PM label or time picker icon in duration mode.
892 Make sure they're hidden. */
893 gtk_widget_hide(GTK_WIDGET(priv->ampm_label));
894 gtk_widget_hide(GTK_WIDGET(priv->eventbox));
895 gtk_widget_hide(GTK_WIDGET(priv->iconbutton));
896 /* Duration mode has seconds by default. */
897 hildon_time_editor_set_show_seconds(editor, TRUE);
899 /* Make sure AM/PM label and time picker icons are visible if needed */
900 if (!priv->clock_24h)
901 gtk_widget_show(GTK_WIDGET(priv->ampm_label));
903 gtk_widget_show(GTK_WIDGET(priv->eventbox));
904 gtk_widget_show(GTK_WIDGET(priv->iconbutton));
906 /* Reset the ticks to current time. Anything set in duration mode
907 * is bound to be invalid or useless in time mode.
909 hildon_time_editor_set_to_current_time (editor);
912 g_object_notify (G_OBJECT (editor), "duration_mode");
917 * hildon_time_editor_get_duration_mode:
918 * @editor: the #HildonTimeEditor widget
920 * This function returns a boolean indicating whether the #HildonTimeEditor
921 * is in the duration mode.
923 * Returns: TRUE if the #HildonTimeEditor is in duration mode
926 gboolean hildon_time_editor_get_duration_mode (HildonTimeEditor * editor)
928 HildonTimeEditorPrivate *priv;
930 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
931 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
933 return (priv->duration_mode);
937 * hildon_time_editor_set_duration_min:
938 * @editor: the #HildonTimeEditor widget
939 * @duration_min: mimimum allowed duration
941 * Sets the minimum allowed duration for the duration mode.
942 * Note: Has no effect in time mode
945 void hildon_time_editor_set_duration_min (HildonTimeEditor * editor,
948 HildonTimeEditorPrivate *priv;
950 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
951 g_return_if_fail(duration_min >= MIN_DURATION);
953 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
955 if( !priv->duration_mode )
958 priv->duration_min = duration_min;
960 /* Clamp the current value to the minimum if necessary */
961 if (priv->ticks < duration_min)
963 hildon_time_editor_set_ticks (editor, duration_min);
966 g_object_notify (G_OBJECT (editor), "duration_min");
970 * hildon_time_editor_get_duration_min:
971 * @editor: the #HildonTimeEditor widget
973 * This function returns the smallest duration the #HildonTimeEditor
974 * allows in the duration mode.
976 * Returns: minimum allowed duration in seconds
979 guint hildon_time_editor_get_duration_min (HildonTimeEditor * editor)
981 HildonTimeEditorPrivate *priv;
983 g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0);
985 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
987 if( !priv->duration_mode )
990 return (priv->duration_min);
994 * hildon_time_editor_set_duration_max:
995 * @editor: the #HildonTimeEditor widget
996 * @duration_max: maximum allowed duration in seconds
998 * Sets the maximum allowed duration in seconds for the duration mode.
999 * Note: Has no effect in time mode
1002 void hildon_time_editor_set_duration_max (HildonTimeEditor * editor,
1005 HildonTimeEditorPrivate *priv;
1007 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1008 g_return_if_fail(duration_max <= MAX_DURATION);
1010 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1012 if( !priv->duration_mode )
1015 priv->duration_max = duration_max;
1017 /* Clamp the current value to the maximum if necessary */
1018 if (priv->ticks > duration_max)
1020 hildon_time_editor_set_ticks (editor, duration_max);
1023 g_object_notify (G_OBJECT (editor), "duration_max");
1027 * hildon_time_editor_get_duration_max:
1028 * @editor: the #HildonTimeEditor widget
1030 * This function returns the longest duration the #HildonTimeEditor
1031 * allows in the duration mode.
1033 * Returns: maximum allowed duration in seconds
1036 guint hildon_time_editor_get_duration_max (HildonTimeEditor * editor)
1038 HildonTimeEditorPrivate *priv;
1040 g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0);
1042 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1044 if( !priv->duration_mode )
1047 return (priv->duration_max);
1052 * hildon_time_editor_set_time:
1053 * @editor: the #HildonTimeEditor widget
1058 * This function sets the time on an existing time editor. If the
1059 * time specified by the arguments is invalid, it's fixed.
1060 * The time is assumed to be in 24h format.
1063 void hildon_time_editor_set_time(HildonTimeEditor * editor, guint hours,
1064 guint minutes, guint seconds)
1066 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1068 hildon_time_editor_set_ticks (editor, TICKS(hours, minutes, seconds));
1072 * hildon_time_editor_get_time:
1073 * @editor: the #HildonTimeEditor widget
1078 * Gets the time of the #HildonTimeEditor widget. The time returned is
1079 * always in 24h format.
1082 void hildon_time_editor_get_time(HildonTimeEditor * editor,
1084 guint * minutes, guint * seconds)
1086 HildonTimeEditorPrivate *priv;
1088 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1090 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1092 ticks_to_time (hildon_time_editor_get_ticks (editor),
1093 hours, minutes, seconds);
1097 * hildon_time_editor_set_duration_range:
1098 * @editor: the #HildonTimeEditor widget
1099 * @min_seconds: minimum allowed time in seconds
1100 * @max_seconds: maximum allowed time in seconds
1102 * Sets the duration editor time range of the #HildonTimeEditor widget.
1105 void hildon_time_editor_set_duration_range(HildonTimeEditor * editor,
1109 HildonTimeEditorPrivate *priv;
1112 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1114 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1115 /* Swap values if reversed */
1116 if (min_seconds > max_seconds)
1119 max_seconds = min_seconds;
1123 hildon_time_editor_set_duration_max (editor, max_seconds);
1124 hildon_time_editor_set_duration_min (editor, min_seconds);
1126 if (priv->duration_mode) {
1127 /* Set minimum allowed value for duration editor.
1128 FIXME: Shouldn't it be changed only if it's not in range?
1129 Would change API, so won't touch this for now. */
1130 hildon_time_editor_set_ticks(editor, min_seconds);
1135 * hildon_time_editor_get_duration_range:
1136 * @editor: the #HildonTimeEditor widget
1137 * @min_seconds: pointer to guint
1138 * @max_seconds: pointer to guint
1140 * Gets the duration editor time range of the #HildonTimeEditor widget.
1143 void hildon_time_editor_get_duration_range(HildonTimeEditor * editor,
1144 guint * min_seconds,
1145 guint * max_seconds)
1147 HildonTimeEditorPrivate *priv;
1149 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1151 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1153 *min_seconds = priv->duration_min;
1154 *max_seconds = priv->duration_max;
1157 static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor)
1159 HildonTimeEditorPrivate *priv;
1161 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1163 /* Update time separator symbols */
1164 get_time_separators(priv);
1166 /* Get AM/PM symbols. We want to show them in lowercase. */
1167 priv->am_symbol = g_ascii_strdown(nl_langinfo(AM_STR), -1);
1168 priv->pm_symbol = g_ascii_strdown(nl_langinfo(PM_STR), -1);
1170 if (priv->am_symbol[0] == '\0')
1173 /* 12h clock mode. Check if AM/PM should be before or after time.
1174 %p is the AM/PM string, so we assume that if the format string
1175 begins with %p it's in the beginning, and in any other case it's
1176 in the end (although that's not necessarily the case). */
1177 if (strncmp(nl_langinfo(T_FMT_AMPM), "%p", 2) == 0)
1178 priv->ampm_pos_after = FALSE;
1183 static gboolean hildon_time_editor_entry_focusin(GtkWidget * widget,
1184 GdkEventFocus * event,
1187 /* If we were trying to move away from a field with invalid value,
1188 we get moved back to it. Here we want to select the text in the field.
1189 The !button check checks that the entry wasn't focused with a mouse
1192 The selection happens temporarily if we got here with left/right
1193 keys, but it gets immediately unselected within same call due to some
1194 inner entry/clipboard magic. */
1195 if (!GTK_ENTRY(widget)->button)
1196 gtk_editable_select_region(GTK_EDITABLE(widget), 0, 2);
1201 /* Returns negative if we didn't get value,
1202 * and should stop further validation
1204 static gint validated_conversion(HildonTimeEditorPrivate *priv,
1208 gboolean allow_intermediate,
1209 GString *error_string)
1215 text = gtk_entry_get_text(GTK_ENTRY(field));
1217 if (text && text[0])
1219 /* Try to convert entry text to number */
1220 value = strtol(text, &tail, 10);
1222 /* Check if conversion succeeded */
1226 g_string_printf(error_string, _("ckct_ib_maximum_value"), max);
1227 priv->error_widget = field;
1230 if (value < min && !allow_intermediate) {
1231 g_string_printf(error_string, _("ckct_ib_minimum_value"), min);
1232 priv->error_widget = field;
1238 /* We'll handle failed conversions soon */
1240 else if (allow_intermediate)
1241 return -1; /* Empty field while user is still editing. No error, but
1242 cannot validate either... */
1244 /* Empty field and not allowed intermediated OR failed conversion */
1245 g_string_printf(error_string, _("ckct_ib_set_a_value_within_range"), min, max);
1246 priv->error_widget = field;
1251 hildon_time_editor_real_validate(HildonTimeEditor *editor,
1252 gboolean allow_intermediate, GString *error_string)
1254 HildonTimeEditorPrivate *priv;
1255 guint h, m, s, ticks;
1256 guint max_hours, min_hours, max_minutes, min_minutes, max_seconds, min_seconds;
1258 g_assert(HILDON_IS_TIME_EDITOR(editor));
1260 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1262 /* Find limits for field based validation. */
1263 if (priv->duration_mode)
1265 ticks_to_time(priv->duration_min, &min_hours, &min_minutes, &min_seconds);
1266 ticks_to_time(priv->duration_max, &max_hours, &max_minutes, &max_seconds);
1268 if (priv->clock_24h) {
1269 max_hours = HOURS_MAX_24;
1270 min_hours = HOURS_MIN_24;
1272 max_hours = HOURS_MAX_12;
1273 min_hours = HOURS_MIN_12;
1277 /* Get time components from fields and validate them... */
1278 if (priv->show_hours) {
1279 h = validated_conversion(priv, priv->entries[ENTRY_HOURS], min_hours, max_hours,
1280 allow_intermediate, error_string);
1281 if ((gint) h < 0) return;
1284 m = validated_conversion(priv, priv->entries[ENTRY_MINS], MINUTES_MIN, MINUTES_MAX,
1285 allow_intermediate, error_string);
1286 if ((gint) m < 0) return;
1287 if (priv->show_seconds) {
1288 s = validated_conversion(priv, priv->entries[ENTRY_SECS], SECONDS_MIN, SECONDS_MAX,
1289 allow_intermediate, error_string);
1290 if ((gint) s < 0) return;
1294 /* Ok, we now do separate check that tick count is valid for duration mode */
1295 if (priv->duration_mode)
1297 ticks = TICKS(h, m, s);
1299 if (ticks < priv->duration_min && !allow_intermediate)
1301 g_string_printf(error_string,
1302 _("ckct_ib_min_allowed_duration_hts"),
1303 min_hours, min_minutes, min_seconds);
1304 hildon_time_editor_set_ticks (editor, priv->duration_min);
1305 priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS];
1308 else if (ticks > priv->duration_max)
1310 g_string_printf(error_string,
1311 _("ckct_ib_max_allowed_duration_hts"),
1312 max_hours, max_minutes, max_seconds);
1313 hildon_time_editor_set_ticks (editor, priv->duration_max);
1314 priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS];
1318 else if (!priv->clock_24h)
1319 convert_to_24h (&h, &m, &s, priv->am);
1321 /* The only case when we do not want to refresh the
1322 time display, is when the user is editing a value
1323 (unless the value was out of bounds and we have to fix it) */
1324 if (!allow_intermediate || priv->error_widget)
1325 hildon_time_editor_set_time (editor, h, m, s);
1328 /* Setting text to entries causes entry to recompute itself
1329 in idle callback, which remove selection. Because of this
1330 we need to do selection in idle as well. */
1331 static gboolean highlight_callback(gpointer data)
1333 HildonTimeEditorPrivate *priv;
1336 g_assert(HILDON_IS_TIME_EDITOR(data));
1338 priv = HILDON_TIME_EDITOR_GET_PRIVATE(data);
1339 widget = priv->error_widget;
1340 priv->error_widget = NULL;
1341 priv->highlight_idle = 0;
1343 g_assert(GTK_IS_ENTRY(widget));
1345 /* Grabbing focus can cause re-validation, priv->error widget
1346 can be set to something else, including NULL */
1347 gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
1348 gtk_widget_grab_focus(widget);
1353 /* Update ticks from current H:M:S entries. If they're invalid, show an
1354 infoprint and update the fields unless they're empty. */
1356 hildon_time_editor_validate (HildonTimeEditor *editor, gboolean allow_intermediate)
1358 HildonTimeEditorPrivate *priv;
1359 GString *error_message;
1361 g_assert(HILDON_IS_TIME_EDITOR(editor));
1363 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1364 priv->error_widget = NULL;
1366 error_message = g_string_new(NULL);
1367 hildon_time_editor_real_validate(editor,
1368 allow_intermediate, error_message);
1370 if (priv->error_widget) {
1371 hildon_banner_show_information(priv->error_widget, NULL,
1372 error_message->str);
1373 if (priv->highlight_idle == 0)
1374 priv->highlight_idle = g_idle_add(highlight_callback, editor);
1376 g_string_free(error_message, TRUE);
1379 static gboolean hildon_time_editor_entry_focusout(GtkWidget * widget,
1380 GdkEventFocus * event,
1383 g_assert(HILDON_IS_TIME_EDITOR(data));
1385 /* Validate the given time and update ticks. */
1386 hildon_time_editor_validate(HILDON_TIME_EDITOR(data), FALSE);
1392 hildon_time_editor_ampm_clicked(GtkWidget * widget,
1393 GdkEventButton * event, gpointer data)
1395 HildonTimeEditor *editor;
1396 HildonTimeEditorPrivate *priv;
1398 g_assert(GTK_IS_WIDGET(widget));
1399 g_assert(HILDON_IS_TIME_EDITOR(data));
1401 editor = HILDON_TIME_EDITOR(data);
1402 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1404 /* First validate the given time and update ticks. */
1405 hildon_time_editor_validate (editor, FALSE);
1407 /* Apply the AM/PM change by moving the current time by 12 hours */
1409 /* 00:00 .. 11:59 -> 12:00 .. 23:59 */
1410 hildon_time_editor_set_ticks (editor, priv->ticks + 12*3600);
1412 /* 12:00 .. 23:59 -> 00:00 .. 11:59 */
1413 hildon_time_editor_set_ticks (editor, priv->ticks - 12*3600);
1419 hildon_time_editor_icon_clicked(GtkWidget * widget, gpointer data)
1421 HildonTimeEditor *editor;
1424 guint h, m, s, result;
1426 g_assert(HILDON_IS_TIME_EDITOR(data));
1428 editor = HILDON_TIME_EDITOR(data);
1430 /* icon is passive in duration editor mode */
1431 if (hildon_time_editor_get_duration_mode(editor))
1434 /* Launch HildonTimePicker dialog */
1435 parent = gtk_widget_get_ancestor(GTK_WIDGET(editor), GTK_TYPE_WINDOW);
1436 picker = hildon_time_picker_new(GTK_WINDOW(parent));
1438 hildon_time_editor_get_time(editor, &h, &m, &s);
1439 hildon_time_picker_set_time(HILDON_TIME_PICKER(picker), h, m);
1441 result = gtk_dialog_run(GTK_DIALOG(picker));
1443 case GTK_RESPONSE_OK:
1444 case GTK_RESPONSE_ACCEPT:
1445 /* Use the selected time */
1446 hildon_time_picker_get_time(HILDON_TIME_PICKER(picker), &h, &m);
1447 hildon_time_editor_set_time(editor, h, m, 0);
1453 gtk_widget_destroy(picker);
1457 static gboolean hildon_time_editor_entry_clicked(GtkWidget * widget,
1458 GdkEventButton * event,
1461 HildonTimeEditor *editor;
1462 HildonTimeEditorPrivate *priv;
1464 editor = HILDON_TIME_EDITOR (data);
1465 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1467 /* If the focus has been grabbed back before the "clicked"
1468 * signal gets processed, don't highlight the text.
1469 * This happens when input in one H:M:S field is invalid and we're
1470 * trying to move to another field. The focus moves back to the invalid
1473 if (gtk_widget_is_focus (widget))
1474 gtk_editable_select_region(GTK_EDITABLE(widget), 0, 2);
1479 static void hildon_time_editor_size_request(GtkWidget * widget,
1480 GtkRequisition * requisition)
1482 HildonTimeEditor *editor;
1483 HildonTimeEditorPrivate *priv;
1486 editor = HILDON_TIME_EDITOR(widget);
1487 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1489 /* Get frame's size */
1490 gtk_widget_size_request(priv->frame, requisition);
1492 if (GTK_WIDGET_VISIBLE(priv->iconbutton))
1494 gtk_widget_size_request(priv->iconbutton, &req);
1495 /* Reserve space for icon */
1496 requisition->width += req.width + ICON_PRESSED +
1497 HILDON_MARGIN_DEFAULT;
1500 /* FIXME: It's evil to use hardcoded TIME_EDITOR_HEIGHT. For now we'll
1501 want to force this since themes might have varying thickness values
1502 which cause the height to change. */
1503 requisition->height = TIME_EDITOR_HEIGHT;
1506 static void hildon_time_editor_size_allocate(GtkWidget * widget,
1507 GtkAllocation * allocation)
1509 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget);
1510 GtkAllocation alloc;
1511 GtkRequisition req, max_req;
1513 widget->allocation = *allocation;
1514 gtk_widget_get_child_requisition(widget, &max_req);
1516 /* Center horizontally */
1517 alloc.x = allocation->x + MAX(allocation->width - max_req.width, 0) / 2;
1518 /* Center vertically */
1519 alloc.y = allocation->y + MAX(allocation->height - max_req.height, 0) / 2;
1521 /* allocate frame */
1522 gtk_widget_get_child_requisition(priv->frame, &req);
1524 alloc.width = req.width;
1525 alloc.height = max_req.height;
1526 gtk_widget_size_allocate(priv->frame, &alloc);
1529 if (GTK_WIDGET_VISIBLE(priv->iconbutton)) {
1530 gtk_widget_get_child_requisition(priv->iconbutton, &req);
1532 alloc.x += alloc.width + HILDON_MARGIN_DEFAULT;
1533 alloc.width = req.width;
1534 gtk_widget_size_allocate(priv->iconbutton, &alloc);
1537 /* FIXME: ugly way to move labels up. They just don't seem move up
1538 otherwise. This is likely because we force the editor to be
1539 smaller than it otherwise would be. */
1540 alloc = priv->ampm_label->allocation;
1541 alloc.y = allocation->y - 2;
1542 alloc.height = max_req.height + 2;
1543 gtk_widget_size_allocate(priv->ampm_label, &alloc);
1545 alloc = priv->hm_label->allocation;
1546 alloc.y = allocation->y - 2;
1547 alloc.height = max_req.height + 2;
1548 gtk_widget_size_allocate(priv->hm_label, &alloc);
1550 alloc = priv->sec_label->allocation;
1551 alloc.y = allocation->y - 2;
1552 alloc.height = max_req.height + 2;
1553 gtk_widget_size_allocate(priv->sec_label, &alloc);
1556 static gboolean hildon_time_editor_entry_keypress(GtkWidget * widget,
1557 GdkEventKey * event,
1560 HildonTimeEditor *editor;
1561 HildonTimeEditorPrivate *priv;
1564 g_assert(GTK_IS_ENTRY(widget));
1565 g_assert(event != NULL);
1566 g_assert(HILDON_IS_TIME_EDITOR(data));
1568 editor = HILDON_TIME_EDITOR(data);
1569 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1570 cursor_pos = gtk_editable_get_position(GTK_EDITABLE(widget));
1572 switch (event->keyval)
1575 /* Return key popups up time picker dialog. Visually it looks as if
1576 the time picker icon was clicked. Before opening the time picker
1577 the fields are first validated and fixed. */
1578 hildon_time_editor_validate (editor, FALSE);
1579 _gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), TRUE);
1580 hildon_time_editor_icon_clicked(widget, data);
1581 _gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), FALSE);
1585 /* left arrow pressed in the entry. If we are on first position, try to
1586 move to the previous field. */
1587 if (cursor_pos == 0) {
1588 (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_LEFT);
1594 /* right arrow pressed in the entry. If we are on last position, try to
1595 move to the next field. */
1596 if (cursor_pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1)) {
1597 (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_RIGHT);
1614 convert_to_12h (guint *h, guint *m, guint *s, gboolean *am)
1616 g_assert(0 <= *h && *h < 24);
1618 /* 00:00 to 00:59 add 12 hours */
1619 /* 01:00 to 11:59 straight to am */
1620 /* 12:00 to 12:59 straight to pm */
1621 /* 13:00 to 23:59 subtract 12 hours */
1623 if ( *h == 0 ) { *am = TRUE; *h += 12;}
1624 else if ( 1 <= *h && *h < 12 ) { *am = TRUE; }
1625 else if ( 12 <= *h && *h < 13 ) { *am = FALSE; }
1626 else { *am = FALSE; *h -= 12;}
1630 convert_to_24h (guint *h, guint *m, guint *s, gboolean am)
1632 if (*h == 12 && am) /* 12 midnight - 12:59 AM subtract 12 hours */
1636 else if (!am && 1 <= *h && *h < 12) /* 1:00 PM - 11:59 AM add 12 hours */
1643 * hildon_time_editor_set_show_hours:
1644 * @editor: The #HildonTimeEditor.
1645 * @enable: Enable or disable showing of hours.
1647 * This function shows or hides the hours field.
1650 void hildon_time_editor_set_show_hours(HildonTimeEditor * editor,
1651 gboolean show_hours)
1653 HildonTimeEditorPrivate *priv;
1655 g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
1657 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1659 if (show_hours != priv->show_hours) {
1660 priv->show_hours = show_hours;
1662 /* show/hide hours field and its ':' label if the value changed. */
1664 gtk_widget_show(priv->entries[ENTRY_HOURS]);
1665 gtk_widget_show(priv->hm_label);
1667 gtk_widget_hide(priv->entries[ENTRY_HOURS]);
1668 gtk_widget_hide(priv->hm_label);
1671 g_object_notify (G_OBJECT (editor), "show_hours");
1676 * hildon_time_editor_get_show_hours:
1677 * @self: the @HildonTimeEditor widget.
1679 * This function returns a boolean indicating the visibility of
1680 * hours in the @HildonTimeEditor
1682 * Return value: TRUE if hours are visible.
1684 gboolean hildon_time_editor_get_show_hours(HildonTimeEditor *editor)
1686 HildonTimeEditorPrivate *priv;
1688 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
1689 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1691 return priv->show_hours;
1695 * Deprecated functions
1699 * hildon_time_editor_show_seconds:
1700 * @editor: the #HildonTimeEditor
1701 * @enable: enable or disable showing of seconds
1703 * This function is deprecated,
1704 * use #hildon_time_editor_set_show_seconds instead.
1706 void hildon_time_editor_show_seconds(HildonTimeEditor * editor,
1709 hildon_time_editor_set_show_seconds (editor, enable);
1712 * hildon_time_editor_enable_duration_mode:
1713 * @editor: the #HildonTimeEditor
1714 * @enable: enable or disable duration editor mode
1716 * This function is deprecated,
1717 * use #hildon_time_editor_set_duration_mode instead.
1719 void hildon_time_editor_enable_duration_mode(HildonTimeEditor * editor,
1722 hildon_time_editor_set_duration_mode (editor, enable);