Code

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