2006-11-01 Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
[hildon] / hildon-widgets / hildon-seekbar.c
index 39dac07..34d3b50 100644 (file)
@@ -1,14 +1,14 @@
 /*
  * 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
@@ -46,8 +51,6 @@
 
 #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));
@@ -60,7 +63,6 @@ static GtkScaleClass *parent_class = NULL;
 /* 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,
@@ -85,15 +87,10 @@ static gboolean hildon_seekbar_button_release_event(GtkWidget * widget,
 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
@@ -104,9 +101,10 @@ static gboolean hildon_seekbar_keypress(GtkWidget * widget,
 #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
@@ -115,7 +113,12 @@ static gboolean hildon_seekbar_keypress(GtkWidget * widget,
  * 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,
@@ -124,9 +127,7 @@ enum {
 
 /* 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
@@ -167,12 +168,10 @@ static void hildon_seekbar_class_init(HildonSeekbarClass * seekbar_class)
     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;
@@ -181,12 +180,9 @@ static void hildon_seekbar_class_init(HildonSeekbarClass * seekbar_class)
         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",
@@ -224,6 +220,7 @@ static void hildon_seekbar_init(HildonSeekbar * seekbar)
 
     priv = HILDON_SEEKBAR_GET_PRIVATE(seekbar);
 
+    /* Initialize range widget */
     range->orientation = GTK_ORIENTATION_HORIZONTAL;
     range->flippable = TRUE;
     range->has_stepper_a = TRUE;
@@ -233,21 +230,11 @@ static void hildon_seekbar_init(HildonSeekbar * seekbar)
     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)
 {
@@ -257,7 +244,6 @@ static gboolean hildon_seekbar_keypress(GtkWidget * widget,
                                                                event));
 }
 
-/* handle setting of seekbar properties */
 static void
 hildon_seekbar_set_property(GObject * object, guint prop_id,
                             const GValue * value, GParamSpec * pspec)
@@ -307,25 +293,21 @@ hildon_seekbar_get_property(GObject * object, guint prop_id,
 /**
  * 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;
@@ -337,13 +319,11 @@ gint hildon_seekbar_get_total_time(HildonSeekbar *seekbar)
 
 /**
  * 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;
@@ -362,16 +342,19 @@ void hildon_seekbar_set_total_time(HildonSeekbar *seekbar, gint time)
     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,
@@ -392,13 +375,12 @@ void hildon_seekbar_set_total_time(HildonSeekbar *seekbar, gint time)
 
 /**
  * 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 );
@@ -408,12 +390,12 @@ guint hildon_seekbar_get_fraction( HildonSeekbar *seekbar )
 
 /**
  * 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;
@@ -430,6 +412,7 @@ void hildon_seekbar_set_fraction( HildonSeekbar *seekbar, guint fraction )
   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))
@@ -440,14 +423,12 @@ void hildon_seekbar_set_fraction( HildonSeekbar *seekbar, guint fraction )
 
 /**
  * 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);
@@ -458,12 +439,11 @@ gint hildon_seekbar_get_position(HildonSeekbar *seekbar)
 
 /**
  * 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;
@@ -493,21 +473,22 @@ void hildon_seekbar_set_position(HildonSeekbar *seekbar, gint time)
 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;
 }
@@ -521,32 +502,31 @@ static void hildon_seekbar_size_allocate(GtkWidget * widget,
 
     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);
 }
@@ -563,6 +543,7 @@ static gboolean hildon_seekbar_expose(GtkWidget * widget,
                                             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",
@@ -578,21 +559,18 @@ static gboolean hildon_seekbar_expose(GtkWidget * widget,
 }
 
 /*
- * 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)
@@ -601,27 +579,23 @@ hildon_seekbar_button_press_event(GtkWidget * widget,
 
     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;
 }