source: trunk/third/bonobo/bonobo/bonobo-client-site.c @ 16750

Revision 16750, 13.4 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-client-site.h: a ClientSite object.
4 *
5 * A BonoboClientSite object acts as the point-of-contact for an
6 * embedded component: the contained Bonobo::Embeddable object
7 * communicates with the BonoboClientSite when it wants to talk to its
8 * container.  There must be a one-to-one mapping between
9 * BonoboClientSite objects and embedding BonoboEmbeddable components.
10 *
11 * Author:
12 *   Miguel de Icaza (miguel@kernel.org)
13 *   Nat Friedman    (nat@nat.org)
14 *
15 * Copyright 1999 Helix Code, Inc.
16 */
17#include <config.h>
18#include <stdio.h>
19#include <gtk/gtksignal.h>
20#include <gtk/gtkmarshal.h>
21#include <bonobo/bonobo-exception.h>
22#include <bonobo/bonobo-client-site.h>
23#include <bonobo/bonobo-embeddable.h>
24#include <bonobo/bonobo-canvas-item.h>
25#include <gdk/gdkprivate.h>
26#include <gdk/gdkx.h>
27#include <gdk/gdktypes.h>
28
29#define PARENT_TYPE BONOBO_X_OBJECT_TYPE
30
31enum {
32        SHOW_WINDOW,
33        SAVE_OBJECT,
34        LAST_SIGNAL
35};
36
37static GtkObjectClass *bonobo_client_site_parent_class;
38static guint bonobo_client_site_signals [LAST_SIGNAL];
39
40static Bonobo_ItemContainer
41impl_Bonobo_ClientSite_getContainer (PortableServer_Servant servant, CORBA_Environment *ev)
42{
43        BonoboObject         *object = bonobo_object_from_servant (servant);
44        Bonobo_ItemContainer  corba_object;
45        BonoboClientSite     *client_site = BONOBO_CLIENT_SITE (object);
46
47        corba_object = BONOBO_OBJREF (client_site->container);
48
49        return bonobo_object_dup_ref (corba_object, ev);
50}
51
52static void
53impl_Bonobo_ClientSite_showWindow (PortableServer_Servant servant, CORBA_boolean shown,
54                                    CORBA_Environment *ev)
55{
56        BonoboClientSite *client_site = BONOBO_CLIENT_SITE (bonobo_object_from_servant (servant));
57        BonoboObject *object = BONOBO_OBJECT (client_site);
58
59        gtk_signal_emit (GTK_OBJECT (object),
60                         bonobo_client_site_signals [SHOW_WINDOW],
61                         shown);
62}
63
64static Bonobo_Persist_Status
65impl_Bonobo_ClientSite_saveObject (PortableServer_Servant servant, CORBA_Environment *ev)
66{
67        BonoboObject *object = bonobo_object_from_servant (servant);
68        Bonobo_Persist_Status status;
69
70        status = Bonobo_Persist_SAVE_OK;
71       
72        gtk_signal_emit (GTK_OBJECT (object),
73                         bonobo_client_site_signals [SAVE_OBJECT],
74                         &status);
75        return status;
76}
77
78static void
79bonobo_client_site_destroy (GtkObject *object)
80{
81        BonoboClientSite *client_site = BONOBO_CLIENT_SITE (object);
82       
83        bonobo_object_list_unref_all (&client_site->view_frames);
84
85        /* Destroy all canvas items */
86        /* FIXME: this looks dodgy to me */
87        while (client_site->canvas_items) {
88                BonoboCanvasItem *item = BONOBO_CANVAS_ITEM (client_site->canvas_items->data);
89                gtk_object_unref (GTK_OBJECT (item));
90        }
91
92        if (client_site->bound_embeddable) {
93                bonobo_object_unref (BONOBO_OBJECT (client_site->bound_embeddable));
94                client_site->bound_embeddable = NULL;
95        }
96
97        bonobo_client_site_parent_class->destroy (object);
98}
99
100static void
101default_show_window (BonoboClientSite *cs, CORBA_boolean shown)
102{
103        cs->child_shown = shown ? 1 : 0;
104}
105
106static void
107default_save_object (BonoboClientSite *cs, Bonobo_Persist_Status *status)
108{
109}
110
111static void
112bonobo_client_site_class_init (BonoboClientSiteClass *klass)
113{
114        BonoboObjectClass *gobject_class = (BonoboObjectClass *) klass;
115        GtkObjectClass    *object_class  = (GtkObjectClass *) gobject_class;
116        POA_Bonobo_ClientSite__epv  *epv = &klass->epv;
117
118        bonobo_client_site_parent_class = gtk_type_class (PARENT_TYPE);
119
120        bonobo_client_site_signals [SHOW_WINDOW] =
121                gtk_signal_new ("show_window",
122                                GTK_RUN_LAST,
123                                object_class->type,
124                                GTK_SIGNAL_OFFSET (BonoboClientSiteClass, show_window),
125                                gtk_marshal_NONE__INT,
126                                GTK_TYPE_NONE, 1,
127                                GTK_TYPE_INT);
128        bonobo_client_site_signals [SAVE_OBJECT] =
129                gtk_signal_new ("save_object",
130                                GTK_RUN_LAST,
131                                object_class->type,
132                                GTK_SIGNAL_OFFSET (BonoboClientSiteClass, save_object),
133                                gtk_marshal_NONE__POINTER,
134                                GTK_TYPE_NONE, 1,
135                                GTK_TYPE_POINTER);
136
137        gtk_object_class_add_signals (object_class,
138                                      bonobo_client_site_signals,
139                                      LAST_SIGNAL);
140       
141        object_class->destroy = bonobo_client_site_destroy;
142        klass->show_window = default_show_window;
143        klass->save_object = default_save_object;
144
145        epv->getContainer = impl_Bonobo_ClientSite_getContainer;
146        epv->showWindow   = impl_Bonobo_ClientSite_showWindow;
147        epv->saveObject   = impl_Bonobo_ClientSite_saveObject;
148}
149
150static void
151bonobo_client_site_init (BonoboClientSite *client_site)
152{
153        client_site->bound_embeddable = NULL;
154}
155
156/**
157 * bonobo_client_site_construct:
158 * @client_site: The BonoboClientSite object to initialize
159 * @container: a BonoboContainer to bind to.
160 *
161 * This initializes an object of type BonoboClientSite.  See the description
162 * for bonobo_client_site_new () for more details.
163 *
164 * Returns: the constructed BonoboClientSite @client_site.
165 */
166BonoboClientSite *
167bonobo_client_site_construct (BonoboClientSite    *client_site,
168                              BonoboItemContainer *container)
169{
170        g_return_val_if_fail (client_site != NULL, NULL);
171        g_return_val_if_fail (BONOBO_IS_CLIENT_SITE (client_site), NULL);
172        g_return_val_if_fail (container != NULL, NULL);
173        g_return_val_if_fail (BONOBO_IS_ITEM_CONTAINER (container), NULL);
174       
175        BONOBO_CLIENT_SITE (client_site)->container = container;
176
177        return client_site;
178}
179
180/**
181 * bonobo_client_site_new:
182 * @container: The container to which this client_site belongs.
183 *
184 * Container programs should provide a BonoboClientSite GTK object (ie,
185 * a Bonobo::ClientSite CORBA server) for each Embeddable which they
186 * embed.  This is the contact end point for the remote
187 * Bonobo::Embeddable object.
188 *
189 * This routine creates a new BonoboClientSite.
190 *
191 * Returns: The activated BonoboClientSite object bound to the @container
192 * container.
193 */
194BonoboClientSite *
195bonobo_client_site_new (BonoboItemContainer *container)
196{
197        BonoboClientSite *client_site;
198
199        g_return_val_if_fail (container != NULL, NULL);
200        g_return_val_if_fail (BONOBO_IS_ITEM_CONTAINER (container), NULL);
201       
202        client_site = gtk_type_new (bonobo_client_site_get_type ());
203
204        return bonobo_client_site_construct (client_site, container);
205}
206
207BONOBO_X_TYPE_FUNC_FULL (BonoboClientSite,
208                           Bonobo_ClientSite,
209                           PARENT_TYPE,
210                           bonobo_client_site);
211
212/**
213 * bonobo_client_site_bind_embeddable:
214 * @client_site: the client site to which the remote Embeddable object will be bound.
215 * @object: The remote object which supports the Bonobo::Embeddable interface.
216 *
217 * This routine binds a remote Embeddable object to a local
218 * BonoboClientSite object.  The idea is that there is always a
219 * one-to-one mapping between BonoboClientSites and BonoboEmbeddables.
220 * The Embeddable uses its BonoboClientSite to communicate with the
221 * container in which it is embedded.
222 *
223 * Returns: %TRUE if @object was successfully bound to @client_site
224 * @client_site.
225 */
226gboolean
227bonobo_client_site_bind_embeddable (BonoboClientSite   *client_site,
228                                    BonoboObjectClient *object)
229{
230        CORBA_Object embeddable_object;
231        CORBA_Environment ev;
232       
233        g_return_val_if_fail (client_site != NULL, FALSE);
234        g_return_val_if_fail (object != NULL, FALSE);
235        g_return_val_if_fail (BONOBO_IS_CLIENT_SITE (client_site), FALSE);
236        g_return_val_if_fail (BONOBO_IS_OBJECT_CLIENT (object), FALSE);
237
238        embeddable_object = bonobo_object_client_query_interface (
239                object, "IDL:Bonobo/Embeddable:1.0", NULL);
240
241        if (embeddable_object == CORBA_OBJECT_NIL)
242                return FALSE;
243
244        CORBA_exception_init (&ev);
245
246        /* The QI adds a ref */
247        Bonobo_Unknown_unref (BONOBO_OBJREF (object), &ev);
248
249        Bonobo_Embeddable_setClientSite (embeddable_object,
250                                         BONOBO_OBJREF (client_site), &ev);
251               
252        if (BONOBO_EX (&ev)) {
253                bonobo_object_check_env (BONOBO_OBJECT (object),
254                                         embeddable_object, &ev);
255                CORBA_exception_free (&ev);
256                return FALSE;
257        }
258        CORBA_exception_free (&ev);
259
260        if (client_site->bound_embeddable)
261                bonobo_object_unref (BONOBO_OBJECT (client_site->bound_embeddable));
262
263        client_site->bound_embeddable = bonobo_object_client_from_corba (embeddable_object);
264        bonobo_object_client_ref (client_site->bound_embeddable, NULL);
265
266        return TRUE;
267}
268
269/**
270 * bonobo_client_site_get_embeddable:
271 * @client_site: A BonoboClientSite object which is bound to a remote
272 * BonoboObject server.
273 *
274 * Returns: The BonoboObjectClient object which corresponds to the
275 * remote BonoboObject to which @client_site is bound.
276 */
277BonoboObjectClient *
278bonobo_client_site_get_embeddable (BonoboClientSite *client_site)
279{
280        g_return_val_if_fail (
281                BONOBO_IS_CLIENT_SITE (client_site), NULL);
282
283        return client_site->bound_embeddable;
284}
285
286/**
287 * bonobo_client_site_get_container:
288 * @client_site: A BonoboClientSite object which is bound to a remote
289 * BonoboObject server.
290 *
291 * Returns: The BonoboObjectClient object which corresponds to the
292 * remote BonoboObject to which @client_site is bound.
293 **/
294BonoboItemContainer *
295bonobo_client_site_get_container (BonoboClientSite *client_site)
296{
297        g_return_val_if_fail (
298                BONOBO_IS_CLIENT_SITE (client_site), NULL);
299
300        return client_site->container;
301}
302
303static void
304bonobo_client_site_view_frame_destroy (BonoboViewFrame  *view_frame,
305                                       BonoboClientSite *client_site)
306{
307        /*
308         * Remove this view frame.
309         */
310        client_site->view_frames = g_list_remove (client_site->view_frames, view_frame);
311}
312
313/**
314 * bonobo_client_site_new_view_full:
315 * @client_site: the client site that contains a remote Embeddable object.
316 * @uic: The CORBA object for the container's UIContainer server.
317 * @visible_cover: %TRUE if the cover should draw a border when it is active.
318 * @active_view: %TRUE if the view should be uncovered when it is created.
319 *
320 * Creates a ViewFrame and asks the remote @server_object (which must
321 * support the Bonobo::Embeddable interface) to provide a new view of
322 * its data.  The remote @server_object will construct a BonoboView
323 * object which corresponds to the new BonoboViewFrame returned by this
324 * function.
325 *
326 * Returns: A BonoboViewFrame object that contains the view frame for
327 * the new view of @server_object.
328 */
329BonoboViewFrame *
330bonobo_client_site_new_view_full (BonoboClientSite  *client_site,
331                                  Bonobo_UIContainer uic,
332                                  gboolean           visible_cover,
333                                  gboolean           active_view)
334{
335        Bonobo_Embeddable server_object;
336        BonoboViewFrame *view_frame;
337        BonoboWrapper *wrapper;
338        Bonobo_View view;
339
340        CORBA_Environment ev;
341
342        g_return_val_if_fail (client_site != NULL, NULL);
343        g_return_val_if_fail (BONOBO_IS_CLIENT_SITE (client_site), NULL);
344        g_return_val_if_fail (client_site->bound_embeddable != NULL, NULL);
345
346        /*
347         * 1. Create the view frame.
348         */
349        view_frame = bonobo_view_frame_new (client_site, uic);
350        wrapper = BONOBO_WRAPPER (bonobo_view_frame_get_wrapper (view_frame));
351        bonobo_wrapper_set_visibility (wrapper, visible_cover);
352        bonobo_wrapper_set_covered (wrapper, ! active_view);
353
354        /*
355         * 2. Now, create the view.
356         */
357        server_object = BONOBO_OBJREF (client_site->bound_embeddable);
358        CORBA_exception_init (&ev);
359        view = Bonobo_Embeddable_createView (server_object,
360                                             BONOBO_OBJREF (view_frame), &ev);
361
362        if (BONOBO_EX (&ev)) {
363                bonobo_object_check_env (
364                        BONOBO_OBJECT (client_site),
365                        server_object,
366                        &ev);
367                bonobo_object_unref (BONOBO_OBJECT (view_frame));
368                CORBA_exception_free (&ev);
369                return NULL;
370        }
371
372        bonobo_view_frame_bind_to_view (view_frame, view);
373        bonobo_object_release_unref (view, &ev);
374       
375        /*
376         * 3. Add this new view frame to the list of ViewFrames for
377         * this embedded component.
378         */
379        client_site->view_frames = g_list_prepend (client_site->view_frames, view_frame);
380       
381        gtk_signal_connect (GTK_OBJECT (view_frame), "destroy",
382                            GTK_SIGNAL_FUNC (bonobo_client_site_view_frame_destroy),
383                            client_site);
384
385        CORBA_exception_free (&ev);             
386        return view_frame;
387}
388
389/**
390 * bonobo_client_site_new_view:
391 * @client_site: the client site that contains a remote Embeddable
392 * object.
393 * @uic: The UIContainer object.
394 *
395 * The same as bonobo_client_site_new_view_full() with an inactive,
396 * visible cover.
397 *
398 * Returns: A BonoboViewFrame object that contains the view frame for
399 * the new view of @server_object.
400 */
401BonoboViewFrame *
402bonobo_client_site_new_view (BonoboClientSite  *client_site,
403                             Bonobo_UIContainer uic)
404{
405
406        return bonobo_client_site_new_view_full (client_site, uic, TRUE, FALSE);
407}
408
409static void
410canvas_item_destroyed (GnomeCanvasItem *item, BonoboClientSite *client_site)
411{
412        client_site->canvas_items = g_list_remove (client_site->canvas_items, item);
413}
414                     
415/**
416 * bonobo_client_site_new_item:
417 * @client_site: The client site that contains a remote Embeddable object
418 * @uic: The UI container for the item.
419 * @group: The Canvas group that will be the parent for the new item.
420 *
421 * Returns: A GnomeCanvasItem that wraps the remote Canvas Item.
422 */
423GnomeCanvasItem *
424bonobo_client_site_new_item (BonoboClientSite  *client_site,
425                             Bonobo_UIContainer uic,
426                             GnomeCanvasGroup  *group)
427{
428        GnomeCanvasItem *item;
429        Bonobo_Embeddable corba_emb;
430               
431        g_return_val_if_fail (client_site != NULL, NULL);
432        g_return_val_if_fail (BONOBO_IS_CLIENT_SITE (client_site), NULL);
433        g_return_val_if_fail (client_site->bound_embeddable != NULL, NULL);
434        g_return_val_if_fail (group != NULL, NULL);
435        g_return_val_if_fail (GNOME_IS_CANVAS_GROUP (group), NULL);
436
437        corba_emb = BONOBO_OBJREF (client_site->bound_embeddable);
438
439        item = gnome_canvas_item_new (group, bonobo_canvas_item_get_type (),
440                                      "corba_ui_container", uic,
441                                      "corba_embeddable", corba_emb, NULL);
442
443        /*
444         * 5. Add this new item to the list of CanvasItems for
445         * this embedded component.
446         */
447        client_site->canvas_items = g_list_prepend (client_site->canvas_items, item);
448
449        gtk_signal_connect (GTK_OBJECT (item), "destroy",
450                            GTK_SIGNAL_FUNC (canvas_item_destroyed), client_site);
451       
452        return item;
453}
Note: See TracBrowser for help on using the repository browser.