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 | |
---|
31 | enum { |
---|
32 | SHOW_WINDOW, |
---|
33 | SAVE_OBJECT, |
---|
34 | LAST_SIGNAL |
---|
35 | }; |
---|
36 | |
---|
37 | static GtkObjectClass *bonobo_client_site_parent_class; |
---|
38 | static guint bonobo_client_site_signals [LAST_SIGNAL]; |
---|
39 | |
---|
40 | static Bonobo_ItemContainer |
---|
41 | impl_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 | |
---|
52 | static void |
---|
53 | impl_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 | |
---|
64 | static Bonobo_Persist_Status |
---|
65 | impl_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 | |
---|
78 | static void |
---|
79 | bonobo_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 | |
---|
100 | static void |
---|
101 | default_show_window (BonoboClientSite *cs, CORBA_boolean shown) |
---|
102 | { |
---|
103 | cs->child_shown = shown ? 1 : 0; |
---|
104 | } |
---|
105 | |
---|
106 | static void |
---|
107 | default_save_object (BonoboClientSite *cs, Bonobo_Persist_Status *status) |
---|
108 | { |
---|
109 | } |
---|
110 | |
---|
111 | static void |
---|
112 | bonobo_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 | |
---|
150 | static void |
---|
151 | bonobo_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 | */ |
---|
166 | BonoboClientSite * |
---|
167 | bonobo_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 | */ |
---|
194 | BonoboClientSite * |
---|
195 | bonobo_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 | |
---|
207 | BONOBO_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 | */ |
---|
226 | gboolean |
---|
227 | bonobo_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 | */ |
---|
277 | BonoboObjectClient * |
---|
278 | bonobo_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 | **/ |
---|
294 | BonoboItemContainer * |
---|
295 | bonobo_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 | |
---|
303 | static void |
---|
304 | bonobo_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 | */ |
---|
329 | BonoboViewFrame * |
---|
330 | bonobo_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 | */ |
---|
401 | BonoboViewFrame * |
---|
402 | bonobo_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 | |
---|
409 | static void |
---|
410 | canvas_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 | */ |
---|
423 | GnomeCanvasItem * |
---|
424 | bonobo_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 | } |
---|