1 #define __SP_SVG_VIEW_C__
3 /** \file
4 * Functions and callbacks for generic SVG view and widget
5 *
6 * Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 * Ralf Stephan <ralf@ark.in-berlin.de>
9 *
10 * Copyright (C) 2001-2002 Lauris Kaplinski
11 * Copyright (C) 2001 Ximian, Inc.
12 *
13 * Released under GNU GPL, read the file 'COPYING' for more information
14 */
16 #include "display/canvas-arena.h"
17 #include "display/display-forward.h"
18 #include "document.h"
19 #include "sp-item.h"
20 #include "svg-view.h"
23 /**
24 * Constructs new SPSVGView object and returns pointer to it.
25 */
26 SPSVGView::SPSVGView (SPCanvasGroup *parent)
27 {
28 _hscale = 1.0;
29 _vscale = 1.0;
30 _rescale = FALSE;
31 _keepaspect = FALSE;
32 _width = 0.0;
33 _height = 0.0;
35 _dkey = 0;
36 _drawing = 0;
37 _parent = parent;
38 }
40 SPSVGView::~SPSVGView()
41 {
42 if (doc() && _drawing)
43 {
44 sp_item_invoke_hide (SP_ITEM (sp_document_root (doc())), _dkey);
45 _drawing = NULL;
46 }
47 }
49 /**
50 * Rescales SPSVGView to given proportions.
51 */
52 void
53 SPSVGView::setScale (gdouble hscale, gdouble vscale)
54 {
55 if (!_rescale && ((hscale != _hscale) || (vscale != _vscale))) {
56 _hscale = hscale;
57 _vscale = vscale;
58 doRescale (true);
59 }
60 }
62 /**
63 * Rescales SPSVGView and keeps aspect ratio.
64 */
65 void
66 SPSVGView::setRescale
67 (bool rescale, bool keepaspect, gdouble width, gdouble height)
68 {
69 g_return_if_fail (!rescale || (width >= 0.0));
70 g_return_if_fail (!rescale || (height >= 0.0));
72 _rescale = rescale;
73 _keepaspect = keepaspect;
74 _width = width;
75 _height = height;
77 doRescale (true);
78 }
80 /**
81 * Helper function that sets rescale ratio and emits resize event.
82 */
83 void
84 SPSVGView::doRescale (bool event)
85 {
86 if (!doc()) return;
87 if (sp_document_width (doc()) < 1e-9) return;
88 if (sp_document_height (doc()) < 1e-9) return;
90 if (_rescale) {
91 _hscale = _width / sp_document_width (doc());
92 _vscale = _height / sp_document_height (doc());
93 if (_keepaspect) {
94 if (_hscale > _vscale) {
95 _hscale = _vscale;
96 } else {
97 _vscale = _hscale;
98 }
99 }
100 }
102 if (_drawing) {
103 sp_canvas_item_affine_absolute (_drawing, NR::Matrix(NR::scale(_hscale, _vscale)));
104 }
106 if (event) {
107 emitResized (sp_document_width (doc()) * _hscale,
108 sp_document_height (doc()) * _vscale);
109 }
110 }
112 void
113 SPSVGView::mouseover()
114 {
115 GdkCursor *cursor = gdk_cursor_new(GDK_HAND2);
116 gdk_window_set_cursor(GTK_WIDGET(SP_CANVAS_ITEM(_drawing)->canvas)->window, cursor);
117 gdk_cursor_destroy(cursor);
118 }
120 void
121 SPSVGView::mouseout()
122 {
123 gdk_window_set_cursor(GTK_WIDGET(SP_CANVAS_ITEM(_drawing)->canvas)->window, NULL);
124 }
126 //----------------------------------------------------------------
127 /**
128 * Callback connected with arena_event.
129 */
130 /// \todo fixme.
131 static gint
132 arena_handler (SPCanvasArena *arena, NRArenaItem *ai, GdkEvent *event, SPSVGView *svgview)
133 {
134 static gdouble x, y;
135 static gboolean active = FALSE;
136 SPEvent spev;
138 SPItem *spitem = (ai) ? (SPItem*)NR_ARENA_ITEM_GET_DATA (ai) : 0;
140 switch (event->type) {
141 case GDK_BUTTON_PRESS:
142 if (event->button.button == 1) {
143 active = TRUE;
144 x = event->button.x;
145 y = event->button.y;
146 }
147 break;
148 case GDK_BUTTON_RELEASE:
149 if (event->button.button == 1) {
150 if (active && (event->button.x == x) &&
151 (event->button.y == y)) {
152 spev.type = SP_EVENT_ACTIVATE;
153 if ( spitem != 0 )
154 {
155 sp_item_event (spitem, &spev);
156 }
157 }
158 }
159 active = FALSE;
160 break;
161 case GDK_MOTION_NOTIFY:
162 active = FALSE;
163 break;
164 case GDK_ENTER_NOTIFY:
165 spev.type = SP_EVENT_MOUSEOVER;
166 spev.data = svgview;
167 if ( spitem != 0 )
168 {
169 sp_item_event (spitem, &spev);
170 }
171 break;
172 case GDK_LEAVE_NOTIFY:
173 spev.type = SP_EVENT_MOUSEOUT;
174 spev.data = svgview;
175 if ( spitem != 0 )
176 {
177 sp_item_event (spitem, &spev);
178 }
179 break;
180 default:
181 break;
182 }
184 return TRUE;
185 }
187 /**
188 * Callback connected with set_document signal.
189 */
190 void
191 SPSVGView::setDocument (SPDocument *document)
192 {
193 if (doc()) {
194 sp_item_invoke_hide (SP_ITEM (sp_document_root (doc())), _dkey);
195 }
197 if (!_drawing) {
198 _drawing = sp_canvas_item_new (_parent, SP_TYPE_CANVAS_ARENA, NULL);
199 g_signal_connect (G_OBJECT (_drawing), "arena_event", G_CALLBACK (arena_handler), this);
200 }
202 if (document) {
203 NRArenaItem *ai = sp_item_invoke_show (
204 SP_ITEM (sp_document_root (document)),
205 SP_CANVAS_ARENA (_drawing)->arena,
206 _dkey,
207 SP_ITEM_SHOW_DISPLAY);
209 if (ai) {
210 nr_arena_item_add_child (SP_CANVAS_ARENA (_drawing)->root, ai, NULL);
211 nr_arena_item_unref (ai);
212 }
214 doRescale (!_rescale);
215 }
217 View::setDocument (document);
218 }
220 /**
221 * Callback connected with document_resized signal.
222 */
223 void
224 SPSVGView::onDocumentResized (gdouble width, gdouble height)
225 {
226 setScale (width, height);
227 doRescale (!_rescale);
228 }
231 /*
232 Local Variables:
233 mode:c++
234 c-file-style:"stroustrup"
235 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
236 indent-tabs-mode:nil
237 fill-column:99
238 End:
239 */
240 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :