1 /* Dia -- an diagram creation/manipulation program
2  * Copyright (C) 2000 Alexander Larsson
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program 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
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #  include <config.h>
21 #endif
22 
23 #include <gnome.h>
24 #include <bonobo.h>
25 #include <liboaf/liboaf.h>
26 
27 #include "display.h"
28 #include "menus.h"
29 #include "disp_callbacks.h"
30 #include "app_procs.h"
31 #include "interface.h"
32 #include "load_save.h"
33 
34 #ifdef GNOME_PRINT
35 #  include "render_gnomeprint.h"
36 #endif
37 
38 typedef struct _EmbeddedDia EmbeddedDia;
39 typedef struct _EmbeddedView EmbeddedView;
40 
41 struct _EmbeddedDia {
42   BonoboEmbeddable     *embeddable;
43 
44   Diagram *diagram;
45 };
46 
47 struct _EmbeddedView {
48   BonoboView	    *view;
49   EmbeddedDia *embedded_dia;
50   DDisplay *display;
51 };
52 
53 static BonoboGenericFactory *factory = NULL;
54 
55 static void
view_show_hide(EmbeddedView * view_data,gboolean activate)56 view_show_hide (EmbeddedView *view_data,
57 		gboolean      activate)
58 {
59   DDisplay *ddisp = view_data->display;
60 
61   if (activate) {
62     toolbox_show();
63 
64     display_rulers_show(ddisp);
65     gtk_widget_show(ddisp->hsb);
66     gtk_widget_show(ddisp->vsb);
67     gtk_widget_show(ddisp->zoom_status->parent);
68     gtk_widget_show(ddisp->modified_status);
69   } else {
70     toolbox_hide();
71 
72     display_rulers_hide(ddisp);
73     gtk_widget_hide(ddisp->hsb);
74     gtk_widget_hide(ddisp->vsb);
75     gtk_widget_hide(ddisp->zoom_status->parent);
76     gtk_widget_hide(ddisp->modified_status);
77   }
78 }
79 
80 static void
dia_view_activate(BonoboView * view,gboolean activate,EmbeddedView * view_data)81 dia_view_activate(BonoboView *view, gboolean activate,
82 		  EmbeddedView *view_data)
83 {
84   bonobo_view_activate_notify(view, activate);
85   view_show_hide(view_data,activate);
86 }
87 
88 static void
dia_view_display_destroy(GtkWidget * ddisp_shell,EmbeddedView * view_data)89 dia_view_display_destroy (GtkWidget *ddisp_shell, EmbeddedView *view_data)
90 {
91   view_data->display = NULL;
92   bonobo_object_unref(BONOBO_OBJECT(view_data->view));
93 }
94 
95 static void
dia_view_destroy(BonoboView * view,EmbeddedView * view_data)96 dia_view_destroy (BonoboView *view, EmbeddedView *view_data)
97 {
98   if (view_data->display)
99     ddisplay_destroy(view_data->display->shell, view_data->display);
100   g_free(view_data);
101 }
102 
103 static void
dia_embeddable_destroy(BonoboEmbeddable * embeddable,EmbeddedDia * embedded_dia)104 dia_embeddable_destroy(BonoboEmbeddable *embeddable,
105 		       EmbeddedDia *embedded_dia)
106 {
107   Diagram *dia = embedded_dia->diagram;
108   DDisplay *ddisp;
109 
110   /* Destroy all views: */
111   while (dia->displays) {
112     ddisp = (DDisplay *)dia->displays->data;
113     gtk_widget_destroy(ddisp->shell);
114   }
115 
116   diagram_destroy(embedded_dia->diagram);
117   g_free(embedded_dia);
118 }
119 
120 static void
dia_view_system_exception(BonoboView * view,CORBA_Object corba_object,CORBA_Environment * ev,gpointer data)121 dia_view_system_exception(BonoboView *view, CORBA_Object corba_object,
122 			  CORBA_Environment *ev, gpointer data)
123 {
124   bonobo_object_unref(BONOBO_OBJECT(view));
125 }
126 
127 static void
dia_embeddable_system_exception(BonoboEmbeddable * embeddable,CORBA_Object corba_object,CORBA_Environment * ev,gpointer data)128 dia_embeddable_system_exception(BonoboEmbeddable *embeddable, CORBA_Object corba_object,
129 				CORBA_Environment *ev, gpointer data)
130 {
131   bonobo_object_unref(BONOBO_OBJECT(embeddable));
132 }
133 
134 static BonoboView *
view_factory(BonoboEmbeddable * embeddable,const Bonobo_ViewFrame view_frame,EmbeddedDia * embedded_dia)135 view_factory (BonoboEmbeddable *embeddable,
136 	      const Bonobo_ViewFrame view_frame,
137 	      EmbeddedDia *embedded_dia)
138 {
139   EmbeddedView *view_data;
140   BonoboView  *view;
141 
142   /*
143    * Create the private view data.
144    */
145   view_data = g_new0 (EmbeddedView, 1);
146   view_data->embedded_dia = embedded_dia;
147 
148   view_data->display = new_display(embedded_dia->diagram);
149 
150   view_show_hide (view_data, FALSE);
151 
152   g_signal_connect (GTK_OBJECT (view_data->display->shell), "destroy",
153 		    G_CALLBACK (dia_view_display_destroy),
154                       view_data);
155 
156   view = bonobo_view_new (view_data->display->shell);
157   view_data->view = view;
158   gtk_object_set_data (GTK_OBJECT (view), "view_data", view_data);
159 
160   g_signal_connect(GTK_OBJECT (view), "activate",
161 		   G_CALLBACK (dia_view_activate), view_data);
162 
163   g_signal_connect(GTK_OBJECT (view), "system_exception",
164 		   G_CALLBACK (dia_view_system_exception), view_data);
165 
166   g_signal_connect (GTK_OBJECT (view), "destroy",
167 		    G_CALLBACK (dia_view_destroy), view_data);
168 
169 
170 #if 0
171   menuitem = menus_get_item_from_path("<Display>/File/New diagram");
172   gtk_widget_hide(menuitem);
173   menuitem = menus_get_item_from_path("<Display>/File/Open...");
174   gtk_widget_hide(menuitem);
175   menuitem = menus_get_item_from_path("<Display>/File/Save As...");
176   gtk_widget_hide(menuitem);
177   menuitem = menus_get_item_from_path("<Display>/File/Close");
178   gtk_widget_hide(menuitem);
179   menuitem = menus_get_item_from_path("<Display>/File/Exit");
180   gtk_widget_hide(menuitem);
181   menuitem = menus_get_item_from_path("<Display>/View/New View");
182   gtk_widget_hide(menuitem);
183 #endif
184 
185   return view;
186 }
187 
188 static int
save_fn(BonoboPersistFile * pf,const CORBA_char * filename,CORBA_Environment * ev,void * closure)189 save_fn (BonoboPersistFile *pf,
190 	 const CORBA_char  *filename,
191 	 CORBA_Environment *ev,
192 	 void              *closure)
193 {
194   EmbeddedDia *dia = closure;
195 
196   if (!diagram_save (dia->diagram, filename))
197     CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
198 			 ex_Bonobo_Storage_IOError, NULL);
199   return 0;
200 }
201 
202 static void
refresh_view(DDisplay * ddisp)203 refresh_view (DDisplay *ddisp)
204 {
205   Point        middle;
206   Rectangle   *visible;
207 
208   visible = &ddisp->visible;
209   middle.x = visible->left*0.5 + visible->right*0.5;
210   middle.y = visible->top*0.5 + visible->bottom*0.5;
211 
212   ddisplay_zoom(ddisp, &middle, 1.0);
213   gtk_widget_queue_draw(ddisp->shell);
214 }
215 
216 static int
load_fn(BonoboPersistFile * pf,const CORBA_char * filename,CORBA_Environment * ev,void * closure)217 load_fn (BonoboPersistFile *pf,
218 	 const CORBA_char  *filename,
219 	 CORBA_Environment *ev,
220 	 void              *closure)
221 {
222   EmbeddedDia *dia = closure;
223 
224   if (!diagram_load_into (dia->diagram, filename, NULL)) {
225 	  g_warning ("Failed to load '%s'", filename);
226 	  CORBA_exception_set (ev, CORBA_USER_EXCEPTION,
227 			       ex_Bonobo_Persist_WrongDataType,
228 			       NULL);
229   } else {
230 	  GSList *l;
231 	  diagram_update_extents(dia->diagram);
232 	  for (l=dia->diagram->displays;l;l=l->next)
233 		  refresh_view (l->data);
234   }
235   return 0;
236 }
237 
238 #ifdef GNOME_PRINT
239 static void
object_print(GnomePrintContext * ctx,double width,double height,const Bonobo_PrintScissor * scissor,gpointer user_data)240 object_print (GnomePrintContext         *ctx,
241 	      double                     width,
242 	      double                     height,
243 	      const Bonobo_PrintScissor *scissor,
244 	      gpointer                   user_data)
245 {
246   RendererGPrint *rend;
247   EmbeddedDia    *edia = user_data;
248   Diagram        *dia = edia->diagram;
249   Rectangle      *extents;
250   double          scalex, scaley;
251 
252   rend = new_gnomeprint_renderer(dia, ctx);
253 
254   /*
255    * FIXME: we need to de-complicate all this - this should
256    * probably be done by scaling the view to the extent or
257    * alternatively keeping the visible bounds on the embeddable
258    * not the view; or possibly none of these.
259    */
260   extents = &dia->data->extents;
261 
262   scalex = width / (extents->right - extents->left);
263   scaley = -height / (extents->bottom - extents->top);
264 
265   gnome_print_translate (ctx, - scalex* extents->left,
266 			 height - scaley * extents->top);
267   gnome_print_scale     (ctx, scalex, scaley);
268 
269 
270   data_render(dia->data, (Renderer *)rend, extents, NULL, NULL);
271 
272   g_free (rend);
273 }
274 #endif
275 
276 static BonoboObject *
embeddable_factory(BonoboGenericFactory * this,void * data)277 embeddable_factory (BonoboGenericFactory *this,
278 		    void *data)
279 {
280   BonoboPersistFile *pfile;
281   BonoboEmbeddable  *embeddable;
282   BonoboPrint       *print;
283   EmbeddedDia       *embedded_dia;
284 
285   embedded_dia = g_new0 (EmbeddedDia, 1);
286   if (embedded_dia == NULL)
287 	  return NULL;
288 
289   embedded_dia->diagram = new_diagram("foobar_embedd");
290 
291   embeddable = bonobo_embeddable_new (BONOBO_VIEW_FACTORY (view_factory),
292 				      embedded_dia);
293 
294   if (embeddable == NULL) {
295     diagram_destroy (embedded_dia->diagram);
296     return NULL;
297   }
298 
299   embedded_dia->embeddable = embeddable;
300 
301   g_signal_connect(GTK_OBJECT(embeddable), "system_exception",
302 		   G_CALLBACK (dia_embeddable_system_exception),
303 		     embedded_dia);
304 
305   g_signal_connect(GTK_OBJECT(embeddable), "destroy",
306 		   G_CALLBACK (dia_embeddable_destroy),
307 		     embedded_dia);
308 
309   /* Register the Bonobo::PersistFile interface. */
310   pfile = bonobo_persist_file_new (load_fn, save_fn, embedded_dia);
311   bonobo_object_add_interface (
312 	  BONOBO_OBJECT (embeddable),
313 	  BONOBO_OBJECT (pfile));
314 
315 #ifdef GNOME_PRINT
316   /* Register the Bonobo::Print interface */
317   print = bonobo_print_new (object_print, embedded_dia);
318   if (!print) {
319 	  bonobo_object_unref (BONOBO_OBJECT (embeddable));
320 	  return NULL;
321   }
322 
323   bonobo_object_add_interface (BONOBO_OBJECT (embeddable),
324 			       BONOBO_OBJECT (print));
325 #endif
326 
327   return BONOBO_OBJECT (embeddable);
328 }
329 
330 static BonoboGenericFactory *
init_dia_factory(void)331 init_dia_factory (void)
332 {
333   return bonobo_generic_factory_new ("OAFIID:GNOME_Dia_DiagramFactory",
334 				     embeddable_factory, NULL);
335 }
336 
337 static void
init_server_factory(int argc,char ** argv)338 init_server_factory (int argc, char **argv)
339 {
340   CORBA_ORB orb;
341 
342   gnome_init_with_popt_table ("dia-embedd", VERSION,
343 			      argc, argv, oaf_popt_options, 0, NULL);
344 
345   orb = oaf_init (argc, argv);
346 
347   if (bonobo_init (orb, NULL, NULL) == FALSE)
348     g_error (_("Could not initialize Bonobo!"));
349   bonobo_activate ();
350 }
351 
352 int
app_is_embedded(void)353 app_is_embedded(void)
354 {
355   return 1;
356 }
357 
358 static void
last_unref_cb(BonoboObject * bonobo_object,gpointer dummy)359 last_unref_cb (BonoboObject *bonobo_object,
360 	       gpointer      dummy)
361 {
362   bonobo_object_unref (BONOBO_OBJECT (factory));
363   gtk_main_quit ();
364 }
365 
366 int
main(int argc,char ** argv)367 main (int argc, char **argv)
368 {
369   GtkWidget *menuitem;
370 
371   init_server_factory (argc, argv);
372   factory = init_dia_factory ();
373 
374   app_init(0, NULL);
375   app_splash_done();
376 
377 /*
378    The hiding of some of our menu entries is necessary to
379    adapt to the 'run-embeded' case, e.g. no File/(New|Open|Exit)
380    because these would conflict with the embedder's menu entries.
381  */
382 #ifdef GNOME
383   menuitem = menus_get_item("/ToolboxMenu/File/FileNew");
384   gtk_widget_hide(menuitem);
385   menuitem = menus_get_item("/ToolboxMenu/File/FileOpen");
386   gtk_widget_hide(menuitem);
387   menuitem = menus_get_item("/ToolboxMenu/File/FileExit");
388   gtk_widget_hide(menuitem);
389 #else
390   menuitem = menus_get_item("/ToolboxMenu/File/FileNew");
391   gtk_widget_hide(menuitem);
392   menuitem = menus_get_item("/ToolboxMenu/File/FileOpen");
393   gtk_widget_hide(menuitem);
394   menuitem = menus_get_item("/ToolboxMenu/File/FileSep1");
395   gtk_widget_hide(menuitem);
396   menuitem = menus_get_item("/ToolboxMenu/File/FileQuit");
397   gtk_widget_hide(menuitem);
398 #endif
399 
400   g_signal_connect (GTK_OBJECT (bonobo_context_running_get ()),
401 		      "last_unref",
402 		    G_CALLBACK (last_unref_cb),
403 		      NULL);
404   /*
405    * Start processing.
406    */
407   bonobo_main ();
408 
409   return 0;
410 }
411 
412