Code

moving trunk for module inkscape
[inkscape.git] / src / context-fns.cpp
1 #include <glibmm/i18n.h>
2 #include "sp-item.h"
3 #include "desktop.h"
4 #include "message-context.h"
5 #include "message-stack.h"
6 #include "context-fns.h"
7 #include "snap.h"
8 #include "desktop-affine.h"
9 #include "event-context.h"
11 /* FIXME: could probably use a template here */
13 /**
14  *  Check to see if the current layer is both unhidden and unlocked.  If not,
15  *  set a message about it on the given context.
16  *
17  *  \param desktop Desktop.
18  *  \param message Message context to put messages on.
19  *  \return true if the current layer is both unhidden and unlocked, otherwise false.
20  */
22 bool Inkscape::have_viable_layer(SPDesktop *desktop, MessageContext *message)
23 {
24     SPItem const *layer = SP_ITEM(desktop->currentLayer());
25     
26     if ( !layer || desktop->itemIsHidden(layer) ) {
27             message->flash(Inkscape::ERROR_MESSAGE,
28                          _("<b>Current layer is hidden</b>. Unhide it to be able to draw on it."));
29             return false;
30     }
31     
32     if ( !layer || layer->isLocked() ) {
33             message->flash(Inkscape::ERROR_MESSAGE,
34                          _("<b>Current layer is locked</b>. Unlock it to be able to draw on it."));
35             return false;
36     }
38     return true;
39 }
42 /**
43  *  Check to see if the current layer is both unhidden and unlocked.  If not,
44  *  set a message about it on the given context.
45  *
46  *  \param desktop Desktop.
47  *  \param message Message context to put messages on.
48  *  \return true if the current layer is both unhidden and unlocked, otherwise false.
49  */
51 bool Inkscape::have_viable_layer(SPDesktop *desktop, MessageStack *message)
52 {
53     SPItem const *layer = SP_ITEM(desktop->currentLayer());
54     
55     if ( !layer || desktop->itemIsHidden(layer) ) {
56             message->flash(Inkscape::WARNING_MESSAGE,
57                          _("<b>Current layer is hidden</b>. Unhide it to be able to draw on it."));
58             return false;
59     }
60     
61     if ( !layer || layer->isLocked() ) {
62             message->flash(Inkscape::WARNING_MESSAGE,
63                          _("<b>Current layer is locked</b>. Unlock it to be able to draw on it."));
64             return false;
65     }
67     return true;
68 }
71 NR::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item,
72                                         NR::Point const &pt, NR::Point const &center, int state)
73 {
74     NR::Point p[2];
76     bool const shift = state & GDK_SHIFT_MASK;
77     bool const control = state & GDK_CONTROL_MASK;
79     SnapManager const m(desktop->namedview);
81     if (control) {
83         /* Control is down: we are constrained to producing integer-ratio rectangles */
85         /* Vector from the centre of the box to the point we are dragging to */
86         NR::Point delta = pt - center;
88         /* Round it so that we have an integer-ratio box */
89         if (fabs(delta[NR::X]) > fabs(delta[NR::Y]) && (delta[NR::Y] != 0.0)) {
90             delta[NR::X] = floor(delta[NR::X] / delta[NR::Y] + 0.5) * delta[NR::Y];
91         } else if (delta[NR::X] != 0.0) {
92             delta[NR::Y] = floor(delta[NR::Y] / delta[NR::X] + 0.5) * delta[NR::X];
93         }
95         /* p[1] is the dragged point with the integer-ratio constraint */
96         p[1] = center + delta;
97         
98         if (shift) {
100             /* Shift is down, so our origin is the centre point rather than the corner
101             ** point; this means that corner-point movements are bound to each other.
102             */
104             /* p[0] is the opposite corner of our box */
105             p[0] = center - delta;
106             
107             Inkscape::SnappedPoint s[2];
109             /* Try to snap p[0] (the opposite corner) along the constraint vector */
110             s[0] = m.constrainedSnap(Inkscape::Snapper::SNAP_POINT,
111                                      p[0], p[0] - p[1], item);
113             /* Try to snap p[1] (the dragged corner) along the constraint vector */
114             s[1] = m.constrainedSnap(Inkscape::Snapper::SNAP_POINT,
115                                      p[1], p[1] - p[0], item);
117             /* Choose the best snap and update points accordingly */
118             if (s[0].getDistance() < s[1].getDistance()) {
119                 p[0] = s[0].getPoint();
120                 p[1] = 2 * center - s[0].getPoint();
121             } else {
122                 p[0] = 2 * center - s[1].getPoint();
123                 p[1] = s[1].getPoint();
124             }
125             
126         } else {
128             /* Our origin is the opposite corner.  Snap the drag point along the constraint vector */
129             p[0] = center;
130             p[1] = m.constrainedSnap(Inkscape::Snapper::SNAP_POINT, p[1], p[1] - p[0], item).getPoint();
131         }
132         
133     } else if (shift) {
135         /* Shift is down, so our origin is the centre point rather than the corner point;
136         ** this means that corner-point movements are bound to each other.
137         */
138         
139         p[1] = pt;
140         p[0] = 2 * center - p[1];
142         Inkscape::SnappedPoint s[2];
144         s[0] = m.freeSnap(Inkscape::Snapper::SNAP_POINT, p[0], item);
145         s[1] = m.freeSnap(Inkscape::Snapper::SNAP_POINT, p[1], item);
147         if (s[0].getDistance() < s[1].getDistance()) {
148             p[0] = s[0].getPoint();
149             p[1] = 2 * center - s[0].getPoint();
150         } else {
151             p[0] = 2 * center - s[1].getPoint();
152             p[1] = s[1].getPoint();
153         }
154         
155     } else {
156         
157         /* There's no constraint on the corner point, so just snap it to anything */
158         p[0] = center;
159         p[1] = m.freeSnap(Inkscape::Snapper::SNAP_POINT, pt, item).getPoint();
160     }
162     p[0] = sp_desktop_dt2root_xy_point(desktop, p[0]);
163     p[1] = sp_desktop_dt2root_xy_point(desktop, p[1]);
165     return NR::Rect(NR::Point(MIN(p[0][NR::X], p[1][NR::X]), MIN(p[0][NR::Y], p[1][NR::Y])),
166                     NR::Point(MAX(p[0][NR::X], p[1][NR::X]), MAX(p[0][NR::Y], p[1][NR::Y])));
171 NR::Point Inkscape::setup_for_drag_start(SPDesktop *desktop, SPEventContext* ec, GdkEvent *ev)
173     ec->xp = static_cast<gint>(ev->button.x);
174     ec->yp = static_cast<gint>(ev->button.y);
175     ec->within_tolerance = true;
177     NR::Point const p(ev->button.x, ev->button.y);
178     ec->item_to_select = sp_event_context_find_item(desktop, p, ev->button.state & GDK_MOD1_MASK, TRUE);
179     return ec->desktop->w2d(p);
183 /*
184   Local Variables:
185   mode:c++
186   c-file-style:"stroustrup"
187   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
188   indent-tabs-mode:nil
189   fill-column:99
190   End:
191 */
192 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :