source: trunk/third/bonobo/bonobo/bonobo-control.c @ 16750

Revision 16750, 25.6 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r16749, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * Bonobo control object
4 *
5 * Author:
6 *   Nat Friedman      (nat@helixcode.com)
7 *   Miguel de Icaza   (miguel@helixcode.com)
8 *   Maciej Stachowiak (mjs@eazel.com)
9 *
10 * Copyright 1999, 2000 Helix Code, Inc.
11 *                 2000 Eazel, Inc.
12 */
13#include <config.h>
14#include <stdlib.h>
15#include <gtk/gtksignal.h>
16#include <gtk/gtkmarshal.h>
17#include <bonobo/bonobo-main.h>
18#include <bonobo/bonobo-plug.h>
19#include <bonobo/bonobo-control.h>
20#include <bonobo/bonobo-exception.h>
21#include <gdk/gdkprivate.h>
22#include <gtk/gtkbox.h>
23#include <gtk/gtkmain.h>
24
25#define PARENT_TYPE BONOBO_X_OBJECT_TYPE
26
27enum {
28        SET_FRAME,
29        ACTIVATE,
30        LAST_SIGNAL
31};
32
33static guint control_signals [LAST_SIGNAL];
34
35/* Parent object class in GTK hierarchy */
36static BonoboObjectClass *bonobo_control_parent_class;
37
38struct _BonoboControlPrivate {
39        GtkWidget                  *widget;
40        Bonobo_ControlFrame         control_frame;
41        gboolean                    active;
42
43        GtkWidget                  *plug;
44        GtkWidget                  *socket;
45        gboolean                    is_local;
46        gboolean                    xid_received;
47        guint                       destroy_idle_id;
48                       
49        BonoboUIComponent          *ui_component;
50        gboolean                    automerge;
51                                   
52        BonoboPropertyBag          *propbag;
53};
54
55/**
56 * window_id_demangle:
57 * @id: CORBA_char *
58 *
59 * De-mangle a window id string,
60 * fields are separated by ':' character,
61 * currently only the first field is used.
62 *
63 * Return value: the X11 window id.
64 **/
65inline static guint32
66window_id_demangle (Bonobo_Control_windowId id)
67{
68        guint32 x11_id;
69        char **elements;
70       
71/*      printf ("ID string '%s'\n", id);*/
72
73        elements = g_strsplit (id, ":", -1);
74        if (elements && elements [0])
75                x11_id = strtol (elements [0], NULL, 10);
76        else {
77                g_warning ("Serious X id mangling error");
78                x11_id = 0;
79        }
80        g_strfreev (elements);
81
82/*      printf ("x11 : %d\n", x11_id);*/
83
84        return x11_id;
85}
86
87/**
88 * bonobo_control_windowid_from_x11:
89 * @x11_id: the x11 window id.
90 *
91 * This mangles the X11 name into the ':' delimited
92 * string format "X-id: ..."
93 *
94 * Return value: the string; free after use.
95 **/
96Bonobo_Control_windowId
97bonobo_control_windowid_from_x11 (guint32 x11_id)
98{
99        CORBA_char *str;
100
101        str = g_strdup_printf ("%d", x11_id);
102
103/*      printf ("Mangled %d to '%s'\n", x11_id, str);*/
104        return str;
105}
106
107/*
108 * This callback is invoked when the plug is unexpectedly destroyed by
109 * way of its associated X window dying.  This usually indicates that
110 * the container application has died.  This callback is _not_ invoked
111 * if the BonoboControl is destroyed normally, i.e. the user unrefs
112 * the BonoboControl away.
113 */
114static gboolean
115bonobo_control_plug_destroy_event_cb (GtkWidget   *plug,
116                                      GdkEventAny *event,
117                                      gpointer     closure)
118{
119        BonoboControl *control = BONOBO_CONTROL (closure);
120
121        if (control->priv->plug == NULL)
122                return FALSE;
123
124        if (control->priv->plug != plug)
125                g_warning ("Destroying incorrect plug!");
126
127        /*
128         * Set the plug to NULL here so that we don't try to
129         * destroy it later.  It will get destroyed on its
130         * own.
131         */
132        control->priv->plug            = NULL;
133
134        /*
135         * Destroy this plug's BonoboControl.
136         */
137        bonobo_object_unref (BONOBO_OBJECT (control));
138
139        return FALSE;
140}
141
142/*
143 * This callback is invoked when the plug is unexpectedly destroyed
144 * through normal Gtk channels. FIXME FIXME FIXME
145 *
146 */
147static void
148bonobo_control_plug_destroy_cb (GtkWidget *plug,
149                                gpointer   closure)
150{
151        BonoboControl *control = BONOBO_CONTROL (closure);
152
153        if (control->priv->plug == NULL)
154                return;
155
156        if (control->priv->plug != plug)
157                g_warning ("Destroying incorrect plug!");
158
159        /*
160         * Set the plug to NULL here so that we don't try to
161         * destroy it later.  It will get destroyed on its
162         * own.
163         */
164        control->priv->plug = NULL;
165}
166
167
168static void
169bonobo_control_auto_merge (BonoboControl *control)
170{
171        Bonobo_UIContainer remote_container;
172
173        if (control->priv->ui_component == NULL)
174                return;
175
176        remote_container = bonobo_control_get_remote_ui_container (control);
177        if (remote_container == CORBA_OBJECT_NIL)
178                return;
179
180        bonobo_ui_component_set_container (
181                control->priv->ui_component, remote_container);
182
183        bonobo_object_release_unref (remote_container, NULL);
184}
185
186
187static void
188bonobo_control_auto_unmerge (BonoboControl *control)
189{
190        if (control->priv->ui_component == NULL)
191                return;
192       
193        bonobo_ui_component_unset_container (control->priv->ui_component);
194}
195
196static void
197impl_Bonobo_Control_activate (PortableServer_Servant servant,
198                              CORBA_boolean activated,
199                              CORBA_Environment *ev)
200{
201        BonoboControl *control = BONOBO_CONTROL (bonobo_object_from_servant (servant));
202
203        if (control->priv->automerge && control->priv->active != activated) {
204                if (activated)
205                        bonobo_control_auto_merge (control);
206                else
207                        bonobo_control_auto_unmerge (control);
208        }
209
210        if (control->priv->active != activated)
211                gtk_signal_emit (GTK_OBJECT (control), control_signals [ACTIVATE], (gboolean) activated);
212
213        control->priv->active = activated;
214}
215
216       
217static void
218impl_Bonobo_Control_setFrame (PortableServer_Servant servant,
219                               Bonobo_ControlFrame frame,
220                               CORBA_Environment *ev)
221{
222        BonoboControl *control = BONOBO_CONTROL (bonobo_object_from_servant (servant));
223
224        bonobo_control_set_control_frame (control, frame);
225}
226
227
228static GtkWidget *
229bonobo_gtk_widget_from_x11_id (guint32 xid)
230{
231        GdkWindow *window;
232        gpointer data;
233
234        window = gdk_window_lookup (xid);
235       
236        if (!window)
237                return NULL;
238
239        gdk_window_get_user_data(window, &data);
240
241        if (!GTK_IS_WIDGET (data))
242                return NULL;
243        else
244                return GTK_WIDGET (data);
245}
246
247static gint
248idle_destroy_socket (gpointer data)
249{
250        BonoboControl *control = BONOBO_CONTROL (data);
251
252        g_return_val_if_fail (control != NULL, FALSE);
253
254        control->priv->destroy_idle_id = 0;
255
256        gtk_widget_destroy (control->priv->socket);
257
258        return FALSE;
259}
260
261
262static void
263remove_destroy_idle (GtkWidget *socket,
264                     BonoboControl *control)
265{
266        if (control->priv->destroy_idle_id != 0)
267                gtk_idle_remove (control->priv->destroy_idle_id);
268
269        control->priv->destroy_idle_id = 0;
270}
271
272static void
273impl_Bonobo_Control_setWindowId (PortableServer_Servant  servant,
274                                 Bonobo_Control_windowId id,
275                                 CORBA_Environment      *ev)
276{
277        BonoboControl *control = BONOBO_CONTROL (bonobo_object_from_servant (servant));
278        GtkWidget     *local_socket;
279        guint32        x11_id;
280
281        g_return_if_fail (control->priv->widget != NULL);
282
283        x11_id = window_id_demangle (id);
284
285        /*
286         * Check to see if this XID is local to the application.  In
287         * that case, we bypass the GtkPlug/GtkSocket mechanism and
288         * embed the control directly into the widget hierarchy.  This
289         * avoids a lot of the problems that Plug/Socket give us.
290         */
291        local_socket = bonobo_gtk_widget_from_x11_id (x11_id);
292
293        if (! local_socket) {
294                GtkWidget *old_plug;
295
296                old_plug            = control->priv->plug;
297
298                /* Create the new plug */
299                control->priv->plug = bonobo_plug_new (x11_id);
300
301                gtk_signal_connect_while_alive (GTK_OBJECT (control->priv->plug), "destroy_event",
302                                                GTK_SIGNAL_FUNC (bonobo_control_plug_destroy_event_cb),
303                                                control, GTK_OBJECT (control));
304                gtk_signal_connect_while_alive (GTK_OBJECT (control->priv->plug), "destroy",
305                                                GTK_SIGNAL_FUNC (bonobo_control_plug_destroy_cb),
306                                                control, GTK_OBJECT (control));
307
308                /*
309                 * Put the control widget inside the plug.  If we
310                 * already have a plug, then reparent the control into
311                 * the new plug.
312                 */
313                if (control->priv->xid_received) {
314
315                        if (old_plug != NULL) {
316                                gtk_object_unref (GTK_OBJECT (old_plug));
317                        }
318
319                        gtk_widget_reparent (control->priv->widget, control->priv->plug);
320                } else {
321                        gtk_container_add (GTK_CONTAINER (control->priv->plug), control->priv->widget);
322                }
323
324                gtk_widget_show (control->priv->plug);
325
326                control->priv->is_local = FALSE;
327
328        } else {
329                GtkWidget *socket_parent;
330
331                if (control->priv->xid_received)
332                        return;
333
334                control->priv->is_local = TRUE;
335
336                socket_parent = local_socket->parent;
337                gtk_widget_hide (local_socket);
338
339                control->priv->socket = local_socket;
340                control->priv->destroy_idle_id = gtk_idle_add (
341                        idle_destroy_socket, control);
342
343                gtk_signal_connect_while_alive (GTK_OBJECT (local_socket),
344                                                "destroy",
345                                                remove_destroy_idle,
346                                                control, GTK_OBJECT (control));
347
348
349                gtk_box_pack_end (GTK_BOX (socket_parent),
350                                  control->priv->widget,
351                                  TRUE, TRUE, 0);
352        }
353
354        control->priv->xid_received = TRUE;
355}
356
357static void
358impl_Bonobo_Control_setSize (PortableServer_Servant  servant,
359                             const CORBA_short       width,
360                             const CORBA_short       height,
361                             CORBA_Environment      *ev)
362{
363        /*
364         * Nothing.
365         *
366         * In the Gnome implementation of Bonobo, all size negotiation
367         * is handled by GtkPlug/GtkSocket for us, or GtkFrame in the
368         * local case.
369         */
370}
371
372static void
373impl_Bonobo_Control_getDesiredSize (PortableServer_Servant  servant,
374                                    CORBA_short            *desired_width,
375                                    CORBA_short            *desired_height,
376                                    CORBA_Environment      *ev)
377{
378        BonoboControl *control = BONOBO_CONTROL (bonobo_object_from_servant (servant));
379        GtkRequisition requisition;
380
381        gtk_widget_size_request (control->priv->widget, &requisition);
382
383        *desired_width = requisition.width;
384        *desired_height = requisition.height;
385}
386
387static GtkStateType
388bonobo_control_gtk_state_from_corba (const Bonobo_Control_State state)
389{
390        switch (state) {
391        case Bonobo_Control_StateNormal:
392                return GTK_STATE_NORMAL;
393
394        case Bonobo_Control_StateActive:
395                return GTK_STATE_ACTIVE;
396
397        case Bonobo_Control_StatePrelight:
398                return GTK_STATE_PRELIGHT;
399
400        case Bonobo_Control_StateSelected:
401                return GTK_STATE_SELECTED;
402
403        case Bonobo_Control_StateInsensitive:
404                return GTK_STATE_INSENSITIVE;
405
406        default:
407                g_warning ("bonobo_control_gtk_state_from_corba: Unknown state: %d", (gint) state);
408                return GTK_STATE_NORMAL;
409        }
410}
411
412static void
413impl_Bonobo_Control_setState (PortableServer_Servant      servant,
414                               const Bonobo_Control_State  state,
415                               CORBA_Environment          *ev)
416{
417        BonoboControl *control = BONOBO_CONTROL (bonobo_object_from_servant (servant));
418        GtkStateType gtk_state = bonobo_control_gtk_state_from_corba (state);
419
420        g_return_if_fail (control->priv->widget != NULL);
421
422        if (gtk_state == GTK_STATE_INSENSITIVE)
423                gtk_widget_set_sensitive (control->priv->widget, FALSE);
424        else {
425                if (! GTK_WIDGET_SENSITIVE (control->priv->widget))
426                        gtk_widget_set_sensitive (control->priv->widget, TRUE);
427
428                gtk_widget_set_state (control->priv->widget,
429                                      gtk_state);
430        }
431}
432
433static Bonobo_PropertyBag
434impl_Bonobo_Control_getProperties (PortableServer_Servant  servant,
435                                      CORBA_Environment      *ev)
436{
437        BonoboControl *control = BONOBO_CONTROL (bonobo_object_from_servant (servant));
438        Bonobo_PropertyBag corba_propbag;
439
440        if (control->priv->propbag == NULL)
441                return CORBA_OBJECT_NIL;
442
443        corba_propbag = BONOBO_OBJREF (control->priv->propbag);
444
445        return bonobo_object_dup_ref (corba_propbag, ev);
446}
447
448static void
449process_events (PortableServer_Servant servant)
450{
451        BonoboControl *control =
452                BONOBO_CONTROL (bonobo_object_from_servant (servant));
453
454        g_return_if_fail (control != NULL);
455        g_return_if_fail (control->priv != NULL);
456
457        if (!control->priv->is_local) {
458                while (gtk_events_pending ())
459                        gtk_main_iteration ();
460                gdk_flush ();
461        }
462}
463
464static void
465impl_Bonobo_Control_realize (PortableServer_Servant servant,
466                             CORBA_Environment     *ev)
467{
468        process_events (servant);
469}
470
471static void
472impl_Bonobo_Control_unrealize (PortableServer_Servant servant,
473                               CORBA_Environment     *ev)
474{
475        process_events (servant);
476}
477
478static CORBA_boolean
479impl_Bonobo_Control_focusChild (PortableServer_Servant servant,
480                                Bonobo_Control_FocusDirection corba_direction,
481                                CORBA_Environment *ev)
482{
483        BonoboControl *control;
484        BonoboControlPrivate *priv;
485        GtkDirectionType direction;
486
487        control = BONOBO_CONTROL (bonobo_object_from_servant (servant));
488        priv = control->priv;
489
490        if (!priv->plug)
491                return FALSE;
492
493        switch (corba_direction) {
494        case Bonobo_Control_TAB_FORWARD:
495                direction = GTK_DIR_TAB_FORWARD;
496                break;
497
498        case Bonobo_Control_TAB_BACKWARD:
499                direction = GTK_DIR_TAB_BACKWARD;
500                break;
501
502        case Bonobo_Control_UP:
503                direction = GTK_DIR_UP;
504                break;
505
506        case Bonobo_Control_DOWN:
507                direction = GTK_DIR_DOWN;
508                break;
509
510        case Bonobo_Control_LEFT:
511                direction = GTK_DIR_LEFT;
512                break;
513
514        case Bonobo_Control_RIGHT:
515                direction = GTK_DIR_RIGHT;
516                break;
517
518        default:
519                /* Hmmm, we should throw an exception. */
520                return FALSE;
521        }
522
523        bonobo_plug_clear_focus_chain (BONOBO_PLUG (priv->plug));
524        return gtk_container_focus (GTK_CONTAINER (priv->plug), direction);
525}
526
527BonoboControl *
528bonobo_control_construct (BonoboControl  *control,
529                          GtkWidget      *widget)
530{
531        g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
532        g_return_val_if_fail (BONOBO_IS_CONTROL (control), NULL);
533
534        /*
535         * This sets up the X handler for Bonobo objects.  We basically will
536         * ignore X errors if our container dies (because X will kill the
537         * windows of the container and our container without telling us).
538         */
539        bonobo_setup_x_error_handler ();
540
541        control->priv->widget = GTK_WIDGET (widget);
542        gtk_object_ref (GTK_OBJECT (widget));
543        gtk_object_sink (GTK_OBJECT (widget));
544
545        control->priv->ui_component = NULL;
546        control->priv->propbag = NULL;
547
548        return control;
549}
550
551/**
552 * bonobo_control_new:
553 * @widget: a GTK widget that contains the control and will be passed to the
554 * container process.
555 *
556 * This function creates a new BonoboControl object for @widget.
557 *
558 * Returns: a BonoboControl object that implements the Bonobo::Control CORBA
559 * service that will transfer the @widget to the container process.
560 */
561BonoboControl *
562bonobo_control_new (GtkWidget *widget)
563{
564        BonoboControl *control;
565       
566        g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
567
568        control = gtk_type_new (bonobo_control_get_type ());
569       
570        return bonobo_control_construct (control, widget);
571}
572
573/**
574 * bonobo_control_get_widget:
575 * @control: a BonoboControl
576 *
577 * Returns the GtkWidget associated with a BonoboControl.
578 *
579 * Return value: the BonoboControl's widget
580 **/
581GtkWidget *
582bonobo_control_get_widget (BonoboControl *control)
583{
584        g_return_val_if_fail (BONOBO_IS_CONTROL (control), NULL);
585
586        return control->priv->widget;
587}
588
589/**
590 * bonobo_control_set_automerge:
591 * @control: A #BonoboControl.
592 * @automerge: Whether or not menus and toolbars should be
593 * automatically merged when the control is activated.
594 *
595 * Sets whether or not the control handles menu/toolbar merging
596 * automatically.  If automerge is on, the control will automatically
597 * register its BonoboUIComponent with the remote BonoboUIContainer
598 * when it is activated.
599 */
600void
601bonobo_control_set_automerge (BonoboControl *control,
602                              gboolean       automerge)
603{
604        g_return_if_fail (BONOBO_IS_CONTROL (control));
605
606        control->priv->automerge = automerge;
607
608        if (automerge && !control->priv->ui_component)
609                control->priv->ui_component = bonobo_ui_component_new_default ();
610}
611
612/**
613 * bonobo_control_get_automerge:
614 * @control: A #BonoboControl.
615 *
616 * Returns: Whether or not the control is set to automerge its
617 * menus/toolbars.  See bonobo_control_set_automerge().
618 */
619gboolean
620bonobo_control_get_automerge (BonoboControl *control)
621{
622        g_return_val_if_fail (BONOBO_IS_CONTROL (control), FALSE);
623
624        return control->priv->automerge;
625}
626
627static void
628bonobo_control_destroy (GtkObject *object)
629{
630        BonoboControl *control = BONOBO_CONTROL (object);
631        CORBA_Environment ev;
632
633        CORBA_exception_init (&ev);
634
635        if (control->priv->destroy_idle_id != 0) {
636                gtk_idle_remove (control->priv->destroy_idle_id);
637        }
638        control->priv->destroy_idle_id = 0;
639
640        if (control->priv->propbag)
641                bonobo_object_unref (BONOBO_OBJECT (control->priv->propbag));
642        control->priv->propbag = NULL;
643
644        if (control->priv->control_frame != CORBA_OBJECT_NIL) {
645                if (control->priv->active)
646                        Bonobo_ControlFrame_activated (control->priv->control_frame,
647                                                       FALSE, &ev);
648               
649                CORBA_Object_release (control->priv->control_frame, &ev);
650        }
651
652        CORBA_exception_free (&ev);
653
654        /*
655         * If we have a UIComponent, destroy it.
656         */
657        if (control->priv->ui_component != NULL) {
658                bonobo_ui_component_unset_container (control->priv->ui_component);
659                bonobo_object_unref (BONOBO_OBJECT (control->priv->ui_component));
660        }
661
662        GTK_OBJECT_CLASS (bonobo_control_parent_class)->destroy (object);
663}
664
665static void
666bonobo_control_finalize (GtkObject *object)
667{
668        BonoboControl *control = BONOBO_CONTROL (object);
669
670        /*
671         * Destroy the control's top-level widget.
672         */
673        if (control->priv->widget)
674                gtk_object_unref (GTK_OBJECT (control->priv->widget));
675
676        /*
677         * If the plug still exists, destroy it.  The plug might not
678         * exist in the case where the container application died,
679         * taking the plug out with it, or the optimized local case
680         * where the plug/socket mechanism was bypassed.  In the
681         * formaer case, plug_destroy_cb() would have been invoked,
682         * and it would have triggered the destruction of the Control,
683         * which is why we're here now. In the latter case, it's not
684         * needed because there is no plug. 
685         */
686        if (control->priv->plug) {
687                gtk_object_destroy (GTK_OBJECT (control->priv->plug));
688                control->priv->plug = NULL;
689        }
690
691        g_free (control->priv);
692
693        GTK_OBJECT_CLASS (bonobo_control_parent_class)->finalize (object);
694}
695
696/**
697 * bonobo_control_set_control_frame:
698 * @control: A BonoboControl object.
699 * @control_frame: A CORBA interface for the ControlFrame which contains this Controo.
700 *
701 * Sets the ControlFrame for @control to @control_frame.
702 */
703void
704bonobo_control_set_control_frame (BonoboControl *control, Bonobo_ControlFrame control_frame)
705{
706        CORBA_Environment ev;
707
708        g_return_if_fail (BONOBO_IS_CONTROL (control));
709
710        CORBA_exception_init (&ev);
711
712        if (control->priv->control_frame != CORBA_OBJECT_NIL)
713                CORBA_Object_release (control->priv->control_frame, &ev);
714       
715        if (control_frame == CORBA_OBJECT_NIL)
716                control->priv->control_frame = CORBA_OBJECT_NIL;
717        else
718                control->priv->control_frame = CORBA_Object_duplicate (control_frame, &ev);
719       
720        CORBA_exception_free (&ev);
721
722        gtk_signal_emit (GTK_OBJECT (control), control_signals [SET_FRAME]);
723}
724
725/**
726 * bonobo_control_get_control_frame:
727 * @control: A BonoboControl object whose Bonobo_ControlFrame CORBA interface is
728 * being retrieved.
729 *
730 * Returns: The Bonobo_ControlFrame CORBA object associated with @control, this is
731 * a CORBA_Object_duplicated object.  You need to CORBA_Object_release it when you are
732 * done with it.
733 */
734Bonobo_ControlFrame
735bonobo_control_get_control_frame (BonoboControl *control)
736{
737        Bonobo_ControlFrame control_frame;
738        CORBA_Environment ev;
739       
740        g_return_val_if_fail (BONOBO_IS_CONTROL (control), CORBA_OBJECT_NIL);
741
742        CORBA_exception_init (&ev);
743        control_frame = CORBA_Object_duplicate (control->priv->control_frame, &ev);
744        CORBA_exception_free (&ev);
745
746        return control_frame;
747}
748
749/**
750 * bonobo_control_get_ui_component:
751 * @control: The control
752 *
753 * Return value: the associated UI component
754 **/
755BonoboUIComponent *
756bonobo_control_get_ui_component (BonoboControl *control)
757{
758        g_return_val_if_fail (BONOBO_IS_CONTROL (control), NULL);
759
760        if (!control->priv->ui_component)
761                control->priv->ui_component = bonobo_ui_component_new_default ();
762
763        return control->priv->ui_component;
764}
765
766void
767bonobo_control_set_ui_component (BonoboControl     *control,
768                                 BonoboUIComponent *component)
769{
770        g_return_if_fail (BONOBO_IS_CONTROL (control));
771        g_return_if_fail (BONOBO_IS_UI_COMPONENT (component));
772
773        if (control->priv->ui_component)
774                bonobo_object_unref (BONOBO_OBJECT (control->priv->ui_component));
775       
776        control->priv->ui_component = component;
777}
778
779/**
780 * bonobo_control_set_properties:
781 * @control: A #BonoboControl object.
782 * @pb: A #BonoboPropertyBag.
783 *
784 * Binds @pb to @control.  When a remote object queries @control
785 * for its property bag, @pb will be used in the responses.
786 */
787void
788bonobo_control_set_properties (BonoboControl *control, BonoboPropertyBag *pb)
789{
790        BonoboPropertyBag *old_bag;
791
792        g_return_if_fail (BONOBO_IS_CONTROL (control));
793        g_return_if_fail (BONOBO_IS_PROPERTY_BAG (pb));
794
795        old_bag = control->priv->propbag;
796        control->priv->propbag = pb;
797
798        if (pb)
799                bonobo_object_ref (BONOBO_OBJECT (pb));
800
801        if (old_bag)
802                bonobo_object_unref (BONOBO_OBJECT (old_bag));
803}
804
805/**
806 * bonobo_control_get_properties:
807 * @control: A #BonoboControl whose PropertyBag has already been set.
808 *
809 * Returns: The #BonoboPropertyBag bound to @control.
810 */
811BonoboPropertyBag *
812bonobo_control_get_properties (BonoboControl *control)
813{
814        g_return_val_if_fail (BONOBO_IS_CONTROL (control), NULL);
815
816        return control->priv->propbag;
817}
818
819/**
820 * bonobo_control_get_ambient_properties:
821 * @control: A #BonoboControl which is bound to a remote
822 * #BonoboControlFrame.
823 * @ev: CORBA exception environment.
824 *
825 * Returns: A #Bonobo_PropertyBag bound to the bag of ambient
826 * properties associated with this #Control's #ControlFrame.
827 */
828Bonobo_PropertyBag
829bonobo_control_get_ambient_properties (BonoboControl     *control,
830                                       CORBA_Environment *ev)
831{
832        Bonobo_ControlFrame control_frame;
833        Bonobo_PropertyBag pbag;
834        CORBA_Environment *real_ev, tmp_ev;
835
836        g_return_val_if_fail (BONOBO_IS_CONTROL (control), NULL);
837
838        control_frame = control->priv->control_frame;
839
840        if (control_frame == CORBA_OBJECT_NIL)
841                return NULL;
842
843        if (ev)
844                real_ev = ev;
845        else {
846                CORBA_exception_init (&tmp_ev);
847                real_ev = &tmp_ev;
848        }
849
850        pbag = Bonobo_ControlFrame_getAmbientProperties (
851                control_frame, real_ev);
852
853        if (BONOBO_EX (real_ev)) {
854                if (!ev)
855                        CORBA_exception_free (&tmp_ev);
856                pbag = CORBA_OBJECT_NIL;
857        }
858
859        return pbag;
860}
861
862/**
863 * bonobo_control_get_remote_ui_container:
864 * @control: A BonoboControl object which is associated with a remote
865 * ControlFrame.
866 *
867 * Returns: The Bonobo_UIContainer CORBA server for the remote BonoboControlFrame.
868 */
869Bonobo_UIContainer
870bonobo_control_get_remote_ui_container (BonoboControl *control)
871{
872        CORBA_Environment  ev;
873        Bonobo_UIContainer ui_container;
874
875        g_return_val_if_fail (BONOBO_IS_CONTROL (control), CORBA_OBJECT_NIL);
876
877        g_return_val_if_fail (control->priv->control_frame != CORBA_OBJECT_NIL,
878                              CORBA_OBJECT_NIL);
879
880        CORBA_exception_init (&ev);
881
882        ui_container = Bonobo_ControlFrame_getUIHandler (control->priv->control_frame, &ev);
883
884        bonobo_object_check_env (BONOBO_OBJECT (control), control->priv->control_frame, &ev);
885
886        CORBA_exception_free (&ev);
887
888        return ui_container;
889}
890
891/**
892 * bonobo_control_activate_notify:
893 * @control: A #BonoboControl object which is bound
894 * to a remote ControlFrame.
895 * @activated: Whether or not @control has been activated.
896 *
897 * Notifies the remote ControlFrame which is associated with
898 * @control that @control has been activated/deactivated.
899 */
900void
901bonobo_control_activate_notify (BonoboControl *control,
902                                gboolean      activated)
903{
904        CORBA_Environment ev;
905
906        g_return_if_fail (BONOBO_IS_CONTROL (control));
907        g_return_if_fail (control->priv->control_frame != CORBA_OBJECT_NIL);
908       
909        CORBA_exception_init (&ev);
910
911        Bonobo_ControlFrame_activated (control->priv->control_frame, activated, &ev);
912
913        bonobo_object_check_env (BONOBO_OBJECT (control), control->priv->control_frame, &ev);
914
915        CORBA_exception_free (&ev);
916}
917
918static void
919bonobo_control_class_init (BonoboControlClass *klass)
920{
921        GtkObjectClass *object_class = (GtkObjectClass *)klass;
922        POA_Bonobo_Control__epv *epv;
923
924        bonobo_control_parent_class = gtk_type_class (PARENT_TYPE);
925
926        control_signals [SET_FRAME] =
927                gtk_signal_new ("set_frame",
928                                GTK_RUN_LAST,
929                                object_class->type,
930                                GTK_SIGNAL_OFFSET (BonoboControlClass, set_frame),
931                                gtk_marshal_NONE__NONE,
932                                GTK_TYPE_NONE, 0);
933
934        control_signals [ACTIVATE] =
935                gtk_signal_new ("activate",
936                                GTK_RUN_LAST,
937                                object_class->type,
938                                GTK_SIGNAL_OFFSET (BonoboControlClass, activate),
939                                gtk_marshal_NONE__BOOL,
940                                GTK_TYPE_NONE, 1,
941                                GTK_TYPE_BOOL);
942
943        gtk_object_class_add_signals (object_class, control_signals, LAST_SIGNAL);
944
945        object_class->destroy  = bonobo_control_destroy;
946        object_class->finalize = bonobo_control_finalize;
947
948        epv = &klass->epv;
949
950        epv->activate       = impl_Bonobo_Control_activate;
951        epv->setSize        = impl_Bonobo_Control_setSize;
952        epv->setWindowId    = impl_Bonobo_Control_setWindowId;
953        epv->setState       = impl_Bonobo_Control_setState;
954        epv->setFrame       = impl_Bonobo_Control_setFrame;
955        epv->getDesiredSize = impl_Bonobo_Control_getDesiredSize;
956        epv->getProperties  = impl_Bonobo_Control_getProperties;
957        epv->realize        = impl_Bonobo_Control_realize;
958        epv->unrealize      = impl_Bonobo_Control_unrealize;
959        epv->focusChild     = impl_Bonobo_Control_focusChild;
960}
961
962static void
963bonobo_control_init (BonoboControl *control)
964{
965        control->priv = g_new0 (BonoboControlPrivate, 1);
966
967        control->priv->control_frame = CORBA_OBJECT_NIL;
968}
969
970BONOBO_X_TYPE_FUNC_FULL (BonoboControl,
971                         Bonobo_Control,
972                         PARENT_TYPE,
973                         bonobo_control);
974
975void
976bonobo_control_set_property (BonoboControl       *control,
977                             const char          *first_prop,
978                             ...)
979{
980        Bonobo_PropertyBag  bag;
981        char               *err;
982        CORBA_Environment   ev;
983        va_list             args;
984
985        g_return_if_fail (first_prop != NULL);
986        g_return_if_fail (BONOBO_IS_CONTROL (control));
987
988        va_start (args, first_prop);
989
990        CORBA_exception_init (&ev);
991
992        bag = BONOBO_OBJREF (control->priv->propbag);
993
994        if ((err = bonobo_property_bag_client_setv (bag, &ev, first_prop, args)))
995                g_warning ("Error '%s'", err);
996
997        CORBA_exception_free (&ev);
998
999        va_end (args);
1000}
1001
1002void
1003bonobo_control_get_property (BonoboControl       *control,
1004                             const char          *first_prop,
1005                             ...)
1006{
1007        Bonobo_PropertyBag  bag;
1008        char               *err;
1009        CORBA_Environment   ev;
1010        va_list             args;
1011
1012        g_return_if_fail (first_prop != NULL);
1013        g_return_if_fail (BONOBO_IS_CONTROL (control));
1014
1015        va_start (args, first_prop);
1016
1017        CORBA_exception_init (&ev);
1018
1019        bag = BONOBO_OBJREF (control->priv->propbag);
1020
1021        if ((err = bonobo_property_bag_client_getv (bag, &ev, first_prop, args)))
1022                g_warning ("Error '%s'", err);
1023
1024        CORBA_exception_free (&ev);
1025
1026        va_end (args);
1027}
Note: See TracBrowser for help on using the repository browser.