Code

moving trunk for module inkscape
[inkscape.git] / src / svg-view.cpp
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     }
112 void
113 SPSVGView::mouseover()
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);
120 void
121 SPSVGView::mouseout()
123     gdk_window_set_cursor(GTK_WIDGET(SP_CANVAS_ITEM(_drawing)->canvas)->window, NULL);
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)
134         static gdouble x, y;
135         static gboolean active = FALSE;
136         SPEvent spev;
138         SPItem *spitem = (ai) ? (SPItem*)NR_ARENA_ITEM_GET_DATA (ai) : NULL;
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) && (event->button.y == y)) {
151                                 spev.type = SP_EVENT_ACTIVATE;
152                                 sp_item_event (spitem, &spev);
153                         }
154                 }
155                 active = FALSE;
156                 break;
157         case GDK_MOTION_NOTIFY:
158                 active = FALSE;
159                 break;
160         case GDK_ENTER_NOTIFY:
161                 spev.type = SP_EVENT_MOUSEOVER;
162                 spev.data = svgview;
163                 sp_item_event (spitem, &spev);
164                 break;
165         case GDK_LEAVE_NOTIFY:
166                 spev.type = SP_EVENT_MOUSEOUT;
167                 spev.data = svgview;
168                 sp_item_event (spitem, &spev);
169                 break;
170         default:
171                 break;
172         }
174         return TRUE;
177 /**
178  * Callback connected with set_document signal.
179  */
180 void
181 SPSVGView::setDocument (SPDocument *document)
183     if (doc()) {
184         sp_item_invoke_hide (SP_ITEM (sp_document_root (doc())), _dkey);
185     }
187     if (!_drawing) {
188         _drawing = sp_canvas_item_new (_parent, SP_TYPE_CANVAS_ARENA, NULL);
189         g_signal_connect (G_OBJECT (_drawing), "arena_event", G_CALLBACK (arena_handler), this);
190     }
192     if (document) {
193         NRArenaItem *ai = sp_item_invoke_show (
194                 SP_ITEM (sp_document_root (document)), 
195                 SP_CANVAS_ARENA (_drawing)->arena,
196                 _dkey, 
197                 SP_ITEM_SHOW_DISPLAY);
198         
199         if (ai) {
200             nr_arena_item_add_child (SP_CANVAS_ARENA (_drawing)->root, ai, NULL);
201             nr_arena_item_unref (ai);
202         }
204         doRescale (!_rescale);
205     }
207     View::setDocument (document);
210 /**
211  * Callback connected with document_resized signal.
212  */
213 void
214 SPSVGView::onDocumentResized (gdouble width, gdouble height)
216     setScale (width, height);
217     doRescale (!_rescale);
221 /*
222   Local Variables:
223   mode:c++
224   c-file-style:"stroustrup"
225   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
226   indent-tabs-mode:nil
227   fill-column:99
228   End:
229 */
230 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :