Code

whitespace
[inkscape.git] / src / ui / widget / rotateable.cpp
1 /**
2  * \brief widget adjustable by dragging it to rotate away from a zero-change axis
3  *
4  * Authors:
5  *   buliabyak@gmail.com
6  *
7  * Copyright (C) 2007 authors
8  *
9  * Released under GNU GPL.  Read the file 'COPYING' for more information.
10  */
12 #include "event-context.h"
13 #include "rotateable.h"
14 #include "libnr/nr-point.h"
15 #include "libnr/nr-point-fns.h"
16 #include <gtkmm/box.h>
17 #include <gtkmm/eventbox.h>
18 #include <glibmm/i18n.h>
20 namespace Inkscape {
21 namespace UI {
22 namespace Widget {
24 Rotateable::Rotateable():
25     axis(-M_PI/4),
26     maxdecl(M_PI/4)
27 {
28                 dragging = false;
29                 working = false;
30                 modifier = 0;
31                 current_axis = axis;
33     signal_button_press_event().connect(sigc::mem_fun(*this, &Rotateable::on_click));
34     signal_motion_notify_event().connect(sigc::mem_fun(*this, &Rotateable::on_motion));
35     signal_button_release_event().connect(sigc::mem_fun(*this, &Rotateable::on_release));
36 }
38 bool Rotateable::on_click(GdkEventButton *event) {
39                 if (event->button == 1) {
40         drag_started_x = event->x;
41         drag_started_y = event->y;
42         modifier = get_single_modifier(modifier, event->state); 
43         dragging = true;
44         working = false;
45         current_axis = axis;
46         return true;
47                 } 
48                 return false; 
49 }
51 guint Rotateable::get_single_modifier(guint old, guint state) {
53                 if (old == 0) {
54         if (state & GDK_CONTROL_MASK)
55             return 1; // ctrl
56         if (state & GDK_SHIFT_MASK)
57             return 2; // shift
58         return 0;
59                 } else {
60         if (!(state & GDK_CONTROL_MASK) && !(state & GDK_SHIFT_MASK))
61             return 0; // none
62         if (old == 1) 
63             if (state & GDK_SHIFT_MASK && !(state & GDK_CONTROL_MASK))
64                 return 2; // shift
65             else 
66                 return 1;
67         if (old == 2) 
68             if (state & GDK_CONTROL_MASK && !(state & GDK_SHIFT_MASK))
69                 return 1; // ctrl
70             else 
71                 return 2;
72         return old;
73                 }
74 }
77 bool Rotateable::on_motion(GdkEventMotion *event) {
78                 if (dragging) {
79         double dist = NR::L2(NR::Point(event->x, event->y) - NR::Point(drag_started_x, drag_started_y));
80         double angle = atan2(event->y - drag_started_y, event->x - drag_started_x);
81         if (dist > 20) {
82             working = true;
83             double force = CLAMP (-(angle - current_axis)/maxdecl, -1, 1);
84             if (fabs(force) < 0.002)
85                 force = 0; // snap to zero
86             if (modifier != get_single_modifier(modifier, event->state)) { 
87                 // user has switched modifiers in mid drag, close past drag and start a new
88                 // one, redefining axis temporarily
89                 do_release(force, modifier);
90                 current_axis = angle;
91                 modifier = get_single_modifier(modifier, event->state); 
92             } else {
93                 do_motion(force, modifier);
94             }
95         }
96         gobble_motion_events(GDK_BUTTON1_MASK);
97         return true;
98                 } 
99                 return false; 
103 bool Rotateable::on_release(GdkEventButton *event) {
104                 if (dragging && working) {
105         double angle = atan2(event->y - drag_started_y, event->x - drag_started_x);
106         double force = CLAMP (-(angle - current_axis)/maxdecl, -1, 1);
107         if (fabs(force) < 0.002)
108             force = 0; // snap to zero
109         do_release(force, modifier);
110         dragging = false;
111         working = false;
112         current_axis = axis;
113         return true;
114                 }
115                 return false;
119 Rotateable::~Rotateable() {
124 } // namespace Widget
125 } // namespace UI
126 } // namespace Inkscape
128 /* 
129   Local Variables:
130   mode:c++
131   c-file-style:"stroustrup"
132   c-file-offsets:((innamespace . 0)(inline-open . 0))
133   indent-tabs-mode:nil
134   fill-column:99
135   End:
136 */
137 // vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :