summaryrefslogtreecommitdiffstats
path: root/src/ui/tool/transform-handle-set.h
blob: 4b6877c83321dc59fd0eee74b3cf810ee9de2c80 (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
// SPDX-License-Identifier: GPL-2.0-or-later
/** @file
 * Affine transform handles component
 */
/* Authors:
 *   Krzysztof Kosiński <tweenk.pl@gmail.com>
 *   Jon A. Cruz <jon@joncruz.org>
 *
 * Copyright (C) 2009 Authors
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifndef SEEN_UI_TOOL_TRANSFORM_HANDLE_SET_H
#define SEEN_UI_TOOL_TRANSFORM_HANDLE_SET_H

#include <memory>
#include <gdk/gdk.h>
#include <2geom/forward.h>
#include "ui/tool/commit-events.h"
#include "ui/tool/manipulator.h"
#include "ui/tool/control-point.h"
#include "enums.h"
#include "snap-candidate.h"

class SPDesktop;

namespace Inkscape {

class CanvasItemGroup;
class CanvasItemRect;

namespace UI {

class RotateHandle;
class SkewHandle;
class ScaleCornerHandle;
class ScaleSideHandle;
class RotationCenter;

class TransformHandleSet : public Manipulator {
public:

    enum Mode {
        MODE_SCALE,
        MODE_ROTATE_SKEW
    };

    TransformHandleSet(SPDesktop *d, Inkscape::CanvasItemGroup *th_group);
    ~TransformHandleSet() override;
    bool event(Inkscape::UI::Tools::ToolBase *, GdkEvent *) override;

    bool visible() const { return _visible; }
    Mode mode() const { return _mode; }
    Geom::Rect bounds() const;
    void setVisible(bool v);

    /** Sets the mode of transform handles (scale or rotate). */
    void setMode(Mode m);

    void setBounds(Geom::Rect const &, bool preserve_center = false);

    bool transforming() { return _in_transform; }

    ControlPoint const &rotationCenter() const;
    ControlPoint &rotationCenter();

    sigc::signal<void, Geom::Affine const &> signal_transform;
    sigc::signal<void, CommitEvent> signal_commit;

private:

    void _emitTransform(Geom::Affine const &);
    void _setActiveHandle(ControlPoint *h);
    void _clearActiveHandle();

    /** Update the visibility of transformation handles according to settings and the dimensions
     * of the bounding box. It hides the handles that would have no effect or lead to
     * discontinuities. Additionally, side handles for which there is no space are not shown.
     */
    void _updateVisibility(bool v);

    // TODO unions must GO AWAY:
    union {
        ControlPoint *_handles[17];
        struct {
            ScaleCornerHandle *_scale_corners[4];
            ScaleSideHandle *_scale_sides[4];
            RotateHandle *_rot_corners[4];
            SkewHandle *_skew_sides[4];
            RotationCenter *_center;
        };
    };

    ControlPoint *_active;
    Inkscape::CanvasItemGroup *_transform_handle_group;
    Inkscape::CanvasItemRect *_trans_outline;
    Mode _mode;
    bool _in_transform;
    bool _visible;
    friend class TransformHandle;
    friend class RotationCenter;
};

/** Base class for node transform handles to simplify implementation. */
class TransformHandle : public ControlPoint
{
public:
    TransformHandle(TransformHandleSet &th, SPAnchorType anchor, Inkscape::CanvasItemCtrlType type);
    void getNextClosestPoint(bool reverse);

protected:
    virtual void startTransform() {}
    virtual void endTransform() {}
    virtual Geom::Affine computeTransform(Geom::Point const &pos, GdkEventMotion *event) = 0;
    virtual CommitEvent getCommitEvent() = 0;

    Geom::Affine _last_transform;
    Geom::Point _origin;
    TransformHandleSet &_th;
    std::vector<Inkscape::SnapCandidatePoint> _snap_points;
    std::vector<Inkscape::SnapCandidatePoint> _unselected_points;
    std::vector<Inkscape::SnapCandidatePoint> _all_snap_sources_sorted;
    std::vector<Inkscape::SnapCandidatePoint>::iterator _all_snap_sources_iter;

private:
    bool grabbed(GdkEventMotion *) override;
    void dragged(Geom::Point &new_pos, GdkEventMotion *event) override;
    void ungrabbed(GdkEventButton *) override;

    static ColorSet thandle_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:fileencoding=utf-8:textwidth=99 :