[gtk+/wip/strength-bar] strength-bar: introduce GtkStrengthBar



commit 2939dc765f45b5773a701d5c4f556aab67944c1d
Author: Cosimo Cecchi <cosimoc gnome org>
Date:   Tue May 29 17:00:33 2012 -0400

    strength-bar: introduce GtkStrengthBar
    
    Similar to CcStrengthBar from gnome-control-center, but more generic and
    with thorough CSS styling support.

 docs/reference/gtk/gtk3-sections.txt |   35 ++
 gtk/Makefile.am                      |    2 +
 gtk/gtk.h                            |    1 +
 gtk/gtk.symbols                      |   10 +
 gtk/gtkstrengthbar.c                 |  691 ++++++++++++++++++++++++++++++++++
 gtk/gtkstrengthbar.h                 |   80 ++++
 gtk/gtkstylecontext.h                |   48 +++
 7 files changed, 867 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index 5d8a822..96a30c1 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -3206,6 +3206,31 @@ gtk_status_icon_get_type
 </SECTION>
 
 <SECTION>
+<FILE>gtkstrengthbar</FILE>
+<TITLE>GtkStrenghtBar</TITLE>
+GtkStrenghtBar
+gtk_strength_bar_new
+gtk_strength_bar_set_fraction
+gtk_strength_bar_get_fraction
+gtk_strength_bar_set_weak_fraction
+gtk_strength_bar_get_weak_fraction
+gtk_strength_bar_set_strong_fraction
+gtk_strength_bar_get_strong_fraction
+gtk_strength_bar_set_num_blocks
+gtk_strength_bar_get_num_blocks
+<SUBSECTION Standard>
+GTK_STRENGTH_BAR
+GTK_IS_STRENGTH_BAR
+GTK_TYPE_STRENGTH_BAR
+GTK_STRENGTH_BAR_CLASS
+GTK_IS_STRENGTH_BAR_CLASS
+GTK_STRENGTH_BAR_GET_CLASS
+<SUBSECTION Private>
+GtkStrengthBarPrivate
+gtk_strength_bar_get_type
+</SECTION>
+
+<SECTION>
 <FILE>gtktable</FILE>
 <TITLE>GtkTable</TITLE>
 GtkTable
@@ -5679,6 +5704,16 @@ GTK_STYLE_CLASS_RIGHT
 GTK_STYLE_CLASS_LINKED
 GTK_STYLE_CLASS_ARROW
 GTK_STYLE_CLASS_OSD
+<<<<<<< HEAD
+=======
+GTK_STYLE_CLASS_STRENGTH_BAR
+<<<<<<< HEAD
+GTK_STYLE_CLASS_SUCCESS
+>>>>>>> f7335b7... strength-bar: introduce GtkStrengthBar
+=======
+GTK_STYLE_CLASS_EMPTY
+GTK_STYLE_CLASS_FILL_COMPONENT
+>>>>>>> a171510... f
 GTK_STYLE_REGION_COLUMN
 GTK_STYLE_REGION_COLUMN_HEADER
 GTK_STYLE_REGION_ROW
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 659bad9..0ef29e0 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -323,6 +323,7 @@ gtk_public_h_sources = 		\
 	gtkstatusbar.h		\
 	gtkstatusicon.h		\
 	gtkstock.h		\
+	gtkstrengthbar.h	\
 	gtkstylecontext.h	\
 	gtkstyleproperties.h	\
 	gtkstyleprovider.h	\
@@ -761,6 +762,7 @@ gtk_base_c_sources = 		\
 	gtkprivate.c		\
 	gtkprivatetypebuiltins.c \
 	gtkprogressbar.c	\
+	gtkstrengthbar.c	\
 	gtkradioaction.c	\
 	gtkradiobutton.c	\
 	gtkradiomenuitem.c	\
diff --git a/gtk/gtk.h b/gtk/gtk.h
index de0181b..bcb3765 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -178,6 +178,7 @@
 #include <gtk/gtkstatusbar.h>
 #include <gtk/gtkstatusicon.h>
 #include <gtk/gtkstock.h>
+#include <gtk/gtkstrengthbar.h>
 #include <gtk/gtkstylecontext.h>
 #include <gtk/gtkstyleproperties.h>
 #include <gtk/gtkstyleprovider.h>
