1 /** \file
2 * Functions and callbacks for generic SVG view and widget
3 *
4 * Authors:
5 * Lauris Kaplinski <lauris@kaplinski.com>
6 * Ralf Stephan <ralf@ark.in-berlin.de>
7 * Jon A. Cruz <jon@joncruz.org>
8 * Abhishek Sharma
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 "document.h"
18 #include "sp-item.h"
19 #include "svg-view.h"
22 /**
23 * Constructs new SPSVGView object and returns pointer to it.
24 */
25 SPSVGView::SPSVGView (SPCanvasGroup *parent)
26 {
27 _hscale = 1.0;
28 _vscale = 1.0;
29 _rescale = FALSE;
30 _keepaspect = FALSE;
31 _width = 0.0;
32 _height = 0.0;
34 _dkey = 0;
35 _drawing = 0;
36 _parent = parent;
37 }
39 SPSVGView::~SPSVGView()
40 {
41 if (doc() && _drawing)
42 {
43 SP_ITEM( doc()->getRoot() )->invoke_hide(_dkey);
44 _drawing = NULL;
45 }
46 }
48 /**
49 * Rescales SPSVGView to given proportions.
50 */
51 void
52 SPSVGView::setScale (gdouble hscale, gdouble vscale)
53 {
54 if (!_rescale && ((hscale != _hscale) || (vscale != _vscale))) {
55 _hscale = hscale;
56 _vscale = vscale;
57 doRescale (true);
58 }
59 }
61 /**
62 * Rescales SPSVGView and keeps aspect ratio.
63 */
64 void
65 SPSVGView::setRescale
66 (bool rescale, bool keepaspect, gdouble width, gdouble height)
67 {
68 g_return_if_fail (!rescale || (width >= 0.0));
69 g_return_if_fail (!rescale || (height >= 0.0));
71 _rescale = rescale;
72 _keepaspect = keepaspect;
73 _width = width;
74 _height = height;
76 doRescale (true);
77 }
79 /**
80 * Helper function that sets rescale ratio and emits resize event.
81 */
82 void
83 SPSVGView::doRescale (bool event)
84 {
85 if (!doc()) return;
86 if (doc()->getWidth () < 1e-9) return;
87 if (doc()->getHeight () < 1e-9) return;
89 if (_rescale) {
90 _hscale = _width / doc()->getWidth ();
91 _vscale = _height / doc()->getHeight ();
92 if (_keepaspect) {
93 if (_hscale > _vscale) {
94 _hscale = _vscale;
95 } else {
96 _vscale = _hscale;
97 }
98 }
99 }
101 if (_drawing) {
102 sp_canvas_item_affine_absolute (_drawing, Geom::Scale(_hscale, _vscale));
103 }
105 if (event) {
106 emitResized (doc()->getWidth () * _hscale,
107 doc()->getHeight () * _vscale);
108 }
109 }
111 void
112 SPSVGView::mouseover()
113 {
114 GdkCursor *cursor = gdk_cursor_new(GDK_HAND2);
115 gdk_window_set_cursor(GTK_WIDGET(SP_CANVAS_ITEM(_drawing)->canvas)->window, cursor);
116 gdk_cursor_unref(cursor);
117 }
119 void
120 SPSVGView::mouseout()
121 {
122 gdk_window_set_cursor(GTK_WIDGET(SP_CANVAS_ITEM(_drawing)->canvas)->window, NULL);
123 }
125 //----------------------------------------------------------------
126 /**
127 * Callback connected with arena_event.
128 */
129 /// \todo fixme.
130 static gint
131 arena_handler (SPCanvasArena */*arena*/, NRArenaItem *ai, GdkEvent *event, SPSVGView *svgview)
132 {
133 static gdouble x, y;
134 static gboolean active = FALSE;
135 SPEvent spev;
137 SPItem *spitem = (ai) ? (SPItem*)NR_ARENA_ITEM_GET_DATA (ai) : 0;
139 switch (event->type) {
140 case GDK_BUTTON_PRESS:
141 if (event->button.button == 1) {
142 active = TRUE;
143 x = event->button.x;
144 y = event->button.y;
145 }
146 break;
147 case GDK_BUTTON_RELEASE:
148 if (event->button.button == 1) {
149 if (active && (event->button.x == x) &&
150 (event->button.y == y)) {
151 spev.type = SP_EVENT_ACTIVATE;
152 if ( spitem != 0 )
153 {
154 spitem->emitEvent (spev);
155 }
156 }
157 }
158 active = FALSE;
159 break;
160 case GDK_MOTION_NOTIFY:
161 active = FALSE;
162 break;
163 case GDK_ENTER_NOTIFY:
164 spev.type = SP_EVENT_MOUSEOVER;
165 spev.data = svgview;
166 if ( spitem != 0 )
167 {
168 spitem->emitEvent (spev);
169 }
170 break;
171 case GDK_LEAVE_NOTIFY:
172 spev.type = SP_EVENT_MOUSEOUT;
173 spev.data = svgview;
174 if ( spitem != 0 )
175 {
176 spitem->emitEvent (spev);
177 }
178 break;
179 default:
180 break;
181 }
183 return TRUE;
184 }
186 /**
187 * Callback connected with set_document signal.
188 */
189 void
190 SPSVGView::setDocument (SPDocument *document)
191 {
192 if (doc()) {
193 SP_ITEM( doc()->getRoot() )->invoke_hide(_dkey);
194 }
196 if (!_drawing) {
197 _drawing = sp_canvas_item_new (_parent, SP_TYPE_CANVAS_ARENA, NULL);
198 g_signal_connect (G_OBJECT (_drawing), "arena_event", G_CALLBACK (arena_handler), this);
199 }
201 if (document) {
202 NRArenaItem *ai = SP_ITEM( document->getRoot() )->invoke_show(
203 SP_CANVAS_ARENA (_drawing)->arena,
204 _dkey,
205 SP_ITEM_SHOW_DISPLAY);
207 if (ai) {
208 nr_arena_item_add_child (SP_CANVAS_ARENA (_drawing)->root, ai, NULL);
209 }
211 doRescale (!_rescale);
212 }
214 View::setDocument (document);
215 }
217 /**
218 * Callback connected with document_resized signal.
219 */
220 void
221 SPSVGView::onDocumentResized (gdouble width, gdouble height)
222 {
223 setScale (width, height);
224 doRescale (!_rescale);
225 }
228 /*
229 Local Variables:
230 mode:c++
231 c-file-style:"stroustrup"
232 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
233 indent-tabs-mode:nil
234 fill-column:99
235 End:
236 */
237 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :