~danieljabailey/inkscape/arc_node_editor

« back to all changes in this revision

Viewing changes to src/knot-holder-entity.cpp

  • Committer: scislac
  • Date: 2009-08-12 07:57:52 UTC
  • Revision ID: scislac@users.sourceforge.net-20090812075752-3zt99jgeqr3bm16j
much better quality multi-size windows icon, thanks ChrisMorgan

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
 
1
#define __KNOT_HOLDER_ENTITY_C__
 
2
 
 
3
/** \file
2
4
 * KnotHolderEntity definition.
3
5
 *
4
6
 * Authors:
5
7
 *   Mitsuru Oka <oka326@parkcity.ne.jp>
6
8
 *   Maximilian Albert <maximilian.albert@gmail.com>
7
 
 *   Abhishek Sharma
8
9
 *
9
10
 * Copyright (C) 1999-2001 Lauris Kaplinski
10
11
 * Copyright (C) 2000-2001 Ximian, Inc.
15
16
 * Released under GNU GPL
16
17
 */
17
18
 
18
 
#include "knot-holder-entity.h"
19
19
#include "knotholder.h"
20
20
#include "sp-item.h"
21
21
#include "style.h"
22
22
#include "preferences.h"
23
23
#include "macros.h"
 
24
#include <libnr/nr-matrix-ops.h>
24
25
#include "sp-pattern.h"
25
26
#include "snap.h"
26
27
#include "desktop.h"
27
28
#include "sp-namedview.h"
28
 
#include <2geom/affine.h>
 
29
#include <2geom/matrix.h>
29
30
#include <2geom/transforms.h>
30
31
 
31
32
int KnotHolderEntity::counter = 0;
32
33
 
33
 
void KnotHolderEntity::create(SPDesktop *desktop, SPItem *item, KnotHolder *parent, Inkscape::ControlType type,
34
 
                              const gchar *tip,
35
 
                              SPKnotShapeType shape, SPKnotModeType mode, guint32 color)
 
34
void
 
35
KnotHolderEntity::create(SPDesktop *desktop, SPItem *item, KnotHolder *parent, const gchar *tip,
 
36
                         SPKnotShapeType shape, SPKnotModeType mode, guint32 color)
36
37
{
37
 
    knot = new SPKnot(desktop, tip);
 
38
    knot = sp_knot_new(desktop, tip);
38
39
 
39
40
    this->parent_holder = parent;
40
41
    this->item = item; // TODO: remove the item either from here or from knotholder.cpp
42
43
 
43
44
    my_counter = KnotHolderEntity::counter++;
44
45
 
45
 
    g_object_set(G_OBJECT(knot->item), "shape", shape, NULL);
46
 
    g_object_set(G_OBJECT(knot->item), "mode", mode, NULL);
47
 
 
48
 
    // TODO base more appearance from this type instead of passing in arbitrary values.
49
 
    knot->item->ctrlType = type;
 
46
    g_object_set(G_OBJECT (knot->item), "shape", shape, NULL);
 
47
    g_object_set(G_OBJECT (knot->item), "mode", mode, NULL);
50
48
 
51
49
    knot->fill [SP_KNOT_STATE_NORMAL] = color;
52
 
    g_object_set (G_OBJECT(knot->item), "fill_color", color, NULL);
 
50
    g_object_set (G_OBJECT (knot->item), "fill_color", color, NULL);
53
51
 
54
52
    update_knot();
55
 
    knot->show();
 
53
    sp_knot_show(knot);
56
54
 
57
 
    _moved_connection = knot->moved_signal.connect(sigc::mem_fun(*parent_holder, &KnotHolder::knot_moved_handler));
58
 
    _click_connection = knot->click_signal.connect(sigc::mem_fun(*parent_holder, &KnotHolder::knot_clicked_handler));
59
 
    _ungrabbed_connection = knot->ungrabbed_signal.connect(sigc::mem_fun(*parent_holder, &KnotHolder::knot_ungrabbed_handler));
 
55
    _moved_connection = knot->_moved_signal.connect(sigc::mem_fun(*parent_holder, &KnotHolder::knot_moved_handler));
 
56
    _click_connection = knot->_click_signal.connect(sigc::mem_fun(*parent_holder, &KnotHolder::knot_clicked_handler));
 
57
    _ungrabbed_connection = knot->_ungrabbed_signal.connect(sigc::mem_fun(*parent_holder, &KnotHolder::knot_ungrabbed_handler));
60
58
}
61
59
 
62
60
 
68
66
 
69
67
    /* unref should call destroy */
70
68
    if (knot) {
71
 
        //g_object_unref(knot);
72
 
        knot_unref(knot);
 
69
        g_object_unref(knot);
73
70
    } else {
74
71
        // FIXME: This shouldn't occur. Perhaps it is caused by LPE PointParams being knotholder entities, too
75
72
        //        If so, it will likely be fixed with upcoming refactoring efforts.
80
77
void
81
78
KnotHolderEntity::update_knot()
82
79
{
83
 
    Geom::Point knot_pos(knot_get());
84
 
    if (knot_pos.isFinite()) {
85
 
        Geom::Point dp(knot_pos * item->i2dt_affine());
86
 
 
87
 
        _moved_connection.block();
88
 
        knot->setPosition(dp, SP_KNOT_STATE_NORMAL);
89
 
        _moved_connection.unblock();
90
 
    } else {
91
 
        // knot coords are non-finite, hide knot
92
 
        knot->hide();
93
 
    }
94
 
}
95
 
 
96
 
Geom::Point
97
 
KnotHolderEntity::snap_knot_position(Geom::Point const &p, guint state)
98
 
{
99
 
    if (state & GDK_SHIFT_MASK) { // Don't snap when shift-key is held
100
 
        return p;
101
 
    }
102
 
 
103
 
    Geom::Affine const i2dt (item->i2dt_affine());
104
 
    Geom::Point s = p * i2dt;
105
 
 
106
 
    SnapManager &m = desktop->namedview->snap_manager;
107
 
    m.setup(desktop, true, item);
108
 
    m.freeSnapReturnByRef(s, Inkscape::SNAPSOURCE_NODE_HANDLE);
109
 
    m.unSetup();
110
 
 
111
 
    return s * i2dt.inverse();
112
 
}
113
 
 
114
 
Geom::Point
115
 
KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint, guint state)
116
 
{
117
 
    if (state & GDK_SHIFT_MASK) { // Don't snap when shift-key is held
118
 
        return p;
119
 
    }
120
 
 
121
 
    Geom::Affine const i2d (item->i2dt_affine());
122
 
    Geom::Point s = p * i2d;
123
 
 
124
 
    SnapManager &m = desktop->namedview->snap_manager;
125
 
    m.setup(desktop, true, item);
126
 
 
127
 
    // constrainedSnap() will first project the point p onto the constraint line and then try to snap along that line.
128
 
    // This way the constraint is already enforced, no need to worry about that later on
129
 
    Inkscape::Snapper::SnapConstraint transformed_constraint = Inkscape::Snapper::SnapConstraint(constraint.getPoint() * i2d, (constraint.getPoint() + constraint.getDirection()) * i2d - constraint.getPoint() * i2d);
130
 
    m.constrainedSnapReturnByRef(s, Inkscape::SNAPSOURCE_NODE_HANDLE, transformed_constraint);
131
 
    m.unSetup();
132
 
 
 
80
    Geom::Matrix const i2d(sp_item_i2d_affine(item));
 
81
 
 
82
    Geom::Point dp(knot_get() * i2d);
 
83
 
 
84
    _moved_connection.block();
 
85
    sp_knot_set_position(knot, dp, SP_KNOT_STATE_NORMAL);
 
86
    _moved_connection.unblock();
 
87
}
 
88
 
 
89
Geom::Point
 
90
KnotHolderEntity::snap_knot_position(Geom::Point const &p)
 
91
{
 
92
    Geom::Matrix const i2d (sp_item_i2d_affine(item));
 
93
    Geom::Point s = p * i2d;
 
94
    SnapManager &m = desktop->namedview->snap_manager;
 
95
    m.setup(desktop, true, item);
 
96
    m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, s, Inkscape::SNAPSOURCE_HANDLE);
 
97
    return s * i2d.inverse();
 
98
}
 
99
 
 
100
Geom::Point
 
101
KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::ConstraintLine const &constraint)
 
102
{
 
103
    Geom::Matrix const i2d (sp_item_i2d_affine(item));
 
104
    Geom::Point s = p * i2d;
 
105
    Inkscape::Snapper::ConstraintLine transformed_constraint = Inkscape::Snapper::ConstraintLine(constraint.getPoint() * i2d, (constraint.getPoint() + constraint.getDirection()) * i2d - constraint.getPoint() * i2d);
 
106
    SnapManager &m = desktop->namedview->snap_manager;
 
107
    m.setup(desktop, true, item);
 
108
    m.constrainedSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, s, Inkscape::SNAPSOURCE_HANDLE, transformed_constraint);
133
109
    return s * i2d.inverse();
134
110
}
135
111
 
138
114
 
139
115
/*  TODO: this pattern manipulation is not able to handle general transformation matrices. Only matrices that are the result of a pure scale times a pure rotation. */
140
116
 
141
 
static gdouble sp_pattern_extract_theta(SPPattern const *pat)
 
117
static gdouble sp_pattern_extract_theta(SPPattern *pat)
142
118
{
143
 
    Geom::Affine transf = pat->getTransform();
 
119
    Geom::Matrix transf = pat->patternTransform;
144
120
    return Geom::atan2(transf.xAxis());
145
121
}
146
122
 
147
 
static Geom::Point sp_pattern_extract_scale(SPPattern const *pat)
 
123
static Geom::Point sp_pattern_extract_scale(SPPattern *pat)
148
124
{
149
 
    Geom::Affine transf = pat->getTransform();
 
125
    Geom::Matrix transf = pat->patternTransform;
150
126
    return Geom::Point( transf.expansionX(), transf.expansionY() );
151
127
}
152
128
 
153
129
static Geom::Point sp_pattern_extract_trans(SPPattern const *pat)
154
130
{
155
 
    return Geom::Point(pat->getTransform()[4], pat->getTransform()[5]);
 
131
    return Geom::Point(pat->patternTransform[4], pat->patternTransform[5]);
156
132
}
157
133
 
