/*
* 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
#include <hildon-widgets/hildon-input-mode-hint.h>
#include <hildon-widgets/hildon-private.h>
#include "hildon-composite-widget.h"
+#include "hildon-marshalers.h"
+#include "hildon-libs-enum-types.h"
#define _(String) dgettext(PACKAGE, String)
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 */
GdkEventFocus *event,
gpointer data);
+static gboolean hildon_time_editor_time_error(HildonTimeEditor *editor,
+ HildonTimeEditorErrorType type);
+
static gboolean hildon_time_editor_ampm_clicked(GtkWidget *widget,
GdkEventButton *event,
gpointer data);
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:
*
{
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);
{
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),
return FALSE;
}
+static gboolean
+hildon_time_editor_time_error(HildonTimeEditor *editor,
+ HildonTimeEditorErrorType type)
+{
+ return TRUE;
+}
+
/* Returns negative if we didn't get value,
* and should stop further validation
*/
gint min,
gint max,
gboolean allow_intermediate,
+ guint *error_code,
GString *error_string)
{
const gchar *text;
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;
}
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 */
+ {
+ g_string_printf(error_string, _("ckct_ib_set_a_value_within_range"), min, max);
+ priv->error_widget = field;
+ *error_code = WITHIN_RANGE;
+ return min;
+ }
/* 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;
}
{
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));
/* 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_string);
+ 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_string);
+ 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_string);
+ 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;
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)
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;
}
}
{
HildonTimeEditorPrivate *priv;
GtkWidget *widget;
+ gint i;
GDK_THREADS_ENTER ();
g_assert(GTK_IS_ENTRY(widget));
- /* Grabbing focus can cause re-validation, priv->error widget
- can be set to something else, including NULL */
+ /* 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;
}
g_assert(HILDON_IS_TIME_EDITOR(editor));
priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- priv->error_widget = NULL;
-
- error_message = g_string_new(NULL);
- hildon_time_editor_real_validate(editor,
- allow_intermediate, error_message);
- if (priv->error_widget) {
- hildon_banner_show_information(priv->error_widget, NULL,
- error_message->str);
- if (priv->highlight_idle == 0)
+ /* if there is already an error we do nothing until it will be managed by the idle */
+ if (priv->highlight_idle == 0)
+ {
+ error_message = g_string_new(NULL);
+ hildon_time_editor_real_validate(editor,
+ allow_intermediate, error_message);
+
+ if (priv->error_widget)
+ {
+ hildon_banner_show_information(priv->error_widget, NULL,
+ error_message->str);
+
priv->highlight_idle = g_idle_add(highlight_callback, editor);
- }
- g_string_free(error_message, TRUE);
+ }
+
+ g_string_free(error_message, TRUE);
+ }
}
/* on inserted text, if entry has two digits, jumps to the next field. */
HildonTimeEditor *editor;
GtkEntry *entry;
gchar *value;
-
+ HildonTimeEditorPrivate *priv;
+
entry = GTK_ENTRY(editable);
editor = HILDON_TIME_EDITOR(user_data);
-
- value = (gchar *) gtk_entry_get_text(entry);
-
- if (strlen(value) == 2)
+
+ priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+
+ /* if there is already an error we don't have to do anything */
+ if (!priv->error_widget)
{
- HildonTimeEditorPrivate *priv;
+
+ value = (gchar *) gtk_entry_get_text(entry);
+
+ if (strlen(value) == 2)
+ {
+ HildonTimeEditorPrivate *priv;
- priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
+ priv = HILDON_TIME_EDITOR_GET_PRIVATE(editor);
- if (GTK_WIDGET(editable) == priv->entries[ENTRY_HOURS])
- {
- gtk_widget_grab_focus(priv->entries[ENTRY_MINS]);
- *position = -1;
- }
- else if (GTK_WIDGET(editable) == priv->entries[ENTRY_MINS])
- {
- gtk_widget_grab_focus(priv->entries[ENTRY_SECS]);
- *position = -1;
+ 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);
+
+ }
}
}
}