]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkscale.c
When finding a matching non-scalable dir, keep going and look for a closer
[~andy/gtk] / gtk / gtkscale.c
index 6f65ca7de6648654d04eed27197fd374bfec511e..7cce057b9a060401bc9a338dc725f5a5d295bf5a 100644 (file)
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <config.h>
 #include <math.h>
 #include "gtkintl.h"
 #include "gtkscale.h"
 #include "gtkmarshalers.h"
 #include "gdk/gdkkeysyms.h"
 #include "gtkbindings.h"
+#include "gtkprivate.h"
+#include "gtkalias.h"
 
 
 #define        MAX_DIGITS      (64)    /* don't change this,
                                 *    unrelated code portions otherwise
                                 */
 
+#define GTK_SCALE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_SCALE, GtkScalePrivate))
+
+typedef struct _GtkScalePrivate GtkScalePrivate;
+
+struct _GtkScalePrivate
+{
+  PangoLayout *layout;
+};
+
 enum {
   PROP_0,
   PROP_DIGITS,
@@ -52,10 +64,7 @@ enum {
 };
 
 static guint signals[LAST_SIGNAL];
-static GtkRangeClass *parent_class = NULL;
 
-static void gtk_scale_class_init       (GtkScaleClass *klass);
-static void gtk_scale_init             (GtkScale      *scale);
 static void gtk_scale_set_property     (GObject       *object,
                                         guint          prop_id,
                                         const GValue  *value,
@@ -68,34 +77,11 @@ static void gtk_scale_style_set        (GtkWidget     *widget,
                                         GtkStyle      *previous);
 static void gtk_scale_get_range_border (GtkRange      *range,
                                         GtkBorder     *border);
+static void gtk_scale_finalize         (GObject       *object);
+static void gtk_scale_screen_changed   (GtkWidget     *widget,
+                                        GdkScreen     *old_screen);
 
-GType
-gtk_scale_get_type (void)
-{
-  static GType scale_type = 0;
-
-  if (!scale_type)
-    {
-      static const GTypeInfo scale_info =
-      {
-       sizeof (GtkScaleClass),
-       NULL,           /* base_init */
-       NULL,           /* base_finalize */
-       (GClassInitFunc) gtk_scale_class_init,
-       NULL,           /* class_finalize */
-       NULL,           /* class_data */
-       sizeof (GtkScale),
-       0,              /* n_preallocs */
-       (GInstanceInitFunc) gtk_scale_init,
-       NULL,           /* value_table */
-      };
-
-      scale_type = g_type_register_static (GTK_TYPE_RANGE, "GtkScale",
-                                          &scale_info, G_TYPE_FLAG_ABSTRACT);
-    }
-
-  return scale_type;
-}
+G_DEFINE_ABSTRACT_TYPE (GtkScale, gtk_scale, GTK_TYPE_RANGE)
 
 static gboolean
 single_string_accumulator (GSignalInvocationHint *ihint,
@@ -114,9 +100,9 @@ single_string_accumulator (GSignalInvocationHint *ihint,
 }
 
 
-#define add_slider_binding(binding_set, keyval, mask, scroll)          \
-  gtk_binding_entry_add_signal (binding_set, keyval, mask,             \
-                                "move_slider", 1,                      \
+#define add_slider_binding(binding_set, keyval, mask, scroll)              \
+  gtk_binding_entry_add_signal (binding_set, keyval, mask,                 \
+                                I_("move_slider"), 1, \
                                 GTK_TYPE_SCROLL_TYPE, scroll)
 
 static void
@@ -131,17 +117,17 @@ gtk_scale_class_init (GtkScaleClass *class)
   range_class = (GtkRangeClass*) class;
   widget_class = (GtkWidgetClass*) class;
   
-  parent_class = g_type_class_peek_parent (class);
-  
   gobject_class->set_property = gtk_scale_set_property;
   gobject_class->get_property = gtk_scale_get_property;
+  gobject_class->finalize = gtk_scale_finalize;
 
   widget_class->style_set = gtk_scale_style_set;
+  widget_class->screen_changed = gtk_scale_screen_changed;
 
   range_class->get_range_border = gtk_scale_get_range_border;
   
   signals[FORMAT_VALUE] =
-    g_signal_new ("format_value",
+    g_signal_new (I_("format_value"),
                   G_TYPE_FROM_CLASS (gobject_class),
                   G_SIGNAL_RUN_LAST,
                   G_STRUCT_OFFSET (GtkScaleClass, format_value),
@@ -158,42 +144,42 @@ gtk_scale_class_init (GtkScaleClass *class)
                                                     -1,
                                                     MAX_DIGITS,
                                                     1,
-                                                    G_PARAM_READWRITE));
+                                                    GTK_PARAM_READWRITE));
   
   g_object_class_install_property (gobject_class,
                                    PROP_DRAW_VALUE,
-                                   g_param_spec_boolean ("draw_value",
+                                   g_param_spec_boolean ("draw-value",
                                                         P_("Draw Value"),
                                                         P_("Whether the current value is displayed as a string next to the slider"),
-                                                        FALSE,
-                                                        G_PARAM_READWRITE));
+                                                        TRUE,
+                                                        GTK_PARAM_READWRITE));
   
   g_object_class_install_property (gobject_class,
                                    PROP_VALUE_POS,
-                                   g_param_spec_enum ("value_pos",
+                                   g_param_spec_enum ("value-pos",
                                                      P_("Value Position"),
                                                      P_("The position in which the current value is displayed"),
                                                      GTK_TYPE_POSITION_TYPE,
-                                                     GTK_POS_LEFT,
-                                                     G_PARAM_READWRITE));
+                                                     GTK_POS_TOP,
+                                                     GTK_PARAM_READWRITE));
 
   gtk_widget_class_install_style_property (widget_class,
-                                          g_param_spec_int ("slider_length",
+                                          g_param_spec_int ("slider-length",
                                                             P_("Slider Length"),
                                                             P_("Length of scale's slider"),
                                                             0,
                                                             G_MAXINT,
                                                             31,
-                                                            G_PARAM_READABLE));
+                                                            GTK_PARAM_READABLE));
 
   gtk_widget_class_install_style_property (widget_class,
-                                          g_param_spec_int ("value_spacing",
+                                          g_param_spec_int ("value-spacing",
                                                             P_("Value spacing"),
                                                             P_("Space between value text and the slider/trough area"),
                                                             0,
                                                             G_MAXINT,
                                                             2,
-                                                            G_PARAM_READABLE));
+                                                            GTK_PARAM_READABLE));
   
   /* All bindings (even arrow keys) are on both h/v scale, because
    * blind users etc. don't care about scale orientation.
@@ -249,10 +235,10 @@ gtk_scale_class_init (GtkScaleClass *class)
   add_slider_binding (binding_set, GDK_KP_Down, GDK_CONTROL_MASK,
                       GTK_SCROLL_PAGE_DOWN);
    
-  add_slider_binding (binding_set, GDK_Page_Up, 0,
+  add_slider_binding (binding_set, GDK_Page_Up, GDK_CONTROL_MASK,
                       GTK_SCROLL_PAGE_LEFT);
 
-  add_slider_binding (binding_set, GDK_KP_Page_Up, 0,
+  add_slider_binding (binding_set, GDK_KP_Page_Up, GDK_CONTROL_MASK,
                       GTK_SCROLL_PAGE_LEFT);  
 
   add_slider_binding (binding_set, GDK_Page_Up, 0,
@@ -261,10 +247,10 @@ gtk_scale_class_init (GtkScaleClass *class)
   add_slider_binding (binding_set, GDK_KP_Page_Up, 0,
                       GTK_SCROLL_PAGE_UP);
   
-  add_slider_binding (binding_set, GDK_Page_Down, 0,
+  add_slider_binding (binding_set, GDK_Page_Down, GDK_CONTROL_MASK,
                       GTK_SCROLL_PAGE_RIGHT);
 
-  add_slider_binding (binding_set, GDK_KP_Page_Down, 0,
+  add_slider_binding (binding_set, GDK_KP_Page_Down, GDK_CONTROL_MASK,
                       GTK_SCROLL_PAGE_RIGHT);
 
   add_slider_binding (binding_set, GDK_Page_Down, 0,
@@ -312,6 +298,8 @@ gtk_scale_class_init (GtkScaleClass *class)
 
   add_slider_binding (binding_set, GDK_KP_End, 0,
                       GTK_SCROLL_END);
+
+  g_type_class_add_private (gobject_class, sizeof (GtkScalePrivate));
 }
 
 static void
@@ -407,6 +395,7 @@ gtk_scale_set_digits (GtkScale *scale,
       if (scale->draw_value)
        range->round_digits = digits;
       
+      _gtk_scale_clear_layout (scale);
       gtk_widget_queue_resize (GTK_WIDGET (scale));
 
       g_object_notify (G_OBJECT (scale), "digits");
@@ -437,9 +426,11 @@ gtk_scale_set_draw_value (GtkScale *scale,
       else
        GTK_RANGE (scale)->round_digits = -1;
 
+      _gtk_scale_clear_layout (scale);
+
       gtk_widget_queue_resize (GTK_WIDGET (scale));
 
-      g_object_notify (G_OBJECT (scale), "draw_value");
+      g_object_notify (G_OBJECT (scale), "draw-value");
     }
 }
 
@@ -461,10 +452,11 @@ gtk_scale_set_value_pos (GtkScale        *scale,
     {
       scale->value_pos = pos;
 
+      _gtk_scale_clear_layout (scale);
       if (GTK_WIDGET_VISIBLE (scale) && GTK_WIDGET_MAPPED (scale))
        gtk_widget_queue_resize (GTK_WIDGET (scale));
 
-      g_object_notify (G_OBJECT (scale), "value_pos");
+      g_object_notify (G_OBJECT (scale), "value-pos");
     }
 }
 
@@ -497,7 +489,7 @@ gtk_scale_get_range_border (GtkRange  *range,
   if (scale->draw_value)
     {
       gint value_spacing;
-      gtk_widget_style_get (widget, "value_spacing", &value_spacing, NULL);
+      gtk_widget_style_get (widget, "value-spacing", &value_spacing, NULL);
 
       switch (scale->value_pos)
         {
@@ -581,14 +573,22 @@ gtk_scale_style_set (GtkWidget *widget,
   range = GTK_RANGE (widget);
   
   gtk_widget_style_get (widget,
-                        "slider_length", &slider_length,
+                        "slider-length", &slider_length,
                         NULL);
   
   range->min_slider_size = slider_length;
   
-  (* GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous);
+  _gtk_scale_clear_layout (GTK_SCALE (widget));
+
+  (* GTK_WIDGET_CLASS (gtk_scale_parent_class)->style_set) (widget, previous);
 }
 
+static void
+gtk_scale_screen_changed (GtkWidget *widget,
+                          GdkScreen *old_screen)
+{
+  _gtk_scale_clear_layout (GTK_SCALE (widget));
+}
 
 /**
  * _gtk_scale_format_value:
@@ -615,6 +615,109 @@ _gtk_scale_format_value (GtkScale *scale,
   if (fmt)
     return fmt;
   else
-    return g_strdup_printf ("%0.*f", scale->digits,
-                            value);
+    /* insert a LRM, to prevent -20 to come out as 20- in RTL locales */
+    return g_strdup_printf ("\342\200\216%0.*f", scale->digits, value);
+}
+
+static void
+gtk_scale_finalize (GObject *object)
+{
+  GtkScale *scale;
+
+  g_return_if_fail (GTK_IS_SCALE (object));
+
+  scale = GTK_SCALE (object);
+
+  _gtk_scale_clear_layout (scale);
+
+  G_OBJECT_CLASS (gtk_scale_parent_class)->finalize (object);
+}
+
+/**
+ * gtk_scale_get_layout:
+ * @scale: A #GtkScale
+ *
+ * Gets the #PangoLayout used to display the scale. The returned object
+ * is owned by the scale so does not need to be freed by the caller. 
+ *
+ * Return value: the #PangoLayout for this scale, or %NULL if the draw_value property
+ *    is %FALSE.
+ *   
+ * Since: 2.4
+ **/
+PangoLayout *
+gtk_scale_get_layout (GtkScale *scale)
+{
+  GtkScalePrivate *priv = GTK_SCALE_GET_PRIVATE (scale);
+  gchar *txt;
+
+  g_return_val_if_fail (GTK_IS_SCALE (scale), NULL);
+
+  if (!priv->layout)
+    {
+      if (scale->draw_value)
+       priv->layout = gtk_widget_create_pango_layout (GTK_WIDGET (scale), NULL);
+    }
+
+  if (scale->draw_value) 
+    {
+      txt = _gtk_scale_format_value (scale,
+                                    GTK_RANGE (scale)->adjustment->value);
+      pango_layout_set_text (priv->layout, txt, -1);
+      g_free (txt);
+    }
+
+  return priv->layout;
+}
+
+/**
+ * gtk_scale_get_layout_offsets:
+ * @scale: a #GtkScale
+ * @x: location to store X offset of layout, or %NULL
+ * @y: location to store Y offset of layout, or %NULL
+ *
+ * Obtains the coordinates where the scale will draw the #PangoLayout
+ * representing the text in the scale. Remember
+ * when using the #PangoLayout function you need to convert to
+ * and from pixels using PANGO_PIXELS() or #PANGO_SCALE. 
+ *
+ * If the draw_value property is %FALSE, the return values are 
+ * undefined.
+ *
+ * Since: 2.4
+ **/
+void 
+gtk_scale_get_layout_offsets (GtkScale *scale,
+                              gint     *x,
+                              gint     *y)
+{
+  gint local_x = 0; 
+  gint local_y = 0;
+
+  g_return_if_fail (GTK_IS_SCALE (scale));
+
+  if (GTK_SCALE_GET_CLASS (scale)->get_layout_offsets)
+    (GTK_SCALE_GET_CLASS (scale)->get_layout_offsets) (scale, &local_x, &local_y);
+
+  if (x)
+    *x = local_x;
+  
+  if (y)
+    *y = local_y;
 }
+
+void _gtk_scale_clear_layout (GtkScale *scale)
+{
+  GtkScalePrivate *priv = GTK_SCALE_GET_PRIVATE (scale);
+
+  g_return_if_fail (GTK_IS_SCALE (scale));
+
+  if (priv->layout)
+    {
+      g_object_unref (priv->layout);
+      priv->layout = NULL;
+    }
+}
+
+#define __GTK_SCALE_C__
+#include "gtkaliasdef.c"