/*
* This file is part of hildon-libs
*
- * Copyright (C) 2005 Nokia Corporation.
+ * Copyright (C) 2005, 2006 Nokia Corporation.
*
- * Contact: Luc Pionchon <luc.pionchon@nokia.com>
+ * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
+ * as published by the Free Software Foundation; version 2.1 of
+ * the License.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
*
*/
-/* HILDON DOC
- * @shortdesc: TimeEditor is a widget for setting, getting and showing a
- * time.
- * @longdesc: The Time Editor widget is used to enter the system time
- * (hours and minutes) in the Date/Time system plugin. It is a composite
- * widget consisting of two GtkEntry widgets that are placed next to each
- * other. The leftmost GtkEntry is used to enter the hours, and it accepts
- * the values 0--23, while the rightmost GtkEntry accepts values 0--59
- * and is used to set the minutes. Between the two GtkEntries there
- * is a label displaying a colon.
- * </para><para>
- * From the usability point of view, the GtkSpinbutton widget would
- * have been a better choice than the GtkEntry widgets, but it uses
- * floating point operations and is thus not acceptable in this
- * project.
- *
- * @seealso: #HildonDateEditor
+/**
+ * SECTION:hildon-time-editor
+ * @short_description: A widget used to enter time or duration in hours, minutes,
+ * and optional seconds
+ * @see_also: #HildonTimePicker
+ *
+ * HildonTimeEditor is used to edit time or duration. Time mode is
+ * restricted to normal 24 hour cycle, but Duration mode can select any
+ * amount of time up to 99 hours. It consists of entries for hours,
+ * minutes and seconds, and pm/am indicator as well as a button which
+ * popups a #HildonTimePicker dialog.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-#include <pango/pango.h>
-#include <gtk/gtkbox.h>
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkeventbox.h>
#include <gtk/gtkentry.h>
-#include <gtk/gtk.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtkframe.h>
#include <gdk/gdkkeysyms.h>
-#include <gtk/gtkwidget.h>
#include <string.h>
#include <time.h>
-#include <stdio.h>
#include <stdlib.h>
-#include <ctype.h>
#include <langinfo.h>
#include <libintl.h>
#include <hildon-widgets/hildon-defines.h>
#include <hildon-widgets/hildon-time-editor.h>
#include <hildon-widgets/hildon-time-picker.h>
-#include <hildon-widgets/gtk-infoprint.h>
+#include <hildon-widgets/hildon-banner.h>
#include <hildon-widgets/hildon-input-mode-hint.h>
+#include <hildon-widgets/hildon-private.h>
#include "hildon-composite-widget.h"
-#include "hildon-date-editor.h"
+#include "hildon-marshalers.h"
+#include "hildon-libs-enum-types.h"
#define _(String) dgettext(PACKAGE, String)
-/* empty space on left and right side of a GtkEntry. Space needed
-is 12, we add 4 extra pixels so that the arabic locale works
-correctly. (With 12 only one digit would be shown in the entries).
-*/
-#define TIME_EDITOR_LBORDER 2
-#define TIME_EDITOR_RBORDER 1
-#define TIME_EDITOR_HEIGHT 28
-#define TIME_EDITOR_CLOCK_BORDER 6
-#define ENTRY_BORDER 2
-#define ICON_WIDTH 26
-#define ICON_HEIGHT 26
-#define ICON_PRESSED 4
-#define ICON_NAME "qgn_widg_timedit"
-#define ICON_SIZE "timepicker-size"
#define HILDON_TIME_EDITOR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
HILDON_TYPE_TIME_EDITOR, HildonTimeEditorPrivate));
+
+#define TICKS(h,m,s) ((h) * 3600 + (m) * 60 + (s))
+
+#define TIME_EDITOR_HEIGHT 30
+#define ICON_PRESSED 4
+#define ICON_NAME "qgn_widg_timedit"
+#define ICON_SIZE "timepicker-size"
#define MIN_DURATION 0
-#define MAX_DURATION (3600 * 99) + (60 * 59) + 59
+#define MAX_DURATION TICKS(99, 59, 59)
+/* Default values for properties */
#define HILDON_TIME_EDITOR_TICKS_VALUE 0
-#define HILDON_TIME_EDITOR_SHOW_SECONDS TRUE
#define HILDON_TIME_EDITOR_DURATION_MODE FALSE
#define HILDON_TIME_EDITOR_DURATION_LOWER_VALUE 0
-#define HILDON_TIME_EDITOR_TIME_LOWER_VALUE 0
-#define HILDON_TIME_EDITOR_TIME_UPPER_VALUE (3600 * 23) + (60 * 59) + 59
-#define HILDON_TIME_EDITOR_DURATION_UPPER_VALUE (3600 * 99) + (60 * 59) + 59
+#define HILDON_TIME_EDITOR_DURATION_UPPER_VALUE TICKS(99, 59, 59)
#define HOURS_MAX_24 23
#define HOURS_MAX_12 12
-#define HOURS_MIN_24 0
-#define HOURS_MIN_12 1
+#define HOURS_MIN_24 0
+#define HOURS_MIN_12 1
#define MINUTES_MAX 59
#define SECONDS_MAX 59
#define MINUTES_MIN 0
PROP_DURATION_MODE,
PROP_DURATION_MIN,
PROP_DURATION_MAX,
- PROP_SHOW_SECONDS
+ PROP_SHOW_SECONDS,
+ PROP_SHOW_HOURS
};
-typedef enum
-{
- VALIDATION_ERROR, /* should never be returned, translates as system error */
- VALIDATION_OK,
- VALIDATION_DURATION_MAX,
- VALIDATION_DURATION_MIN,
- VALIDATION_TIME_HOURS,
- VALIDATION_TIME_MINUTES,
- VALIDATION_TIME_SECONDS,
- VALIDATION_LAST
-} HildonValidation;
+/* Indices for h/m/s entries in priv->entries */
+enum {
+ ENTRY_HOURS,
+ ENTRY_MINS,
+ ENTRY_SECS,
+
+ ENTRY_COUNT
+};
+
+/* Signals */
+enum {
+ TIME_ERROR,
+ LAST_SIGNAL
+};
+
+/* Error codes categories */
+enum {
+ MAX_VALUE,
+ MIN_VALUE,
+ WITHIN_RANGE,
+ NUM_ERROR_CODES
+};
+
+static guint time_editor_signals[LAST_SIGNAL] = { 0 };
+static guint hour_errors[NUM_ERROR_CODES] = { MAX_HOURS, MIN_HOURS, EMPTY_HOURS };
+static guint min_errors[NUM_ERROR_CODES] = { MAX_MINS, MIN_MINS, EMPTY_MINS };
+static guint sec_errors[NUM_ERROR_CODES] = { MAX_SECS, MIN_SECS, EMPTY_SECS };
+
+struct _HildonTimeEditorPrivate {
+ guint ticks; /* Current duration in seconds */
+
+ gchar *am_symbol;
+ gchar *pm_symbol;
+
+ GtkWidget *eventbox; /* hold entries */
+ GtkWidget *iconbutton; /* button for icon */
+
+ GtkWidget *frame; /* frame around the entries */
+ GtkWidget *entries[ENTRY_COUNT]; /* h, m, s entries */
+ GtkWidget *hm_label; /* between hour and minute */
+ GtkWidget *sec_label; /* between minute and second */
+ GtkWidget *ampm_label; /* label for showing am or pm */
+
+ GtkWidget *error_widget; /* field to highlight in idle */
+
+
+ gboolean duration_mode; /* In HildonDurationEditor mode */
+ gboolean show_seconds; /* show seconds */
+ gboolean show_hours; /* show hours */
+
+ gboolean ampm_pos_after; /* is am/pm shown after others */
+ gboolean clock_24h; /* whether to show a 24h clock */
+ gboolean am; /* TRUE == am, FALSE == pm */
+
+ guint duration_min; /* duration editor ranges */
+ guint duration_max; /* duration editor ranges */
+
+ guint highlight_idle;
+};
/***
* Widget functions
*/
-static void
-hildon_time_editor_class_init(HildonTimeEditorClass * editor_class);
+static void hildon_time_editor_class_init (HildonTimeEditorClass *editor_class);
+static void hildon_time_editor_init (HildonTimeEditor *editor);
-static void hildon_time_editor_init(HildonTimeEditor * editor);
+static void hildon_time_editor_finalize (GObject *obj_self);
-static void hildon_time_editor_finalize(GObject * obj_self);
+static void hildon_time_editor_set_property(GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
-static void hildon_time_editor_set_property( GObject *object, guint param_id,
- const GValue *value, GParamSpec *pspec );
-static void hildon_time_editor_get_property( GObject *object, guint param_id,
- GValue *value, GParamSpec *pspec );
+static void hildon_time_editor_get_property(GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
-static void
-hildon_time_editor_forall(GtkContainer * container,
- gboolean include_internals, GtkCallback callback,
- gpointer callback_data);
+static void hildon_time_editor_forall(GtkContainer *container,
+ gboolean include_internals,
+ GtkCallback callback,
+ gpointer callback_data);
static void hildon_time_editor_destroy(GtkObject * self);
-static void hildon_time_editor_add_style(void);
-
-static void
-set_widget_allocation(GtkWidget * widget, GtkAllocation * alloc,
- GtkAllocation * allocation);
-
/***
* Signal handlers
*/
-static gboolean
-hildon_time_editor_entry_focusout(GtkWidget * widget,
- GdkEventFocus * event, gpointer data);
+static gboolean hildon_time_editor_entry_focusout(GtkWidget *widget,
+ GdkEventFocus *event,
+ gpointer data);
-static gboolean hildon_time_editor_entry_focusin(GtkWidget * widget,
- GdkEventFocus * event,
- gpointer data);
-static gboolean
-hildon_time_editor_mnemonic_activate(GtkWidget * widget,
- gboolean group_cycling);
+static gboolean hildon_time_editor_entry_focusin(GtkWidget *widget,
+ GdkEventFocus *event,
+ gpointer data);
-static gboolean
-hildon_time_editor_ampm_clicked(GtkWidget * widget, GdkEventButton * event,
- gpointer data);
-static gboolean
-hildon_time_editor_icon_clicked(GtkWidget * widget, gpointer data);
+static gboolean hildon_time_editor_time_error(HildonTimeEditor *editor,
+ HildonTimeEditorErrorType type);
-static gboolean
-hildon_time_editor_entry_clicked(GtkWidget * widget,
- GdkEventButton * event, gpointer data);
+static gboolean hildon_time_editor_ampm_clicked(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data);
-static void
-hildon_time_editor_entry_changed(GtkWidget * widget, gpointer user_data);
+static gboolean hildon_time_editor_icon_clicked(GtkWidget *widget,
+ gpointer data);
+static gboolean hildon_time_editor_entry_clicked(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data);
-static void
-hildon_time_editor_size_request(GtkWidget * widget,
- GtkRequisition * requisition);
+static void hildon_time_editor_size_request(GtkWidget *widget,
+ GtkRequisition *requisition);
-static void
-hildon_time_editor_size_allocate(GtkWidget * widget,
- GtkAllocation * allocation);
+static void hildon_time_editor_size_allocate(GtkWidget *widget,
+ GtkAllocation *allocation);
-static gboolean
-hildon_time_editor_entry_keypress(GtkWidget * widget, GdkEventKey * event,
- gpointer data);
+static gboolean hildon_time_editor_entry_keypress(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data);
/***
* Internal functions
GtkWidget * menu,
GtkCallback func,
GtkWidgetTapAndHoldFlags flags);
-
static void
-hildon_time_editor_get_max_values(HildonTimeEditor *editor,
- guint * max_hours, guint * min_hours,
- guint * max_minutes, guint * min_minutes,
- guint * max_seconds, guint * min_seconds);
-
-static void
-hildon_time_editor_validate (HildonTimeEditor *editor);
+hildon_time_editor_validate (HildonTimeEditor *editor, gboolean allow_intermediate);
-static HildonValidation
-hildon_time_editor_validate_duration (HildonTimeEditor * editor, guint ticks);
-
-static HildonValidation
-hildon_time_editor_validate_time (HildonTimeEditor * editor,
- guint hours,
- guint minutes,
- guint seconds,
- gboolean mode_24h);
+static void hildon_time_editor_set_to_current_time (HildonTimeEditor * editor);
/***
* Utility functions
*/
-static void
-convert_to_12h (guint *h, guint *m, guint *s, gboolean *am);
-static void
-convert_to_24h (guint *h, guint *m, guint *s, gboolean am);
+static void convert_to_12h (guint *h, gboolean *am);
+static void convert_to_24h (guint *h, gboolean am);
-static void ticks_to_time (guint ticks,
+static void ticks_to_time (guint ticks,
guint *hours,
guint *minutes,
- guint *seconds);
-
-
-struct _HildonTimeEditorPrivate {
- guint ticks; /* Current duration in seconds */
- gchar *am_symbol;
- gchar *pm_symbol;
-
- GtkWidget *eventbox; /* hold entries */
- GtkWidget *iconbutton; /* button for icon */
-
- GtkWidget *h_entry;
- GtkWidget *m_entry;
- GtkWidget *s_entry;
- GtkWidget *label; /* between h and m */
- GtkWidget *label2; /* between m and s */
- GtkWidget *ampm; /* label for showing am or pm */
- GtkWidget *icon; /* label for showing am or pm */
- GtkWidget *frame; /* frame around the entries */
-
- gboolean duration_mode; /* In HildonDurationEditor mode */
- gboolean show_s; /* show seconds */
- gboolean ampm_pos_after; /* is the am/pm shown after others */
- gboolean clock_24h; /* whether to show a 24h clock */
- gboolean am; /* TRUE == showing am, FALSE == pm */
- gboolean valid_value; /* If entry has an valid value */
-
- gboolean validated; /* If the current value has been validated */
+ guint *seconds);
- /* Duration editor ranges */
- guint duration_min;
- guint duration_max;
-};
+static void
+hildon_time_editor_inserted_text (GtkEditable * editable,
+ gchar * new_text,
+ gint new_text_length,
+ gint * position,
+ gpointer user_data);
GType hildon_time_editor_get_type(void)
{
if (!editor_type) {
static const GTypeInfo editor_info = {
sizeof(HildonTimeEditorClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
+ NULL, /* base_init */
+ NULL, /* base_finalize */
(GClassInitFunc) hildon_time_editor_class_init,
NULL, /* class_finalize */
- NULL, /* class_data */
+ NULL, /* class_data */
sizeof(HildonTimeEditor),
- 0, /* n_preallocs */
+ 0, /* n_preallocs */
(GInstanceInitFunc) hildon_time_editor_init,
};
editor_type = g_type_register_static(GTK_TYPE_CONTAINER,
HildonTimeEditor *editor;
HildonTimeEditorPrivate *priv;
+ g_assert(HILDON_IS_TIME_EDITOR(container));
+ g_assert(callback != NULL);
+
editor = HILDON_TIME_EDITOR(container);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- g_return_if_fail(container);
- g_return_if_fail(callback);
-
if (!include_internals)
return;
-
/* widget that are always shown */
- (*callback) (priv->h_entry, callback_data);
- (*callback) (priv->m_entry, callback_data);
(*callback) (priv->iconbutton, callback_data);
(*callback) (priv->frame, callback_data);
- (*callback) (priv->label, callback_data);
- (*callback) (priv->label2, callback_data);
- (*callback) (priv->s_entry, callback_data);
- (*callback) (priv->eventbox, callback_data);
}
static void hildon_time_editor_destroy(GtkObject * self)
priv = HILDON_TIME_EDITOR_GET_PRIVATE(self);
- if (priv->h_entry) {
- gtk_widget_unparent(priv->h_entry);
- priv->h_entry = NULL;
- }
- if (priv->m_entry) {
- gtk_widget_unparent(priv->m_entry);
- priv->m_entry = NULL;
- }
- if (priv->label) {
- gtk_widget_unparent(priv->label);
- priv->label = NULL;
- }
if (priv->iconbutton) {
gtk_widget_unparent(priv->iconbutton);
priv->iconbutton = NULL;
gtk_widget_unparent(priv->frame);
priv->frame = NULL;
}
- if (priv->eventbox) {
- gtk_widget_unparent(priv->eventbox);
- priv->eventbox = NULL;
- priv->ampm = NULL;
- }
- if (priv->label2) {
- gtk_widget_unparent(priv->label2);
- priv->label2 = NULL;
- }
- if (priv->s_entry) {
- gtk_widget_unparent(priv->s_entry);
- priv->s_entry = NULL;
- }
if (GTK_OBJECT_CLASS(parent_class)->destroy)
GTK_OBJECT_CLASS(parent_class)->destroy(self);
object_class->get_property = hildon_time_editor_get_property;
object_class->set_property = hildon_time_editor_set_property;
-
-
- widget_class->mnemonic_activate = hildon_time_editor_mnemonic_activate;
widget_class->size_request = hildon_time_editor_size_request;
widget_class->size_allocate = hildon_time_editor_size_allocate;
widget_class->tap_and_hold_setup =
object_class->finalize = hildon_time_editor_finalize;
+ editor_class->time_error = hildon_time_editor_time_error;
+
+ time_editor_signals[TIME_ERROR] =
+ g_signal_new("time-error",
+ G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HildonTimeEditorClass, time_error),
+ g_signal_accumulator_true_handled, NULL,
+ _hildon_marshal_BOOLEAN__ENUM,
+ G_TYPE_BOOLEAN, 1, HILDON_TYPE_TIME_EDITOR_ERROR_TYPE);
+
/**
* HildonTimeEditor:ticks:
*
- * TimeEditor current duration (or time since midnight) value.
+ * If editor is in duration mode, contains the duration seconds.
+ * If not, contains seconds since midnight.
*/
g_object_class_install_property( object_class, PROP_TICKS,
g_param_spec_uint("ticks",
/**
* HildonTimeEditor:show_seconds:
*
- * TimeEditor show_seconds property.
+ * Controls whether seconds are shown in the editor
*/
g_object_class_install_property( object_class, PROP_SHOW_SECONDS,
g_param_spec_boolean("show_seconds",
"Show seconds property",
"Controls whether the seconds are shown in the editor",
- HILDON_TIME_EDITOR_SHOW_SECONDS,
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE) );
+
+ /**
+ * HildonTimeEditor:show_hours:
+ *
+ * Controls whether hours are shown in the editor
+ */
+ g_object_class_install_property( object_class, PROP_SHOW_HOURS,
+ g_param_spec_boolean("show_hours",
+ "Show hours field",
+ "Controls whether the hours field is shown in the editor",
+ TRUE,
G_PARAM_READABLE | G_PARAM_WRITABLE) );
/**
* HildonTimeEditor:duration_mode:
*
- * TimeEditor duration mode indicator.
+ * Controls whether the TimeEditor is in duration mode
*/
g_object_class_install_property( object_class, PROP_DURATION_MODE,
g_param_spec_boolean("duration_mode",
/**
* HildonTimeEditor:duration_min:
*
- * TimeEditor minimum duration value.
+ * Minimum allowed duration value.
*/
g_object_class_install_property( object_class, PROP_DURATION_MIN,
g_param_spec_uint("duration_min",
"Minumum duration value",
"Smallest possible duration value",
- 0, G_MAXUINT,
+ MIN_DURATION, MAX_DURATION,
HILDON_TIME_EDITOR_DURATION_LOWER_VALUE,
G_PARAM_READABLE | G_PARAM_WRITABLE) );
/**
* HildonTimeEditor:duration_max:
*
- * TimeEditor maximum duration value.
+ * Maximum allowed duration value.
*/
g_object_class_install_property( object_class, PROP_DURATION_MAX,
g_param_spec_uint("duration_max",
0, G_MAXUINT,
HILDON_TIME_EDITOR_DURATION_UPPER_VALUE,
G_PARAM_READABLE | G_PARAM_WRITABLE) );
-
}
static
GtkWidgetTapAndHoldFlags flags)
{
HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget);
+ gint i;
- gtk_widget_tap_and_hold_setup(priv->h_entry, menu, func,
- GTK_TAP_AND_HOLD_NO_SIGNALS);
- gtk_widget_tap_and_hold_setup(priv->m_entry, menu, func,
- GTK_TAP_AND_HOLD_NO_SIGNALS);
- gtk_widget_tap_and_hold_setup(priv->s_entry, menu, func,
- GTK_TAP_AND_HOLD_NO_SIGNALS);
+ /* Forward this tap_and_hold_setup signal to all our child widgets */
+ for (i = 0; i < ENTRY_COUNT; i++)
+ {
+ gtk_widget_tap_and_hold_setup(priv->entries[i], menu, func,
+ GTK_TAP_AND_HOLD_NO_SIGNALS);
+ }
gtk_widget_tap_and_hold_setup(priv->eventbox, menu, func,
GTK_TAP_AND_HOLD_NO_SIGNALS);
gtk_widget_tap_and_hold_setup(priv->iconbutton, menu, func,
GTK_TAP_AND_HOLD_NONE);
}
+static void hildon_time_editor_entry_changed(GtkWidget *widget, gpointer data)
+{
+ g_assert(HILDON_IS_TIME_EDITOR(data));
+ hildon_time_editor_validate(HILDON_TIME_EDITOR(data), TRUE);
+}
+
static void hildon_time_editor_init(HildonTimeEditor * editor)
{
HildonTimeEditorPrivate *priv;
- guint ticks = 0;
+ GtkWidget *hbox, *icon;
+ gint i;
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
gtk_widget_push_composite_child();
- priv->ticks = 0;
- priv->show_s = FALSE;
+ /* Setup defaults and create widgets */
+ priv->ticks = 0;
+ priv->show_seconds = FALSE;
+ priv->show_hours = TRUE;
priv->ampm_pos_after = TRUE;
- priv->clock_24h = TRUE;
- priv->duration_mode = FALSE;
- priv->iconbutton = gtk_button_new();
- priv->h_entry = gtk_entry_new();
- priv->m_entry = gtk_entry_new();
- priv->s_entry = gtk_entry_new();
- priv->ampm = gtk_label_new(NULL);
- priv->label = gtk_label_new(_("Ecdg_ti_time_editor_separator"));
- priv->label2 = gtk_label_new(_("Ecdg_ti_time_editor_separator"));
- priv->icon = gtk_image_new_from_icon_name(ICON_NAME, HILDON_ICON_SIZE_26);
- priv->frame = gtk_frame_new(NULL);
- priv->eventbox = gtk_event_box_new();
- priv->valid_value = TRUE;
- priv->validated = FALSE;
-
+ priv->clock_24h = TRUE;
+ priv->duration_mode = FALSE;
+ priv->iconbutton = gtk_button_new();
+ priv->ampm_label = gtk_label_new(NULL);
+ priv->hm_label = gtk_label_new(NULL);
+ priv->sec_label = gtk_label_new(NULL);
+ priv->frame = gtk_frame_new(NULL);
+ priv->eventbox = gtk_event_box_new();
+
+ icon = gtk_image_new_from_icon_name(ICON_NAME, HILDON_ICON_SIZE_WIDG);
+ hbox = gtk_hbox_new(FALSE, 0);
+
GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW);
- GTK_WIDGET_UNSET_FLAGS(priv->iconbutton, GTK_CAN_FOCUS);
+ GTK_WIDGET_UNSET_FLAGS(priv->iconbutton, GTK_CAN_FOCUS | GTK_CAN_DEFAULT);
gtk_event_box_set_visible_window(GTK_EVENT_BOX(priv->eventbox), FALSE);
gtk_container_set_border_width(GTK_CONTAINER(priv->frame), 0);
- gtk_container_add(GTK_CONTAINER(priv->iconbutton), priv->icon);
- gtk_container_add(GTK_CONTAINER(priv->eventbox), priv->ampm);
+ gtk_container_add(GTK_CONTAINER(priv->iconbutton), icon);
+ gtk_container_add(GTK_CONTAINER(priv->eventbox), priv->ampm_label);
- gtk_entry_set_has_frame(GTK_ENTRY(priv->h_entry), FALSE);
- gtk_entry_set_has_frame(GTK_ENTRY(priv->m_entry), FALSE);
- gtk_entry_set_has_frame(GTK_ENTRY(priv->s_entry), FALSE);
+ /* Create hour, minute and second entries */
+ for (i = 0; i < ENTRY_COUNT; i++)
+ {
+ priv->entries[i] = gtk_entry_new();
+
+ /* No frames for entries, so that they all appear to be inside one long entry */
+ gtk_entry_set_has_frame(GTK_ENTRY(priv->entries[i]), FALSE);
+
+ /* Set the entries to accept only numeric characters */
+ g_object_set (priv->entries[i], "input-mode",
+ HILDON_INPUT_MODE_HINT_NUMERIC, NULL);
+
+ /* The entry fields all take exactly two characters */
+ gtk_entry_set_max_length (GTK_ENTRY(priv->entries[i]), 2);
+ gtk_entry_set_width_chars (GTK_ENTRY(priv->entries[i]), 2);
+
+ /* Connect signals */
+ g_signal_connect(priv->entries[i], "button-release-event",
+ G_CALLBACK(hildon_time_editor_entry_clicked), editor);
+ g_signal_connect(priv->entries[i], "focus-in-event",
+ G_CALLBACK(hildon_time_editor_entry_focusin), editor);
+ g_signal_connect(priv->entries[i], "focus-out-event",
+ G_CALLBACK(hildon_time_editor_entry_focusout), editor);
+ g_signal_connect(priv->entries[i], "key-press-event",
+ G_CALLBACK(hildon_time_editor_entry_keypress), editor);
+ g_signal_connect(priv->entries[i], "changed",
+ G_CALLBACK(hildon_time_editor_entry_changed), editor);
- g_object_set (G_OBJECT(priv->h_entry), "input-mode",
- HILDON_INPUT_MODE_HINT_NUMERIC, NULL);
- g_object_set (G_OBJECT(priv->m_entry), "input-mode",
- HILDON_INPUT_MODE_HINT_NUMERIC, NULL);
- g_object_set (G_OBJECT(priv->s_entry), "input-mode",
- HILDON_INPUT_MODE_HINT_NUMERIC, NULL);
-
+ /* inserted signal sets time */
+ g_signal_connect_after (G_OBJECT(priv->entries[i]), "insert_text",
+ G_CALLBACK (hildon_time_editor_inserted_text),
+ editor);
+ }
/* clicked signal for am/pm label */
g_signal_connect(G_OBJECT(priv->eventbox), "button_press_event",
g_signal_connect(G_OBJECT(priv->iconbutton), "clicked",
G_CALLBACK(hildon_time_editor_icon_clicked), editor);
- /* clicked signal for hour entry */
- g_signal_connect(G_OBJECT(priv->h_entry), "button-release-event",
- G_CALLBACK(hildon_time_editor_entry_clicked), editor);
- g_signal_connect(G_OBJECT(priv->h_entry), "focus-in-event",
- G_CALLBACK(hildon_time_editor_entry_focusin), editor);
-
- /* clicked signal for minute entry */
- g_signal_connect(G_OBJECT(priv->m_entry), "button-release-event",
- G_CALLBACK(hildon_time_editor_entry_clicked), editor);
- g_signal_connect(G_OBJECT(priv->m_entry), "focus-in-event",
- G_CALLBACK(hildon_time_editor_entry_focusin), editor);
-
- /* clicked signal for second entry */
- g_signal_connect(G_OBJECT(priv->s_entry), "button-release-event",
- G_CALLBACK(hildon_time_editor_entry_clicked), editor);
- g_signal_connect(G_OBJECT(priv->s_entry), "focus-in-event",
- G_CALLBACK(hildon_time_editor_entry_focusin), editor);
-
- /* focus out events */
- g_signal_connect(G_OBJECT(priv->h_entry), "focus-out-event",
- G_CALLBACK(hildon_time_editor_entry_focusout),
- editor);
- g_signal_connect(G_OBJECT(priv->m_entry), "focus-out-event",
- G_CALLBACK(hildon_time_editor_entry_focusout),
- editor);
- g_signal_connect(G_OBJECT(priv->s_entry), "focus-out-event",
- G_CALLBACK(hildon_time_editor_entry_focusout),
- editor);
-
- /* key press events */
- g_signal_connect(G_OBJECT(priv->h_entry), "key-press-event",
- G_CALLBACK(hildon_time_editor_entry_keypress),
- editor);
- g_signal_connect(G_OBJECT(priv->m_entry), "key-press-event",
- G_CALLBACK(hildon_time_editor_entry_keypress),
- editor);
- g_signal_connect(G_OBJECT(priv->s_entry), "key-press-event",
- G_CALLBACK(hildon_time_editor_entry_keypress),
- editor);
-
- /* changed signal sets time */
- g_signal_connect_after (G_OBJECT(priv->h_entry), "changed",
- G_CALLBACK (hildon_time_editor_entry_changed),
- editor);
- g_signal_connect_after (G_OBJECT(priv->m_entry), "changed",
- G_CALLBACK (hildon_time_editor_entry_changed),
- editor);
- g_signal_connect_after (G_OBJECT(priv->s_entry), "changed",
- G_CALLBACK (hildon_time_editor_entry_changed),
- editor);
-
+ /* Set ourself as the parent of all the widgets we created */
gtk_widget_set_parent(priv->iconbutton, GTK_WIDGET(editor));
- gtk_widget_set_parent(priv->label, GTK_WIDGET(editor));
-
- gtk_widget_set_parent(priv->label2, GTK_WIDGET(editor));
- gtk_widget_set_parent(priv->s_entry, GTK_WIDGET(editor));
- gtk_widget_set_parent(priv->eventbox, GTK_WIDGET(editor));
- gtk_widget_set_parent(priv->m_entry, GTK_WIDGET(editor));
- gtk_widget_set_parent(priv->h_entry, GTK_WIDGET(editor));
+ gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_HOURS], FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), priv->hm_label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_MINS], FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), priv->sec_label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), priv->entries[ENTRY_SECS], FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), priv->eventbox, FALSE, FALSE, 0);
- gtk_widget_show(priv->h_entry);
- gtk_widget_show(priv->m_entry);
- gtk_widget_show_all(priv->iconbutton);
- gtk_widget_show(priv->label);
+ gtk_container_add(GTK_CONTAINER(priv->frame), hbox);
+ /* Show created widgets */
gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor));
gtk_widget_show_all(priv->frame);
+ gtk_widget_show_all(priv->iconbutton);
- /* Check if we are in am/pm time locale */
+ /* Update AM/PM and time separators settings from locale */
if (!hildon_time_editor_check_locale(editor)) {
+ /* Using 12h clock */
priv->clock_24h = FALSE;
- gtk_widget_show_all(priv->eventbox);
+ } else {
+ gtk_widget_hide(priv->eventbox);
}
-
- { /* get current time */
- time_t tm;
- struct tm *stm;
-
- tm = time(NULL);
- stm = localtime(&tm);
-
- if (stm) {
- ticks = stm->tm_hour * 3600;
- ticks = ticks + stm->tm_min * 60;
- ticks = ticks + stm->tm_sec;
- }
+
+ if (!priv->show_seconds) {
+ gtk_widget_hide(priv->sec_label);
+ gtk_widget_hide(priv->entries[ENTRY_SECS]);
}
- hildon_time_editor_set_ticks (editor, ticks);
-
- gtk_entry_set_max_length(GTK_ENTRY(priv->h_entry), 2);
- gtk_entry_set_width_chars(GTK_ENTRY(priv->h_entry), 2);
- gtk_entry_set_max_length(GTK_ENTRY(priv->m_entry), 2);
- gtk_entry_set_width_chars(GTK_ENTRY(priv->m_entry), 2);
- gtk_entry_set_max_length(GTK_ENTRY(priv->s_entry), 2);
- gtk_entry_set_width_chars(GTK_ENTRY(priv->s_entry), 2);
-
- hildon_time_editor_add_style();
- gtk_widget_set_name(GTK_WIDGET(priv->iconbutton),
- "hildon-time-editor-icon");
-
+ /* set the default time to current time. */
+ hildon_time_editor_set_to_current_time (editor);
+
gtk_widget_pop_composite_child();
}
-static void hildon_time_editor_set_property (GObject *object, guint param_id,
- const GValue *value, GParamSpec *pspec)
+static void hildon_time_editor_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object);
switch (param_id)
hildon_time_editor_set_show_seconds (time_editor, g_value_get_boolean(value));
break;
+ case PROP_SHOW_HOURS:
+ hildon_time_editor_set_show_hours (time_editor, g_value_get_boolean(value));
+ break;
+
case PROP_DURATION_MODE:
hildon_time_editor_set_duration_mode (time_editor, g_value_get_boolean(value));
break;
}
}
-static void hildon_time_editor_get_property (GObject *object, guint param_id,
- GValue *value, GParamSpec *pspec)
+static void hildon_time_editor_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
{
HildonTimeEditor *time_editor = HILDON_TIME_EDITOR(object);
switch (param_id)
g_value_set_boolean (value, hildon_time_editor_get_show_seconds (time_editor));
break;
+ case PROP_SHOW_HOURS:
+ g_value_set_boolean (value, hildon_time_editor_get_show_hours (time_editor));
+ break;
+
case PROP_DURATION_MODE:
g_value_set_boolean (value, hildon_time_editor_get_duration_mode (time_editor));
break;
}
}
-
-static gboolean
-hildon_time_editor_mnemonic_activate( GtkWidget *widget,
- gboolean group_cycling)
-{
- HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget);
- gtk_widget_grab_focus( priv->h_entry );
- gtk_editable_select_region(GTK_EDITABLE(priv->h_entry), 0, 2);
- return TRUE;
-}
-
/**
* hildon_time_editor_new:
*
* This function creates a new time editor.
*
- * Return value: pointer to a new #HildonTimeEditor widget.
- **/
+ * Returns: pointer to a new #HildonTimeEditor widget
+ */
GtkWidget *hildon_time_editor_new(void)
{
{
HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(obj_self);
- if (priv->am_symbol)
- g_free(priv->am_symbol);
- if (priv->pm_symbol)
- g_free(priv->pm_symbol);
+ g_free(priv->am_symbol);
+ g_free(priv->pm_symbol);
+
+ if (priv->highlight_idle)
+ g_source_remove(priv->highlight_idle);
if (G_OBJECT_CLASS(parent_class)->finalize)
G_OBJECT_CLASS(parent_class)->finalize(obj_self);
}
-static void hildon_time_editor_add_style(void)
+/**
+ * _hildon_time_editor_get_time_separators:
+ * @editor: the #HildonTimeEditor
+ * @hm_sep_label: the label that will show the hour:minutes separator
+ * @ms_sep_label: the label that will show the minutes:seconds separator
+ *
+ * Gets hour-minute separator and minute-second separator from current
+ * locale and sets then to the labels we set as parameters. Both
+ * parameters can be NULL if you just want to assing one separator.
+ *
+ */
+void
+_hildon_time_editor_get_time_separators(GtkLabel *hm_sep_label,
+ GtkLabel *ms_sep_label)
{
- gtk_rc_parse_string(" style \"hildon-time-editor-icon\" {"
- " GtkButton::default_border = { 0, 0, 0, 0 }"
- " xthickness = 0"
- " ythickness = 0"
- " engine \"pixmap\" {"
- " image {"
- " function = BOX"
- " }"
- " }"
- " }"
- " widget \"*.hildon-time-editor-icon\""
- " style \"hildon-time-editor-icon\"");
+ gchar buffer[256];
+ gchar *separator;
+ GDate locale_test_date;
+ gchar *iter, *endp;
+
+ /* Get localized time string */
+ g_date_set_dmy(&locale_test_date, 1, 2, 1970);
+ (void) g_date_strftime(buffer, sizeof(buffer), "%X", &locale_test_date);
+
+ if (hm_sep_label != NULL)
+ {
+ /* Find h-m separator */
+ iter = buffer;
+ while (*iter && g_ascii_isdigit(*iter)) iter++;
+
+ /* Extract h-m separator*/
+ endp = iter;
+ while (*endp && !g_ascii_isdigit(*endp)) endp++;
+ separator = g_strndup(iter, endp - iter);
+ gtk_label_set_label(hm_sep_label, separator);
+ g_free(separator);
+ }
+
+ if (ms_sep_label != NULL)
+ {
+ /* Find m-s separator */
+ iter = endp;
+ while (*iter && g_ascii_isdigit(*iter)) iter++;
+
+ /* Extract m-s separator*/
+ endp = iter;
+ while (*endp && !g_ascii_isdigit(*endp)) endp++;
+ separator = g_strndup(iter, endp - iter);
+ gtk_label_set_label(ms_sep_label, separator);
+ g_free(separator);
+ }
+
}
+/* Convert ticks to H:M:S. Ticks = seconds since 00:00:00. */
static void ticks_to_time (guint ticks,
guint *hours,
guint *minutes,
guint *seconds)
{
- guint h,m,s;
-
- h = ticks / 3600;
- m = (ticks - h*3600) / 60;
- s = ticks - h*3600 - m*60;
-
- *hours = h;
- *minutes = m;
- *seconds = s;
+ guint left;
+ *hours = ticks / 3600;
+ left = ticks % 3600;
+ *minutes = left / 60;
+ *seconds = left % 60;
}
/**
* hildon_time_editor_set_ticks:
- * @self: the @HildonTimeEditor widget.
- * @ticks: The duration to set, in seconds.
+ * @editor: the #HildonTimeEditor widget
+ * @ticks: the duration to set, in seconds
*
* Sets the current duration in seconds. This means seconds from
* midnight, if not in duration mode. In case of any errors, it tries
* to fix it.
- *
- **/
+ */
void hildon_time_editor_set_ticks (HildonTimeEditor * editor,
guint ticks)
{
HildonTimeEditorPrivate *priv;
- HildonValidation validation;
- guint h = 1;
- guint m = 0;
- guint s = 0;
- gchar hours[3] = "01";
- gchar minutes[3] = "00";
- gchar seconds[3] = "00";
-
- g_return_if_fail(editor);
- g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
+ guint i, h, m, s;
+ gchar str[3];
+
+ g_assert(HILDON_IS_TIME_EDITOR(editor));
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- /* Validate the value if it is not already validated */
- if (!priv->validated) {
- if (priv->duration_mode) {
- validation = hildon_time_editor_validate_duration (editor, ticks);
- switch(validation) {
- case VALIDATION_DURATION_MIN:
- priv->ticks = priv->duration_min;
- break;
- case VALIDATION_DURATION_MAX:
- priv->ticks = priv->duration_max;
- break;
- default:
- priv->ticks = ticks;
- break;
- }
- } else {
- ticks_to_time (ticks, &h, &m, &s);
- validation = hildon_time_editor_validate_time (editor, h, m, s, TRUE);
- switch (validation) {
- case VALIDATION_TIME_HOURS:
- if (priv->clock_24h) {
- if (h > HOURS_MAX_24) {
- h = HOURS_MAX_24;
- } else if (h < HOURS_MIN_24) {
- h = HOURS_MIN_24;
- }
- } else {
- if (h > HOURS_MAX_12) {
- h = HOURS_MAX_12;
- } else if (h < HOURS_MIN_12) {
- h = HOURS_MIN_12;
- }
- }
- priv->ticks = (3600 * h) + (60 * m) + s;
- break;
- case VALIDATION_TIME_MINUTES:
- if (m > MINUTES_MAX) {
- m = MINUTES_MAX;
- } else if (m < MINUTES_MIN) {
- m = MINUTES_MIN;
- }
- break;
- case VALIDATION_TIME_SECONDS:
- if (s > SECONDS_MAX) {
- s = SECONDS_MAX;
- } else if (s < SECONDS_MIN) {
- s = SECONDS_MIN;
- }
- priv->ticks = (3600 * h) + (60 * m) + s;
- break;
- default:
- priv->ticks = ticks;
- break;
- }
- }
- } else {
- priv->ticks = ticks;
+ /* Validate ticks. If it's too low or too high, set it to
+ min/max value for the current mode. */
+ if (priv->duration_mode)
+ priv->ticks = CLAMP(ticks, priv->duration_min, priv->duration_max);
+ else {
+ /* Check that ticks value is valid. We only need to check that hours
+ don't exceed 23. */
+ ticks_to_time (ticks, &h, &m, &s);
+ if (h > HOURS_MAX_24)
+ ticks = TICKS(HOURS_MAX_24, m, s);
+
+ priv->ticks = ticks;
}
- ticks_to_time (priv->ticks, &h, &m, &s);
-
+ /* Get the time in H:M:S. */
ticks_to_time (priv->ticks, &h, &m, &s);
if (!priv->clock_24h && !priv->duration_mode)
{
- convert_to_12h (&h, &m, &s, &priv->am);
+ /* Convert 24h H:M:S values to 12h mode, and update AM/PM state */
+ convert_to_12h (&h, &priv->am);
}
- g_snprintf(hours, 3, "%02u", h);
- g_snprintf(minutes, 3, "%02u", m);
- g_snprintf(seconds, 3, "%02u", s);
- gtk_entry_set_text(GTK_ENTRY(priv->h_entry), hours);
- gtk_entry_set_text(GTK_ENTRY(priv->m_entry), minutes);
- gtk_entry_set_text(GTK_ENTRY(priv->s_entry), seconds);
-
- priv->valid_value = TRUE;
- priv->validated = FALSE;
-
- /* set current time (am/pm) */
- gtk_label_set_label(GTK_LABEL(priv->ampm), priv->am ? priv->am_symbol :
- priv->pm_symbol);
+ /* Set H:M:S values to entries. We do not want to invoke validation
+ callbacks (since they can cause new call to this function), so we
+ block signals while setting values. */
+ for (i = 0; i < ENTRY_COUNT; i++)
+ {
+ g_signal_handlers_block_by_func(priv->entries[i],
+ (gpointer) hildon_time_editor_entry_changed, editor);
+
+ g_signal_handlers_block_by_func(priv->entries[i],
+ (gpointer) hildon_time_editor_inserted_text, editor);
+
+ g_signal_handlers_block_by_func(priv->entries[i],
+ (gpointer) hildon_time_editor_entry_focusout, editor);
+
+ }
+
+ g_snprintf(str, sizeof(str), "%02u", h);
+ gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_HOURS]), str);
+
+ g_snprintf(str, sizeof(str), "%02u", m);
+ gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_MINS]), str);
+
+ g_snprintf(str, sizeof(str), "%02u", s);
+ gtk_entry_set_text(GTK_ENTRY(priv->entries[ENTRY_SECS]), str);
+
+ for (i = 0; i < ENTRY_COUNT; i++)
+ {
+ g_signal_handlers_unblock_by_func(priv->entries[i],
+ (gpointer) hildon_time_editor_entry_changed, editor);
+
+ g_signal_handlers_unblock_by_func(priv->entries[i],
+ (gpointer) hildon_time_editor_inserted_text, editor);
+
+ g_signal_handlers_unblock_by_func(priv->entries[i],
+ (gpointer) hildon_time_editor_entry_focusout, editor);
+
+ }
+
+ /* Update AM/PM label in case we're in 12h mode */
+ gtk_label_set_label(GTK_LABEL(priv->ampm_label),
+ priv->am ? priv->am_symbol : priv->pm_symbol);
g_object_notify (G_OBJECT (editor), "ticks");
}
+static void
+hildon_time_editor_set_to_current_time (HildonTimeEditor * editor)
+{
+ time_t now;
+ const struct tm *tm;
+
+ now = time(NULL);
+ tm = localtime(&now);
+
+ if (tm != NULL)
+ hildon_time_editor_set_time(editor, tm->tm_hour, tm->tm_min, tm->tm_sec);
+}
+
/**
* hildon_time_editor_get_ticks:
- * @self: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
*
* This function returns the current duration, in seconds.
* This means seconds from midnight, if not in duration mode.
*
- * Return value: Current duration in seconds.
- **/
+ * Returns: current duration in seconds
+ */
guint hildon_time_editor_get_ticks (HildonTimeEditor * editor)
{
/**
* hildon_time_editor_set_show_seconds:
- * @editor: The #HildonTimeEditor.
- * @enable: Enable or disable showing of seconds.
+ * @editor: the #HildonTimeEditor
+ * @show_seconds: enable or disable showing of seconds
*
* This function shows or hides the seconds field.
- *
- **/
+ */
void hildon_time_editor_set_show_seconds (HildonTimeEditor * editor,
gboolean show_seconds)
{
HildonTimeEditorPrivate *priv;
- g_return_if_fail(editor);
+ g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- if (!priv->show_s && show_seconds) {
- priv->show_s = TRUE;
-
- gtk_widget_show(priv->s_entry);
- gtk_widget_show(priv->label2);
-
- } else if (priv->show_s && !show_seconds) {
-
- gtk_widget_hide(priv->s_entry);
- gtk_widget_hide(priv->label2);
+ if (show_seconds != priv->show_seconds) {
+ priv->show_seconds = show_seconds;
- priv->show_s = FALSE;
- } else
- return;
-
- gtk_widget_queue_resize(GTK_WIDGET(editor));
+ /* show/hide seconds field and its ':' label if the value changed. */
+ if (show_seconds) {
+ gtk_widget_show(priv->entries[ENTRY_SECS]);
+ gtk_widget_show(priv->sec_label);
+ } else {
+ gtk_widget_hide(priv->entries[ENTRY_SECS]);
+ gtk_widget_hide(priv->sec_label);
+ }
- g_object_notify (G_OBJECT (editor), "show_seconds");
+ g_object_notify (G_OBJECT (editor), "show_seconds");
+ }
}
/**
* hildon_time_editor_get_show_seconds:
- * @self: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
*
* This function returns a boolean indicating the visibility of
- * seconds in the @HildonTimeEditor
+ * seconds in the #HildonTimeEditor
*
- * Return value: TRUE if the seconds are visible.
- **/
+ * Returns: TRUE if the seconds are visible
+ */
gboolean hildon_time_editor_get_show_seconds (HildonTimeEditor * editor)
{
g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- return (priv->show_s);
+ return (priv->show_seconds);
}
/**
* hildon_time_editor_set_duration_mode:
- * @editor: The #HildonTimeEditor.
- * @enable: Enable or disable duration editor mode
+ * @editor: the #HildonTimeEditor
+ * @duration_mode: enable or disable duration editor mode
*
* This function sets the duration editor mode in which the maximum hours
- * is 99 and the #HildonTimePicker is disabled.
- *
- **/
+ * is 99.
+ */
void hildon_time_editor_set_duration_mode (HildonTimeEditor * editor,
gboolean duration_mode)
{
HildonTimeEditorPrivate *priv;
- g_return_if_fail(editor);
+ g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- /* switch to duration editor mode */
- if (duration_mode && !priv->duration_mode) {
+ if (duration_mode != priv->duration_mode) {
priv->duration_mode = duration_mode;
- hildon_time_editor_set_duration_range(editor, MIN_DURATION,
- MAX_DURATION);
- if (!priv->clock_24h)
- gtk_widget_hide(GTK_WIDGET(priv->ampm));
-
- gtk_widget_hide(GTK_WIDGET(priv->eventbox));
- gtk_widget_hide(GTK_WIDGET(priv->icon));
-
- /* Show seconds for duration editor */
- hildon_time_editor_set_show_seconds(editor, TRUE);
- }
- /* switch to time editor mode */
- else if (!duration_mode && priv->duration_mode) {
- guint ticks;
- time_t tm;
- struct tm *stm;
-
- priv->duration_mode = duration_mode;
-
- if (!priv->clock_24h)
- gtk_widget_show(GTK_WIDGET(priv->ampm));
-
- gtk_widget_show(GTK_WIDGET(priv->eventbox));
- gtk_widget_show(GTK_WIDGET(priv->icon));
-
+ if (duration_mode) {
+ /* FIXME: Why do we reset the duration range here?
+ Would change API, so won't touch this for now. */
+ hildon_time_editor_set_duration_range(editor, MIN_DURATION,
+ MAX_DURATION);
+ /* There's no AM/PM label or time picker icon in duration mode.
+ Make sure they're hidden. */
+ gtk_widget_hide(GTK_WIDGET(priv->ampm_label));
+ gtk_widget_hide(GTK_WIDGET(priv->eventbox));
+ gtk_widget_hide(GTK_WIDGET(priv->iconbutton));
+ /* Duration mode has seconds by default. */
+ hildon_time_editor_set_show_seconds(editor, TRUE);
+ } else {
+ /* Make sure AM/PM label and time picker icons are visible if needed */
+ if (!priv->clock_24h)
+ gtk_widget_show(GTK_WIDGET(priv->ampm_label));
- /* Put the ticks to match current time, anything set in the
- * duration mode is bound to be invalid or useless in time mode
- */
-
- tm = time(NULL);
- stm = localtime(&tm);
+ gtk_widget_show(GTK_WIDGET(priv->eventbox));
+ gtk_widget_show(GTK_WIDGET(priv->iconbutton));
- ticks = HILDON_TIME_EDITOR_TIME_LOWER_VALUE;
-
- if (stm) {
- ticks = stm->tm_hour * 3600;
- ticks = ticks + stm->tm_min * 60;
- ticks = ticks + stm->tm_sec;
+ /* Reset the ticks to current time. Anything set in duration mode
+ * is bound to be invalid or useless in time mode.
+ */
+ hildon_time_editor_set_to_current_time (editor);
}
-
- hildon_time_editor_set_ticks (editor, ticks);
-
+
+ g_object_notify (G_OBJECT (editor), "duration_mode");
}
- gtk_widget_queue_resize(GTK_WIDGET(editor));
-
- g_object_notify (G_OBJECT (editor), "duration_mode");
}
/**
* hildon_time_editor_get_duration_mode:
- * @self: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
*
- * This function returns a boolean indicating whether the @HildonTimeEditor
+ * This function returns a boolean indicating whether the #HildonTimeEditor
* is in the duration mode.
*
- * Return value: TRUE if the @HildonTimeEditor is in duration mode.
- **/
+ * Returns: TRUE if the #HildonTimeEditor is in duration mode
+ */
gboolean hildon_time_editor_get_duration_mode (HildonTimeEditor * editor)
{
/**
* hildon_time_editor_set_duration_min:
- * @self: the @HildonTimeEditor widget.
- * @duration_min: Mimimum allowed duration.
+ * @editor: the #HildonTimeEditor widget
+ * @duration_min: mimimum allowed duration
*
* Sets the minimum allowed duration for the duration mode.
* Note: Has no effect in time mode
- **/
+ */
void hildon_time_editor_set_duration_min (HildonTimeEditor * editor,
guint duration_min)
{
HildonTimeEditorPrivate *priv;
- g_return_if_fail(editor);
g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
-
g_return_if_fail(duration_min >= MIN_DURATION);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
/**
* hildon_time_editor_get_duration_min:
- * @self: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
*
- * This function returns the smallest duration the @HildonTimeEditor
+ * This function returns the smallest duration the #HildonTimeEditor
* allows in the duration mode.
*
- * Return value: Mimimum allowed duration in seconds.
- **/
+ * Returns: minimum allowed duration in seconds
+ */
guint hildon_time_editor_get_duration_min (HildonTimeEditor * editor)
{
HildonTimeEditorPrivate *priv;
- g_return_val_if_fail(editor, 0);
g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
/**
* hildon_time_editor_set_duration_max:
- * @self: the @HildonTimeEditor widget.
- * @duration_min: Maximum allowed duration in seconds.
+ * @editor: the #HildonTimeEditor widget
+ * @duration_max: maximum allowed duration in seconds
*
* Sets the maximum allowed duration in seconds for the duration mode.
* Note: Has no effect in time mode
- *
- **/
+ */
void hildon_time_editor_set_duration_max (HildonTimeEditor * editor,
guint duration_max)
{
HildonTimeEditorPrivate *priv;
- g_return_if_fail(editor);
g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
-
g_return_if_fail(duration_max <= MAX_DURATION);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
/**
* hildon_time_editor_get_duration_max:
- * @self: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
*
- * This function returns the longest duration the @HildonTimeEditor
+ * This function returns the longest duration the #HildonTimeEditor
* allows in the duration mode.
*
- * Return value: Maximum allowed duration in seconds.
- **/
+ * Returns: maximum allowed duration in seconds
+ */
guint hildon_time_editor_get_duration_max (HildonTimeEditor * editor)
{
HildonTimeEditorPrivate *priv;
- g_return_val_if_fail(editor, 0);
g_return_val_if_fail(HILDON_IS_TIME_EDITOR(editor), 0);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
/**
* hildon_time_editor_set_time:
- * @editor: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
* @hours: hours
* @minutes: minutes
* @seconds: seconds
*
* This function sets the time on an existing time editor. If the
- * time specified by the arguments is invalid, the function returns
- * without doing anything else. The time is assumed to be in 24h format.
- *
- **/
+ * time specified by the arguments is invalid, it's fixed.
+ * The time is assumed to be in 24h format.
+ */
void hildon_time_editor_set_time(HildonTimeEditor * editor, guint hours,
guint minutes, guint seconds)
{
g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
- hildon_time_editor_set_ticks (editor, hours * 3600 + minutes * 60 + seconds);
-
+ hildon_time_editor_set_ticks (editor, TICKS(hours, minutes, seconds));
}
/**
* hildon_time_editor_get_time:
- * @editor: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
* @hours: hours
* @minutes: minutes
* @seconds: seconds
*
- * Gets the time of the @HildonTimeEditor widget. The time returned is
+ * Gets the time of the #HildonTimeEditor widget. The time returned is
* always in 24h format.
- **/
+ */
void hildon_time_editor_get_time(HildonTimeEditor * editor,
guint * hours,
{
HildonTimeEditorPrivate *priv;
- g_return_if_fail(editor);
g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
ticks_to_time (hildon_time_editor_get_ticks (editor),
hours, minutes, seconds);
-
}
/**
* hildon_time_editor_set_duration_range:
- * @editor: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
* @min_seconds: minimum allowed time in seconds
* @max_seconds: maximum allowed time in seconds
*
- * Sets the duration editor time range of the @HildonTimeEditor widget.
- **/
+ * Sets the duration editor time range of the #HildonTimeEditor widget.
+ */
void hildon_time_editor_set_duration_range(HildonTimeEditor * editor,
guint min_seconds,
HildonTimeEditorPrivate *priv;
guint tmp;
- g_return_if_fail(editor);
g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
hildon_time_editor_set_duration_min (editor, min_seconds);
if (priv->duration_mode) {
- /* Set minimum allowed value for duration editor */
+ /* Set minimum allowed value for duration editor.
+ FIXME: Shouldn't it be changed only if it's not in range?
+ Would change API, so won't touch this for now. */
hildon_time_editor_set_ticks(editor, min_seconds);
}
}
/**
* hildon_time_editor_get_duration_range:
- * @editor: the @HildonTimeEditor widget.
+ * @editor: the #HildonTimeEditor widget
* @min_seconds: pointer to guint
* @max_seconds: pointer to guint
*
- * Gets the duration editor time range of the @HildonTimeEditor widget.
- **/
+ * Gets the duration editor time range of the #HildonTimeEditor widget.
+ */
void hildon_time_editor_get_duration_range(HildonTimeEditor * editor,
guint * min_seconds,
{
HildonTimeEditorPrivate *priv;
- g_return_if_fail(editor);
g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
static gboolean hildon_time_editor_check_locale(HildonTimeEditor * editor)
{
HildonTimeEditorPrivate *priv;
- gchar *t_fm;
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+ /* Update time separator symbols */
+ _hildon_time_editor_get_time_separators(GTK_LABEL(priv->hm_label), GTK_LABEL(priv->sec_label));
+
+ /* Get AM/PM symbols. */
priv->am_symbol = g_strdup(nl_langinfo(AM_STR));
priv->pm_symbol = g_strdup(nl_langinfo(PM_STR));
- if (!strcmp(priv->am_symbol, ""))
+ if (priv->am_symbol[0] == '\0')
return TRUE;
else {
- t_fm = g_strdup(nl_langinfo(T_FMT_AMPM));
- /* Check what format am/pm time should be */
- if (!strncmp(t_fm, "%p", 2))
+ /* 12h clock mode. Check if AM/PM should be before or after time.
+ %p is the AM/PM string, so we assume that if the format string
+ begins with %p it's in the beginning, and in any other case it's
+ in the end (although that's not necessarily the case). */
+ if (strncmp(nl_langinfo(T_FMT_AMPM), "%p", 2) == 0)
priv->ampm_pos_after = FALSE;
- priv->am_symbol =
- g_ascii_strdown((const gchar *) priv->am_symbol, -1);
- priv->pm_symbol =
- g_ascii_strdown((const gchar *) priv->pm_symbol, -1);
- g_free(t_fm);
return FALSE;
}
}
GdkEventFocus * event,
gpointer data)
{
+ /* If we were trying to move away from a field with invalid value,
+ we get moved back to it. Here we want to select the text in the field.
+ The !button check checks that the entry wasn't focused with a mouse
+ click.
+
+ The selection happens temporarily if we got here with left/right
+ keys, but it gets immediately unselected within same call due to some
+ inner entry/clipboard magic. */
if (!GTK_ENTRY(widget)->button)
gtk_editable_select_region(GTK_EDITABLE(widget), 0, 2);
return FALSE;
}
-
-void
-hildon_time_editor_validate (HildonTimeEditor *editor)
+static gboolean
+hildon_time_editor_time_error(HildonTimeEditor *editor,
+ HildonTimeEditorErrorType type)
{
- guint max_hours = 0;
- guint min_hours = 0;
- guint max_minutes = 0;
- guint min_minutes = 0;
- guint max_seconds = 0;
- guint min_seconds = 0;
-
- HildonTimeEditorPrivate *priv;
- HildonValidation validation;
+ return TRUE;
+}
- GtkWindow *window;
- guint h,m,s;
+/* Returns negative if we didn't get value,
+ * and should stop further validation
+ */
+static gint validated_conversion(HildonTimeEditorPrivate *priv,
+ GtkWidget *field,
+ gint min,
+ gint max,
+ gboolean allow_intermediate,
+ guint *error_code,
+ GString *error_string)
+{
+ const gchar *text;
+ gchar *tail;
+ long value;
- priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+ text = gtk_entry_get_text(GTK_ENTRY(field));
- window = GTK_WINDOW (gtk_widget_get_ancestor (GTK_WIDGET (editor),
- GTK_TYPE_WINDOW));
+ if (text && text[0])
+ {
+ /* Try to convert entry text to number */
+ value = strtol(text, &tail, 10);
+
+ /* Check if conversion succeeded */
+ if (tail[0] == 0)
+ {
+ if (value > max) {
+ g_string_printf(error_string, _("ckct_ib_maximum_value"), max);
+ priv->error_widget = field;
+ *error_code = MAX_VALUE;
+ return max;
+ }
+ if (value < min && !allow_intermediate) {
+ g_string_printf(error_string, _("ckct_ib_minimum_value"), min);
+ priv->error_widget = field;
+ *error_code = MIN_VALUE;
+ return min;
+ }
- hildon_time_editor_get_max_values(editor,
- &max_hours, &min_hours,
- &max_minutes, &min_minutes,
- &max_seconds, &min_seconds);
-
- /* No empty values thank you */
- if (strlen(GTK_ENTRY(priv->h_entry)->text) == 0)
+ return value;
+ }
+ /* We'll handle failed conversions soon */
+ }
+ else if (allow_intermediate)
+ return -1; /* Empty field while user is still editing. No error, but
+ cannot validate either... */
+ else /* Empty field: show error and set value to minimum allowed */
{
- if (!priv->duration_mode)
- {
- if (priv->clock_24h)
- {
- gtk_infoprintf(window,
- _("Ckct_ib_set_a_value_within_range"),
- HOURS_MIN_24, HOURS_MAX_24);
- }
- else
- {
- gtk_infoprintf(window,
- _("Ckct_ib_set_a_value_within_range"),
- HOURS_MIN_12, HOURS_MAX_12);
- }
- }
- else
- {
- gtk_infoprintf(window,
- _("Ckct_ib_set_a_value_within_range"),
- min_hours, max_hours);
- }
- hildon_time_editor_set_ticks (editor, priv->ticks);
- gtk_widget_grab_focus (priv->h_entry);
+ g_string_printf(error_string, _("ckct_ib_set_a_value_within_range"), min, max);
+ priv->error_widget = field;
+ *error_code = WITHIN_RANGE;
+ return min;
}
- else if (strlen(GTK_ENTRY(priv->m_entry)->text) == 0)
- {
- if (!priv->duration_mode)
- {
- gtk_infoprintf(window,
- _("Ckct_ib_set_a_value_within_range"),
- MINUTES_MIN, MINUTES_MAX);
- }
- else
- {
- gtk_infoprintf(window,
- _("Ckct_ib_set_a_value_within_range"),
- min_minutes, max_minutes);
- }
- hildon_time_editor_set_ticks (editor, priv->ticks);
- gtk_widget_grab_focus (priv->m_entry);
- }
- else if (strlen(GTK_ENTRY(priv->s_entry)->text) == 0)
+
+ /* Empty field and not allowed intermediated OR failed conversion */
+ g_string_printf(error_string, _("ckct_ib_set_a_value_within_range"), min, max);
+ priv->error_widget = field;
+ *error_code = WITHIN_RANGE;
+ return -1;
+}
+
+static void
+hildon_time_editor_real_validate(HildonTimeEditor *editor,
+ gboolean allow_intermediate, GString *error_string)
+{
+ HildonTimeEditorPrivate *priv;
+ guint h, m, s, ticks;
+ guint error_code;
+ guint max_hours, min_hours, max_minutes, min_minutes, max_seconds, min_seconds;
+ gboolean r;
+
+ g_assert(HILDON_IS_TIME_EDITOR(editor));
+
+ priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+
+ /* Find limits for field based validation. */
+ if (priv->duration_mode)
+ {
+ ticks_to_time(priv->duration_min, &min_hours, &min_minutes, &min_seconds);
+ ticks_to_time(priv->duration_max, &max_hours, &max_minutes, &max_seconds);
+ } else {
+ if (priv->clock_24h) {
+ max_hours = HOURS_MAX_24;
+ min_hours = HOURS_MIN_24;
+ } else {
+ max_hours = HOURS_MAX_12;
+ min_hours = HOURS_MIN_12;
+ }
+ }
+
+ /* Get time components from fields and validate them... */
+ if (priv->show_hours) {
+ h = validated_conversion(priv, priv->entries[ENTRY_HOURS], min_hours, max_hours,
+ allow_intermediate, &error_code, error_string);
+ if (priv->error_widget == priv->entries[ENTRY_HOURS])
+ g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, hour_errors[error_code], &r);
+ if ((gint) h < 0) return;
+ }
+ else h = 0;
+ m = validated_conversion(priv, priv->entries[ENTRY_MINS], MINUTES_MIN, MINUTES_MAX,
+ allow_intermediate, &error_code, error_string);
+ if (priv->error_widget == priv->entries[ENTRY_MINS])
+ g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, min_errors[error_code], &r);
+ if ((gint) m < 0) return;
+ if (priv->show_seconds) {
+ s = validated_conversion(priv, priv->entries[ENTRY_SECS], SECONDS_MIN, SECONDS_MAX,
+ allow_intermediate, &error_code, error_string);
+ if (priv->error_widget == priv->entries[ENTRY_SECS])
+ g_signal_emit (editor, time_editor_signals [TIME_ERROR], 0, sec_errors[error_code], &r);
+ if ((gint) s < 0) return;
+ }
+ else s = 0;
+
+ /* Ok, we now do separate check that tick count is valid for duration mode */
+ if (priv->duration_mode)
+ {
+ ticks = TICKS(h, m, s);
+
+ if (ticks < priv->duration_min && !allow_intermediate)
+ {
+ g_string_printf(error_string,
+ _("ckct_ib_min_allowed_duration_hts"),
+ min_hours, min_minutes, min_seconds);
+ hildon_time_editor_set_ticks (editor, priv->duration_min);
+ priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS];
+ g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, MIN_DUR, &r);
+ return;
+ }
+ else if (ticks > priv->duration_max)
+ {
+ g_string_printf(error_string,
+ _("ckct_ib_max_allowed_duration_hts"),
+ max_hours, max_minutes, max_seconds);
+ hildon_time_editor_set_ticks (editor, priv->duration_max);
+ priv->error_widget = priv->show_hours ? priv->entries[ENTRY_HOURS] : priv->entries[ENTRY_MINS];
+ g_signal_emit (editor, time_editor_signals[TIME_ERROR], 0, MAX_DUR, &r);
+ return;
+ }
+ }
+ else if (!priv->clock_24h)
+ convert_to_24h (&h, priv->am);
+
+ /* The only case when we do not want to refresh the
+ time display, is when the user is editing a value
+ (unless the value was out of bounds and we have to fix it) */
+ if (!allow_intermediate || priv->error_widget)
+ hildon_time_editor_set_time (editor, h, m, s);
+}
+
+/* Setting text to entries causes entry to recompute itself
+ in idle callback, which remove selection. Because of this
+ we need to do selection in idle as well. */
+static gboolean highlight_callback(gpointer data)
+{
+ HildonTimeEditorPrivate *priv;
+ GtkWidget *widget;
+ gint i;
+
+ GDK_THREADS_ENTER ();
+
+ g_assert(HILDON_IS_TIME_EDITOR(data));
+
+ priv = HILDON_TIME_EDITOR_GET_PRIVATE(data);
+ widget = priv->error_widget;
+ priv->error_widget = NULL;
+ priv->highlight_idle = 0;
+
+ g_assert(GTK_IS_ENTRY(widget));
+
+ /* Avoid revalidation because it will issue the date_error signal
+ twice when there is an empty field. We must block the signal
+ for all the entries because we do not know where the focus
+ comes from */
+ for (i = 0; i < ENTRY_COUNT; i++)
+ g_signal_handlers_block_by_func(priv->entries[i],
+ (gpointer) hildon_time_editor_entry_focusout, data);
+ gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
+ gtk_widget_grab_focus(widget);
+ for (i = 0; i < ENTRY_COUNT; i++)
+ g_signal_handlers_unblock_by_func(priv->entries[i],
+ (gpointer) hildon_time_editor_entry_focusout, data);
+
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
+}
+
+/* Update ticks from current H:M:S entries. If they're invalid, show an
+ infoprint and update the fields unless they're empty. */
+static void
+hildon_time_editor_validate (HildonTimeEditor *editor, gboolean allow_intermediate)
+{
+ HildonTimeEditorPrivate *priv;
+ GString *error_message;
+
+ g_assert(HILDON_IS_TIME_EDITOR(editor));
+
+ priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+
+ /* if there is already an error we do nothing until it will be managed by the idle */
+ if (priv->highlight_idle == 0)
{
- if (!priv->duration_mode)
- {
- gtk_infoprintf(window,
- _("Ckct_ib_set_a_value_within_range"),
- SECONDS_MIN, SECONDS_MAX);
- }
- else
+ error_message = g_string_new(NULL);
+ hildon_time_editor_real_validate(editor,
+ allow_intermediate, error_message);
+
+ if (priv->error_widget)
{
- gtk_infoprintf(window,
- _("Ckct_ib_set_a_value_within_range"),
- min_seconds, max_seconds);
+ hildon_banner_show_information(priv->error_widget, NULL,
+ error_message->str);
+
+ priv->highlight_idle = g_idle_add(highlight_callback, editor);
}
- hildon_time_editor_set_ticks (editor, priv->ticks);
- gtk_widget_grab_focus (priv->s_entry);
+
+ g_string_free(error_message, TRUE);
}
- /* Do the validation dance! */
- else
- {
+}
+
+/* on inserted text, if entry has two digits, jumps to the next field. */
+static void
+hildon_time_editor_inserted_text (GtkEditable * editable,
+ gchar * new_text,
+ gint new_text_length,
+ gint * position,
+ gpointer user_data)
+{
+ HildonTimeEditor *editor;
+ GtkEntry *entry;
+ gchar *value;
+ HildonTimeEditorPrivate *priv;
+
+ entry = GTK_ENTRY(editable);
+ editor = HILDON_TIME_EDITOR(user_data);
+
+ priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- h = (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->h_entry)));
- m = (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry)));
- s = (guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->s_entry)));
+ /* if there is already an error we don't have to do anything */
+ if (!priv->error_widget)
+ {
+
+ value = (gchar *) gtk_entry_get_text(entry);
+
+ if (strlen(value) == 2)
+ {
+ HildonTimeEditorPrivate *priv;
- if (priv->duration_mode)
- {
- validation = hildon_time_editor_validate_duration (editor,
- h*3600 + m*60 + s);
-
- switch (validation)
- {
- case VALIDATION_DURATION_MIN:
- gtk_infoprintf(window,
- _("Ckct_ib_min_allowed_duration_hts"),
- min_hours, min_minutes, min_seconds);
- hildon_time_editor_set_ticks (editor, priv->duration_min);
- break;
- case VALIDATION_DURATION_MAX:
- gtk_infoprintf(window,
- _("Ckct_ib_max_allowed_duration_hts"),
- max_hours, max_minutes, max_seconds);
- hildon_time_editor_set_ticks (editor, priv->duration_max);
- break;
- default:
- hildon_time_editor_set_ticks (editor, h*3600 + m*60 + s);
- break;
- }
- }
- else
- {
- validation = hildon_time_editor_validate_time (editor, h, m, s, priv->clock_24h);
- switch (validation)
- {
- case VALIDATION_TIME_HOURS:
- if (priv->clock_24h)
- {
- if (h > HOURS_MAX_24)
- {
- gtk_infoprintf(window,
- _("Ckct_ib_maximum_value"),
- HOURS_MAX_24);
- h = HOURS_MAX_24;
- }
- else
- {
- gtk_infoprintf(window,
- _("Ckct_ib_minimum_value"),
- HOURS_MIN_24);
- h = HOURS_MIN_24;
- }
- }
- else
- {
- if (h > HOURS_MAX_12)
- {
- gtk_infoprintf(window,
- _("Ckct_ib_maximum_value"),
- HOURS_MAX_12);
- h = HOURS_MAX_12;
- }
- else
- {
- gtk_infoprintf(window,
- _("Ckct_ib_minimum_value"),
- HOURS_MIN_12);
- h = HOURS_MIN_12;
- }
- }
- if (!priv->clock_24h)
- convert_to_24h (&h, &m, &s, priv->am);
- hildon_time_editor_set_time (editor, h, m, s);
- gtk_widget_grab_focus (priv->h_entry);
- gtk_editable_select_region(GTK_EDITABLE(priv->h_entry), 0, 2);
- break;
- case VALIDATION_TIME_MINUTES:
- if (m > MINUTES_MAX)
- {
- gtk_infoprintf(window,
- _("Ckct_ib_maximum_value"),
- MINUTES_MAX);
- m = MINUTES_MAX;
- }
- else
- {
- gtk_infoprintf(window,
- _("Ckct_ib_minimum_value"),
- MINUTES_MIN);
- m = MINUTES_MIN;
- }
- if (!priv->clock_24h)
- convert_to_24h (&h, &m, &s, priv->am);
- hildon_time_editor_set_time (editor, h, m, s);
- gtk_widget_grab_focus (priv->m_entry);
- gtk_editable_select_region(GTK_EDITABLE(priv->m_entry), 0, 2);
- break;
- case VALIDATION_TIME_SECONDS:
- if (s > SECONDS_MAX)
- {
- gtk_infoprintf(window,
- _("Ckct_ib_maximum_value"),
- SECONDS_MAX);
- s = SECONDS_MAX;
- }
- else
- {
- gtk_infoprintf(window,
- _("Ckct_ib_minimum_value"),
- SECONDS_MIN);
- s = SECONDS_MIN;
- }
- if (!priv->clock_24h)
- convert_to_24h (&h, &m, &s, priv->am);
- hildon_time_editor_set_time (editor, h, m, s);
- gtk_widget_grab_focus (priv->s_entry);
- gtk_editable_select_region(GTK_EDITABLE(priv->s_entry), 0, 2);
- break;
- default:
- if (!priv->clock_24h)
- {
- convert_to_24h (&h, &m, &s, priv->am);
- }
- hildon_time_editor_set_time (editor, h, m, s);
- break;
- }
- }
-
- }
+ priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+
+ if (GTK_WIDGET(editable) == priv->entries[ENTRY_HOURS])
+ {
+ /* we don't want a focusout signal with this grab_focus
+ because the validation was already done during the
+ changed signal */
+ g_signal_handlers_block_by_func(priv->entries[ENTRY_HOURS],
+ (gpointer) hildon_time_editor_entry_focusout, editor);
+
+ gtk_widget_grab_focus(priv->entries[ENTRY_MINS]);
+ *position = -1;
+
+ g_signal_handlers_unblock_by_func(priv->entries[ENTRY_HOURS],
+ (gpointer) hildon_time_editor_entry_focusout, editor);
+
+ }
+ else if (GTK_WIDGET(editable) == priv->entries[ENTRY_MINS] &&
+ GTK_WIDGET_VISIBLE (priv->entries[ENTRY_SECS]))
+ {
+ g_signal_handlers_block_by_func(priv->entries[ENTRY_MINS],
+ (gpointer) hildon_time_editor_entry_focusout, editor);
+
+ gtk_widget_grab_focus(priv->entries[ENTRY_SECS]);
+ *position = -1;
+
+ g_signal_handlers_unblock_by_func(priv->entries[ENTRY_MINS],
+ (gpointer) hildon_time_editor_entry_focusout, editor);
+
+ }
+ }
+ }
}
static gboolean hildon_time_editor_entry_focusout(GtkWidget * widget,
GdkEventFocus * event,
gpointer data)
{
- HildonTimeEditor *editor;
+ g_assert(HILDON_IS_TIME_EDITOR(data));
- editor = HILDON_TIME_EDITOR(data);
-
- hildon_time_editor_validate (editor);
+ /* Validate the given time and update ticks. */
+ hildon_time_editor_validate(HILDON_TIME_EDITOR(data), FALSE);
return FALSE;
}
GdkEventButton * event, gpointer data)
{
HildonTimeEditor *editor;
- HildonTimeEditorPrivate *priv = NULL;
-
- g_return_val_if_fail(widget, FALSE);
- g_return_val_if_fail(data, FALSE);
+ HildonTimeEditorPrivate *priv;
+ g_assert(GTK_IS_WIDGET(widget));
+ g_assert(HILDON_IS_TIME_EDITOR(data));
editor = HILDON_TIME_EDITOR(data);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- /* validate to set the time and get infoprints
- * if the user was editing the value
- */
- hildon_time_editor_validate (editor);
+ /* First validate the given time and update ticks. */
+ hildon_time_editor_validate (editor, FALSE);
+
+ /* Apply the AM/PM change by moving the current time by 12 hours */
if (priv->am) {
- if (priv->ticks >= (12*3600))
- {
- hildon_time_editor_set_ticks (editor, priv->ticks - 12*3600);
- } else
- {
- hildon_time_editor_set_ticks (editor, priv->ticks + 12*3600);
- }
+ /* 00:00 .. 11:59 -> 12:00 .. 23:59 */
+ hildon_time_editor_set_ticks (editor, priv->ticks + 12*3600);
} else {
+ /* 12:00 .. 23:59 -> 00:00 .. 11:59 */
hildon_time_editor_set_ticks (editor, priv->ticks - 12*3600);
}
return FALSE;
hildon_time_editor_icon_clicked(GtkWidget * widget, gpointer data)
{
HildonTimeEditor *editor;
- HildonTimeEditorPrivate *priv;
GtkWidget *picker;
GtkWidget *parent;
guint h, m, s, result;
- g_return_val_if_fail(widget, FALSE);
- g_return_val_if_fail(data, FALSE);
+ g_assert(HILDON_IS_TIME_EDITOR(data));
editor = HILDON_TIME_EDITOR(data);
- priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
/* icon is passive in duration editor mode */
- if (priv->duration_mode)
+ if (hildon_time_editor_get_duration_mode(editor))
return FALSE;
+ /* Launch HildonTimePicker dialog */
parent = gtk_widget_get_ancestor(GTK_WIDGET(editor), GTK_TYPE_WINDOW);
picker = hildon_time_picker_new(GTK_WINDOW(parent));
switch (result) {
case GTK_RESPONSE_OK:
case GTK_RESPONSE_ACCEPT:
+ /* Use the selected time */
hildon_time_picker_get_time(HILDON_TIME_PICKER(picker), &h, &m);
hildon_time_editor_set_time(editor, h, m, 0);
break;
priv = HILDON_TIME_EDITOR_GET_PRIVATE (editor);
/* If the focus has been grabbed back before the "clicked"
- * signal gets processed, don't highlight the text
+ * signal gets processed, don't highlight the text.
+ * This happens when input in one H:M:S field is invalid and we're
+ * trying to move to another field. The focus moves back to the invalid
+ * field.
*/
if (gtk_widget_is_focus (widget))
gtk_editable_select_region(GTK_EDITABLE(widget), 0, 2);
editor = HILDON_TIME_EDITOR(widget);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- gtk_widget_size_request(priv->frame, &req);
- *requisition = req;
-
- requisition->width = TIME_EDITOR_LBORDER + TIME_EDITOR_RBORDER;
-
- gtk_widget_size_request(priv->h_entry, &req);
- requisition->width += req.width;
-
- gtk_widget_size_request(priv->m_entry, &req);
- requisition->width += req.width;
+ /* Get frame's size */
+ gtk_widget_size_request(priv->frame, requisition);
- gtk_widget_size_request(priv->label, &req);
- requisition->width += req.width;
-
- if (priv->iconbutton && GTK_WIDGET_VISIBLE(priv->iconbutton))
+ if (GTK_WIDGET_VISIBLE(priv->iconbutton))
{
gtk_widget_size_request(priv->iconbutton, &req);
- requisition->width += ICON_WIDTH + ICON_PRESSED +
- TIME_EDITOR_CLOCK_BORDER;
- }
-
- if (priv->show_s) {
- gtk_widget_size_request(priv->s_entry, &req);
- requisition->width += req.width;
-
- gtk_widget_size_request(priv->label2, &req);
- requisition->width += req.width;
- }
-
- if (!priv->clock_24h && !priv->duration_mode) {
- gtk_widget_size_request(priv->eventbox, &req);
- requisition->width += req.width + 4;
+ /* Reserve space for icon */
+ requisition->width += req.width + ICON_PRESSED +
+ HILDON_MARGIN_DEFAULT;
}
- requisition->height = TIME_EDITOR_HEIGHT + widget->style->ythickness * 2;
-}
-
-static void set_widget_allocation(GtkWidget * widget,
- GtkAllocation * alloc,
- GtkAllocation * allocation)
-{
- GtkRequisition child_requisition;
-
- gtk_widget_get_child_requisition(widget, &child_requisition);
-
- if (allocation->width + allocation->x >
- alloc->x + child_requisition.width)
- alloc->width = child_requisition.width;
- else {
- alloc->width = allocation->width - (alloc->x - allocation->x);
- if (alloc->width < 0)
- alloc->width = 0;
- }
- gtk_widget_size_allocate(widget, alloc);
- alloc->x += alloc->width;
+ /* FIXME: It's evil to use hardcoded TIME_EDITOR_HEIGHT. For now we'll
+ want to force this since themes might have varying thickness values
+ which cause the height to change. */
+ requisition->height = TIME_EDITOR_HEIGHT;
}
static void hildon_time_editor_size_allocate(GtkWidget * widget,
GtkAllocation * allocation)
{
- HildonTimeEditor *editor;
- HildonTimeEditorPrivate *priv;
+ HildonTimeEditorPrivate *priv = HILDON_TIME_EDITOR_GET_PRIVATE(widget);
GtkAllocation alloc;
- GtkAllocation child_alloc;
- GtkRequisition child_requisition;
- gint mod_w = 0;
-
- editor = HILDON_TIME_EDITOR(widget);
- priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+ GtkRequisition req, max_req;
widget->allocation = *allocation;
+ gtk_widget_get_child_requisition(widget, &max_req);
- /*Init start values*/
- alloc.y = widget->allocation.y + widget->style->ythickness;
-
- if (widget->allocation.height > (TIME_EDITOR_HEIGHT +
- widget->style->ythickness * 2)) {
- alloc.height = TIME_EDITOR_HEIGHT;
- alloc.y +=
- (widget->allocation.height - TIME_EDITOR_HEIGHT) / 2;
- } else
- alloc.height =
- widget->allocation.height - widget->style->ythickness * 2;
-
- if (alloc.height < 0)
- alloc.height = 0;
-
- gtk_widget_get_child_requisition(widget, &child_requisition);
- if (allocation->width > child_requisition.width) {
- mod_w = (allocation->width - child_requisition.width) / 2;
- alloc.x = allocation->x + mod_w;
- } else
- alloc.x = allocation->x;
-
-
- /** frame **/
- if (priv->frame && GTK_WIDGET_VISIBLE(priv->frame))
- {
- alloc.width = child_requisition.width -
- TIME_EDITOR_CLOCK_BORDER - ICON_WIDTH - ICON_PRESSED;
- gtk_widget_size_allocate(priv->frame, &alloc);
- }
-
- /** icon **/
- if (priv->iconbutton && GTK_WIDGET_VISIBLE(priv->iconbutton)) {
- gtk_widget_get_child_requisition(priv->iconbutton,
- &child_requisition);
-
- child_alloc.x = alloc.x + alloc.width + TIME_EDITOR_CLOCK_BORDER;
-
- if(alloc.height > ICON_HEIGHT)
- child_alloc.y = alloc.y + (alloc.height - ICON_HEIGHT) / 2 -1;
- else
- child_alloc.y = alloc.y;
- child_alloc.height = ICON_HEIGHT + ICON_PRESSED / 2;
- child_alloc.width = ICON_WIDTH + ICON_PRESSED;
- gtk_widget_size_allocate(priv->iconbutton, &child_alloc);
- }
-
- /* allocation of child widgets */
- child_alloc.x = alloc.x + TIME_EDITOR_LBORDER;
- child_alloc.y = alloc.y;
- child_alloc.height = TIME_EDITOR_HEIGHT;
- child_alloc.width = -1;
-
- /* am/pm label (when first) */
- if (!priv->duration_mode) {
- if (!priv->clock_24h && !priv->ampm_pos_after)
- {
- set_widget_allocation(priv->eventbox, &child_alloc,
- &widget->allocation);
- }
- }
+ /* Center horizontally */
+ alloc.x = allocation->x + MAX(allocation->width - max_req.width, 0) / 2;
+ /* Center vertically */
+ alloc.y = allocation->y + MAX(allocation->height - max_req.height, 0) / 2;
+
+ /* allocate frame */
+ gtk_widget_get_child_requisition(priv->frame, &req);
- /* hours */
- if (priv->h_entry && GTK_WIDGET_VISIBLE(priv->h_entry))
- {
- child_alloc.y += ENTRY_BORDER;
- child_alloc.height -= ENTRY_BORDER * 2;
- set_widget_allocation(priv->h_entry, &child_alloc,
- &widget->allocation);
- child_alloc.y -= ENTRY_BORDER;
- child_alloc.height += ENTRY_BORDER * 2;
- }
+ alloc.width = req.width;
+ alloc.height = max_req.height;
+ gtk_widget_size_allocate(priv->frame, &alloc);
- /* first separator label */
- if (priv->label && GTK_WIDGET_VISIBLE(priv->label))
- {
- /* We'll have to subtract the ythickness from the labels
- * allocation or it'll be there twice
- */
- child_alloc.y -= widget->style->ythickness;
- set_widget_allocation(priv->label, &child_alloc,
- &widget->allocation);
- child_alloc.y += widget->style->ythickness;
- }
- /* minutes */
- if (priv->m_entry && GTK_WIDGET_VISIBLE(priv->m_entry))
- {
- /* Entries have a little different allocation requirements
- * so we'll have to accommodate. This is done per entry
- * so that the "running" width value of the allocation isn't lost
- * FIXME: Rearrange this code so it could be done just once
- */
- child_alloc.y += ENTRY_BORDER;
- child_alloc.height -= ENTRY_BORDER * 2;
- set_widget_allocation(priv->m_entry, &child_alloc,
- &widget->allocation);
- child_alloc.y -= ENTRY_BORDER;
- child_alloc.height += ENTRY_BORDER * 2;
- }
-
- if (priv->show_s) {
- /* second separator label */
- if (priv->label2)
- {
- child_alloc.y -= widget->style->ythickness;
- set_widget_allocation(priv->label2, &child_alloc,
- &widget->allocation);
- child_alloc.y += widget->style->ythickness;
- }
+ /* allocate icon */
+ if (GTK_WIDGET_VISIBLE(priv->iconbutton)) {
+ gtk_widget_get_child_requisition(priv->iconbutton, &req);
- /* seconds */
- if (priv->s_entry)
- {
- child_alloc.y += ENTRY_BORDER;
- child_alloc.height -= ENTRY_BORDER * 2;
- set_widget_allocation(priv->s_entry, &child_alloc,
- &widget->allocation);
- child_alloc.y -= ENTRY_BORDER;
- child_alloc.height += ENTRY_BORDER * 2;
- }
+ alloc.x += alloc.width + HILDON_MARGIN_DEFAULT;
+ alloc.width = req.width;
+ gtk_widget_size_allocate(priv->iconbutton, &alloc);
}
- /* am/pm label (when last) */
- if (!priv->duration_mode) {
- if (!priv->clock_24h && priv->ampm_pos_after)
- {
- child_alloc.y -= widget->style->ythickness;
- set_widget_allocation(priv->eventbox, &child_alloc,
- &widget->allocation);
- child_alloc.y += widget->style->ythickness;
- }
- }
+ /* FIXME: ugly way to move labels up. They just don't seem move up
+ otherwise. This is likely because we force the editor to be
+ smaller than it otherwise would be. */
+ alloc = priv->ampm_label->allocation;
+ alloc.y = allocation->y - 2;
+ alloc.height = max_req.height + 2;
+ gtk_widget_size_allocate(priv->ampm_label, &alloc);
+
+ alloc = priv->hm_label->allocation;
+ alloc.y = allocation->y - 2;
+ alloc.height = max_req.height + 2;
+ gtk_widget_size_allocate(priv->hm_label, &alloc);
+
+ alloc = priv->sec_label->allocation;
+ alloc.y = allocation->y - 2;
+ alloc.height = max_req.height + 2;
+ gtk_widget_size_allocate(priv->sec_label, &alloc);
}
static gboolean hildon_time_editor_entry_keypress(GtkWidget * widget,
{
HildonTimeEditor *editor;
HildonTimeEditorPrivate *priv;
- gint pos;
+ gint cursor_pos;
- g_return_val_if_fail(widget, FALSE);
- g_return_val_if_fail(event, FALSE);
- g_return_val_if_fail(data, FALSE);
+ g_assert(GTK_IS_ENTRY(widget));
+ g_assert(event != NULL);
+ g_assert(HILDON_IS_TIME_EDITOR(data));
editor = HILDON_TIME_EDITOR(data);
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+ cursor_pos = gtk_editable_get_position(GTK_EDITABLE(widget));
- pos = gtk_editable_get_position(GTK_EDITABLE(widget));
-
- if (event->keyval == GDK_Return) {
- /* Check that we have correct values in entries */
- hildon_time_editor_validate (editor);
- _gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), TRUE);
- hildon_time_editor_icon_clicked(widget, data);
- _gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), FALSE);
- return TRUE;
- }
-
- if (event->keyval == GDK_KP_Enter)
- return FALSE;
-
- /* We don't want wrap */
- if (event->keyval == GDK_KP_Left || event->keyval == GDK_Left) {
- if (pos == 0 && widget == priv->h_entry) {
+ switch (event->keyval)
+ {
+ case GDK_Return:
+ /* Return key popups up time picker dialog. Visually it looks as if
+ the time picker icon was clicked. Before opening the time picker
+ the fields are first validated and fixed. */
+ hildon_time_editor_validate (editor, FALSE);
+ hildon_gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), TRUE);
+ hildon_time_editor_icon_clicked(widget, data);
+ hildon_gtk_button_set_depressed(GTK_BUTTON(priv->iconbutton), FALSE);
return TRUE;
- }
- }
- if (event->keyval == GDK_KP_Right || event->keyval == GDK_Right) {
- if (pos >= strlen(GTK_ENTRY(widget)->text)) {
- if ((widget == priv->m_entry
- && !GTK_WIDGET_REALIZED(priv->s_entry))
- || (widget == priv->s_entry
- && GTK_WIDGET_REALIZED(priv->s_entry))) {
+ case GDK_Left:
+ /* left arrow pressed in the entry. If we are on first position, try to
+ move to the previous field. */
+ if (cursor_pos == 0) {
+ (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_LEFT);
return TRUE;
}
- }
- }
-
- /* numeric key pressed */
- if (event->keyval >= GDK_0 && event->keyval <= GDK_9) {
- GtkWidgetClass *c = GTK_WIDGET_GET_CLASS(widget);
-
- c->key_press_event(widget, event);
-
- if (GTK_IS_ENTRY (widget))
- {
- if (strlen (gtk_entry_get_text (GTK_ENTRY (widget))) == 2)
- {
- hildon_time_editor_validate (editor);
- }
- }
-
- return TRUE;
- }
- /* tab pressed in hour entry */
- else if (widget == priv->h_entry && (event->keyval == GDK_Tab ||
- event->keyval == GDK_KP_Tab)) {
- gtk_widget_grab_focus(priv->m_entry);
- return TRUE;
- }
- /* tab pressed in minute entry */
- else if (widget == priv->m_entry && (event->keyval == GDK_Tab ||
- event->keyval == GDK_KP_Tab)) {
- if (priv->show_s)
- gtk_widget_grab_focus(priv->s_entry);
- else
- gtk_widget_grab_focus(priv->h_entry);
- return TRUE;
- }
- /* tab pressed in second entry */
- else if (widget == priv->s_entry && (event->keyval == GDK_Tab ||
- event->keyval == GDK_KP_Tab)) {
- gtk_widget_grab_focus(priv->h_entry);
- return TRUE;
- }
- /* left tab pressed in second entry */
- else if (widget == priv->s_entry &&
- event->keyval == GDK_ISO_Left_Tab) {
- gtk_widget_grab_focus(priv->m_entry);
- return TRUE;
- }
- /* left tab pressed in minute entry */
- else if (widget == priv->m_entry &&
- event->keyval == GDK_ISO_Left_Tab) {
- gtk_widget_grab_focus(priv->h_entry);
- return TRUE;
- }
- /* left tab pressed in hour entry */
- else if (widget == priv->h_entry &&
- event->keyval == GDK_ISO_Left_Tab) {
- if (priv->show_s)
- gtk_widget_grab_focus(priv->s_entry);
- else
- gtk_widget_grab_focus(priv->m_entry);
- return TRUE;
- }
- /* right arrow pressed in hour entry */
- else if (widget == priv->h_entry &&
- (event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
- && pos >= GTK_ENTRY(priv->h_entry)->text_length) {
- gtk_widget_grab_focus(priv->m_entry);
- gtk_editable_set_position(GTK_EDITABLE(priv->m_entry), 0);
- return TRUE;
- }
- /* right arrow pressed in minute entry */
- else if (widget == priv->m_entry &&
- (event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
- && pos >= GTK_ENTRY(priv->m_entry)->text_length) {
- if (priv->show_s) {
- gtk_widget_grab_focus(priv->s_entry);
- gtk_editable_set_position(GTK_EDITABLE(priv->s_entry), 0);
- } else {
- gtk_widget_grab_focus(priv->h_entry);
- gtk_editable_set_position(GTK_EDITABLE(priv->h_entry), 0);
- }
- return TRUE;
- }
- /* right arrow pressed in second entry */
- else if (widget == priv->s_entry &&
- (event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
- && pos >= GTK_ENTRY(priv->s_entry)->text_length) {
- gtk_widget_grab_focus(priv->h_entry);
- gtk_editable_set_position(GTK_EDITABLE(priv->h_entry), 0);
- return TRUE;
- }
- /* left arrow key pressed in hour entry */
- else if (widget == priv->h_entry &&
- (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) &&
- pos <= 0) {
- if (priv->show_s) {
- gtk_widget_grab_focus(priv->s_entry);
- gtk_editable_set_position(GTK_EDITABLE(priv->s_entry), -1);
- } else {
- gtk_widget_grab_focus(priv->m_entry);
- gtk_editable_set_position(GTK_EDITABLE(priv->m_entry), -1);
- }
- return TRUE;
- }
- /* left arrow key pressed in minute entry */
- else if (widget == priv->m_entry &&
- (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) &&
- pos <= 0) {
- gtk_widget_grab_focus(priv->h_entry);
- gtk_editable_set_position(GTK_EDITABLE(priv->h_entry), -1);
- return TRUE;
- }
- /* left arrow key pressed in seconds entry */
- else if (widget == priv->s_entry &&
- (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) &&
- pos <= 0) {
- gtk_widget_grab_focus(priv->m_entry);
- gtk_editable_set_position(GTK_EDITABLE(priv->m_entry), -1);
- return TRUE;
- }
- /* pass other arrow key presses and backspace and del onwards */
- else if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left ||
- event->keyval == GDK_Right || event->keyval == GDK_KP_Right ||
- event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
- event->keyval == GDK_Down || event->keyval == GDK_KP_Down ||
- event->keyval == GDK_BackSpace || event->keyval == GDK_Delete
- || event->keyval == GDK_KP_Delete)
- return FALSE; /* pass the keypress on */
-
- /* ingore other keys */
- return TRUE;
-}
-
-static HildonValidation
-hildon_time_editor_validate_duration (HildonTimeEditor * editor, guint ticks)
-{
- HildonTimeEditorPrivate *priv;
-
- g_return_val_if_fail (editor, VALIDATION_ERROR);
+ break;
- priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
-
- if (ticks > priv->duration_max)
- return VALIDATION_DURATION_MAX;
+ case GDK_Right:
+ /* right arrow pressed in the entry. If we are on last position, try to
+ move to the next field. */
+ if (cursor_pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1)) {
+ (void) gtk_widget_child_focus(GTK_WIDGET(editor), GTK_DIR_RIGHT);
+ return TRUE;
+ }
+ break;
- if (ticks < priv->duration_min)
- return VALIDATION_DURATION_MIN;
+ default:
+ break;
+ };
- return (VALIDATION_OK);
+ return FALSE;
}
+/***
+ * Utility functions
+ */
-static HildonValidation
-hildon_time_editor_validate_time (HildonTimeEditor * editor,
- guint hours,
- guint minutes,
- guint seconds,
- gboolean mode_24h)
+static void
+convert_to_12h (guint *h, gboolean *am)
{
- HildonTimeEditorPrivate *priv;
-
- g_return_val_if_fail (editor, VALIDATION_ERROR);
-
- priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
-
- priv->validated = FALSE;
+ g_assert(0 <= *h && *h < 24);
- if (mode_24h) {
- if (hours < HOURS_MIN_24 || hours > HOURS_MAX_24)
- return VALIDATION_TIME_HOURS;
- } else {
- if (hours < HOURS_MIN_12 || hours > HOURS_MAX_12)
- return VALIDATION_TIME_HOURS;
- }
-
- if (minutes < MINUTES_MIN || minutes > MINUTES_MAX)
- return VALIDATION_TIME_MINUTES;
-
- if (seconds < SECONDS_MIN || seconds > SECONDS_MAX)
- return VALIDATION_TIME_SECONDS;
+ /* 00:00 to 00:59 add 12 hours */
+ /* 01:00 to 11:59 straight to am */
+ /* 12:00 to 12:59 straight to pm */
+ /* 13:00 to 23:59 subtract 12 hours */
- priv->validated = TRUE;
- return (VALIDATION_OK);
+ if ( *h == 0 ) { *am = TRUE; *h += 12;}
+ else if ( 1 <= *h && *h < 12 ) { *am = TRUE; }
+ else if ( 12 <= *h && *h < 13 ) { *am = FALSE; }
+ else { *am = FALSE; *h -= 12;}
}
static void
-hildon_time_editor_entry_changed(GtkWidget * widget, gpointer user_data)
+convert_to_24h (guint *h, gboolean am)
{
- HildonTimeEditor *editor;
-
- editor = HILDON_TIME_EDITOR(user_data);
-
-/* hildon_time_editor_validate (editor);*/
+ if (*h == 12 && am) /* 12 midnight - 12:59 AM subtract 12 hours */
+ {
+ *h -= 12;
+ }
+ else if (!am && 1 <= *h && *h < 12) /* 1:00 PM - 11:59 AM add 12 hours */
+ {
+ *h += 12;
+ }
}
-/* NOTE: This function is mostly broken for the duration mode */
-static void
-hildon_time_editor_get_max_values(HildonTimeEditor *editor,
- guint * pmax_hours, guint * pmin_hours,
- guint * pmax_minutes, guint * pmin_minutes,
- guint * pmax_seconds, guint * pmin_seconds)
+/**
+ * hildon_time_editor_set_show_hours:
+ * @editor: The #HildonTimeEditor.
+ * @enable: Enable or disable showing of hours.
+ *
+ * This function shows or hides the hours field.
+ *
+ * Since: 0.12.4
+ **/
+void hildon_time_editor_set_show_hours(HildonTimeEditor * editor,
+ gboolean show_hours)
{
- guint max_hours;
- guint max_minutes;
- guint max_seconds;
- guint min_hours;
- guint min_minutes;
- guint min_seconds;
-
HildonTimeEditorPrivate *priv;
+ g_return_if_fail(HILDON_IS_TIME_EDITOR(editor));
+
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- max_hours = priv->duration_max / 3600;
- max_minutes = (priv->duration_max - (max_hours * 3600)) / 60;
- max_seconds = priv->duration_max - (max_hours * 3600) - (max_minutes * 60);
- min_hours = priv->duration_min / 3600;
- min_minutes = (priv->duration_min - (min_hours * 3600)) / 60;
- min_seconds = priv->duration_min - (min_hours * 3600) - (min_minutes * 60);
+ if (show_hours != priv->show_hours) {
+ priv->show_hours = show_hours;
- /* Determine max and min values for duration mode */
- if (priv->duration_mode)
- {
- /* if the widget has focus, the value could be out of range, so
- use the calculated values then
- */
- if (!gtk_widget_is_focus (priv->h_entry))
- {
- if ((guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->h_entry))) < max_hours)
- {
- max_minutes = 59;
- max_seconds = 59;
- }
- if ((guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->h_entry))) > min_hours)
- {
- min_minutes = 0;
- min_seconds = 0;
- }
+ /* show/hide hours field and its ':' label if the value changed. */
+ if (show_hours) {
+ gtk_widget_show(priv->entries[ENTRY_HOURS]);
+ gtk_widget_show(priv->hm_label);
+ } else {
+ gtk_widget_hide(priv->entries[ENTRY_HOURS]);
+ gtk_widget_hide(priv->hm_label);
}
- if (!gtk_widget_is_focus (priv->m_entry))
- {
- if ((guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry))) < max_minutes)
- {
- max_seconds = 59;
- }
- if ((guint) atoi(gtk_entry_get_text(GTK_ENTRY(priv->m_entry))) > min_minutes)
- {
- min_seconds = 0;
- }
- }
- }
- /* 24h clock mode */
- else if (priv->clock_24h) {
- max_hours = 23;
- max_seconds = max_minutes = 59;
- min_seconds = min_minutes = min_hours = 0;
- }
- /* 12h clock mode */
- else {
- max_hours = 12;
- min_hours = 1;
- max_seconds = max_minutes = 59;
- min_seconds = min_minutes = 0;
+
+ g_object_notify (G_OBJECT (editor), "show_hours");
}
-
- *pmax_hours = max_hours;
- *pmax_minutes = max_minutes;
- *pmax_seconds = max_seconds;
- *pmin_hours = min_hours;
- *pmin_minutes = min_minutes;
- *pmin_seconds = min_seconds;
-
}
-/***
- * Utility functions
- */
-
-static void
-convert_to_12h (guint *h, guint *m, guint *s, gboolean *am)
+/**
+ * hildon_time_editor_get_show_hours:
+ * @self: the @HildonTimeEditor widget.
+ *
+ * This function returns a boolean indicating the visibility of
+ * hours in the @HildonTimeEditor
+ *
+ * Return value: TRUE if hours are visible.
+ *
+ * Since: 0.12.4-1
+ **/
+gboolean hildon_time_editor_get_show_hours(HildonTimeEditor *editor)
{
- /* 0000 to 0059
- * add 12 hours
- */
- if (*h == 0)
- {
- *h += 12;
- *am = TRUE;
- }
- /* 0100 to 1159
- * straight to am
- */
- else if (*h >= 1 && *h < 12)
- {
- *am = TRUE;
- }
- /* 1200 to 1259
- * straight to pm
- */
- else if (*h >= 12 && *h < 13)
- {
- *am = FALSE;
- }
- /* 1300 to 23:59
- * subtract 12 hours
- */
- else if (*h >= 13 && *h < 24 )
- {
- *h -= 12;
- *am = FALSE;
- }
-}
+ HildonTimeEditorPrivate *priv;
-static void
-convert_to_24h (guint *h, guint *m, guint *s, gboolean am)
-{
- /* 12 midnight - 12:59 AM
- * subtract 12 hours
- */
- if (*h == 12 && am)
- {
- *h -= 12;
- }
- /* 1:00 PM - 11:59 AM
- * add 12 hours
- */
- else if (!am && *h >= 1 && *h < 12)
- {
- *h += 12;
- }
+ g_return_val_if_fail (HILDON_IS_TIME_EDITOR (editor), FALSE);
+ priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+
+ return priv->show_hours;
}
/***
* Deprecated functions
*/
-
-#ifndef HILDON_DISABLE_DEPRECATED
-
/**
* hildon_time_editor_show_seconds:
- * @editor: The #HildonTimeEditor.
- * @enable: Enable or disable showing of seconds.
- *
- * This function is deprecated, use @hildon_time_editor_set_show_seconds instead.
+ * @editor: the #HildonTimeEditor
+ * @enable: enable or disable showing of seconds
*
- **/
+ * This function is deprecated,
+ * use #hildon_time_editor_set_show_seconds instead.
+ */
void hildon_time_editor_show_seconds(HildonTimeEditor * editor,
gboolean enable)
{
}
/**
* hildon_time_editor_enable_duration_mode:
- * @editor: The #HildonTimeEditor.
- * @enable: Enable or disable duration editor mode
+ * @editor: the #HildonTimeEditor
+ * @enable: enable or disable duration editor mode
*
- * This function is deprecated, use @hildon_time_editor_set_duration_mode instead.
- *
- **/
+ * This function is deprecated,
+ * use #hildon_time_editor_set_duration_mode instead.
+ */
void hildon_time_editor_enable_duration_mode(HildonTimeEditor * editor,
gboolean enable)
{
hildon_time_editor_set_duration_mode (editor, enable);
}
-
-#endif /* HILDON_DISABLE_DEPRECATED */