#include <stdlib.h>
#include "hildon-number-editor.h"
+#include "hildon-marshalers.h"
#include <hildon-widgets/gtk-infoprint.h>
#include "hildon-composite-widget.h"
+#include <hildon-widgets/hildon-input-mode-hint.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_NUMBER_EDITOR, \
HildonNumberEditorPrivate));
-enum
-{
- MAXIMUM_VALUE_EXCEED,
- MINIMUM_VALUE_EXCEED,
- ERRONEOUS_VALUE
-};
-
-
typedef struct _HildonNumberEditorPrivate HildonNumberEditorPrivate;
static void
set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc,
GtkAllocation *allocation);
-static int
-hildon_number_editor_get_font_width (GtkWidget *widget);
-
static void
hildon_number_editor_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
hildon_number_editor_button_released (GtkWidget *widget,
GdkEvent *event,
HildonNumberEditor *editor);
-static void
-construct_error_message (HildonNumberEditor *editor, gint type);
-
static gboolean
do_mouse_timeout (HildonNumberEditor *editor);
static gboolean
hildon_number_editor_mnemonic_activate( GtkWidget *widget,
gboolean group_cycle );
+static gboolean
+hildon_number_editor_error_handler(HildonNumberEditor *editor,
+ HildonNumberEditorErrorType type);
+
+static gboolean
+hildon_number_editor_select_all (HildonNumberEditorPrivate *priv);
+
+enum
+{
+ RANGE_ERROR,
+
+ LAST_SIGNAL
+};
static GtkContainerClass *parent_class;
+static guint HildonNumberEditor_signal[LAST_SIGNAL] = {0};
struct _HildonNumberEditorPrivate
{
gint end;
gint default_val;
gint button_type;
- gint button_event_id;
- gint entry_len;
- gint entry_width;
- gboolean rem_sign_space;
+ guint button_event_id;
+ guint select_all_idle_id;
+
gboolean negative;
};
widget_class->mnemonic_activate = hildon_number_editor_mnemonic_activate;
widget_class->focus = hildon_composite_widget_focus;
+ editor_class->error_handler = hildon_number_editor_error_handler;
+
/* Because we derived our widget from GtkContainer, we should override
forall method */
container_class->forall = hildon_number_editor_forall;
GTK_OBJECT_CLASS(editor_class)->destroy = hildon_number_editor_destroy;
G_OBJECT_CLASS(editor_class)->finalize = hildon_number_editor_finalize;
+
+ HildonNumberEditor_signal[RANGE_ERROR] =
+ g_signal_new("range_error", HILDON_TYPE_NUMBER_EDITOR,
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET
+ (HildonNumberEditorClass, error_handler),
+ g_signal_accumulator_true_handled, NULL,
+ _hildon_marshal_BOOLEAN__INT,
+ G_TYPE_BOOLEAN, 1, G_TYPE_INT);
}
static void
if (priv->button_event_id)
g_source_remove (priv->button_event_id);
+ if (priv->select_all_idle_id)
+ g_source_remove (priv->select_all_idle_id);
+
/* Call parent class finalize, if have one */
if (G_OBJECT_CLASS (parent_class)->finalize)
G_OBJECT_CLASS (parent_class)->finalize(self);
GTK_WIDGET_UNSET_FLAGS( priv->minus, GTK_CAN_FOCUS );
GTK_WIDGET_UNSET_FLAGS( priv->plus, GTK_CAN_FOCUS );
- priv->entry_width = 0;
- priv->button_event_id = -1;
- priv->rem_sign_space = TRUE;
+ priv->button_event_id = 0;
+ priv->select_all_idle_id = 0;
gtk_widget_set_parent(priv->minus, GTK_WIDGET(editor));
gtk_widget_set_parent(priv->num_entry, GTK_WIDGET(editor));
G_CALLBACK(hildon_number_editor_button_released),
editor);
+ g_object_set( G_OBJECT(priv->num_entry),
+ "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL );
+
gtk_widget_show(priv->num_entry);
gtk_widget_show(priv->minus);
gtk_widget_show(priv->plus);
return FALSE;
}
-static void
-construct_error_message (HildonNumberEditor *editor, gint type)
-{
- gint min, max;
- gchar *err_msg = NULL;
- HildonNumberEditorPrivate *priv;
-
- priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
- min = priv->start;
- max = priv->end;
-
- /* Construct different error message */
- switch (type)
- {
- case MAXIMUM_VALUE_EXCEED:
- err_msg = g_strdup_printf(_("Ckct_ib_maximum_value"), max, max);
- break;
- case MINIMUM_VALUE_EXCEED:
- err_msg = g_strdup_printf(_("Ckct_ib_minimum_value"), min, min);
- break;
- case ERRONEOUS_VALUE:
- err_msg =
- g_strdup_printf(_("Ckct_ib_set_a_value_within_range"), min, max);
- break;
- }
-
- if (err_msg)
- {
- gtk_infoprint(GTK_WINDOW(gtk_widget_get_ancestor(GTK_WIDGET(editor),
- GTK_TYPE_WINDOW)), err_msg);
- g_free(err_msg);
- }
-}
-
static gboolean
hildon_number_editor_button_released (GtkWidget *widget, GdkEvent *event,
HildonNumberEditor *editor)
HildonNumberEditorPrivate *priv =
HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
- if (priv->button_event_id != -1)
+ if (priv->button_event_id)
{
g_source_remove(priv->button_event_id);
- priv->button_event_id = -1;
+ priv->button_event_id = 0;
}
return FALSE;
}
else
priv->button_type = -1;
- if (priv->button_event_id == -1)
+ if (!priv->button_event_id)
{
do_mouse_timeout(editor);
priv->button_event_id = g_timeout_add (timeout,
static gboolean
change_numbers (HildonNumberEditor *editor, gint type, gint cursor_pos)
{
+ gboolean r;
gint nvalue;
gchar *snvalue;
HildonNumberEditorPrivate *priv =
nvalue += 1;
else
{
- construct_error_message(editor, MAXIMUM_VALUE_EXCEED);
+ g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR],
+ 0, MAXIMUM_VALUE_EXCEED, &r);
return FALSE;
}
}
else
{
- construct_error_message(editor, MINIMUM_VALUE_EXCEED);
+ g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR],
+ 0, MINIMUM_VALUE_EXCEED, &r);
return FALSE;
}
}
}
static void
+add_select_all_idle (HildonNumberEditorPrivate *priv)
+{
+ if (!priv->select_all_idle_id)
+ {
+ priv->select_all_idle_id =
+ g_idle_add((GSourceFunc) hildon_number_editor_select_all, priv);
+ }
+}
+
+static void
hildon_number_editor_entry_changed (GtkWidget *widget, gpointer data)
{
- HildonNumberEditor *editor;
- HildonNumberEditorPrivate *priv;
- gchar *tmpstr;
- gint value;
- gchar *tail = NULL;
+ HildonNumberEditor *editor;
+ HildonNumberEditorPrivate *priv;
+ gchar *tmpstr;
+ gint value;
+ gchar *tail = NULL;
+ gboolean r;
- editor = HILDON_NUMBER_EDITOR(data);
- priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
+ editor = HILDON_NUMBER_EDITOR(data);
+ priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
- tmpstr = GTK_ENTRY(priv->num_entry)->text;
+ tmpstr = GTK_ENTRY(priv->num_entry)->text;
- if (strlen(tmpstr) > 0)
- {
- tmpstr = NULL;
- value = strtol(GTK_ENTRY(priv->num_entry)->text, &tail, 10);
- if (!strncmp(tail, "\0", 1) || !strncmp(tail, "-", 1))
- {
- if (atoi(GTK_ENTRY(priv->num_entry)->text) > priv->end)
- {
- construct_error_message(editor, MAXIMUM_VALUE_EXCEED);
- tmpstr = integer_to_string(priv->end);
- gtk_entry_set_text(GTK_ENTRY(priv->num_entry), tmpstr);
- if (tmpstr)
- g_free(tmpstr);
- }
- else if (atoi(GTK_ENTRY(priv->num_entry)->text) < priv->start) {
- construct_error_message(editor, MINIMUM_VALUE_EXCEED);
- tmpstr = integer_to_string(priv->start);
- gtk_entry_set_text(GTK_ENTRY(priv->num_entry), tmpstr);
- if (tmpstr)
- g_free(tmpstr);
- }
- }
- else
- {
- construct_error_message(editor, ERRONEOUS_VALUE);
- tmpstr = integer_to_string(priv->start);
- gtk_entry_set_text(GTK_ENTRY(priv->num_entry), tmpstr);
- if (tmpstr)
- g_free(tmpstr);
- }
- }
+ if (strlen(tmpstr) > 0)
+ {
+ tmpstr = NULL;
+ value = strtol(GTK_ENTRY(priv->num_entry)->text, &tail, 10);
+ if (!strncmp(tail, "\0", 1) || !strncmp(tail, "-", 1))
+ {
+ if (atoi(GTK_ENTRY(priv->num_entry)->text) > priv->end)
+ {
+ g_signal_emit(editor,HildonNumberEditor_signal[RANGE_ERROR],
+ 0, MAXIMUM_VALUE_EXCEED, &r);
+ tmpstr = integer_to_string(priv->end);
+ gtk_entry_set_text(GTK_ENTRY(priv->num_entry), tmpstr);
+ add_select_all_idle(priv);
+ if (tmpstr)
+ g_free(tmpstr);
+ }
+ else if (atoi(GTK_ENTRY(priv->num_entry)->text) < priv->start) {
+ g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR],
+ 0, MINIMUM_VALUE_EXCEED, &r);
+ tmpstr = integer_to_string(priv->start);
+ gtk_entry_set_text(GTK_ENTRY(priv->num_entry), tmpstr);
+ add_select_all_idle(priv);
+ if (tmpstr)
+ g_free(tmpstr);
+ }
+ }
+ else
+ {
+ g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR],
+ 0, ERRONEOUS_VALUE, &r);
+ tmpstr = integer_to_string(priv->start);
+ gtk_entry_set_text(GTK_ENTRY(priv->num_entry), tmpstr);
+ add_select_all_idle(priv);
+ if (tmpstr)
+ g_free(tmpstr);
+ }
+ }
}
static void
editor = HILDON_NUMBER_EDITOR(widget);
priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
-/* FIXME -- If it's needed to fix button sizes.. priv->minus and priv->plus
- * requisitions are right places to do that.
- */
-
gtk_widget_size_request(priv->minus, &req);
- *requisition = req;
+ requisition->width = req.width;
gtk_widget_size_request(priv->num_entry, &req);
requisition->width += req.width;
- if (!priv->entry_width)
- {
- gint font_w = hildon_number_editor_get_font_width(priv->num_entry);
-
- priv->entry_width = (priv->entry_len + 1) * font_w +
- widget->style->xthickness * 2 -
- (font_w / 2 * priv->rem_sign_space);
- gtk_widget_set_size_request(priv->num_entry, priv->entry_width,
- req.height);
- }
-
gtk_widget_size_request(priv->plus, &req);
- requisition->width += priv->entry_len;
+ requisition->width += req.width;
requisition->width += SPACE_BORDER * 2;
requisition->height = NUMBER_EDITOR_HEIGHT;
alloc->x += alloc->width;
}
-static int
-hildon_number_editor_get_font_width (GtkWidget *widget)
-{
- PangoContext *context;
- PangoFontMetrics *metrics;
- gint digit_width;
-
- context = gtk_widget_get_pango_context(widget);
- metrics = pango_context_get_metrics(context,
- widget->style->font_desc,
- pango_context_get_language
- (context));
-
- digit_width = pango_font_metrics_get_approximate_digit_width(metrics);
- digit_width = PANGO_PIXELS(digit_width);
-
- pango_font_metrics_unref(metrics);
-
- return digit_width;
-}
-
static void
hildon_number_editor_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
HildonNumberEditor *editor;
HildonNumberEditorPrivate *priv;
gchar *str;
+ gboolean r;
editor = HILDON_NUMBER_EDITOR(data);
priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
/* empty entry, must infoprint error message */
if (!strlen(GTK_ENTRY(priv->num_entry)->text))
{
- construct_error_message(editor, ERRONEOUS_VALUE);
+ g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR],
+ 0, ERRONEOUS_VALUE, &r);
/* Changing to default value */
str = integer_to_string(priv->default_val);
gtk_entry_set_text(GTK_ENTRY(priv->num_entry), str);
return ret_val;
}
+static gboolean
+hildon_number_editor_error_handler(HildonNumberEditor *editor,
+ HildonNumberEditorErrorType type)
+{
+
+ gint min, max;
+ gchar *err_msg = NULL;
+ HildonNumberEditorPrivate *priv;
+
+ priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
+ min = priv->start;
+ max = priv->end;
+
+ /* Construct different error message */
+ switch (type)
+ {
+ case MAXIMUM_VALUE_EXCEED:
+ err_msg = g_strdup_printf(_("Ckct_ib_maximum_value"), max, max);
+ break;
+ case MINIMUM_VALUE_EXCEED:
+ err_msg = g_strdup_printf(_("Ckct_ib_minimum_value"), min, min);
+ break;
+ case ERRONEOUS_VALUE:
+ err_msg =
+ g_strdup_printf(_("Ckct_ib_set_a_value_within_range"), min, max);
+ break;
+ }
+
+ if (err_msg)
+ {
+ gtk_infoprint(GTK_WINDOW(gtk_widget_get_ancestor(GTK_WIDGET(editor),
+ GTK_TYPE_WINDOW)), err_msg);
+ g_free(err_msg);
+ }
+
+ return TRUE;
+}
+
/**
* hildon_number_editor_new:
{
HildonNumberEditorPrivate *priv;
gchar *str, *str2;
- gint a, b;
+ gint a, b, entry_len;
g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor));
b = strlen(str2);
if (a >= b)
- {
- priv->entry_len = a;
- priv->rem_sign_space = FALSE;
- }
+ entry_len = a;
else
- {
- priv->entry_len = b;
- priv->rem_sign_space = TRUE;
- }
+ entry_len = b;
- /* reserving space for the minus sign */
- if (priv->negative)
- priv->entry_len++;
-
-/* priv->entry_len = a >= b ? a : b;*/
- priv->entry_width = 0;
+ gtk_entry_set_width_chars(GTK_ENTRY(priv->num_entry), entry_len);
gtk_entry_set_text(GTK_ENTRY(priv->num_entry), str);
gtk_widget_queue_resize(GTK_WIDGET(editor));
if (str)
g_free(str);
}
+
+/* When calling gtk_entry_set_text, the entry widget does things that can
+ * cause the whole widget to redraw. This redrawing is delayed and if any
+ * selections are made right after calling the gtk_entry_set_text the
+ * setting of the selection might seem to have no effect.
+ *
+ * If the selection is delayed with a lower priority than the redrawing,
+ * the selection should stick. Calling this function with g_idle_add should
+ * do it.
+ */
+static gboolean
+hildon_number_editor_select_all (HildonNumberEditorPrivate *priv)
+{
+ gtk_editable_select_region(GTK_EDITABLE(priv->num_entry), 0, -1);
+ priv->select_all_idle_id = 0;
+ return FALSE;
+}
+