2012-05-29 21:00:33 +00:00
|
|
|
|
/* 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:gtklevelbar
|
|
|
|
|
* @Title: GtkLevelBar
|
|
|
|
|
* @Short_description: A bar that can used as a level indicator
|
|
|
|
|
*
|
|
|
|
|
* The #GtkLevelBar is a bar widget that can be used
|
|
|
|
|
* as a level indicator. Typical use cases are displaying the strength
|
|
|
|
|
* of a password, or showing the charge level of a battery.
|
|
|
|
|
*
|
|
|
|
|
* Use gtk_level_bar_set_value() to set the current value, and
|
|
|
|
|
* gtk_level_bar_add_offset_value() to set the value offsets at which
|
2016-02-06 15:11:17 +00:00
|
|
|
|
* the bar will be considered in a different state. GTK will add a few
|
|
|
|
|
* offsets by default on the level bar: #GTK_LEVEL_BAR_OFFSET_LOW,
|
|
|
|
|
* #GTK_LEVEL_BAR_OFFSET_HIGH and #GTK_LEVEL_BAR_OFFSET_FULL, with
|
|
|
|
|
* values 0.25, 0.75 and 1.0 respectively.
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*
|
2016-02-06 15:19:13 +00:00
|
|
|
|
* Note that it is your responsibility to update preexisting offsets
|
|
|
|
|
* when changing the minimum or maximum value. GTK+ will simply clamp
|
|
|
|
|
* them to the new range.
|
|
|
|
|
*
|
2014-02-04 21:57:57 +00:00
|
|
|
|
* ## Adding a custom offset on the bar
|
|
|
|
|
*
|
2014-01-27 19:55:18 +00:00
|
|
|
|
* |[<!-- language="C" -->
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*
|
|
|
|
|
* static GtkWidget *
|
|
|
|
|
* create_level_bar (void)
|
|
|
|
|
* {
|
2014-02-12 21:09:09 +00:00
|
|
|
|
* GtkWidget *widget;
|
|
|
|
|
* GtkLevelBar *bar;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*
|
2014-02-12 21:09:09 +00:00
|
|
|
|
* widget = gtk_level_bar_new ();
|
|
|
|
|
* bar = GTK_LEVEL_BAR (widget);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*
|
2015-11-11 05:25:24 +00:00
|
|
|
|
* // This changes the value of the default low offset
|
2014-02-12 21:09:09 +00:00
|
|
|
|
*
|
|
|
|
|
* gtk_level_bar_add_offset_value (bar,
|
|
|
|
|
* GTK_LEVEL_BAR_OFFSET_LOW,
|
|
|
|
|
* 0.10);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*
|
2015-11-11 05:25:24 +00:00
|
|
|
|
* // This adds a new offset to the bar; the application will
|
2015-11-13 05:55:28 +00:00
|
|
|
|
* // be able to change its color CSS like this:
|
2015-11-11 05:25:24 +00:00
|
|
|
|
* //
|
2015-11-13 05:55:28 +00:00
|
|
|
|
* // levelbar block.my-offset {
|
|
|
|
|
* // background-color: magenta;
|
2015-11-11 05:25:24 +00:00
|
|
|
|
* // border-style: solid;
|
|
|
|
|
* // border-color: black;
|
|
|
|
|
* // border-style: 1px;
|
|
|
|
|
* // }
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*
|
2014-02-12 21:09:09 +00:00
|
|
|
|
* gtk_level_bar_add_offset_value (bar, "my-offset", 0.60);
|
|
|
|
|
*
|
|
|
|
|
* return widget;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
* }
|
2014-01-27 17:12:55 +00:00
|
|
|
|
* ]|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*
|
2014-02-07 18:01:26 +00:00
|
|
|
|
* The default interval of values is between zero and one, but it’s possible to
|
2012-05-29 21:00:33 +00:00
|
|
|
|
* modify the interval using gtk_level_bar_set_min_value() and
|
|
|
|
|
* gtk_level_bar_set_max_value(). The value will be always drawn in proportion to
|
|
|
|
|
* the admissible interval, i.e. a value of 15 with a specified interval between
|
|
|
|
|
* 10 and 20 is equivalent to a value of 0.5 with an interval between 0 and 1.
|
|
|
|
|
* When #GTK_LEVEL_BAR_MODE_DISCRETE is used, the bar level is rendered
|
2015-11-13 05:55:28 +00:00
|
|
|
|
* as a finite number of separated blocks instead of a single one. The number
|
2012-05-29 21:00:33 +00:00
|
|
|
|
* of blocks that will be rendered is equal to the number of units specified by
|
|
|
|
|
* the admissible interval.
|
2015-11-11 05:25:24 +00:00
|
|
|
|
*
|
2014-02-07 18:01:26 +00:00
|
|
|
|
* For instance, to build a bar rendered with five blocks, it’s sufficient to
|
2012-05-29 21:00:33 +00:00
|
|
|
|
* set the minimum value to 0 and the maximum value to 5 after changing the indicator
|
|
|
|
|
* mode to discrete.
|
|
|
|
|
*
|
2016-02-07 10:28:08 +00:00
|
|
|
|
* GtkLevelBar was introduced in GTK+ 3.6.
|
|
|
|
|
*
|
|
|
|
|
* # GtkLevelBar as GtkBuildable
|
|
|
|
|
*
|
|
|
|
|
* The GtkLevelBar implementation of the GtkBuildable interface supports a
|
|
|
|
|
* custom <offsets> element, which can contain any number of <offset> elements,
|
|
|
|
|
* each of which must have name and value attributes.
|
2015-11-11 05:25:24 +00:00
|
|
|
|
*
|
|
|
|
|
* # CSS nodes
|
|
|
|
|
*
|
|
|
|
|
* |[<!-- language="plain" -->
|
2015-11-13 05:55:28 +00:00
|
|
|
|
* levelbar[.discrete]
|
2015-11-11 05:25:24 +00:00
|
|
|
|
* ╰── trough
|
2015-12-16 15:55:52 +00:00
|
|
|
|
* ├── block.filled.level-name
|
2015-11-13 05:55:28 +00:00
|
|
|
|
* ┊
|
|
|
|
|
* ├── block.empty
|
|
|
|
|
* ┊
|
2015-11-11 05:25:24 +00:00
|
|
|
|
* ]|
|
|
|
|
|
*
|
2015-11-13 05:55:28 +00:00
|
|
|
|
* GtkLevelBar has a main CSS node with name levelbar and one of the style
|
|
|
|
|
* classes .discrete or .continuous and a subnode with name trough. Below the
|
|
|
|
|
* trough node are a number of nodes with name block and style class .filled
|
|
|
|
|
* or .empty. In continuous mode, there is exactly one node of each, in discrete
|
|
|
|
|
* mode, the number of filled and unfilled nodes corresponds to blocks that are
|
2015-12-16 15:55:52 +00:00
|
|
|
|
* drawn. The block.filled nodes also get a style class .level-name corresponding
|
2015-11-13 05:55:28 +00:00
|
|
|
|
* to the level for the current value.
|
2016-01-23 04:30:36 +00:00
|
|
|
|
*
|
|
|
|
|
* In horizontal orientation, the nodes are always arranged from left to right,
|
|
|
|
|
* regardless of text direction.
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*/
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
2019-09-21 10:56:09 +00:00
|
|
|
|
#include "gtkbinlayout.h"
|
2012-05-29 21:00:33 +00:00
|
|
|
|
#include "gtkbuildable.h"
|
2015-04-25 15:22:10 +00:00
|
|
|
|
#include "gtkbuilderprivate.h"
|
2012-05-29 21:00:33 +00:00
|
|
|
|
#include "gtkintl.h"
|
|
|
|
|
#include "gtkorientableprivate.h"
|
|
|
|
|
#include "gtklevelbar.h"
|
|
|
|
|
#include "gtkmarshalers.h"
|
|
|
|
|
#include "gtkstylecontext.h"
|
|
|
|
|
#include "gtktypebuiltins.h"
|
|
|
|
|
#include "gtkwidget.h"
|
2014-07-18 21:47:20 +00:00
|
|
|
|
#include "gtkwidgetprivate.h"
|
2015-11-11 05:25:24 +00:00
|
|
|
|
#include "gtkstylecontextprivate.h"
|
|
|
|
|
#include "gtkcssstylepropertyprivate.h"
|
|
|
|
|
#include "gtkcssnodeprivate.h"
|
2017-04-07 08:01:23 +00:00
|
|
|
|
#include "gtkgizmoprivate.h"
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
2012-12-03 22:07:23 +00:00
|
|
|
|
#include "a11y/gtklevelbaraccessible.h"
|
|
|
|
|
|
2012-08-15 07:52:01 +00:00
|
|
|
|
#include "fallback-c89.c"
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
enum {
|
|
|
|
|
PROP_VALUE = 1,
|
|
|
|
|
PROP_MIN_VALUE,
|
|
|
|
|
PROP_MAX_VALUE,
|
|
|
|
|
PROP_MODE,
|
2012-09-18 12:05:45 +00:00
|
|
|
|
PROP_INVERTED,
|
2012-05-29 21:00:33 +00:00
|
|
|
|
LAST_PROPERTY,
|
|
|
|
|
PROP_ORIENTATION /* overridden */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum {
|
|
|
|
|
SIGNAL_OFFSET_CHANGED,
|
|
|
|
|
NUM_SIGNALS
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
|
|
|
|
|
static guint signals[NUM_SIGNALS] = { 0, };
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
gchar *name;
|
|
|
|
|
gdouble value;
|
|
|
|
|
} GtkLevelBarOffset;
|
|
|
|
|
|
2019-05-27 02:24:14 +00:00
|
|
|
|
struct _GtkLevelBar {
|
|
|
|
|
GtkWidget parent_instance;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct _GtkLevelBarClass GtkLevelBarClass;
|
|
|
|
|
struct _GtkLevelBarClass {
|
|
|
|
|
GtkWidgetClass parent_class;
|
|
|
|
|
|
|
|
|
|
void (* offset_changed) (GtkLevelBar *self,
|
|
|
|
|
const gchar *name);
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
typedef struct _GtkLevelBarPrivate GtkLevelBarPrivate;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
struct _GtkLevelBarPrivate {
|
|
|
|
|
GtkOrientation orientation;
|
|
|
|
|
|
2013-09-22 03:37:48 +00:00
|
|
|
|
GtkLevelBarMode bar_mode;
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
gdouble min_value;
|
|
|
|
|
gdouble max_value;
|
|
|
|
|
gdouble cur_value;
|
|
|
|
|
|
|
|
|
|
GList *offsets;
|
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
GtkWidget *trough_widget;
|
|
|
|
|
GtkWidget **block_widget;
|
2015-11-13 05:55:28 +00:00
|
|
|
|
guint n_blocks;
|
2014-10-24 22:25:36 +00:00
|
|
|
|
|
2012-09-18 12:05:45 +00:00
|
|
|
|
guint inverted : 1;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static void gtk_level_bar_set_value_internal (GtkLevelBar *self,
|
|
|
|
|
gdouble value);
|
|
|
|
|
|
2013-06-27 19:02:52 +00:00
|
|
|
|
static void gtk_level_bar_buildable_init (GtkBuildableIface *iface);
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GtkLevelBar, gtk_level_bar, GTK_TYPE_WIDGET,
|
|
|
|
|
G_ADD_PRIVATE (GtkLevelBar)
|
|
|
|
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL)
|
|
|
|
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
|
|
|
|
gtk_level_bar_buildable_init))
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
static GtkLevelBarOffset *
|
|
|
|
|
gtk_level_bar_offset_new (const gchar *name,
|
|
|
|
|
gdouble value)
|
|
|
|
|
{
|
|
|
|
|
GtkLevelBarOffset *offset = g_slice_new0 (GtkLevelBarOffset);
|
|
|
|
|
|
|
|
|
|
offset->name = g_strdup (name);
|
|
|
|
|
offset->value = value;
|
|
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_offset_free (GtkLevelBarOffset *offset)
|
|
|
|
|
{
|
|
|
|
|
g_free (offset->name);
|
|
|
|
|
g_slice_free (GtkLevelBarOffset, offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
|
offset_find_func (gconstpointer data,
|
|
|
|
|
gconstpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
const GtkLevelBarOffset *offset = data;
|
|
|
|
|
const gchar *name = user_data;
|
|
|
|
|
|
|
|
|
|
return g_strcmp0 (name, offset->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
|
offset_sort_func (gconstpointer a,
|
|
|
|
|
gconstpointer b)
|
|
|
|
|
{
|
|
|
|
|
const GtkLevelBarOffset *offset_a = a;
|
|
|
|
|
const GtkLevelBarOffset *offset_b = b;
|
|
|
|
|
|
|
|
|
|
return (offset_a->value > offset_b->value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
gtk_level_bar_ensure_offset (GtkLevelBar *self,
|
|
|
|
|
const gchar *name,
|
|
|
|
|
gdouble value)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
GList *existing;
|
|
|
|
|
GtkLevelBarOffset *offset = NULL;
|
2016-02-26 19:51:24 +00:00
|
|
|
|
GtkLevelBarOffset *new_offset;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
existing = g_list_find_custom (priv->offsets, name, offset_find_func);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
if (existing)
|
|
|
|
|
offset = existing->data;
|
|
|
|
|
|
|
|
|
|
if (offset && (offset->value == value))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2016-02-26 19:51:24 +00:00
|
|
|
|
new_offset = gtk_level_bar_offset_new (name, value);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
if (offset)
|
|
|
|
|
{
|
|
|
|
|
gtk_level_bar_offset_free (offset);
|
2018-03-18 12:52:55 +00:00
|
|
|
|
priv->offsets = g_list_delete_link (priv->offsets, existing);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
priv->offsets = g_list_insert_sorted (priv->offsets, new_offset, offset_sort_func);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
gtk_level_bar_value_in_interval (GtkLevelBar *self,
|
|
|
|
|
gdouble value)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
return ((value >= priv->min_value) &&
|
|
|
|
|
(value <= priv->max_value));
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gint
|
|
|
|
|
gtk_level_bar_get_num_blocks (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
if (priv->bar_mode == GTK_LEVEL_BAR_MODE_CONTINUOUS)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
return 1;
|
2018-03-18 12:52:55 +00:00
|
|
|
|
else if (priv->bar_mode == GTK_LEVEL_BAR_MODE_DISCRETE)
|
|
|
|
|
return MAX (1, (gint) (round (priv->max_value) - round (priv->min_value)));
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-03 01:54:06 +00:00
|
|
|
|
static gint
|
|
|
|
|
gtk_level_bar_get_num_block_nodes (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
if (priv->bar_mode == GTK_LEVEL_BAR_MODE_CONTINUOUS)
|
2016-01-03 01:54:06 +00:00
|
|
|
|
return 2;
|
|
|
|
|
else
|
|
|
|
|
return gtk_level_bar_get_num_blocks (self);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-05 02:14:33 +00:00
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_get_min_block_size (GtkLevelBar *self,
|
|
|
|
|
gint *block_width,
|
|
|
|
|
gint *block_height)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2016-01-05 02:14:33 +00:00
|
|
|
|
guint i, n_blocks;
|
|
|
|
|
gint width, height;
|
|
|
|
|
|
|
|
|
|
*block_width = *block_height = 0;
|
|
|
|
|
n_blocks = gtk_level_bar_get_num_block_nodes (self);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < n_blocks; i++)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_measure (priv->block_widget[i],
|
2017-04-07 08:01:23 +00:00
|
|
|
|
GTK_ORIENTATION_HORIZONTAL,
|
|
|
|
|
-1,
|
|
|
|
|
&width, NULL,
|
|
|
|
|
NULL, NULL);
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_measure (priv->block_widget[i],
|
2017-04-07 08:01:23 +00:00
|
|
|
|
GTK_ORIENTATION_VERTICAL,
|
|
|
|
|
-1,
|
|
|
|
|
&height, NULL,
|
|
|
|
|
NULL, NULL);
|
2016-01-05 02:14:33 +00:00
|
|
|
|
|
|
|
|
|
*block_width = MAX (width, *block_width);
|
|
|
|
|
*block_height = MAX (height, *block_height);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-03 02:03:15 +00:00
|
|
|
|
static gboolean
|
|
|
|
|
gtk_level_bar_get_real_inverted (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2016-01-03 02:03:15 +00:00
|
|
|
|
if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL &&
|
2018-03-18 12:52:55 +00:00
|
|
|
|
priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
|
|
|
|
return !priv->inverted;
|
2016-01-03 02:03:15 +00:00
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
return priv->inverted;
|
2016-01-03 02:03:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-18 07:01:40 +00:00
|
|
|
|
static void
|
2017-04-07 08:01:23 +00:00
|
|
|
|
gtk_level_bar_render_trough (GtkGizmo *gizmo,
|
|
|
|
|
GtkSnapshot *snapshot)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2017-04-07 08:01:23 +00:00
|
|
|
|
GtkWidget *widget = GTK_WIDGET (gizmo);
|
|
|
|
|
GtkLevelBar *self = GTK_LEVEL_BAR (gtk_widget_get_parent (GTK_WIDGET (gizmo)));
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->bar_mode == GTK_LEVEL_BAR_MODE_CONTINUOUS)
|
2017-04-07 08:01:23 +00:00
|
|
|
|
{
|
|
|
|
|
gboolean inverted;
|
2015-11-11 05:25:24 +00:00
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
inverted = gtk_level_bar_get_real_inverted (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
/* render the empty (unfilled) part */
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_snapshot_child (widget, priv->block_widget[inverted ? 0 : 1], snapshot);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
/* now render the filled part on top of it */
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->cur_value != 0)
|
|
|
|
|
gtk_widget_snapshot_child (widget, priv->block_widget[inverted ? 1 : 0], snapshot);
|
2017-04-07 08:01:23 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
gint num_blocks, i;
|
2012-09-18 12:05:45 +00:00
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
num_blocks = gtk_level_bar_get_num_blocks (self);
|
2016-01-03 02:03:50 +00:00
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
for (i = 0; i < num_blocks; i++)
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_snapshot_child (widget, priv->block_widget[i], snapshot);
|
2017-04-07 08:01:23 +00:00
|
|
|
|
}
|
2016-01-03 02:03:50 +00:00
|
|
|
|
}
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
static void
|
2017-04-07 08:01:23 +00:00
|
|
|
|
gtk_level_bar_measure_trough (GtkGizmo *gizmo,
|
2016-01-03 02:03:50 +00:00
|
|
|
|
GtkOrientation orientation,
|
|
|
|
|
int for_size,
|
|
|
|
|
int *minimum,
|
|
|
|
|
int *natural,
|
|
|
|
|
int *minimum_baseline,
|
2017-04-07 08:01:23 +00:00
|
|
|
|
int *natural_baseline)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2017-04-07 08:01:23 +00:00
|
|
|
|
GtkWidget *widget = GTK_WIDGET (gizmo);
|
|
|
|
|
GtkLevelBar *self = GTK_LEVEL_BAR (gtk_widget_get_parent (widget));
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2016-01-03 02:03:50 +00:00
|
|
|
|
gint num_blocks, size;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
gint block_width, block_height;
|
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
num_blocks = gtk_level_bar_get_num_blocks (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
gtk_level_bar_get_min_block_size (self, &block_width, &block_height);
|
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
2016-01-03 02:03:50 +00:00
|
|
|
|
size = num_blocks * block_width;
|
|
|
|
|
else
|
|
|
|
|
size = block_width;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->orientation == GTK_ORIENTATION_VERTICAL)
|
2016-01-03 02:03:50 +00:00
|
|
|
|
size = num_blocks * block_height;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
else
|
2016-01-03 02:03:50 +00:00
|
|
|
|
size = block_height;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
2016-01-03 02:03:50 +00:00
|
|
|
|
|
|
|
|
|
*minimum = size;
|
|
|
|
|
*natural = size;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
static void
|
2018-08-16 04:53:03 +00:00
|
|
|
|
gtk_level_bar_allocate_trough_continuous (GtkLevelBar *self,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
int baseline)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2018-03-31 19:02:28 +00:00
|
|
|
|
GtkAllocation block_area;
|
2016-01-03 02:03:50 +00:00
|
|
|
|
gdouble fill_percentage;
|
|
|
|
|
gboolean inverted;
|
2017-08-12 15:13:11 +00:00
|
|
|
|
int block_min;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
inverted = gtk_level_bar_get_real_inverted (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
/* allocate the empty (unfilled) part */
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_size_allocate (priv->block_widget[inverted ? 0 : 1],
|
2018-08-16 04:53:03 +00:00
|
|
|
|
&(GtkAllocation) {0, 0, width, height},
|
2018-03-31 19:02:28 +00:00
|
|
|
|
baseline);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->cur_value == 0)
|
2017-08-12 15:13:11 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
/* now allocate the filled part */
|
2018-08-16 04:53:03 +00:00
|
|
|
|
block_area = (GtkAllocation) {0, 0, width, height};
|
2018-03-18 12:52:55 +00:00
|
|
|
|
fill_percentage = (priv->cur_value - priv->min_value) /
|
|
|
|
|
(priv->max_value - priv->min_value);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_measure (priv->block_widget[inverted ? 1 : 0],
|
|
|
|
|
priv->orientation, -1,
|
2017-08-12 15:13:11 +00:00
|
|
|
|
&block_min, NULL,
|
|
|
|
|
NULL, NULL);
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
2016-01-03 02:03:50 +00:00
|
|
|
|
{
|
|
|
|
|
block_area.width = (gint) floor (block_area.width * fill_percentage);
|
2017-08-12 15:13:11 +00:00
|
|
|
|
block_area.width = MAX (block_area.width, block_min);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
if (inverted)
|
2018-08-16 04:53:03 +00:00
|
|
|
|
block_area.x += width - block_area.width;
|
2016-01-03 02:03:50 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
block_area.height = (gint) floor (block_area.height * fill_percentage);
|
2017-08-12 15:13:11 +00:00
|
|
|
|
block_area.height = MAX (block_area.height, block_min);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
if (inverted)
|
2018-08-16 04:53:03 +00:00
|
|
|
|
block_area.y += height - block_area.height;
|
2016-01-03 02:03:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_size_allocate (priv->block_widget[inverted ? 1 : 0],
|
2017-07-11 07:58:21 +00:00
|
|
|
|
&block_area,
|
2018-03-31 19:02:28 +00:00
|
|
|
|
baseline);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2016-01-03 02:03:50 +00:00
|
|
|
|
gtk_level_bar_allocate_trough_discrete (GtkLevelBar *self,
|
2018-08-16 04:53:03 +00:00
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
int baseline)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2018-03-31 19:02:28 +00:00
|
|
|
|
GtkAllocation block_area;
|
2016-01-03 02:03:50 +00:00
|
|
|
|
gint num_blocks, i;
|
|
|
|
|
gint block_width, block_height;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
gtk_level_bar_get_min_block_size (self, &block_width, &block_height);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
num_blocks = gtk_level_bar_get_num_blocks (self);
|
|
|
|
|
|
2017-04-30 18:19:56 +00:00
|
|
|
|
if (num_blocks == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
2016-02-05 10:53:50 +00:00
|
|
|
|
{
|
2018-08-16 04:53:03 +00:00
|
|
|
|
block_width = MAX (block_width, (gint) floor (width / num_blocks));
|
|
|
|
|
block_height = height;
|
2016-02-05 10:53:50 +00:00
|
|
|
|
}
|
2012-05-29 21:00:33 +00:00
|
|
|
|
else
|
2016-02-05 10:53:50 +00:00
|
|
|
|
{
|
2018-08-16 04:53:03 +00:00
|
|
|
|
block_width = width;
|
|
|
|
|
block_height = MAX (block_height, (gint) floor (height / num_blocks));
|
2016-02-05 10:53:50 +00:00
|
|
|
|
}
|
2016-01-03 02:03:50 +00:00
|
|
|
|
|
2018-08-16 04:53:03 +00:00
|
|
|
|
block_area.x = 0;
|
|
|
|
|
block_area.y = 0;
|
2016-01-03 02:03:50 +00:00
|
|
|
|
block_area.width = block_width;
|
|
|
|
|
block_area.height = block_height;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2016-01-03 02:03:50 +00:00
|
|
|
|
for (i = 0; i < num_blocks; i++)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_size_allocate (priv->block_widget[i],
|
2017-07-11 07:58:21 +00:00
|
|
|
|
&block_area,
|
2018-03-31 19:02:28 +00:00
|
|
|
|
baseline);
|
2016-01-03 02:03:50 +00:00
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
|
2016-01-03 02:03:50 +00:00
|
|
|
|
block_area.x += block_area.width;
|
|
|
|
|
else
|
|
|
|
|
block_area.y += block_area.height;
|
|
|
|
|
}
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2018-08-16 04:53:03 +00:00
|
|
|
|
gtk_level_bar_allocate_trough (GtkGizmo *gizmo,
|
|
|
|
|
int width,
|
|
|
|
|
int height,
|
|
|
|
|
int baseline)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2017-04-07 08:01:23 +00:00
|
|
|
|
GtkWidget *widget = GTK_WIDGET (gizmo);
|
|
|
|
|
GtkLevelBar *self = GTK_LEVEL_BAR (gtk_widget_get_parent (widget));
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (priv->bar_mode == GTK_LEVEL_BAR_MODE_CONTINUOUS)
|
2018-08-16 04:53:03 +00:00
|
|
|
|
gtk_level_bar_allocate_trough_continuous (self, width, height, baseline);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
else
|
2018-08-16 04:53:03 +00:00
|
|
|
|
gtk_level_bar_allocate_trough_discrete (self, width, height, baseline);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
static void
|
|
|
|
|
update_block_nodes (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
guint n_blocks;
|
|
|
|
|
guint i;
|
|
|
|
|
|
2016-01-03 01:54:06 +00:00
|
|
|
|
n_blocks = gtk_level_bar_get_num_block_nodes (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
|
|
|
|
|
if (priv->n_blocks == n_blocks)
|
|
|
|
|
return;
|
|
|
|
|
else if (n_blocks < priv->n_blocks)
|
|
|
|
|
{
|
|
|
|
|
for (i = n_blocks; i < priv->n_blocks; i++)
|
2016-03-01 20:35:32 +00:00
|
|
|
|
{
|
2017-04-07 08:01:23 +00:00
|
|
|
|
gtk_widget_unparent (priv->block_widget[i]);
|
2016-03-01 20:35:32 +00:00
|
|
|
|
}
|
2017-04-07 08:01:23 +00:00
|
|
|
|
priv->block_widget = g_renew (GtkWidget*, priv->block_widget, n_blocks);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
priv->n_blocks = n_blocks;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2017-04-07 08:01:23 +00:00
|
|
|
|
priv->block_widget = g_renew (GtkWidget*, priv->block_widget, n_blocks);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
for (i = priv->n_blocks; i < n_blocks; i++)
|
|
|
|
|
{
|
2019-04-07 15:47:24 +00:00
|
|
|
|
priv->block_widget[i] = gtk_gizmo_new ("block", NULL, NULL, NULL, NULL);
|
2017-04-07 08:01:23 +00:00
|
|
|
|
gtk_widget_insert_before (priv->block_widget[i], GTK_WIDGET (priv->trough_widget), NULL);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
}
|
|
|
|
|
priv->n_blocks = n_blocks;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
update_mode_style_classes (GtkLevelBar *self)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
GtkCssNode *widget_node;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
widget_node = gtk_widget_get_css_node (GTK_WIDGET (self));
|
2015-11-11 05:25:24 +00:00
|
|
|
|
if (priv->bar_mode == GTK_LEVEL_BAR_MODE_CONTINUOUS)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2015-11-13 05:55:28 +00:00
|
|
|
|
gtk_css_node_remove_class (widget_node, g_quark_from_static_string ("discrete"));
|
|
|
|
|
gtk_css_node_add_class (widget_node, g_quark_from_static_string ("continuous"));
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
2015-11-11 05:25:24 +00:00
|
|
|
|
else if (priv->bar_mode == GTK_LEVEL_BAR_MODE_DISCRETE)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2015-11-13 05:55:28 +00:00
|
|
|
|
gtk_css_node_add_class (widget_node, g_quark_from_static_string ("discrete"));
|
|
|
|
|
gtk_css_node_remove_class (widget_node, g_quark_from_static_string ("continuous"));
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-11-13 05:55:28 +00:00
|
|
|
|
update_level_style_classes (GtkLevelBar *self)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-11 05:25:24 +00:00
|
|
|
|
gdouble value;
|
2015-11-13 05:55:28 +00:00
|
|
|
|
const gchar *value_class = NULL;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
GtkLevelBarOffset *offset, *prev_offset;
|
|
|
|
|
GList *l;
|
2016-11-02 02:46:10 +00:00
|
|
|
|
gint num_filled, num_blocks, i;
|
|
|
|
|
gboolean inverted;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2015-11-11 05:25:24 +00:00
|
|
|
|
value = gtk_level_bar_get_value (self);
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
for (l = priv->offsets; l != NULL; l = l->next)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
|
|
|
|
offset = l->data;
|
|
|
|
|
|
|
|
|
|
/* find the right offset for our style class */
|
2016-02-06 15:42:25 +00:00
|
|
|
|
if (value <= offset->value)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2016-02-06 15:42:25 +00:00
|
|
|
|
if (l->prev == NULL)
|
|
|
|
|
{
|
|
|
|
|
value_class = offset->name;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
prev_offset = l->prev->data;
|
|
|
|
|
if (prev_offset->value < value)
|
|
|
|
|
value_class = offset->name;
|
|
|
|
|
}
|
2015-11-13 05:55:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value_class)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-02 02:46:10 +00:00
|
|
|
|
inverted = gtk_level_bar_get_real_inverted (self);
|
|
|
|
|
num_blocks = gtk_level_bar_get_num_block_nodes (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
|
2016-11-02 02:46:10 +00:00
|
|
|
|
if (priv->bar_mode == GTK_LEVEL_BAR_MODE_CONTINUOUS)
|
|
|
|
|
num_filled = 1;
|
|
|
|
|
else
|
|
|
|
|
num_filled = MIN (num_blocks, (gint) round (priv->cur_value) - (gint) round (priv->min_value));
|
2016-01-03 02:14:47 +00:00
|
|
|
|
|
2016-11-02 02:46:10 +00:00
|
|
|
|
for (i = 0; i < num_filled; i++)
|
2017-04-07 08:01:23 +00:00
|
|
|
|
{
|
|
|
|
|
GtkStyleContext *context = gtk_widget_get_style_context (priv->block_widget[inverted ? num_blocks - 1 - i : i]);
|
|
|
|
|
GList *classes = gtk_style_context_list_classes (context);
|
|
|
|
|
|
|
|
|
|
for (l = classes; l; l = l->next)
|
|
|
|
|
gtk_style_context_remove_class (context, l->data);
|
|
|
|
|
|
|
|
|
|
g_list_free (classes);
|
|
|
|
|
|
|
|
|
|
gtk_style_context_add_class (context, "filled");
|
|
|
|
|
if (value_class)
|
|
|
|
|
gtk_style_context_add_class (context, value_class);
|
|
|
|
|
}
|
2015-11-13 05:55:28 +00:00
|
|
|
|
|
2016-11-02 02:46:10 +00:00
|
|
|
|
for (; i < num_blocks; i++)
|
2017-04-07 08:01:23 +00:00
|
|
|
|
{
|
|
|
|
|
GtkStyleContext *context = gtk_widget_get_style_context (priv->block_widget[inverted ? num_blocks - 1 - i : i]);
|
|
|
|
|
GList *classes = gtk_style_context_list_classes (context);
|
|
|
|
|
|
|
|
|
|
for (l = classes; l; l = l->next)
|
|
|
|
|
gtk_style_context_remove_class (context, l->data);
|
|
|
|
|
|
|
|
|
|
g_list_free (classes);
|
|
|
|
|
|
|
|
|
|
gtk_style_context_add_class (context, "empty");
|
|
|
|
|
}
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_direction_changed (GtkWidget *widget,
|
|
|
|
|
GtkTextDirection previous_dir)
|
|
|
|
|
{
|
|
|
|
|
GtkLevelBar *self = GTK_LEVEL_BAR (widget);
|
|
|
|
|
|
|
|
|
|
update_level_style_classes (self);
|
|
|
|
|
|
|
|
|
|
GTK_WIDGET_CLASS (gtk_level_bar_parent_class)->direction_changed (widget, previous_dir);
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_ensure_offsets_in_range (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
GtkLevelBarOffset *offset;
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GList *l = priv->offsets;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
while (l != NULL)
|
|
|
|
|
{
|
|
|
|
|
offset = l->data;
|
|
|
|
|
l = l->next;
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (offset->value < priv->min_value)
|
|
|
|
|
gtk_level_bar_ensure_offset (self, offset->name, priv->min_value);
|
|
|
|
|
else if (offset->value > priv->max_value)
|
|
|
|
|
gtk_level_bar_ensure_offset (self, offset->name, priv->max_value);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
GtkLevelBar *self;
|
2015-04-25 15:22:10 +00:00
|
|
|
|
GtkBuilder *builder;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
GList *offsets;
|
|
|
|
|
} OffsetsParserData;
|
|
|
|
|
|
|
|
|
|
static void
|
2019-08-29 13:21:20 +00:00
|
|
|
|
offset_start_element (GtkBuildableParseContext *context,
|
|
|
|
|
const gchar *element_name,
|
|
|
|
|
const gchar **names,
|
|
|
|
|
const gchar **values,
|
|
|
|
|
gpointer user_data,
|
|
|
|
|
GError **error)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2015-04-25 15:22:10 +00:00
|
|
|
|
OffsetsParserData *data = user_data;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
if (strcmp (element_name, "offsets") == 0)
|
2015-04-25 15:22:10 +00:00
|
|
|
|
{
|
|
|
|
|
if (!_gtk_builder_check_parent (data->builder, context, "object", error))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!g_markup_collect_attributes (element_name, names, values, error,
|
|
|
|
|
G_MARKUP_COLLECT_INVALID, NULL, NULL,
|
|
|
|
|
G_MARKUP_COLLECT_INVALID))
|
|
|
|
|
_gtk_builder_prefix_error (data->builder, context, error);
|
|
|
|
|
}
|
2012-05-29 21:00:33 +00:00
|
|
|
|
else if (strcmp (element_name, "offset") == 0)
|
|
|
|
|
{
|
2015-04-25 15:22:10 +00:00
|
|
|
|
const gchar *name;
|
|
|
|
|
const gchar *value;
|
|
|
|
|
GValue gvalue = G_VALUE_INIT;
|
|
|
|
|
GtkLevelBarOffset *offset;
|
|
|
|
|
|
|
|
|
|
if (!_gtk_builder_check_parent (data->builder, context, "offsets", error))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!g_markup_collect_attributes (element_name, names, values, error,
|
|
|
|
|
G_MARKUP_COLLECT_STRING, "name", &name,
|
|
|
|
|
G_MARKUP_COLLECT_STRING, "value", &value,
|
|
|
|
|
G_MARKUP_COLLECT_INVALID))
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2015-04-25 15:22:10 +00:00
|
|
|
|
_gtk_builder_prefix_error (data->builder, context, error);
|
|
|
|
|
return;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-04-25 15:22:10 +00:00
|
|
|
|
if (!gtk_builder_value_from_string_type (data->builder, G_TYPE_DOUBLE, value, &gvalue, error))
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2015-04-25 15:22:10 +00:00
|
|
|
|
_gtk_builder_prefix_error (data->builder, context, error);
|
|
|
|
|
return;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
2015-04-25 15:22:10 +00:00
|
|
|
|
|
|
|
|
|
offset = gtk_level_bar_offset_new (name, g_value_get_double (&gvalue));
|
|
|
|
|
data->offsets = g_list_prepend (data->offsets, offset);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-04-25 15:22:10 +00:00
|
|
|
|
_gtk_builder_error_unhandled_tag (data->builder, context,
|
|
|
|
|
"GtkLevelBar", element_name,
|
|
|
|
|
error);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-29 13:21:20 +00:00
|
|
|
|
static const GtkBuildableParser offset_parser =
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
|
|
|
|
offset_start_element
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2019-08-29 13:21:20 +00:00
|
|
|
|
gtk_level_bar_buildable_custom_tag_start (GtkBuildable *buildable,
|
|
|
|
|
GtkBuilder *builder,
|
|
|
|
|
GObject *child,
|
|
|
|
|
const gchar *tagname,
|
|
|
|
|
GtkBuildableParser *parser,
|
|
|
|
|
gpointer *parser_data)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2015-04-25 15:22:10 +00:00
|
|
|
|
OffsetsParserData *data;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
if (child)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (strcmp (tagname, "offsets") != 0)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2015-04-25 15:22:10 +00:00
|
|
|
|
data = g_slice_new0 (OffsetsParserData);
|
|
|
|
|
data->self = GTK_LEVEL_BAR (buildable);
|
|
|
|
|
data->builder = builder;
|
|
|
|
|
data->offsets = NULL;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
*parser = offset_parser;
|
2015-04-25 15:22:10 +00:00
|
|
|
|
*parser_data = data;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_buildable_custom_finished (GtkBuildable *buildable,
|
|
|
|
|
GtkBuilder *builder,
|
|
|
|
|
GObject *child,
|
|
|
|
|
const gchar *tagname,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
2015-04-25 15:22:10 +00:00
|
|
|
|
OffsetsParserData *data = user_data;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
GtkLevelBar *self;
|
|
|
|
|
GtkLevelBarOffset *offset;
|
|
|
|
|
GList *l;
|
|
|
|
|
|
2015-04-25 15:22:10 +00:00
|
|
|
|
self = data->self;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
if (strcmp (tagname, "offsets") != 0)
|
|
|
|
|
goto out;
|
|
|
|
|
|
2015-04-25 15:22:10 +00:00
|
|
|
|
for (l = data->offsets; l != NULL; l = l->next)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
|
|
|
|
offset = l->data;
|
|
|
|
|
gtk_level_bar_add_offset_value (self, offset->name, offset->value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out:
|
2015-04-25 15:22:10 +00:00
|
|
|
|
g_list_free_full (data->offsets, (GDestroyNotify) gtk_level_bar_offset_free);
|
|
|
|
|
g_slice_free (OffsetsParserData, data);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_buildable_init (GtkBuildableIface *iface)
|
|
|
|
|
{
|
|
|
|
|
iface->custom_tag_start = gtk_level_bar_buildable_custom_tag_start;
|
|
|
|
|
iface->custom_finished = gtk_level_bar_buildable_custom_finished;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-06-09 13:01:23 +00:00
|
|
|
|
gtk_level_bar_set_orientation (GtkLevelBar *self,
|
|
|
|
|
GtkOrientation orientation)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
if (priv->orientation != orientation)
|
2012-05-29 21:00:33 +00:00
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
priv->orientation = orientation;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (self));
|
|
|
|
|
gtk_widget_queue_resize (GTK_WIDGET (self));
|
2014-06-09 13:01:23 +00:00
|
|
|
|
g_object_notify (G_OBJECT (self), "orientation");
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_get_property (GObject *obj,
|
|
|
|
|
guint property_id,
|
|
|
|
|
GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
GtkLevelBar *self = GTK_LEVEL_BAR (obj);
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
|
{
|
|
|
|
|
case PROP_VALUE:
|
|
|
|
|
g_value_set_double (value, gtk_level_bar_get_value (self));
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MIN_VALUE:
|
|
|
|
|
g_value_set_double (value, gtk_level_bar_get_min_value (self));
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MAX_VALUE:
|
|
|
|
|
g_value_set_double (value, gtk_level_bar_get_max_value (self));
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MODE:
|
|
|
|
|
g_value_set_enum (value, gtk_level_bar_get_mode (self));
|
|
|
|
|
break;
|
2012-09-18 12:05:45 +00:00
|
|
|
|
case PROP_INVERTED:
|
|
|
|
|
g_value_set_boolean (value, gtk_level_bar_get_inverted (self));
|
|
|
|
|
break;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
case PROP_ORIENTATION:
|
2018-03-18 12:52:55 +00:00
|
|
|
|
g_value_set_enum (value, priv->orientation);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_set_property (GObject *obj,
|
|
|
|
|
guint property_id,
|
|
|
|
|
const GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
|
|
|
|
GtkLevelBar *self = GTK_LEVEL_BAR (obj);
|
|
|
|
|
|
|
|
|
|
switch (property_id)
|
|
|
|
|
{
|
|
|
|
|
case PROP_VALUE:
|
|
|
|
|
gtk_level_bar_set_value (self, g_value_get_double (value));
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MIN_VALUE:
|
|
|
|
|
gtk_level_bar_set_min_value (self, g_value_get_double (value));
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MAX_VALUE:
|
|
|
|
|
gtk_level_bar_set_max_value (self, g_value_get_double (value));
|
|
|
|
|
break;
|
|
|
|
|
case PROP_MODE:
|
|
|
|
|
gtk_level_bar_set_mode (self, g_value_get_enum (value));
|
|
|
|
|
break;
|
2012-09-18 12:05:45 +00:00
|
|
|
|
case PROP_INVERTED:
|
|
|
|
|
gtk_level_bar_set_inverted (self, g_value_get_boolean (value));
|
|
|
|
|
break;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
case PROP_ORIENTATION:
|
|
|
|
|
gtk_level_bar_set_orientation (self, g_value_get_enum (value));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_finalize (GObject *obj)
|
|
|
|
|
{
|
|
|
|
|
GtkLevelBar *self = GTK_LEVEL_BAR (obj);
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2016-01-03 02:03:50 +00:00
|
|
|
|
gint i;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
g_list_free_full (priv->offsets, (GDestroyNotify) gtk_level_bar_offset_free);
|
2016-01-03 02:03:50 +00:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < priv->n_blocks; i++)
|
2017-04-07 08:01:23 +00:00
|
|
|
|
gtk_widget_unparent (priv->block_widget[i]);
|
|
|
|
|
|
|
|
|
|
g_free (priv->block_widget);
|
2016-01-03 02:03:50 +00:00
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
gtk_widget_unparent (priv->trough_widget);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (gtk_level_bar_parent_class)->finalize (obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_class_init (GtkLevelBarClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *oclass = G_OBJECT_CLASS (klass);
|
|
|
|
|
GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
oclass->get_property = gtk_level_bar_get_property;
|
|
|
|
|
oclass->set_property = gtk_level_bar_set_property;
|
|
|
|
|
oclass->finalize = gtk_level_bar_finalize;
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
wclass->direction_changed = gtk_level_bar_direction_changed;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
g_object_class_override_property (oclass, PROP_ORIENTATION, "orientation");
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GtkLevelBar::offset-changed:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
* @name: the name of the offset that changed value
|
|
|
|
|
*
|
|
|
|
|
* Emitted when an offset specified on the bar changes value as an
|
|
|
|
|
* effect to gtk_level_bar_add_offset_value() being called.
|
|
|
|
|
*
|
|
|
|
|
* The signal supports detailed connections; you can connect to the
|
|
|
|
|
* detailed signal "changed::x" in order to only receive callbacks when
|
|
|
|
|
* the value of offset "x" changes.
|
|
|
|
|
*/
|
|
|
|
|
signals[SIGNAL_OFFSET_CHANGED] =
|
2015-09-12 13:13:00 +00:00
|
|
|
|
g_signal_new (I_("offset-changed"),
|
2012-05-29 21:00:33 +00:00
|
|
|
|
GTK_TYPE_LEVEL_BAR,
|
|
|
|
|
G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
|
|
|
|
|
G_STRUCT_OFFSET (GtkLevelBarClass, offset_changed),
|
|
|
|
|
NULL, NULL,
|
2016-08-29 14:00:17 +00:00
|
|
|
|
NULL,
|
2012-05-29 21:00:33 +00:00
|
|
|
|
G_TYPE_NONE,
|
|
|
|
|
1, G_TYPE_STRING);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* GtkLevelBar:value:
|
|
|
|
|
*
|
|
|
|
|
* The #GtkLevelBar:value property determines the currently
|
|
|
|
|
* filled value of the level bar.
|
|
|
|
|
*/
|
|
|
|
|
properties[PROP_VALUE] =
|
|
|
|
|
g_param_spec_double ("value",
|
|
|
|
|
P_("Currently filled value level"),
|
|
|
|
|
P_("Currently filled value level of the level bar"),
|
|
|
|
|
0.0, G_MAXDOUBLE, 0.0,
|
2014-06-09 13:01:23 +00:00
|
|
|
|
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
/**
|
|
|
|
|
* GtkLevelBar:min-value:
|
|
|
|
|
*
|
|
|
|
|
* The #GtkLevelBar:min-value property determines the minimum value of
|
|
|
|
|
* the interval that can be displayed by the bar.
|
|
|
|
|
*/
|
|
|
|
|
properties[PROP_MIN_VALUE] =
|
|
|
|
|
g_param_spec_double ("min-value",
|
|
|
|
|
P_("Minimum value level for the bar"),
|
|
|
|
|
P_("Minimum value level that can be displayed by the bar"),
|
|
|
|
|
0.0, G_MAXDOUBLE, 0.0,
|
2014-06-09 13:01:23 +00:00
|
|
|
|
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
/**
|
|
|
|
|
* GtkLevelBar:max-value:
|
|
|
|
|
*
|
|
|
|
|
* The #GtkLevelBar:max-value property determaxes the maximum value of
|
|
|
|
|
* the interval that can be displayed by the bar.
|
|
|
|
|
*/
|
|
|
|
|
properties[PROP_MAX_VALUE] =
|
|
|
|
|
g_param_spec_double ("max-value",
|
|
|
|
|
P_("Maximum value level for the bar"),
|
|
|
|
|
P_("Maximum value level that can be displayed by the bar"),
|
|
|
|
|
0.0, G_MAXDOUBLE, 1.0,
|
2014-06-09 13:01:23 +00:00
|
|
|
|
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
/**
|
|
|
|
|
* GtkLevelBar:mode:
|
|
|
|
|
*
|
2014-01-21 19:49:40 +00:00
|
|
|
|
* The #GtkLevelBar:mode property determines the way #GtkLevelBar
|
2012-05-29 21:00:33 +00:00
|
|
|
|
* interprets the value properties to draw the level fill area.
|
|
|
|
|
* Specifically, when the value is #GTK_LEVEL_BAR_MODE_CONTINUOUS,
|
|
|
|
|
* #GtkLevelBar will draw a single block representing the current value in
|
|
|
|
|
* that area; when the value is #GTK_LEVEL_BAR_MODE_DISCRETE,
|
|
|
|
|
* the widget will draw a succession of separate blocks filling the
|
|
|
|
|
* draw area, with the number of blocks being equal to the units separating
|
|
|
|
|
* the integral roundings of #GtkLevelBar:min-value and #GtkLevelBar:max-value.
|
|
|
|
|
*/
|
|
|
|
|
properties[PROP_MODE] =
|
|
|
|
|
g_param_spec_enum ("mode",
|
|
|
|
|
P_("The mode of the value indicator"),
|
|
|
|
|
P_("The mode of the value indicator displayed by the bar"),
|
|
|
|
|
GTK_TYPE_LEVEL_BAR_MODE,
|
|
|
|
|
GTK_LEVEL_BAR_MODE_CONTINUOUS,
|
2014-06-09 13:01:23 +00:00
|
|
|
|
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2012-09-18 12:05:45 +00:00
|
|
|
|
/**
|
|
|
|
|
* GtkLevelBar:inverted:
|
|
|
|
|
*
|
|
|
|
|
* Level bars normally grow from top to bottom or left to right.
|
|
|
|
|
* Inverted level bars grow in the opposite direction.
|
|
|
|
|
*/
|
|
|
|
|
properties[PROP_INVERTED] =
|
|
|
|
|
g_param_spec_boolean ("inverted",
|
|
|
|
|
P_("Inverted"),
|
|
|
|
|
P_("Invert the direction in which the level bar grows"),
|
|
|
|
|
FALSE,
|
2014-06-09 13:01:23 +00:00
|
|
|
|
G_PARAM_READWRITE|G_PARAM_STATIC_STRINGS|G_PARAM_EXPLICIT_NOTIFY);
|
2012-09-18 12:05:45 +00:00
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_object_class_install_properties (oclass, LAST_PROPERTY, properties);
|
2012-12-03 22:07:23 +00:00
|
|
|
|
|
|
|
|
|
gtk_widget_class_set_accessible_type (wclass, GTK_TYPE_LEVEL_BAR_ACCESSIBLE);
|
2019-09-21 10:56:09 +00:00
|
|
|
|
gtk_widget_class_set_layout_manager_type (wclass, GTK_TYPE_BIN_LAYOUT);
|
2017-11-18 03:49:57 +00:00
|
|
|
|
gtk_widget_class_set_css_name (wclass, I_("levelbar"));
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-11-11 05:25:24 +00:00
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_init (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-11 05:25:24 +00:00
|
|
|
|
|
|
|
|
|
priv->cur_value = 0.0;
|
|
|
|
|
priv->min_value = 0.0;
|
|
|
|
|
priv->max_value = 1.0;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
/* set initial orientation and style classes */
|
2015-11-11 05:25:24 +00:00
|
|
|
|
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
_gtk_orientable_set_style_classes (GTK_ORIENTABLE (self));
|
|
|
|
|
|
2015-11-11 05:25:24 +00:00
|
|
|
|
priv->inverted = FALSE;
|
2012-09-18 12:05:45 +00:00
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
priv->trough_widget = gtk_gizmo_new ("trough",
|
|
|
|
|
gtk_level_bar_measure_trough,
|
|
|
|
|
gtk_level_bar_allocate_trough,
|
2019-04-07 15:47:24 +00:00
|
|
|
|
gtk_level_bar_render_trough,
|
|
|
|
|
NULL);
|
2017-04-07 08:01:23 +00:00
|
|
|
|
gtk_widget_set_parent (priv->trough_widget, GTK_WIDGET (self));
|
2015-11-11 05:25:24 +00:00
|
|
|
|
|
|
|
|
|
gtk_level_bar_ensure_offset (self, GTK_LEVEL_BAR_OFFSET_LOW, 0.25);
|
|
|
|
|
gtk_level_bar_ensure_offset (self, GTK_LEVEL_BAR_OFFSET_HIGH, 0.75);
|
2016-02-06 15:11:17 +00:00
|
|
|
|
gtk_level_bar_ensure_offset (self, GTK_LEVEL_BAR_OFFSET_FULL, 1.0);
|
2015-11-11 05:25:24 +00:00
|
|
|
|
|
2017-04-07 08:01:23 +00:00
|
|
|
|
priv->block_widget = NULL;
|
2015-11-13 05:55:28 +00:00
|
|
|
|
priv->n_blocks = 0;
|
2015-11-11 05:25:24 +00:00
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
priv->bar_mode = GTK_LEVEL_BAR_MODE_CONTINUOUS;
|
|
|
|
|
update_mode_style_classes (self);
|
|
|
|
|
update_block_nodes (self);
|
|
|
|
|
update_level_style_classes (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_new:
|
|
|
|
|
*
|
|
|
|
|
* Creates a new #GtkLevelBar.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a #GtkLevelBar.
|
|
|
|
|
*/
|
|
|
|
|
GtkWidget *
|
|
|
|
|
gtk_level_bar_new (void)
|
|
|
|
|
{
|
|
|
|
|
return g_object_new (GTK_TYPE_LEVEL_BAR, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_new_for_interval:
|
|
|
|
|
* @min_value: a positive value
|
|
|
|
|
* @max_value: a positive value
|
|
|
|
|
*
|
|
|
|
|
* Utility constructor that creates a new #GtkLevelBar for the specified
|
|
|
|
|
* interval.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a #GtkLevelBar
|
|
|
|
|
*/
|
|
|
|
|
GtkWidget *
|
|
|
|
|
gtk_level_bar_new_for_interval (gdouble min_value,
|
|
|
|
|
gdouble max_value)
|
|
|
|
|
{
|
|
|
|
|
return g_object_new (GTK_TYPE_LEVEL_BAR,
|
|
|
|
|
"min-value", min_value,
|
|
|
|
|
"max-value", max_value,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_get_min_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
*
|
|
|
|
|
* Returns the value of the #GtkLevelBar:min-value property.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a positive value
|
|
|
|
|
*/
|
|
|
|
|
gdouble
|
|
|
|
|
gtk_level_bar_get_min_value (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_LEVEL_BAR (self), 0.0);
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
return priv->min_value;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_get_max_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
*
|
|
|
|
|
* Returns the value of the #GtkLevelBar:max-value property.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a positive value
|
|
|
|
|
*/
|
|
|
|
|
gdouble
|
|
|
|
|
gtk_level_bar_get_max_value (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_LEVEL_BAR (self), 0.0);
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
return priv->max_value;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_get_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
*
|
|
|
|
|
* Returns the value of the #GtkLevelBar:value property.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a value in the interval between
|
|
|
|
|
* #GtkLevelBar:min-value and #GtkLevelBar:max-value
|
|
|
|
|
*/
|
|
|
|
|
gdouble
|
|
|
|
|
gtk_level_bar_get_value (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_LEVEL_BAR (self), 0.0);
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
return priv->cur_value;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gtk_level_bar_set_value_internal (GtkLevelBar *self,
|
|
|
|
|
gdouble value)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
|
|
|
|
priv->cur_value = value;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VALUE]);
|
2018-03-18 12:52:55 +00:00
|
|
|
|
gtk_widget_queue_allocate (GTK_WIDGET (priv->trough_widget));
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_set_min_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
* @value: a positive value
|
|
|
|
|
*
|
|
|
|
|
* Sets the value of the #GtkLevelBar:min-value property.
|
|
|
|
|
*
|
2016-02-06 15:19:13 +00:00
|
|
|
|
* You probably want to update preexisting level offsets after calling
|
|
|
|
|
* this function.
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gtk_level_bar_set_min_value (GtkLevelBar *self,
|
|
|
|
|
gdouble value)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_LEVEL_BAR (self));
|
|
|
|
|
g_return_if_fail (value >= 0.0);
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
if (value == priv->min_value)
|
|
|
|
|
return;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
priv->min_value = value;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
if (priv->min_value > priv->cur_value)
|
|
|
|
|
gtk_level_bar_set_value_internal (self, priv->min_value);
|
|
|
|
|
|
|
|
|
|
update_block_nodes (self);
|
|
|
|
|
update_level_style_classes (self);
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MIN_VALUE]);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_set_max_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
* @value: a positive value
|
|
|
|
|
*
|
|
|
|
|
* Sets the value of the #GtkLevelBar:max-value property.
|
|
|
|
|
*
|
2016-02-06 15:19:13 +00:00
|
|
|
|
* You probably want to update preexisting level offsets after calling
|
|
|
|
|
* this function.
|
2012-05-29 21:00:33 +00:00
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gtk_level_bar_set_max_value (GtkLevelBar *self,
|
|
|
|
|
gdouble value)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_LEVEL_BAR (self));
|
|
|
|
|
g_return_if_fail (value >= 0.0);
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
if (value == priv->max_value)
|
|
|
|
|
return;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
priv->max_value = value;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
if (priv->max_value < priv->cur_value)
|
|
|
|
|
gtk_level_bar_set_value_internal (self, priv->max_value);
|
|
|
|
|
|
|
|
|
|
gtk_level_bar_ensure_offsets_in_range (self);
|
|
|
|
|
update_block_nodes (self);
|
|
|
|
|
update_level_style_classes (self);
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MAX_VALUE]);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_set_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
* @value: a value in the interval between
|
|
|
|
|
* #GtkLevelBar:min-value and #GtkLevelBar:max-value
|
|
|
|
|
*
|
|
|
|
|
* Sets the value of the #GtkLevelBar:value property.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gtk_level_bar_set_value (GtkLevelBar *self,
|
|
|
|
|
gdouble value)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_LEVEL_BAR (self));
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
if (value == priv->cur_value)
|
2015-11-13 05:55:28 +00:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
gtk_level_bar_set_value_internal (self, value);
|
|
|
|
|
update_level_style_classes (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_get_mode:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
*
|
|
|
|
|
* Returns the value of the #GtkLevelBar:mode property.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a #GtkLevelBarMode
|
|
|
|
|
*/
|
|
|
|
|
GtkLevelBarMode
|
|
|
|
|
gtk_level_bar_get_mode (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_LEVEL_BAR (self), 0);
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
return priv->bar_mode;
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_set_mode:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
* @mode: a #GtkLevelBarMode
|
|
|
|
|
*
|
|
|
|
|
* Sets the value of the #GtkLevelBar:mode property.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gtk_level_bar_set_mode (GtkLevelBar *self,
|
|
|
|
|
GtkLevelBarMode mode)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_LEVEL_BAR (self));
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
if (priv->bar_mode == mode)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
priv->bar_mode = mode;
|
|
|
|
|
|
|
|
|
|
update_mode_style_classes (self);
|
|
|
|
|
update_block_nodes (self);
|
|
|
|
|
update_level_style_classes (self);
|
|
|
|
|
gtk_widget_queue_resize (GTK_WIDGET (self));
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODE]);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-18 12:05:45 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_get_inverted:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
*
|
|
|
|
|
* Return the value of the #GtkLevelBar:inverted property.
|
|
|
|
|
*
|
2014-02-19 23:49:43 +00:00
|
|
|
|
* Returns: %TRUE if the level bar is inverted
|
2012-09-18 12:05:45 +00:00
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
gtk_level_bar_get_inverted (GtkLevelBar *self)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
|
|
|
|
|
2012-09-18 12:05:45 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_LEVEL_BAR (self), FALSE);
|
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
return priv->inverted;
|
2012-09-18 12:05:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_set_inverted:
|
|
|
|
|
* @self: a #GtkLevelBar
|
2012-10-17 14:09:08 +00:00
|
|
|
|
* @inverted: %TRUE to invert the level bar
|
2012-09-18 12:05:45 +00:00
|
|
|
|
*
|
|
|
|
|
* Sets the value of the #GtkLevelBar:inverted property.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gtk_level_bar_set_inverted (GtkLevelBar *self,
|
|
|
|
|
gboolean inverted)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
|
2012-09-18 12:05:45 +00:00
|
|
|
|
g_return_if_fail (GTK_IS_LEVEL_BAR (self));
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
if (priv->inverted == inverted)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
priv->inverted = inverted;
|
|
|
|
|
gtk_widget_queue_resize (GTK_WIDGET (self));
|
|
|
|
|
update_level_style_classes (self);
|
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INVERTED]);
|
2012-09-18 12:05:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2012-05-29 21:00:33 +00:00
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_remove_offset_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
* @name: (allow-none): the name of an offset in the bar
|
|
|
|
|
*
|
|
|
|
|
* Removes an offset marker previously added with
|
|
|
|
|
* gtk_level_bar_add_offset_value().
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gtk_level_bar_remove_offset_value (GtkLevelBar *self,
|
|
|
|
|
const gchar *name)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
GList *existing;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (GTK_IS_LEVEL_BAR (self));
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
existing = g_list_find_custom (priv->offsets, name, offset_find_func);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
if (existing)
|
|
|
|
|
{
|
|
|
|
|
gtk_level_bar_offset_free (existing->data);
|
2015-11-13 05:55:28 +00:00
|
|
|
|
priv->offsets = g_list_delete_link (priv->offsets, existing);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
update_level_style_classes (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_add_offset_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
* @name: the name of the new offset
|
|
|
|
|
* @value: the value for the new offset
|
|
|
|
|
*
|
|
|
|
|
* Adds a new offset marker on @self at the position specified by @value.
|
|
|
|
|
* When the bar value is in the interval topped by @value (or between @value
|
|
|
|
|
* and #GtkLevelBar:max-value in case the offset is the last one on the bar)
|
2014-02-04 23:21:13 +00:00
|
|
|
|
* a style class named `level-`@name will be applied
|
2012-05-29 21:00:33 +00:00
|
|
|
|
* when rendering the level bar fill.
|
|
|
|
|
* If another offset marker named @name exists, its value will be
|
|
|
|
|
* replaced by @value.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
gtk_level_bar_add_offset_value (GtkLevelBar *self,
|
|
|
|
|
const gchar *name,
|
|
|
|
|
gdouble value)
|
|
|
|
|
{
|
|
|
|
|
GQuark name_quark;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (GTK_IS_LEVEL_BAR (self));
|
|
|
|
|
g_return_if_fail (gtk_level_bar_value_in_interval (self, value));
|
|
|
|
|
|
|
|
|
|
if (!gtk_level_bar_ensure_offset (self, name, value))
|
|
|
|
|
return;
|
|
|
|
|
|
2015-11-13 05:55:28 +00:00
|
|
|
|
update_level_style_classes (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
name_quark = g_quark_from_string (name);
|
|
|
|
|
g_signal_emit (self, signals[SIGNAL_OFFSET_CHANGED], name_quark, name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* gtk_level_bar_get_offset_value:
|
|
|
|
|
* @self: a #GtkLevelBar
|
|
|
|
|
* @name: (allow-none): the name of an offset in the bar
|
|
|
|
|
* @value: (out): location where to store the value
|
|
|
|
|
*
|
|
|
|
|
* Fetches the value specified for the offset marker @name in @self,
|
|
|
|
|
* returning %TRUE in case an offset named @name was found.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the specified offset is found
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
gtk_level_bar_get_offset_value (GtkLevelBar *self,
|
|
|
|
|
const gchar *name,
|
|
|
|
|
gdouble *value)
|
|
|
|
|
{
|
2018-03-18 12:52:55 +00:00
|
|
|
|
GtkLevelBarPrivate *priv = gtk_level_bar_get_instance_private (self);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
GList *existing;
|
|
|
|
|
GtkLevelBarOffset *offset = NULL;
|
|
|
|
|
|
2018-07-20 15:59:35 +00:00
|
|
|
|
g_return_val_if_fail (GTK_IS_LEVEL_BAR (self), FALSE);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
|
2018-03-18 12:52:55 +00:00
|
|
|
|
existing = g_list_find_custom (priv->offsets, name, offset_find_func);
|
2012-05-29 21:00:33 +00:00
|
|
|
|
if (existing)
|
|
|
|
|
offset = existing->data;
|
|
|
|
|
|
|
|
|
|
if (!offset)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (value)
|
|
|
|
|
*value = offset->value;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|