source: trunk/third/bonobo/bonobo/bonobo-ui-sync.c @ 16754

Revision 16754, 11.0 KB checked in by ghudson, 23 years ago (diff)
Merge with bonobo 1.0.14; remove ATHTOOLROOT support.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2/*
3 * bonobo-ui-sync.h: An abstract base for Bonobo XML / widget sync sync'ing.
4 *
5 * Author:
6 *      Michael Meeks (michael@helixcode.com)
7 *
8 * Copyright 2000 Helix Code, Inc.
9 */
10
11#include <config.h>
12#include <stdlib.h>
13#include <bonobo/bonobo-ui-engine.h>
14#include <bonobo/bonobo-ui-sync.h>
15
16#define PARENT_TYPE gtk_object_get_type ()
17#define CLASS(o) BONOBO_UI_SYNC_CLASS (GTK_OBJECT (o)->klass)
18
19static void
20impl_sync_state_placeholder (BonoboUISync     *sync,
21                             BonoboUINode     *node,
22                             BonoboUINode     *cmd_node,
23                             GtkWidget        *widget,
24                             GtkWidget        *parent)
25{
26        gboolean show = FALSE;
27        char    *txt;
28               
29        if ((txt = bonobo_ui_engine_get_attr (
30                node, cmd_node, "delimit"))) {
31
32                show = !strcmp (txt, "top");
33                bonobo_ui_node_free_string (txt);
34        }
35               
36        if (show)
37                gtk_widget_show (widget);       
38        else
39                gtk_widget_hide (widget);
40}
41
42static void
43class_init (BonoboUISyncClass *sync_class)
44{
45        sync_class->sync_state_placeholder = impl_sync_state_placeholder;
46}
47
48/**
49 * bonobo_ui_sync_get_type:
50 * @void:
51 *
52 * Synchronizer type function for derivation.
53 *
54 * Return value: the GtkType index.
55 **/
56GtkType
57bonobo_ui_sync_get_type (void)
58{
59        static GtkType type = 0;
60
61        if (type == 0) {
62                static const GtkTypeInfo info = {
63                        "BonoboUISync",
64                        sizeof (BonoboUISync),
65                        sizeof (BonoboUISyncClass),
66                        (GtkClassInitFunc)  class_init,
67                        (GtkObjectInitFunc) NULL,
68                        /* reserved_1 */ NULL,
69                        /* reserved_2 */ NULL,
70                        (GtkClassInitFunc) NULL,
71                };
72
73                type = gtk_type_unique (PARENT_TYPE, &info);
74        }
75
76        return type;
77}
78
79/**
80 * bonobo_ui_sync_construct:
81 * @sync: the synchronizer
82 * @engine: the associated engine
83 * @is_recursive: whether it deals with its children recursively
84 * @has_widgets: whether it has associated widgets.
85 *
86 * Used to construct a new synchronizer object
87 *
88 * Return value: the new object.
89 **/
90BonoboUISync *
91bonobo_ui_sync_construct (BonoboUISync   *sync,
92                          BonoboUIEngine *engine,
93                          gboolean        is_recursive,
94                          gboolean        has_widgets)
95{
96        g_return_val_if_fail (BONOBO_IS_UI_SYNC (sync), NULL);
97
98        sync->engine = engine;
99        sync->is_recursive = is_recursive;
100        sync->has_widgets  = has_widgets;
101
102        return sync;
103}
104
105/**
106 * bonobo_ui_sync_is_recursive:
107 * @sync: the synchronizer
108 *
109 * Return value: whether this deals with its children recursively
110 **/
111gboolean
112bonobo_ui_sync_is_recursive (BonoboUISync *sync)
113{
114        g_return_val_if_fail (BONOBO_IS_UI_SYNC (sync), FALSE);
115
116        return sync->is_recursive;
117}
118
119/**
120 * bonobo_ui_sync_has_widgets:
121 * @sync: the synchronizer
122 *
123 * Return value: whether this deals with widgets
124 **/
125gboolean
126bonobo_ui_sync_has_widgets (BonoboUISync *sync)
127{
128        g_return_val_if_fail (BONOBO_IS_UI_SYNC (sync), FALSE);
129
130        return sync->has_widgets;
131}
132
133/**
134 * bonobo_ui_sync_state:
135 * @sync: the synchronizer
136 * @node: the node
137 * @cmd_node: the associated command node
138 * @widget: the widget
139 * @parent: the parent of @node
140 *
141 * This method is used to synchronize the state of a @node
142 * with that of a @widget, by ensuring the pertainant
143 * attributes are reflected in the widget view.
144 **/
145void
146bonobo_ui_sync_state (BonoboUISync     *sync,
147                      BonoboUINode     *node,
148                      BonoboUINode     *cmd_node,
149                      GtkWidget        *widget,
150                      GtkWidget        *parent)
151{
152        g_return_if_fail (BONOBO_IS_UI_SYNC (sync));
153
154        CLASS (sync)->sync_state (sync, node, cmd_node, widget, parent);
155}
156
157/**
158 * bonobo_ui_sync_state_placeholder:
159 * @sync: the synchronizer
160 * @node: the node
161 * @cmd_node: the associated command node
162 * @widget: the widget
163 * @parent: the parent of @node
164 *
165 * This synchronizes the state of a placeholder, there is
166 * a default implementation for this method.
167 **/
168void
169bonobo_ui_sync_state_placeholder (BonoboUISync     *sync,
170                                  BonoboUINode     *node,
171                                  BonoboUINode     *cmd_node,
172                                  GtkWidget        *widget,
173                                  GtkWidget        *parent)
174{
175        g_return_if_fail (BONOBO_IS_UI_SYNC (sync));
176
177        CLASS (sync)->sync_state_placeholder (sync, node, cmd_node, widget,
178                                              parent);
179}
180
181/**
182 * bonobo_ui_sync_build:
183 * @sync: the synchronizer
184 * @node: the node
185 * @cmd_node: the associated command node
186 * @pos: the position in the parent container to insert at
187 * @parent: the parent of @node
188 *
189 * This function causes a child widget to be build that matches
190 * @node's attributes. This should then be inserted by into
191 * @parent's associated widget at position @pos in the container.
192 *
193 * Return value: the freshly built widget.
194 **/
195GtkWidget *
196bonobo_ui_sync_build (BonoboUISync     *sync,
197                      BonoboUINode     *node,
198                      BonoboUINode     *cmd_node,
199                      int              *pos,
200                      GtkWidget        *parent)
201{
202        g_return_val_if_fail (BONOBO_IS_UI_SYNC (sync), NULL);
203
204        return CLASS (sync)->build (sync, node, cmd_node, pos, parent);
205}
206
207/**
208 * bonobo_ui_sync_build_placeholder:
209 * @sync: the synchronizer
210 * @node: the node
211 * @cmd_node: the associated command node
212 * @pos: position in the parent to insert the built widget
213 * @parent: the parent of @node
214 *
215 * As for #bonobo_ui_sync_build but for placeholders
216 *
217 * Return value: the freshly built widget.
218 **/
219GtkWidget *
220bonobo_ui_sync_build_placeholder (BonoboUISync     *sync,
221                                  BonoboUINode     *node,
222                                  BonoboUINode     *cmd_node,
223                                  int              *pos,
224                                  GtkWidget        *parent)
225{
226        g_return_val_if_fail (BONOBO_IS_UI_SYNC (sync), NULL);
227
228        return CLASS (sync)->build_placeholder (
229                sync, node, cmd_node, pos, parent);
230}
231
232/**
233 * bonobo_ui_sync_get_widgets:
234 * @sync: the synchronizer
235 * @node: the node
236 *
237 * This method is used to obtain a sensibly ordered list
238 * of child widgets of the container associated with @node.
239 * Essentialy this does something like gtk_container_children
240 * but preserving the visible order of the widgets in the list.
241 *
242 * Return value: An ordered list of child widgets of @node
243 **/
244GList *
245bonobo_ui_sync_get_widgets (BonoboUISync *sync,
246                            BonoboUINode *node)
247{
248        g_return_val_if_fail (BONOBO_IS_UI_SYNC (sync), NULL);
249
250        if (CLASS (sync)->get_widgets)
251                return CLASS (sync)->get_widgets (sync, node);
252        else
253                return NULL;
254}
255
256/**
257 * bonobo_ui_sync_state_update:
258 * @sync: the synchronizer
259 * @widget: the widget
260 * @new_state: the new state
261 *
262 * This is used to synchronize state with a stateful widget,
263 * eg. when a "state" attribute is set, this is not reflected
264 * in the normal 'state-sync' process, but occurs later with
265 * a set of state_updates to avoid re-enterancy problems.
266 **/
267void
268bonobo_ui_sync_state_update (BonoboUISync     *sync,
269                             GtkWidget        *widget,
270                             const char       *new_state)
271{
272        g_return_if_fail (BONOBO_IS_UI_SYNC (sync));
273
274        CLASS (sync)->state_update (sync, widget, new_state);
275}
276
277/**
278 * bonobo_ui_sync_remove_root:
279 * @sync: the synchronizer
280 * @root: the toplevel node to be removed.
281 *
282 * This is called when a 'root' or toplevel node is
283 * removed that this synchronizer deals with. eg. in
284 * the toolbar case, this might trigger hiding an
285 * associated dock item.
286 **/
287void
288bonobo_ui_sync_remove_root (BonoboUISync *sync,
289                            BonoboUINode *root)
290{
291        g_return_if_fail (BONOBO_IS_UI_SYNC (sync));
292
293        if (CLASS (sync)->remove_root)
294                CLASS (sync)->remove_root (sync, root);
295}
296
297/**
298 * bonobo_ui_sync_update_root:
299 * @sync: the synchronizer
300 * @root: the toplevel node
301 *
302 * This flags the fact that a toplevel node has changed
303 * and is used primarily by non-recursive handlers, such
304 * as the keybinding sync method.
305 **/
306void
307bonobo_ui_sync_update_root (BonoboUISync *sync,
308                            BonoboUINode *root)
309{
310        g_return_if_fail (BONOBO_IS_UI_SYNC (sync));
311
312        if (CLASS (sync)->update_root)
313                CLASS (sync)->update_root (sync, root);
314}
315
316/**
317 * bonobo_ui_sync_ignore_widget:
318 * @sync: the synchronizer
319 * @widget: the widget
320 *
321 * Return value: TRUE if this widget should be ignored in a container
322 * this is the case for eg. menu tearoffs items, and toolbar popout items.
323 **/
324gboolean
325bonobo_ui_sync_ignore_widget (BonoboUISync *sync,
326                              GtkWidget    *widget)
327{
328        g_return_val_if_fail (BONOBO_IS_UI_SYNC (sync), FALSE);
329
330        if (CLASS (sync)->ignore_widget)
331                return CLASS (sync)->ignore_widget (sync, widget);
332        else
333                return FALSE;
334}
335
336/**
337 * bonobo_ui_sync_stamp_root:
338 * @sync: the synchronizer
339 *
340 * This asks the synchronizer to stamp all its associated
341 * root widget containers into the XML tree.
342 **/
343void
344bonobo_ui_sync_stamp_root (BonoboUISync *sync)
345{
346        g_return_if_fail (BONOBO_IS_UI_SYNC (sync));
347
348        if (CLASS (sync)->stamp_root)
349                CLASS (sync)->stamp_root (sync);
350}
351
352/**
353 * bonobo_ui_sync_can_handle:
354 * @sync: the synchronizer
355 * @node: the node
356 *
357 * This is used to determine which, of multiple synchronizers
358 * can be used to deal with a specific node type. Each synchronizer
359 * deals with different types of node.
360 *
361 * Return value: TRUE if the synchronizer can deal with this node type
362 **/
363gboolean
364bonobo_ui_sync_can_handle (BonoboUISync *sync,
365                           BonoboUINode *node)
366{
367        if (CLASS (sync)->can_handle)
368                return CLASS (sync)->can_handle (sync, node);
369        else
370                return FALSE;
371}
372
373/**
374 * bonobo_ui_sync_get_attached:
375 * @sync: the synchronizer
376 * @widget: the widget
377 * @node: the node
378 *
379 * This is used to get an 'attached' widget - some
380 * widgets have associated widgets that are coupled
381 * in strange ways - eg. GtkMenuItem <-> GtkMenuShell
382 * It is neccessary to store the GtkContainer item of
383 * these couples in the XML tree, since then we can
384 * do things more genericaly and cleanly.
385 *
386 * Return value: an assoicated widget or NULL if none exists.
387 **/
388GtkWidget *
389bonobo_ui_sync_get_attached (BonoboUISync *sync,
390                             GtkWidget    *widget,
391                             BonoboUINode *node)
392{
393        /*
394         *   For some widgets such as menus, the submenu widget
395         * is attached to the actual container in a strange way
396         * this works around only having single inheritance.
397         */
398        g_return_val_if_fail (BONOBO_IS_UI_SYNC (sync), NULL);
399
400        if (CLASS (sync)->get_attached)
401                return CLASS (sync)->get_attached (sync, widget, node);
402        else
403                return NULL;
404}
405
406/**
407 * bonobo_ui_sync_do_show_hide:
408 * @sync: the synchronizer
409 * @node: the node
410 * @cmd_node: the associated command node
411 * @widget: the widget
412 *
413 * This is a helper function that applies the hidden attribute
414 * from either the @node or fallback to the @cmd_node to the
415 * @widget.
416 *
417 * Return value: TRUE if the widget's hidden / shown state changed,
418 * this is needed to work around some nasty dock sizing bugs.
419 **/
420gboolean
421bonobo_ui_sync_do_show_hide (BonoboUISync *sync,
422                             BonoboUINode *node,
423                             BonoboUINode *cmd_node,
424                             GtkWidget    *widget)
425{
426        char      *txt;
427        gboolean   changed;
428        GtkWidget *attached;
429
430        if (sync &&
431            (attached = bonobo_ui_sync_get_attached (
432                    sync, widget, node)))
433
434                widget = attached;
435
436        if (!widget)
437                return FALSE;
438
439        if ((txt = bonobo_ui_engine_get_attr (node, cmd_node, "hidden"))) {
440                if (atoi (txt)) {
441                        changed = GTK_WIDGET_VISIBLE (widget);
442                        gtk_widget_hide (widget);
443                } else {
444                        changed = !GTK_WIDGET_VISIBLE (widget);
445                        gtk_widget_show (widget);
446                }
447                bonobo_ui_node_free_string (txt);
448        } else {
449                changed = !GTK_WIDGET_VISIBLE (widget);
450                gtk_widget_show (widget);
451        }
452
453        return changed;
454}
Note: See TracBrowser for help on using the repository browser.