summaryrefslogtreecommitdiffstats
path: root/src/seltrans.h
blob: 9d14fda26a4a6b8f44c5b13ce5e354082d127da5 (plain)
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#ifndef __SELTRANS_H__
#define __SELTRANS_H__

/*
 * Helper object for transforming selected items
 *
 * Authors:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *   Carl Hetherington <inkscape@carlh.net>
 *   Diederik van Lierop <mail@diedenrezi.nl>
 *
 * Copyright (C) 2006      Johan Engelen <johan@shouraizou.nl>
 * Copyright (C) 1999-2002 Lauris Kaplinski
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#include <stddef.h>
#include <sigc++/sigc++.h>
#include <2geom/point.h>
#include <2geom/affine.h>
#include <2geom/rect.h>
#include "knot.h"
#include "forward.h"
#include "selcue.h"
#include "message-context.h"
#include <vector>
#include "sp-item.h"

struct SPKnot;
class SPDesktop;
class SPCanvasItem;
class SPSelTransHandle;

namespace Inkscape
{

Geom::Scale calcScaleFactors(Geom::Point const &initial_point, Geom::Point const &new_point, Geom::Point const &origin, bool const skew = false);

namespace XML
{
  class Node;
}

class SelTrans
{
public:
    SelTrans(SPDesktop *desktop);
    ~SelTrans();

    Inkscape::MessageContext &messageContext() {
        return _message_context;
    }

    void increaseState();
    void resetState();
    void setCenter(Geom::Point const &p);
    void grab(Geom::Point const &p, gdouble x, gdouble y, bool show_handles, bool translating);
    void transform(Geom::Affine const &rel_affine, Geom::Point const &norm);
    void ungrab();
    void stamp();
    void moveTo(Geom::Point const &xy, guint state);
    void stretch(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
    void scale(Geom::Point &pt, guint state);
    void skew(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
    void rotate(Geom::Point &pt, guint state);
    gboolean scaleRequest(Geom::Point &pt, guint state);
    gboolean stretchRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
    gboolean skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
    gboolean rotateRequest(Geom::Point &pt, guint state);
    gboolean centerRequest(Geom::Point &pt, guint state);

    gboolean handleRequest(SPKnot *knot, Geom::Point *position, guint state, SPSelTransHandle const &handle);
    void handleGrab(SPKnot *knot, guint state, SPSelTransHandle const &handle);
    void handleClick(SPKnot *knot, guint state, SPSelTransHandle const &handle);
    void handleNewEvent(SPKnot *knot, Geom::Point *position, guint state, SPSelTransHandle const &handle);

    enum Show
    {
        SHOW_CONTENT,
        SHOW_OUTLINE
    };

    void setShow(Show s) {
        _show = s;
    }
    bool isEmpty() {
        return _empty;
    }
    bool isGrabbed() {
        return _grabbed;
    }
	bool centerIsVisible() {
		return ( _chandle && SP_KNOT_IS_VISIBLE (_chandle) );
	}

private:
    void _updateHandles();
    void _updateVolatileState();
    void _selChanged(Inkscape::Selection *selection);
    void _selModified(Inkscape::Selection *selection, guint flags);
    void _showHandles(SPKnot *knot[], SPSelTransHandle const handle[], gint num,
                      gchar const *even_tip, gchar const *odd_tip);
    Geom::Point _getGeomHandlePos(Geom::Point const &visual_handle_pos);
    Geom::Point _calcAbsAffineDefault(Geom::Scale const default_scale);
    Geom::Point _calcAbsAffineGeom(Geom::Scale const geom_scale);
    void _display_snapsource();

    enum State {
        STATE_SCALE, //scale or stretch
        STATE_ROTATE //rotate or skew
    };

    SPDesktop *_desktop;

    std::vector<SPItem *> _items;
    std::vector<SPItem const *> _items_const;
    std::vector<Geom::Affine> _items_affines;
    std::vector<Geom::Point> _items_centers;

    std::vector<Inkscape::SnapCandidatePoint> _snap_points;
    std::vector<Inkscape::SnapCandidatePoint> _bbox_points; // the bbox point of the selection as a whole, i.e. max. 4 corners plus optionally some midpoints
    std::vector<Inkscape::SnapCandidatePoint> _bbox_points_for_translating; // the bbox points of each selected item, only to be used for translating

    Inkscape::SelCue _selcue;

    Inkscape::Selection *_selection;
    State _state;
    Show _show;

    bool _grabbed;
    bool _show_handles;
    bool _empty;
    bool _changed;

    SPItem::BBoxType _snap_bbox_type;

    Geom::OptRect _bbox;
    Geom::OptRect _visual_bbox;
    Geom::OptRect _geometric_bbox;
    gdouble _strokewidth;

    Geom::Affine _current_relative_affine;
    Geom::Affine _absolute_affine;
    Geom::Affine _relative_affine;
    /* According to Merriam - Webster's online dictionary
     * Affine: a transformation (as a translation, a rotation, or a uniform stretching) that carries straight
     * lines into straight lines and parallel lines into parallel lines but may alter distance between points
     * and angles between lines <affine geometry>
     */

    Geom::Point _opposite; ///< opposite point to where a scale is taking place
    Geom::Point _opposite_for_specpoints;
    Geom::Point _opposite_for_bboxpoints;
    Geom::Point _origin_for_specpoints;
    Geom::Point _origin_for_bboxpoints;

    gdouble _handle_x;
    gdouble _handle_y;

    boost::optional<Geom::Point> _center;
    bool _center_is_set; ///< we've already set _center, no need to reread it from items

    SPKnot *_shandle[8];
    SPKnot *_rhandle[8];
    SPKnot *_chandle;
    SPCanvasItem *_norm;
    SPCanvasItem *_grip;
    SPCanvasItem *_l[4];
    guint _sel_changed_id;
    guint _sel_modified_id;
    GSList *_stamp_cache;

    Geom::Point _origin; ///< position of origin for transforms
    Geom::Point _point; ///< original position of the knot being used for the current transform
    Geom::Point _point_geom; ///< original position of the knot being used for the current transform
    Inkscape::MessageContext _message_context;
    sigc::connection _sel_changed_connection;
    sigc::connection _sel_modified_connection;
};

}

#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 :