diff options
Diffstat (limited to 'hildon/hildon-controlbar.c')
-rw-r--r-- | hildon/hildon-controlbar.c | 893 |
1 files changed, 893 insertions, 0 deletions
diff --git a/hildon/hildon-controlbar.c b/hildon/hildon-controlbar.c new file mode 100644 index 0000000..e9b4d8e --- /dev/null +++ b/hildon/hildon-controlbar.c @@ -0,0 +1,893 @@ +/* + * This file is a part of hildon + * + * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved. + * + * Contact: Rodrigo Novo <rodrigo.novo@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; version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +/** + * SECTION:hildon-controlbar + * @short_description: A widget that allows increasing or decreasing + * a value within a pre-defined range. + * + * #HildonControlbar is a horizontally positioned range widget that is + * visually divided into blocks and supports setting a minimum and + * maximum value for the range. + * + * <note> + * <para> + * #HildonControlbar has been deprecated since Hildon 2.2 + * See <link linkend="hildon-migrating-control-bar">Migrating Control Bars</link> + * section to know how to migrate this deprecated widget. + * </para> + * </note> + * + * <example> + * <title>HildonControlbar example</title> + * <programlisting> + * GtkWidget *cbar = hildon_controlbar_new(); + * hildon_controlbar_set_max (HILDON_CONTROLBAR (cbar), 12); + * hildon_controlbar_set_value (HILDON_CONTROLBAR (cbar), 6); + * </programlisting> + * </example> + * + */ + +#undef HILDON_DISABLE_DEPRECATED + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <math.h> +#include <libintl.h> +#include <gdk/gdk.h> +#include <gdk/gdkkeysyms.h> + +#include "hildon-controlbar.h" +#include "hildon-controlbar-private.h" + +#define _(string)\ + dgettext("hildon-libs", string) + +#define DEFAULT_WIDTH 234 + +#define DEFAULT_HEIGHT 60 + +#define DEFAULT_BORDER_WIDTH 0 + +#define HILDON_CONTROLBAR_STEP_INCREMENT 1 + +#define HILDON_CONTROLBAR_PAGE_INCREMENT 1 + +#define HILDON_CONTROLBAR_PAGE_SIZE 0 + +#define HILDON_CONTROLBAR_UPPER_VALUE 10 + +#define HILDON_CONTROLBAR_LOWER_VALUE 0.0 + +#define HILDON_CONTROLBAR_INITIAL_VALUE 0 + +static GtkScaleClass* parent_class; + +enum +{ + PROP_0, + PROP_MIN = 1, + PROP_MAX, + PROP_VALUE +}; + +enum +{ + END_REACHED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static void +hildon_controlbar_class_init (HildonControlbarClass *controlbar_class); + +static void +hildon_controlbar_init (HildonControlbar *controlbar); + +static GObject* +hildon_controlbar_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties); + +static gint +hildon_controlbar_button_press_event (GtkWidget *widget, + GdkEventButton * event); + +static gint +hildon_controlbar_button_release_event (GtkWidget *widget, + GdkEventButton *event); + +static gint +hildon_controlbar_expose_event (GtkWidget *widget, + GdkEventExpose *event); + +static void +hildon_controlbar_size_request (GtkWidget *self, + GtkRequisition *req); +static void +hildon_controlbar_paint (HildonControlbar *self, + GdkRectangle * area); + +static gboolean +hildon_controlbar_keypress (GtkWidget *widget, + GdkEventKey * event); + +static void +hildon_controlbar_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec); + +static void +hildon_controlbar_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec); + +static void +hildon_controlbar_value_changed (GtkAdjustment *adj, + GtkRange *range); + +static gboolean +hildon_controlbar_change_value (GtkRange *range, + GtkScrollType scroll, + gdouble new_value, + gpointer data); + +/** + * hildon_controlbar_get_type: + * + * Initializes and returns the type of a hildon control bar. + * + * Returns: GType of #HildonControlbar + */ +GType G_GNUC_CONST +hildon_controlbar_get_type (void) +{ + static GType controlbar_type = 0; + + if (!controlbar_type) { + static const GTypeInfo controlbar_info = { + sizeof (HildonControlbarClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) hildon_controlbar_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (HildonControlbar), + 0, /* n_preallocs */ + (GInstanceInitFunc) hildon_controlbar_init, + }; + controlbar_type = g_type_register_static (GTK_TYPE_SCALE, + "HildonControlbar", + &controlbar_info, 0); + } + + return controlbar_type; +} + +static void +hildon_controlbar_class_init (HildonControlbarClass *controlbar_class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (controlbar_class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (controlbar_class); + + parent_class = g_type_class_peek_parent(controlbar_class); + + g_type_class_add_private(controlbar_class, sizeof (HildonControlbarPrivate)); + + gobject_class->get_property = hildon_controlbar_get_property; + gobject_class->set_property = hildon_controlbar_set_property; + gobject_class->constructor = hildon_controlbar_constructor; + widget_class->size_request = hildon_controlbar_size_request; + widget_class->button_press_event = hildon_controlbar_button_press_event; + widget_class->button_release_event = hildon_controlbar_button_release_event; + widget_class->expose_event = hildon_controlbar_expose_event; + widget_class->key_press_event = hildon_controlbar_keypress; + controlbar_class->end_reached = NULL; + + /** + * HildonControlbar:min: + * + * Controlbar minimum value. + */ + g_object_class_install_property (gobject_class, PROP_MIN, + g_param_spec_int ("min", + "Minimum value", + "Smallest possible value", + G_MININT, G_MAXINT, + HILDON_CONTROLBAR_LOWER_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + /** + * HildonControlbar:max: + * + * Controlbar maximum value. + */ + g_object_class_install_property (gobject_class, PROP_MAX, + g_param_spec_int ("max", + "Maximum value", + "Greatest possible value", + G_MININT, G_MAXINT, + HILDON_CONTROLBAR_UPPER_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE)); + + /** + * HildonControlbar:value: + * + * Controlbar current value. + */ + g_object_class_install_property (gobject_class, PROP_VALUE, + g_param_spec_int ("value", + "Current value", + "Current value", + G_MININT, G_MAXINT, + HILDON_CONTROLBAR_INITIAL_VALUE, + G_PARAM_READABLE | G_PARAM_WRITABLE) ); + + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_uint ("inner_border_width", + "Inner border width", + "The border spacing between the controlbar border and controlbar blocks.", + 0, G_MAXINT, + DEFAULT_BORDER_WIDTH, + G_PARAM_READABLE)); + + signals[END_REACHED] = + g_signal_new("end-reached", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (HildonControlbarClass, end_reached), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); +} + +static void +hildon_controlbar_init (HildonControlbar *controlbar) +{ + GtkRange *range; + HildonControlbarPrivate *priv; + + /* Initialize the private property */ + priv = HILDON_CONTROLBAR_GET_PRIVATE(controlbar); + g_assert (priv); + + priv->button_press = FALSE; + priv->old_value = 0; + range = GTK_RANGE (controlbar); + + range->round_digits = -1; + + gtk_widget_set_size_request (GTK_WIDGET (controlbar), + DEFAULT_WIDTH, + DEFAULT_HEIGHT); + + g_signal_connect (range, "change-value", + G_CALLBACK (hildon_controlbar_change_value), NULL); +} + +static GObject* +hildon_controlbar_constructor (GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *obj; + GtkAdjustment *adj; + + obj = G_OBJECT_CLASS (parent_class)->constructor (type, + n_construct_properties, construct_properties); + + gtk_scale_set_draw_value (GTK_SCALE (obj), FALSE); + + /* Initialize the GtkAdjustment of the controlbar*/ + adj = GTK_RANGE (obj)->adjustment; + adj->step_increment = HILDON_CONTROLBAR_STEP_INCREMENT; + adj->page_increment = HILDON_CONTROLBAR_PAGE_INCREMENT; + adj->page_size = HILDON_CONTROLBAR_PAGE_SIZE; + + g_signal_connect (adj, "value-changed", + G_CALLBACK (hildon_controlbar_value_changed), obj); + return obj; +} + +static void +hildon_controlbar_set_property (GObject *object, + guint param_id, + const GValue *value, + GParamSpec *pspec) +{ + HildonControlbar *controlbar = HILDON_CONTROLBAR (object); + + switch (param_id) + { + case PROP_MIN: + hildon_controlbar_set_min (controlbar, g_value_get_int(value)); + break; + + case PROP_MAX: + hildon_controlbar_set_max (controlbar, g_value_get_int(value)); + break; + + case PROP_VALUE: + hildon_controlbar_set_value (controlbar, g_value_get_int(value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + +static void hildon_controlbar_get_property (GObject *object, + guint param_id, + GValue *value, + GParamSpec *pspec) +{ + HildonControlbar *controlbar = HILDON_CONTROLBAR(object); + + switch (param_id) + { + case PROP_MIN: + g_value_set_int (value, hildon_controlbar_get_min (controlbar)); + break; + + case PROP_MAX: + g_value_set_int (value, hildon_controlbar_get_max (controlbar)); + break; + + case PROP_VALUE: + g_value_set_int (value, hildon_controlbar_get_value (controlbar)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); + break; + } +} + + +static void +hildon_controlbar_value_changed (GtkAdjustment *adj, + GtkRange *range) +{ + HildonControlbarPrivate *priv = HILDON_CONTROLBAR_GET_PRIVATE(range); + g_assert (priv); + + /* Change the controlbar value if the adjusted value is large enough + * otherwise, keep the old value + */ + if (ABS(ceil (adj->value) - priv->old_value) >= 1) + { + priv->old_value = ceil (adj->value); + adj->value = priv->old_value; + } + else + g_signal_stop_emission_by_name (adj, "value-changed"); + + gtk_adjustment_set_value (adj, priv->old_value); +} + +/** + * hildon_controlbar_new: + * + * Creates a new #HildonControlbar widget. + * + * Returns: a #GtkWidget pointer of newly created control bar + * widget + */ +GtkWidget* +hildon_controlbar_new (void) +{ + return GTK_WIDGET (g_object_new (HILDON_TYPE_CONTROLBAR, NULL)); +} + +/* This function prevents Up and Down keys from changing the + * widget's value (like Left and Right). + * Instead they are used for changing focus to other widgtes. + */ +static gboolean +hildon_controlbar_keypress (GtkWidget *widget, + GdkEventKey *event) +{ + if (event->keyval == GDK_Up || event->keyval == GDK_Down) + return FALSE; + + return ((GTK_WIDGET_CLASS (parent_class)->key_press_event) (widget, event)); +} + +static void +hildon_controlbar_size_request (GtkWidget *self, + GtkRequisition *req) +{ + if (GTK_WIDGET_CLASS (parent_class)->size_request) + GTK_WIDGET_CLASS (parent_class)->size_request(self, req); + + req->width = DEFAULT_WIDTH; + req->height = DEFAULT_HEIGHT; +} + +/** + * hildon_controlbar_set_value: + * @self: pointer to #HildonControlbar + * @value: value in range of >= 0 && < G_MAX_INT + * + * Set the current value of the control bar to the specified value. + */ +void +hildon_controlbar_set_value (HildonControlbar * self, + gint value) +{ + GtkAdjustment *adj; + g_return_if_fail (HILDON_IS_CONTROLBAR (self)); + adj = GTK_RANGE (self)->adjustment; + + g_return_if_fail (value >= 0); + + if (value >= adj->upper) + value = adj->upper; + else if (value <= adj->lower) + value = adj->lower; + + adj->value = value; + gtk_adjustment_value_changed (adj); + + g_object_notify (G_OBJECT(self), "value"); +} + +/** + * hildon_controlbar_get_value: + * @self: pointer to #HildonControlbar + * + * Returns: current value as gint + */ +gint +hildon_controlbar_get_value (HildonControlbar * self) +{ + GtkAdjustment *adj; + g_return_val_if_fail (HILDON_IS_CONTROLBAR (self), 0); + adj = GTK_RANGE(self)->adjustment; + + return (gint) ceil(adj->value); +} + +/** + * hildon_controlbar_set_max: + * @self: pointer to #HildonControlbar + * @max: maximum value to set. The value needs to be greater than 0. + * + * Set the control bar's maximum to the given value. + * + * If the new maximum is smaller than current value, the value will be + * adjusted so that it equals the new maximum. + */ +void +hildon_controlbar_set_max (HildonControlbar * self, + gint max) +{ + GtkAdjustment *adj; + g_return_if_fail (HILDON_IS_CONTROLBAR (self)); + adj = GTK_RANGE (self)->adjustment; + + if (max < adj->lower) + max = adj->lower; + + if (adj->value > max) + hildon_controlbar_set_value (self, max); + + adj->upper = max; + gtk_adjustment_changed (adj); + + g_object_notify (G_OBJECT(self), "max"); +} + +/** + * hildon_controlbar_set_min: + * @self: pointer to #HildonControlbar + * @min: minimum value to set. The value needs to be greater than or + * equal to 0. + * + * Set the control bar's minimum to the given value. + * + * If the new minimum is smaller than current value, the value will be + * adjusted so that it equals the new minimum. + */ +void +hildon_controlbar_set_min (HildonControlbar *self, + gint min) +{ + GtkAdjustment *adj; + g_return_if_fail (HILDON_IS_CONTROLBAR (self)); + adj = GTK_RANGE (self)->adjustment; + + if (min > adj->upper) + min = adj->upper; + + if (adj->value < min) + hildon_controlbar_set_value (self, min); + + adj->lower = min; + gtk_adjustment_changed (adj); + g_object_notify (G_OBJECT(self), "min"); +} + +/** + * hildon_controlbar_set_range: + * @self: pointer to #HildonControlbar + * @max: maximum value to set. The value needs to be greater than 0. + * @min: Minimum value to set. The value needs to be greater than or + * equal to 0. + * + * Set the controlbars range to the given value + * + * If the new maximum is smaller than current value, the value will be + * adjusted so that it equals the new maximum. + * + * If the new minimum is smaller than current value, the value will be + * adjusted so that it equals the new minimum. + */ +void +hildon_controlbar_set_range (HildonControlbar *self, + gint min, + gint max) +{ + g_return_if_fail (HILDON_IS_CONTROLBAR (self)); + + if (min > max) + min = max; + + /* We need to set max first here, because when min is set before + * max is set, it would end up 0, because max can't be bigger than 0. + */ + hildon_controlbar_set_max (self, max); + hildon_controlbar_set_min (self, min); +} + +/** + * hildon_controlbar_get_max: + * @self: a pointer to #HildonControlbar + * + * Returns: maximum value of control bar + */ +gint hildon_controlbar_get_max (HildonControlbar *self) +{ + GtkAdjustment *adj; + g_return_val_if_fail (HILDON_IS_CONTROLBAR (self), 0); + adj = GTK_RANGE (self)->adjustment; + + return (gint) adj->upper; +} + +/** + * hildon_controlbar_get_min: + * @self: a pointer to #HildonControlbar + * + * Returns: minimum value of controlbar + */ +gint +hildon_controlbar_get_min (HildonControlbar *self) +{ + GtkAdjustment *adj = GTK_RANGE (self)->adjustment; + return (gint) adj->lower; +} + +/* + * Event handler for button press + * Need to change button1 to button2 before passing this event to + * parent handler. (see specs) + * Also updates button_press variable so that we can draw highlights + * correctly + */ +static gint +hildon_controlbar_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + HildonControlbar *self; + HildonControlbarPrivate *priv; + gboolean result = FALSE; + + g_return_val_if_fail (widget, FALSE); + g_return_val_if_fail (event, FALSE); + + self = HILDON_CONTROLBAR (widget); + priv = HILDON_CONTROLBAR_GET_PRIVATE (self); + g_assert (priv); + + priv->button_press = TRUE; + event->button = event->button == 1 ? 2 : event->button; + + /* Ugh dirty hack. We manipulate the mouse event location to + compensate for centering the widget in case it is taller than the + default height. */ + if (widget->allocation.height > DEFAULT_HEIGHT) { + gint difference = widget->allocation.height - DEFAULT_HEIGHT; + + if (difference & 1) + difference += 1; + difference = difference / 2; + + event->y -= difference; + } + + + /* call the parent handler */ + if (GTK_WIDGET_CLASS (parent_class)->button_press_event) + result = GTK_WIDGET_CLASS (parent_class)->button_press_event(widget, event); + + return result; +} + +/* + * Purpose of this function is to prevent Up and Down keys from + * changing the widget's value (like Left and Right). Instead they + * are used for changing focus to other widgtes. + */ +static gboolean +hildon_controlbar_change_value (GtkRange *range, + GtkScrollType scroll, + gdouble new_value, + gpointer data) +{ + HildonControlbarPrivate *priv; + GtkAdjustment *adj = range->adjustment; + gdouble vv = adj->upper - adj->lower; + gint calc = ((new_value - adj->lower) / vv) * (vv + 1.0) + adj->lower; + + priv = HILDON_CONTROLBAR_GET_PRIVATE(range); + g_assert (priv); + + /* Emit a signal when upper or lower limit is reached */ + switch (scroll) + { + case GTK_SCROLL_STEP_FORWARD : + case GTK_SCROLL_PAGE_FORWARD : + if( adj->value == priv->old_value ) + if( adj->value == adj->upper ) + g_signal_emit( G_OBJECT(range), signals[END_REACHED], 0, TRUE ); + break; + + case GTK_SCROLL_STEP_BACKWARD : + case GTK_SCROLL_PAGE_BACKWARD : + if( adj->value == priv->old_value ) + if( adj->value == adj->lower ) + g_signal_emit( G_OBJECT(range), signals[END_REACHED], 0, FALSE ); + break; + + default: + break; + } + + GTK_RANGE_CLASS (parent_class)->change_value (range, scroll, calc); + + return TRUE; +} + +/* + * Event handler for button release + * Need to change button1 to button2 before passing this event to + * parent handler. (see specs) + * Also updates button_press variable so that we can draw hilites + * correctly + */ +static gint +hildon_controlbar_button_release_event (GtkWidget *widget, + GdkEventButton *event) +{ + HildonControlbar *self; + HildonControlbarPrivate *priv; + gboolean result = FALSE; + + g_return_val_if_fail (widget, FALSE); + g_return_val_if_fail (event, FALSE); + + self = HILDON_CONTROLBAR (widget); + priv = HILDON_CONTROLBAR_GET_PRIVATE (self); + g_assert (priv); + + priv->button_press = FALSE; + event->button = event->button == 1 ? 2 : event->button; + + /* call the parent handler */ + if (GTK_WIDGET_CLASS (parent_class)->button_release_event) + result = GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event); + + return result; +} + +/* + * Event handler for expose event + */ +static gint +hildon_controlbar_expose_event (GtkWidget *widget, + GdkEventExpose * event) +{ + HildonControlbar *self = NULL; + + gboolean result = FALSE; + gint old_height = -1; + gint old_y = -1; + + g_return_val_if_fail (event, FALSE); + g_return_val_if_fail (HILDON_IS_CONTROLBAR(widget), FALSE); + + self = HILDON_CONTROLBAR(widget); + + old_height = widget->allocation.height; + old_y = widget->allocation.y; + + if (widget->allocation.height > DEFAULT_HEIGHT) { + int difference = widget->allocation.height - DEFAULT_HEIGHT; + + if (difference & 1) + difference += 1; + + difference = difference / 2; + + widget->allocation.y += difference; + widget->allocation.height = DEFAULT_HEIGHT; + } + + /* call the parent handler */ + if (GTK_WIDGET_CLASS (parent_class)->expose_event) + result = GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); + + hildon_controlbar_paint (self, &event->area); + + widget->allocation.height = old_height; + widget->allocation.y = old_y; + + return TRUE; +} + +/* + * Paint method. + * This is where all the work is actually done... + */ +static void +hildon_controlbar_paint (HildonControlbar *self, + GdkRectangle *area) +{ + HildonControlbarPrivate *priv; + GtkWidget *widget = GTK_WIDGET(self); + GtkAdjustment *ctrlbar = GTK_RANGE(self)->adjustment; + gint x = widget->allocation.x; + gint y = widget->allocation.y; + gint h = widget->allocation.height; + gint w = widget->allocation.width; + gint max = 0; + gint stepper_size = 0; + gint stepper_spacing = 0; + gint inner_border_width = 0; + gint block_area = 0, block_width = 0, block_x = 0, block_max = 0, block_height,block_y; + /* Number of blocks on the controlbar */ + guint block_count = 0; + /* Number of displayed active blocks */ + guint block_act = 0; + /* Minimum no. of blocks visible */ + guint block_min = 0; + gint separatingpixels = 2; + gint block_remains = 0; + gint i, start_x, end_x, current_width; + GtkStateType state = GTK_STATE_NORMAL; + + g_return_if_fail(area); + + priv = HILDON_CONTROLBAR_GET_PRIVATE(self); + g_assert (priv); + + if (GTK_WIDGET_SENSITIVE (self) == FALSE) + state = GTK_STATE_INSENSITIVE; + + gtk_widget_style_get (GTK_WIDGET (self), + "stepper-size", &stepper_size, + "stepper-spacing", &stepper_spacing, + "inner_border_width", &inner_border_width, NULL); + + block_area = (w - 2 * stepper_size - 2 * stepper_spacing - 2 * inner_border_width); + + if (block_area <= 0) + return; + + block_min = 1; + block_max = ctrlbar->upper - ctrlbar->lower + block_min; + block_act = priv->old_value - GTK_RANGE (self)->adjustment->lower + block_min; + + /* We check border width and maximum value and adjust + * separating pixels for block width here. If the block size would + * become too small, we make the separators smaller. Graceful fallback. + */ + max = ctrlbar->upper; + if(ctrlbar->upper == 0) + separatingpixels = 3; + else if ((block_area - ((max - 1) * 3)) / max >= 4) + separatingpixels = 3; + else if ((block_area - ((max - 1) * 2)) / max >= 4) + separatingpixels = 2; + else if ((block_area - ((max - 1) * 1)) / max >= 4) + separatingpixels = 1; + else + separatingpixels = 0; + + if (block_max == 0) + { + /* If block max is 0 then we dim the whole control. */ + state = GTK_STATE_INSENSITIVE; + block_width = block_area; + block_remains = 0; + block_max = 1; + } + else + { + block_width = + (block_area - (separatingpixels * (block_max - 1))) / block_max; + block_remains = + (block_area - (separatingpixels * (block_max - 1))) % block_max; + } + + block_x = x + stepper_size + stepper_spacing + inner_border_width; + block_y = y + inner_border_width; + block_height = h - 2 * inner_border_width; + + block_count = ctrlbar->value - ctrlbar->lower + block_min; + + if (block_count == 0) + block_count = 1; + /* Without this there is vertical block corruption when block_height = + 1. This should work from 0 up to whatever */ + + if (block_height < 2) + block_height = 2; + + /* + * Changed the drawing of the blocks completely, + * because of "do-not-resize-when-changing-max"-specs. + * Now the code calculates from the block_remains when + * it should add one pixel to the block and when not. + */ + + for (i = 1; i <= block_max; i++) { + + /* Here we calculate whether we add one pixel to current_width or + not. */ + start_x = block_width * (i - 1) + ((i - 1) * block_remains) / block_max; + end_x = block_width * i + (i * block_remains) / block_max; + current_width = end_x - start_x; + + gtk_paint_box (widget->style, widget->window, state, + (i <= block_count) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, + NULL, widget, "hildon_block", + block_x, block_y, current_width, + block_height); + + /* We keep the block_x separate because of the + 'separatingpixels' */ + block_x += current_width + separatingpixels; + } + +} |