2 * This file is part of hildon-libs
4 * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
6 * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; version 2.1 of
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
26 * SECTION:hildon-number-editor
27 * @short_description: A widget used to enter a number within a pre-defined range
29 * HildonNumberEditor is used to enter a number from a specific range.
30 * There are two buttons to scroll the value in number field.
31 * Manual input is also possible.
34 #include <gdk/gdkkeysyms.h>
41 #include "hildon-number-editor.h"
42 #include "hildon-marshalers.h"
43 #include <hildon-widgets/gtk-infoprint.h>
44 #include "hildon-composite-widget.h"
45 #include <hildon-widgets/hildon-input-mode-hint.h>
46 #include <hildon-widgets/hildon-defines.h>
47 #include "hildon-enum-types.h"
48 #include "hildon-banner.h"
55 #define _(String) dgettext(PACKAGE, String)
57 /*Pixel spec defines*/
58 #define NUMBER_EDITOR_HEIGHT 30
60 /* Size of plus and minus buttons */
61 #define BUTTON_HEIGHT 30
62 #define BUTTON_WIDTH 30
64 #define HILDON_NUMBER_EDITOR_GET_PRIVATE(obj) \
65 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_NUMBER_EDITOR, \
66 HildonNumberEditorPrivate));
68 typedef struct _HildonNumberEditorPrivate HildonNumberEditorPrivate;
71 hildon_number_editor_class_init (HildonNumberEditorClass *editor_class);
74 hildon_number_editor_init (HildonNumberEditor *editor);
77 hildon_number_editor_entry_focusout (GtkWidget *widget, GdkEventFocus *event,
81 hildon_number_editor_entry_changed (GtkWidget *widget, gpointer data);
84 hildon_number_editor_size_request (GtkWidget *widget,
85 GtkRequisition *requisition);
88 set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc,
89 const GtkAllocation *allocation);
92 hildon_number_editor_size_allocate (GtkWidget *widget,
93 GtkAllocation *allocation);
96 hildon_number_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event,
100 hildon_number_editor_button_pressed (GtkWidget *widget, GdkEventButton *event,
104 hildon_number_editor_entry_button_released (GtkWidget *widget,
105 GdkEventButton *event,
108 hildon_number_editor_button_released (GtkWidget *widget,
110 HildonNumberEditor *editor);
112 do_mouse_timeout (HildonNumberEditor *editor);
115 change_numbers (HildonNumberEditor *editor, gint update);
118 hildon_number_editor_forall (GtkContainer *container, gboolean include_internals,
119 GtkCallback callback, gpointer callback_data);
122 hildon_number_editor_destroy (GtkObject *self);
125 hildon_number_editor_start_timer (HildonNumberEditor *editor);
128 hildon_number_editor_finalize (GObject *self);
131 hildon_number_editor_range_error(HildonNumberEditor *editor,
132 HildonNumberEditorErrorType type);
135 hildon_number_editor_select_all (HildonNumberEditorPrivate *priv);
138 hildon_number_editor_validate_value(HildonNumberEditor *editor, gboolean allow_intermediate);
140 static void hildon_number_editor_set_property(GObject * object,
142 const GValue * value,
145 static void hildon_number_editor_get_property(GObject * object,
147 GValue * value, GParamSpec * pspec);
156 /* Property indices */
162 static GtkContainerClass *parent_class;
164 static guint HildonNumberEditor_signal[LAST_SIGNAL] = {0};
166 struct _HildonNumberEditorPrivate
169 GtkWidget *num_entry;
173 gint start; /* Minimum */
174 gint end; /* Maximum */
176 gint button_type; /* Type of button pressed: 1 = plus, -1 = minus */
179 guint button_event_id; /* Repeat change when button is held */
180 guint select_all_idle_id; /* Selection repaint hack
181 see hildon_number_editor_select_all */
185 GType hildon_number_editor_get_type(void)
187 static GType editor_type = 0;
191 static const GTypeInfo editor_info =
193 sizeof(HildonNumberEditorClass),
194 NULL, /* base_init */
195 NULL, /* base_finalize */
196 (GClassInitFunc) hildon_number_editor_class_init,
197 NULL, /* class_finalize */
198 NULL, /* class_data */
199 sizeof(HildonNumberEditor),
201 (GInstanceInitFunc) hildon_number_editor_init,
203 editor_type = g_type_register_static(GTK_TYPE_CONTAINER,
204 "HildonNumberEditor",
211 hildon_number_editor_class_init(HildonNumberEditorClass * editor_class)
213 GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class);
214 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class);
215 GObjectClass *gobject_class = G_OBJECT_CLASS(editor_class);
217 g_type_class_add_private(editor_class,
218 sizeof(HildonNumberEditorPrivate));
220 parent_class = g_type_class_peek_parent(editor_class);
222 widget_class->size_request = hildon_number_editor_size_request;
223 widget_class->size_allocate = hildon_number_editor_size_allocate;
224 widget_class->focus = hildon_composite_widget_focus;
226 editor_class->range_error = hildon_number_editor_range_error;
228 /* Because we derived our widget from GtkContainer, we should override
230 container_class->forall = hildon_number_editor_forall;
231 GTK_OBJECT_CLASS(editor_class)->destroy = hildon_number_editor_destroy;
232 gobject_class->finalize = hildon_number_editor_finalize;
233 gobject_class->set_property = hildon_number_editor_set_property;
234 gobject_class->get_property = hildon_number_editor_get_property;
236 g_object_class_install_property(gobject_class, PROP_VALUE,
237 g_param_spec_int("value",
239 "The current value of number editor",
242 0, G_PARAM_READWRITE));
244 HildonNumberEditor_signal[RANGE_ERROR] =
245 g_signal_new("range_error", HILDON_TYPE_NUMBER_EDITOR,
246 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET
247 (HildonNumberEditorClass, range_error),
248 g_signal_accumulator_true_handled, NULL,
249 _hildon_marshal_BOOLEAN__ENUM,
250 G_TYPE_BOOLEAN, 1, HILDON_TYPE_NUMBER_EDITOR_ERROR_TYPE);
254 hildon_number_editor_forall(GtkContainer *container, gboolean include_internals,
255 GtkCallback callback, gpointer callback_data)
257 HildonNumberEditorPrivate *priv =
258 HILDON_NUMBER_EDITOR_GET_PRIVATE(container);
260 g_assert(callback != NULL);
262 if (!include_internals)
265 /* Enumerate child widgets */
266 (*callback) (priv->minus, callback_data);
267 (*callback) (priv->num_entry, callback_data);
268 (*callback) (priv->plus, callback_data);
272 hildon_number_editor_destroy(GtkObject *self)
274 HildonNumberEditorPrivate *priv;
276 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(self);
278 /* Free child widgets */
281 gtk_widget_unparent(priv->minus);
286 gtk_widget_unparent(priv->num_entry);
287 priv->num_entry = NULL;
291 gtk_widget_unparent(priv->plus);
295 if (GTK_OBJECT_CLASS(parent_class)->destroy)
296 GTK_OBJECT_CLASS(parent_class)->destroy(self);
300 hildon_number_editor_stop_repeat_timer(HildonNumberEditorPrivate *priv)
302 if (priv->button_event_id)
304 g_source_remove(priv->button_event_id);
305 priv->button_event_id = 0;
310 hildon_number_editor_finalize (GObject *self)
312 HildonNumberEditorPrivate *priv;
314 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(self);
317 hildon_number_editor_stop_repeat_timer(priv);
319 if (priv->select_all_idle_id)
320 g_source_remove (priv->select_all_idle_id);
322 /* Call parent class finalize, if have one */
323 if (G_OBJECT_CLASS (parent_class)->finalize)
324 G_OBJECT_CLASS (parent_class)->finalize(self);
328 hildon_number_editor_init (HildonNumberEditor *editor)
330 HildonNumberEditorPrivate *priv;
332 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
333 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(editor), GTK_NO_WINDOW);
335 /* Create child widgets */
336 priv->num_entry = gtk_entry_new();
337 priv->minus = gtk_button_new();
338 priv->plus = gtk_button_new();
340 gtk_widget_set_name( priv->minus, "ne-minus-button" );
341 gtk_widget_set_name( priv->plus, "ne-plus-button" );
342 gtk_widget_set_size_request( priv->minus, BUTTON_WIDTH, BUTTON_HEIGHT );
343 gtk_widget_set_size_request( priv->plus, BUTTON_WIDTH, BUTTON_HEIGHT );
344 gtk_entry_set_alignment (GTK_ENTRY(priv->num_entry), 1);
346 GTK_WIDGET_UNSET_FLAGS( priv->minus, GTK_CAN_FOCUS );
347 GTK_WIDGET_UNSET_FLAGS( priv->plus, GTK_CAN_FOCUS );
349 priv->button_event_id = 0;
350 priv->select_all_idle_id = 0;
352 gtk_widget_set_parent(priv->minus, GTK_WIDGET(editor));
353 gtk_widget_set_parent(priv->num_entry, GTK_WIDGET(editor));
354 gtk_widget_set_parent(priv->plus, GTK_WIDGET(editor));
356 /* Connect child widget signals */
357 g_signal_connect(GTK_OBJECT(priv->num_entry), "changed",
358 G_CALLBACK(hildon_number_editor_entry_changed),
361 g_signal_connect(GTK_OBJECT(priv->num_entry), "focus-out-event",
362 G_CALLBACK(hildon_number_editor_entry_focusout),
365 g_signal_connect(GTK_OBJECT(priv->num_entry), "key-press-event",
366 G_CALLBACK(hildon_number_editor_entry_keypress),
369 g_signal_connect(GTK_OBJECT(priv->num_entry), "button-release-event",
370 G_CALLBACK(hildon_number_editor_entry_button_released),
373 g_signal_connect(GTK_OBJECT(priv->minus), "button-press-event",
374 G_CALLBACK(hildon_number_editor_button_pressed),
377 g_signal_connect(GTK_OBJECT(priv->plus), "button-press-event",
378 G_CALLBACK(hildon_number_editor_button_pressed),
381 g_signal_connect(GTK_OBJECT(priv->minus), "button-release-event",
382 G_CALLBACK(hildon_number_editor_button_released),
385 g_signal_connect(GTK_OBJECT(priv->plus), "button-release-event",
386 G_CALLBACK(hildon_number_editor_button_released),
389 g_signal_connect(GTK_OBJECT(priv->minus), "leave-notify-event",
390 G_CALLBACK(hildon_number_editor_button_released),
393 g_signal_connect(GTK_OBJECT(priv->plus), "leave-notify-event",
394 G_CALLBACK(hildon_number_editor_button_released),
397 g_object_set( G_OBJECT(priv->num_entry),
398 "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL );
400 gtk_widget_show(priv->num_entry);
401 gtk_widget_show(priv->minus);
402 gtk_widget_show(priv->plus);
404 hildon_number_editor_set_range(editor, G_MININT, G_MAXINT);
408 hildon_number_editor_entry_button_released (GtkWidget *widget,
409 GdkEventButton *event,
412 gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
417 hildon_number_editor_button_released (GtkWidget *widget, GdkEvent *event,
418 HildonNumberEditor *editor)
420 HildonNumberEditorPrivate *priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
421 hildon_number_editor_stop_repeat_timer(priv);
425 /* Format given number to editor field, no checks performed, all signals
426 are sent normally. */
428 hildon_number_editor_real_set_value (HildonNumberEditorPrivate *priv, gint value)
432 /* Update text in entry to new value */
433 g_snprintf(buffer, sizeof(buffer), "%d", value);
434 gtk_entry_set_text(GTK_ENTRY(priv->num_entry), buffer);
438 hildon_number_editor_button_pressed (GtkWidget *widget, GdkEventButton *event,
441 /* FIXME: XXX Why aren't we using hildon_number_editor_start_timer here? XXX */
442 /* Need to fetch current value from entry and increment or decrement
444 HildonNumberEditor *editor;
445 HildonNumberEditorPrivate *priv;
446 GtkSettings *settings;
449 g_assert(HILDON_IS_NUMBER_EDITOR(data));
451 editor = HILDON_NUMBER_EDITOR(data);
452 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
453 settings = gtk_settings_get_default();
454 g_object_get(settings, "gtk-initial-timeout", &timeout, NULL);
456 /* Save type of button pressed */
457 if (GTK_BUTTON(widget) == GTK_BUTTON(priv->plus))
458 priv->button_type = 1;
460 priv->button_type = -1;
462 /* Start repetition timer */
463 if (!priv->button_event_id)
465 do_mouse_timeout(editor);
466 priv->button_event_id = g_timeout_add (timeout,
467 (GSourceFunc) hildon_number_editor_start_timer,
475 hildon_number_editor_start_timer (HildonNumberEditor *editor)
477 HildonNumberEditorPrivate *priv;
478 GtkSettings *settings;
481 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
482 settings = gtk_settings_get_default();
483 g_object_get(settings, "gtk-update-timeout", &timeout, NULL);
485 priv->button_event_id = g_timeout_add(timeout,
486 (GSourceFunc) do_mouse_timeout,
492 do_mouse_timeout (HildonNumberEditor *editor)
494 HildonNumberEditorPrivate *priv;
496 GDK_THREADS_ENTER ();
498 g_assert(HILDON_IS_NUMBER_EDITOR(editor));
500 /* Update value based on button held */
501 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
502 change_numbers(editor, priv->button_type);
504 GDK_THREADS_LEAVE ();
509 /* Changes the current number value by the amount of update
510 and verifies the result. */
512 change_numbers (HildonNumberEditor *editor, gint update)
514 HildonNumberEditorPrivate *priv;
517 g_assert(HILDON_IS_NUMBER_EDITOR(editor));
519 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
520 current_value = hildon_number_editor_get_value(editor);
522 /* We need to rerun validation by hand, since validation
523 done in "changed" callback allows intermediate values */
524 hildon_number_editor_real_set_value(priv, current_value + update);
525 hildon_number_editor_validate_value(editor, FALSE);
526 g_object_notify (G_OBJECT(editor), "value");
530 add_select_all_idle (HildonNumberEditorPrivate *priv)
532 if (!priv->select_all_idle_id)
534 priv->select_all_idle_id =
535 g_idle_add((GSourceFunc) hildon_number_editor_select_all, priv);
540 hildon_number_editor_validate_value(HildonNumberEditor *editor, gboolean allow_intermediate)
542 HildonNumberEditorPrivate *priv;
543 gint error_code, fixup_value;
549 g_assert(HILDON_IS_NUMBER_EDITOR(editor));
551 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
552 text = gtk_entry_get_text(GTK_ENTRY(priv->num_entry));
554 fixup_value = priv->default_val;
558 /* Try to convert entry text to number */
559 value = strtol(text, &tail, 10);
561 /* Check if conversion succeeded */
564 /* Check if value is in allowed range. This is tricky in those
565 cases when user is editing a value.
566 For example: Range = [100, 500] and user have just inputted "4".
567 This should not lead into error message. Otherwise value is
568 resetted back to "100" and next "4" press will reset it back
570 if (allow_intermediate)
572 /* We now have the following error cases:
573 * If inputted value as above maximum and
574 maximum is either positive or then maximum
575 negative and value is positive.
576 * If inputted value is below minimum and minimum
577 is negative or minumum positive and value
579 In all other cases situation can be fixed just by
580 adding new numbers to the string.
582 if (value > priv->end && (priv->end >= 0 || (priv->end < 0 && value >= 0)))
584 error_code = MAXIMUM_VALUE_EXCEED;
585 fixup_value = priv->end;
587 else if (value < priv->start && (priv->start < 0 || (priv->start >= 0 && value <= 0)))
589 error_code = MINIMUM_VALUE_EXCEED;
590 fixup_value = priv->start;
595 if (value > priv->end) {
596 error_code = MAXIMUM_VALUE_EXCEED;
597 fixup_value = priv->end;
599 else if (value < priv->start) {
600 error_code = MINIMUM_VALUE_EXCEED;
601 fixup_value = priv->start;
605 /* The only valid case when conversion can fail is when we
606 have plain '-', intermediate forms are allowed AND
607 minimum bound is negative */
608 else if (!allow_intermediate || strcmp(text, "-") != 0 || priv->start >= 0)
609 error_code = ERRONEOUS_VALUE;
611 else if (!allow_intermediate)
612 error_code = ERRONEOUS_VALUE;
614 if (error_code != -1)
616 /* If entry is empty and intermediate forms are nor allowed,
618 /* Change to default value */
619 hildon_number_editor_set_value(editor, fixup_value);
620 g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR],
622 add_select_all_idle(priv);
627 hildon_number_editor_entry_changed(GtkWidget *widget, gpointer data)
629 g_assert(HILDON_IS_NUMBER_EDITOR(data));
630 hildon_number_editor_validate_value(HILDON_NUMBER_EDITOR(data), TRUE);
631 g_object_notify (G_OBJECT(data), "value");
635 hildon_number_editor_size_request (GtkWidget *widget,
636 GtkRequisition *requisition)
638 HildonNumberEditor *editor;
639 HildonNumberEditorPrivate *priv;
642 editor = HILDON_NUMBER_EDITOR(widget);
643 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
645 /* Requested size is size of all child widgets plus border space */
646 gtk_widget_size_request(priv->minus, &req);
647 requisition->width = req.width;
649 gtk_widget_size_request(priv->num_entry, &req);
650 requisition->width += req.width;
652 gtk_widget_size_request(priv->plus, &req);
653 requisition->width += req.width;
655 requisition->width += HILDON_MARGIN_DEFAULT * 2;
657 /* FIXME: XXX Height is fixed */
658 requisition->height = NUMBER_EDITOR_HEIGHT;
661 /* Update @alloc->width so widget fits, update @alloc->x to point to free space */
663 set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc,
664 const GtkAllocation *allocation)
666 GtkRequisition child_requisition;
668 gtk_widget_get_child_requisition(widget, &child_requisition);
670 /* Fit to widget width */
671 if (allocation->width + allocation->x >
672 alloc->x + child_requisition.width)
673 alloc->width = child_requisition.width;
676 alloc->width = allocation->width - (alloc->x - allocation->x);
677 if (alloc->width < 0)
681 gtk_widget_size_allocate(widget, alloc);
682 /* Update x position */
683 alloc->x += alloc->width;
687 hildon_number_editor_size_allocate (GtkWidget *widget,
688 GtkAllocation *allocation)
690 HildonNumberEditor *editor;
691 HildonNumberEditorPrivate *priv;
694 editor = HILDON_NUMBER_EDITOR(widget);
695 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
697 widget->allocation = *allocation;
699 /* Add upper border */
700 alloc.y = widget->allocation.y + widget->style->ythickness;
703 if (widget->allocation.height > NUMBER_EDITOR_HEIGHT)
705 alloc.height = NUMBER_EDITOR_HEIGHT - widget->style->ythickness * 2;
706 alloc.y += (widget->allocation.height - NUMBER_EDITOR_HEIGHT) / 2;
709 alloc.height = widget->allocation.height - widget->style->ythickness * 2;
711 if (alloc.height < 0)
714 /* Add left border */
715 alloc.x = allocation->x + widget->style->xthickness;
717 /* Allocate positions for widgets (left-to-right) */
718 set_widget_allocation(priv->minus, &alloc, &widget->allocation);
719 alloc.x += HILDON_MARGIN_DEFAULT;
721 set_widget_allocation(priv->num_entry, &alloc, &widget->allocation);
722 alloc.x += HILDON_MARGIN_DEFAULT;
724 set_widget_allocation(priv->plus, &alloc, &widget->allocation);
728 hildon_number_editor_entry_focusout (GtkWidget *widget, GdkEventFocus *event,
731 g_assert(HILDON_IS_NUMBER_EDITOR(data));
732 hildon_number_editor_validate_value(HILDON_NUMBER_EDITOR(data), FALSE);
737 hildon_number_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event,
740 GtkEditable *editable;
743 g_assert(HILDON_IS_NUMBER_EDITOR(data));
745 editable = GTK_EDITABLE(widget);
746 cursor_pos = gtk_editable_get_position(editable);
748 switch (event->keyval)
751 /* If the cursor is on the left, try to decrement */
752 if (cursor_pos == 0) {
753 change_numbers(HILDON_NUMBER_EDITOR(data), -1);
759 /* If the cursor is on the right, try to increment */
760 if (cursor_pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1))
762 change_numbers(HILDON_NUMBER_EDITOR(data), 1);
763 gtk_editable_set_position(editable, cursor_pos);
776 hildon_number_editor_range_error(HildonNumberEditor *editor,
777 HildonNumberEditorErrorType type)
781 gchar *err_msg = NULL;
782 HildonNumberEditorPrivate *priv;
784 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
788 /* Construct error message */
791 case MAXIMUM_VALUE_EXCEED:
792 err_msg = g_strdup_printf(_("ckct_ib_maximum_value"), max, max);
794 case MINIMUM_VALUE_EXCEED:
795 err_msg = g_strdup_printf(_("ckct_ib_minimum_value"), min, min);
797 case ERRONEOUS_VALUE:
799 g_strdup_printf(_("ckct_ib_set_a_value_within_range"), min, max);
803 /* Infoprint error */
806 hildon_banner_show_information(GTK_WIDGET (GTK_WINDOW(gtk_widget_get_ancestor(GTK_WIDGET(editor),
807 GTK_TYPE_WINDOW))), NULL, err_msg);
816 * hildon_number_editor_new:
817 * @min: minimum accepted value
818 * @max: maximum accepted value
820 * Creates new number editor
822 * Returns: a new #HildonNumberEditor widget
825 hildon_number_editor_new (gint min, gint max)
827 HildonNumberEditor *editor =
828 g_object_new(HILDON_TYPE_NUMBER_EDITOR, NULL);
830 /* Set user inputted range to editor */
831 hildon_number_editor_set_range(editor, min, max);
833 return GTK_WIDGET(editor);
837 * hildon_number_editor_set_range:
838 * @editor: a #HildonNumberEditor widget
839 * @min: minimum accepted value
840 * @max: maximum accepted value
842 * Sets accepted number range for editor
845 hildon_number_editor_set_range (HildonNumberEditor *editor, gint min, gint max)
847 HildonNumberEditorPrivate *priv;
848 gchar buffer_min[32], buffer_max[32];
851 g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor));
853 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
855 /* Set preferences */
856 priv->start = MIN(min, max);
857 priv->end = MAX(min, max);
859 /* Find maximum allowed length of value */
860 g_snprintf(buffer_min, sizeof(buffer_min), "%d", min);
861 g_snprintf(buffer_max, sizeof(buffer_max), "%d", max);
862 a = strlen(buffer_min);
863 b = strlen(buffer_max);
865 /* Set maximum size of entry */
866 gtk_entry_set_width_chars(GTK_ENTRY(priv->num_entry), MAX(a, b));
867 hildon_number_editor_set_value(editor, priv->start);
871 * hildon_number_editor_get_value:
872 * @editor: pointer to #HildonNumberEditor
874 * Returns: current NumberEditor value
877 hildon_number_editor_get_value (HildonNumberEditor *editor)
879 HildonNumberEditorPrivate *priv;
881 g_return_val_if_fail(HILDON_IS_NUMBER_EDITOR(editor), 0);
883 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
884 return atoi(gtk_entry_get_text(GTK_ENTRY(priv->num_entry)));
888 * hildon_number_editor_set_value:
889 * @editor: pointer to #HildonNumberEditor
890 * @value: numeric value for number editor
892 * Sets numeric value for number editor
895 hildon_number_editor_set_value (HildonNumberEditor *editor, gint value)
897 HildonNumberEditorPrivate *priv;
899 g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor));
901 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
903 g_return_if_fail(value <= priv->end);
904 g_return_if_fail(value >= priv->start);
906 priv->default_val = value;
907 hildon_number_editor_real_set_value(priv, value);
908 g_object_notify (G_OBJECT(editor), "value");
911 /* When calling gtk_entry_set_text, the entry widget does things that can
912 * cause the whole widget to redraw. This redrawing is delayed and if any
913 * selections are made right after calling the gtk_entry_set_text the
914 * setting of the selection might seem to have no effect.
916 * If the selection is delayed with a lower priority than the redrawing,
917 * the selection should stick. Calling this function with g_idle_add should
921 hildon_number_editor_select_all (HildonNumberEditorPrivate *priv)
923 GDK_THREADS_ENTER ();
924 gtk_editable_select_region(GTK_EDITABLE(priv->num_entry), 0, -1);
925 priv->select_all_idle_id = 0;
926 GDK_THREADS_LEAVE ();
931 hildon_number_editor_set_property(GObject * object,
933 const GValue * value, GParamSpec * pspec)
935 HildonNumberEditor *editor;
937 editor = HILDON_NUMBER_EDITOR(object);
941 hildon_number_editor_set_value(editor, g_value_get_int(value));
944 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
950 hildon_number_editor_get_property(GObject * object,
951 guint prop_id, GValue * value, GParamSpec * pspec)
953 HildonNumberEditor *editor;
955 editor = HILDON_NUMBER_EDITOR(object);
959 g_value_set_int(value, hildon_number_editor_get_value(editor));
962 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);