1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 */
24
25 #include "config.h"
26
27 #include "gtkseparator.h"
28
29 #include "gtkorientableprivate.h"
30 #include "gtkintl.h"
31 #include "gtkprivate.h"
32 #include "gtkrender.h"
33 #include "gtkwidgetprivate.h"
34 #include "gtkcsscustomgadgetprivate.h"
35
36 /**
37 * SECTION:gtkseparator
38 * @Short_description: A separator widget
39 * @Title: GtkSeparator
40 *
41 * GtkSeparator is a horizontal or vertical separator widget, depending on the
42 * value of the #GtkOrientable:orientation property, used to group the widgets
43 * within a window. It displays a line with a shadow to make it appear sunken
44 * into the interface.
45 *
46 * # CSS nodes
47 *
48 * GtkSeparator has a single CSS node with name separator. The node
49 * gets one of the .horizontal or .vertical style classes.
50 */
51
52
53 struct _GtkSeparatorPrivate
54 {
55 GtkOrientation orientation;
56 GtkCssGadget *gadget;
57 };
58
59
60 enum {
61 PROP_0,
62 PROP_ORIENTATION
63 };
64
65
G_DEFINE_TYPE_WITH_CODE(GtkSeparator,gtk_separator,GTK_TYPE_WIDGET,G_ADD_PRIVATE (GtkSeparator)G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE,NULL))66 G_DEFINE_TYPE_WITH_CODE (GtkSeparator, gtk_separator, GTK_TYPE_WIDGET,
67 G_ADD_PRIVATE (GtkSeparator)
68 G_IMPLEMENT_INTERFACE (GTK_TYPE_ORIENTABLE, NULL))
69
70
71 static void
72 gtk_separator_set_property (GObject *object,
73 guint prop_id,
74 const GValue *value,
75 GParamSpec *pspec)
76 {
77 GtkSeparator *separator = GTK_SEPARATOR (object);
78 GtkSeparatorPrivate *private = separator->priv;
79
80 switch (prop_id)
81 {
82 case PROP_ORIENTATION:
83 if (private->orientation != g_value_get_enum (value))
84 {
85 private->orientation = g_value_get_enum (value);
86 _gtk_orientable_set_style_classes (GTK_ORIENTABLE (object));
87 gtk_widget_queue_resize (GTK_WIDGET (object));
88 g_object_notify_by_pspec (object, pspec);
89 }
90 break;
91 default:
92 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
93 break;
94 }
95 }
96
97 static void
gtk_separator_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)98 gtk_separator_get_property (GObject *object,
99 guint prop_id,
100 GValue *value,
101 GParamSpec *pspec)
102 {
103 GtkSeparator *separator = GTK_SEPARATOR (object);
104 GtkSeparatorPrivate *private = separator->priv;
105
106 switch (prop_id)
107 {
108 case PROP_ORIENTATION:
109 g_value_set_enum (value, private->orientation);
110 break;
111 default:
112 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
113 break;
114 }
115 }
116
117 static void
gtk_separator_get_preferred_width(GtkWidget * widget,gint * minimum,gint * natural)118 gtk_separator_get_preferred_width (GtkWidget *widget,
119 gint *minimum,
120 gint *natural)
121 {
122 gtk_css_gadget_get_preferred_size (GTK_SEPARATOR (widget)->priv->gadget,
123 GTK_ORIENTATION_HORIZONTAL,
124 -1,
125 minimum, natural,
126 NULL, NULL);
127 }
128
129 static void
gtk_separator_get_preferred_height(GtkWidget * widget,gint * minimum,gint * natural)130 gtk_separator_get_preferred_height (GtkWidget *widget,
131 gint *minimum,
132 gint *natural)
133 {
134 gtk_css_gadget_get_preferred_size (GTK_SEPARATOR (widget)->priv->gadget,
135 GTK_ORIENTATION_VERTICAL,
136 -1,
137 minimum, natural,
138 NULL, NULL);
139 }
140
141 static void
gtk_separator_size_allocate(GtkWidget * widget,GtkAllocation * allocation)142 gtk_separator_size_allocate (GtkWidget *widget,
143 GtkAllocation *allocation)
144 {
145 GtkAllocation clip;
146
147 gtk_widget_set_allocation (widget, allocation);
148
149 gtk_css_gadget_allocate (GTK_SEPARATOR (widget)->priv->gadget,
150 allocation,
151 gtk_widget_get_allocated_baseline (widget),
152 &clip);
153
154 gtk_widget_set_clip (widget, &clip);
155 }
156
157 static gboolean
gtk_separator_draw(GtkWidget * widget,cairo_t * cr)158 gtk_separator_draw (GtkWidget *widget,
159 cairo_t *cr)
160 {
161 gtk_css_gadget_draw (GTK_SEPARATOR (widget)->priv->gadget, cr);
162
163 return FALSE;
164 }
165
166 static void
gtk_separator_init(GtkSeparator * separator)167 gtk_separator_init (GtkSeparator *separator)
168 {
169 GtkCssNode *widget_node;
170
171 separator->priv = gtk_separator_get_instance_private (separator);
172 separator->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
173
174 gtk_widget_set_has_window (GTK_WIDGET (separator), FALSE);
175
176 _gtk_orientable_set_style_classes (GTK_ORIENTABLE (separator));
177
178 widget_node = gtk_widget_get_css_node (GTK_WIDGET (separator));
179 separator->priv->gadget = gtk_css_custom_gadget_new_for_node (widget_node,
180 GTK_WIDGET (separator),
181 NULL, NULL, NULL,
182 NULL, NULL);
183 }
184
185 static void
gtk_separator_finalize(GObject * object)186 gtk_separator_finalize (GObject *object)
187 {
188 GtkSeparatorPrivate *priv = GTK_SEPARATOR (object)->priv;
189
190 g_clear_object (&priv->gadget);
191
192
193 G_OBJECT_CLASS (gtk_separator_parent_class)->finalize (object);
194 }
195
196 static void
gtk_separator_class_init(GtkSeparatorClass * class)197 gtk_separator_class_init (GtkSeparatorClass *class)
198 {
199 GObjectClass *object_class = G_OBJECT_CLASS (class);
200 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
201
202 object_class->set_property = gtk_separator_set_property;
203 object_class->get_property = gtk_separator_get_property;
204 object_class->finalize = gtk_separator_finalize;
205
206 widget_class->get_preferred_width = gtk_separator_get_preferred_width;
207 widget_class->get_preferred_height = gtk_separator_get_preferred_height;
208 widget_class->size_allocate = gtk_separator_size_allocate;
209
210 widget_class->draw = gtk_separator_draw;
211
212 g_object_class_override_property (object_class, PROP_ORIENTATION, "orientation");
213
214 gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_SEPARATOR);
215 gtk_widget_class_set_css_name (widget_class, "separator");
216 }
217
218 /**
219 * gtk_separator_new:
220 * @orientation: the separator’s orientation.
221 *
222 * Creates a new #GtkSeparator with the given orientation.
223 *
224 * Returns: a new #GtkSeparator.
225 *
226 * Since: 3.0
227 */
228 GtkWidget *
gtk_separator_new(GtkOrientation orientation)229 gtk_separator_new (GtkOrientation orientation)
230 {
231 return g_object_new (GTK_TYPE_SEPARATOR,
232 "orientation", orientation,
233 NULL);
234 }
235