re-adding .pngs as binary
[dia.git] / app / display.c
blobfd068a42758db147719885172372a0407c91d840
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
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.
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.
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.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <string.h>
24 #include <stdio.h>
25 #include <math.h>
27 #ifdef GNOME
28 #include <gnome.h>
29 #endif
31 #include "intl.h"
33 #include "display.h"
34 #include "group.h"
35 #include "interface.h"
36 #include "color.h"
37 #include "handle_ops.h"
38 #include "connectionpoint_ops.h"
39 #include "menus.h"
40 #include "cut_n_paste.h"
41 #include "message.h"
42 #include "preferences.h"
43 #include "app_procs.h"
44 #include "layer_dialog.h"
45 #include "load_save.h"
46 #include "dia-props.h"
48 #ifdef THIS_IS_PROBABLY_DEAD_CODE
49 #include "pixmaps/snap-to-grid.xpm"
50 #include "pixmaps/snap-to-grid-mask.xpm"
51 #endif
53 static GHashTable *display_ht = NULL;
54 static GdkCursor *current_cursor = NULL;
56 GdkCursor *default_cursor = NULL;
58 static DDisplay *active_display = NULL;
61 typedef struct _IRectangle {
62 int top, bottom;
63 int left,right;
64 } IRectangle;
66 static guint display_hash(DDisplay *ddisp);
68 static GtkPixmap *snapping;
69 #ifdef THIS_IS_PROBABLY_DEAD_CODE
70 static GtkPixmap *not_snapping;
71 #endif
73 GtkPixmap *
74 snap_status_load_images(GdkWindow *window)
76 #ifdef THIS_IS_PROBABLY_DEAD_CODE
77 GdkPixmap *dpix;
78 GdkBitmap *mask = NULL;
80 dpix = gdk_pixmap_create_from_xpm_d(window, &mask, NULL, snap_to_grid_xpm);
81 g_assert(dpix != NULL);
83 snapping = gtk_pixmap_new(dpix, mask);
84 g_assert(snapping != NULL);
86 gdk_pixmap_unref(dpix);
87 gdk_pixmap_unref(mask);
89 dpix = gdk_pixmap_create_from_data(window, data, width, height);
90 mask = gdk_pixmap_create_from_data(window, mask, width, height);
91 g_assert(dpix != NULL && mask != NULL);
93 snapping = gdk_image_new(dpix, mask);
94 g_assert(snapping != NULL);
96 gdk_pixmap_unref(dpix);
97 gdk_pixmap_unref(mask);
99 #endif
100 return snapping;
103 static void
104 update_snap_status(DDisplay *ddisp)
106 #ifdef THIS_IS_PROBABLY_DEAD_CODE
107 GtkButton *zoomimage = GTK_BUTTON(ddisp->snap_status);
108 return;
109 if (ddisp->grid.snap) {
111 } else {
113 #endif
116 static void
117 update_zoom_status(DDisplay *ddisp)
119 #ifndef WITHOUT_ZOOM_COMBO
120 GtkCombo *zoomcombo;
121 gchar zoom_text[7];
123 zoomcombo = GTK_COMBO(ddisp->zoom_status);
124 sprintf (zoom_text, "%.1f%%",
125 ddisp->zoom_factor * 100.0 / DDISPLAY_NORMAL_ZOOM);
126 gtk_entry_set_text(GTK_ENTRY(zoomcombo->entry), zoom_text);
128 #else
129 /* HB: if the combo above ever get's the focus, the window
130 * hotkeys won't work anymore; plus IHMO it clutters the UI
131 * and isn't the useful anyway ...
133 GtkStatusbar *statusbar;
134 guint context_id;
135 gchar *zoom_text;
137 statusbar = GTK_STATUSBAR (ddisp->zoom_status);
138 context_id = gtk_statusbar_get_context_id (statusbar, "Zoom");
140 gtk_statusbar_pop (statusbar, context_id);
141 zoom_text = g_malloc (sizeof (guchar) * (strlen (_("Zoom")) + 1 + 8 + 1));
142 sprintf (zoom_text, "%s % 7.1f%c", _("Zoom"),
143 ddisp->zoom_factor * 100.0 / DDISPLAY_NORMAL_ZOOM, '%');
144 gtk_statusbar_push (statusbar, context_id, zoom_text);
146 g_free (zoom_text);
147 #endif
150 static void
151 update_modified_status(DDisplay *ddisp)
153 GtkStatusbar *statusbar;
154 guint context_id;
156 if (ddisp->diagram->modified)
158 statusbar = GTK_STATUSBAR (ddisp->modified_status);
159 context_id = gtk_statusbar_get_context_id (statusbar, "Changed");
161 gtk_statusbar_pop (statusbar, context_id);
162 gtk_statusbar_push (statusbar, context_id, _("Diagram modified!"));
164 else
166 statusbar = GTK_STATUSBAR (ddisp->modified_status);
167 context_id = gtk_statusbar_get_context_id (statusbar, "Changed");
169 gtk_statusbar_pop (statusbar, context_id);
173 DDisplay *
174 new_display(Diagram *dia)
176 DDisplay *ddisp;
177 char *filename;
178 int embedded = app_is_embedded();
179 Rectangle visible;
181 ddisp = g_new0(DDisplay,1);
183 ddisp->menu_bar = NULL;
184 ddisp->mbar_item_factory = NULL;
186 ddisp->rulers = NULL;
187 ddisp->visible_grid = NULL;
188 ddisp->snap_to_grid = NULL;
189 ddisp->show_cx_pts_mitem = NULL;
190 #ifdef HAVE_LIBART
191 ddisp->antialiased = NULL;
192 #endif
193 /* initialize the whole struct to 0 so that we are sure to catch errors.*/
194 memset (&ddisp->updatable_menu_items, 0, sizeof (UpdatableMenuItems));
196 ddisp->diagram = dia;
198 ddisp->grid.visible = prefs.grid.visible;
199 ddisp->grid.snap = prefs.grid.snap;
201 ddisp->show_cx_pts = prefs.show_cx_pts;
203 ddisp->autoscroll = TRUE;
205 ddisp->aa_renderer = 0;
206 ddisp->renderer = (Renderer *)new_gdk_renderer(ddisp);
208 ddisp->update_areas = NULL;
209 ddisp->display_areas = NULL;
210 ddisp->update_id = 0;
212 filename = strrchr(dia->filename, G_DIR_SEPARATOR);
213 if (filename==NULL) {
214 filename = dia->filename;
215 } else {
216 filename++;
219 diagram_add_ddisplay(dia, ddisp);
221 ddisp->origo.x = 0.0;
222 ddisp->origo.y = 0.0;
223 ddisp->zoom_factor = prefs.new_view.zoom/100.0*DDISPLAY_NORMAL_ZOOM;
224 if ((ddisp->diagram) && (ddisp->diagram->data)) {
225 Rectangle *extents = &ddisp->diagram->data->extents;
227 visible.left = extents->left;
228 visible.top = extents->top;
229 } else {
230 visible.left = 0.0;
231 visible.top = 0.0;
233 visible.right = visible.left + prefs.new_view.width/ddisp->zoom_factor;
234 visible.bottom = visible.top + prefs.new_view.height/ddisp->zoom_factor;
236 ddisp->visible = visible;
238 create_display_shell(ddisp, prefs.new_view.width, prefs.new_view.height,
239 filename, prefs.new_view.use_menu_bar, !embedded);
242 ddisplay_update_statusbar (ddisp);
244 ddisplay_set_origo(ddisp, visible.left, visible.top);
245 ddisp->visible = visible; /* force the visible area extents */
246 ddisplay_update_scrollbars(ddisp);
247 ddisplay_add_update_all(ddisp);
249 if (!display_ht)
250 display_ht = g_hash_table_new ((GHashFunc) display_hash, NULL);
252 if (!embedded)
253 ddisplay_set_cursor(ddisp, current_cursor);
255 g_hash_table_insert (display_ht, ddisp->shell, ddisp);
256 g_hash_table_insert (display_ht, ddisp->canvas, ddisp);
259 return ddisp; /* set the user data */
262 static guint
263 display_hash(DDisplay *ddisp)
265 return (gulong) ddisp;
268 void
269 ddisplay_transform_coords_double(DDisplay *ddisp,
270 coord x, coord y,
271 double *xi, double *yi)
273 Rectangle *visible = &ddisp->visible;
274 double width = ddisp->renderer->pixel_width;
275 double height = ddisp->renderer->pixel_height;
277 *xi = (x - visible->left) * (real)width / (visible->right - visible->left);
278 *yi = (y - visible->top) * (real)height / (visible->bottom - visible->top);
282 void
283 ddisplay_transform_coords(DDisplay *ddisp,
284 coord x, coord y,
285 int *xi, int *yi)
287 Rectangle *visible = &ddisp->visible;
288 int width = ddisp->renderer->pixel_width;
289 int height = ddisp->renderer->pixel_height;
291 *xi = ROUND ( (x - visible->left) * (real)width /
292 (visible->right - visible->left) );
293 *yi = ROUND ( (y - visible->top) * (real)height /
294 (visible->bottom - visible->top) );
297 /* Takes real length and returns pixel length */
298 real
299 ddisplay_transform_length(DDisplay *ddisp, real len)
301 return len * ddisp->zoom_factor;
304 /* Takes pixel length and returns real length */
305 real
306 ddisplay_untransform_length(DDisplay *ddisp, real len)
308 return len / ddisp->zoom_factor;
312 void
313 ddisplay_untransform_coords(DDisplay *ddisp,
314 int xi, int yi,
315 coord *x, coord *y)
317 Rectangle *visible = &ddisp->visible;
318 int width = ddisp->renderer->pixel_width;
319 int height = ddisp->renderer->pixel_height;
321 *x = visible->left + xi*(visible->right - visible->left) / (real)width;
322 *y = visible->top + yi*(visible->bottom - visible->top) / (real)height;
326 void
327 ddisplay_add_update_pixels(DDisplay *ddisp, Point *point,
328 int pixel_width, int pixel_height)
330 Rectangle rect;
331 real size_x, size_y;
333 size_x = ddisplay_untransform_length(ddisp, pixel_width+1);
334 size_y = ddisplay_untransform_length(ddisp, pixel_height+1);
336 rect.left = point->x - size_x/2.0;
337 rect.top = point->y - size_y/2.0;
338 rect.right = point->x + size_x/2.0;
339 rect.bottom = point->y + size_y/2.0;
341 ddisplay_add_update(ddisp, &rect);
344 void
345 ddisplay_add_update_all(DDisplay *ddisp)
347 ddisplay_add_update(ddisp, &ddisp->visible);
350 void
351 ddisplay_add_update(DDisplay *ddisp, Rectangle *rect)
353 Rectangle *r;
354 int top,bottom,left,right;
355 Rectangle *visible;
356 int width = ddisp->renderer->pixel_width;
357 int height = ddisp->renderer->pixel_height;
359 if (!rectangle_intersects(rect, &ddisp->visible))
360 return;
362 /* Temporarily just do a union of all rectangles: */
363 if (ddisp->update_areas==NULL) {
364 r = g_new(Rectangle,1);
365 *r = *rect;
366 rectangle_intersection(r, &ddisp->visible);
367 ddisp->update_areas = g_slist_prepend(ddisp->update_areas, r);
368 } else {
369 r = (Rectangle *) ddisp->update_areas->data;
370 rectangle_union(r, rect);
371 rectangle_intersection(r, &ddisp->visible);
374 visible = &ddisp->visible;
375 left = floor( (r->left - visible->left) * (real)width /
376 (visible->right - visible->left) ) - 1;
377 top = floor( (r->top - visible->top) * (real)height /
378 (visible->bottom - visible->top) ) - 1;
379 right = ceil( (r->right - visible->left) * (real)width /
380 (visible->right - visible->left) ) + 1;
381 bottom = ceil( (r->bottom - visible->top) * (real)height /
382 (visible->bottom - visible->top) ) + 1;
384 ddisplay_add_display_area(ddisp,
385 left, top,
386 right, bottom);
389 void
390 ddisplay_add_display_area(DDisplay *ddisp,
391 int left, int top,
392 int right, int bottom)
394 IRectangle *r;
396 if (left < 0)
397 left = 0;
398 if (top < 0)
399 top = 0;
400 if (right > ddisp->renderer->pixel_width)
401 right = ddisp->renderer->pixel_width;
402 if (bottom > ddisp->renderer->pixel_height)
403 bottom = ddisp->renderer->pixel_height;
405 /* draw some rectangles to show where updates are...*/
406 /* gdk_draw_rectangle(ddisp->canvas->window, ddisp->canvas->style->black_gc, TRUE, left, top, right-left,bottom-top); */
408 /* Temporarily just do a union of all Irectangles: */
409 if (ddisp->display_areas==NULL) {
410 r = g_new(IRectangle,1);
411 r->top = top; r->bottom = bottom;
412 r->left = left; r->right = right;
413 ddisp->display_areas = g_slist_prepend(ddisp->display_areas, r);
414 } else {
415 r = (IRectangle *) ddisp->display_areas->data;
417 r->top = MIN( r->top, top );
418 r->bottom = MAX( r->bottom, bottom );
419 r->left = MIN( r->left, left );
420 r->right = MAX( r->right, right );
424 static gint
425 ddisplay_update_handler(DDisplay *ddisp)
427 GSList *l;
428 IRectangle *ir;
429 Rectangle *r, totrect;
430 Renderer *renderer;
432 /* Renders updates to pixmap + copies display_areas to canvas(screen) */
434 renderer = ddisp->renderer;
436 (renderer->interactive_ops->clip_region_clear)(renderer);
438 l = ddisp->update_areas;
439 if (l==NULL)
440 totrect = ddisp->visible;
441 else
442 totrect = *(Rectangle *) l->data;
444 while(l!=NULL) {
445 r = (Rectangle *) l->data;
447 rectangle_union(&totrect, r);
448 (renderer->interactive_ops->clip_region_add_rect)(renderer, r);
450 l = g_slist_next(l);
453 /* Free update_areas list: */
454 l = ddisp->update_areas;
455 while(l!=NULL) {
456 g_free(l->data);
457 l = g_slist_next(l);
459 g_slist_free(ddisp->update_areas);
460 ddisp->update_areas = NULL;
462 totrect.left -= 0.1;
463 totrect.right += 0.1;
464 totrect.top -= 0.1;
465 totrect.bottom += 0.1;
467 ddisplay_render_pixmap(ddisp, &totrect);
469 l = ddisp->display_areas;
470 while(l!=NULL) {
471 ir = (IRectangle *) l->data;
473 if (ddisp->aa_renderer)
474 renderer_libart_copy_to_window((RendererLibart *)ddisp->renderer, ddisp->canvas->window,
475 ir->left, ir->top,
476 ir->right - ir->left, ir->bottom - ir->top);
477 else
478 renderer_gdk_copy_to_window((RendererGdk *)ddisp->renderer, ddisp->canvas->window,
479 ir->left, ir->top,
480 ir->right - ir->left, ir->bottom - ir->top);
482 l = g_slist_next(l);
485 /* Free display_areas list */
486 l = ddisp->display_areas;
487 while(l!=NULL) {
488 g_free(l->data);
489 l = g_slist_next(l);
491 g_slist_free(ddisp->display_areas);
492 ddisp->display_areas = NULL;
494 ddisp->update_id = 0;
495 return FALSE;
498 void
499 ddisplay_flush(DDisplay *ddisp)
501 /* if no update is queued, queue update */
502 if (!ddisp->update_id)
503 ddisp->update_id = gtk_idle_add((GtkFunction) ddisplay_update_handler,
504 ddisp);
507 static void
508 ddisplay_obj_render(Object *obj, Renderer *renderer,
509 int active_layer,
510 gpointer data)
512 DDisplay *ddisp = (DDisplay *)data;
513 int i;
515 obj->ops->draw(obj, renderer);
516 if (active_layer && ddisp->show_cx_pts) {
517 for (i=0;i<obj->num_connections;i++) {
518 connectionpoint_draw(obj->connections[i], ddisp);
523 void
524 ddisplay_render_pixmap(DDisplay *ddisp, Rectangle *update)
526 GList *list;
527 Object *obj;
528 int i;
529 Renderer *renderer;
531 if (ddisp->renderer==NULL) {
532 printf("ERROR! Renderer was NULL!!\n");
533 return;
536 renderer = ddisp->renderer;
538 /* Erase background */
539 (renderer->interactive_ops->fill_pixel_rect)(renderer,
540 0, 0,
541 renderer->pixel_width-1,
542 renderer->pixel_height-1,
543 &ddisp->diagram->data->bg_color);
545 /* Draw grid */
546 grid_draw(ddisp, update);
548 data_render(ddisp->diagram->data, (Renderer *)ddisp->renderer, update,
549 ddisplay_obj_render, (gpointer) ddisp);
551 /* Draw handles for all selected objects */
552 list = ddisp->diagram->data->selected;
553 while (list!=NULL) {
554 obj = (Object *) list->data;
556 for (i=0;i<obj->num_handles;i++) {
557 handle_draw(obj->handles[i], ddisp);
559 list = g_list_next(list);
563 void
564 ddisplay_update_scrollbars(DDisplay *ddisp)
566 Rectangle *extents = &ddisp->diagram->data->extents;
567 Rectangle *visible = &ddisp->visible;
568 GtkAdjustment *hsbdata, *vsbdata;
570 hsbdata = ddisp->hsbdata;
571 /* Horizontal: */
572 hsbdata->lower = MIN(extents->left, visible->left);
573 hsbdata->upper = MAX(extents->right, visible->right);
574 hsbdata->page_size = visible->right - visible->left - 0.0001;
575 /* remove some to fix strange behaviour in gtk_range_adjustment_changed */
576 hsbdata->page_increment = (visible->right - visible->left) / 2.0;
577 hsbdata->step_increment = (visible->right - visible->left) / 10.0;
578 hsbdata->value = visible->left;
580 gtk_signal_emit_by_name (GTK_OBJECT (ddisp->hsbdata), "changed");
582 /* Vertical: */
583 vsbdata = ddisp->vsbdata;
584 vsbdata->lower = MIN(extents->top, visible->top);
585 vsbdata->upper = MAX(extents->bottom, visible->bottom);
586 vsbdata->page_size = visible->bottom - visible->top - 0.00001;
587 /* remove some to fix strange behaviour in gtk_range_adjustment_changed */
588 vsbdata->page_increment = (visible->bottom - visible->top) / 2.0;
589 vsbdata->step_increment = (visible->bottom - visible->top) / 10.0;
590 vsbdata->value = visible->top;
592 gtk_signal_emit_by_name (GTK_OBJECT (ddisp->vsbdata), "changed");
595 void
596 ddisplay_set_origo(DDisplay *ddisp, coord x, coord y)
598 Rectangle *extents = &ddisp->diagram->data->extents;
599 Rectangle *visible = &ddisp->visible;
600 int width, height;
602 /* updaterar origo+visible+rulers */
603 ddisp->origo.x = x;
604 ddisp->origo.y = y;
606 if (ddisp->zoom_factor<DDISPLAY_MIN_ZOOM)
607 ddisp->zoom_factor = DDISPLAY_MIN_ZOOM;
609 if (ddisp->zoom_factor > DDISPLAY_MAX_ZOOM)
610 ddisp->zoom_factor = DDISPLAY_MAX_ZOOM;
612 width = ddisp->renderer->pixel_width;
613 height = ddisp->renderer->pixel_height;
615 visible->left = ddisp->origo.x;
616 visible->top = ddisp->origo.y;
617 visible->right = ddisp->origo.x + width/ddisp->zoom_factor;
618 visible->bottom = ddisp->origo.y + height/ddisp->zoom_factor;
620 gtk_ruler_set_range (GTK_RULER (ddisp->hrule),
621 visible->left,
622 visible->right,
623 0.0f /* position*/,
624 MAX(extents->right, visible->right)/* max_size*/);
625 gtk_ruler_set_range (GTK_RULER (ddisp->vrule),
626 visible->top,
627 visible->bottom,
628 0.0f /* position*/,
629 MAX(extents->bottom, visible->bottom)/* max_size*/);
632 void
633 ddisplay_zoom(DDisplay *ddisp, Point *point, real magnify)
635 Rectangle *visible;
636 real width, height;
638 visible = &ddisp->visible;
640 width = (visible->right - visible->left)/magnify;
641 height = (visible->bottom - visible->top)/magnify;
643 if ((ddisp->zoom_factor <= DDISPLAY_MIN_ZOOM) && (magnify<=1.0))
644 return;
645 if ((ddisp->zoom_factor >= DDISPLAY_MAX_ZOOM) && (magnify>=1.0))
646 return;
648 ddisp->zoom_factor *= magnify;
650 ddisplay_set_origo(ddisp, point->x - width/2.0, point->y - height/2.0);
652 ddisplay_update_scrollbars(ddisp);
653 ddisplay_add_update_all(ddisp);
654 ddisplay_flush(ddisp);
656 update_zoom_status (ddisp);
659 gboolean
660 ddisplay_autoscroll(DDisplay *ddisp, int x, int y)
662 guint16 width, height;
663 Point scroll;
665 if (! ddisp->autoscroll)
666 return FALSE;
668 scroll.x = scroll.y = 0;
670 width = GTK_WIDGET(ddisp->canvas)->allocation.width;
671 height = GTK_WIDGET(ddisp->canvas)->allocation.height;
673 if (x < 0)
675 scroll.x = x;
677 else if ( x > width)
679 scroll.x = x - width;
682 if (y < 0)
684 scroll.y = y;
686 else if (y > height)
688 scroll.y = y - height;
691 if ((scroll.x != 0) || (scroll.y != 0))
693 gboolean scrolled;
695 scroll.x = ddisplay_untransform_length(ddisp, scroll.x);
696 scroll.y = ddisplay_untransform_length(ddisp, scroll.y);
698 scrolled = ddisplay_scroll(ddisp, &scroll);
700 if (scrolled) {
701 ddisplay_flush(ddisp);
702 return TRUE;
705 return FALSE;
708 gboolean
709 ddisplay_scroll(DDisplay *ddisp, Point *delta)
711 Rectangle *visible = &ddisp->visible;
712 real width = visible->right - visible->left;
713 real height = visible->bottom - visible->top;
715 Rectangle extents = ddisp->diagram->data->extents;
716 real ex_width = extents.right - extents.left;
717 real ex_height = extents.bottom - extents.top;
719 Point new_origo = ddisp->origo;
720 point_add(&new_origo, delta);
722 rectangle_union(&extents, visible);
724 if (new_origo.x < extents.left - ex_width)
725 new_origo.x = extents.left - ex_width;
727 if (new_origo.x+width > extents.right + ex_width)
728 new_origo.x = extents.right - width + ex_width;
730 if (new_origo.y < extents.top - ex_height)
731 new_origo.y = extents.top - ex_height;
733 if (new_origo.y+height > extents.bottom + ex_height)
734 new_origo.y = extents.bottom - height + ex_height;
736 if ( (new_origo.x != ddisp->origo.x) ||
737 (new_origo.y != ddisp->origo.y) ) {
738 ddisplay_set_origo(ddisp, new_origo.x, new_origo.y);
739 ddisplay_update_scrollbars(ddisp);
740 ddisplay_add_update_all(ddisp);
741 return TRUE;
743 return FALSE;
746 void ddisplay_scroll_up(DDisplay *ddisp)
748 Point delta;
750 delta.x = 0;
751 delta.y = -(ddisp->visible.bottom - ddisp->visible.top)/4.0;
753 ddisplay_scroll(ddisp, &delta);
756 void ddisplay_scroll_down(DDisplay *ddisp)
758 Point delta;
760 delta.x = 0;
761 delta.y = (ddisp->visible.bottom - ddisp->visible.top)/4.0;
763 ddisplay_scroll(ddisp, &delta);
766 void ddisplay_scroll_left(DDisplay *ddisp)
768 Point delta;
770 delta.x = -(ddisp->visible.right - ddisp->visible.left)/4.0;
771 delta.y = 0;
773 ddisplay_scroll(ddisp, &delta);
776 void ddisplay_scroll_right(DDisplay *ddisp)
778 Point delta;
780 delta.x = (ddisp->visible.right - ddisp->visible.left)/4.0;
781 delta.y = 0;
783 ddisplay_scroll(ddisp, &delta);
786 void
787 ddisplay_set_renderer(DDisplay *ddisp, int aa_renderer)
789 int width, height;
791 if (ddisp->aa_renderer) {
792 if (ddisp->renderer)
793 destroy_libart_renderer((RendererLibart *)ddisp->renderer);
794 } else {
795 if (ddisp->renderer)
796 destroy_gdk_renderer((RendererGdk *)ddisp->renderer);
799 ddisp->aa_renderer = aa_renderer;
801 width = ddisp->canvas->allocation.width;
802 height = ddisp->canvas->allocation.height;
804 if (ddisp->aa_renderer){
805 ddisp->renderer = (Renderer *)new_libart_renderer(ddisp, 1);
806 libart_renderer_set_size((RendererLibart *)ddisp->renderer, ddisp->canvas->window, width, height);
807 } else {
808 ddisp->renderer = (Renderer *)new_gdk_renderer(ddisp);
809 gdk_renderer_set_size((RendererGdk *)ddisp->renderer, ddisp->canvas->window, width, height);
813 void
814 ddisplay_resize_canvas(DDisplay *ddisp,
815 int width, int height)
817 if (ddisp->renderer==NULL) {
818 if (ddisp->aa_renderer)
819 ddisp->renderer = (Renderer *)new_libart_renderer(ddisp, 1);
820 else
821 ddisp->renderer = (Renderer *)new_gdk_renderer(ddisp);
824 if (ddisp->aa_renderer)
825 libart_renderer_set_size((RendererLibart *)ddisp->renderer, ddisp->canvas->window, width, height);
826 else
827 gdk_renderer_set_size((RendererGdk *)ddisp->renderer, ddisp->canvas->window, width, height);
829 ddisplay_set_origo(ddisp, ddisp->origo.x, ddisp->origo.y);
831 ddisplay_add_update(ddisp, &ddisp->visible);
832 ddisplay_flush(ddisp);
835 DDisplay *
836 ddisplay_active(void)
838 return active_display;
841 Diagram *
842 ddisplay_active_diagram(void)
844 DDisplay *ddisp = ddisplay_active ();
846 if (!ddisp) return NULL;
847 return ddisp->diagram;
850 static void
851 ddisp_destroy(DDisplay *ddisp)
853 if (ddisp->update_id) {
854 gtk_idle_remove(ddisp->update_id);
855 ddisp->update_id = 0;
857 gtk_widget_destroy (ddisp->shell);
860 static void
861 are_you_sure_close_dialog_cancel(GtkWidget *widget, GtkWidget *dialog)
863 gtk_widget_destroy(dialog);
866 static void
867 are_you_sure_close_dialog_yes(GtkWidget *widget,
868 GtkWidget *dialog)
870 DDisplay *ddisp;
872 ddisp = gtk_object_get_user_data(GTK_OBJECT(dialog));
874 /* save changes */
875 diagram_save(ddisp->diagram, ddisp->diagram->filename);
877 if (ddisp->update_id) {
878 gtk_idle_remove(ddisp->update_id);
879 ddisp->update_id = 0;
882 gtk_widget_destroy(dialog);
883 ddisp_destroy (ddisp);
886 static void
887 are_you_sure_close_dialog_no(GtkWidget *widget,
888 GtkWidget *dialog)
890 DDisplay *ddisp;
892 ddisp = gtk_object_get_user_data(GTK_OBJECT(dialog));
894 gtk_widget_destroy(dialog);
895 ddisp_destroy(ddisp);
898 void
899 ddisplay_close(DDisplay *ddisp)
901 Diagram *dia;
902 GtkWidget *dialog, *vbox;
903 GtkWidget *label;
904 #ifndef GNOME
905 GtkWidget *button;
906 #endif
907 dia = ddisp->diagram;
909 if ( (dia->display_count > 1) ||
910 (!dia->modified) ) {
911 ddisp_destroy(ddisp);
912 return;
915 #ifdef GNOME
916 dialog = gnome_dialog_new(_("Close Diagram?"),
917 GNOME_STOCK_BUTTON_YES,GNOME_STOCK_BUTTON_NO,NULL);
918 gnome_dialog_set_default(GNOME_DIALOG(dialog), 0);
919 vbox = GNOME_DIALOG(dialog)->vbox;
920 #else
921 dialog = gtk_dialog_new();
922 gtk_window_set_title (GTK_WINDOW (dialog), _("Really close?"));
923 gtk_container_set_border_width (GTK_CONTAINER (dialog), 0);
924 vbox = GTK_DIALOG(dialog)->vbox;
925 #endif
927 label = gtk_label_new (_("This diagram has not been saved.\n"
928 "Save changes now?"));
930 gtk_misc_set_padding (GTK_MISC (label), 10, 10);
931 gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
933 gtk_widget_show (label);
935 gtk_object_set_user_data(GTK_OBJECT(dialog), ddisp);
937 #ifdef GNOME
938 gnome_dialog_button_connect(GNOME_DIALOG(dialog), 0,
939 GTK_SIGNAL_FUNC(are_you_sure_close_dialog_yes),
940 dialog);
941 gnome_dialog_button_connect(GNOME_DIALOG(dialog), 1,
942 GTK_SIGNAL_FUNC(are_you_sure_close_dialog_no),
943 dialog);
944 #else
945 button = gtk_button_new_with_label (_("Yes"));
946 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
947 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
948 button, TRUE, TRUE, 0);
949 gtk_widget_grab_default (button);
950 gtk_signal_connect (GTK_OBJECT (button), "clicked",
951 GTK_SIGNAL_FUNC(are_you_sure_close_dialog_yes),
952 dialog);
953 gtk_widget_show (button);
955 button = gtk_button_new_with_label (_("No"));
956 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
957 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
958 button, TRUE, TRUE, 0);
960 gtk_signal_connect (GTK_OBJECT (button), "clicked",
961 GTK_SIGNAL_FUNC(are_you_sure_close_dialog_no),
962 dialog);
964 gtk_widget_show (button);
966 button = gtk_button_new_with_label (_("Cancel"));
967 GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
968 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
969 button, TRUE, TRUE, 0);
971 gtk_signal_connect (GTK_OBJECT (button), "clicked",
972 GTK_SIGNAL_FUNC(are_you_sure_close_dialog_cancel),
973 dialog);
975 gtk_widget_show (button);
976 #endif
978 /* Make dialog modal: */
979 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
981 gtk_widget_show(dialog);
984 void
985 display_update_menu_state(DDisplay *ddisp)
987 static gboolean initialized = 0;
989 static GtkWidget *rulers;
990 static GtkWidget *visible_grid;
991 static GtkWidget *snap_to_grid;
992 static GtkWidget *show_cx_pts;
993 #ifdef HAVE_LIBART
994 static GtkWidget *antialiased;
995 #endif
997 if ((!initialized) && (ddisp->menu_bar == NULL)) {
998 rulers = menus_get_item_from_path("<Display>/View/Show Rulers", NULL);
999 visible_grid = menus_get_item_from_path("<Display>/View/Visible Grid", NULL);
1000 snap_to_grid = menus_get_item_from_path("<Display>/View/Snap To Grid", NULL);
1001 show_cx_pts =
1002 menus_get_item_from_path("<Display>/View/Show Connection Points", NULL);
1003 #ifdef HAVE_LIBART
1004 antialiased = menus_get_item_from_path("<Display>/View/AntiAliased", NULL);
1005 #endif
1007 initialized = TRUE;
1009 ddisplay_do_update_menu_sensitivity (ddisp);
1011 if (ddisp->menu_bar) {
1012 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ddisp->rulers),
1013 GTK_WIDGET_VISIBLE (ddisp->hrule) ? 1 : 0);
1014 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ddisp->visible_grid),
1015 ddisp->grid.visible);
1016 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ddisp->snap_to_grid),
1017 ddisp->grid.snap);
1018 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ddisp->show_cx_pts_mitem),
1019 ddisp->show_cx_pts);
1020 #ifdef HAVE_LIBART
1021 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(ddisp->antialiased),
1022 ddisp->aa_renderer);
1023 #endif
1025 else {
1026 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(rulers),
1027 GTK_WIDGET_VISIBLE (ddisp->hrule) ? 1 : 0);
1028 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(visible_grid),
1029 ddisp->grid.visible);
1030 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(snap_to_grid),
1031 ddisp->grid.snap);
1032 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(show_cx_pts),
1033 ddisp->show_cx_pts);
1034 #ifdef HAVE_LIBART
1035 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(antialiased),
1036 ddisp->aa_renderer);
1037 #endif
1041 void
1042 ddisplay_do_update_menu_sensitivity (DDisplay *ddisp)
1044 Diagram *dia;
1046 dia = ddisp->diagram;
1047 if (ddisp->menu_bar) {
1048 diagram_update_menubar_sensitivity(dia, &ddisp->updatable_menu_items);
1050 else {
1051 diagram_update_popupmenu_sensitivity(dia);
1057 /* This is called when ddisp->shell is destroyed... */
1058 void
1059 ddisplay_really_destroy(DDisplay *ddisp)
1061 Diagram *dia;
1062 GSList *l;
1064 if (active_display == ddisp)
1065 display_set_active(NULL);
1067 dia = ddisp->diagram;
1069 diagram_remove_ddisplay(dia, ddisp);
1071 if (ddisp->aa_renderer)
1072 destroy_libart_renderer((RendererLibart *)ddisp->renderer);
1073 else
1074 destroy_gdk_renderer((RendererGdk *)ddisp->renderer);
1076 ddisp->renderer = NULL;
1078 g_hash_table_remove(display_ht, ddisp->shell);
1079 g_hash_table_remove(display_ht, ddisp->canvas);
1081 /* Free update_areas list: */
1082 l = ddisp->update_areas;
1083 while(l!=NULL) {
1084 g_free(l->data);
1085 l = g_slist_next(l);
1087 g_slist_free(ddisp->update_areas);
1088 /* Free display_areas list */
1089 l = ddisp->display_areas;
1090 while(l!=NULL) {
1091 g_free(l->data);
1092 l = g_slist_next(l);
1094 g_slist_free(ddisp->display_areas);
1097 g_free(ddisp);
1101 void
1102 ddisplay_set_title(DDisplay *ddisp, char *title)
1104 gtk_window_set_title (GTK_WINDOW (ddisp->shell), title);
1107 void
1108 ddisplay_set_all_cursor(GdkCursor *cursor)
1110 Diagram *dia;
1111 DDisplay *ddisp;
1112 GList *list;
1113 GSList *slist;
1115 current_cursor = cursor;
1117 list = open_diagrams;
1118 while (list != NULL) {
1119 dia = (Diagram *) list->data;
1121 slist = dia->displays;
1122 while (slist != NULL) {
1123 ddisp = (DDisplay *) slist->data;
1125 ddisplay_set_cursor(ddisp, cursor);
1127 slist = g_slist_next(slist);
1130 list = g_list_next(list);
1134 void
1135 ddisplay_set_cursor(DDisplay *ddisp, GdkCursor *cursor)
1137 gdk_window_set_cursor(ddisp->canvas->window, cursor);
1140 void
1141 ddisplay_update_statusbar(DDisplay *ddisp)
1143 /* update_snap_status (ddisp);*/
1144 update_zoom_status (ddisp);
1145 update_modified_status (ddisp);
1148 void
1149 display_set_active(DDisplay *ddisp)
1151 if (ddisp != active_display) {
1152 active_display = ddisp;
1154 /* perform notification here (such as switch layers dialog) */
1155 layer_dialog_set_diagram(ddisp ? ddisp->diagram : NULL);
1156 diagram_properties_set_diagram(ddisp ? ddisp->diagram : NULL);
1158 if (ddisp)
1159 display_update_menu_state(ddisp);