summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCosimo Cecchi <cosimoc@gnome.org>2016-02-28 21:13:54 -0800
committerCosimo Cecchi <cosimoc@gnome.org>2016-02-28 21:49:54 -0800
commit27fc7a1f1d3c45636a79034e3b86e95cdb589b52 (patch)
treee3f74986c6a2b45ab61841a11009b62c6b7c7d1f
parent1b15b2391b6da9639d1bc3e90ddfaa686acdc9ba (diff)
downloadgtk+-wip/cosimoc/range-gadget.tar.gz
scale: add gadgets for indicator/label in scale markswip/cosimoc/range-gadget
This will allow us to theme them indepdendently, and specify a size for the indicator from the theme.
-rw-r--r--gtk/gtkscale.c280
-rw-r--r--gtk/theme/Adwaita/_common.scss10
-rw-r--r--gtk/theme/Adwaita/gtk-contained-dark.css8
-rw-r--r--gtk/theme/Adwaita/gtk-contained.css8
4 files changed, 209 insertions, 97 deletions
diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c
index 4adc0220da..3caecb7037 100644
--- a/gtk/gtkscale.c
+++ b/gtk/gtkscale.c
@@ -140,6 +140,8 @@ struct _GtkScaleMark
int stop_position;
gchar *markup;
GtkCssGadget *gadget;
+ GtkCssGadget *indicator_gadget;
+ GtkCssGadget *label_gadget;
GtkPositionType position; /* always GTK_POS_TOP or GTK_POS_BOTTOM */
};
@@ -257,6 +259,81 @@ gtk_scale_notify (GObject *object,
G_OBJECT_CLASS (gtk_scale_parent_class)->notify (object, pspec);
}
+static void
+gtk_scale_allocate_mark (GtkCssGadget *gadget,
+ const GtkAllocation *allocation,
+ int baseline,
+ GtkAllocation *out_clip,
+ gpointer user_data)
+{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
+ GtkScaleMark *mark = user_data;
+ GtkAllocation indicator_alloc, widget_alloc;
+ int indicator_width, indicator_height;
+ GtkOrientation orientation;
+
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
+ gtk_widget_get_allocation (widget, &widget_alloc);
+ gtk_css_gadget_get_preferred_size (mark->indicator_gadget,
+ GTK_ORIENTATION_HORIZONTAL, -1,
+ &indicator_width, NULL,
+ NULL, NULL);
+ gtk_css_gadget_get_preferred_size (mark->indicator_gadget,
+ GTK_ORIENTATION_VERTICAL, -1,
+ &indicator_height, NULL,
+ NULL, NULL);
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ indicator_alloc.x = mark->stop_position + widget_alloc.x - indicator_width / 2;
+ if (mark->position == GTK_POS_TOP)
+ indicator_alloc.y = allocation->y + allocation->height - indicator_height;
+ else
+ indicator_alloc.y = allocation->y;
+ indicator_alloc.width = indicator_width;
+ indicator_alloc.height = indicator_height;
+ }
+ else
+ {
+ if (mark->position == GTK_POS_TOP)
+ indicator_alloc.x = allocation->x + allocation->width - indicator_width;
+ else
+ indicator_alloc.x = allocation->x;
+ indicator_alloc.y = mark->stop_position + widget_alloc.y - indicator_height / 2;
+ indicator_alloc.width = indicator_width;
+ indicator_alloc.height = indicator_height;
+ }
+
+ gtk_css_gadget_allocate (mark->indicator_gadget,
+ &indicator_alloc, baseline,
+ out_clip);
+
+ if (mark->label_gadget)
+ {
+ GtkAllocation label_alloc, label_clip;
+
+ label_alloc = *allocation;
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ label_alloc.height = allocation->height - indicator_alloc.height;
+ if (mark->position == GTK_POS_BOTTOM)
+ label_alloc.y = indicator_alloc.y + indicator_alloc.height;
+ }
+ else
+ {
+ label_alloc.width = allocation->width - indicator_alloc.width;
+ if (mark->position == GTK_POS_BOTTOM)
+ label_alloc.x = indicator_alloc.x + indicator_alloc.width;
+ }
+
+ gtk_css_gadget_allocate (mark->label_gadget,
+ &label_alloc, baseline,
+ &label_clip);
+ gdk_rectangle_union (out_clip, &label_clip, out_clip);
+ }
+}
+
static gint
find_next_pos (GtkWidget *widget,
GSList *list,
@@ -1255,14 +1332,14 @@ gtk_scale_screen_changed (GtkWidget *widget,
}
static void
-gtk_scale_measure_mark (GtkCssGadget *gadget,
- GtkOrientation orientation,
- gint for_size,
- gint *minimum,
- gint *natural,
- gint *minimum_baseline,
- gint *natural_baseline,
- gpointer user_data)
+gtk_scale_measure_mark_label (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline,
+ gpointer user_data)
{
GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
GtkScaleMark *mark = user_data;
@@ -1288,6 +1365,36 @@ gtk_scale_measure_mark (GtkCssGadget *gadget,
}
static void
+gtk_scale_measure_mark (GtkCssGadget *gadget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline,
+ gpointer user_data)
+{
+ GtkScaleMark *mark = user_data;
+
+ gtk_css_gadget_get_preferred_size (mark->indicator_gadget,
+ orientation, -1,
+ minimum, natural,
+ NULL, NULL);
+
+ if (mark->label_gadget)
+ {
+ int label_min, label_nat;
+
+ gtk_css_gadget_get_preferred_size (mark->label_gadget,
+ orientation, -1,
+ &label_min, &label_nat,
+ NULL, NULL);
+ *minimum += label_min;
+ *natural += label_nat;
+ }
+}
+
+static void
gtk_scale_measure_marks (GtkCssGadget *gadget,
GtkOrientation orientation,
gint for_size,
@@ -1397,100 +1504,57 @@ gtk_scale_get_preferred_height (GtkWidget *widget,
}
static gboolean
-gtk_scale_render_mark (GtkCssGadget *gadget,
- cairo_t *cr,
- int x,
- int y,
- int width,
- int height,
- gpointer user_data)
+gtk_scale_render_mark_indicator (GtkCssGadget *gadget,
+ cairo_t *cr,
+ int x,
+ int y,
+ int width,
+ int height,
+ gpointer user_data)
{
GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
- GtkScale *scale = GTK_SCALE (widget);
- GtkScaleMark *mark = user_data;
- GtkOrientation orientation;
- GtkAllocation slider_alloc;
- GtkCssGadget *slider_gadget;
GtkStyleContext *context;
- PangoLayout *layout;
-
- slider_gadget = gtk_range_get_slider_gadget (GTK_RANGE (scale));
- gtk_css_gadget_get_content_allocation (slider_gadget,
- &slider_alloc, NULL);
-
- orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (scale));
+ GtkOrientation orientation;
+ orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (widget));
context = gtk_widget_get_style_context (widget);
gtk_style_context_save_to_node (context, gtk_css_gadget_get_node (gadget));
- layout = gtk_widget_create_pango_layout (widget, NULL);
-
if (orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- int y1, y2;
-
- if (mark->position == GTK_POS_TOP)
- {
- y1 = y + height;
- y2 = y + height - slider_alloc.height / 4;
- }
- else
- {
- y1 = y;
- y2 = y + slider_alloc.height / 4;
- }
-
- gtk_render_line (context, cr,
- mark->stop_position, y1,
- mark->stop_position, y2);
-
- if (mark->markup)
- {
- int y3;
-
- pango_layout_set_markup (layout, mark->markup, -1);
-
- if (mark->position == GTK_POS_TOP)
- y3 = y;
- else
- y3 = y2;
-
- gtk_render_layout (context, cr, x, y3, layout);
- }
- }
+ gtk_render_line (context, cr,
+ x + width / 2, y,
+ x + width / 2, y + height);
else
- {
- int x1, x2;
+ gtk_render_line (context, cr,
+ x, y + height / 2,
+ x + width, y + height / 2);
- if (mark->position == GTK_POS_TOP)
- {
- x1 = x + width;
- x2 = x + width - slider_alloc.width / 4;
- }
- else
- {
- x1 = x;
- x2 = x + slider_alloc.width / 4;
- }
+ gtk_style_context_restore (context);
- gtk_render_line (context, cr,
- x1, mark->stop_position,
- x2, mark->stop_position);
+ return FALSE;
+}
- if (mark->markup)
- {
- int x3;
+static gboolean
+gtk_scale_render_mark_label (GtkCssGadget *gadget,
+ cairo_t *cr,
+ int x,
+ int y,
+ int width,
+ int height,
+ gpointer user_data)
+{
+ GtkWidget *widget = gtk_css_gadget_get_owner (gadget);
+ GtkScaleMark *mark = user_data;
+ GtkStyleContext *context;
+ PangoLayout *layout;
- pango_layout_set_markup (layout, mark->markup, -1);
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_save_to_node (context, gtk_css_gadget_get_node (gadget));
- if (mark->position == GTK_POS_TOP)
- x3 = x;
- else
- x3 = x2;
+ layout = gtk_widget_create_pango_layout (widget, NULL);
+ pango_layout_set_markup (layout, mark->markup, -1);
- gtk_render_layout (context, cr, x3, y, layout);
- }
- }
+ gtk_render_layout (context, cr, x, y, layout);
gtk_style_context_restore (context);
g_object_unref (layout);
@@ -1499,6 +1563,24 @@ gtk_scale_render_mark (GtkCssGadget *gadget,
}
static gboolean
+gtk_scale_render_mark (GtkCssGadget *gadget,
+ cairo_t *cr,
+ int x,
+ int y,
+ int width,
+ int height,
+ gpointer user_data)
+{
+ GtkScaleMark *mark = user_data;
+
+ gtk_css_gadget_draw (mark->indicator_gadget, cr);
+ if (mark->label_gadget)
+ gtk_css_gadget_draw (mark->label_gadget, cr);
+
+ return FALSE;
+}
+
+static gboolean
gtk_scale_render_marks (GtkCssGadget *gadget,
cairo_t *cr,
int x,
@@ -1778,6 +1860,8 @@ gtk_scale_mark_free (gpointer data)
{
GtkScaleMark *mark = data;
+ g_clear_object (&mark->label_gadget);
+ g_object_unref (mark->indicator_gadget);
g_object_unref (mark->gadget);
g_free (mark->markup);
g_free (mark);
@@ -1853,7 +1937,7 @@ gtk_scale_add_mark (GtkScale *scale,
priv = scale->priv;
widget_node = gtk_widget_get_css_node (GTK_WIDGET (scale));
- mark = g_new (GtkScaleMark, 1);
+ mark = g_new0 (GtkScaleMark, 1);
mark->value = value;
mark->markup = g_strdup (markup);
if (position == GTK_POS_LEFT ||
@@ -1905,11 +1989,29 @@ gtk_scale_add_mark (GtkScale *scale,
gtk_css_custom_gadget_new ("mark",
GTK_WIDGET (scale), NULL, NULL,
gtk_scale_measure_mark,
- NULL,
+ gtk_scale_allocate_mark,
gtk_scale_render_mark,
mark, NULL);
gtk_css_gadget_set_state (mark->gadget, gtk_css_node_get_state (marks_node));
+ mark->indicator_gadget =
+ gtk_css_custom_gadget_new ("indicator",
+ GTK_WIDGET (scale), mark->gadget, NULL,
+ NULL,
+ NULL,
+ gtk_scale_render_mark_indicator,
+ mark, NULL);
+ if (mark->markup)
+ mark->label_gadget =
+ gtk_css_custom_gadget_new ("label",
+ GTK_WIDGET (scale), mark->gadget,
+ mark->position == GTK_POS_TOP ?
+ NULL : mark->indicator_gadget,
+ gtk_scale_measure_mark_label,
+ NULL,
+ gtk_scale_render_mark_label,
+ mark, NULL);
+
m = g_slist_find (priv->marks, mark);
m = m->next;
while (m)
diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss
index 5adbd2a1c1..2a0608739d 100644
--- a/gtk/theme/Adwaita/_common.scss
+++ b/gtk/theme/Adwaita/_common.scss
@@ -2578,8 +2578,14 @@ scale {
}
marks { color: gtkalpha(currentColor, 0.4); }
- &.horizontal marks { min-height: 8px; }
- &.vertical marks { min-width: 8px; }
+ &.horizontal mark indicator {
+ min-height: 8px;
+ min-width: 1px;
+ }
+ &.vertical mark indicator {
+ min-height: 1px;
+ min-width: 8px;
+ }
// *WARNING* scale with marks madness following
diff --git a/gtk/theme/Adwaita/gtk-contained-dark.css b/gtk/theme/Adwaita/gtk-contained-dark.css
index f56f6b50ee..5025b1704c 100644
--- a/gtk/theme/Adwaita/gtk-contained-dark.css
+++ b/gtk/theme/Adwaita/gtk-contained-dark.css
@@ -2757,9 +2757,11 @@ scale {
-gtk-icon-shadow: none; }
scale marks {
color: alpha(currentColor,0.4); }
- scale.horizontal marks {
- min-height: 8px; }
- scale.vertical marks {
+ scale.horizontal mark indicator {
+ min-height: 8px;
+ min-width: 1px; }
+ scale.vertical mark indicator {
+ min-height: 1px;
min-width: 8px; }
scale.color.horizontal trough > trough > slider, scale.horizontal contents:last-child:not(:only-child) > trough > slider {
margin: -9px;
diff --git a/gtk/theme/Adwaita/gtk-contained.css b/gtk/theme/Adwaita/gtk-contained.css
index 3662aff95c..e35f5be8d7 100644
--- a/gtk/theme/Adwaita/gtk-contained.css
+++ b/gtk/theme/Adwaita/gtk-contained.css
@@ -2788,9 +2788,11 @@ scale {
-gtk-icon-shadow: none; }
scale marks {
color: alpha(currentColor,0.4); }
- scale.horizontal marks {
- min-height: 8px; }
- scale.vertical marks {
+ scale.horizontal mark indicator {
+ min-height: 8px;
+ min-width: 1px; }
+ scale.vertical mark indicator {
+ min-height: 1px;
min-width: 8px; }
scale.color.horizontal trough > trough > slider, scale.horizontal contents:last-child:not(:only-child) > trough > slider {
margin: -9px;