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-libs-enum-types.h"
54 #define _(String) dgettext(PACKAGE, String)
56 /*Pixel spec defines*/
57 #define NUMBER_EDITOR_HEIGHT 30
59 /* Size of plus and minus buttons */
60 #define BUTTON_HEIGHT 30
61 #define BUTTON_WIDTH 30
63 #define HILDON_NUMBER_EDITOR_GET_PRIVATE(obj) \
64 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), HILDON_TYPE_NUMBER_EDITOR, \
65 HildonNumberEditorPrivate));
67 typedef struct _HildonNumberEditorPrivate HildonNumberEditorPrivate;
70 hildon_number_editor_class_init (HildonNumberEditorClass *editor_class);
73 hildon_number_editor_init (HildonNumberEditor *editor);
76 hildon_number_editor_entry_focusout (GtkWidget *widget, GdkEventFocus *event,
80 hildon_number_editor_entry_changed (GtkWidget *widget, gpointer data);
83 hildon_number_editor_size_request (GtkWidget *widget,
84 GtkRequisition *requisition);
87 set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc,
88 const GtkAllocation *allocation);
91 hildon_number_editor_size_allocate (GtkWidget *widget,
92 GtkAllocation *allocation);
95 hildon_number_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event,
99 hildon_number_editor_button_pressed (GtkWidget *widget, GdkEventButton *event,
103 hildon_number_editor_entry_button_released (GtkWidget *widget,
104 GdkEventButton *event,
107 hildon_number_editor_button_released (GtkWidget *widget,
109 HildonNumberEditor *editor);
111 do_mouse_timeout (HildonNumberEditor *editor);
114 change_numbers (HildonNumberEditor *editor, gint update);
117 hildon_number_editor_forall (GtkContainer *container, gboolean include_internals,
118 GtkCallback callback, gpointer callback_data);
121 hildon_number_editor_destroy (GtkObject *self);
124 hildon_number_editor_start_timer (HildonNumberEditor *editor);
127 hildon_number_editor_finalize (GObject *self);
130 hildon_number_editor_range_error(HildonNumberEditor *editor,
131 HildonNumberEditorErrorType type);
134 hildon_number_editor_select_all (HildonNumberEditorPrivate *priv);
137 hildon_number_editor_validate_value(HildonNumberEditor *editor, gboolean allow_intermediate);
139 static void hildon_number_editor_set_property(GObject * object,
141 const GValue * value,
144 static void hildon_number_editor_get_property(GObject * object,
146 GValue * value, GParamSpec * pspec);
155 /* Property indices */
161 static GtkContainerClass *parent_class;
163 static guint HildonNumberEditor_signal[LAST_SIGNAL] = {0};
165 struct _HildonNumberEditorPrivate
168 GtkWidget *num_entry;
172 gint start; /* Minimum */
173 gint end; /* Maximum */
175 gint button_type; /* Type of button pressed: 1 = plus, -1 = minus */
178 guint button_event_id; /* Repeat change when button is held */
179 guint select_all_idle_id; /* Selection repaint hack
180 see hildon_number_editor_select_all */
184 GType hildon_number_editor_get_type(void)
186 static GType editor_type = 0;
190 static const GTypeInfo editor_info =
192 sizeof(HildonNumberEditorClass),
193 NULL, /* base_init */
194 NULL, /* base_finalize */
195 (GClassInitFunc) hildon_number_editor_class_init,
196 NULL, /* class_finalize */
197 NULL, /* class_data */
198 sizeof(HildonNumberEditor),
200 (GInstanceInitFunc) hildon_number_editor_init,
202 editor_type = g_type_register_static(GTK_TYPE_CONTAINER,
203 "HildonNumberEditor",
210 hildon_number_editor_class_init(HildonNumberEditorClass * editor_class)
212 GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class);
213 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class);
214 GObjectClass *gobject_class = G_OBJECT_CLASS(editor_class);
216 g_type_class_add_private(editor_class,
217 sizeof(HildonNumberEditorPrivate));
219 parent_class = g_type_class_peek_parent(editor_class);
221 widget_class->size_request = hildon_number_editor_size_request;
222 widget_class->size_allocate = hildon_number_editor_size_allocate;
223 widget_class->focus = hildon_composite_widget_focus;
225 editor_class->range_error = hildon_number_editor_range_error;
227 /* Because we derived our widget from GtkContainer, we should override
229 container_class->forall = hildon_number_editor_forall;
230 GTK_OBJECT_CLASS(editor_class)->destroy = hildon_number_editor_destroy;
231 gobject_class->finalize = hildon_number_editor_finalize;
232 gobject_class->set_property = hildon_number_editor_set_property;
233 gobject_class->get_property = hildon_number_editor_get_property;
235 g_object_class_install_property(gobject_class, PROP_VALUE,
236 g_param_spec_int("value",
238 "The current value of number editor",
241 0, G_PARAM_READWRITE));
243 HildonNumberEditor_signal[RANGE_ERROR] =
244 g_signal_new("range_error", HILDON_TYPE_NUMBER_EDITOR,
245 G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET
246 (HildonNumberEditorClass, range_error),
247 g_signal_accumulator_true_handled, NULL,
248 _hildon_marshal_BOOLEAN__ENUM,
249 G_TYPE_BOOLEAN, 1, HILDON_TYPE_NUMBER_EDITOR_ERROR_TYPE);
253 hildon_number_editor_forall(GtkContainer *container, gboolean include_internals,
254 GtkCallback callback, gpointer callback_data)
256 HildonNumberEditorPrivate *priv =
257 HILDON_NUMBER_EDITOR_GET_PRIVATE(container);
259 g_assert(callback != NULL);
261 if (!include_internals)
264 /* Enumerate child widgets */
265 (*callback) (priv->minus, callback_data);
266 (*callback) (priv->num_entry, callback_data);
267 (*callback) (priv->plus, callback_data);
271 hildon_number_editor_destroy(GtkObject *self)
273 HildonNumberEditorPrivate *priv;
275 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(self);
277 /* Free child widgets */
280 gtk_widget_unparent(priv->minus);
285 gtk_widget_unparent(priv->num_entry);
286 priv->num_entry = NULL;
290 gtk_widget_unparent(priv->plus);
294 if (GTK_OBJECT_CLASS(parent_class)->destroy)
295 GTK_OBJECT_CLASS(parent_class)->destroy(self);
299 hildon_number_editor_stop_repeat_timer(HildonNumberEditorPrivate *priv)
301 if (priv->button_event_id)
303 g_source_remove(priv->button_event_id);
304 priv->button_event_id = 0;
309 hildon_number_editor_finalize (GObject *self)
311 HildonNumberEditorPrivate *priv;
313 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(self);
316 hildon_number_editor_stop_repeat_timer(priv);
318 if (priv->select_all_idle_id)
319 g_source_remove (priv->select_all_idle_id);
321 /* Call parent class finalize, if have one */
322 if (G_OBJECT_CLASS (parent_class)->finalize)
323 G_OBJECT_CLASS (parent_class)->finalize(self);
327 hildon_number_editor_init (HildonNumberEditor *editor)
329 HildonNumberEditorPrivate *priv;
331 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
332 GTK_WIDGET_SET_FLAGS(GTK_WIDGET(editor), GTK_NO_WINDOW);
334 /* Create child widgets */
335 priv->num_entry = gtk_entry_new();
336 priv->minus = gtk_button_new();
337 priv->plus = gtk_button_new();
339 gtk_widget_set_name( priv->minus, "ne-minus-button" );
340 gtk_widget_set_name( priv->plus, "ne-plus-button" );
341 gtk_widget_set_size_request( priv->minus, BUTTON_WIDTH, BUTTON_HEIGHT );
342 gtk_widget_set_size_request( priv->plus, BUTTON_WIDTH, BUTTON_HEIGHT );
343 gtk_entry_set_alignment (GTK_ENTRY(priv->num_entry), 1);
345 GTK_WIDGET_UNSET_FLAGS( priv->minus, GTK_CAN_FOCUS );
346 GTK_WIDGET_UNSET_FLAGS( priv->plus, GTK_CAN_FOCUS );
348 priv->button_event_id = 0;
349 priv->select_all_idle_id = 0;
351 gtk_widget_set_parent(priv->minus, GTK_WIDGET(editor));
352 gtk_widget_set_parent(priv->num_entry, GTK_WIDGET(editor));
353 gtk_widget_set_parent(priv->plus, GTK_WIDGET(editor));
355 /* Connect child widget signals */
356 g_signal_connect(GTK_OBJECT(priv->num_entry), "changed",
357 G_CALLBACK(hildon_number_editor_entry_changed),
360 g_signal_connect(GTK_OBJECT(priv->num_entry), "focus-out-event",
361 G_CALLBACK(hildon_number_editor_entry_focusout),
364 g_signal_connect(GTK_OBJECT(priv->num_entry), "key-press-event",
365 G_CALLBACK(hildon_number_editor_entry_keypress),
368 g_signal_connect(GTK_OBJECT(priv->num_entry), "button-release-event",
369 G_CALLBACK(hildon_number_editor_entry_button_released),
372 g_signal_connect(GTK_OBJECT(priv->minus), "button-press-event",
373 G_CALLBACK(hildon_number_editor_button_pressed),
376 g_signal_connect(GTK_OBJECT(priv->plus), "button-press-event",
377 G_CALLBACK(hildon_number_editor_button_pressed),
380 g_signal_connect(GTK_OBJECT(priv->minus), "button-release-event",
381 G_CALLBACK(hildon_number_editor_button_released),
384 g_signal_connect(GTK_OBJECT(priv->plus), "button-release-event",
385 G_CALLBACK(hildon_number_editor_button_released),
388 g_signal_connect(GTK_OBJECT(priv->minus), "leave-notify-event",
389 G_CALLBACK(hildon_number_editor_button_released),
392 g_signal_connect(GTK_OBJECT(priv->plus), "leave-notify-event",
393 G_CALLBACK(hildon_number_editor_button_released),
396 g_object_set( G_OBJECT(priv->num_entry),
397 "input-mode", HILDON_INPUT_MODE_HINT_NUMERIC, NULL );
399 gtk_widget_show(priv->num_entry);
400 gtk_widget_show(priv->minus);
401 gtk_widget_show(priv->plus);
403 hildon_number_editor_set_range(editor, G_MININT, G_MAXINT);
407 hildon_number_editor_entry_button_released (GtkWidget *widget,
408 GdkEventButton *event,
411 gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
416 hildon_number_editor_button_released (GtkWidget *widget, GdkEvent *event,
417 HildonNumberEditor *editor)
419 HildonNumberEditorPrivate *priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
420 hildon_number_editor_stop_repeat_timer(priv);
424 /* Format given number to editor field, no checks performed, all signals
425 are sent normally. */
427 hildon_number_editor_real_set_value (HildonNumberEditorPrivate *priv, gint value)
431 /* Update text in entry to new value */
432 g_snprintf(buffer, sizeof(buffer), "%d", value);
433 gtk_entry_set_text(GTK_ENTRY(priv->num_entry), buffer);
437 hildon_number_editor_button_pressed (GtkWidget *widget, GdkEventButton *event,
440 /* FIXME: XXX Why aren't we using hildon_number_editor_start_timer here? XXX */
441 /* Need to fetch current value from entry and increment or decrement
443 HildonNumberEditor *editor;
444 HildonNumberEditorPrivate *priv;
445 GtkSettings *settings;
448 g_assert(HILDON_IS_NUMBER_EDITOR(data));
450 editor = HILDON_NUMBER_EDITOR(data);
451 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
452 settings = gtk_settings_get_default();
453 g_object_get(settings, "gtk-initial-timeout", &timeout, NULL);
455 /* Save type of button pressed */
456 if (GTK_BUTTON(widget) == GTK_BUTTON(priv->plus))
457 priv->button_type = 1;
459 priv->button_type = -1;
461 /* Start repetition timer */
462 if (!priv->button_event_id)
464 do_mouse_timeout(editor);
465 priv->button_event_id = g_timeout_add (timeout,
466 (GSourceFunc) hildon_number_editor_start_timer,
474 hildon_number_editor_start_timer (HildonNumberEditor *editor)
476 HildonNumberEditorPrivate *priv;
477 GtkSettings *settings;
480 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
481 settings = gtk_settings_get_default();
482 g_object_get(settings, "gtk-update-timeout", &timeout, NULL);
484 priv->button_event_id = g_timeout_add(timeout,
485 (GSourceFunc) do_mouse_timeout,
491 do_mouse_timeout (HildonNumberEditor *editor)
493 HildonNumberEditorPrivate *priv;
495 GDK_THREADS_ENTER ();
497 g_assert(HILDON_IS_NUMBER_EDITOR(editor));
499 /* Update value based on button held */
500 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
501 change_numbers(editor, priv->button_type);
503 GDK_THREADS_LEAVE ();
508 /* Changes the current number value by the amount of update
509 and verifies the result. */
511 change_numbers (HildonNumberEditor *editor, gint update)
513 HildonNumberEditorPrivate *priv;
516 g_assert(HILDON_IS_NUMBER_EDITOR(editor));
518 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
519 current_value = hildon_number_editor_get_value(editor);
521 /* We need to rerun validation by hand, since validation
522 done in "changed" callback allows intermediate values */
523 hildon_number_editor_real_set_value(priv, current_value + update);
524 hildon_number_editor_validate_value(editor, FALSE);
525 g_object_notify (G_OBJECT(editor), "value");
529 add_select_all_idle (HildonNumberEditorPrivate *priv)
531 if (!priv->select_all_idle_id)
533 priv->select_all_idle_id =
534 g_idle_add((GSourceFunc) hildon_number_editor_select_all, priv);
539 hildon_number_editor_validate_value(HildonNumberEditor *editor, gboolean allow_intermediate)
541 HildonNumberEditorPrivate *priv;
542 gint error_code, fixup_value;
548 g_assert(HILDON_IS_NUMBER_EDITOR(editor));
550 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
551 text = gtk_entry_get_text(GTK_ENTRY(priv->num_entry));
553 fixup_value = priv->default_val;
557 /* Try to convert entry text to number */
558 value = strtol(text, &tail, 10);
560 /* Check if conversion succeeded */
563 /* Check if value is in allowed range. This is tricky in those
564 cases when user is editing a value.
565 For example: Range = [100, 500] and user have just inputted "4".
566 This should not lead into error message. Otherwise value is
567 resetted back to "100" and next "4" press will reset it back
569 if (allow_intermediate)
571 /* We now have the following error cases:
572 * If inputted value as above maximum and
573 maximum is either positive or then maximum
574 negative and value is positive.
575 * If inputted value is below minimum and minimum
576 is negative or minumum positive and value
578 In all other cases situation can be fixed just by
579 adding new numbers to the string.
581 if (value > priv->end && (priv->end >= 0 || (priv->end < 0 && value >= 0)))
583 error_code = MAXIMUM_VALUE_EXCEED;
584 fixup_value = priv->end;
586 else if (value < priv->start && (priv->start < 0 || (priv->start >= 0 && value <= 0)))
588 error_code = MINIMUM_VALUE_EXCEED;
589 fixup_value = priv->start;
594 if (value > priv->end) {
595 error_code = MAXIMUM_VALUE_EXCEED;
596 fixup_value = priv->end;
598 else if (value < priv->start) {
599 error_code = MINIMUM_VALUE_EXCEED;
600 fixup_value = priv->start;
604 /* The only valid case when conversion can fail is when we
605 have plain '-', intermediate forms are allowed AND
606 minimum bound is negative */
607 else if (!allow_intermediate || strcmp(text, "-") != 0 || priv->start >= 0)
608 error_code = ERRONEOUS_VALUE;
610 else if (!allow_intermediate)
611 error_code = ERRONEOUS_VALUE;
613 if (error_code != -1)
615 /* If entry is empty and intermediate forms are nor allowed,
617 /* Change to default value */
618 hildon_number_editor_set_value(editor, fixup_value);
619 g_signal_emit(editor, HildonNumberEditor_signal[RANGE_ERROR],
621 add_select_all_idle(priv);
626 hildon_number_editor_entry_changed(GtkWidget *widget, gpointer data)
628 g_assert(HILDON_IS_NUMBER_EDITOR(data));
629 hildon_number_editor_validate_value(HILDON_NUMBER_EDITOR(data), TRUE);
630 g_object_notify (G_OBJECT(data), "value");
634 hildon_number_editor_size_request (GtkWidget *widget,
635 GtkRequisition *requisition)
637 HildonNumberEditor *editor;
638 HildonNumberEditorPrivate *priv;
641 editor = HILDON_NUMBER_EDITOR(widget);
642 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
644 /* Requested size is size of all child widgets plus border space */
645 gtk_widget_size_request(priv->minus, &req);
646 requisition->width = req.width;
648 gtk_widget_size_request(priv->num_entry, &req);
649 requisition->width += req.width;
651 gtk_widget_size_request(priv->plus, &req);
652 requisition->width += req.width;
654 requisition->width += HILDON_MARGIN_DEFAULT * 2;
656 /* FIXME: XXX Height is fixed */
657 requisition->height = NUMBER_EDITOR_HEIGHT;
660 /* Update @alloc->width so widget fits, update @alloc->x to point to free space */
662 set_widget_allocation (GtkWidget *widget, GtkAllocation *alloc,
663 const GtkAllocation *allocation)
665 GtkRequisition child_requisition;
667 gtk_widget_get_child_requisition(widget, &child_requisition);
669 /* Fit to widget width */
670 if (allocation->width + allocation->x >
671 alloc->x + child_requisition.width)
672 alloc->width = child_requisition.width;
675 alloc->width = allocation->width - (alloc->x - allocation->x);
676 if (alloc->width < 0)
680 gtk_widget_size_allocate(widget, alloc);
681 /* Update x position */
682 alloc->x += alloc->width;
686 hildon_number_editor_size_allocate (GtkWidget *widget,
687 GtkAllocation *allocation)
689 HildonNumberEditor *editor;
690 HildonNumberEditorPrivate *priv;
693 editor = HILDON_NUMBER_EDITOR(widget);
694 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
696 widget->allocation = *allocation;
698 /* Add upper border */
699 alloc.y = widget->allocation.y + widget->style->ythickness;
702 if (widget->allocation.height > NUMBER_EDITOR_HEIGHT)
704 alloc.height = NUMBER_EDITOR_HEIGHT - widget->style->ythickness * 2;
705 alloc.y += (widget->allocation.height - NUMBER_EDITOR_HEIGHT) / 2;
708 alloc.height = widget->allocation.height - widget->style->ythickness * 2;
710 if (alloc.height < 0)
713 /* Add left border */
714 alloc.x = allocation->x + widget->style->xthickness;
716 /* Allocate positions for widgets (left-to-right) */
717 set_widget_allocation(priv->minus, &alloc, &widget->allocation);
718 alloc.x += HILDON_MARGIN_DEFAULT;
720 set_widget_allocation(priv->num_entry, &alloc, &widget->allocation);
721 alloc.x += HILDON_MARGIN_DEFAULT;
723 set_widget_allocation(priv->plus, &alloc, &widget->allocation);
727 hildon_number_editor_entry_focusout (GtkWidget *widget, GdkEventFocus *event,
730 g_assert(HILDON_IS_NUMBER_EDITOR(data));
731 hildon_number_editor_validate_value(HILDON_NUMBER_EDITOR(data), FALSE);
736 hildon_number_editor_entry_keypress (GtkWidget *widget, GdkEventKey *event,
739 GtkEditable *editable;
742 g_assert(HILDON_IS_NUMBER_EDITOR(data));
744 editable = GTK_EDITABLE(widget);
745 cursor_pos = gtk_editable_get_position(editable);
747 switch (event->keyval)
750 /* If the cursor is on the left, try to decrement */
751 if (cursor_pos == 0) {
752 change_numbers(HILDON_NUMBER_EDITOR(data), -1);
758 /* If the cursor is on the right, try to increment */
759 if (cursor_pos >= g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1))
761 change_numbers(HILDON_NUMBER_EDITOR(data), 1);
762 gtk_editable_set_position(editable, cursor_pos);
775 hildon_number_editor_range_error(HildonNumberEditor *editor,
776 HildonNumberEditorErrorType type)
780 gchar *err_msg = NULL;
781 HildonNumberEditorPrivate *priv;
783 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
787 /* Construct error message */
790 case MAXIMUM_VALUE_EXCEED:
791 err_msg = g_strdup_printf(_("ckct_ib_maximum_value"), max, max);
793 case MINIMUM_VALUE_EXCEED:
794 err_msg = g_strdup_printf(_("ckct_ib_minimum_value"), min, min);
796 case ERRONEOUS_VALUE:
798 g_strdup_printf(_("ckct_ib_set_a_value_within_range"), min, max);
802 /* Infoprint error */
805 gtk_infoprint(GTK_WINDOW(gtk_widget_get_ancestor(GTK_WIDGET(editor),
806 GTK_TYPE_WINDOW)), err_msg);
815 * hildon_number_editor_new:
816 * @min: minimum accepted value
817 * @max: maximum accepted value
819 * Creates new number editor
821 * Returns: a new #HildonNumberEditor widget
824 hildon_number_editor_new (gint min, gint max)
826 HildonNumberEditor *editor =
827 g_object_new(HILDON_TYPE_NUMBER_EDITOR, NULL);
829 /* Set user inputted range to editor */
830 hildon_number_editor_set_range(editor, min, max);
832 return GTK_WIDGET(editor);
836 * hildon_number_editor_set_range:
837 * @editor: a #HildonNumberEditor widget
838 * @min: minimum accepted value
839 * @max: maximum accepted value
841 * Sets accepted number range for editor
844 hildon_number_editor_set_range (HildonNumberEditor *editor, gint min, gint max)
846 HildonNumberEditorPrivate *priv;
847 gchar buffer_min[32], buffer_max[32];
850 g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor));
852 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
854 /* Set preferences */
855 priv->start = MIN(min, max);
856 priv->end = MAX(min, max);
858 /* Find maximum allowed length of value */
859 g_snprintf(buffer_min, sizeof(buffer_min), "%d", min);
860 g_snprintf(buffer_max, sizeof(buffer_max), "%d", max);
861 a = strlen(buffer_min);
862 b = strlen(buffer_max);
864 /* Set maximum size of entry */
865 gtk_entry_set_width_chars(GTK_ENTRY(priv->num_entry), MAX(a, b));
866 hildon_number_editor_set_value(editor, priv->start);
870 * hildon_number_editor_get_value:
871 * @editor: pointer to #HildonNumberEditor
873 * Returns: current NumberEditor value
876 hildon_number_editor_get_value (HildonNumberEditor *editor)
878 HildonNumberEditorPrivate *priv;
880 g_return_val_if_fail(HILDON_IS_NUMBER_EDITOR(editor), 0);
882 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
883 return atoi(gtk_entry_get_text(GTK_ENTRY(priv->num_entry)));
887 * hildon_number_editor_set_value:
888 * @editor: pointer to #HildonNumberEditor
889 * @value: numeric value for number editor
891 * Sets numeric value for number editor
894 hildon_number_editor_set_value (HildonNumberEditor *editor, gint value)
896 HildonNumberEditorPrivate *priv;
898 g_return_if_fail(HILDON_IS_NUMBER_EDITOR(editor));
900 priv = HILDON_NUMBER_EDITOR_GET_PRIVATE(editor);
902 g_return_if_fail(value <= priv->end);
903 g_return_if_fail(value >= priv->start);
905 priv->default_val = value;
906 hildon_number_editor_real_set_value(priv, value);
907 g_object_notify (G_OBJECT(editor), "value");
910 /* When calling gtk_entry_set_text, the entry widget does things that can
911 * cause the whole widget to redraw. This redrawing is delayed and if any
912 * selections are made right after calling the gtk_entry_set_text the
913 * setting of the selection might seem to have no effect.
915 * If the selection is delayed with a lower priority than the redrawing,
916 * the selection should stick. Calling this function with g_idle_add should
920 hildon_number_editor_select_all (HildonNumberEditorPrivate *priv)
922 GDK_THREADS_ENTER ();
923 gtk_editable_select_region(GTK_EDITABLE(priv->num_entry), 0, -1);
924 priv->select_all_idle_id = 0;
925 GDK_THREADS_LEAVE ();
930 hildon_number_editor_set_property(GObject * object,
932 const GValue * value, GParamSpec * pspec)
934 HildonNumberEditor *editor;
936 editor = HILDON_NUMBER_EDITOR(object);
940 hildon_number_editor_set_value(editor, g_value_get_int(value));
943 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
949 hildon_number_editor_get_property(GObject * object,
950 guint prop_id, GValue * value, GParamSpec * pspec)
952 HildonNumberEditor *editor;
954 editor = HILDON_NUMBER_EDITOR(object);
958 g_value_set_int(value, hildon_number_editor_get_value(editor));
961 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);