/*
* This file is part of hildon-libs
*
- * Copyright (C) 2005 Nokia Corporation.
+ * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
*
- * 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
*
*/
-/*
- * @file hildon-seekbar.c
+/**
+ * SECTION:hildon-seekbar
+ * @short_description: A widget used to identify a place from a content
*
- * This file contains the API implementation for Hildon Seekbar widget.
- * Based on seekbar.gob rev 1.10
+ * HildonSeekbar allows seeking in media with a range widget. It
+ * supports for setting or getting the length (total time) of the media,
+ * the position within it and the fraction (maximum position in a
+ * stream/the amount currently downloaded). The position is clamped
+ * between zero and the total time, or zero and the fraction in case of
+ * a stream.
*/
#ifdef HAVE_CONFIG_H
#include "hildon-seekbar.h"
-#define _(String) dgettext(PACKAGE, String)
-
#define HILDON_SEEKBAR_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
HILDON_TYPE_SEEKBAR, HildonSeekbarPrivate));
/* Init functions */
static void hildon_seekbar_class_init(HildonSeekbarClass * seekbar_class);
static void hildon_seekbar_init(HildonSeekbar * seekbar);
-static void hildon_seekbar_finalize(GObject * self);
/* property functions */
static void hildon_seekbar_set_property(GObject * object, guint prop_id,
static gboolean hildon_seekbar_keypress(GtkWidget * widget,
GdkEventKey * event);
-/* private stuff */
-/*
- * Some constants
- * These should be named so that they are quite self
- * explanatory
- */
#define MINIMUM_WIDTH 115
#define DEFAULT_HEIGHT 58
+
/* Toolbar width and height defines */
#define TOOL_MINIMUM_WIDTH 75
#define TOOL_DEFAULT_HEIGHT 40
#define TOOL_EXTRA_SIDE_BORDER 0
/* the number of steps it takes to move from left to right */
-#define SECONDS_PER_MINUTE 60
#define NUM_STEPS 20
+#define SECONDS_PER_MINUTE 60
+
/* the number of digits precision for the internal range.
* note, this needs to be enough so that the step size for
* small total_times doesn't get rounded off. Currently set to 3
* add one for safety */
#define MAX_ROUND_DIGITS 3
-/* enum for properties */
+/*
+ * FIXME HildonSeekbar introduced major changes in GtkRange mostly related
+ * to stream_indicator. These changes should be minimized.
+ */
+
+/* Property indices */
enum {
PROP_TOTAL_TIME = 1,
PROP_POSITION,
/* private variables */
struct _HildonSeekbarPrivate {
- GtkWidget *label;
- gboolean draw_value;
- gboolean is_toolbar;
+ gboolean is_toolbar; /* TRUE if this widget is inside a toolbar */
guint fraction; /* This is the amount of time that has progressed from
the beginning. It should be an integer between the
minimum and maximum values of the corresponding
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(seekbar_class);
GObjectClass *object_class = G_OBJECT_CLASS(seekbar_class);
- /* set the global parent_class */
parent_class = g_type_class_peek_parent(seekbar_class);
g_type_class_add_private(seekbar_class, sizeof(HildonSeekbarPrivate));
- /* setup our widgets v-table */
widget_class->size_request = hildon_seekbar_size_request;
widget_class->size_allocate = hildon_seekbar_size_allocate;
widget_class->expose_event = hildon_seekbar_expose;
hildon_seekbar_button_release_event;
widget_class->key_press_event = hildon_seekbar_keypress;
- /* now the object stuff */
object_class->set_property = hildon_seekbar_set_property;
object_class->get_property = hildon_seekbar_get_property;
- object_class->finalize = hildon_seekbar_finalize;
- /* install the properties */
g_object_class_install_property(object_class, PROP_TOTAL_TIME,
g_param_spec_double("total_time",
"total time",
priv = HILDON_SEEKBAR_GET_PRIVATE(seekbar);
+ /* Initialize range widget */
range->orientation = GTK_ORIENTATION_HORIZONTAL;
range->flippable = TRUE;
range->has_stepper_a = TRUE;
gtk_scale_set_draw_value (GTK_SCALE (seekbar), FALSE);
}
-/* is this even necessary? */
-static void hildon_seekbar_finalize( GObject *obj_self )
-{
- HildonSeekbar *self;
- HildonSeekbarPrivate *priv;
-
- self = HILDON_SEEKBAR ( obj_self );
- priv = HILDON_SEEKBAR_GET_PRIVATE (self);
-
- if( G_OBJECT_CLASS( parent_class )->finalize )
- G_OBJECT_CLASS( parent_class )->finalize( obj_self );
-}
-
-
-/* handle keypress events */
+/*
+ * 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_seekbar_keypress(GtkWidget * widget,
GdkEventKey * event)
{
event));
}
-/* handle setting of seekbar properties */
static void
hildon_seekbar_set_property(GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
/**
* hildon_seekbar_new:
*
- * Creates a new #HildonSeekbar widget.
+ * Create a new #HildonSeekbar widget.
*
- * Return value: A #GtkWidget pointer of #HildonSeekbar widget.
+ * Returns: a #GtkWidget pointer of #HildonSeekbar widget
*/
GtkWidget *hildon_seekbar_new(void)
{
- /* return a new object */
return g_object_new(HILDON_TYPE_SEEKBAR, NULL);
}
/**
* hildon_seekbar_get_total_time:
- * @seekbar: Pointer to #HildonSeekbar widget.
- *
- * Accessor method for getting total playing time of stream
- * in seconds.
+ * @seekbar: pointer to #HildonSeekbar widget
*
- * Returns: Total time as gint.
- **/
+ * Returns: total playing time of media in seconds.
+ */
gint hildon_seekbar_get_total_time(HildonSeekbar *seekbar)
{
GtkWidget *widget;
/**
* hildon_seekbar_set_total_time:
- * @seekbar: Pointer to #HildonSeekbar widget.
- * @time: Time within range of > 0 && < G_MAXINT
+ * @seekbar: pointer to #HildonSeekbar widget
+ * @time: integer greater than zero
*
- * Accessor method for setting total playing time of stream
- * in seconds.
- *
- **/
+ * Set total playing time of media in seconds.
+ */
void hildon_seekbar_set_total_time(HildonSeekbar *seekbar, gint time)
{
GtkAdjustment *adj;
adj = GTK_RANGE(widget)->adjustment;
adj->upper = time;
+ /* Clamp position to total time */
if (adj->value > time) {
adj->value = time;
value_changed = TRUE;
}
+ /* Calculate new step value */
adj->step_increment = adj->upper / NUM_STEPS;
adj->page_increment = adj->step_increment;
gtk_adjustment_changed(adj);
+ /* Update range widget position/fraction */
if (value_changed) {
gtk_adjustment_value_changed(adj);
hildon_seekbar_set_fraction(seekbar,
/**
* hildon_seekbar_get_fraction:
- * @seekbar: Pointer to #HildonSeekbar widget.
+ * @seekbar: pointer to #HildonSeekbar widget
*
- * Accessor method for getting current fraction related to the progress indicator.
- * It should be between min and max of seekbar range.
+ * Get current fraction value of the rage.
*
- * Returns: Current fraction.
- **/
+ * Returns: current fraction
+ */
guint hildon_seekbar_get_fraction( HildonSeekbar *seekbar )
{
g_return_val_if_fail( HILDON_IS_SEEKBAR( seekbar ), 0 );
/**
* hildon_seekbar_set_fraction:
- * @seekbar: Pointer to #HildonSeekbar widget.
- * @fraction: The new position of the progress indicator.
+ * @seekbar: pointer to #HildonSeekbar widget
+ * @fraction: the new position of the progress indicator
*
- * Method for setting current value related to the progress indicator.
+ * Set current fraction value of the range.
* It should be between the minimal and maximal values of the range in seekbar.
- **/
+ */
void hildon_seekbar_set_fraction( HildonSeekbar *seekbar, guint fraction )
{
GtkRange *range = NULL;
fraction = CLAMP(fraction, range->adjustment->lower,
range->adjustment->upper);
+ /* Update stream position of range widget */
osso_gtk_range_set_stream_position( range, fraction );
if (fraction < hildon_seekbar_get_position(seekbar))
/**
* hildon_seekbar_get_position:
- * @seekbar: Pointer to #HildonSeekbar widget.
- *
- * Accessor method for getting current position in stream
- * in seconds.
+ * @seekbar: pointer to #HildonSeekbar widget
*
+ * Get current position in stream in seconds.
*
- * Returns: Current position in stream in seconds.
- **/
+ * Returns: current position in stream in seconds
+ */
gint hildon_seekbar_get_position(HildonSeekbar *seekbar)
{
g_return_val_if_fail(HILDON_IS_SEEKBAR(seekbar), 0);
/**
* hildon_seekbar_set_position:
- * @seekbar: Pointer to #HildonSeekbar widget.
- * @time: Time within range of >= 0 && < G_MAXINT
+ * @seekbar: pointer to #HildonSeekbar widget
+ * @time: time within range of >= 0 && < G_MAXINT
*
- * Accessor method for setting current position in stream
- * in seconds.
- **/
+ * Set current position in stream in seconds.
+ */
void hildon_seekbar_set_position(HildonSeekbar *seekbar, gint time)
{
GtkRange *range;
static void hildon_seekbar_size_request(GtkWidget * widget,
GtkRequisition * req)
{
- HildonSeekbar *self = NULL;
+ HildonSeekbar *self = NULL;
HildonSeekbarPrivate *priv = NULL;
GtkWidget *parent = NULL;
self = HILDON_SEEKBAR(widget);
- priv = HILDON_SEEKBAR_GET_PRIVATE(self)
+ priv = HILDON_SEEKBAR_GET_PRIVATE(self);
- parent =
- gtk_widget_get_ancestor(GTK_WIDGET(self), GTK_TYPE_TOOLBAR);
+ parent = gtk_widget_get_ancestor(GTK_WIDGET(self), GTK_TYPE_TOOLBAR);
priv->is_toolbar = parent ? TRUE : FALSE;
if (GTK_WIDGET_CLASS(parent_class)->size_request)
GTK_WIDGET_CLASS(parent_class)->size_request(widget, req);
+ /* Request minimum size, depending on whether the widget is in a
+ * toolbar or not */
req->width = priv->is_toolbar ? TOOL_MINIMUM_WIDTH : MINIMUM_WIDTH;
req->height = priv->is_toolbar ? TOOL_DEFAULT_HEIGHT : DEFAULT_HEIGHT;
}
if (priv->is_toolbar == TRUE)
{
- if (allocation->height > TOOL_DEFAULT_HEIGHT) {
+ /* Center vertically */
+ if (allocation->height > TOOL_DEFAULT_HEIGHT)
+ {
allocation->y +=
(allocation->height - TOOL_DEFAULT_HEIGHT) / 2;
allocation->height = TOOL_DEFAULT_HEIGHT;
}
+ /* Add space for border */
+ allocation->x += TOOL_EXTRA_SIDE_BORDER;
+ allocation->width -= 2 * TOOL_EXTRA_SIDE_BORDER;
}
else
{
- if (allocation->height > DEFAULT_HEIGHT) {
- allocation->y +=
- (allocation->height - DEFAULT_HEIGHT) / 2;
+ /* Center vertically */
+ if (allocation->height > DEFAULT_HEIGHT)
+ {
+ allocation->y += (allocation->height - DEFAULT_HEIGHT) / 2;
allocation->height = DEFAULT_HEIGHT;
}
- }
- if (priv->is_toolbar == TRUE)
- {
- allocation->x += TOOL_EXTRA_SIDE_BORDER;
- allocation->width -= 2 * TOOL_EXTRA_SIDE_BORDER;
- }
- else
- {
+ /* Add space for border */
allocation->x += EXTRA_SIDE_BORDER;
allocation->width -= 2 * EXTRA_SIDE_BORDER;
}
-
+
if (GTK_WIDGET_CLASS(parent_class)->size_allocate)
GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation);
}
EXTRA_SIDE_BORDER;
if (GTK_WIDGET_DRAWABLE(widget)) {
+ /* Paint border */
gtk_paint_box(widget->style, widget->window,
GTK_WIDGET_STATE(widget), GTK_SHADOW_OUT,
NULL, widget, "seekbar",
}
/*
- * Event handler for button_press_event
+ * Event handler for button press. Changes button1 to button2.
*/
static gboolean
hildon_seekbar_button_press_event(GtkWidget * widget,
GdkEventButton * event)
{
- HildonSeekbar *self;
- HildonSeekbarPrivate *priv;
-
gint result = FALSE;
- self = HILDON_SEEKBAR(widget);
- priv = HILDON_SEEKBAR_GET_PRIVATE(self);
-
- event->button = event->button == 1 ? 2 : event->button;
+ /* We change here the button id because we want to use button2
+ * functionality for button1: jump to mouse position
+ * instead of slowly incrementing to it */
+ if (event->button == 1) event->button = 2;
/* call the parent handler */
if (GTK_WIDGET_CLASS(parent_class)->button_press_event)
return result;
}
-
/*
- * Event handler for button_release_event
+ * Event handler for button release. Changes button1 to button2.
*/
static gboolean
hildon_seekbar_button_release_event(GtkWidget * widget,
GdkEventButton * event)
{
- HildonSeekbar *self;
- HildonSeekbarPrivate *priv;
gboolean result = FALSE;
- self = HILDON_SEEKBAR(widget);
- priv = HILDON_SEEKBAR_GET_PRIVATE(self);
-
+ /* We change here the button id because we want to use button2
+ * functionality for button1: jump to mouse position
+ * instead of slowly incrementing to it */
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);
+ result = GTK_WIDGET_CLASS(parent_class)->button_release_event(widget,
+ event);
return result;
}