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. See
41 * <link linkend="hildon-migrating-time-widgets">Migrating Time Widgets</link>
42 * section to know how to migrate this deprecated widget.
47 * <title>HildonTimePicker example</title>
50 * editor = hildon_time_editor_new ();
51 * hildon_time_editor_set_time (editor, h, m, s);
53 * gtk_box_pack_start (..., editor)
55 * hildon_time_editor_get_time (editor, &h, &m, &s);
62 #undef HILDON_DISABLE_DEPRECATED
73 #include <gdk/gdkkeysyms.h>
75 #include "hildon-time-editor.h"
76 #include "hildon-defines.h"
77 #include "hildon-time-picker.h"
78 #include "hildon-banner.h"
79 #include "hildon-private.h"
80 #include "hildon-marshalers.h"
81 #include "hildon-enum-types.h"
82 #include "hildon-time-editor-private.h"
84 #define _(String) dgettext("hildon-libs", String)
86 #define c_(String) dgettext("hildon-common-strings", String)
88 #define TICKS(h,m,s) \
89 ((h) * 3600 + (m) * 60 + (s))
91 #define TIME_EDITOR_HEIGHT 30
93 #define ICON_PRESSED 4
95 #define ICON_NAME "widgets_time_editor"
97 #define ICON_SIZE "timepicker-size"
99 #define MIN_DURATION 0
101 #define MAX_DURATION TICKS(99, 59, 59)
103 /* Default values for properties */
105 #define HILDON_TIME_EDITOR_TICKS_VALUE 0
107 #define HILDON_TIME_EDITOR_DURATION_MODE FALSE
109 #define HILDON_TIME_EDITOR_DURATION_LOWER_VALUE 0
111 #define HILDON_TIME_EDITOR_DURATION_UPPER_VALUE TICKS(99, 59, 59)
113 #define HOURS_MAX_24 23
115 #define HOURS_MAX_12 12
117 #define HOURS_MIN_24 0
119 #define HOURS_MIN_12 1
121 #define MINUTES_MAX 59
123 #define SECONDS_MAX 59
125 #define MINUTES_MIN 0
127 #define SECONDS_MIN 0
129 static GtkContainerClass* parent_class;
148 /* Error codes categories */
156 static guint time_editor_signals[LAST_SIGNAL] = { 0 };
158 static guint hour_errors[NUM_ERROR_CODES] = {
159 HILDON_DATE_TIME_ERROR_MAX_HOURS,
160 HILDON_DATE_TIME_ERROR_MIN_HOURS,
161 HILDON_DATE_TIME_ERROR_EMPTY_HOURS };
163 static guint min_errors[NUM_ERROR_CODES] = {
164 HILDON_DATE_TIME_ERROR_MAX_MINS,
165 HILDON_DATE_TIME_ERROR_MIN_MINS,
166 HILDON_DATE_TIME_ERROR_EMPTY_MINS };
168 static guint sec_errors[NUM_ERROR_CODES] = {
169 HILDON_DATE_TIME_ERROR_MAX_SECS,
170 HILDON_DATE_TIME_ERROR_MIN_SECS,
171 HILDON_DATE_TIME_ERROR_EMPTY_SECS };
174 hildon_time_editor_class_init (HildonTimeEditorClass *editor_class);
177 hildon_time_editor_init (HildonTimeEditor *editor);
180 hildon_time_editor_finalize (GObject *obj_self);
183 hildon_time_editor_set_property (GObject *object,
189 hildon_time_editor_get_property (GObject *object,
195 hildon_time_editor_forall (GtkContainer *container,
196 gboolean include_internals,
197 GtkCallback callback,
198 gpointer callback_data);
201 hildon_time_editor_destroy (GtkObject *self);
204 hildon_time_editor_entry_focus_out (GtkWidget *widget,
205 GdkEventFocus *event,
209 hildon_time_editor_entry_focus_in (GtkWidget *widget,
210 GdkEventFocus *event,
214 hildon_time_editor_time_error (HildonTimeEditor *editor,
215 HildonDateTimeError type);
218 hildon_time_editor_ampm_clicked (GtkWidget *widget,
222 hildon_time_editor_icon_clicked (GtkWidget *widget,
226 hildon_time_editor_size_request (GtkWidget *widget,
227 GtkRequisition *requisition);
230 hildon_time_editor_size_allocate (GtkWidget *widget,
231 GtkAllocation *allocation);
234 hildon_time_editor_focus (GtkWidget *widget,
235 GtkDirectionType direction);
238 hildon_time_editor_entry_keypress (GtkEntry *entry,
243 hildon_time_editor_check_locale (HildonTimeEditor *editor);
247 hildon_time_editor_tap_and_hold_setup (GtkWidget *widget,
250 GtkWidgetTapAndHoldFlags flags);
254 hildon_time_editor_validate (HildonTimeEditor *editor,
255 gboolean allow_intermediate);
258 hildon_time_editor_set_to_current_time (HildonTimeEditor *editor);
261 hildon_time_editor_entry_select_all (GtkWidget *widget);
264 convert_to_12h (guint *h,
268 convert_to_24h (guint *h,
272 ticks_to_time (guint ticks,
278 hildon_time_editor_inserted_text (GtkEditable *editable,
280 gint new_text_length,
285 * hildon_time_editor_get_type:
287 * Initializes and returns the type of a hildon time editor.
289 * Returns: GType of #HildonTimeEditor
292 hildon_time_editor_get_type (void)
294 static GType editor_type = 0;
297 static const GTypeInfo editor_info = {
298 sizeof(HildonTimeEditorClass),
299 NULL, /* base_init */
300 NULL, /* base_finalize */
301 (GClassInitFunc) hildon_time_editor_class_init,
302 NULL, /* class_finalize */
303 NULL, /* class_data */
304 sizeof(HildonTimeEditor),
306 (GInstanceInitFunc) hildon_time_editor_init,
308 editor_type = g_type_register_static (GTK_TYPE_CONTAINER,
317 hildon_time_editor_forall (GtkContainer *container,
318 gboolean include_internals,
319 GtkCallback callback,
320 gpointer callback_data)
322 HildonTimeEditorPrivate *priv;
324 g_assert (HILDON_IS_TIME_EDITOR (container));
325 g_assert (callback != NULL);
327 priv = HILDON_TIME_EDITOR_GET_PRIVATE (container);
331 if (! include_internals)
334 /* widget that are always shown */
335 (*callback) (priv->iconbutton, callback_data);
336 (*callback) (priv->frame, callback_data);
340 hildon_time_editor_destroy (GtkObject *self)
342 HildonTimeEditorPrivate *priv;
344 priv = HILDON_TIME_EDITOR_GET_PRIVATE (self);
347 if (priv->iconbutton) {
348 gtk_widget_unparent (priv->iconbutton);
349 priv->iconbutton = NULL;
352 gtk_widget_unparent (priv->frame);
356 if (GTK_OBJECT_CLASS (parent_class)->destroy)
357 GTK_OBJECT_CLASS (parent_class)->destroy (self);
361 hildon_time_editor_class_init (HildonTimeEditorClass *editor_class)
363 GObjectClass *object_class = G_OBJECT_CLASS (editor_class);
364 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (editor_class);
365 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (editor_class);
367 parent_class = g_type_class_peek_parent (editor_class);
369 g_type_class_add_private (editor_class, sizeof (HildonTimeEditorPrivate));
371 object_class->get_property = hildon_time_editor_get_property;
372 object_class->set_property = hildon_time_editor_set_property;
373 widget_class->size_request = hildon_time_editor_size_request;
374 widget_class->size_allocate = hildon_time_editor_size_allocate;
375 widget_class->focus = hildon_time_editor_focus;
377 container_class->forall = hildon_time_editor_forall;
378 GTK_OBJECT_CLASS (editor_class)->destroy = hildon_time_editor_destroy;
380 object_class->finalize = hildon_time_editor_finalize;
382 editor_class->time_error = hildon_time_editor_time_error;
384 time_editor_signals[TIME_ERROR] =
385 g_signal_new ("time-error",
386 G_OBJECT_CLASS_TYPE (object_class),
388 G_STRUCT_OFFSET (HildonTimeEditorClass, time_error),
389 g_signal_accumulator_true_handled, NULL,
390 _hildon_marshal_BOOLEAN__ENUM,
391 G_TYPE_BOOLEAN, 1, HILDON_TYPE_DATE_TIME_ERROR);
394 * HildonTimeEditor:ticks:
396 * If editor is in duration mode, contains the duration seconds.
397 * If not, contains seconds since midnight.
399 g_object_class_install_property (object_class, PROP_TICKS,
400 g_param_spec_uint ("ticks",
402 "Current value of duration",
404 HILDON_TIME_EDITOR_TICKS_VALUE,
405 G_PARAM_READABLE | G_PARAM_WRITABLE) );
408 * HildonTimeEditor:show_seconds:
410 * Controls whether seconds are shown in the editor
412 g_object_class_install_property (object_class, PROP_SHOW_SECONDS,
413 g_param_spec_boolean ("show_seconds",
414 "Show seconds property",
415 "Controls whether the seconds are shown in the editor",
417 G_PARAM_READABLE | G_PARAM_WRITABLE) );
420 * HildonTimeEditor:show_hours:
422 * Controls whether hours are shown in the editor
424 g_object_class_install_property (object_class, PROP_SHOW_HOURS,
425 g_param_spec_boolean ("show_hours",
427 "Controls whether the hours field is shown in the editor",
429 G_PARAM_READABLE | G_PARAM_WRITABLE) );
432 * HildonTimeEditor:duration_mode:
434 * Controls whether the TimeEditor is in duration mode
436 g_object_class_install_property (object_class, PROP_DURATION_MODE,
437 g_param_spec_boolean ("duration_mode",
439 "Controls whether the TimeEditor is in duration mode",
440 HILDON_TIME_EDITOR_DURATION_MODE,
441 G_PARAM_READABLE | G_PARAM_WRITABLE) );
444 * HildonTimeEditor:duration_min:
446 * Minimum allowed duration value.
448 g_object_class_install_property (object_class, PROP_DURATION_MIN,
449 g_param_spec_uint ("duration_min",
450 "Minumum duration value",
451 "Smallest possible duration value",
452 MIN_DURATION, MAX_DURATION,
453 HILDON_TIME_EDITOR_DURATION_LOWER_VALUE,
454 G_PARAM_READABLE | G_PARAM_WRITABLE) );
457 * HildonTimeEditor:duration_max:
459 * Maximum allowed duration value.
461 g_object_class_install_property (object_class, PROP_DURATION_MAX,
462 g_param_spec_uint ("duration_max",
463 "Maximum duration value",
464 "Largest possible duration value",
466 HILDON_TIME_EDITOR_DURATION_UPPER_VALUE,
467 G_PARAM_READABLE | G_PARAM_WRITABLE) );
472 hildon_time_editor_tap_and_hold_setup (GtkWidget *widget,
475 GtkWidgetTapAndHoldFlags flags)
477 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE (widget);
480 /* Forward this tap_and_hold_setup signal to all our child widgets */
481 for (i = 0; i < ENTRY_COUNT; i++)
483 gtk_widget_tap_and_hold_setup (priv->entries[i], menu, func,
484 GTK_TAP_AND_HOLD_NO_SIGNALS);
486 gtk_widget_tap_and_hold_setup (priv->ampm_button, menu, func,
487 GTK_TAP_AND_HOLD_NO_SIGNALS);
488 gtk_widget_tap_and_hold_setup (priv->iconbutton, menu, func,
489 GTK_TAP_AND_HOLD_NONE);
494 hildon_time_editor_entry_changed (GtkWidget *widget,
497 g_assert (HILDON_IS_TIME_EDITOR (data));
498 hildon_time_editor_validate (HILDON_TIME_EDITOR (data), TRUE);
502 hildon_time_editor_init (HildonTimeEditor *editor)
504 HildonTimeEditorPrivate *priv;
505 GtkWidget *hbox, *icon;
508 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
511 gtk_widget_push_composite_child ();
513 /* Setup defaults and create widgets */
515 priv->show_seconds = FALSE;
516 priv->show_hours = TRUE;
517 priv->ampm_pos_after = TRUE;
518 priv->clock_24h = TRUE;
519 priv->duration_mode = FALSE;
520 priv->iconbutton = gtk_button_new();
521 priv->ampm_label = gtk_label_new(NULL);
522 priv->hm_label = gtk_label_new(NULL);
523 priv->sec_label = gtk_label_new(NULL);
524 priv->frame = gtk_frame_new(NULL);
525 priv->ampm_button = gtk_button_new();
526 priv->skipper = FALSE;
528 icon = gtk_image_new_from_icon_name (ICON_NAME, HILDON_ICON_SIZE_SMALL);
529 hbox = gtk_hbox_new (FALSE, 0);
531 GTK_WIDGET_SET_FLAGS (editor, GTK_NO_WINDOW);
532 GTK_WIDGET_UNSET_FLAGS (priv->iconbutton, GTK_CAN_FOCUS | GTK_CAN_DEFAULT);
534 gtk_container_set_border_width (GTK_CONTAINER(priv->frame), 0);
536 gtk_container_add (GTK_CONTAINER (priv->iconbutton), icon);
537 gtk_container_add (GTK_CONTAINER (priv->ampm_button), priv->ampm_label);
538 gtk_button_set_relief(GTK_BUTTON (priv->ampm_button), GTK_RELIEF_NONE);
539 gtk_button_set_focus_on_click (GTK_BUTTON (priv->ampm_button), FALSE);
541 /* Create hour, minute and second entries */
542 for (i = 0; i < ENTRY_COUNT; i++)
544 priv->entries[i] = gtk_entry_new ();
546 /* No frames for entries, so that they all appear to be inside one long entry */
547 gtk_entry_set_has_frame (GTK_ENTRY (priv->entries[i]), FALSE);
550 /* Set the entries to accept only numeric characters */
551 g_object_set (priv->entries[i], "hildon-input-mode", HILDON_GTK_INPUT_MODE_NUMERIC, NULL);
554 /* The entry fields all take exactly two characters */
555 gtk_entry_set_max_length (GTK_ENTRY (priv->entries[i]), 2);
556 gtk_entry_set_width_chars (GTK_ENTRY (priv->entries[i]), 2);
558 g_signal_connect (priv->entries[i], "focus-in-event",
559 G_CALLBACK (hildon_time_editor_entry_focus_in), editor);
560 g_signal_connect (priv->entries[i], "focus-out-event",
561 G_CALLBACK (hildon_time_editor_entry_focus_out), editor);
562 g_signal_connect (priv->entries[i], "key-press-event",
563 G_CALLBACK (hildon_time_editor_entry_keypress), editor);
564 g_signal_connect (priv->entries[i], "changed",
565 G_CALLBACK (hildon_time_editor_entry_changed), editor);
567 /* inserted signal sets time */
568 g_signal_connect_after (G_OBJECT(priv->entries[i]), "insert_text",
569 G_CALLBACK (hildon_time_editor_inserted_text),
573 /* clicked signal for am/pm label */
574 g_signal_connect (G_OBJECT (priv->ampm_button), "clicked",
575 G_CALLBACK (hildon_time_editor_ampm_clicked), editor);
577 /* clicked signal for icon */
578 g_signal_connect (G_OBJECT (priv->iconbutton), "clicked",
579 G_CALLBACK (hildon_time_editor_icon_clicked), editor);
581 /* Set ourself as the parent of all the widgets we created */
582 gtk_widget_set_parent (priv->iconbutton, GTK_WIDGET(editor));
583 gtk_box_pack_start (GTK_BOX (hbox), priv->entries[ENTRY_HOURS], FALSE, FALSE, 0);
584 gtk_box_pack_start (GTK_BOX (hbox), priv->hm_label, FALSE, FALSE, 0);
585 gtk_box_pack_start (GTK_BOX (hbox), priv->entries[ENTRY_MINS], FALSE, FALSE, 0);
586 gtk_box_pack_start (GTK_BOX (hbox), priv->sec_label, FALSE, FALSE, 0);
587 gtk_box_pack_start (GTK_BOX (hbox), priv->entries[ENTRY_SECS], FALSE, FALSE, 0);
588 gtk_box_pack_start (GTK_BOX (hbox), priv->ampm_button, FALSE, FALSE, 0);
589 gtk_misc_set_padding (GTK_MISC (priv->ampm_label), 0, 0);
591 gtk_container_add (GTK_CONTAINER (priv->frame), hbox);
593 /* Show created widgets */
594 gtk_widget_set_parent (priv->frame, GTK_WIDGET(editor));
595 gtk_widget_show_all (priv->frame);
596 gtk_widget_show_all (priv->iconbutton);
598 /* Update AM/PM and time separators settings from locale */
599 if (! hildon_time_editor_check_locale (editor)) {
600 /* Using 12h clock */
601 priv->clock_24h = FALSE;
603 gtk_widget_hide (priv->ampm_button);
606 if (! priv->show_seconds) {
607 gtk_widget_hide (priv->sec_label);
608 gtk_widget_hide (priv->entries[ENTRY_SECS]);
611 /* set the default time to current time. */
612 hildon_time_editor_set_to_current_time (editor);
614 gtk_widget_pop_composite_child ();
617 g_signal_connect (editor, "tap-and-hold-setup",
618 G_CALLBACK (hildon_time_editor_tap_and_hold_setup),
625 hildon_time_editor_set_property (GObject *object,
630 HildonTimeEditor *time_editor = HILDON_TIME_EDITOR (object);
635 hildon_time_editor_set_ticks (time_editor, g_value_get_uint(value));
638 case PROP_SHOW_SECONDS:
639 hildon_time_editor_set_show_seconds (time_editor, g_value_get_boolean(value));
642 case PROP_SHOW_HOURS:
643 hildon_time_editor_set_show_hours (time_editor, g_value_get_boolean(value));
646 case PROP_DURATION_MODE:
647 hildon_time_editor_set_duration_mode (time_editor, g_value_get_boolean(value));
650 case PROP_DURATION_MIN:
651 hildon_time_editor_set_duration_min (time_editor, g_value_get_uint(value));
654 case PROP_DURATION_MAX:
655 hildon_time_editor_set_duration_max (time_editor, g_value_get_uint(value));
659 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
665 hildon_time_editor_get_property (GObject *object,
670 HildonTimeEditor *time_editor = HILDON_TIME_EDITOR (object);
676 g_value_set_uint (value, hildon_time_editor_get_ticks (time_editor));
679 case PROP_SHOW_SECONDS:
680 g_value_set_boolean (value, hildon_time_editor_get_show_seconds (time_editor));
683 case PROP_SHOW_HOURS:
684 g_value_set_boolean (value, hildon_time_editor_get_show_hours (time_editor));
687 case PROP_DURATION_MODE:
688 g_value_set_boolean (value, hildon_time_editor_get_duration_mode (time_editor));
691 case PROP_DURATION_MIN:
692 g_value_set_uint (value, hildon_time_editor_get_duration_min (time_editor));
695 case PROP_DURATION_MAX:
696 g_value_set_uint (value, hildon_time_editor_get_duration_max (time_editor));
700 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
706 * hildon_time_editor_new:
708 * This function creates a new time editor.
710 * Returns: pointer to a new #HildonTimeEditor widget
713 hildon_time_editor_new (void)
715 return GTK_WIDGET (g_object_new (HILDON_TYPE_TIME_EDITOR, NULL));
719 hildon_time_editor_finalize (GObject *obj_self)
721 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE (obj_self);
725 g_free (priv->am_symbol);
728 g_free (priv->pm_symbol);
730 if (priv->highlight_idle)
731 g_source_remove (priv->highlight_idle);
733 if (G_OBJECT_CLASS (parent_class)->finalize)
734 G_OBJECT_CLASS (parent_class)->finalize (obj_self);
738 * hildon_time_editor_get_time_separators:
739 * @hm_sep_label: the label that will show the hour:minutes separator
740 * @ms_sep_label: the label that will show the minutes:seconds separator
742 * Gets hour-minute separator and minute-second separator from current
743 * locale and sets then to the labels we set as parameters. Both
744 * parameters can be NULL if you just want to assing one separator.
748 hildon_time_editor_get_time_separators (GtkLabel *hm_sep_label,
749 GtkLabel *ms_sep_label)
753 GDate locale_test_date;
754 gchar *iter, *endp = NULL;
756 /* Get localized time string */
757 g_date_set_dmy (&locale_test_date, 1, 2, 1970);
758 (void) g_date_strftime (buffer, sizeof (buffer), "%X", &locale_test_date);
760 /* Find h-m separator */
762 while (*iter && g_ascii_isdigit (*iter)) iter++;
763 /* Extract h-m separator*/
765 while (*endp && ! g_ascii_isdigit (*endp)) endp++;
767 if (hm_sep_label != NULL)
769 separator = g_strndup (iter, endp - iter);
770 gtk_label_set_label (hm_sep_label, separator);
774 if (ms_sep_label != NULL)
776 /* Find m-s separator */
778 while (*iter && g_ascii_isdigit (*iter)) iter++;
780 /* Extract m-s separator*/
782 while (*endp && ! g_ascii_isdigit (*endp)) endp++;
783 separator = g_strndup (iter, endp - iter);
784 gtk_label_set_label (ms_sep_label, separator);
789 /* Convert ticks to H:M:S. Ticks = seconds since 00:00:00. */
791 ticks_to_time (guint ticks,
798 *hours = ticks / 3600;
800 *minutes = left / 60;
801 *seconds = left % 60;
805 * hildon_time_editor_set_ticks:
806 * @editor: the #HildonTimeEditor widget
807 * @ticks: the duration to set, in seconds
809 * Sets the current duration in seconds. This means seconds from
810 * midnight, if not in duration mode. In case of any errors, it tries
815 hildon_time_editor_set_ticks (HildonTimeEditor *editor,
818 HildonTimeEditorPrivate *priv;
822 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
824 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
827 /* Validate ticks. If it's too low or too high, set it to
828 min/max value for the current mode. */
829 if (priv->duration_mode)
830 priv->ticks = CLAMP (ticks, priv->duration_min, priv->duration_max);
832 /* Check that ticks value is valid. We only need to check that hours
834 ticks_to_time (ticks, &h, &m, &s);
835 if (h > HOURS_MAX_24)
836 ticks = TICKS(HOURS_MAX_24, m, s);
841 /* Get the time in H:M:S. */
842 ticks_to_time (priv->ticks, &h, &m, &s);
844 if (!priv->clock_24h && ! priv->duration_mode)
846 /* Convert 24h H:M:S values to 12h mode, and update AM/PM state */
847 convert_to_12h (&h, &priv->am);
850 /* Set H:M:S values to entries. We do not want to invoke validation
851 callbacks (since they can cause new call to this function), so we
852 block signals while setting values. */
853 for (i = 0; i < ENTRY_COUNT; i++)
855 g_signal_handlers_block_by_func(priv->entries[i],
856 (gpointer) hildon_time_editor_entry_changed, editor);
858 g_signal_handlers_block_by_func(priv->entries[i],
859 (gpointer) hildon_time_editor_inserted_text, editor);
861 g_signal_handlers_block_by_func(priv->entries[i],
862 (gpointer) hildon_time_editor_entry_focus_out, editor);
865 g_snprintf (str, sizeof (str), "%02u", h);
866 gtk_entry_set_text (GTK_ENTRY (priv->entries[ENTRY_HOURS]), str);
868 g_snprintf(str, sizeof (str), "%02u", m);
869 gtk_entry_set_text (GTK_ENTRY (priv->entries[ENTRY_MINS]), str);
871 g_snprintf(str, sizeof (str), "%02u", s);
872 gtk_entry_set_text (GTK_ENTRY (priv->entries[ENTRY_SECS]), str);
874 for (i = 0; i < ENTRY_COUNT; i++)
876 g_signal_handlers_unblock_by_func (priv->entries[i],
877 (gpointer) hildon_time_editor_entry_changed, editor);
879 g_signal_handlers_unblock_by_func (priv->entries[i],
880 (gpointer) hildon_time_editor_inserted_text, editor);
882 g_signal_handlers_unblock_by_func (priv->entries[i],
883 (gpointer) hildon_time_editor_entry_focus_out, editor);
886 /* Update AM/PM label in case we're in 12h mode */
887 gtk_label_set_label( GTK_LABEL (priv->ampm_label),
888 priv->am ? priv->am_symbol : priv->pm_symbol);
890 g_object_notify (G_OBJECT (editor), "ticks");
894 hildon_time_editor_set_to_current_time (HildonTimeEditor *editor)
900 tm = localtime (&now);
903 hildon_time_editor_set_time (editor, tm->tm_hour, tm->tm_min, tm->tm_sec);
907 * hildon_time_editor_get_ticks:
908 * @editor: the #HildonTimeEditor widget
910 * This function returns the current duration, in seconds.
911 * This means seconds from midnight, if not in duration mode.
913 * Returns: current duration in seconds
916 hildon_time_editor_get_ticks (HildonTimeEditor *editor)
918 HildonTimeEditorPrivate *priv;
920 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), 0);
922 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
925 return (priv->ticks);
929 * hildon_time_editor_set_show_seconds:
930 * @editor: the #HildonTimeEditor
931 * @show_seconds: enable or disable showing of seconds
933 * This function shows or hides the seconds field.
936 hildon_time_editor_set_show_seconds (HildonTimeEditor *editor,
937 gboolean show_seconds)
939 HildonTimeEditorPrivate *priv;
941 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
943 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
946 if (show_seconds != priv->show_seconds) {
947 priv->show_seconds = show_seconds;
949 /* show/hide seconds field and its ':' label if the value changed. */
951 gtk_widget_show (priv->entries[ENTRY_SECS]);
952 gtk_widget_show (priv->sec_label);
954 gtk_widget_hide (priv->entries[ENTRY_SECS]);
955 gtk_widget_hide (priv->sec_label);
958 g_object_notify (G_OBJECT (editor), "show_seconds");
963 * hildon_time_editor_get_show_seconds:
964 * @editor: the #HildonTimeEditor widget
966 * This function returns a boolean indicating the visibility of
967 * seconds in the #HildonTimeEditor
969 * Returns: TRUE if the seconds are visible
972 hildon_time_editor_get_show_seconds (HildonTimeEditor *editor)
974 HildonTimeEditorPrivate *priv;
976 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
977 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
980 return (priv->show_seconds);
984 * hildon_time_editor_set_duration_mode:
985 * @editor: the #HildonTimeEditor
986 * @duration_mode: enable or disable duration editor mode
988 * This function sets the duration editor mode in which the maximum hours
992 hildon_time_editor_set_duration_mode (HildonTimeEditor *editor,
993 gboolean duration_mode)
995 HildonTimeEditorPrivate *priv;
997 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
999 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1002 if (duration_mode != priv->duration_mode) {
1003 priv->duration_mode = duration_mode;
1005 if (duration_mode) {
1006 /* FIXME: Why do we reset the duration range here?
1007 Would change API, so won't touch this for now. */
1008 hildon_time_editor_set_duration_range (editor, MIN_DURATION, MAX_DURATION);
1009 /* There's no AM/PM label or time picker icon in duration mode.
1010 Make sure they're hidden. */
1011 gtk_widget_hide (GTK_WIDGET (priv->ampm_label));
1012 gtk_widget_hide (GTK_WIDGET (priv->ampm_button));
1013 gtk_widget_hide (GTK_WIDGET (priv->iconbutton));
1014 /* Duration mode has seconds by default. */
1015 hildon_time_editor_set_show_seconds (editor, TRUE);
1017 /* Make sure AM/PM label and time picker icons are visible if needed */
1018 if (! priv->clock_24h)
1019 gtk_widget_show (GTK_WIDGET (priv->ampm_label));
1021 gtk_widget_show (GTK_WIDGET (priv->ampm_button));
1022 gtk_widget_show (GTK_WIDGET (priv->iconbutton));
1024 /* Reset the ticks to current time. Anything set in duration mode
1025 * is bound to be invalid or useless in time mode.
1027 hildon_time_editor_set_to_current_time (editor);
1030 g_object_notify (G_OBJECT (editor), "duration_mode");
1035 * hildon_time_editor_get_duration_mode:
1036 * @editor: the #HildonTimeEditor widget
1038 * This function returns a boolean indicating whether the #HildonTimeEditor
1039 * is in the duration mode.
1041 * Returns: TRUE if the #HildonTimeEditor is in duration mode
1044 hildon_time_editor_get_duration_mode (HildonTimeEditor *editor)
1046 HildonTimeEditorPrivate *priv;
1048 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
1049 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1052 return (priv->duration_mode);
1056 * hildon_time_editor_set_duration_min:
1057 * @editor: the #HildonTimeEditor widget
1058 * @duration_min: mimimum allowed duration
1060 * Sets the minimum allowed duration for the duration mode.
1061 * Note: Has no effect in time mode
1064 hildon_time_editor_set_duration_min (HildonTimeEditor *editor,
1067 HildonTimeEditorPrivate *priv;
1069 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1070 g_return_if_fail (duration_min >= MIN_DURATION);
1072 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1075 if (! priv->duration_mode )
1078 priv->duration_min = duration_min;
1080 /* Clamp the current value to the minimum if necessary */
1081 if (priv->ticks < duration_min)
1083 hildon_time_editor_set_ticks (editor, duration_min);
1086 g_object_notify (G_OBJECT (editor), "duration_min");
1090 * hildon_time_editor_get_duration_min:
1091 * @editor: the #HildonTimeEditor widget
1093 * This function returns the smallest duration the #HildonTimeEditor
1094 * allows in the duration mode.
1096 * Returns: minimum allowed duration in seconds
1099 hildon_time_editor_get_duration_min (HildonTimeEditor *editor)
1101 HildonTimeEditorPrivate *priv;
1103 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), 0);
1105 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1108 if(! priv->duration_mode )
1111 return (priv->duration_min);
1115 * hildon_time_editor_set_duration_max:
1116 * @editor: the #HildonTimeEditor widget
1117 * @duration_max: maximum allowed duration in seconds
1119 * Sets the maximum allowed duration in seconds for the duration mode.
1120 * Note: Has no effect in time mode
1123 hildon_time_editor_set_duration_max (HildonTimeEditor *editor,
1126 HildonTimeEditorPrivate *priv;
1128 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1129 g_return_if_fail (duration_max <= MAX_DURATION);
1131 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1134 if (! priv->duration_mode)
1137 priv->duration_max = duration_max;
1139 /* Clamp the current value to the maximum if necessary */
1140 if (priv->ticks > duration_max)
1142 hildon_time_editor_set_ticks (editor, duration_max);
1145 g_object_notify (G_OBJECT (editor), "duration_max");
1149 * hildon_time_editor_get_duration_max:
1150 * @editor: the #HildonTimeEditor widget
1152 * This function returns the longest duration the #HildonTimeEditor
1153 * allows in the duration mode.
1155 * Returns: maximum allowed duration in seconds
1158 hildon_time_editor_get_duration_max (HildonTimeEditor * editor)
1160 HildonTimeEditorPrivate *priv;
1162 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), 0);
1164 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1167 if (! priv->duration_mode)
1170 return (priv->duration_max);
1174 * hildon_time_editor_set_time:
1175 * @editor: the #HildonTimeEditor widget
1180 * This function sets the time on an existing time editor. If the
1181 * time specified by the arguments is invalid, it's fixed.
1182 * The time is assumed to be in 24h format.
1185 hildon_time_editor_set_time (HildonTimeEditor *editor,
1190 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1192 hildon_time_editor_set_ticks (editor, TICKS(hours, minutes, seconds));
1196 * hildon_time_editor_get_time:
1197 * @editor: the #HildonTimeEditor widget
1202 * Gets the time of the #HildonTimeEditor widget. The time returned is
1203 * always in 24h format.
1206 hildon_time_editor_get_time (HildonTimeEditor *editor,
1211 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1213 ticks_to_time (hildon_time_editor_get_ticks (editor), hours, minutes, seconds);
1217 * hildon_time_editor_set_duration_range:
1218 * @editor: the #HildonTimeEditor widget
1219 * @min_seconds: minimum allowed time in seconds
1220 * @max_seconds: maximum allowed time in seconds
1222 * Sets the duration editor time range of the #HildonTimeEditor widget.
1225 hildon_time_editor_set_duration_range (HildonTimeEditor *editor,
1229 HildonTimeEditorPrivate *priv;
1232 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1234 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1237 /* Swap values if reversed */
1238 if (min_seconds > max_seconds)
1241 max_seconds = min_seconds;
1245 hildon_time_editor_set_duration_max (editor, max_seconds);
1246 hildon_time_editor_set_duration_min (editor, min_seconds);
1248 if (priv->duration_mode) {
1249 /* Set minimum allowed value for duration editor.
1250 FIXME: Shouldn't it be changed only if it's not in range?
1251 Would change API, so won't touch this for now. */
1252 hildon_time_editor_set_ticks (editor, min_seconds);
1257 * hildon_time_editor_get_duration_range:
1258 * @editor: the #HildonTimeEditor widget
1259 * @min_seconds: pointer to guint
1260 * @max_seconds: pointer to guint
1262 * Gets the duration editor time range of the #HildonTimeEditor widget.
1265 hildon_time_editor_get_duration_range (HildonTimeEditor *editor,
1269 HildonTimeEditorPrivate *priv;
1271 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1273 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1276 *min_seconds = priv->duration_min;
1277 *max_seconds = priv->duration_max;
1281 hildon_time_editor_check_locale (HildonTimeEditor *editor)
1283 HildonTimeEditorPrivate *priv;
1285 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1288 /* Update time separator symbols */
1289 hildon_time_editor_get_time_separators (GTK_LABEL (priv->hm_label), GTK_LABEL (priv->sec_label));
1291 /* Get AM/PM symbols. */
1292 priv->am_symbol = g_strdup (nl_langinfo (AM_STR));
1293 priv->pm_symbol = g_strdup (nl_langinfo (PM_STR));
1295 if (priv->am_symbol[0] == '\0')
1298 /* 12h clock mode. Check if AM/PM should be before or after time.
1299 %p is the AM/PM string, so we assume that if the format string
1300 begins with %p it's in the beginning, and in any other case it's
1301 in the end (although that's not necessarily the case). */
1302 if (strncmp (nl_langinfo (T_FMT_AMPM), "%p", 2) == 0)
1303 priv->ampm_pos_after = FALSE;
1309 hildon_time_editor_entry_focus_in (GtkWidget *widget,
1310 GdkEventFocus *event,
1313 gdk_threads_add_idle ((GSourceFunc) hildon_time_editor_entry_select_all,
1314 GTK_ENTRY (widget));
1320 hildon_time_editor_time_error (HildonTimeEditor *editor,
1321 HildonDateTimeError type)
1326 /* Returns negative if we didn't get value,
1327 * and should stop further validation
1330 validated_conversion (HildonTimeEditorPrivate *priv,
1335 gboolean allow_intermediate,
1337 GString *error_string)
1343 text = gtk_entry_get_text (GTK_ENTRY (field));
1345 if (text && text[0])
1347 /* Try to convert entry text to number */
1348 value = strtol (text, &tail, 10);
1350 /* Check if conversion succeeded */
1351 if ((tail[0] == 0) && !(text[0] == '-'))
1354 g_string_printf (error_string, _("ckct_ib_maximum_value"), max);
1355 priv->error_widget = field;
1356 *error_code = MAX_VALUE;
1360 if (value < min && !allow_intermediate) {
1361 g_string_printf (error_string, _("ckct_ib_minimum_value"), min);
1362 priv->error_widget = field;
1363 *error_code = MIN_VALUE;
1370 /* We'll handle failed conversions soon */
1373 if ((tail[0] == '-') || (text[0] == '-'))
1375 g_string_printf (error_string, _("ckct_ib_minimum_value"), min);
1376 priv->error_widget = field;
1377 *error_code = MIN_VALUE;
1382 else if (allow_intermediate)
1383 return -1; /* Empty field while user is still editing. No error, but
1384 cannot validate either... */
1385 else /* Empty field: show error and set value to minimum allowed */
1387 g_string_printf (error_string, _("ckct_ib_set_a_value_within_range"), min, max);
1388 priv->error_widget = field;
1389 *error_code = WITHIN_RANGE;
1393 /* Empty field and not allowed intermediated OR failed conversion */
1394 g_string_printf (error_string, _("ckct_ib_set_a_value_within_range"), min, max);
1395 priv->error_widget = field;
1396 *error_code = WITHIN_RANGE;
1401 hildon_time_editor_real_validate (HildonTimeEditor *editor,
1402 gboolean allow_intermediate,
1403 GString *error_string)
1405 HildonTimeEditorPrivate *priv;
1406 guint h, m, s, ticks;
1408 guint max_hours, min_hours, def_hours;
1409 guint max_minutes, min_minutes, def_minutes;
1410 guint max_seconds, min_seconds, def_seconds;
1413 g_assert (HILDON_IS_TIME_EDITOR (editor));
1415 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1418 /* Find limits for field based validation. */
1419 if (priv->duration_mode)
1421 ticks_to_time (priv->duration_min, &min_hours, &min_minutes, &min_seconds);
1422 ticks_to_time (priv->duration_max, &max_hours, &max_minutes, &max_seconds);
1424 if (priv->clock_24h) {
1425 max_hours = HOURS_MAX_24;
1426 min_hours = HOURS_MIN_24;
1428 max_hours = HOURS_MAX_12;
1429 min_hours = HOURS_MIN_12;
1433 hildon_time_editor_get_time (editor, &def_hours, &def_minutes, &def_seconds);
1435 /* Get time components from fields and validate them... */
1436 if (priv->show_hours) {
1437 h = validated_conversion (priv, priv->entries[ENTRY_HOURS], min_hours, max_hours, def_hours,
1438 allow_intermediate, &error_code, error_string);
1439 if (priv->error_widget == priv->entries[ENTRY_HOURS])
1440 g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, hour_errors[error_code], &r);
1441 if ((gint) h < 0) return;
1444 m = validated_conversion (priv, priv->entries[ENTRY_MINS], MINUTES_MIN, MINUTES_MAX, def_minutes,
1445 allow_intermediate, &error_code, error_string);
1446 if (priv->error_widget == priv->entries[ENTRY_MINS])
1447 g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, min_errors[error_code], &r);
1448 if ((gint) m < 0) return;
1449 if (priv->show_seconds) {
1450 s = validated_conversion (priv, priv->entries[ENTRY_SECS], SECONDS_MIN, SECONDS_MAX, def_seconds,
1451 allow_intermediate, &error_code, error_string);
1452 if (priv->error_widget == priv->entries[ENTRY_SECS])
1453 g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, sec_errors[error_code], &r);
1454 if ((gint) s < 0) return;
1458 /* Ok, we now do separate check that tick count is valid for duration mode */
1459 if (priv->duration_mode)
1461 ticks = TICKS(h, m, s);
1463 if (ticks < priv->duration_min && !allow_intermediate)
1465 g_string_printf (error_string,
1466 _("ckct_ib_min_allowed_duration_hts"),
1467 min_hours, min_minutes, min_seconds);
1468 hildon_time_editor_set_ticks (editor, priv->duration_min);
1469 priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS];
1470 g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, HILDON_DATE_TIME_ERROR_MIN_DURATION, &r);
1473 else if (ticks > priv->duration_max)
1475 g_string_printf (error_string,
1476 _("ckct_ib_max_allowed_duration_hts"),
1477 max_hours, max_minutes, max_seconds);
1478 hildon_time_editor_set_ticks (editor, priv->duration_max);
1479 priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS];
1480 g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, HILDON_DATE_TIME_ERROR_MAX_DURATION, &r);
1484 else if (! priv->clock_24h)
1485 convert_to_24h (&h, priv->am);
1487 /* The only case when we do not want to refresh the
1488 time display, is when the user is editing a value
1489 (unless the value was out of bounds and we have to fix it) */
1490 if (! allow_intermediate || priv->error_widget)
1491 hildon_time_editor_set_time (editor, h, m, s);
1494 /* Setting text to entries causes entry to recompute itself
1495 in idle callback, which remove selection. Because of this
1496 we need to do selection in idle as well. */
1498 highlight_callback (gpointer data)
1500 HildonTimeEditorPrivate *priv;
1504 g_assert (HILDON_IS_TIME_EDITOR (data));
1505 priv = HILDON_TIME_EDITOR_GET_PRIVATE (data);
1508 widget = priv->error_widget;
1509 priv->error_widget = NULL;
1511 if (GTK_IS_WIDGET (widget) == FALSE)
1514 /* Avoid revalidation because it will issue the date_error signal
1515 twice when there is an empty field. We must block the signal
1516 for all the entries because we do not know where the focus
1518 for (i = 0; i < ENTRY_COUNT; i++)
1519 g_signal_handlers_block_by_func (priv->entries[i],
1520 (gpointer) hildon_time_editor_entry_focus_out, data);
1521 gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);
1522 gtk_widget_grab_focus (widget);
1523 for (i = 0; i < ENTRY_COUNT; i++)
1524 g_signal_handlers_unblock_by_func (priv->entries[i],
1525 (gpointer) hildon_time_editor_entry_focus_out, data);
1528 priv->highlight_idle = 0;
1533 /* Update ticks from current H:M:S entries. If they're invalid, show an
1534 infoprint and update the fields unless they're empty. */
1536 hildon_time_editor_validate (HildonTimeEditor *editor,
1537 gboolean allow_intermediate)
1539 HildonTimeEditorPrivate *priv;
1540 GString *error_message;
1542 g_assert (HILDON_IS_TIME_EDITOR(editor));
1543 priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
1546 /* if there is already an error we do nothing until it will be managed by the idle */
1547 if (priv->highlight_idle == 0 && priv->skipper == FALSE)
1549 priv->skipper = TRUE;
1550 error_message = g_string_new (NULL);
1551 hildon_time_editor_real_validate (editor,
1552 allow_intermediate, error_message);
1554 if (priv->error_widget)
1556 hildon_banner_show_information (priv->error_widget, NULL,
1557 error_message->str);
1559 priv->highlight_idle = gdk_threads_add_idle (highlight_callback, editor);
1562 priv->skipper = FALSE;
1563 g_string_free (error_message, TRUE);
1567 /* on inserted text, if entry has two digits, jumps to the next field. */
1569 hildon_time_editor_inserted_text (GtkEditable *editable,
1571 gint new_text_length,
1575 HildonTimeEditor *editor;
1578 HildonTimeEditorPrivate *priv;
1580 entry = GTK_ENTRY (editable);
1581 editor = HILDON_TIME_EDITOR (user_data);
1583 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1586 /* if there is already an error we don't have to do anything */
1587 if (! priv->error_widget)
1589 value = (gchar *) gtk_entry_get_text (entry);
1591 if (strlen (value) == 2)
1593 if (GTK_WIDGET (editable) == priv->entries[ENTRY_HOURS])
1595 /* We already checked the input in changed signal, but
1596 * now we will re-check it again in focus-out we
1597 * intermediate flag set to FALSE */
1598 gtk_widget_grab_focus (priv->entries[ENTRY_MINS]);
1601 else if (GTK_WIDGET (editable) == priv->entries[ENTRY_MINS] &&
1602 GTK_WIDGET_VISIBLE (priv->entries[ENTRY_SECS]))
1605 gtk_widget_grab_focus (priv->entries[ENTRY_SECS]);
1613 hildon_time_editor_entry_focus_out (GtkWidget *widget,
1614 GdkEventFocus *event,
1617 g_assert (HILDON_IS_TIME_EDITOR (data));
1619 /* Validate the given time and update ticks. */
1620 hildon_time_editor_validate (HILDON_TIME_EDITOR (data), FALSE);
1626 hildon_time_editor_ampm_clicked (GtkWidget *widget,
1629 HildonTimeEditor *editor;
1630 HildonTimeEditorPrivate *priv;
1632 g_assert (GTK_IS_WIDGET (widget));
1633 g_assert (HILDON_IS_TIME_EDITOR (data));
1635 editor = HILDON_TIME_EDITOR (data);
1636 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1639 /* First validate the given time and update ticks. */
1640 hildon_time_editor_validate (editor, FALSE);
1642 /* Apply the AM/PM change by moving the current time by 12 hours */
1644 /* 00:00 .. 11:59 -> 12:00 .. 23:59 */
1645 hildon_time_editor_set_ticks (editor, priv->ticks + 12 * 3600);
1647 /* 12:00 .. 23:59 -> 00:00 .. 11:59 */
1648 hildon_time_editor_set_ticks (editor, priv->ticks - 12 * 3600);
1655 hildon_time_editor_icon_clicked (GtkWidget *widget,
1658 HildonTimeEditor *editor;
1661 guint h, m, s, result;
1662 HildonTimeEditorPrivate *priv;
1664 g_assert (HILDON_IS_TIME_EDITOR (data));
1666 editor = HILDON_TIME_EDITOR (data);
1667 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1670 /* icon is passive in duration editor mode */
1671 if (hildon_time_editor_get_duration_mode (editor))
1674 /* Validate and do not launch if broken */
1675 hildon_time_editor_validate (HILDON_TIME_EDITOR (data), FALSE);
1676 if (priv->error_widget != NULL)
1679 /* Launch HildonTimePicker dialog */
1680 parent = gtk_widget_get_ancestor (GTK_WIDGET (editor), GTK_TYPE_WINDOW);
1681 picker = hildon_time_picker_new (GTK_WINDOW (parent));
1683 hildon_time_editor_get_time (editor, &h, &m, &s);
1684 hildon_time_picker_set_time (HILDON_TIME_PICKER (picker), h, m);
1686 result = gtk_dialog_run (GTK_DIALOG (picker));
1689 case GTK_RESPONSE_OK:
1690 case GTK_RESPONSE_ACCEPT:
1691 /* Use the selected time */
1692 hildon_time_picker_get_time (HILDON_TIME_PICKER (picker), &h, &m);
1693 hildon_time_editor_set_time (editor, h, m, 0);
1700 gtk_widget_destroy (picker);
1705 hildon_time_editor_size_request (GtkWidget *widget,
1706 GtkRequisition *requisition)
1708 HildonTimeEditor *editor;
1709 HildonTimeEditorPrivate *priv;
1712 editor = HILDON_TIME_EDITOR (widget);
1713 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1715 /* Get frame's size */
1716 gtk_widget_size_request (priv->frame, requisition);
1718 if (GTK_WIDGET_VISIBLE (priv->iconbutton))
1720 gtk_widget_size_request (priv->iconbutton, &req);
1721 /* Reserve space for icon */
1722 requisition->width += req.width + ICON_PRESSED +
1723 HILDON_MARGIN_DEFAULT;
1726 /* FIXME: It's evil to use hardcoded TIME_EDITOR_HEIGHT. For now we'll
1727 want to force this since themes might have varying thickness values
1728 which cause the height to change. */
1729 requisition->height = TIME_EDITOR_HEIGHT;
1733 hildon_time_editor_size_allocate (GtkWidget *widget,
1734 GtkAllocation *allocation)
1736 HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE (widget);
1737 GtkAllocation alloc;
1738 GtkRequisition req, max_req;
1743 rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
1744 widget->allocation = *allocation;
1745 gtk_widget_get_child_requisition (widget, &max_req);
1747 /* Center horizontally */
1748 alloc.x = allocation->x + MAX (allocation->width - max_req.width, 0) / 2;
1749 /* Center vertically */
1750 alloc.y = allocation->y + MAX (allocation->height - max_req.height, 0) / 2;
1752 /* allocate frame */
1754 gtk_widget_get_child_requisition (priv->iconbutton, &req);
1756 gtk_widget_get_child_requisition (priv->frame, &req);
1758 alloc.width = req.width;
1759 alloc.height = max_req.height;
1761 gtk_widget_size_allocate (priv->iconbutton, &alloc);
1763 gtk_widget_size_allocate (priv->frame, &alloc);
1766 if (GTK_WIDGET_VISIBLE (priv->iconbutton)) {
1768 gtk_widget_get_child_requisition (priv->frame, &req);
1770 gtk_widget_get_child_requisition (priv->iconbutton, &req);
1772 alloc.x += alloc.width + HILDON_MARGIN_DEFAULT;
1773 alloc.width = req.width;
1776 gtk_widget_size_allocate (priv->frame, &alloc);
1778 gtk_widget_size_allocate (priv->iconbutton, &alloc);
1781 /* FIXME: ugly way to move labels up. They just don't seem move up
1782 otherwise. This is likely because we force the editor to be
1783 smaller than it otherwise would be. */
1784 alloc = priv->ampm_label->allocation;
1785 alloc.y = allocation->y - 2;
1786 alloc.height = max_req.height + 2;
1787 gtk_widget_size_allocate (priv->ampm_label, &alloc);
1789 alloc = priv->hm_label->allocation;
1790 alloc.y = allocation->y - 2;
1791 alloc.height = max_req.height + 2;
1792 gtk_widget_size_allocate (priv->hm_label, &alloc);
1794 alloc = priv->sec_label->allocation;
1795 alloc.y = allocation->y - 2;
1796 alloc.height = max_req.height + 2;
1797 gtk_widget_size_allocate (priv->sec_label, &alloc);
1801 hildon_time_editor_focus (GtkWidget *widget,
1802 GtkDirectionType direction)
1805 GtkDirectionType effective_direction;
1807 g_assert (HILDON_IS_TIME_EDITOR (widget));
1809 retval = hildon_private_composite_focus (widget, direction, &effective_direction);
1812 return GTK_WIDGET_CLASS (parent_class)->focus (widget, effective_direction);
1818 hildon_time_editor_entry_keypress (GtkEntry *entry,
1822 switch (event->keyval)
1826 hildon_time_editor_icon_clicked (GTK_WIDGET (entry), data);
1832 g_assert_not_reached ();
1836 convert_to_12h (guint *h,
1839 g_assert (0 <= *h && *h < 24);
1841 /* 00:00 to 00:59 add 12 hours */
1842 /* 01:00 to 11:59 straight to am */
1843 /* 12:00 to 12:59 straight to pm */
1844 /* 13:00 to 23:59 subtract 12 hours */
1846 if ( *h == 0 ) { *am = TRUE; *h += 12;}
1847 else if ( 1 <= *h && *h < 12 ) { *am = TRUE; }
1848 else if ( 12 <= *h && *h < 13 ) { *am = FALSE; }
1849 else { *am = FALSE; *h -= 12;}
1853 convert_to_24h (guint *h,
1856 if (*h == 12 && am) /* 12 midnight - 12:59 AM subtract 12 hours */
1861 else if (! am && 1 <= *h && *h < 12) /* 1:00 PM - 11:59 AM add 12 hours */
1868 * hildon_time_editor_set_show_hours:
1869 * @editor: The #HildonTimeEditor.
1870 * @show_hours: Enable or disable showing of hours.
1872 * This function shows or hides the hours field.
1876 hildon_time_editor_set_show_hours (HildonTimeEditor *editor,
1877 gboolean show_hours)
1879 HildonTimeEditorPrivate *priv;
1881 g_return_if_fail (HILDON_IS_TIME_EDITOR (editor));
1883 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1886 if (show_hours != priv->show_hours) {
1887 priv->show_hours = show_hours;
1889 /* show/hide hours field and its ':' label if the value changed. */
1891 gtk_widget_show (priv->entries[ENTRY_HOURS]);
1892 gtk_widget_show (priv->hm_label);
1894 gtk_widget_hide (priv->entries[ENTRY_HOURS]);
1895 gtk_widget_hide (priv->hm_label);
1898 g_object_notify (G_OBJECT (editor), "show_hours");
1903 * hildon_time_editor_get_show_hours:
1904 * @editor: the @HildonTimeEditor widget.
1906 * This function returns a boolean indicating the visibility of
1907 * hours in the @HildonTimeEditor
1909 * Return value: TRUE if hours are visible.
1913 hildon_time_editor_get_show_hours (HildonTimeEditor *editor)
1915 HildonTimeEditorPrivate *priv;
1917 g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
1918 priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
1921 return priv->show_hours;
1926 hildon_time_editor_entry_select_all (GtkWidget *widget)
1928 gtk_editable_select_region (GTK_EDITABLE (widget), 0, -1);