diff --git a/gtk/gtk.symbols b/gtk/gtk.symbols
index 6f2be20..3b475fc 100644
--- a/gtk/gtk.symbols
+++ b/gtk/gtk.symbols
@@ -2553,6 +2553,16 @@ gtk_switch_get_active
 gtk_switch_get_type
 gtk_switch_new
 gtk_switch_set_active
+gtk_strength_bar_get_type
+gtk_strength_bar_new
+gtk_strength_bar_set_fraction
+gtk_strength_bar_get_fraction
+gtk_strength_bar_set_weak_fraction
+gtk_strength_bar_get_weak_fraction
+gtk_strength_bar_set_strong_fraction
+gtk_strength_bar_get_strong_fraction
+gtk_strength_bar_set_num_blocks
+gtk_strength_bar_get_num_blocks
 gtk_style_apply_default_background
 gtk_style_attach
 gtk_style_context_add_class
diff --git a/gtk/gtkstrengthbar.c b/gtk/gtkstrengthbar.c
new file mode 100644
index 0000000..9141b94
--- /dev/null
+++ b/gtk/gtkstrengthbar.c
@@ -0,0 +1,691 @@
+/* GTK - The GIMP Toolkit
+ * Copyright  2012 Red Hat, Inc.
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Cosimo Cecchi <cosimoc gnome org>
+ *
+ */
+
+/**
+ * SECTION:gtkstrengthbar
+ * @Title: GtkStrengthBar
+ * @Short_description: A bar that can used as a strength indicator
+ *
+ * The #GtkStrengthBar is a bar widget that can be used
+ * as a strength indicator. Typical use cases are displaying the strength
+ * of a password, or showing the charge level of a battery.
+ *
+ * Use #gtk_strength_bar_set_fraction to set the current value.
+ * #GtkStrengthBar will draw the fill with a different style according to
+ * the current fraction: the #GTK_STYLE_CLASS_WEAK will be set on the
+ * widget when the fraction is less than #GtkStrengthBar:weak-fraction, 
+ * and #GTK_STYLE_CLASS_STRONG will be set when the fraction is more 
+ * than #GtkStrengthBar:strong-fraction.
+ */
+#include "config.h"
+
+#include "gtkintl.h"
+#include "gtkorientableprivate.h"
+#include "gtkstrengthbar.h"
+#include "gtkstylecontext.h"
+#include "gtkwidget.h"
+
+#include <math.h>
+
+#define DEFAULT_BLOCK_SIZE 3
+
+G_DEFINE_TYPE_WITH_CODE (GtkStrengthBar, gtk_strength_bar, GTK_TYPE_WIDGET,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
+
+enum {
+  PROP_FRACTION = 1,
+  PROP_WEAK_FRACTION,
+  PROP_STRONG_FRACTION,
+  PROP_NUM_BLOCKS,
+  LAST_PROPERTY,
+  PROP_ORIENTATION /* overridden */
+};
+
+static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
+
+struct _GtkStrengthBarPrivate {
+  GtkOrientation orientation;
+
+  gdouble weak_fraction;
+  gdouble strong_fraction;
+
+  gdouble cur_fraction;
+
+  gint num_blocks;
+};
+
+static void
+gtk_strength_bar_get_min_block_size (GtkStrengthBar *self,
+                                     gint *block_width,
+                                     gint *block_height)
+{
+  GtkWidget *widget = GTK_WIDGET (self);
+  GtkStyleContext *context = gtk_widget_get_style_context (widget);
+  GtkStateFlags flags = gtk_widget_get_state_flags (widget);
+  GtkBorder border, tmp, tmp2;
+  gint min_width, min_height;
+
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_FILL_COMPONENT);
+  gtk_style_context_get_border (context, flags, &border);
+  gtk_style_context_get_padding (context, flags, &tmp);
+  gtk_style_context_get_margin (context, flags, &tmp2);
+  gtk_style_context_restore (context);
+
+  gtk_style_context_get_style (context,
+                               "min-block-width", &min_width,
+                               "min-block-height", &min_height,
+                               NULL);
+
+  border.top += tmp.top;
+  border.right += tmp.right;
+  border.bottom += tmp.bottom;
+  border.left += tmp.left;
+
+  border.top += tmp2.top;
+  border.right += tmp2.right;
+  border.bottom += tmp2.bottom;
+  border.left += tmp2.left;
+
+  if (block_width)
+    *block_width = border.left + border.right + min_width;
+  if (block_height)
+    *block_height = border.top + border.bottom + min_height;
+}
+
+static void
+gtk_strength_bar_get_borders (GtkStrengthBar *self,
+                              GtkBorder *borders_out)
+{
+  GtkWidget *widget = GTK_WIDGET (self);
+  GtkStyleContext *context = gtk_widget_get_style_context (widget);
+  GtkStateFlags flags = gtk_widget_get_state_flags (widget);
+  GtkBorder border, tmp;
+
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);
+  gtk_style_context_get_border (context, flags, &border);
+  gtk_style_context_get_padding (context, flags, &tmp);
+  gtk_style_context_restore (context);
+
+  border.top += tmp.top;
+  border.right += tmp.right;
+  border.bottom += tmp.bottom;
+  border.left += tmp.left;
+
+  if (borders_out)
+    *borders_out = border;
+}
+
+static void
+gtk_strength_bar_draw_blocks (GtkStrengthBar *self,
+                              cairo_t *cr)
+{
+  GtkWidget *widget = GTK_WIDGET (self);
+  GtkStyleContext *context = gtk_widget_get_style_context (widget);
+  GtkStateFlags flags = gtk_widget_get_state_flags (widget);
+  gint num_blocks, idx;
+  gint block_area_x, block_area_y;
+  gint block_area_width, block_area_height;
+  gint block_width, block_height;
+  gint block_draw_width, block_draw_height;
+  gint block_area_skew;
+  GtkBorder trough_borders, block_margin;
+
+  gint block_area_fill, current_fill;
+
+  gtk_strength_bar_get_borders (self, &trough_borders);
+  gtk_strength_bar_get_min_block_size (self, &block_width, &block_height);
+
+  block_area_x = trough_borders.left;
+  block_area_y = trough_borders.top;
+  block_area_width = gtk_widget_get_allocated_width (widget) -
+    trough_borders.left - trough_borders.right;
+  block_area_height = gtk_widget_get_allocated_height (widget) -
+    trough_borders.top - trough_borders.bottom;
+
+  block_area_skew = 0;
+
+  if (self->priv->num_blocks != -1 &&
+      self->priv->num_blocks > 0)
+    {
+      num_blocks = self->priv->num_blocks;
+
+      if (self->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+        block_width = MAX (block_width, (gint) floor (block_area_width / num_blocks));
+      else
+        block_height = MAX (block_height, (gint) floor (block_area_height / num_blocks));
+    }
+  else
+    {
+      if (self->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+        num_blocks = (gint) floor (block_area_width  / block_width);
+      else
+        num_blocks = (gint) floor (block_area_height / block_height);
+    }
+
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_FILL_COMPONENT);
+  gtk_style_context_get_margin (context, flags, &block_margin);
+
+  block_draw_width = block_width - block_margin.left - block_margin.right;
+  block_draw_height = block_height - block_margin.top - block_margin.bottom;
+
+  if (self->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      block_draw_height = MAX (block_draw_height, block_area_height - block_margin.top - block_margin.bottom);
+      block_area_y += block_margin.top;
+
+      block_area_skew = block_area_width - (num_blocks * block_width);
+      block_area_x += (gint) floor (block_area_skew / 2.0);
+      block_area_width -= block_area_skew;
+
+      block_area_fill = (gint) ceil (block_area_width * self->priv->cur_fraction);
+    }
+  else /* orientation == GTK_ORIENTATION_VERTICAL */
+    {
+      block_draw_width = MAX (block_draw_width, block_area_width - block_margin.left - block_margin.right);
+      block_area_x += block_margin.left;
+
+      block_area_skew = block_area_height - (num_blocks * block_height);
+      block_area_y += (gint) floor (block_area_skew / 2.0);
+      block_area_height -= block_area_skew;
+
+      block_area_fill = (gint) ceil (block_area_height * self->priv->cur_fraction);
+    }
+
+  for (idx = 0; idx < num_blocks; idx++)
+    {
+      if (self->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+        {
+          block_area_x += block_margin.left;
+          current_fill = (idx * block_width);
+        }
+      else /* orientation == GTK_ORIENTATION_VERTICAL */
+        {
+          block_area_y += block_margin.top;
+          current_fill = (idx * block_height);
+        }
+
+      if (current_fill >= block_area_fill)
+        gtk_style_context_add_class (context, GTK_STYLE_CLASS_EMPTY);
+
+      gtk_render_background (context, cr,
+                             block_area_x, block_area_y,
+                             block_draw_width, block_draw_height);
+      gtk_render_frame (context, cr,
+                        block_area_x, block_area_y,
+                        block_draw_width, block_draw_height);
+
+      if (self->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+        block_area_x += block_draw_width + block_margin.right;
+      else
+        block_area_y += block_draw_height + block_margin.bottom;
+    }
+
+  gtk_style_context_restore (context);
+}
+
+static gboolean
+gtk_strength_bar_draw (GtkWidget *widget,
+                       cairo_t *cr)
+{
+  GtkStrengthBar *self = GTK_STRENGTH_BAR (widget);
+  GtkStyleContext *context = gtk_widget_get_style_context (widget);
+  gint width, height;
+
+  width = gtk_widget_get_allocated_width (widget);
+  height = gtk_widget_get_allocated_height (widget);
+
+  gtk_style_context_save (context);
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_TROUGH);
+
+  gtk_render_background (context, cr,
+                         0, 0, width, height);
+  gtk_render_frame (context, cr,
+                    0, 0, width, height);
+
+  gtk_style_context_restore (context);
+
+  gtk_strength_bar_draw_blocks (self, cr);
+
+  return FALSE;
+}
+
+static void
+gtk_strength_bar_get_preferred_width (GtkWidget *widget,
+                                      gint *minimum,
+                                      gint *natural)
+{
+  GtkStrengthBar *self = GTK_STRENGTH_BAR (widget);
+  GtkBorder borders;
+  gint num_blocks;
+  gint width, block_width;
+
+  /* fit at least one block */
+  num_blocks = MAX (self->priv->num_blocks, 1);
+  gtk_strength_bar_get_min_block_size (self, &block_width, NULL);
+
+  gtk_strength_bar_get_borders (self, &borders);
+  width = borders.left + borders.right;
+
+  if (self->priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+    width += num_blocks * block_width;
+  else
+    width += block_width;
+
+  if (minimum)
+    *minimum = width;
+  if (natural)
+    *natural = width;
+}
+
+static void
+gtk_strength_bar_get_preferred_height (GtkWidget *widget,
+                                       gint *minimum,
+                                       gint *natural)
+{
+  GtkStrengthBar *self = GTK_STRENGTH_BAR (widget);
+  GtkBorder borders;
+  gint num_blocks;
+  gint height, block_height;
+
+  /* fit at least one block */
+  num_blocks = MAX (self->priv->num_blocks, 1);
+  gtk_strength_bar_get_min_block_size (self, NULL, &block_height);
+
+  gtk_strength_bar_get_borders (self, &borders);
+  height = borders.top + borders.bottom;
+
+  if (self->priv->orientation == GTK_ORIENTATION_VERTICAL)
+    height += num_blocks * block_height;
+  else
+    height += block_height;
+
+  if (minimum)
+    *minimum = height;
+  if (natural)
+    *natural = height;
+}
+
+static void
+gtk_strength_bar_update_style_classes (GtkStrengthBar *self)
+{
+  GtkStyleContext *context = gtk_widget_get_style_context (GTK_WIDGET (self));
+  gdouble fraction = gtk_strength_bar_get_fraction (self);
+
+  if (fraction < self->priv->weak_fraction)
+    {
+      gtk_style_context_remove_class (context, GTK_STYLE_CLASS_STRONG);
+      gtk_style_context_add_class (context, GTK_STYLE_CLASS_WEAK);
+    }
+  else if (fraction > self->priv->strong_fraction)
+    {
+      gtk_style_context_remove_class (context, GTK_STYLE_CLASS_WEAK);
+      gtk_style_context_add_class (context, GTK_STYLE_CLASS_STRONG);
+    }
+}
+
+static void
+gtk_strength_bar_set_orientation (GtkStrengthBar *self,
+                                  GtkOrientation orientation)
+{
+  if (self->priv->orientation != orientation)
+    {
+      self->priv->orientation = orientation;
+      _gtk_orientable_set_style_classes (GTK_ORIENTABLE (self));
+
+      gtk_widget_queue_resize (GTK_WIDGET (self));
+    }
+}
+
+static void
+gtk_strength_bar_notify (GObject *obj,
+                         GParamSpec *pspec)
+{
+  if ((g_strcmp0 (pspec->name, "fraction") == 0) ||
+      (g_strcmp0 (pspec->name, "strong-fraction") == 0) ||
+      (g_strcmp0 (pspec->name, "weak-fraction") == 0))
+    gtk_strength_bar_update_style_classes (GTK_STRENGTH_BAR (obj));
+}
+
+static void
+gtk_strength_bar_get_property (GObject    *obj,
+                               guint       property_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  GtkStrengthBar *self = GTK_STRENGTH_BAR (obj);
+
+  switch (property_id)
+    {
+    case PROP_FRACTION:
+      g_value_set_double (value, gtk_strength_bar_get_fraction (self));
+      break;
+    case PROP_WEAK_FRACTION:
+      g_value_set_double (value, gtk_strength_bar_get_weak_fraction (self));
+      break;
+    case PROP_STRONG_FRACTION:
+      g_value_set_double (value, gtk_strength_bar_get_strong_fraction (self));
+      break;
+    case PROP_ORIENTATION:
+      g_value_set_enum (value, self->priv->orientation);
+      break;
+    case PROP_NUM_BLOCKS:
+      g_value_set_enum (value, self->priv->num_blocks);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_strength_bar_set_property (GObject      *obj,
+                               guint         property_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  GtkStrengthBar *self = GTK_STRENGTH_BAR (obj);
+
+  switch (property_id)
+    {
+    case PROP_FRACTION:
+      gtk_strength_bar_set_fraction (self, g_value_get_double (value));
+      break;
+    case PROP_WEAK_FRACTION:
+      gtk_strength_bar_set_weak_fraction (self, g_value_get_double (value));
+      break;
+    case PROP_STRONG_FRACTION:
+      gtk_strength_bar_set_strong_fraction (self, g_value_get_double (value));
+      break;
+    case PROP_ORIENTATION:
+      gtk_strength_bar_set_orientation (self, g_value_get_enum (value));
+      break;
+    case PROP_NUM_BLOCKS:
+      gtk_strength_bar_set_num_blocks (self, g_value_get_int (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_strength_bar_class_init (GtkStrengthBarClass *klass)
+{
+  GObjectClass *oclass = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
+
+  oclass->notify = gtk_strength_bar_notify;
+  oclass->get_property = gtk_strength_bar_get_property;
+  oclass->set_property = gtk_strength_bar_set_property;
+
+  wclass->draw = gtk_strength_bar_draw;
+  wclass->get_preferred_width = gtk_strength_bar_get_preferred_width;
+  wclass->get_preferred_height = gtk_strength_bar_get_preferred_height;
+
+  g_object_class_override_property (oclass, PROP_ORIENTATION, "orientation");
+
+  /**
+   * GtkStrengthBar:fraction:
+   *
+   * The #GtkStrengthBar:fraction property determines the currently
+   * filled fraction of the strength bar.
+   */
+  properties[PROP_FRACTION] =
+    g_param_spec_double ("fraction",
+                         P_("Currently filled fraction level"),
+                         P_("Currently filled fraction level of the strength bar"),
+                         0.0, 1.0, 0.0,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  /**
+   * GtkStrengthBar:weak-fraction:
+   *
+   * The #GtkStrengthBar:weak-fraction property determines
+   * the fraction below which the bar displays in a weak state.
+   */
+  properties[PROP_WEAK_FRACTION] =
+    g_param_spec_double ("weak-fraction",
+                         P_("Fraction level for the weak state"),
+                         P_("Fraction level below which the bar is treated in a weak state"),
+                         0.0, 1.0, 0.25,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  /**
+   * GtkStrengthBar:strong-fraction:
+   *
+   * The #GtkStrengthBar:strong-fraction property determines
+   * the fraction above which the bar displays in a strong state.
+   */
+  properties[PROP_STRONG_FRACTION] =
+    g_param_spec_double ("strong-fraction",
+                         P_("Fraction level for the strong state"),
+                         P_("Fraction level above which the bar is treated as strong"),
+                         0.0, 1.0, 0.75,
+                         G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+  /**
+   * GtkStrengthBar:num-blocks:
+   *
+   * The #GtkStrengthBar:num-blocks property determines
+   * the number of blocks drawn in the bar. If the value of this property
+   * is -1 (the default), the number of blocks will be calculated automatically
+   * to fit in the allocated space, respecting the value of the
+   * #GtkStrengthBar:min-num-blocks property.
+   */
+  properties[PROP_NUM_BLOCKS] =
+    g_param_spec_int ("num-blocks",
+                      P_("Number of blocks"),
+                      P_("Number of blocks drawn in the bar"),
+                      -1, G_MAXINT, -1,
+                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+  gtk_widget_class_install_style_property 
+    (wclass, g_param_spec_int ("min-block-height",
+                               P_("Minimum height for filling blocks"),
+                               P_("Minimum height for blocks that fill the bar"),
+                               1, G_MAXINT, DEFAULT_BLOCK_SIZE,
+                               G_PARAM_READWRITE));
+  gtk_widget_class_install_style_property 
+    (wclass, g_param_spec_int ("min-block-width",
+                               P_("Minimum width for filling blocks"),
+                               P_("Minimum width for blocks that fill the bar"),
+                               1, G_MAXINT, DEFAULT_BLOCK_SIZE,
+                               G_PARAM_READWRITE));
+
+  g_type_class_add_private (klass, sizeof (GtkStrengthBarPrivate));
+  g_object_class_install_properties (oclass, LAST_PROPERTY, properties);
+}
+
+static void
+gtk_strength_bar_init (GtkStrengthBar *self)
+{
+  GtkStyleContext *context;
+
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTK_TYPE_STRENGTH_BAR, GtkStrengthBarPrivate);
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (self));
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_STRENGTH_BAR);
+
+  self->priv->weak_fraction = 0.25;
+  self->priv->strong_fraction = 0.75;
+  self->priv->cur_fraction = 0.0;
+
+  /* set initial orientation and style classes */
+  self->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+  _gtk_orientable_set_style_classes (GTK_ORIENTABLE (self));
+
+  self->priv->num_blocks = -1;
+
+  gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
+}
+
+GtkWidget *
+gtk_strength_bar_new (void)
+{
+  return g_object_new (GTK_TYPE_STRENGTH_BAR, NULL);
+}
+
+/**
+ * gtk_strength_bar_get_weak_fraction:
+ * @self: a #GtkStrengthBar
+ * 
+ * Returns the value of the #GtkStrengthBar:weak-fraction property.
+ *
+ * Returns: a fraction from 0.0 to 1.0.
+ */
+gdouble
+gtk_strength_bar_get_weak_fraction (GtkStrengthBar *self)
+{
+  g_return_val_if_fail (GTK_IS_STRENGTH_BAR (self), 0.0);
+
+  return self->priv->weak_fraction;
+}
+
+/**
+ * gtk_strength_bar_get_strong_fraction:
+ * @self: a #GtkStrengthBar
+ * 
+ * Returns the value of the #GtkStrengthBar:strong-fraction property.
+ *
+ * Returns: a fraction from 0.0 to 1.0.
+ */
+gdouble
+gtk_strength_bar_get_strong_fraction (GtkStrengthBar *self)
+{
+  g_return_val_if_fail (GTK_IS_STRENGTH_BAR (self), 0.0);
+
+  return self->priv->strong_fraction;
+}
+
+/**
+ * gtk_strength_bar_set_weak_fraction:
+ * @self: a #GtkStrengthBar
+ * @fraction: a fraction from 0.0 to 1.0
+ * 
+ * Sets the value of the #GtkStrengthBar:weak-fraction property.
+ */
+void
+gtk_strength_bar_set_weak_fraction (GtkStrengthBar *self,
+                                       gdouble         fraction)
+{
+  g_return_if_fail (GTK_IS_STRENGTH_BAR (self));
+  g_return_if_fail (fraction >= 0.0 && fraction <= 1.0);
+
+  if (fraction != self->priv->weak_fraction)
+    {
+      self->priv->weak_fraction = fraction;
+      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WEAK_FRACTION]);
+    }
+}
+
+/**
+ * gtk_strength_bar_set_strong_fraction:
+ * @self: a #GtkStrengthBar
+ * @fraction: a fraction from 0.0 to 1.0
+ * 
+ * Sets the value of the #GtkStrengthBar:strong-fraction property.
+ */
+void
+gtk_strength_bar_set_strong_fraction (GtkStrengthBar *self,
+                                       gdouble         fraction)
+{
+  g_return_if_fail (GTK_IS_STRENGTH_BAR (self));
+  g_return_if_fail (fraction >= 0.0 && fraction <= 1.0);
+
+  if (fraction != self->priv->strong_fraction)
+    {
+      self->priv->strong_fraction = fraction;
+      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STRONG_FRACTION]);
+    }
+}
+
+/**
+ * gtk_strength_bar_set_fraction:
+ * @self: a #GtkStrengthBar
+ * @fraction: a fraction from 0.0 to 1.0
+ *
+ * Sets the value of the #GtkStrengthBar:fraction property.
+ */
+void
+gtk_strength_bar_set_fraction (GtkStrengthBar *self,
+                               gdouble fraction)
+{
+  g_return_if_fail (GTK_IS_STRENGTH_BAR (self));
+  g_return_if_fail (fraction >= 0.0 && fraction <= 1.0);
+
+  if (fraction != self->priv->cur_fraction)
+    {
+      self->priv->cur_fraction = fraction;
+      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FRACTION]);
+    }
+}
+
+/**
+ * gtk_strength_bar_get_fraction:
+ * @self: a #GtkStrengthBar
+ *
+ * Returns the value of the #GtkStrengthBar:fraction property.
+ *
+ * Returns: a fraction from 0.0 to 1.0.
+ */
+gdouble
+gtk_strength_bar_get_fraction (GtkStrengthBar *self)
+{
+  return self->priv->cur_fraction;
+}
+
+/**
+ * gtk_strength_bar_set_num_blocks:
+ * @self: a #GtkStrengthBar
+ * @num_blocks: the desired number of blocks, or -1
+ *
+ * Sets the value of the #GtkStrengthBar:num-blocks property
+ */
+void
+gtk_strength_bar_set_num_blocks (GtkStrengthBar *self,
+                                 gint num_blocks)
+{
+  g_return_if_fail (GTK_IS_STRENGTH_BAR (self));
+  g_return_if_fail (num_blocks >= -1);
+
+  if (num_blocks != self->priv->num_blocks)
+    {
+      self->priv->num_blocks = num_blocks;
+      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_NUM_BLOCKS]);
+
+      gtk_widget_queue_resize (GTK_WIDGET (self));
+    }
+}
+
+/**
+ * gtk_strength_bar_get_num_blocks:
+ * @self: a #GtkStrengthBar
+ *
+ * Returns the value of the #GtkStrengthBar:num-blocks property
+ *
+ * Returns: the number of blocks drawn in the bar, or -1
+ */
+gint
+gtk_strength_bar_get_num_blocks (GtkStrengthBar *self)
+{
+  g_return_val_if_fail (GTK_IS_STRENGTH_BAR (self), 0);
+
+  return self->priv->num_blocks;
+}
diff --git a/gtk/gtkstrengthbar.h b/gtk/gtkstrengthbar.h
new file mode 100644
index 0000000..0a2b3cb
--- /dev/null
+++ b/gtk/gtkstrengthbar.h
@@ -0,0 +1,80 @@
+/* GTK - The GIMP Toolkit
+ * Copyright  2012 Red Hat, Inc.
+ *
+ * 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 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Cosimo Cecchi <cosimoc gnome org>
+ *
+ */
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#ifndef __GTK_STRENGTH_BAR_H__
+#define __GTK_STRENGTH_BAR_H__
+
+#include <gtk/gtkprogressbar.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_STRENGTH_BAR            (gtk_strength_bar_get_type ())
+#define GTK_STRENGTH_BAR(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_STRENGTH_BAR, GtkStrengthBar))
+#define GTK_STRENGTH_BAR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_STRENGTH_BAR, GtkStrengthBarClass))
+#define GTK_IS_STRENGTH_BAR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_STRENGTH_BAR))
+#define GTK_IS_STRENGTH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_STRENGTH_BAR))
+#define GTK_STRENGTH_BAR_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_STRENGTH_BAR, GtkStrengthBarClass))
+
+typedef struct _GtkStrengthBarClass GtkStrengthBarClass;
+typedef struct _GtkStrengthBar GtkStrengthBar;
+typedef struct _GtkStrengthBarPrivate GtkStrengthBarPrivate;
+
+struct _GtkStrengthBar {
+  GtkWidget parent;
+
+  /*< private >*/
+  GtkStrengthBarPrivate *priv;
+};
+
+struct _GtkStrengthBarClass {
+  GtkWidgetClass parent_class;
+
+  /* padding for future class expansion */
+  gpointer padding[16];
+};
+
+GType      gtk_strength_bar_get_type             (void) G_GNUC_CONST;
+
+GtkWidget *gtk_strength_bar_new                  (void);
+
+void       gtk_strength_bar_set_fraction         (GtkStrengthBar *self,
+                                                  gdouble         fraction);
+gdouble    gtk_strength_bar_get_fraction         (GtkStrengthBar *self);
+
+void       gtk_strength_bar_set_weak_fraction    (GtkStrengthBar *self,
+                                                  gdouble         fraction);
+gdouble    gtk_strength_bar_get_weak_fraction    (GtkStrengthBar *self);
+
+void       gtk_strength_bar_set_strong_fraction  (GtkStrengthBar *self,
+                                                  gdouble         fraction);
+
+gdouble    gtk_strength_bar_get_strong_fraction  (GtkStrengthBar *self);
+
+void       gtk_strength_bar_set_num_blocks       (GtkStrengthBar *self,
+                                                  gint            num_blocks);
+gint       gtk_strength_bar_get_num_blocks       (GtkStrengthBar *self);
+
+G_END_DECLS
+
+#endif /* __GTK_STRENGTH_BAR_H__ */
diff --git a/gtk/gtkstylecontext.h b/gtk/gtkstylecontext.h
index 4975862..7d9550f 100644
--- a/gtk/gtkstylecontext.h
+++ b/gtk/gtkstylecontext.h
@@ -691,6 +691,54 @@ struct _GtkStyleContextClass
  */
 #define GTK_STYLE_CLASS_OSD "osd"
 
+/**
+ * GTK_STYLE_CLASS_STRENGTH_BAR:
+ *
+ * A CSS class used when rendering a strength indicator, such
+ * as a battery charge level, or a password strength.
+ *
+ * This is used by #GtkStrengthBar.
+ */
+#define GTK_STYLE_CLASS_STRENGTH_BAR "strength-bar"
+
+/**
+ * GTK_STYLE_CLASS_STRONG:
+ *
+ * A CSS class used when the rendered element is in a strong state.
+ * 
+ * This is used by #GtkStrengthBar.
+ */
+#define GTK_STYLE_CLASS_STRONG "strong"
+
+/**
+ * GTK_STYLE_CLASS_WEAK:
+ *
+ * A CSS class used when the rendered element is in a weak state.
+ * 
+ * This is used by #GtkStrengthBar.
+ */
+#define GTK_STYLE_CLASS_WEAK "weak"
+
+/**
+ * GTK_STYLE_CLASS_EMPTY:
+ *
+ * A CSS class used when the rendered element is in an empty state, such
+ * an empty fill component of a #GtkStrengthBar.
+ *
+ * This is used by #GtkStrengthBar.
+ */
+#define GTK_STYLE_CLASS_EMPTY "empty"
+
+/**
+ * GTK_STYLE_CLASS_FILL_COMPONENT:
+ *
+ * A CSS class used when rendering components belonging to a bigger filling
+ * area, such as those in #GtkStrengthBar.
+ *
+ * This is used by #GtkStrengthBar.
+ */
+#define GTK_STYLE_CLASS_FILL_COMPONENT "fill-component"
+
 /* Predefined set of widget regions */
 
 /**



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]