2 * This file is a part of hildon
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Rodrigo Novo <rodrigo.novo@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; 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.
39 * #HildonTimeEditor has been deprecated since Hildon 2.2 and should not
40 * be used in newly written code. Use #HildonTimeSelector instead.
45 * <title>HildonTimePicker example</title>
48 * editor = hildon_time_editor_new ();
49 * hildon_time_editor_set_time (editor, h, m, s);
51 * gtk_box_pack_start (..., editor)
53 * hildon_time_editor_get_time (editor, &h, &m, &s);
60 #undef HILDON_DISABLE_DEPRECATED
71 #include <gdk/gdkkeysyms.h>
73 #include "hildon-time-editor.h"
74 #include "hildon-defines.h"
75 #include "hildon-time-picker.h"
76 #include "hildon-banner.h"
77 #include "hildon-private.h"
78 #include "hildon-marshalers.h"
79 #include "hildon-enum-types.h"
80 #include "hildon-time-editor-private.h"
82 #define _(String) dgettext("hildon-libs", String)
84 #define c_(String) dgettext("hildon-common-strings", String)
86 #define TICKS(h,m,s) \
87 ((h) * 3600 + (m) * 60 + (s))
89 #define TIME_EDITOR_HEIGHT 30
91 #define ICON_PRESSED 4
93 #define ICON_NAME "qgn_widg_timedit"
95 #define ICON_SIZE "timepicker-size"
97 #define MIN_DURATION 0
99 #define MAX_DURATION TICKS(99, 59, 59)
101 /* Default values for properties */
103 #define HILDON_TIME_EDITOR_TICKS_VALUE 0
105 #define HILDON_TIME_EDITOR_DURATION_MODE FALSE
107 #define HILDON_TIME_EDITOR_DURATION_LOWER_VALUE 0
109 #define HILDON_TIME_EDITOR_DURATION_UPPER_VALUE TICKS(99, 59, 59)
111 #define HOURS_MAX_24 23
113 #define HOURS_MAX_12 12
115 #define HOURS_MIN_24 0
117 #define HOURS_MIN_12 1
119 #define MINUTES_MAX 59
121 #define SECONDS_MAX 59
123 #define MINUTES_MIN 0
125 #define SECONDS_MIN 0
127 static GtkContainerClass* parent_class;
146 /* Error codes categories */
154 static guint time_editor_signals[LAST_SIGNAL] = { 0 };
156 static guint hour_errors[NUM_ERROR_CODES] = {
157 HILDON_DATE_TIME_ERROR_MAX_HOURS,
158 HILDON_DATE_TIME_ERROR_MIN_HOURS,
159 HILDON_DATE_TIME_ERROR_EMPTY_HOURS };
161 static guint min_errors[NUM_ERROR_CODES] = {
162 HILDON_DATE_TIME_ERROR_MAX_MINS,
163 HILDON_DATE_TIME_ERROR_MIN_MINS,
164 HILDON_DATE_TIME_ERROR_EMPTY_MINS };
166 static guint sec_errors[NUM_ERROR_CODES] = {
167 HILDON_DATE_TIME_ERROR_MAX_SECS,
168 HILDON_DATE_TIME_ERROR_MIN_SECS,
169 HILDON_DATE_TIME_ERROR_EMPTY_SECS };
172 hildon_time_editor_class_init (HildonTimeEditorClass *editor_class);
175 hildon_time_editor_init (HildonTimeEditor *editor);
178 hildon_time_editor_finalize (GObject *obj_self);
181 hildon_time_editor_set_property (GObject *object,
187 hildon_time_editor_get_property (GObject *object,
193 hildon_time_editor_forall (GtkContainer *container,
194 gboolean include_internals,
195 GtkCallback callback,
196 gpointer callback_data);
199 hildon_time_editor_destroy (GtkObject *self);
202 hildon_time_editor_entry_focus_out (GtkWidget *widget,
203 GdkEventFocus *event,
207 hildon_time_editor_entry_focus_in (GtkWidget *widget,
208 GdkEventFocus *event,
212 hildon_time_editor_time_error (HildonTimeEditor *editor,
213 HildonDateTimeError type);
216 hildon_time_editor_ampm_clicked (GtkWidget *widget,
220 hildon_time_editor_icon_clicked (GtkWidget *widget,
224 hildon_time_editor_size_request (GtkWidget *widget,
225 GtkRequisition *requisition);
228 hildon_time_editor_size_allocate (GtkWidget *widget,
229 GtkAllocation *allocation);
232 hildon_time_editor_focus (GtkWidget *widget,
233 GtkDirectionType direction);
236 hildon_time_editor_entry_keypress (GtkEntry *entry,
241 hildon_time_editor_check_locale (HildonTimeEditor *editor);
245 hildon_time_editor_tap_and_hold_setup (GtkWidget *widget,
248 GtkWidgetTapAndHoldFlags flags);
252 hildon_time_editor_validate (HildonTimeEditor *editor,
253 gboolean allow_intermediate);
256 hildon_time_editor_set_to_current_time (HildonTimeEditor *editor);
259 hildon_time_editor_entry_select_all (GtkWidget *widget);
262 convert_to_12h (guint *h,
266 convert_to_24h (guint *h,
270 ticks_to_time (guint ticks,
276 hildon_time_editor_inserted_text (GtkEditable *editable,
278 gint new_text_length,
283 * hildon_time_editor_get_type:
285 * Initializes and returns the type of a hildon time editor.
287 * Returns: GType of #HildonTimeEditor
290 hildon_time_editor_get_type (void)
292 static GType editor_type = 0;
295 static const GTypeInfo editor_info = {
296 sizeof(HildonTimeEditorClass),
297 NULL, /* base_init */
298 NULL, /* base_finalize */
299 (GClassInitFunc) hildon_time_editor_class_init,
300 NULL, /* class_finalize */
301 NULL, /* class_data */
302 sizeof(HildonTimeEditor),
304 (GInstanceInitFunc) hildon_time_editor_init,
306 editor_type = g_type_register_static (GTK_TYPE_CONTAINER,
315 hildon_time_editor_forall (GtkContainer *container,
316 gboolean include_internals,
317 GtkCallback callback,
318 gpointer callback_data)
320 HildonTimeEditorPrivate *priv;
322 g_assert (HILDON_IS_TIME_EDITOR (container));
323 g_assert (callback != NULL);
325 priv = HILDON_TIME_EDITOR_GET_PRIVATE (container);
329 if (! include_internals)
332 /* widget that are always shown */
333 (*callback) (priv->iconbutton, callback_data);
334 (*callback) (priv->frame, callback_data);
338 hildon_time_editor_destroy (GtkObject *self)
340 HildonTimeEditorPrivate *priv;
342 priv = HILDON_TIME_EDITOR_GET_PRIVATE (self);
345 if (priv->iconbutton) {
346 gtk_widget_unparent (priv->iconbutton);
347 priv->iconbutton = NULL;
350 gtk_widget_unparent (priv->frame);
354 if (GTK_OBJECT_CLASS (parent_class)->destroy)
355 GTK_OBJECT_CLASS (parent_class)->destroy (self);
359 hildon_time_editor_class_init (HildonTimeEditorClass *editor_class)
361 GObjectClass *object_class = G_OBJECT_CLASS (editor_class);
362 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (editor_class);
363 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (editor_class);
365 parent_class = g_type_class_peek_parent (editor_class);
367 g_type_class_add_private (editor_class, sizeof (HildonTimeEditorPrivate));
369 object_class->get_property = hildon_time_editor_get_property;
370 object_class->set_property = hildon_time_editor_set_property;
371 widget_class->size_request = hildon_time_editor_size_request;
372 widget_class->size_allocate = hildon_time_editor_size_allocate;
373 widget_class->focus = hildon_time_editor_focus;
375 container_class->forall = hildon_time_editor_forall;
376 GTK_OBJECT_CLASS (editor_class)->destroy = hildon_time_editor_destroy;
378 object_class->finalize = hildon_time_editor_finalize;
380 editor_class->time_error = hildon_time_editor_time_error;
382 time_editor_signals[TIME_ERROR] =
383 g_signal_new ("time-error",
384 G_OBJECT_CLASS_TYPE (object_class),
386 G_STRUCT_OFFSET (HildonTimeEditorClass, time_error),
387 g_signal_accumulator_true_handled, NULL,
388 _hildon_marshal_BOOLEAN__ENUM,
389 G_TYPE_BOOLEAN, 1, HILDON_TYPE_DATE_TIME_ERROR);
392 * HildonTimeEditor:ticks:
394 * If editor is in duration mode, contains the duration seconds.
395 * If not, contains seconds since midnight.
397 g_object_class_install_property (object_class, PROP_TICKS,
398 g_param_spec_uint ("ticks",
400 "Current value of duration",
402 HILDON_TIME_EDITOR_TICKS_VALUE,
403 G_PARAM_READABLE | G_PARAM_WRITABLE) );
406 * HildonTimeEditor:show_seconds:
408 * Controls whether seconds are shown in the editor
410 g_object_class_install_property (object_class, PROP_SHOW_SECONDS,
411 g_param_spec_boolean ("show_seconds",
412 "Show seconds property",
413 "Controls whether the seconds are shown in the editor",
415 G_PARAM_READABLE | G_PARAM_WRITABLE) );
418 * HildonTimeEditor:show_hours:
420 * Controls whether hours are shown in the editor
422 g_object_class_install_property (object_class, PROP_SHOW_HOURS,
423 g_param_spec_boolean ("show_hours",
425 "Controls whether the hours field is shown in the editor",
427 G_PARAM_READABLE | G_PARAM_WRITABLE) );
430 * HildonTimeEditor:duration_mode:
432 * Controls whether the TimeEditor is in duration mode
434 g_object_class_install_property (object_class, PROP_DURATION_MODE,
435 g_param_spec_boolean ("duration_mode",
437 "Controls whether the TimeEditor is in duration mode",
438 HILDON_TIME_EDITOR_DURATION_MODE,
439 G_PARAM_READABLE | G_PARAM_WRITABLE) );
442 * HildonTimeEditor:duration_min:
444 * Minimum allowed duration value.
446 g_object_class_install_property (object_class, PROP_DURATION_MIN,
447 g_param_spec_uint ("duration_min",
448 "Minumum duration value",
449 "Smallest possible duration value",
450 MIN_DURATION, MAX_DURATION,
451 HILDON_TIME_EDITOR_DURATION_LOWER_VALUE,
452 G_PARAM_READABLE | G_PARAM_WRITABLE) );
455 * HildonTimeEditor:duration_max:
457 * Maximum allowed duration value.
459 g_object_class_install_property (object_class, PROP_DURATION_MAX,
460 g_param_spec_uint ("duration_max",
461 "Maximum duration value",
462 "Largest possible duration value",
464 HILDON_TIME_EDITOR_DURATION_UPPER_VALUE,
465 G_PARAM_READABLE | G_PARAM_WRITABLE) );
470 hildon_time_editor_tap_and_hold_setup (GtkWidget *widget,
473 GtkWidgetTapAndHoldFlags flags)
475 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE (widget);
478 /* Forward this tap_and_hold_setup signal to all our child widgets */
479 for (i = 0; i < ENTRY_COUNT; i++)
481 gtk_widget_tap_and_hold_setup (priv->entries[i], menu, func,
482 GTK_TAP_AND_HOLD_NO_SIGNALS);
484 gtk_widget_tap_and_hold_setup (priv->ampm_button, menu, func,
485 GTK_TAP_AND_HOLD_NO_SIGNALS);
486 gtk_widget_tap_and_hold_setup (priv->iconbutton, menu, func,
487 GTK_TAP_AND_HOLD_NONE);
492 hildon_time_editor_entry_changed (GtkWidget *widget,
495 g_assert (HILDON_IS_TIME_EDITOR (data));
496 hildon_time_editor_validate (HILDON_TIME_EDITOR (data), TRUE);
500 hildon_time_editor_init (HildonTimeEditor *editor)
502 HildonTimeEditorPrivate *priv;
503 GtkWidget *hbox, *icon;
506 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
509 gtk_widget_push_composite_child ();
511 /* Setup defaults and create widgets */
513 priv->show_seconds = FALSE;
514 priv->show_hours = TRUE;
515 priv->ampm_pos_after = TRUE;
516 priv->clock_24h = TRUE;
517 priv->duration_mode = FALSE;
518 priv->iconbutton = gtk_button_new();
519 priv->ampm_label = gtk_label_new(NULL);
520 priv->hm_label = gtk_label_new(NULL);
521 priv->sec_label = gtk_label_new(NULL);
522 priv->frame = gtk_frame_new(NULL);
523 priv->ampm_button = gtk_button_new();
524 priv->skipper = FALSE;
526 icon = gtk_image_new_from_icon_name (ICON_NAME, HILDON_ICON_SIZE_SMALL);
527 hbox = gtk_hbox_new (FALSE, 0);
529 GTK_WIDGET_SET_FLAGS (editor, GTK_NO_WINDOW);
530 GTK_WIDGET_UNSET_FLAGS (priv->iconbutton, GTK_CAN_FOCUS | GTK_CAN_DEFAULT);
532 gtk_container_set_border_width (GTK_CONTAINER(priv->frame), 0);
534 gtk_container_add (GTK_CONTAINER (priv->iconbutton), icon);
535 gtk_container_add (GTK_CONTAINER (priv->ampm_button), priv->ampm_label);
536 gtk_button_set_relief(GTK_BUTTON (priv->ampm_button), GTK_RELIEF_NONE);
537 gtk_button_set_focus_on_click (GTK_BUTTON (priv->ampm_button), FALSE);
539 /* Create hour, minute and second entries */
540 for (i = 0; i < ENTRY_COUNT; i++)
542 priv->entries[i] = gtk_entry_new ();
544 /* No frames for entries, so that they all appear to be inside one long entry */
545 gtk_entry_set_has_frame (GTK_ENTRY (priv->entries[i]), FALSE);
548 /* Set the entries to accept only numeric characters */
549 g_object_set (priv->entries[i], "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL);
552 /* The entry fields all take exactly two characters */
553 gtk_entry_set_max_length (GTK_ENTRY (priv->entries[i]), 2);
554 gtk_entry_set_width_chars (GTK_ENTRY (priv->entries[i]), 2);
556 g_signal_connect (priv->entries[i], "focus-in-event",
557 G_CALLBACK (hildon_time_editor_entry_focus_in), editor);
558 g_signal_connect (priv->entries[i], "focus-out-event",
559 G_CALLBACK (hildon_time_editor_entry_focus_out), editor);
560 g_signal_connect (priv->entries[i], "key-press-event",
561 G_CALLBACK (hildon_time_editor_entry_keypress), editor);
562 g_signal_connect (priv->entries[i], "changed",
563 G_CALLBACK (hildon_time_editor_entry_changed), editor);
565 /* inserted signal sets time */
566 g_signal_connect_after (G_OBJECT(priv->entries[i]), "insert_text",
567 G_CALLBACK (hildon_time_editor_inserted_text),
571 /* clicked signal for am/pm label */
572 g_signal_connect (G_OBJECT (priv->ampm_button), "clicked",
573 G_CALLBACK (hildon_time_editor_ampm_clicked), editor);
575 /* clicked signal for icon */
576 g_signal_connect (G_OBJECT (priv->iconbutton), "clicked",
577 G_CALLBACK (hildon_time_editor_icon_clicked), editor);
579 /* Set ourself as the parent of all the widgets we created */
580 gtk_widget_set_parent (priv->iconbutton, GTK_WIDGET(editor));
581 gtk_box_pack_start (GTK_BOX (hbox), priv->entries[ENTRY_HOURS], FALSE, FALSE, 0);
582 gtk_box_pack_start (GTK_BOX (hbox), priv->hm_label, FALSE, FALSE, 0);
583 gtk_box_pack_start (GTK_BOX (hbox), priv->entries[ENTRY_MINS], FALSE, FALSE, 0);
584 gtk_box_pack_start (GTK_BOX (hbox), priv->sec_label, FALSE, FALSE, 0);
585 gtk_box_pack_start (GTK_BOX (hbox), priv->entries[ENTRY_SECS], FALSE, FALSE, 0);
586 gtk_box_pack_start (GTK_BOX (hbox), priv->ampm_button, FALSE, FALSE, 0);
587 gtk_misc_set_padding (GTK_MISC (priv->ampm_label), 0, 0);
589 gtk_container_add (GTK_CONTAINER (priv->frame), hbox);
591 /* Show created widgets */
592 gtk_widget_set_parent (priv->frame, GTK_WIDGET(editor));
593 gtk_widget_show_all (priv->frame);
594 gtk_widget_show_all (priv->iconbutton);
596 /* Update AM/PM and time separators settings from locale */
597 if (! hildon_time_editor_check_locale (editor)) {
598 /* Using 12h clock */
599 priv->clock_24h = FALSE;
601 gtk_widget_hide (priv->ampm_button);
604 if (! priv->show_seconds) {
605 gtk_widget_hide (priv->sec_label);
606 gtk_widget_hide (priv->entries[ENTRY_SECS]);
609 /* set the default time to current time. */
610 hildon_time_editor_set_to_current_time (editor);
612 gtk_widget_pop_composite_child ();
615 g_signal_connect (editor, "tap-and-hold-setup",
616 G_CALLBACK (hildon_time_editor_tap_and_hold_setup),
623 hildon_time_editor_set_property (GObject *object,
628 HildonTimeEditor *time_editor = HILDON_TIME_EDITOR (object);
633 hildon_time_editor_set_ticks (time_editor, g_value_get_uint(value));
636 case PROP_SHOW_SECONDS:
637 hildon_time_editor_set_show_seconds (time_editor, g_value_get_boolean(value));
640 case PROP_SHOW_HOURS:
641 hildon_time_editor_set_show_hours (time_editor, g_value_get_boolean(value));
644 case PROP_DURATION_MODE:
645 hildon_time_editor_set_duration_mode (time_editor, g_value_get_boolean(value));
648 case PROP_DURATION_MIN:
649 hildon_time_editor_set_duration_min (time_editor, g_value_get_uint(value));
652 case PROP_DURATION_MAX:
653 hildon_time_editor_set_duration_max (time_editor, g_value_get_uint(value));
657 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
663 hildon_time_editor_get_property (GObject *object,
668 HildonTimeEditor *time_editor = HILDON_TIME_EDITOR (object);
674 g_value_set_uint (value, hildon_time_editor_get_ticks (time_editor));
677 case PROP_SHOW_SECONDS:
678 g_value_set_boolean (value, hildon_time_editor_get_show_seconds (time_editor));
681 case PROP_SHOW_HOURS:
682 g_value_set_boolean (value, hildon_time_editor_get_show_hours (time_editor));
685 case PROP_DURATION_MODE:
686 g_value_set_boolean (value, hildon_time_editor_get_duration_mode (time_editor));
689 case PROP_DURATION_MIN:
690 g_value_set_uint (value, hildon_time_editor_get_duration_min (time_editor));
693 case PROP_DURATION_MAX:
694 g_value_set_uint (value, hildon_time_editor_get_duration_max (time_editor));
698 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
704 * hildon_time_editor_new:
706 * This function creates a new time editor.
708 * Returns: pointer to a new #HildonTimeEditor widget
711 hildon_time_editor_new (void)
713 return GTK_WIDGET (g_object_new (HILDON_TYPE_TIME_EDITOR, NULL));
717 hildon_time_editor_finalize (GObject *obj_self)
719 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE (obj_self);
723 g_free (priv->am_symbol);
726 g_free (priv->pm_symbol);
728 if (priv->highlight_idle)
729 g_source_remove (priv->highlight_idle);
731 if (G_OBJECT_CLASS (parent_class)->finalize)
732 G_OBJECT_CLASS (parent_class)->finalize (obj_self);
736 * hildon_time_editor_get_time_separators:
737 * @hm_sep_label: the label that will show the hour:minutes separator
738 * @ms_sep_label: the label that will show the minutes:seconds separator
740 * Gets hour-minute separator and minute-second separator from current
741 * locale and sets then to the labels we set as parameters. Both
742 * parameters can be NULL if you just want to assing one separator.
746 hildon_time_editor_get_time_separators (GtkLabel *hm_sep_label,
747 GtkLabel *ms_sep_label)
751 GDate locale_test_date;
752 gchar *iter, *endp = NULL;
754 /* Get localized time string */
755 g_date_set_dmy (&locale_test_date, 1, 2, 1970);
756 (void) g_date_strftime (buffer, sizeof (buffer), "%X", &locale_test_date);
758 if (hm_sep_label != NULL)
760 /* Find h-m separator */
762 while (*iter && g_ascii_isdigit (*iter)) iter++;
764 /* Extract h-m separator*/
766 while (*endp && ! g_ascii_isdigit (*endp)) endp++;
767 separator = g_strndup (iter, endp - iter);
768 gtk_label_set_label (hm_sep_label, separator);
772 if (ms_sep_label != NULL)
774 /* Find m-s separator */
776 while (*iter && g_ascii_isdigit (*iter)) iter++;
778 /* Extract m-s separator*/
780 while (*endp && ! g_ascii_isdigit (*endp)) endp++;
781 separator = g_strndup (iter, endp - iter);
782 gtk_label_set_label (ms_sep_label, separator);
787 /* Convert ticks to H:M:S. Ticks = seconds since 00:00:00. */
789 ticks_to_time (guint ticks,
796 *hours = ticks / 3600;
798 *minutes = left / 60;
799 *seconds = left % 60;
803 * hildon_time_editor_set_ticks:
804 * @editor: the #HildonTimeEditor widget
805 * @ticks: the duration to set, in seconds
807 * Sets the current duration in seconds. This means seconds from
808 * midnight, if not in duration mode. In case of any errors, it tries
813 hildon_time_editor_set_ticks (HildonTimeEditor *editor,
816 HildonTimeEditorPrivate *priv;
820 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
822 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
825 /* Validate ticks. If it's too low or too high, set it to
826 min/max value for the current mode. */
827 if (priv->duration_mode)
828 priv->ticks = CLAMP (ticks, priv->duration_min, priv->duration_max);
830 /* Check that ticks value is valid. We only need to check that hours
832 ticks_to_time (ticks, &h, &m, &s);
833 if (h > HOURS_MAX_24)
834 ticks = TICKS(HOURS_MAX_24, m, s);
839 /* Get the time in H:M:S. */
840 ticks_to_time (priv->ticks, &h, &m, &s);
842 if (!priv->clock_24h && ! priv->duration_mode)
844 /* Convert 24h H:M:S values to 12h mode, and update AM/PM state */
845 convert_to_12h (&h, &priv->am);
848 /* Set H:M:S values to entries. We do not want to invoke validation
849 callbacks (since they can cause new call to this function), so we
850 block signals while setting values. */
851 for (i = 0; i < ENTRY_COUNT; i++)
853 g_signal_handlers_block_by_func(priv->entries[i],
854 (gpointer) hildon_time_editor_entry_changed, editor);
856 g_signal_handlers_block_by_func(priv->entries[i],
857 (gpointer) hildon_time_editor_inserted_text, editor);
859 g_signal_handlers_block_by_func(priv->entries[i],
860 (gpointer) hildon_time_editor_entry_focus_out, editor);
863 g_snprintf (str, sizeof (str), "%02u", h);
864 gtk_entry_set_text (GTK_ENTRY (priv->entries[ENTRY_HOURS]), str);
866 g_snprintf(str, sizeof (str), "%02u", m);
867 gtk_entry_set_text (GTK_ENTRY (priv->entries[ENTRY_MINS]), str);
869 g_snprintf(str, sizeof (str), "%02u", s);
870 gtk_entry_set_text (GTK_ENTRY (priv->entries[ENTRY_SECS]), str);
872 for (i = 0; i < ENTRY_COUNT; i++)
874 g_signal_handlers_unblock_by_func (priv->entries[i],
875 (gpointer) hildon_time_editor_entry_changed, editor);
877 g_signal_handlers_unblock_by_func (priv->entries[i],
878 (gpointer) hildon_time_editor_inserted_text, editor);
880 g_signal_handlers_unblock_by_func (priv->entries[i],
881 (gpointer) hildon_time_editor_entry_focus_out, editor);
884 /* Update AM/PM label in case we're in 12h mode */
885 gtk_label_set_label( GTK_LABEL (priv->ampm_label),
886 priv->am ? priv->am_symbol : priv->pm_symbol);
888 g_object_notify (G_OBJECT (editor), "ticks");
892 hildon_time_editor_set_to_current_time (HildonTimeEditor *editor)
898 tm = localtime (&now);
901 hildon_time_editor_set_time (editor, tm->tm_hour, tm->tm_min, tm->tm_sec);
905 * hildon_time_editor_get_ticks:
906 * @editor: the #HildonTimeEditor widget
908 * This function returns the current duration, in seconds.
909 * This means seconds from midnight, if not in duration mode.
911 * Returns: current duration in seconds
914 hildon_time_editor_get_ticks (HildonTimeEditor *editor)
916 HildonTimeEditorPrivate *priv;
918 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), 0);
920 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
923 return (priv->ticks);
927 * hildon_time_editor_set_show_seconds:
928 * @editor: the #HildonTimeEditor
929 * @show_seconds: enable or disable showing of seconds
931 * This function shows or hides the seconds field.
934 hildon_time_editor_set_show_seconds (HildonTimeEditor *editor,
935 gboolean show_seconds)
937 HildonTimeEditorPrivate *priv;
939 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
941 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
944 if (show_seconds != priv->show_seconds) {
945 priv->show_seconds = show_seconds;
947 /* show/hide seconds field and its ':' label if the value changed. */
949 gtk_widget_show (priv->entries[ENTRY_SECS]);
950 gtk_widget_show (priv->sec_label);
952 gtk_widget_hide (priv->entries[ENTRY_SECS]);
953 gtk_widget_hide (priv->sec_label);
956 g_object_notify (G_OBJECT (editor), "show_seconds");
961 * hildon_time_editor_get_show_seconds:
962 * @editor: the #HildonTimeEditor widget
964 * This function returns a boolean indicating the visibility of
965 * seconds in the #HildonTimeEditor
967 * Returns: TRUE if the seconds are visible
970 hildon_time_editor_get_show_seconds (HildonTimeEditor *editor)
972 HildonTimeEditorPrivate *priv;
974 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
975 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
978 return (priv->show_seconds);
982 * hildon_time_editor_set_duration_mode:
983 * @editor: the #HildonTimeEditor
984 * @duration_mode: enable or disable duration editor mode
986 * This function sets the duration editor mode in which the maximum hours
990 hildon_time_editor_set_duration_mode (HildonTimeEditor *editor,
991 gboolean duration_mode)
993 HildonTimeEditorPrivate *priv;
995 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
997 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1000 if (duration_mode != priv->duration_mode) {
1001 priv->duration_mode = duration_mode;
1003 if (duration_mode) {
1004 /* FIXME: Why do we reset the duration range here?
1005 Would change API, so won't touch this for now. */
1006 hildon_time_editor_set_duration_range (editor, MIN_DURATION, MAX_DURATION);
1007 /* There's no AM/PM label or time picker icon in duration mode.
1008 Make sure they're hidden. */
1009 gtk_widget_hide (GTK_WIDGET (priv->ampm_label));
1010 gtk_widget_hide (GTK_WIDGET (priv->ampm_button));
1011 gtk_widget_hide (GTK_WIDGET (priv->iconbutton));
1012 /* Duration mode has seconds by default. */
1013 hildon_time_editor_set_show_seconds (editor, TRUE);
1015 /* Make sure AM/PM label and time picker icons are visible if needed */
1016 if (! priv->clock_24h)
1017 gtk_widget_show (GTK_WIDGET (priv->ampm_label));
1019 gtk_widget_show (GTK_WIDGET (priv->ampm_button));
1020 gtk_widget_show (GTK_WIDGET (priv->iconbutton));
1022 /* Reset the ticks to current time. Anything set in duration mode
1023 * is bound to be invalid or useless in time mode.
1025 hildon_time_editor_set_to_current_time (editor);
1028 g_object_notify (G_OBJECT (editor), "duration_mode");
1033 * hildon_time_editor_get_duration_mode:
1034 * @editor: the #HildonTimeEditor widget
1036 * This function returns a boolean indicating whether the #HildonTimeEditor
1037 * is in the duration mode.
1039 * Returns: TRUE if the #HildonTimeEditor is in duration mode
1042 hildon_time_editor_get_duration_mode (HildonTimeEditor *editor)
1044 HildonTimeEditorPrivate *priv;
1046 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
1047 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1050 return (priv->duration_mode);
1054 * hildon_time_editor_set_duration_min:
1055 * @editor: the #HildonTimeEditor widget
1056 * @duration_min: mimimum allowed duration
1058 * Sets the minimum allowed duration for the duration mode.
1059 * Note: Has no effect in time mode
1062 hildon_time_editor_set_duration_min (HildonTimeEditor *editor,
1065 HildonTimeEditorPrivate *priv;
1067 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1068 g_return_if_fail (duration_min >= MIN_DURATION);
1070 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1073 if (! priv->duration_mode )
1076 priv->duration_min = duration_min;
1078 /* Clamp the current value to the minimum if necessary */
1079 if (priv->ticks < duration_min)
1081 hildon_time_editor_set_ticks (editor, duration_min);
1084 g_object_notify (G_OBJECT (editor), "duration_min");
1088 * hildon_time_editor_get_duration_min:
1089 * @editor: the #HildonTimeEditor widget
1091 * This function returns the smallest duration the #HildonTimeEditor
1092 * allows in the duration mode.
1094 * Returns: minimum allowed duration in seconds
1097 hildon_time_editor_get_duration_min (HildonTimeEditor *editor)
1099 HildonTimeEditorPrivate *priv;
1101 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), 0);
1103 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1106 if(! priv->duration_mode )
1109 return (priv->duration_min);
1113 * hildon_time_editor_set_duration_max:
1114 * @editor: the #HildonTimeEditor widget
1115 * @duration_max: maximum allowed duration in seconds
1117 * Sets the maximum allowed duration in seconds for the duration mode.
1118 * Note: Has no effect in time mode
1121 hildon_time_editor_set_duration_max (HildonTimeEditor *editor,
1124 HildonTimeEditorPrivate *priv;
1126 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1127 g_return_if_fail (duration_max <= MAX_DURATION);
1129 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1132 if (! priv->duration_mode)
1135 priv->duration_max = duration_max;
1137 /* Clamp the current value to the maximum if necessary */
1138 if (priv->ticks > duration_max)
1140 hildon_time_editor_set_ticks (editor, duration_max);
1143 g_object_notify (G_OBJECT (editor), "duration_max");
1147 * hildon_time_editor_get_duration_max:
1148 * @editor: the #HildonTimeEditor widget
1150 * This function returns the longest duration the #HildonTimeEditor
1151 * allows in the duration mode.
1153 * Returns: maximum allowed duration in seconds
1156 hildon_time_editor_get_duration_max (HildonTimeEditor * editor)
1158 HildonTimeEditorPrivate *priv;
1160 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), 0);
1162 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1165 if (! priv->duration_mode)
1168 return (priv->duration_max);
1172 * hildon_time_editor_set_time:
1173 * @editor: the #HildonTimeEditor widget
1178 * This function sets the time on an existing time editor. If the
1179 * time specified by the arguments is invalid, it's fixed.
1180 * The time is assumed to be in 24h format.
1183 hildon_time_editor_set_time (HildonTimeEditor *editor,
1188 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1190 hildon_time_editor_set_ticks (editor, TICKS(hours, minutes, seconds));
1194 * hildon_time_editor_get_time:
1195 * @editor: the #HildonTimeEditor widget
1200 * Gets the time of the #HildonTimeEditor widget. The time returned is
1201 * always in 24h format.
1204 hildon_time_editor_get_time (HildonTimeEditor *editor,
1209 HildonTimeEditorPrivate *priv;
1211 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1213 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1216 ticks_to_time (hildon_time_editor_get_ticks (editor), hours, minutes, seconds);
1220 * hildon_time_editor_set_duration_range:
1221 * @editor: the #HildonTimeEditor widget
1222 * @min_seconds: minimum allowed time in seconds
1223 * @max_seconds: maximum allowed time in seconds
1225 * Sets the duration editor time range of the #HildonTimeEditor widget.
1228 hildon_time_editor_set_duration_range (HildonTimeEditor *editor,
1232 HildonTimeEditorPrivate *priv;
1235 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1237 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1240 /* Swap values if reversed */
1241 if (min_seconds > max_seconds)
1244 max_seconds = min_seconds;
1248 hildon_time_editor_set_duration_max (editor, max_seconds);
1249 hildon_time_editor_set_duration_min (editor, min_seconds);
1251 if (priv->duration_mode) {
1252 /* Set minimum allowed value for duration editor.
1253 FIXME: Shouldn't it be changed only if it's not in range?
1254 Would change API, so won't touch this for now. */
1255 hildon_time_editor_set_ticks (editor, min_seconds);
1260 * hildon_time_editor_get_duration_range:
1261 * @editor: the #HildonTimeEditor widget
1262 * @min_seconds: pointer to guint
1263 * @max_seconds: pointer to guint
1265 * Gets the duration editor time range of the #HildonTimeEditor widget.
1268 hildon_time_editor_get_duration_range (HildonTimeEditor *editor,
1272 HildonTimeEditorPrivate *priv;
1274 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1276 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1279 *min_seconds = priv->duration_min;
1280 *max_seconds = priv->duration_max;
1284 hildon_time_editor_check_locale (HildonTimeEditor *editor)
1286 HildonTimeEditorPrivate *priv;
1288 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1291 /* Update time separator symbols */
1292 hildon_time_editor_get_time_separators (GTK_LABEL (priv->hm_label), GTK_LABEL (priv->sec_label));
1294 /* Get AM/PM symbols. */
1295 priv->am_symbol = g_strdup (nl_langinfo (AM_STR));
1296 priv->pm_symbol = g_strdup (nl_langinfo (PM_STR));
1298 if (priv->am_symbol[0] == '\0')
1301 /* 12h clock mode. Check if AM/PM should be before or after time.
1302 %p is the AM/PM string, so we assume that if the format string
1303 begins with %p it's in the beginning, and in any other case it's
1304 in the end (although that's not necessarily the case). */
1305 if (strncmp (nl_langinfo (T_FMT_AMPM), "%p", 2) == 0)
1306 priv->ampm_pos_after = FALSE;
1312 hildon_time_editor_entry_focus_in (GtkWidget *widget,
1313 GdkEventFocus *event,
1316 g_idle_add ((GSourceFunc) hildon_time_editor_entry_select_all,
1317 GTK_ENTRY (widget));
1323 hildon_time_editor_time_error (HildonTimeEditor *editor,
1324 HildonDateTimeError type)
1329 /* Returns negative if we didn't get value,
1330 * and should stop further validation
1333 validated_conversion (HildonTimeEditorPrivate *priv,
1338 gboolean allow_intermediate,
1340 GString *error_string)
1346 text = gtk_entry_get_text (GTK_ENTRY (field));
1348 if (text && text[0])
1350 /* Try to convert entry text to number */
1351 value = strtol (text, &tail, 10);
1353 /* Check if conversion succeeded */
1354 if ((tail[0] == 0) && !(text[0] == '-'))
1357 g_string_printf (error_string, _("ckct_ib_maximum_value"), max);
1358 priv->error_widget = field;
1359 *error_code = MAX_VALUE;
1363 if (value < min && !allow_intermediate) {
1364 g_string_printf (error_string, _("ckct_ib_minimum_value"), min);
1365 priv->error_widget = field;
1366 *error_code = MIN_VALUE;
1373 /* We'll handle failed conversions soon */
1376 if ((tail[0] == '-') || (text[0] == '-'))
1378 g_string_printf (error_string, _("ckct_ib_minimum_value"), min);
1379 priv->error_widget = field;
1380 *error_code = MIN_VALUE;
1385 else if (allow_intermediate)
1386 return -1; /* Empty field while user is still editing. No error, but
1387 cannot validate either... */
1388 else /* Empty field: show error and set value to minimum allowed */
1390 g_string_printf (error_string, _("ckct_ib_set_a_value_within_range"), min, max);
1391 priv->error_widget = field;
1392 *error_code = WITHIN_RANGE;
1396 /* Empty field and not allowed intermediated OR failed conversion */
1397 g_string_printf (error_string, _("ckct_ib_set_a_value_within_range"), min, max);
1398 priv->error_widget = field;
1399 *error_code = WITHIN_RANGE;
1404 hildon_time_editor_real_validate (HildonTimeEditor *editor,
1405 gboolean allow_intermediate,
1406 GString *error_string)
1408 HildonTimeEditorPrivate *priv;
1409 guint h, m, s, ticks;
1411 guint max_hours, min_hours, def_hours;
1412 guint max_minutes, min_minutes, def_minutes;
1413 guint max_seconds, min_seconds, def_seconds;
1416 g_assert (HILDON_IS_TIME_EDITOR (editor));
1418 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1421 /* Find limits for field based validation. */
1422 if (priv->duration_mode)
1424 ticks_to_time (priv->duration_min, &min_hours, &min_minutes, &min_seconds);
1425 ticks_to_time (priv->duration_max, &max_hours, &max_minutes, &max_seconds);
1427 if (priv->clock_24h) {
1428 max_hours = HOURS_MAX_24;
1429 min_hours = HOURS_MIN_24;
1431 max_hours = HOURS_MAX_12;
1432 min_hours = HOURS_MIN_12;
1436 hildon_time_editor_get_time (editor, &def_hours, &def_minutes, &def_seconds);
1438 /* Get time components from fields and validate them... */
1439 if (priv->show_hours) {
1440 h = validated_conversion (priv, priv->entries[ENTRY_HOURS], min_hours, max_hours, def_hours,
1441 allow_intermediate, &error_code, error_string);
1442 if (priv->error_widget == priv->entries[ENTRY_HOURS])
1443 g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, hour_errors[error_code], &r);
1444 if ((gint) h < 0) return;
1447 m = validated_conversion (priv, priv->entries[ENTRY_MINS], MINUTES_MIN, MINUTES_MAX, def_minutes,
1448 allow_intermediate, &error_code, error_string);
1449 if (priv->error_widget == priv->entries[ENTRY_MINS])
1450 g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, min_errors[error_code], &r);
1451 if ((gint) m < 0) return;
1452 if (priv->show_seconds) {
1453 s = validated_conversion (priv, priv->entries[ENTRY_SECS], SECONDS_MIN, SECONDS_MAX, def_seconds,
1454 allow_intermediate, &error_code, error_string);
1455 if (priv->error_widget == priv->entries[ENTRY_SECS])
1456 g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, sec_errors[error_code], &r);
1457 if ((gint) s < 0) return;
1461 /* Ok, we now do separate check that tick count is valid for duration mode */
1462 if (priv->duration_mode)
1464 ticks = TICKS(h, m, s);
1466 if (ticks < priv->duration_min && !allow_intermediate)
1468 g_string_printf (error_string,
1469 _("ckct_ib_min_allowed_duration_hts"),
1470 min_hours, min_minutes, min_seconds);
1471 hildon_time_editor_set_ticks (editor, priv->duration_min);
1472 priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS];
1473 g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, HILDON_DATE_TIME_ERROR_MIN_DURATION, &r);
1476 else if (ticks > priv->duration_max)
1478 g_string_printf (error_string,
1479 _("ckct_ib_max_allowed_duration_hts"),
1480 max_hours, max_minutes, max_seconds);
1481 hildon_time_editor_set_ticks (editor, priv->duration_max);
1482 priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS];
1483 g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, HILDON_DATE_TIME_ERROR_MAX_DURATION, &r);
1487 else if (! priv->clock_24h)
1488 convert_to_24h (&h, priv->am);
1490 /* The only case when we do not want to refresh the
1491 time display, is when the user is editing a value
1492 (unless the value was out of bounds and we have to fix it) */
1493 if (! allow_intermediate || priv->error_widget)
1494 hildon_time_editor_set_time (editor, h, m, s);
1497 /* Setting text to entries causes entry to recompute itself
1498 in idle callback, which remove selection. Because of this
1499 we need to do selection in idle as well. */
1501 highlight_callback (gpointer data)
1503 HildonTimeEditorPrivate *priv;
1507 g_assert (HILDON_IS_TIME_EDITOR (data));
1508 priv = HILDON_TIME_EDITOR_GET_PRIVATE (data);
1511 GDK_THREADS_ENTER ();
1513 widget = priv->error_widget;
1514 priv->error_widget = NULL;
1516 if (GTK_IS_WIDGET (widget) == FALSE)
1519 /* Avoid revalidation because it will issue the date_error signal
1520 twice when there is an empty field. We must block the signal
1521 for all the entries because we do not know where the focus
1523 for (i = 0; i < ENTRY_COUNT; i++)
1524 g_signal_handlers_block_by_func (priv->entries[i],
1525 (gpointer) hildon_time_editor_entry_focus_out, data);
1526 gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
1527 gtk_widget_grab_focus (widget);
1528 for (i = 0; i < ENTRY_COUNT; i++)
1529 g_signal_handlers_unblock_by_func (priv->entries[i],
1530 (gpointer) hildon_time_editor_entry_focus_out, data);
1533 priv->highlight_idle = 0;
1534 GDK_THREADS_LEAVE ();
1539 /* Update ticks from current H:M:S entries. If they're invalid, show an
1540 infoprint and update the fields unless they're empty. */
1542 hildon_time_editor_validate (HildonTimeEditor *editor,
1543 gboolean allow_intermediate)
1545 HildonTimeEditorPrivate *priv;
1546 GString *error_message;
1548 g_assert (HILDON_IS_TIME_EDITOR(editor));
1549 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1552 /* if there is already an error we do nothing until it will be managed by the idle */
1553 if (priv->highlight_idle == 0 && priv->skipper == FALSE)
1555 priv->skipper = TRUE;
1556 error_message = g_string_new (NULL);
1557 hildon_time_editor_real_validate (editor,
1558 allow_intermediate, error_message);
1560 if (priv->error_widget)
1562 hildon_banner_show_information (priv->error_widget, NULL,
1563 error_message->str);
1565 priv->highlight_idle = g_idle_add (highlight_callback, editor);
1568 priv->skipper = FALSE;
1569 g_string_free (error_message, TRUE);
1573 /* on inserted text, if entry has two digits, jumps to the next field. */
1575 hildon_time_editor_inserted_text (GtkEditable *editable,
1577 gint new_text_length,
1581 HildonTimeEditor *editor;
1584 HildonTimeEditorPrivate *priv;
1586 entry = GTK_ENTRY (editable);
1587 editor = HILDON_TIME_EDITOR (user_data);
1589 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1592 /* if there is already an error we don't have to do anything */
1593 if (! priv->error_widget)
1595 value = (gchar *) gtk_entry_get_text (entry);
1597 if (strlen (value) == 2)
1599 if (GTK_WIDGET (editable) == priv->entries[ENTRY_HOURS])
1601 /* We already checked the input in changed signal, but
1602 * now we will re-check it again in focus-out we
1603 * intermediate flag set to FALSE */
1604 gtk_widget_grab_focus (priv->entries[ENTRY_MINS]);
1607 else if (GTK_WIDGET (editable) == priv->entries[ENTRY_MINS] &&
1608 GTK_WIDGET_VISIBLE (priv->entries[ENTRY_SECS]))
1611 gtk_widget_grab_focus (priv->entries[ENTRY_SECS]);
1619 hildon_time_editor_entry_focus_out (GtkWidget *widget,
1620 GdkEventFocus *event,
1623 g_assert (HILDON_IS_TIME_EDITOR (data));
1625 /* Validate the given time and update ticks. */
1626 hildon_time_editor_validate (HILDON_TIME_EDITOR (data), FALSE);
1632 hildon_time_editor_ampm_clicked (GtkWidget *widget,
1635 HildonTimeEditor *editor;
1636 HildonTimeEditorPrivate *priv;
1638 g_assert (GTK_IS_WIDGET (widget));
1639 g_assert (HILDON_IS_TIME_EDITOR (data));
1641 editor = HILDON_TIME_EDITOR (data);
1642 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1645 /* First validate the given time and update ticks. */
1646 hildon_time_editor_validate (editor, FALSE);
1648 /* Apply the AM/PM change by moving the current time by 12 hours */
1650 /* 00:00 .. 11:59 -> 12:00 .. 23:59 */
1651 hildon_time_editor_set_ticks (editor, priv->ticks + 12 * 3600);
1653 /* 12:00 .. 23:59 -> 00:00 .. 11:59 */
1654 hildon_time_editor_set_ticks (editor, priv->ticks - 12 * 3600);
1661 hildon_time_editor_icon_clicked (GtkWidget *widget,
1664 HildonTimeEditor *editor;
1667 guint h, m, s, result;
1668 HildonTimeEditorPrivate *priv;
1670 g_assert (HILDON_IS_TIME_EDITOR (data));
1672 editor = HILDON_TIME_EDITOR (data);
1673 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1676 /* icon is passive in duration editor mode */
1677 if (hildon_time_editor_get_duration_mode (editor))
1680 /* Validate and do not launch if broken */
1681 hildon_time_editor_validate (HILDON_TIME_EDITOR (data), FALSE);
1682 if (priv->error_widget != NULL)
1685 /* Launch HildonTimePicker dialog */
1686 parent = gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW);
1687 picker = hildon_time_picker_new (GTK_WINDOW (parent));
1689 hildon_time_editor_get_time (editor, &h, &m, &s);
1690 hildon_time_picker_set_time (HILDON_TIME_PICKER (picker), h, m);
1692 result = gtk_dialog_run (GTK_DIALOG (picker));
1695 case GTK_RESPONSE_OK:
1696 case GTK_RESPONSE_ACCEPT:
1697 /* Use the selected time */
1698 hildon_time_picker_get_time (HILDON_TIME_PICKER (picker), &h, &m);
1699 hildon_time_editor_set_time (editor, h, m, 0);
1706 gtk_widget_destroy (picker);
1711 hildon_time_editor_size_request (GtkWidget *widget,
1712 GtkRequisition *requisition)
1714 HildonTimeEditor *editor;
1715 HildonTimeEditorPrivate *priv;
1718 editor = HILDON_TIME_EDITOR (widget);
1719 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1721 /* Get frame's size */
1722 gtk_widget_size_request (priv->frame, requisition);
1724 if (GTK_WIDGET_VISIBLE (priv->iconbutton))
1726 gtk_widget_size_request (priv->iconbutton, &req);
1727 /* Reserve space for icon */
1728 requisition->width += req.width + ICON_PRESSED +
1729 HILDON_MARGIN_DEFAULT;
1732 /* FIXME: It's evil to use hardcoded TIME_EDITOR_HEIGHT. For now we'll
1733 want to force this since themes might have varying thickness values
1734 which cause the height to change. */
1735 requisition->height = TIME_EDITOR_HEIGHT;
1739 hildon_time_editor_size_allocate (GtkWidget *widget,
1740 GtkAllocation *allocation)
1742 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE (widget);
1743 GtkAllocation alloc;
1744 GtkRequisition req, max_req;
1749 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1750 widget->allocation = *allocation;
1751 gtk_widget_get_child_requisition (widget, &max_req);
1753 /* Center horizontally */
1754 alloc.x = allocation->x + MAX (allocation->width - max_req.width, 0) / 2;
1755 /* Center vertically */
1756 alloc.y = allocation->y + MAX (allocation->height - max_req.height, 0) / 2;
1758 /* allocate frame */
1760 gtk_widget_get_child_requisition (priv->iconbutton, &req);
1762 gtk_widget_get_child_requisition (priv->frame, &req);
1764 alloc.width = req.width;
1765 alloc.height = max_req.height;
1767 gtk_widget_size_allocate (priv->iconbutton, &alloc);
1769 gtk_widget_size_allocate (priv->frame, &alloc);
1772 if (GTK_WIDGET_VISIBLE (priv->iconbutton)) {
1774 gtk_widget_get_child_requisition (priv->frame, &req);
1776 gtk_widget_get_child_requisition (priv->iconbutton, &req);
1778 alloc.x += alloc.width + HILDON_MARGIN_DEFAULT;
1779 alloc.width = req.width;
1782 gtk_widget_size_allocate (priv->frame, &alloc);
1784 gtk_widget_size_allocate (priv->iconbutton, &alloc);
1787 /* FIXME: ugly way to move labels up. They just don't seem move up
1788 otherwise. This is likely because we force the editor to be
1789 smaller than it otherwise would be. */
1790 alloc = priv->ampm_label->allocation;
1791 alloc.y = allocation->y - 2;
1792 alloc.height = max_req.height + 2;
1793 gtk_widget_size_allocate (priv->ampm_label, &alloc);
1795 alloc = priv->hm_label->allocation;
1796 alloc.y = allocation->y - 2;
1797 alloc.height = max_req.height + 2;
1798 gtk_widget_size_allocate (priv->hm_label, &alloc);
1800 alloc = priv->sec_label->allocation;
1801 alloc.y = allocation->y - 2;
1802 alloc.height = max_req.height + 2;
1803 gtk_widget_size_allocate (priv->sec_label, &alloc);
1807 hildon_time_editor_focus (GtkWidget *widget,
1808 GtkDirectionType direction)
1811 GtkDirectionType effective_direction;
1813 g_assert (HILDON_IS_TIME_EDITOR (widget));
1815 retval = hildon_private_composite_focus (widget, direction, &effective_direction);
1818 return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction);
1824 hildon_time_editor_entry_keypress (GtkEntry *entry,
1828 switch (event->keyval)
1832 hildon_time_editor_icon_clicked (GTK_WIDGET (entry), data);
1838 g_assert_not_reached ();
1842 convert_to_12h (guint *h,
1845 g_assert (0 <= *h && *h < 24);
1847 /* 00:00 to 00:59 add 12 hours */
1848 /* 01:00 to 11:59 straight to am */
1849 /* 12:00 to 12:59 straight to pm */
1850 /* 13:00 to 23:59 subtract 12 hours */
1852 if ( *h == 0 ) { *am = TRUE; *h += 12;}
1853 else if ( 1 <= *h && *h < 12 ) { *am = TRUE; }
1854 else if ( 12 <= *h && *h < 13 ) { *am = FALSE; }
1855 else { *am = FALSE; *h -= 12;}
1859 convert_to_24h (guint *h,
1862 if (*h == 12 && am) /* 12 midnight - 12:59 AM subtract 12 hours */
1867 else if (! am && 1 <= *h && *h < 12) /* 1:00 PM - 11:59 AM add 12 hours */
1874 * hildon_time_editor_set_show_hours:
1875 * @editor: The #HildonTimeEditor.
1876 * @show_hours: Enable or disable showing of hours.
1878 * This function shows or hides the hours field.
1882 hildon_time_editor_set_show_hours (HildonTimeEditor *editor,
1883 gboolean show_hours)
1885 HildonTimeEditorPrivate *priv;
1887 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1889 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1892 if (show_hours != priv->show_hours) {
1893 priv->show_hours = show_hours;
1895 /* show/hide hours field and its ':' label if the value changed. */
1897 gtk_widget_show (priv->entries[ENTRY_HOURS]);
1898 gtk_widget_show (priv->hm_label);
1900 gtk_widget_hide (priv->entries[ENTRY_HOURS]);
1901 gtk_widget_hide (priv->hm_label);
1904 g_object_notify (G_OBJECT (editor), "show_hours");
1909 * hildon_time_editor_get_show_hours:
1910 * @editor: the @HildonTimeEditor widget.
1912 * This function returns a boolean indicating the visibility of
1913 * hours in the @HildonTimeEditor
1915 * Return value: TRUE if hours are visible.
1919 hildon_time_editor_get_show_hours (HildonTimeEditor *editor)
1921 HildonTimeEditorPrivate *priv;
1923 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
1924 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1927 return priv->show_hours;
1932 hildon_time_editor_entry_select_all (GtkWidget *widget)
1934 GDK_THREADS_ENTER ();
1935 gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
1936 GDK_THREADS_LEAVE ();