158
134
void
159
135
PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state)
160
136
{
161
 
    SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
 
137
    SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
162
138
 
163
139
    // FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
164
 
    Geom::Point p_snapped = snap_knot_position(p, state);
 
140
    Geom::Point p_snapped = snap_knot_position(p);
165
141
 
166
142
    if ( state & GDK_CONTROL_MASK ) {
167
143
        if (fabs((p - origin)[Geom::X]) > fabs((p - origin)[Geom::Y])) {
173
149
 
174
150
    if (state)  {
175
151
        Geom::Point const q = p_snapped - sp_pattern_extract_trans(pat);
176
 
        item->adjust_pattern(Geom::Translate(q), false, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
 
152
        sp_item_adjust_pattern(item, Geom::Matrix(Geom::Translate(q)));
177
153
    }
178
154
 
179
155
    item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
180
156
}
181
157
 
182
158
Geom::Point
183
 
PatternKnotHolderEntityXY::knot_get() const
 
159
PatternKnotHolderEntityXY::knot_get()
184
160
{
185
 
    SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
 
161
    SPPattern const *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
186
162
    return sp_pattern_extract_trans(pat);
187
163
}
188
164
 
189
165
Geom::Point
190
 
PatternKnotHolderEntityAngle::knot_get() const
 
166
PatternKnotHolderEntityAngle::knot_get()
191
167
{
192
 
    SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
 
168
    SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
193
169
 
194
 
    gdouble x = pat->width();
 
170
    gdouble x = (pattern_width(pat));
195
171
    gdouble y = 0;
196
172
    Geom::Point delta = Geom::Point(x,y);
197
173
    Geom::Point scale = sp_pattern_extract_scale(pat);
198
174
    gdouble theta = sp_pattern_extract_theta(pat);
199
 
    delta = delta * Geom::Affine(Geom::Scale(scale))*Geom::Affine(Geom::Rotate(theta));
 
175
    delta = delta * Geom::Matrix(Geom::Scale(scale))*Geom::Matrix(Geom::Rotate(theta));
200
176
    delta = delta + sp_pattern_extract_trans(pat);
201
177
    return delta;
202
178
}
207
183
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
208
184
    int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);
209
185
 
210
 
    SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
 
186
    SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
211
187
 
212
188
    // get the angle from pattern 0,0 to the cursor pos
213
189
    Geom::Point delta = p - sp_pattern_extract_trans(pat);
219
195
 
220
196
    // get the scale from the current transform so we can keep it.
221
197
    Geom::Point scl = sp_pattern_extract_scale(pat);
222
 
    Geom::Affine rot = Geom::Affine(Geom::Scale(scl)) * Geom::Affine(Geom::Rotate(theta));
 
198
    Geom::Matrix rot = Geom::Matrix(Geom::Scale(scl)) * Geom::Matrix(Geom::Rotate(theta));
223
199
    Geom::Point const t = sp_pattern_extract_trans(pat);
224
200
    rot[4] = t[Geom::X];
225
201
    rot[5] = t[Geom::Y];
226
 
    item->adjust_pattern(rot, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
 
202
    sp_item_adjust_pattern(item, rot, true);
227
203
    item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
228
204
}
229
205
 
230
206
void
231
207
PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
232
208
{
233
 
    SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
 
209
    SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
234
210
 
235
211
    // FIXME: this snapping should be done together with knowing whether control was pressed. If GDK_CONTROL_MASK, then constrained snapping should be used.
236
 
    Geom::Point p_snapped = snap_knot_position(p, state);
 
212
    Geom::Point p_snapped = snap_knot_position(p);
237
213
 
238
214
    // get angle from current transform
239
215
    gdouble theta = sp_pattern_extract_theta(pat);
240
216
 
241
217
    // Get the new scale from the position of the knotholder
242
218
    Geom::Point d = p_snapped - sp_pattern_extract_trans(pat);
243
 
    gdouble pat_x = pat->width();
244
 
    gdouble pat_y = pat->height();
 
219
    gdouble pat_x = pattern_width(pat);
 
220
    gdouble pat_y = pattern_height(pat);
245
221
    Geom::Scale scl(1);
246
222
    if ( state & GDK_CONTROL_MASK ) {
247
223
        // if ctrl is pressed: use 1:1 scaling
252
228
        scl = Geom::Scale(d[Geom::X] / pat_x, d[Geom::Y] / pat_y);
253
229
    }
254
230
 
255
 
    Geom::Affine rot = (Geom::Affine)scl * Geom::Rotate(theta);
 
231
    Geom::Matrix rot = (Geom::Matrix)scl * Geom::Rotate(theta);
256
232
 
257
233
    Geom::Point const t = sp_pattern_extract_trans(pat);
258
234
    rot[4] = t[Geom::X];
259
235
    rot[5] = t[Geom::Y];
260
 
    item->adjust_pattern(rot, true, _fill ? TRANSFORM_FILL : TRANSFORM_STROKE);
 
236
    sp_item_adjust_pattern(item, rot, true);
261
237
    item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
262
238
}
263
239
 
264
240
 
265
241
Geom::Point
266
 
PatternKnotHolderEntityScale::knot_get() const
 
242
PatternKnotHolderEntityScale::knot_get()
267
243
{
268
 
    SPPattern *pat = _fill ? SP_PATTERN(item->style->getFillPaintServer()) : SP_PATTERN(item->style->getStrokePaintServer());
 
244
    SPPattern *pat = SP_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style));
269
245
 
270
 
    gdouble x = pat->width();
271
 
    gdouble y = pat->height();
 
246
    gdouble x = pattern_width(pat);
 
247
    gdouble y = pattern_height(pat);
272
248
    Geom::Point delta = Geom::Point(x,y);
273
 
    Geom::Affine a = pat->getTransform();
 
249
    Geom::Matrix a = pat->patternTransform;
274
250
    a[4] = 0;
275
251
    a[5] = 0;
276
252
    delta = delta * a;
287
263
  fill-column:99
288
264
  End:
289
265
*/
290
 
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
 
266
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :