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