1 | /* gtkscrollable.c |
2 | * Copyright (C) 2008 Tadej Borovšak <tadeboro@gmail.com> |
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 | * GtkScrollable: |
20 | * |
21 | * `GtkScrollable` is an interface for widgets with native scrolling ability. |
22 | * |
23 | * To implement this interface you should override the |
24 | * [property@Gtk.Scrollable:hadjustment] and |
25 | * [property@Gtk.Scrollable:vadjustment] properties. |
26 | * |
27 | * ## Creating a scrollable widget |
28 | * |
29 | * All scrollable widgets should do the following. |
30 | * |
31 | * - When a parent widget sets the scrollable child widget’s adjustments, |
32 | * the widget should connect to the [signal@Gtk.Adjustment::value-changed] |
33 | * signal. The child widget should then populate the adjustments’ properties |
34 | * as soon as possible, which usually means queueing an allocation right away |
35 | * and populating the properties in the [vfunc@Gtk.Widget.size_allocate] |
36 | * implementation. |
37 | * |
38 | * - Because its preferred size is the size for a fully expanded widget, |
39 | * the scrollable widget must be able to cope with underallocations. |
40 | * This means that it must accept any value passed to its |
41 | * [vfunc@Gtk.Widget.size_allocate] implementation. |
42 | * |
43 | * - When the parent allocates space to the scrollable child widget, |
44 | * the widget must ensure the adjustments’ property values are correct and up |
45 | * to date, for example using [method@Gtk.Adjustment.configure]. |
46 | * |
47 | * - When any of the adjustments emits the [signal@Gtk.Adjustment::value-changed] |
48 | * signal, the scrollable widget should scroll its contents. |
49 | */ |
50 | |
51 | #include "config.h" |
52 | |
53 | #include "gtkscrollable.h" |
54 | |
55 | #include "gtkadjustment.h" |
56 | #include "gtkprivate.h" |
57 | #include "gtktypebuiltins.h" |
58 | #include "gtkintl.h" |
59 | |
60 | G_DEFINE_INTERFACE (GtkScrollable, gtk_scrollable, G_TYPE_OBJECT) |
61 | |
62 | static void |
63 | gtk_scrollable_default_init (GtkScrollableInterface *iface) |
64 | { |
65 | GParamSpec *pspec; |
66 | |
67 | /** |
68 | * GtkScrollable:hadjustment: (attributes org.gtk.Property.get=gtk_scrollable_get_hadjustment org.gtk.Property.set=gtk_scrollable_set_hadjustment) |
69 | * |
70 | * Horizontal `GtkAdjustment` of the scrollable widget. |
71 | * |
72 | * This adjustment is shared between the scrollable widget and its parent. |
73 | */ |
74 | pspec = g_param_spec_object (name: "hadjustment" , |
75 | P_("Horizontal adjustment" ), |
76 | P_("Horizontal adjustment that is shared " |
77 | "between the scrollable widget and its " |
78 | "controller" ), |
79 | GTK_TYPE_ADJUSTMENT, |
80 | GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT); |
81 | g_object_interface_install_property (g_iface: iface, pspec); |
82 | |
83 | /** |
84 | * GtkScrollable:vadjustment: (attributes org.gtk.Property.get=gtk_scrollable_get_vadjustment org.gtk.Property.set=gtk_scrollable_set_vadjustment) |
85 | * |
86 | * Vertical `GtkAdjustment` of the scrollable widget. |
87 | * |
88 | * This adjustment is shared between the scrollable widget and its parent. |
89 | */ |
90 | pspec = g_param_spec_object (name: "vadjustment" , |
91 | P_("Vertical adjustment" ), |
92 | P_("Vertical adjustment that is shared " |
93 | "between the scrollable widget and its " |
94 | "controller" ), |
95 | GTK_TYPE_ADJUSTMENT, |
96 | GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT); |
97 | g_object_interface_install_property (g_iface: iface, pspec); |
98 | |
99 | /** |
100 | * GtkScrollable:hscroll-policy: (attributes org.gtk.Property.get=gtk_scrollable_get_hscroll_policy org.gtk.Property.set=gtk_scrollable_set_hscroll_policy) |
101 | * |
102 | * Determines when horizontal scrolling should start. |
103 | */ |
104 | pspec = g_param_spec_enum (name: "hscroll-policy" , |
105 | P_("Horizontal Scrollable Policy" ), |
106 | P_("How the size of the content should be determined" ), |
107 | enum_type: GTK_TYPE_SCROLLABLE_POLICY, |
108 | default_value: GTK_SCROLL_MINIMUM, |
109 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); |
110 | g_object_interface_install_property (g_iface: iface, pspec); |
111 | |
112 | /** |
113 | * GtkScrollable:vscroll-policy: (attributes org.gtk.Property.get=gtk_scrollable_get_vscroll_policy org.gtk.Property.set=gtk_scrollable_set_vscroll_policy) |
114 | * |
115 | * Determines when vertical scrolling should start. |
116 | */ |
117 | pspec = g_param_spec_enum (name: "vscroll-policy" , |
118 | P_("Vertical Scrollable Policy" ), |
119 | P_("How the size of the content should be determined" ), |
120 | enum_type: GTK_TYPE_SCROLLABLE_POLICY, |
121 | default_value: GTK_SCROLL_MINIMUM, |
122 | GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); |
123 | g_object_interface_install_property (g_iface: iface, pspec); |
124 | } |
125 | |
126 | /** |
127 | * gtk_scrollable_get_hadjustment: (attributes org.gtk.Method.get_property=hadjustment) |
128 | * @scrollable: a `GtkScrollable` |
129 | * |
130 | * Retrieves the `GtkAdjustment` used for horizontal scrolling. |
131 | * |
132 | * Returns: (transfer none) (nullable): horizontal `GtkAdjustment`. |
133 | */ |
134 | GtkAdjustment * |
135 | gtk_scrollable_get_hadjustment (GtkScrollable *scrollable) |
136 | { |
137 | GtkAdjustment *adj = NULL; |
138 | |
139 | g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), NULL); |
140 | |
141 | g_object_get (object: scrollable, first_property_name: "hadjustment" , &adj, NULL); |
142 | |
143 | /* Horrid hack; g_object_get() returns a new reference but |
144 | * that contradicts the memory management conventions |
145 | * for accessors. |
146 | */ |
147 | if (adj) |
148 | g_object_unref (object: adj); |
149 | |
150 | return adj; |
151 | } |
152 | |
153 | /** |
154 | * gtk_scrollable_set_hadjustment: (attributes org.gtk.Method.set_property=hadjustment) |
155 | * @scrollable: a `GtkScrollable` |
156 | * @hadjustment: (nullable): a `GtkAdjustment` |
157 | * |
158 | * Sets the horizontal adjustment of the `GtkScrollable`. |
159 | */ |
160 | void |
161 | gtk_scrollable_set_hadjustment (GtkScrollable *scrollable, |
162 | GtkAdjustment *hadjustment) |
163 | { |
164 | g_return_if_fail (GTK_IS_SCROLLABLE (scrollable)); |
165 | g_return_if_fail (hadjustment == NULL || GTK_IS_ADJUSTMENT (hadjustment)); |
166 | |
167 | g_object_set (object: scrollable, first_property_name: "hadjustment" , hadjustment, NULL); |
168 | } |
169 | |
170 | /** |
171 | * gtk_scrollable_get_vadjustment: (attributes org.gtk.Method.get_property=vadjustment) |
172 | * @scrollable: a `GtkScrollable` |
173 | * |
174 | * Retrieves the `GtkAdjustment` used for vertical scrolling. |
175 | * |
176 | * Returns: (transfer none) (nullable): vertical `GtkAdjustment`. |
177 | */ |
178 | GtkAdjustment * |
179 | gtk_scrollable_get_vadjustment (GtkScrollable *scrollable) |
180 | { |
181 | GtkAdjustment *adj = NULL; |
182 | |
183 | g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), NULL); |
184 | |
185 | g_object_get (object: scrollable, first_property_name: "vadjustment" , &adj, NULL); |
186 | |
187 | /* Horrid hack; g_object_get() returns a new reference but |
188 | * that contradicts the memory management conventions |
189 | * for accessors. |
190 | */ |
191 | if (adj) |
192 | g_object_unref (object: adj); |
193 | |
194 | return adj; |
195 | } |
196 | |
197 | /** |
198 | * gtk_scrollable_set_vadjustment: (attributes org.gtk.Method.set_property=vadjustment) |
199 | * @scrollable: a `GtkScrollable` |
200 | * @vadjustment: (nullable): a `GtkAdjustment` |
201 | * |
202 | * Sets the vertical adjustment of the `GtkScrollable`. |
203 | */ |
204 | void |
205 | gtk_scrollable_set_vadjustment (GtkScrollable *scrollable, |
206 | GtkAdjustment *vadjustment) |
207 | { |
208 | g_return_if_fail (GTK_IS_SCROLLABLE (scrollable)); |
209 | g_return_if_fail (vadjustment == NULL || GTK_IS_ADJUSTMENT (vadjustment)); |
210 | |
211 | g_object_set (object: scrollable, first_property_name: "vadjustment" , vadjustment, NULL); |
212 | } |
213 | |
214 | |
215 | /** |
216 | * gtk_scrollable_get_hscroll_policy: (attributes org.gtk.Method.get_property=hscroll-policy) |
217 | * @scrollable: a `GtkScrollable` |
218 | * |
219 | * Gets the horizontal `GtkScrollablePolicy`. |
220 | * |
221 | * Returns: The horizontal `GtkScrollablePolicy`. |
222 | */ |
223 | GtkScrollablePolicy |
224 | gtk_scrollable_get_hscroll_policy (GtkScrollable *scrollable) |
225 | { |
226 | GtkScrollablePolicy policy; |
227 | |
228 | g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), GTK_SCROLL_MINIMUM); |
229 | |
230 | g_object_get (object: scrollable, first_property_name: "hscroll-policy" , &policy, NULL); |
231 | |
232 | return policy; |
233 | } |
234 | |
235 | /** |
236 | * gtk_scrollable_set_hscroll_policy: (attributes org.gtk.Method.set_property=hscroll-policy) |
237 | * @scrollable: a `GtkScrollable` |
238 | * @policy: the horizontal `GtkScrollablePolicy` |
239 | * |
240 | * Sets the `GtkScrollablePolicy`. |
241 | * |
242 | * The policy determines whether horizontal scrolling should start |
243 | * below the minimum width or below the natural width. |
244 | */ |
245 | void |
246 | gtk_scrollable_set_hscroll_policy (GtkScrollable *scrollable, |
247 | GtkScrollablePolicy policy) |
248 | { |
249 | g_return_if_fail (GTK_IS_SCROLLABLE (scrollable)); |
250 | |
251 | g_object_set (object: scrollable, first_property_name: "hscroll-policy" , policy, NULL); |
252 | } |
253 | |
254 | /** |
255 | * gtk_scrollable_get_vscroll_policy: (attributes org.gtk.Method.get_property=vscroll-policy) |
256 | * @scrollable: a `GtkScrollable` |
257 | * |
258 | * Gets the vertical `GtkScrollablePolicy`. |
259 | * |
260 | * Returns: The vertical `GtkScrollablePolicy`. |
261 | */ |
262 | GtkScrollablePolicy |
263 | gtk_scrollable_get_vscroll_policy (GtkScrollable *scrollable) |
264 | { |
265 | GtkScrollablePolicy policy; |
266 | |
267 | g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), GTK_SCROLL_MINIMUM); |
268 | |
269 | g_object_get (object: scrollable, first_property_name: "vscroll-policy" , &policy, NULL); |
270 | |
271 | return policy; |
272 | } |
273 | |
274 | /** |
275 | * gtk_scrollable_set_vscroll_policy: (attributes org.gtk.Method.set_property=vscroll-policy) |
276 | * @scrollable: a `GtkScrollable` |
277 | * @policy: the vertical `GtkScrollablePolicy` |
278 | * |
279 | * Sets the `GtkScrollablePolicy`. |
280 | * |
281 | * The policy determines whether vertical scrolling should start |
282 | * below the minimum height or below the natural height. |
283 | */ |
284 | void |
285 | gtk_scrollable_set_vscroll_policy (GtkScrollable *scrollable, |
286 | GtkScrollablePolicy policy) |
287 | { |
288 | g_return_if_fail (GTK_IS_SCROLLABLE (scrollable)); |
289 | |
290 | g_object_set (object: scrollable, first_property_name: "vscroll-policy" , policy, NULL); |
291 | } |
292 | |
293 | /** |
294 | * gtk_scrollable_get_border: |
295 | * @scrollable: a `GtkScrollable` |
296 | * @border: (out caller-allocates): return location for the results |
297 | * |
298 | * Returns the size of a non-scrolling border around the |
299 | * outside of the scrollable. |
300 | * |
301 | * An example for this would be treeview headers. GTK can use |
302 | * this information to display overlaid graphics, like the |
303 | * overshoot indication, at the right position. |
304 | * |
305 | * Returns: %TRUE if @border has been set |
306 | */ |
307 | gboolean |
308 | gtk_scrollable_get_border (GtkScrollable *scrollable, |
309 | GtkBorder *border) |
310 | { |
311 | g_return_val_if_fail (GTK_IS_SCROLLABLE (scrollable), FALSE); |
312 | g_return_val_if_fail (border != NULL, FALSE); |
313 | |
314 | if (GTK_SCROLLABLE_GET_IFACE (scrollable)->get_border) |
315 | return GTK_SCROLLABLE_GET_IFACE (scrollable)->get_border (scrollable, border); |
316 | |
317 | return FALSE; |
318 | } |
319 | |