1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
/** @file
* Desktop-bound visual control object
*/
/* Authors:
* Krzysztof Kosiński <tweenk.pl@gmail.com>
*
* Copyright (C) 2009 Authors
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifndef SEEN_UI_TOOL_CONTROL_POINT_H
#define SEEN_UI_TOOL_CONTROL_POINT_H
#include <boost/utility.hpp>
#include <sigc++/sigc++.h>
#include <gdkmm.h>
#include <gtkmm.h>
#include <2geom/point.h>
#include "display/display-forward.h"
#include "forward.h"
#include "util/accumulators.h"
#include "display/sodipodi-ctrl.h"
namespace Inkscape {
namespace UI {
// most of the documentation is in the .cpp file
class ControlPoint : boost::noncopyable, public sigc::trackable {
public:
typedef Inkscape::Util::ReverseInterruptible RInt;
typedef Inkscape::Util::Interruptible Int;
// these have to be public, because GCC doesn't allow protected types in constructors,
// even if the constructors are protected themselves.
struct ColorEntry {
guint32 fill;
guint32 stroke;
};
struct ColorSet {
ColorEntry normal;
ColorEntry mouseover;
ColorEntry clicked;
};
enum State {
STATE_NORMAL,
STATE_MOUSEOVER,
STATE_CLICKED
};
virtual ~ControlPoint();
/// @name Adjust the position of the control point
/// @{
/** Current position of the control point. */
Geom::Point const &position() const { return _position; }
operator Geom::Point const &() { return _position; }
virtual void move(Geom::Point const &pos);
virtual void setPosition(Geom::Point const &pos);
virtual void transform(Geom::Matrix const &m);
/// @}
/// @name Toggle the point's visibility
/// @{
bool visible() const;
virtual void setVisible(bool v);
/// @}
/// @name Transfer grab from another event handler
/// @{
void transferGrab(ControlPoint *from, GdkEventMotion *event);
/// @}
/// @name Receive notifications about control point events
/// @{
sigc::signal<void, Geom::Point const &, Geom::Point &, GdkEventMotion*> signal_dragged;
sigc::signal<bool, GdkEventButton*>::accumulated<RInt> signal_clicked;
sigc::signal<bool, GdkEventButton*>::accumulated<RInt> signal_doubleclicked;
sigc::signal<bool, GdkEventMotion*>::accumulated<Int> signal_grabbed;
sigc::signal<void, GdkEventButton*> signal_ungrabbed;
/// @}
/// @name Inspect the state of the control point
/// @{
State state() { return _state; }
bool mouseovered() { return this == mouseovered_point; }
/// @}
static ControlPoint *mouseovered_point;
static sigc::signal<void, ControlPoint*> signal_mouseover_change;
static Glib::ustring format_tip(char const *format, ...) G_GNUC_PRINTF(1,2);
// temporarily public, until snapping is refactored a little
virtual bool _eventHandler(GdkEvent *event);
protected:
ControlPoint(SPDesktop *d, Geom::Point const &initial_pos, Gtk::AnchorType anchor,
SPCtrlShapeType shape, unsigned int size, ColorSet *cset = 0, SPCanvasGroup *group = 0);
ControlPoint(SPDesktop *d, Geom::Point const &initial_pos, Gtk::AnchorType anchor,
Glib::RefPtr<Gdk::Pixbuf> pixbuf, ColorSet *cset = 0, SPCanvasGroup *group = 0);
/// @name Manipulate the control point's appearance in subclasses
/// @{
virtual void _setState(State state);
void _setColors(ColorEntry c);
unsigned int _size() const;
SPCtrlShapeType _shape() const;
GtkAnchorType _anchor() const;
Glib::RefPtr<Gdk::Pixbuf> _pixbuf();
void _setSize(unsigned int size);
void _setShape(SPCtrlShapeType shape);
void _setAnchor(GtkAnchorType anchor);
void _setPixbuf(Glib::RefPtr<Gdk::Pixbuf>);
/// @}
virtual Glib::ustring _getTip(unsigned /*state*/) { return ""; }
virtual Glib::ustring _getDragTip(GdkEventMotion */*event*/) { return ""; }
virtual bool _hasDragTips() { return false; }
SPDesktop *const _desktop; ///< The desktop this control point resides on.
SPCanvasItem * _canvas_item; ///< Visual representation of the control point.
ColorSet *_cset; ///< Colors used to represent the point
State _state;
static int const _grab_event_mask;
static Geom::Point const &_last_click_event_point() { return _drag_event_origin; }
static Geom::Point const &_last_drag_origin() { return _drag_origin; }
private:
ControlPoint(ControlPoint const &other);
void operator=(ControlPoint const &other);
static int _event_handler(SPCanvasItem *item, GdkEvent *event, ControlPoint *point);
static void _setMouseover(ControlPoint *, unsigned state);
static void _clearMouseover();
bool _updateTip(unsigned state);
bool _updateDragTip(GdkEventMotion *event);
void _setDefaultColors();
void _commonInit();
Geom::Point _position; ///< Current position in desktop coordinates
gulong _event_handler_connection;
static Geom::Point _drag_event_origin;
static Geom::Point _drag_origin;
static bool _event_grab;
static bool _drag_initiated;
};
extern ControlPoint::ColorSet invisible_cset;
} // namespace UI
} // namespace Inkscape
#endif
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
|