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.
26 #include <gdk/gdkkeysyms.h>
36 #include "interface.h"
39 #include "handle_ops.h"
40 #include "connectionpoint_ops.h"
42 #include "cut_n_paste.h"
44 #include "preferences.h"
45 #include "app_procs.h"
46 #include "layer_dialog.h"
47 #include "load_save.h"
48 #include "dia-props.h"
49 #include "render_gdk.h"
50 #include "render_libart.h"
52 static GHashTable
*display_ht
= NULL
;
53 static GdkCursor
*current_cursor
= NULL
;
55 GdkCursor
*default_cursor
= NULL
;
57 static DDisplay
*active_display
= NULL
;
60 typedef struct _IRectangle
{
65 static guint
display_hash(DDisplay
*ddisp
);
68 update_zoom_status(DDisplay
*ddisp
)
73 zoomcombo
= ddisp
->zoom_status
;
74 sprintf (zoom_text
, "%.1f%%",
75 ddisp
->zoom_factor
* 100.0 / DDISPLAY_NORMAL_ZOOM
);
76 gtk_entry_set_text(GTK_ENTRY(gtk_object_get_user_data(GTK_OBJECT(zoomcombo
))),
81 update_modified_status(DDisplay
*ddisp
)
83 GtkStatusbar
*statusbar
;
86 if (diagram_is_modified(ddisp
->diagram
))
88 statusbar
= GTK_STATUSBAR (ddisp
->modified_status
);
89 context_id
= gtk_statusbar_get_context_id (statusbar
, "Changed");
91 gtk_statusbar_pop (statusbar
, context_id
);
92 gtk_statusbar_push (statusbar
, context_id
, _("Diagram modified!"));
96 statusbar
= GTK_STATUSBAR (ddisp
->modified_status
);
97 context_id
= gtk_statusbar_get_context_id (statusbar
, "Changed");
99 gtk_statusbar_pop (statusbar
, context_id
);
104 selection_changed (Diagram
* dia
, int n
, DDisplay
* ddisp
)
106 GtkStatusbar
*statusbar
;
109 statusbar
= GTK_STATUSBAR (ddisp
->modified_status
);
110 context_id
= gtk_statusbar_get_context_id (statusbar
, "Selection");
116 msg
= g_strdup_printf (_("Selection of %d objects"), n
);
117 gtk_statusbar_pop (statusbar
, context_id
);
118 gtk_statusbar_push (statusbar
, context_id
, msg
);
123 /* find the selected objects name - and display it */
124 DiaObject
*object
= (DiaObject
*)ddisp
->diagram
->data
->selected
->data
;
125 gchar
*name
= object_get_displayname (object
);
126 gchar
*msg
= g_strdup_printf (_("Selected '%s'"), name
);
128 gtk_statusbar_pop (statusbar
, context_id
);
129 gtk_statusbar_push (statusbar
, context_id
, msg
);
136 gtk_statusbar_pop (statusbar
, context_id
);
141 new_display(Diagram
*dia
)
145 int embedded
= app_is_embedded();
147 GtkMenuItem
* im_menu_item
;
149 GtkWidget
* im_menu_tearoff
;
150 static gboolean input_methods_done
= FALSE
;
152 ddisp
= g_new0(DDisplay
,1);
154 ddisp
->menu_bar
= NULL
;
155 ddisp
->mbar_item_factory
= NULL
;
157 ddisp
->rulers
= NULL
;
159 ddisp->visible_grid = NULL;
160 ddisp->snap_to_grid = NULL;
161 ddisp->show_cx_pts_mitem = NULL;
163 ddisp->antialiased = NULL;
166 /* initialize the whole struct to 0 so that we are sure to catch errors.*/
167 memset (&ddisp
->updatable_menu_items
, 0, sizeof (UpdatableMenuItems
));
169 ddisp
->diagram
= dia
;
170 /* Every display has it's own reference */
173 ddisp
->grid
.visible
= prefs
.grid
.visible
;
174 ddisp
->grid
.snap
= prefs
.grid
.snap
;
176 ddisp
->show_cx_pts
= prefs
.show_cx_pts
;
178 ddisp
->autoscroll
= TRUE
;
179 ddisp
->mainpoint_magnetism
= TRUE
;
181 ddisp
->aa_renderer
= 0;
182 ddisp
->renderer
= new_gdk_renderer(ddisp
);
184 ddisp
->update_areas
= NULL
;
185 ddisp
->display_areas
= NULL
;
186 ddisp
->update_id
= 0;
188 filename
= strrchr(dia
->filename
, G_DIR_SEPARATOR
);
189 if (filename
==NULL
) {
190 filename
= dia
->filename
;
195 diagram_add_ddisplay(dia
, ddisp
);
196 g_signal_connect (dia
, "selection_changed", G_CALLBACK(selection_changed
), ddisp
);
197 ddisp
->origo
.x
= 0.0;
198 ddisp
->origo
.y
= 0.0;
199 ddisp
->zoom_factor
= prefs
.new_view
.zoom
/100.0*DDISPLAY_NORMAL_ZOOM
;
200 if ((ddisp
->diagram
) && (ddisp
->diagram
->data
)) {
201 Rectangle
*extents
= &ddisp
->diagram
->data
->extents
;
203 visible
.left
= extents
->left
;
204 visible
.top
= extents
->top
;
209 visible
.right
= visible
.left
+ prefs
.new_view
.width
/ddisp
->zoom_factor
;
210 visible
.bottom
= visible
.top
+ prefs
.new_view
.height
/ddisp
->zoom_factor
;
212 ddisp
->visible
= visible
;
214 ddisp
->im_context
= gtk_im_multicontext_new();
215 g_signal_connect (G_OBJECT (ddisp
->im_context
), "commit",
216 G_CALLBACK (ddisplay_im_context_commit
), ddisp
);
217 ddisp
->preedit_string
= NULL
;
218 g_signal_connect (G_OBJECT (ddisp
->im_context
), "preedit_changed",
219 G_CALLBACK (ddisplay_im_context_preedit_changed
),
221 ddisp
->preedit_attrs
= NULL
;
223 create_display_shell(ddisp
, prefs
.new_view
.width
, prefs
.new_view
.height
,
224 filename
, prefs
.new_view
.use_menu_bar
, !embedded
);
226 ddisplay_update_statusbar (ddisp
);
228 ddisplay_set_origo(ddisp
, visible
.left
, visible
.top
);
229 ddisp
->visible
= visible
; /* force the visible area extents */
230 ddisplay_update_scrollbars(ddisp
);
231 ddisplay_add_update_all(ddisp
);
234 display_ht
= g_hash_table_new ((GHashFunc
) display_hash
, NULL
);
237 ddisplay_set_cursor(ddisp
, current_cursor
);
239 g_hash_table_insert (display_ht
, ddisp
->shell
, ddisp
);
240 g_hash_table_insert (display_ht
, ddisp
->canvas
, ddisp
);
243 if (!input_methods_done
) {
244 im_menu_item
= menus_get_item_from_path("<Display>/Input Methods", NULL
);
246 im_menu
= gtk_menu_new();
247 im_menu_tearoff
= gtk_tearoff_menu_item_new();
248 gtk_menu_shell_append(GTK_MENU_SHELL(im_menu
),im_menu_tearoff
);
249 gtk_im_multicontext_append_menuitems(
250 GTK_IM_MULTICONTEXT(ddisp
->im_context
),
251 GTK_MENU_SHELL(im_menu
));
253 gtk_menu_item_set_submenu( GTK_MENU_ITEM(im_menu_item
), im_menu
);
254 input_methods_done
= TRUE
;
258 return ddisp
; /* set the user data */
262 display_hash(DDisplay
*ddisp
)
264 return (gulong
) ddisp
;
268 ddisplay_transform_coords_double(DDisplay
*ddisp
,
270 double *xi
, double *yi
)
272 Rectangle
*visible
= &ddisp
->visible
;
273 double width
= dia_renderer_get_width_pixels (ddisp
->renderer
);
274 double height
= dia_renderer_get_height_pixels (ddisp
->renderer
);
276 *xi
= (x
- visible
->left
) * (real
)width
/ (visible
->right
- visible
->left
);
277 *yi
= (y
- visible
->top
) * (real
)height
/ (visible
->bottom
- visible
->top
);
282 ddisplay_transform_coords(DDisplay
*ddisp
,
286 Rectangle
*visible
= &ddisp
->visible
;
287 int width
= dia_renderer_get_width_pixels (ddisp
->renderer
);
288 int height
= dia_renderer_get_height_pixels (ddisp
->renderer
);
290 *xi
= ROUND ( (x
- visible
->left
) * (real
)width
/
291 (visible
->right
- visible
->left
) );
292 *yi
= ROUND ( (y
- visible
->top
) * (real
)height
/
293 (visible
->bottom
- visible
->top
) );
296 /* Takes real length and returns pixel length */
298 ddisplay_transform_length(DDisplay
*ddisp
, real len
)
300 return len
* ddisp
->zoom_factor
;
303 /* Takes pixel length and returns real length */
305 ddisplay_untransform_length(DDisplay
*ddisp
, real len
)
307 return len
/ ddisp
->zoom_factor
;
312 ddisplay_untransform_coords(DDisplay
*ddisp
,
316 Rectangle
*visible
= &ddisp
->visible
;
317 int width
= dia_renderer_get_width_pixels (ddisp
->renderer
);
318 int height
= dia_renderer_get_height_pixels (ddisp
->renderer
);
320 *x
= visible
->left
+ xi
*(visible
->right
- visible
->left
) / (real
)width
;
321 *y
= visible
->top
+ yi
*(visible
->bottom
- visible
->top
) / (real
)height
;
326 ddisplay_add_update_pixels(DDisplay
*ddisp
, Point
*point
,
327 int pixel_width
, int pixel_height
)
332 size_x
= ddisplay_untransform_length(ddisp
, pixel_width
+1);
333 size_y
= ddisplay_untransform_length(ddisp
, pixel_height
+1);
335 rect
.left
= point
->x
- size_x
/2.0;
336 rect
.top
= point
->y
- size_y
/2.0;
337 rect
.right
= point
->x
+ size_x
/2.0;
338 rect
.bottom
= point
->y
+ size_y
/2.0;
340 ddisplay_add_update(ddisp
, &rect
);
343 /** Free display_areas list */
345 ddisplay_free_display_areas(DDisplay
*ddisp
)
348 l
= ddisp
->display_areas
;
353 g_slist_free(ddisp
->display_areas
);
354 ddisp
->display_areas
= NULL
;
357 /** Free update_areas list */
359 ddisplay_free_update_areas(DDisplay
*ddisp
)
362 l
= ddisp
->update_areas
;
367 g_slist_free(ddisp
->update_areas
);
368 ddisp
->update_areas
= NULL
;
371 /** Marks the entire visible area for update.
372 * Throws out old updates, since everything will be updated anyway.
375 ddisplay_add_update_all(DDisplay
*ddisp
)
377 if (ddisp
->update_areas
!= NULL
) {
378 ddisplay_free_update_areas(ddisp
);
380 if (ddisp
->display_areas
!= NULL
) {
381 ddisplay_free_display_areas(ddisp
);
383 ddisplay_add_update(ddisp
, &ddisp
->visible
);
386 /** Marks a rectangle for update, with a pixel border around it.
389 ddisplay_add_update_with_border(DDisplay
*ddisp
, Rectangle
*rect
,
393 real size
= ddisplay_untransform_length(ddisp
, pixel_border
+1);
395 r
.left
= rect
->left
-size
;
396 r
.top
= rect
->top
-size
;
397 r
.right
= rect
->right
+size
;
398 r
.bottom
= rect
->bottom
+size
;
400 ddisplay_add_update(ddisp
, &r
);
404 ddisplay_add_update(DDisplay
*ddisp
, Rectangle
*rect
)
407 int top
,bottom
,left
,right
;
409 int width
= dia_renderer_get_width_pixels (ddisp
->renderer
);
410 int height
= dia_renderer_get_height_pixels (ddisp
->renderer
);
412 if (!rectangle_intersects(rect
, &ddisp
->visible
))
415 /* Temporarily just do a union of all rectangles: */
416 if (ddisp
->update_areas
==NULL
) {
417 r
= g_new(Rectangle
,1);
419 rectangle_intersection(r
, &ddisp
->visible
);
420 ddisp
->update_areas
= g_slist_prepend(ddisp
->update_areas
, r
);
422 r
= (Rectangle
*) ddisp
->update_areas
->data
;
423 rectangle_union(r
, rect
);
424 rectangle_intersection(r
, &ddisp
->visible
);
427 visible
= &ddisp
->visible
;
428 left
= floor( (r
->left
- visible
->left
) * (real
)width
/
429 (visible
->right
- visible
->left
) ) - 1;
430 top
= floor( (r
->top
- visible
->top
) * (real
)height
/
431 (visible
->bottom
- visible
->top
) ) - 1;
432 right
= ceil( (r
->right
- visible
->left
) * (real
)width
/
433 (visible
->right
- visible
->left
) ) + 1;
434 bottom
= ceil( (r
->bottom
- visible
->top
) * (real
)height
/
435 (visible
->bottom
- visible
->top
) ) + 1;
437 ddisplay_add_display_area(ddisp
,
443 ddisplay_add_display_area(DDisplay
*ddisp
,
445 int right
, int bottom
)
453 if (right
> dia_renderer_get_width_pixels (ddisp
->renderer
))
454 right
= dia_renderer_get_width_pixels (ddisp
->renderer
);
455 if (bottom
> dia_renderer_get_height_pixels (ddisp
->renderer
))
456 bottom
= dia_renderer_get_height_pixels (ddisp
->renderer
);
458 /* draw some rectangles to show where updates are...*/
459 /* gdk_draw_rectangle(ddisp->canvas->window, ddisp->canvas->style->black_gc, TRUE, left, top, right-left,bottom-top); */
461 /* Temporarily just do a union of all Irectangles: */
462 if (ddisp
->display_areas
==NULL
) {
463 r
= g_new(IRectangle
,1);
464 r
->top
= top
; r
->bottom
= bottom
;
465 r
->left
= left
; r
->right
= right
;
466 ddisp
->display_areas
= g_slist_prepend(ddisp
->display_areas
, r
);
468 r
= (IRectangle
*) ddisp
->display_areas
->data
;
470 r
->top
= MIN( r
->top
, top
);
471 r
->bottom
= MAX( r
->bottom
, bottom
);
472 r
->left
= MIN( r
->left
, left
);
473 r
->right
= MAX( r
->right
, right
);
478 ddisplay_update_handler(DDisplay
*ddisp
)
482 Rectangle
*r
, totrect
;
483 DiaInteractiveRendererInterface
*renderer
;
485 /* Renders updates to pixmap + copies display_areas to canvas(screen) */
486 renderer
= DIA_GET_INTERACTIVE_RENDERER_INTERFACE (ddisp
->renderer
);
488 /* Only update if update_areas exist */
489 l
= ddisp
->update_areas
;
492 totrect
= *(Rectangle
*) l
->data
;
494 g_return_val_if_fail ( renderer
->clip_region_clear
!= NULL
495 && renderer
->clip_region_add_rect
!= NULL
, FALSE
);
497 renderer
->clip_region_clear (ddisp
->renderer
);
500 r
= (Rectangle
*) l
->data
;
502 rectangle_union(&totrect
, r
);
503 renderer
->clip_region_add_rect (ddisp
->renderer
, r
);
507 /* Free update_areas list: */
508 ddisplay_free_update_areas(ddisp
);
511 totrect
.right
+= 0.1;
513 totrect
.bottom
+= 0.1;
515 ddisplay_render_pixmap(ddisp
, &totrect
);
518 l
= ddisp
->display_areas
;
520 ir
= (IRectangle
*) l
->data
;
522 g_return_val_if_fail (renderer
->copy_to_window
, FALSE
);
523 renderer
->copy_to_window(ddisp
->renderer
,
524 ddisp
->canvas
->window
,
526 ir
->right
- ir
->left
, ir
->bottom
- ir
->top
);
531 ddisplay_free_display_areas(ddisp
);
533 ddisp
->update_id
= 0;
539 ddisplay_flush(DDisplay
*ddisp
)
541 /* if no update is queued, queue update */
542 if (!ddisp
->update_id
)
543 ddisp
->update_id
= gtk_idle_add((GtkFunction
) ddisplay_update_handler
,
548 ddisplay_obj_render(DiaObject
*obj
, DiaRenderer
*renderer
,
552 DDisplay
*ddisp
= (DDisplay
*)data
;
555 DIA_RENDERER_GET_CLASS(renderer
)->draw_object(renderer
, obj
);
556 if (ddisp
->show_cx_pts
&&
557 obj
->parent_layer
!= NULL
&& obj
->parent_layer
->connectable
) {
558 for (i
=0;i
<obj
->num_connections
;i
++) {
559 connectionpoint_draw(obj
->connections
[i
], ddisp
);
565 ddisplay_render_pixmap(DDisplay
*ddisp
, Rectangle
*update
)
570 DiaInteractiveRendererInterface
*renderer
;
573 if (ddisp
->renderer
==NULL
) {
574 printf("ERROR! Renderer was NULL!!\n");
578 renderer
= DIA_GET_INTERACTIVE_RENDERER_INTERFACE (ddisp
->renderer
);
580 /* Erase background */
581 g_return_if_fail (renderer
->fill_pixel_rect
!= NULL
);
582 DIA_RENDERER_GET_CLASS(ddisp
->renderer
)->begin_render(ddisp
->renderer
);
583 renderer
->fill_pixel_rect (ddisp
->renderer
,
585 dia_renderer_get_width_pixels (ddisp
->renderer
),
586 dia_renderer_get_height_pixels (ddisp
->renderer
),
587 &ddisp
->diagram
->data
->bg_color
);
590 grid_draw(ddisp
, update
);
591 pagebreak_draw(ddisp
, update
);
593 timer
= g_timer_new();
594 data_render(ddisp
->diagram
->data
, ddisp
->renderer
, update
,
595 ddisplay_obj_render
, (gpointer
) ddisp
);
596 g_print ("data_render(%g%%) took %g seconds\n", ddisp
->zoom_factor
* 5.0, g_timer_elapsed (timer
, NULL
));
597 g_timer_destroy (timer
);
598 /* Draw handles for all selected objects */
599 list
= ddisp
->diagram
->data
->selected
;
601 obj
= (DiaObject
*) list
->data
;
603 for (i
=0;i
<obj
->num_handles
;i
++) {
604 handle_draw(obj
->handles
[i
], ddisp
);
606 list
= g_list_next(list
);
608 DIA_RENDERER_GET_CLASS(ddisp
->renderer
)->end_render(ddisp
->renderer
);
612 ddisplay_update_scrollbars(DDisplay
*ddisp
)
614 Rectangle
*extents
= &ddisp
->diagram
->data
->extents
;
615 Rectangle
*visible
= &ddisp
->visible
;
616 GtkAdjustment
*hsbdata
, *vsbdata
;
618 hsbdata
= ddisp
->hsbdata
;
620 hsbdata
->lower
= MIN(extents
->left
, visible
->left
);
621 hsbdata
->upper
= MAX(extents
->right
, visible
->right
);
622 hsbdata
->page_size
= visible
->right
- visible
->left
- 0.0001;
623 /* remove some to fix strange behaviour in gtk_range_adjustment_changed */
624 hsbdata
->page_increment
= (visible
->right
- visible
->left
) / 2.0;
625 hsbdata
->step_increment
= (visible
->right
- visible
->left
) / 10.0;
626 hsbdata
->value
= visible
->left
;
628 g_signal_emit_by_name (G_OBJECT (ddisp
->hsbdata
), "changed");
631 vsbdata
= ddisp
->vsbdata
;
632 vsbdata
->lower
= MIN(extents
->top
, visible
->top
);
633 vsbdata
->upper
= MAX(extents
->bottom
, visible
->bottom
);
634 vsbdata
->page_size
= visible
->bottom
- visible
->top
- 0.00001;
635 /* remove some to fix strange behaviour in gtk_range_adjustment_changed */
636 vsbdata
->page_increment
= (visible
->bottom
- visible
->top
) / 2.0;
637 vsbdata
->step_increment
= (visible
->bottom
- visible
->top
) / 10.0;
638 vsbdata
->value
= visible
->top
;
640 g_signal_emit_by_name (G_OBJECT (ddisp
->vsbdata
), "changed");
644 ddisplay_set_origo(DDisplay
*ddisp
, coord x
, coord y
)
646 Rectangle
*extents
= &ddisp
->diagram
->data
->extents
;
647 Rectangle
*visible
= &ddisp
->visible
;
650 /* updaterar origo+visible+rulers */
654 if (ddisp
->zoom_factor
<DDISPLAY_MIN_ZOOM
)
655 ddisp
->zoom_factor
= DDISPLAY_MIN_ZOOM
;
657 if (ddisp
->zoom_factor
> DDISPLAY_MAX_ZOOM
)
658 ddisp
->zoom_factor
= DDISPLAY_MAX_ZOOM
;
660 width
= dia_renderer_get_width_pixels (ddisp
->renderer
);
661 height
= dia_renderer_get_height_pixels (ddisp
->renderer
);
663 visible
->left
= ddisp
->origo
.x
;
664 visible
->top
= ddisp
->origo
.y
;
665 visible
->right
= ddisp
->origo
.x
+ ddisplay_untransform_length(ddisp
, width
);
666 visible
->bottom
= ddisp
->origo
.y
+ ddisplay_untransform_length(ddisp
, height
);
668 gtk_ruler_set_range (GTK_RULER (ddisp
->hrule
),
672 MAX(extents
->right
, visible
->right
)/* max_size*/);
673 gtk_ruler_set_range (GTK_RULER (ddisp
->vrule
),
677 MAX(extents
->bottom
, visible
->bottom
)/* max_size*/);
681 ddisplay_zoom(DDisplay
*ddisp
, Point
*point
, real magnify
)
686 visible
= &ddisp
->visible
;
688 width
= (visible
->right
- visible
->left
)/magnify
;
689 height
= (visible
->bottom
- visible
->top
)/magnify
;
691 if ((ddisp
->zoom_factor
<= DDISPLAY_MIN_ZOOM
) && (magnify
<=1.0))
693 if ((ddisp
->zoom_factor
>= DDISPLAY_MAX_ZOOM
) && (magnify
>=1.0))
696 ddisp
->zoom_factor
*= magnify
;
698 ddisplay_set_origo(ddisp
, point
->x
- width
/2.0, point
->y
- height
/2.0);
700 ddisplay_update_scrollbars(ddisp
);
701 ddisplay_add_update_all(ddisp
);
702 ddisplay_flush(ddisp
);
704 update_zoom_status (ddisp
);
707 /** Set the display's snap-to-grid setting, updating menu and button
710 ddisplay_set_snap_to_grid(DDisplay
*ddisp
, gboolean snap
)
712 GtkCheckMenuItem
*snap_to_grid
;
713 ddisp
->grid
.snap
= snap
;
715 if (ddisp
->menu_bar
== NULL
) {
716 snap_to_grid
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<Display>/View/Snap To Grid", NULL
));
718 snap_to_grid
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<DisplayMBar>/View/Snap To Grid", ddisp
->mbar_item_factory
));
721 /* Currently, this can cause double emit, but that's a small problem.
723 gtk_check_menu_item_set_active(snap_to_grid
,
725 ddisplay_update_statusbar(ddisp
);
728 /** Update the button showing whether snap-to-grid is on */
730 update_snap_grid_status(DDisplay
*ddisp
)
732 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ddisp
->grid_status
),
736 /** Set the display's mainpoint magnetism setting, updating menu and button
739 ddisplay_set_snap_to_objects(DDisplay
*ddisp
, gboolean magnetic
)
741 GtkCheckMenuItem
*mainpoint_magnetism
;
742 ddisp
->mainpoint_magnetism
= magnetic
;
744 if (ddisp
->menu_bar
== NULL
) {
745 mainpoint_magnetism
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<Display>/View/Snap To Objects", NULL
));
747 mainpoint_magnetism
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<DisplayMBar>/View/Snap To Objects", ddisp
->mbar_item_factory
));
750 /* Currently, this can cause double emit, but that's a small problem.
752 gtk_check_menu_item_set_active(mainpoint_magnetism
,
753 ddisp
->mainpoint_magnetism
);
754 ddisplay_update_statusbar(ddisp
);
757 /** Update the button showing whether mainpoint magnetism is on */
759 update_mainpoint_status(DDisplay
*ddisp
)
761 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ddisp
->mainpoint_status
),
762 ddisp
->mainpoint_magnetism
);
765 /** Scroll display to where point x,y (window coords) is visible */
767 ddisplay_autoscroll(DDisplay
*ddisp
, int x
, int y
)
769 guint16 width
, height
;
772 if (! ddisp
->autoscroll
)
775 scroll
.x
= scroll
.y
= 0;
777 width
= GTK_WIDGET(ddisp
->canvas
)->allocation
.width
;
778 height
= GTK_WIDGET(ddisp
->canvas
)->allocation
.height
;
786 scroll
.x
= x
- width
;
795 scroll
.y
= y
- height
;
798 if ((scroll
.x
!= 0) || (scroll
.y
!= 0))
802 scroll
.x
= ddisplay_untransform_length(ddisp
, scroll
.x
);
803 scroll
.y
= ddisplay_untransform_length(ddisp
, scroll
.y
);
805 scrolled
= ddisplay_scroll(ddisp
, &scroll
);
808 ddisplay_flush(ddisp
);
815 /** Scroll the display by delta (diagram coords) */
817 ddisplay_scroll(DDisplay
*ddisp
, Point
*delta
)
819 Rectangle
*visible
= &ddisp
->visible
;
820 real width
= visible
->right
- visible
->left
;
821 real height
= visible
->bottom
- visible
->top
;
823 Rectangle extents
= ddisp
->diagram
->data
->extents
;
824 real ex_width
= extents
.right
- extents
.left
;
825 real ex_height
= extents
.bottom
- extents
.top
;
827 Point new_origo
= ddisp
->origo
;
828 point_add(&new_origo
, delta
);
830 rectangle_union(&extents
, visible
);
832 if (new_origo
.x
< extents
.left
- ex_width
)
833 new_origo
.x
= extents
.left
- ex_width
;
835 if (new_origo
.x
+width
> extents
.right
+ ex_width
)
836 new_origo
.x
= extents
.right
- width
+ ex_width
;
838 if (new_origo
.y
< extents
.top
- ex_height
)
839 new_origo
.y
= extents
.top
- ex_height
;
841 if (new_origo
.y
+height
> extents
.bottom
+ ex_height
)
842 new_origo
.y
= extents
.bottom
- height
+ ex_height
;
844 if ( (new_origo
.x
!= ddisp
->origo
.x
) ||
845 (new_origo
.y
!= ddisp
->origo
.y
) ) {
846 ddisplay_set_origo(ddisp
, new_origo
.x
, new_origo
.y
);
847 ddisplay_update_scrollbars(ddisp
);
848 ddisplay_add_update_all(ddisp
);
854 void ddisplay_scroll_up(DDisplay
*ddisp
)
859 delta
.y
= -(ddisp
->visible
.bottom
- ddisp
->visible
.top
)/4.0;
861 ddisplay_scroll(ddisp
, &delta
);
864 void ddisplay_scroll_down(DDisplay
*ddisp
)
869 delta
.y
= (ddisp
->visible
.bottom
- ddisp
->visible
.top
)/4.0;
871 ddisplay_scroll(ddisp
, &delta
);
874 void ddisplay_scroll_left(DDisplay
*ddisp
)
878 delta
.x
= -(ddisp
->visible
.right
- ddisp
->visible
.left
)/4.0;
881 ddisplay_scroll(ddisp
, &delta
);
884 void ddisplay_scroll_right(DDisplay
*ddisp
)
888 delta
.x
= (ddisp
->visible
.right
- ddisp
->visible
.left
)/4.0;
891 ddisplay_scroll(ddisp
, &delta
);
894 /** Scroll display to have the diagram point p at the center.
895 * Returns TRUE if anything changed. */
897 ddisplay_scroll_center_point(DDisplay
*ddisp
, Point
*p
)
901 /* Find current center */
902 center
.x
= (ddisp
->visible
.right
+ddisp
->visible
.left
)/2;
903 center
.y
= (ddisp
->visible
.top
+ddisp
->visible
.bottom
)/2;
905 point_sub(p
, ¢er
);
906 return ddisplay_scroll(ddisp
, p
);
909 /** Scroll display so that obj is centered.
910 * Returns TRUE if anything changed. */
912 ddisplay_scroll_to_object(DDisplay
*ddisp
, DiaObject
*obj
)
914 Rectangle r
= obj
->bounding_box
;
917 p
.x
= (r
.left
+r
.right
)/2;
918 p
.y
= (r
.top
+r
.bottom
)/2;
920 return ddisplay_scroll_center_point(ddisp
, &p
);
924 ddisplay_set_renderer(DDisplay
*ddisp
, int aa_renderer
)
929 g_object_unref (ddisp
->renderer
);
931 ddisp
->aa_renderer
= aa_renderer
;
933 width
= ddisp
->canvas
->allocation
.width
;
934 height
= ddisp
->canvas
->allocation
.height
;
936 if (ddisp
->aa_renderer
){
937 ddisp
->renderer
= new_libart_renderer(
938 dia_transform_new (&ddisp
->visible
,
939 &ddisp
->zoom_factor
), 1);
941 ddisp
->renderer
= new_gdk_renderer(ddisp
);
944 dia_renderer_set_size(ddisp
->renderer
, ddisp
->canvas
->window
, width
, height
);
948 ddisplay_resize_canvas(DDisplay
*ddisp
,
949 int width
, int height
)
951 if (ddisp
->renderer
==NULL
) {
952 if (ddisp
->aa_renderer
)
953 ddisp
->renderer
= new_libart_renderer(
954 dia_transform_new (&ddisp
->visible
,
955 &ddisp
->zoom_factor
), 1);
957 ddisp
->renderer
= new_gdk_renderer(ddisp
);
960 dia_renderer_set_size(ddisp
->renderer
, ddisp
->canvas
->window
, width
, height
);
962 ddisplay_set_origo(ddisp
, ddisp
->origo
.x
, ddisp
->origo
.y
);
964 ddisplay_add_update_all(ddisp
);
965 ddisplay_flush(ddisp
);
969 ddisplay_active(void)
971 return active_display
;
975 ddisplay_active_diagram(void)
977 DDisplay
*ddisp
= ddisplay_active ();
979 if (!ddisp
) return NULL
;
980 return ddisp
->diagram
;
984 ddisp_destroy(DDisplay
*ddisp
)
986 if (ddisp
->update_id
) {
987 gtk_idle_remove(ddisp
->update_id
);
988 ddisp
->update_id
= 0;
991 g_signal_handlers_disconnect_by_func (ddisp
->diagram
, selection_changed
, ddisp
);
993 g_object_unref (G_OBJECT (ddisp
->im_context
));
994 ddisp
->im_context
= NULL
;
996 ddisplay_im_context_preedit_reset(ddisp
, active_focus());
998 /* This calls ddisplay_really_destroy */
999 gtk_widget_destroy (ddisp
->shell
);
1003 are_you_sure_close_dialog_respond(GtkWidget
*widget
, /* the dialog */
1005 gpointer user_data
) /* the display */
1007 DDisplay
*ddisp
= (DDisplay
*)user_data
;
1009 switch (response_id
) {
1010 case GTK_RESPONSE_YES
:
1012 diagram_save(ddisp
->diagram
, ddisp
->diagram
->filename
);
1014 if (ddisp
->update_id
) {
1015 gtk_idle_remove(ddisp
->update_id
);
1016 ddisp
->update_id
= 0;
1019 case GTK_RESPONSE_NO
:
1020 ddisp_destroy (ddisp
);
1022 case GTK_RESPONSE_CANCEL
:
1023 case GTK_RESPONSE_NONE
:
1024 case GTK_RESPONSE_DELETE_EVENT
: /* closing via window manager */
1025 gtk_widget_destroy(widget
);
1028 g_assert_not_reached();
1033 ddisplay_close(DDisplay
*ddisp
)
1036 GtkWidget
*dialog
, *button
;
1040 g_return_if_fail(ddisp
!= NULL
);
1042 dia
= ddisp
->diagram
;
1044 if ( (dia
->display_count
> 1) ||
1045 (!diagram_is_modified(dia
)) ) {
1046 ddisp_destroy(ddisp
);
1050 fname
= dia
->filename
;
1052 fname
= _("<unnamed>");
1053 msg
= g_strdup_printf (
1054 _("The diagram '%s'\n"
1055 "has not been saved. Save changes now?"),
1058 dialog
= gtk_message_dialog_new(GTK_WINDOW (ddisp
->shell
),
1060 GTK_MESSAGE_QUESTION
,
1061 GTK_BUTTONS_NONE
, /* no standard buttons */
1065 gtk_window_set_title (GTK_WINDOW(dialog
), _("Close Diagram"));
1067 button
= gtk_button_new_from_stock (GTK_STOCK_CANCEL
);
1068 gtk_dialog_add_action_widget (GTK_DIALOG(dialog
), button
, GTK_RESPONSE_CANCEL
);
1070 button
= gtk_button_new_with_label (_("Discard Changes"));
1071 gtk_dialog_add_action_widget (GTK_DIALOG(dialog
), button
, GTK_RESPONSE_NO
);
1073 /* button = gtk_button_new_with_label (_("Save and Close")); */
1074 button
= gtk_button_new_from_stock (GTK_STOCK_SAVE
);
1075 gtk_dialog_add_action_widget (GTK_DIALOG(dialog
), button
, GTK_RESPONSE_YES
);
1076 GTK_WIDGET_SET_FLAGS (button
, GTK_CAN_DEFAULT
);
1077 gtk_dialog_set_default_response (GTK_DIALOG(dialog
), GTK_RESPONSE_YES
);
1079 g_signal_connect (G_OBJECT (dialog
), "response",
1080 G_CALLBACK(are_you_sure_close_dialog_respond
),
1083 gtk_widget_show_all(dialog
);
1087 display_update_menu_state(DDisplay
*ddisp
)
1089 GtkCheckMenuItem
*rulers
;
1090 GtkCheckMenuItem
*visible_grid
;
1091 GtkCheckMenuItem
*snap_to_grid
;
1092 GtkCheckMenuItem
*show_cx_pts
;
1094 GtkCheckMenuItem
*antialiased
;
1097 if (ddisp
->menu_bar
== NULL
) {
1098 rulers
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<Display>/View/Show Rulers", NULL
));
1099 visible_grid
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<Display>/View/Show Grid", NULL
));
1100 snap_to_grid
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<Display>/View/Snap To Grid", NULL
));
1102 GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<Display>/View/Show Connection Points", NULL
));
1104 antialiased
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<Display>/View/AntiAliased", NULL
));
1107 rulers
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<DisplayMBar>/View/Show Rulers", ddisp
->mbar_item_factory
));
1108 visible_grid
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<DisplayMBar>/View/Show Grid", ddisp
->mbar_item_factory
));
1109 snap_to_grid
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<DisplayMBar>/View/Snap To Grid", ddisp
->mbar_item_factory
));
1111 GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<DisplayMBar>/View/Show Connection Points", ddisp
->mbar_item_factory
));
1113 antialiased
= GTK_CHECK_MENU_ITEM(menus_get_item_from_path("<DisplayMBar>/View/AntiAliased", ddisp
->mbar_item_factory
));
1118 ddisplay_do_update_menu_sensitivity (ddisp
);
1120 gtk_check_menu_item_set_active(rulers
,
1121 GTK_WIDGET_VISIBLE (ddisp
->hrule
) ? 1 : 0);
1122 gtk_check_menu_item_set_active(visible_grid
,
1123 ddisp
->grid
.visible
);
1124 gtk_check_menu_item_set_active(snap_to_grid
,
1126 gtk_check_menu_item_set_active(show_cx_pts
,
1127 ddisp
->show_cx_pts
);
1129 gtk_check_menu_item_set_active(antialiased
,
1130 ddisp
->aa_renderer
);
1135 ddisplay_do_update_menu_sensitivity (DDisplay
*ddisp
)
1139 dia
= ddisp
->diagram
;
1140 if (ddisp
->menu_bar
) {
1141 diagram_update_menubar_sensitivity(dia
, &ddisp
->updatable_menu_items
);
1144 diagram_update_popupmenu_sensitivity(dia
);
1150 /* This is called when ddisp->shell is destroyed... */
1152 ddisplay_really_destroy(DDisplay
*ddisp
)
1154 if (active_display
== ddisp
)
1155 display_set_active(NULL
);
1158 if (ddisp
->diagram
) {
1159 diagram_remove_ddisplay(ddisp
->diagram
, ddisp
);
1160 /* if we are the last user of the diagram it will be unref'ed */
1161 g_object_unref(ddisp
->diagram
);
1162 ddisp
->diagram
= NULL
;
1165 g_object_unref (ddisp
->renderer
);
1166 ddisp
->renderer
= NULL
;
1168 g_hash_table_remove(display_ht
, ddisp
->shell
);
1169 g_hash_table_remove(display_ht
, ddisp
->canvas
);
1171 /* Free update_areas list: */
1172 ddisplay_free_update_areas(ddisp
);
1173 /* Free display_areas list */
1174 ddisplay_free_display_areas(ddisp
);
1181 ddisplay_set_title(DDisplay
*ddisp
, char *title
)
1183 gtk_window_set_title (GTK_WINDOW (ddisp
->shell
), title
);
1187 ddisplay_set_all_cursor(GdkCursor
*cursor
)
1194 current_cursor
= cursor
;
1196 list
= dia_open_diagrams();
1197 while (list
!= NULL
) {
1198 dia
= (Diagram
*) list
->data
;
1200 slist
= dia
->displays
;
1201 while (slist
!= NULL
) {
1202 ddisp
= (DDisplay
*) slist
->data
;
1204 ddisplay_set_cursor(ddisp
, cursor
);
1206 slist
= g_slist_next(slist
);
1209 list
= g_list_next(list
);
1214 ddisplay_set_cursor(DDisplay
*ddisp
, GdkCursor
*cursor
)
1216 gdk_window_set_cursor(ddisp
->canvas
->window
, cursor
);
1220 ddisplay_update_statusbar(DDisplay
*ddisp
)
1222 update_zoom_status (ddisp
);
1223 update_snap_grid_status (ddisp
);
1224 update_mainpoint_status (ddisp
);
1225 update_modified_status (ddisp
);
1229 display_set_active(DDisplay
*ddisp
)
1231 if (ddisp
!= active_display
) {
1232 active_display
= ddisp
;
1234 /* perform notification here (such as switch layers dialog) */
1235 layer_dialog_set_diagram(ddisp
? ddisp
->diagram
: NULL
);
1236 diagram_properties_set_diagram(ddisp
? ddisp
->diagram
: NULL
);
1239 display_update_menu_state(ddisp
);
1241 if (prefs
.toolbox_on_top
) {
1242 gtk_window_set_transient_for(GTK_WINDOW(interface_get_toolbox_shell()),
1243 GTK_WINDOW(ddisp
->shell
));
1245 gtk_window_set_transient_for(GTK_WINDOW(interface_get_toolbox_shell()),
1253 ddisplay_im_context_preedit_reset(DDisplay
*ddisp
, Focus
*focus
)
1255 if (ddisp
->preedit_string
!= NULL
) {
1256 if (focus
!= NULL
) {
1258 ObjectChange
*change
;
1260 for (i
= 0; i
< g_utf8_strlen(ddisp
->preedit_string
, -1); i
++) {
1261 (focus
->key_event
)(focus
, GDK_BackSpace
, NULL
, 0, &change
);
1265 g_free(ddisp
->preedit_string
);
1266 ddisp
->preedit_string
= NULL
;
1268 if (ddisp
->preedit_attrs
!= NULL
) {
1269 pango_attr_list_unref(ddisp
->preedit_attrs
);
1270 ddisp
->preedit_attrs
= NULL
;