~centralelyon2010/inkscape/imagelinks2

5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
1
/** @file
2
 * @brief Miscellanous operations on selected items
3
 */
4
/* Authors:
1 by mental
moving trunk for module inkscape
5
 *   Lauris Kaplinski <lauris@kaplinski.com>
6
 *   Frank Felfe <innerspace@iname.com>
7
 *   MenTaLguY <mental@rydia.net>
8
 *   bulia byak <buliabyak@users.sf.net>
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
9
 *   Andrius R. <knutux@gmail.com>
8983 by Jon A. Cruz
Restore encapsulation of selection implementation.
10
 *   Jon A. Cruz <jon@joncruz.org>
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
11
 *   Martin Sucha <martin.sucha-inkscape@jts-sro.sk>
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
12
 *   Abhishek Sharma
1 by mental
moving trunk for module inkscape
13
 *
8983 by Jon A. Cruz
Restore encapsulation of selection implementation.
14
 * Copyright (C) 1999-2010 authors
1 by mental
moving trunk for module inkscape
15
 * Copyright (C) 2001-2002 Ximian, Inc.
16
 *
17
 * Released under GNU GPL, read the file 'COPYING' for more information
18
 */
19
20
#ifdef HAVE_CONFIG_H
21
# include "config.h"
22
#endif
23
4600 by johanengelen
add copy button to LPE pathparam
24
#include "selection-chemistry.h"
25
8983 by Jon A. Cruz
Restore encapsulation of selection implementation.
26
// TOOD fixme: This should be moved into preference repr
27
SPCycleType SP_CYCLING = SP_CYCLE_FOCUS;
28
29
1 by mental
moving trunk for module inkscape
30
#include <gtkmm/clipboard.h>
31
32
#include "svg/svg.h"
33
#include "desktop.h"
5866 by buliabyak
remove filters verb and command
34
#include "desktop-style.h"
7647 by pjrm
(sp_selection_create_bitmap_copy): Fix: Set xlink:href relative to the correct directory.
35
#include "dir-util.h"
1 by mental
moving trunk for module inkscape
36
#include "selection.h"
37
#include "tools-switch.h"
38
#include "desktop-handles.h"
39
#include "message-stack.h"
40
#include "sp-item-transform.h"
2077 by bryce
Renaming sp-marker.* to marker.*
41
#include "marker.h"
1 by mental
moving trunk for module inkscape
42
#include "sp-use.h"
43
#include "sp-textpath.h"
44
#include "sp-tspan.h"
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
45
#include "sp-tref.h"
1 by mental
moving trunk for module inkscape
46
#include "sp-flowtext.h"
47
#include "sp-flowregion.h"
9012.1.132 by Krzysztof Kosiński
Always embed bitmap copies created with Alt+B.
48
#include "sp-image.h"
1 by mental
moving trunk for module inkscape
49
#include "text-editing.h"
50
#include "text-context.h"
811 by mjwybrow
* src/selection-chemistry.cpp, src/sp-conn-end-pair.cpp:
51
#include "connector-context.h"
52
#include "sp-path.h"
53
#include "sp-conn-end.h"
1 by mental
moving trunk for module inkscape
54
#include "dropper-context.h"
55
#include <glibmm/i18n.h>
6884 by Ted Gould
Merging from trunk
56
#include <2geom/transforms.h>
1 by mental
moving trunk for module inkscape
57
#include "xml/repr.h"
7647 by pjrm
(sp_selection_create_bitmap_copy): Fix: Set xlink:href relative to the correct directory.
58
#include "xml/rebase-hrefs.h"
1 by mental
moving trunk for module inkscape
59
#include "style.h"
60
#include "document-private.h"
61
#include "sp-gradient.h"
62
#include "sp-gradient-reference.h"
63
#include "sp-linear-gradient-fns.h"
64
#include "sp-pattern.h"
65
#include "sp-radial-gradient-fns.h"
8983 by Jon A. Cruz
Restore encapsulation of selection implementation.
66
#include "gradient-context.h"
1 by mental
moving trunk for module inkscape
67
#include "sp-namedview.h"
6823 by tweenk
Refactored preferences handling into a new version of
68
#include "preferences.h"
1 by mental
moving trunk for module inkscape
69
#include "sp-offset.h"
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
70
#include "sp-clippath.h"
71
#include "sp-mask.h"
1 by mental
moving trunk for module inkscape
72
#include "file.h"
1431 by ishmal
factor native PNG export out of file.cpp in preparation for new export dialog
73
#include "helper/png-write.h"
1 by mental
moving trunk for module inkscape
74
#include "layer-fns.h"
75
#include "context-fns.h"
269 by knutux
Mask/Clippath transformations on masking/unmasking
76
#include <map>
4629 by bryce
Applying fixes for gcc 4.3 build issues (closes LP: #169115)
77
#include <cstring>
78
#include <string>
539 by acspike
Adding fit canvas verbs
79
#include "helper/units.h"
80
#include "sp-item.h"
4462 by cilix42
Add possibility to convert objects (only rectangles and 3D boxes currently) to guidelines. Also see corresponding post on the mailing list; in particular, feel free to revert it if this is inappropriate during Frost phase.
81
#include "box3d.h"
8911 by Maximilian Albert
Major simplification of 3D box code.
82
#include "persp3d.h"
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
83
#include "unit-constants.h"
2723 by mental
plumb XML::Document parameter into duplication, courtesy of bryce
84
#include "xml/simple-document.h"
3116 by buliabyak
switch SPStyle to using SPFilterReference for filters; sp_style_new now requires an SPDocument; SPURIReference and SPFilterReference have an alternative constructor taking an owner_document instead of owner object
85
#include "sp-filter-reference.h"
3943 by buliabyak
ensure copy/paste of style between gradient stops works
86
#include "gradient-drag.h"
4367 by johanengelen
+ Fix bug #179840, forking of LPEs
87
#include "uri-references.h"
6573 by buliabyak
add flashing line from clone to original on Shift+D
88
#include "display/curve.h"
89
#include "display/canvas-bpath.h"
7216 by buliabyak
use the same steps to figure out dir for bitmap copy as in export dialog
90
#include "inkscape-private.h"
8983 by Jon A. Cruz
Restore encapsulation of selection implementation.
91
#include "path-chemistry.h"
92
#include "ui/tool/control-point-selection.h"
93
#include "ui/tool/multi-path-manipulator.h"
2723 by mental
plumb XML::Document parameter into duplication, courtesy of bryce
94
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
95
#include "enums.h"
96
#include "sp-item-group.h"
97
4834 by johanengelen
* on-canvas clip and mask editing :) in the object menu you can find how to edit them.
98
// For clippath editing
99
#include "tools-switch.h"
8846.1.1 by Krzysztof Kosiński
First GSoC node tool commit to Bazaar
100
#include "ui/tool/node-tool.h"
4834 by johanengelen
* on-canvas clip and mask editing :) in the object menu you can find how to edit them.
101
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
102
#include "ui/clipboard.h"
103
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
104
using Inkscape::DocumentUndo;
7032 by verbalshadow
More NR ==> Geom changes
105
using Geom::X;
106
using Geom::Y;
1 by mental
moving trunk for module inkscape
107
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
108
/* The clipboard handling is in ui/clipboard.cpp now. There are some legacy functions left here,
109
because the layer manipulation code uses them. It should be rewritten specifically
110
for that purpose. */
1 by mental
moving trunk for module inkscape
111
8983 by Jon A. Cruz
Restore encapsulation of selection implementation.
112
113
114
namespace Inkscape {
115
116
void SelectionHelper::selectAll(SPDesktop *dt)
117
{
118
    if (tools_isactive(dt, TOOLS_NODES)) {
119
        InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
9012.1.58 by Krzysztof Kosiński
Fix multiple minor problems in the node tool
120
        if (!nt->_multipath->empty()) {
121
            nt->_multipath->selectSubpaths();
122
            return;
123
        }
8983 by Jon A. Cruz
Restore encapsulation of selection implementation.
124
    }
9012.1.58 by Krzysztof Kosiński
Fix multiple minor problems in the node tool
125
    sp_edit_select_all(dt);
8983 by Jon A. Cruz
Restore encapsulation of selection implementation.
126
}
127
128
void SelectionHelper::selectAllInAll(SPDesktop *dt)
129
{
130
    if (tools_isactive(dt, TOOLS_NODES)) {
131
        InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
132
        nt->_selected_nodes->selectAll();
133
    } else {
134
        sp_edit_select_all_in_all_layers(dt);
135
    }
136
}
137
138
void SelectionHelper::selectNone(SPDesktop *dt)
139
{
140
    if (tools_isactive(dt, TOOLS_NODES)) {
141
        InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
142
        nt->_selected_nodes->clear();
143
    } else {
144
        sp_desktop_selection(dt)->clear();
145
    }
146
}
147
148
void SelectionHelper::invert(SPDesktop *dt)
149
{
150
    if (tools_isactive(dt, TOOLS_NODES)) {
151
        InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
152
        nt->_multipath->invertSelectionInSubpaths();
153
    } else {
154
        sp_edit_invert(dt);
155
    }
156
}
157
158
void SelectionHelper::invertAllInAll(SPDesktop *dt)
159
{
160
    if (tools_isactive(dt, TOOLS_NODES)) {
161
        InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
162
        nt->_selected_nodes->invertSelection();
163
    } else {
164
        sp_edit_invert_in_all_layers(dt);
165
    }
166
}
167
168
void SelectionHelper::reverse(SPDesktop *dt)
169
{
170
    // TODO make this a virtual method of event context!
171
    if (tools_isactive(dt, TOOLS_NODES)) {
172
        InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
173
        nt->_multipath->reverseSubpaths();
174
    } else {
175
        sp_selected_path_reverse(dt);
176
    }
177
}
178
179
void SelectionHelper::selectNext(SPDesktop *dt)
180
{
181
    SPEventContext *ec = dt->event_context;
182
    if (tools_isactive(dt, TOOLS_NODES)) {
183
        InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
184
        nt->_multipath->shiftSelection(1);
185
    } else if (tools_isactive(dt, TOOLS_GRADIENT)
186
               && ec->_grdrag->isNonEmpty()) {
187
        sp_gradient_context_select_next(ec);
188
    } else {
189
        sp_selection_item_next(dt);
190
    }
191
}
192
193
void SelectionHelper::selectPrev(SPDesktop *dt)
194
{
195
    SPEventContext *ec = dt->event_context;
196
    if (tools_isactive(dt, TOOLS_NODES)) {
197
        InkNodeTool *nt = static_cast<InkNodeTool*>(dt->event_context);
198
        nt->_multipath->shiftSelection(-1);
199
    } else if (tools_isactive(dt, TOOLS_GRADIENT)
200
               && ec->_grdrag->isNonEmpty()) {
201
        sp_gradient_context_select_prev(ec);
202
    } else {
203
        sp_selection_item_prev(dt);
204
    }
205
}
206
207
} // namespace Inkscape
208
209
1985 by bryce
Adding some documentation for things related to markers
210
/**
211
 * Copies repr and its inherited css style elements, along with the accumulated transform 'full_t',
212
 * then prepends the copy to 'clip'.
213
 */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
214
void sp_selection_copy_one(Inkscape::XML::Node *repr, Geom::Affine full_t, GSList **clip, Inkscape::XML::Document* xml_doc)
1 by mental
moving trunk for module inkscape
215
{
2723 by mental
plumb XML::Document parameter into duplication, courtesy of bryce
216
    Inkscape::XML::Node *copy = repr->duplicate(xml_doc);
1 by mental
moving trunk for module inkscape
217
218
    // copy complete inherited style
219
    SPCSSAttr *css = sp_repr_css_attr_inherited(repr, "style");
220
    sp_repr_css_set(copy, css, "style");
221
    sp_repr_css_attr_unref(css);
222
1985 by bryce
Adding some documentation for things related to markers
223
    // write the complete accumulated transform passed to us
4025 by joncruz
Warning cleanup
224
    // (we're dealing with unattached repr, so we write to its attr
1985 by bryce
Adding some documentation for things related to markers
225
    // instead of using sp_item_set_transform)
2466 by mental
refactor sp_svg_transform_write to return a dynamically-allocated string
226
    gchar *affinestr=sp_svg_transform_write(full_t);
227
    copy->setAttribute("transform", affinestr);
228
    g_free(affinestr);
1 by mental
moving trunk for module inkscape
229
230
    *clip = g_slist_prepend(*clip, copy);
231
}
232
7645 by pjrm
noop: whitespace
233
void sp_selection_copy_impl(GSList const *items, GSList **clip, Inkscape::XML::Document* xml_doc)
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
234
{
235
    // Sort items:
7645 by pjrm
noop: whitespace
236
    GSList *sorted_items = g_slist_copy((GSList *) items);
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
237
    sorted_items = g_slist_sort((GSList *) sorted_items, (GCompareFunc) sp_object_compare_position);
238
239
    // Copy item reprs:
240
    for (GSList *i = (GSList *) sorted_items; i != NULL; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
241
        sp_selection_copy_one(SP_OBJECT(i->data)->getRepr(), SP_ITEM(i->data)->i2doc_affine(), clip, xml_doc);
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
242
    }
243
244
    *clip = g_slist_reverse(*clip);
7645 by pjrm
noop: whitespace
245
    g_slist_free((GSList *) sorted_items);
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
246
}
247
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
248
GSList *sp_selection_paste_impl(SPDocument *doc, SPObject *parent, GSList **clip)
1 by mental
moving trunk for module inkscape
249
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
250
    Inkscape::XML::Document *xml_doc = doc->getReprDoc();
1 by mental
moving trunk for module inkscape
251
252
    GSList *copied = NULL;
253
    // add objects to document
254
    for (GSList *l = *clip; l != NULL; l = l->next) {
255
        Inkscape::XML::Node *repr = (Inkscape::XML::Node *) l->data;
2723 by mental
plumb XML::Document parameter into duplication, courtesy of bryce
256
        Inkscape::XML::Node *copy = repr->duplicate(xml_doc);
1 by mental
moving trunk for module inkscape
257
258
        // premultiply the item transform by the accumulated parent transform in the paste layer
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
259
        Geom::Affine local(SP_ITEM(parent)->i2doc_affine());
7032 by verbalshadow
More NR ==> Geom changes
260
        if (!local.isIdentity()) {
1 by mental
moving trunk for module inkscape
261
            gchar const *t_str = copy->attribute("transform");
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
262
            Geom::Affine item_t(Geom::identity());
1 by mental
moving trunk for module inkscape
263
            if (t_str)
264
                sp_svg_transform_read(t_str, &item_t);
265
            item_t *= local.inverse();
266
            // (we're dealing with unattached repr, so we write to its attr instead of using sp_item_set_transform)
2466 by mental
refactor sp_svg_transform_write to return a dynamically-allocated string
267
            gchar *affinestr=sp_svg_transform_write(item_t);
268
            copy->setAttribute("transform", affinestr);
269
            g_free(affinestr);
1 by mental
moving trunk for module inkscape
270
        }
271
272
        parent->appendChildRepr(copy);
273
        copied = g_slist_prepend(copied, copy);
274
        Inkscape::GC::release(copy);
275
    }
276
    return copied;
277
}
278
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
279
void sp_selection_delete_impl(GSList const *items, bool propagate = true, bool propagate_descendants = true)
1 by mental
moving trunk for module inkscape
280
{
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
281
    for (GSList const *i = items ; i ; i = i->next ) {
1 by mental
moving trunk for module inkscape
282
        sp_object_ref((SPObject *)i->data, NULL);
283
    }
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
284
    for (GSList const *i = items; i != NULL; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
285
        SPItem *item = reinterpret_cast<SPItem *>(i->data);
286
        item->deleteObject(propagate, propagate_descendants);
287
        sp_object_unref(item, NULL);
1 by mental
moving trunk for module inkscape
288
    }
289
}
290
291
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
292
void sp_selection_delete(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
293
{
294
    if (desktop == NULL) {
295
        return;
296
    }
297
7645 by pjrm
noop: whitespace
298
    if (tools_isactive(desktop, TOOLS_TEXT))
1 by mental
moving trunk for module inkscape
299
        if (sp_text_delete_selection(desktop->event_context)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
300
            DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT,
301
                               _("Delete text"));
1 by mental
moving trunk for module inkscape
302
            return;
303
        }
304
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
305
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
306
307
    // check if something is selected
308
    if (selection->isEmpty()) {
309
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("<b>Nothing</b> was deleted."));
310
        return;
311
    }
312
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
313
    GSList const *selected = g_slist_copy(const_cast<GSList *>(selection->itemList()));
1 by mental
moving trunk for module inkscape
314
    selection->clear();
7645 by pjrm
noop: whitespace
315
    sp_selection_delete_impl(selected);
316
    g_slist_free((GSList *) selected);
1 by mental
moving trunk for module inkscape
317
318
    /* a tool may have set up private information in it's selection context
319
     * that depends on desktop items.  I think the only sane way to deal with
320
     * this currently is to reset the current tool, which will reset it's
321
     * associated selection context.  For example: deleting an object
322
     * while moving it around the canvas.
323
     */
7645 by pjrm
noop: whitespace
324
    tools_switch( desktop, tools_active( desktop ) );
1 by mental
moving trunk for module inkscape
325
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
326
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_DELETE,
327
                       _("Delete"));
1 by mental
moving trunk for module inkscape
328
}
329
7645 by pjrm
noop: whitespace
330
void add_ids_recursive(std::vector<const gchar *> &ids, SPObject *obj)
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
331
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
332
    if (obj) {
333
        ids.push_back(obj->getId());
334
335
        if (SP_IS_GROUP(obj)) {
336
            for (SPObject *child = obj->firstChild() ; child; child = child->getNext() ) {
337
                add_ids_recursive(ids, child);
338
            }
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
339
        }
340
    }
341
}
342
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
343
void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone)
1 by mental
moving trunk for module inkscape
344
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
345
    if (desktop == NULL) {
1 by mental
moving trunk for module inkscape
346
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
347
    }
1 by mental
moving trunk for module inkscape
348
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
349
    SPDocument *doc = desktop->doc();
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
350
    Inkscape::XML::Document* xml_doc = doc->getReprDoc();
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
351
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
352
353
    // check if something is selected
354
    if (selection->isEmpty()) {
355
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to duplicate."));
356
        return;
357
    }
358
359
    GSList *reprs = g_slist_copy((GSList *) selection->reprList());
360
361
    selection->clear();
362
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
363
    // sorting items from different parents sorts each parent's subset without possibly mixing
364
    // them, just what we need
1 by mental
moving trunk for module inkscape
365
    reprs = g_slist_sort(reprs, (GCompareFunc) sp_repr_compare_position);
366
367
    GSList *newsel = NULL;
368
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
369
    std::vector<const gchar *> old_ids;
370
    std::vector<const gchar *> new_ids;
6823 by tweenk
Refactored preferences handling into a new version of
371
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
372
    bool relink_clones = prefs->getBool("/options/relinkclonesonduplicate/value");
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
373
1 by mental
moving trunk for module inkscape
374
    while (reprs) {
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
375
        Inkscape::XML::Node *old_repr = (Inkscape::XML::Node *) reprs->data;
376
        Inkscape::XML::Node *parent = old_repr->parent();
377
        Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
1 by mental
moving trunk for module inkscape
378
379
        parent->appendChild(copy);
380
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
381
        if (relink_clones) {
382
            SPObject *old_obj = doc->getObjectByRepr(old_repr);
383
            SPObject *new_obj = doc->getObjectByRepr(copy);
7645 by pjrm
noop: whitespace
384
            add_ids_recursive(old_ids, old_obj);
385
            add_ids_recursive(new_ids, new_obj);
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
386
        }
387
1 by mental
moving trunk for module inkscape
388
        newsel = g_slist_prepend(newsel, copy);
389
        reprs = g_slist_remove(reprs, reprs->data);
390
        Inkscape::GC::release(copy);
391
    }
392
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
393
    if (relink_clones) {
394
7645 by pjrm
noop: whitespace
395
        g_assert(old_ids.size() == new_ids.size());
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
396
7645 by pjrm
noop: whitespace
397
        for (unsigned int i = 0; i < old_ids.size(); i++) {
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
398
            const gchar *id = old_ids[i];
399
            SPObject *old_clone = doc->getObjectById(id);
400
            if (SP_IS_USE(old_clone)) {
401
                SPItem *orig = sp_use_get_original(SP_USE(old_clone));
7444 by buliabyak
fix crash when duplicating an orphaned clone
402
                if (!orig) // orphaned
403
                    continue;
7645 by pjrm
noop: whitespace
404
                for (unsigned int j = 0; j < old_ids.size(); j++) {
9012.1.115 by Jon A. Cruz
Cleanup on id access.
405
                    if (!strcmp(orig->getId(), old_ids[j])) {
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
406
                        // we have both orig and clone in selection, relink
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
407
                        // std::cout << id  << " old, its ori: " << orig->getId() << "; will relink:" << new_ids[i] << " to " << new_ids[j] << "\n";
7645 by pjrm
noop: whitespace
408
                        gchar *newref = g_strdup_printf("#%s", new_ids[j]);
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
409
                        SPObject *new_clone = doc->getObjectById(new_ids[i]);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
410
                        new_clone->getRepr()->setAttribute("xlink:href", newref);
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
411
                        new_clone->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
7645 by pjrm
noop: whitespace
412
                        g_free(newref);
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
413
                    }
414
                }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
415
            } else if (SP_IS_OFFSET(old_clone)) {
416
                for (guint j = 0; j < old_ids.size(); j++) {
417
                gchar *source_href = SP_OFFSET(old_clone)->sourceHref;
418
                    if (source_href && source_href[0]=='#' && !strcmp(source_href+1, old_ids[j])) {
419
                        gchar *newref = g_strdup_printf("#%s", new_ids[j]);
420
                        doc->getObjectById(new_ids[i])->getRepr()->setAttribute("xlink:href", newref);
421
                        g_free(newref);
422
                    }
423
                }
6570 by buliabyak
optionally (default off) relink duplicated clones to the duplicated original
424
            }
425
        }
426
    }
427
428
5927 by joncruz
Added duplicate layer command. Fixes bug #171246.
429
    if ( !suppressDone ) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
430
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_DUPLICATE,
431
                           _("Duplicate"));
5927 by joncruz
Added duplicate layer command. Fixes bug #171246.
432
    }
1 by mental
moving trunk for module inkscape
433
434
    selection->setReprList(newsel);
435
436
    g_slist_free(newsel);
437
}
438
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
439
void sp_edit_clear_all(SPDesktop *dt)
1 by mental
moving trunk for module inkscape
440
{
441
    if (!dt)
442
        return;
443
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
444
    SPDocument *doc = sp_desktop_document(dt);
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
445
    sp_desktop_selection(dt)->clear();
1 by mental
moving trunk for module inkscape
446
447
    g_return_if_fail(SP_IS_GROUP(dt->currentLayer()));
448
    GSList *items = sp_item_group_item_list(SP_GROUP(dt->currentLayer()));
449
450
    while (items) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
451
        reinterpret_cast<SPObject*>(items->data)->deleteObject();
1 by mental
moving trunk for module inkscape
452
        items = g_slist_remove(items, items->data);
453
    }
454
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
455
    DocumentUndo::done(doc, SP_VERB_EDIT_CLEAR_ALL,
456
                       _("Delete all"));
1 by mental
moving trunk for module inkscape
457
}
458
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
459
GSList *get_all_items(GSList *list, SPObject *from, SPDesktop *desktop, bool onlyvisible, bool onlysensitive, GSList const *exclude)
1 by mental
moving trunk for module inkscape
460
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
461
    for ( SPObject *child = from->firstChild() ; child; child = child->getNext() ) {
1 by mental
moving trunk for module inkscape
462
        if (SP_IS_ITEM(child) &&
463
            !desktop->isLayer(SP_ITEM(child)) &&
134 by rwst
bulk whitespace removal patch #1198588 by gigaclon
464
            (!onlysensitive || !SP_ITEM(child)->isLocked()) &&
1 by mental
moving trunk for module inkscape
465
            (!onlyvisible || !desktop->itemIsHidden(SP_ITEM(child))) &&
7645 by pjrm
noop: whitespace
466
            (!exclude || !g_slist_find((GSList *) exclude, child))
1 by mental
moving trunk for module inkscape
467
            )
468
        {
7645 by pjrm
noop: whitespace
469
            list = g_slist_prepend(list, SP_ITEM(child));
1 by mental
moving trunk for module inkscape
470
        }
471
472
        if (SP_IS_ITEM(child) && desktop->isLayer(SP_ITEM(child))) {
7645 by pjrm
noop: whitespace
473
            list = get_all_items(list, child, desktop, onlyvisible, onlysensitive, exclude);
1 by mental
moving trunk for module inkscape
474
        }
475
    }
476
477
    return list;
478
}
479
7645 by pjrm
noop: whitespace
480
void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool invert)
1 by mental
moving trunk for module inkscape
481
{
482
    if (!dt)
483
        return;
484
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
485
    Inkscape::Selection *selection = sp_desktop_selection(dt);
1 by mental
moving trunk for module inkscape
486
487
    g_return_if_fail(SP_IS_GROUP(dt->currentLayer()));
7645 by pjrm
noop: whitespace
488
6823 by tweenk
Refactored preferences handling into a new version of
489
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
490
    PrefsSelectionContext inlayer = (PrefsSelectionContext) prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER);
491
    bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true);
492
    bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true);
1 by mental
moving trunk for module inkscape
493
494
    GSList *items = NULL;
495
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
496
    GSList const *exclude = NULL;
1 by mental
moving trunk for module inkscape
497
    if (invert) {
498
        exclude = selection->itemList();
499
    }
500
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
501
    if (force_all_layers)
502
        inlayer = PREFS_SELECTION_ALL;
1 by mental
moving trunk for module inkscape
503
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
504
    switch (inlayer) {
505
        case PREFS_SELECTION_LAYER: {
1 by mental
moving trunk for module inkscape
506
        if ( (onlysensitive && SP_ITEM(dt->currentLayer())->isLocked()) ||
507
             (onlyvisible && dt->itemIsHidden(SP_ITEM(dt->currentLayer()))) )
508
        return;
509
510
        GSList *all_items = sp_item_group_item_list(SP_GROUP(dt->currentLayer()));
511
512
        for (GSList *i = all_items; i; i = i->next) {
7645 by pjrm
noop: whitespace
513
            SPItem *item = SP_ITEM(i->data);
1 by mental
moving trunk for module inkscape
514
515
            if (item && (!onlysensitive || !item->isLocked())) {
516
                if (!onlyvisible || !dt->itemIsHidden(item)) {
517
                    if (!dt->isLayer(item)) {
7645 by pjrm
noop: whitespace
518
                        if (!invert || !g_slist_find((GSList *) exclude, item)) {
519
                            items = g_slist_prepend(items, item); // leave it in the list
1 by mental
moving trunk for module inkscape
520
                        }
521
                    }
522
                }
523
            }
524
        }
525
7645 by pjrm
noop: whitespace
526
        g_slist_free(all_items);
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
527
            break;
528
        }
529
        case PREFS_SELECTION_LAYER_RECURSIVE: {
7645 by pjrm
noop: whitespace
530
            items = get_all_items(NULL, dt->currentLayer(), dt, onlyvisible, onlysensitive, exclude);
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
531
            break;
532
        }
533
        default: {
7645 by pjrm
noop: whitespace
534
        items = get_all_items(NULL, dt->currentRoot(), dt, onlyvisible, onlysensitive, exclude);
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
535
            break;
536
    }
1 by mental
moving trunk for module inkscape
537
    }
538
7645 by pjrm
noop: whitespace
539
    selection->setList(items);
1 by mental
moving trunk for module inkscape
540
541
    if (items) {
7645 by pjrm
noop: whitespace
542
        g_slist_free(items);
1 by mental
moving trunk for module inkscape
543
    }
544
}
545
7645 by pjrm
noop: whitespace
546
void sp_edit_select_all(SPDesktop *desktop)
547
{
548
    sp_edit_select_all_full(desktop, false, false);
549
}
550
551
void sp_edit_select_all_in_all_layers(SPDesktop *desktop)
552
{
553
    sp_edit_select_all_full(desktop, true, false);
554
}
555
556
void sp_edit_invert(SPDesktop *desktop)
557
{
558
    sp_edit_select_all_full(desktop, false, true);
559
}
560
561
void sp_edit_invert_in_all_layers(SPDesktop *desktop)
562
{
563
    sp_edit_select_all_full(desktop, true, true);
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
564
}
565
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
566
void sp_selection_group_impl(GSList *p, Inkscape::XML::Node *group, Inkscape::XML::Document *xml_doc, SPDocument *doc) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
567
1 by mental
moving trunk for module inkscape
568
    p = g_slist_sort(p, (GCompareFunc) sp_repr_compare_position);
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
569
1 by mental
moving trunk for module inkscape
570
    // Remember the position and parent of the topmost object.
571
    gint topmost = ((Inkscape::XML::Node *) g_slist_last(p)->data)->position();
572
    Inkscape::XML::Node *topmost_parent = ((Inkscape::XML::Node *) g_slist_last(p)->data)->parent();
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
573
1 by mental
moving trunk for module inkscape
574
    while (p) {
575
        Inkscape::XML::Node *current = (Inkscape::XML::Node *) p->data;
576
577
        if (current->parent() == topmost_parent) {
2723 by mental
plumb XML::Document parameter into duplication, courtesy of bryce
578
            Inkscape::XML::Node *spnew = current->duplicate(xml_doc);
1 by mental
moving trunk for module inkscape
579
            sp_repr_unparent(current);
580
            group->appendChild(spnew);
581
            Inkscape::GC::release(spnew);
582
            topmost --; // only reduce count for those items deleted from topmost_parent
583
        } else { // move it to topmost_parent first
7645 by pjrm
noop: whitespace
584
            GSList *temp_clip = NULL;
585
586
            // At this point, current may already have no item, due to its being a clone whose original is already moved away
587
            // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent transform
588
            gchar const *t_str = current->attribute("transform");
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
589
            Geom::Affine item_t(Geom::identity());
7645 by pjrm
noop: whitespace
590
            if (t_str)
591
                sp_svg_transform_read(t_str, &item_t);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
592
            item_t *= SP_ITEM(doc->getObjectByRepr(current->parent()))->i2doc_affine();
7645 by pjrm
noop: whitespace
593
            // FIXME: when moving both clone and original from a transformed group (either by
594
            // grouping into another parent, or by cut/paste) the transform from the original's
595
            // parent becomes embedded into original itself, and this affects its clones. Fix
596
            // this by remembering the transform diffs we write to each item into an array and
597
            // then, if this is clone, looking up its original in that array and pre-multiplying
598
            // it by the inverse of that original's transform diff.
599
600
            sp_selection_copy_one(current, item_t, &temp_clip, xml_doc);
601
            sp_repr_unparent(current);
602
603
            // paste into topmost_parent (temporarily)
604
            GSList *copied = sp_selection_paste_impl(doc, doc->getObjectByRepr(topmost_parent), &temp_clip);
605
            if (temp_clip) g_slist_free(temp_clip);
606
            if (copied) { // if success,
607
                // take pasted object (now in topmost_parent)
608
                Inkscape::XML::Node *in_topmost = (Inkscape::XML::Node *) copied->data;
609
                // make a copy
610
                Inkscape::XML::Node *spnew = in_topmost->duplicate(xml_doc);
611
                // remove pasted
612
                sp_repr_unparent(in_topmost);
613
                // put its copy into group
614
                group->appendChild(spnew);
615
                Inkscape::GC::release(spnew);
616
                g_slist_free(copied);
617
            }
1 by mental
moving trunk for module inkscape
618
        }
619
        p = g_slist_remove(p, current);
620
    }
621
622
    // Add the new group to the topmost members' parent
623
    topmost_parent->appendChild(group);
624
625
    // Move to the position of the topmost, reduced by the number of items deleted from topmost_parent
626
    group->setPosition(topmost + 1);
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
627
}
628
629
void sp_selection_group(SPDesktop *desktop)
630
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
631
    if (desktop == NULL) {
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
632
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
633
    }
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
634
635
    SPDocument *doc = sp_desktop_document(desktop);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
636
    Inkscape::XML::Document *xml_doc = doc->getReprDoc();
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
637
638
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
639
640
    // Check if something is selected.
641
    if (selection->isEmpty()) {
642
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>some objects</b> to group."));
643
        return;
644
    }
645
646
    GSList const *l = (GSList *) selection->reprList();
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
647
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
648
    GSList *p = g_slist_copy((GSList *) l);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
649
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
650
    selection->clear();
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
651
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
652
    Inkscape::XML::Node *group = xml_doc->createElement("svg:g");
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
653
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
654
    sp_selection_group_impl(p, group, xml_doc, doc);
1 by mental
moving trunk for module inkscape
655
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
656
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_GROUP,
657
                       _("Group"));
1 by mental
moving trunk for module inkscape
658
659
    selection->set(group);
660
    Inkscape::GC::release(group);
661
}
662
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
663
void sp_selection_ungroup(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
664
{
665
    if (desktop == NULL)
666
        return;
667
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
668
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
669
670
    if (selection->isEmpty()) {
671
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select a <b>group</b> to ungroup."));
672
        return;
673
    }
674
675
    GSList *items = g_slist_copy((GSList *) selection->itemList());
676
    selection->clear();
677
678
    // Get a copy of current selection.
679
    GSList *new_select = NULL;
680
    bool ungrouped = false;
681
    for (GSList *i = items;
682
         i != NULL;
683
         i = i->next)
684
    {
685
        SPItem *group = (SPItem *) i->data;
686
687
        // when ungrouping cloned groups with their originals, some objects that were selected may no more exist due to unlinking
688
        if (!SP_IS_OBJECT(group)) {
689
            continue;
690
        }
691
692
        /* We do not allow ungrouping <svg> etc. (lauris) */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
693
        if (strcmp(group->getRepr()->name(), "svg:g") && strcmp(group->getRepr()->name(), "svg:switch")) {
1 by mental
moving trunk for module inkscape
694
            // keep the non-group item in the new selection
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
695
            new_select = g_slist_append(new_select, group);
1 by mental
moving trunk for module inkscape
696
            continue;
697
        }
698
699
        GSList *children = NULL;
700
        /* This is not strictly required, but is nicer to rely on group ::destroy (lauris) */
701
        sp_item_group_ungroup(SP_GROUP(group), &children, false);
702
        ungrouped = true;
703
        // Add ungrouped items to the new selection.
704
        new_select = g_slist_concat(new_select, children);
705
    }
706
707
    if (new_select) { // Set new selection.
708
        selection->addList(new_select);
709
        g_slist_free(new_select);
710
    }
711
    if (!ungrouped) {
712
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No groups</b> to ungroup in the selection."));
713
    }
714
715
    g_slist_free(items);
716
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
717
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_UNGROUP,
718
                       _("Ungroup"));
1 by mental
moving trunk for module inkscape
719
}
720
7035 by buliabyak
add utility for recursively replacing groups with their members in a list of objects
721
/** Replace all groups in the list with their member objects, recursively; returns a new list, frees old */
722
GSList *
7645 by pjrm
noop: whitespace
723
sp_degroup_list(GSList *items)
7035 by buliabyak
add utility for recursively replacing groups with their members in a list of objects
724
{
725
    GSList *out = NULL;
726
    bool has_groups = false;
727
    for (GSList *item = items; item; item = item->next) {
728
        if (!SP_IS_GROUP(item->data)) {
729
            out = g_slist_prepend(out, item->data);
730
        } else {
731
            has_groups = true;
7645 by pjrm
noop: whitespace
732
            GSList *members = sp_item_group_item_list(SP_GROUP(item->data));
7035 by buliabyak
add utility for recursively replacing groups with their members in a list of objects
733
            for (GSList *member = members; member; member = member->next) {
734
                out = g_slist_prepend(out, member->data);
735
            }
7645 by pjrm
noop: whitespace
736
            g_slist_free(members);
7035 by buliabyak
add utility for recursively replacing groups with their members in a list of objects
737
        }
738
    }
7645 by pjrm
noop: whitespace
739
    out = g_slist_reverse(out);
740
    g_slist_free(items);
7035 by buliabyak
add utility for recursively replacing groups with their members in a list of objects
741
742
    if (has_groups) { // recurse if we unwrapped a group - it may have contained others
7645 by pjrm
noop: whitespace
743
        out = sp_degroup_list(out);
7035 by buliabyak
add utility for recursively replacing groups with their members in a list of objects
744
    }
745
746
    return out;
747
}
7645 by pjrm
noop: whitespace
748
7035 by buliabyak
add utility for recursively replacing groups with their members in a list of objects
749
750
/** If items in the list have a common parent, return it, otherwise return NULL */
1 by mental
moving trunk for module inkscape
751
static SPGroup *
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
752
sp_item_list_common_parent_group(GSList const *items)
1 by mental
moving trunk for module inkscape
753
{
754
    if (!items) {
755
        return NULL;
756
    }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
757
    SPObject *parent = SP_OBJECT(items->data)->parent;
758
    // Strictly speaking this CAN happen, if user selects <svg> from Inkscape::XML editor
1 by mental
moving trunk for module inkscape
759
    if (!SP_IS_GROUP(parent)) {
760
        return NULL;
761
    }
762
    for (items = items->next; items; items = items->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
763
        if (SP_OBJECT(items->data)->parent != parent) {
1 by mental
moving trunk for module inkscape
764
            return NULL;
765
        }
766
    }
767
768
    return SP_GROUP(parent);
769
}
770
3989 by pjrm
noop: comment style
771
/** Finds out the minimum common bbox of the selected items. */
6891 by Ted Gould
Merge from fe-moved
772
static Geom::OptRect
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
773
enclose_items(GSList const *items)
1 by mental
moving trunk for module inkscape
774
{
775
    g_assert(items != NULL);
776
6891 by Ted Gould
Merge from fe-moved
777
    Geom::OptRect r;
2538 by mental
adapt code to new Maybe/bbox regime
778
    for (GSList const *i = items; i; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
779
        r.unionWith(((SPItem *) i->data)->desktopVisualBounds());
1 by mental
moving trunk for module inkscape
780
    }
781
    return r;
782
}
783
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
784
// TODO determine if this is intentionally different from SPObject::getPrev()
785
SPObject *prev_sibling(SPObject *child)
1 by mental
moving trunk for module inkscape
786
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
787
    SPObject *prev = 0;
788
    if ( child && SP_IS_GROUP(child->parent) ) {
789
        prev = child->getPrev();
790
    }
791
    return prev;
1 by mental
moving trunk for module inkscape
792
}
793
794
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
795
sp_selection_raise(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
796
{
797
    if (!desktop)
798
        return;
799
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
800
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
801
802
    GSList const *items = (GSList *) selection->itemList();
803
    if (!items) {
804
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise."));
805
        return;
806
    }
807
808
    SPGroup const *group = sp_item_list_common_parent_group(items);
809
    if (!group) {
810
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
811
        return;
812
    }
813
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
814
    Inkscape::XML::Node *grepr = const_cast<Inkscape::XML::Node *>(group->getRepr());
1 by mental
moving trunk for module inkscape
815
3989 by pjrm
noop: comment style
816
    /* Construct reverse-ordered list of selected children. */
1 by mental
moving trunk for module inkscape
817
    GSList *rev = g_slist_copy((GSList *) items);
818
    rev = g_slist_sort(rev, (GCompareFunc) sp_item_repr_compare_position);
819
3989 by pjrm
noop: comment style
820
    // Determine the common bbox of the selected items.
6891 by Ted Gould
Merge from fe-moved
821
    Geom::OptRect selected = enclose_items(items);
1 by mental
moving trunk for module inkscape
822
3989 by pjrm
noop: comment style
823
    // Iterate over all objects in the selection (starting from top).
2538 by mental
adapt code to new Maybe/bbox regime
824
    if (selected) {
825
        while (rev) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
826
            SPObject *child = reinterpret_cast<SPObject*>(rev->data);
2538 by mental
adapt code to new Maybe/bbox regime
827
            // for each selected object, find the next sibling
828
            for (SPObject *newref = child->next; newref; newref = newref->next) {
829
                // if the sibling is an item AND overlaps our selection,
2596 by mental
Merge further bbox work
830
                if (SP_IS_ITEM(newref)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
831
                    Geom::OptRect newref_bbox = SP_ITEM(newref)->desktopVisualBounds();
2596 by mental
Merge further bbox work
832
                    if ( newref_bbox && selected->intersects(*newref_bbox) ) {
833
                        // AND if it's not one of our selected objects,
834
                        if (!g_slist_find((GSList *) items, newref)) {
835
                            // move the selected object after that sibling
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
836
                            grepr->changeOrder(child->getRepr(), newref->getRepr());
2596 by mental
Merge further bbox work
837
                        }
838
                        break;
2538 by mental
adapt code to new Maybe/bbox regime
839
                    }
1 by mental
moving trunk for module inkscape
840
                }
841
            }
2538 by mental
adapt code to new Maybe/bbox regime
842
            rev = g_slist_remove(rev, child);
1 by mental
moving trunk for module inkscape
843
        }
2538 by mental
adapt code to new Maybe/bbox regime
844
    } else {
845
        g_slist_free(rev);
1 by mental
moving trunk for module inkscape
846
    }
847
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
848
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_RAISE,
849
                       //TRANSLATORS: "Raise" means "to raise an object" in the undo history
850
                       C_("Undo action", "Raise"));
1 by mental
moving trunk for module inkscape
851
}
852
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
853
void sp_selection_raise_to_top(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
854
{
855
    if (desktop == NULL)
856
        return;
857
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
858
    SPDocument *document = sp_desktop_document(desktop);
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
859
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
860
861
    if (selection->isEmpty()) {
862
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise to top."));
863
        return;
864
    }
865
866
    GSList const *items = (GSList *) selection->itemList();
867
868
    SPGroup const *group = sp_item_list_common_parent_group(items);
869
    if (!group) {
870
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
871
        return;
872
    }
873
874
    GSList *rl = g_slist_copy((GSList *) selection->reprList());
875
    rl = g_slist_sort(rl, (GCompareFunc) sp_repr_compare_position);
876
877
    for (GSList *l = rl; l != NULL; l = l->next) {
878
        Inkscape::XML::Node *repr = (Inkscape::XML::Node *) l->data;
879
        repr->setPosition(-1);
880
    }
881
882
    g_slist_free(rl);
883
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
884
    DocumentUndo::done(document, SP_VERB_SELECTION_TO_FRONT,
885
                       _("Raise to top"));
1 by mental
moving trunk for module inkscape
886
}
887
888
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
889
sp_selection_lower(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
890
{
891
    if (desktop == NULL)
892
        return;
893
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
894
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
895
896
    GSList const *items = (GSList *) selection->itemList();
897
    if (!items) {
898
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower."));
899
        return;
900
    }
901
902
    SPGroup const *group = sp_item_list_common_parent_group(items);
903
    if (!group) {
904
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
905
        return;
906
    }
907
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
908
    Inkscape::XML::Node *grepr = const_cast<Inkscape::XML::Node *>(group->getRepr());
1 by mental
moving trunk for module inkscape
909
3989 by pjrm
noop: comment style
910
    // Determine the common bbox of the selected items.
6891 by Ted Gould
Merge from fe-moved
911
    Geom::OptRect selected = enclose_items(items);
1 by mental
moving trunk for module inkscape
912
3989 by pjrm
noop: comment style
913
    /* Construct direct-ordered list of selected children. */
1 by mental
moving trunk for module inkscape
914
    GSList *rev = g_slist_copy((GSList *) items);
915
    rev = g_slist_sort(rev, (GCompareFunc) sp_item_repr_compare_position);
916
    rev = g_slist_reverse(rev);
917
3989 by pjrm
noop: comment style
918
    // Iterate over all objects in the selection (starting from top).
2538 by mental
adapt code to new Maybe/bbox regime
919
    if (selected) {
920
        while (rev) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
921
            SPObject *child = reinterpret_cast<SPObject*>(rev->data);
2538 by mental
adapt code to new Maybe/bbox regime
922
            // for each selected object, find the prev sibling
923
            for (SPObject *newref = prev_sibling(child); newref; newref = prev_sibling(newref)) {
924
                // if the sibling is an item AND overlaps our selection,
2596 by mental
Merge further bbox work
925
                if (SP_IS_ITEM(newref)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
926
                    Geom::OptRect ref_bbox = SP_ITEM(newref)->desktopVisualBounds();
2596 by mental
Merge further bbox work
927
                    if ( ref_bbox && selected->intersects(*ref_bbox) ) {
928
                        // AND if it's not one of our selected objects,
929
                        if (!g_slist_find((GSList *) items, newref)) {
930
                            // move the selected object before that sibling
931
                            SPObject *put_after = prev_sibling(newref);
932
                            if (put_after)
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
933
                                grepr->changeOrder(child->getRepr(), put_after->getRepr());
2596 by mental
Merge further bbox work
934
                            else
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
935
                                child->getRepr()->setPosition(0);
2596 by mental
Merge further bbox work
936
                        }
937
                        break;
2538 by mental
adapt code to new Maybe/bbox regime
938
                    }
1 by mental
moving trunk for module inkscape
939
                }
940
            }
2538 by mental
adapt code to new Maybe/bbox regime
941
            rev = g_slist_remove(rev, child);
1 by mental
moving trunk for module inkscape
942
        }
2538 by mental
adapt code to new Maybe/bbox regime
943
    } else {
944
        g_slist_free(rev);
1 by mental
moving trunk for module inkscape
945
    }
946
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
947
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_LOWER,
948
                       _("Lower"));
1 by mental
moving trunk for module inkscape
949
}
950
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
951
void sp_selection_lower_to_bottom(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
952
{
953
    if (desktop == NULL)
954
        return;
955
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
956
    SPDocument *document = sp_desktop_document(desktop);
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
957
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
958
959
    if (selection->isEmpty()) {
960
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower to bottom."));
961
        return;
962
    }
963
964
    GSList const *items = (GSList *) selection->itemList();
965
966
    SPGroup const *group = sp_item_list_common_parent_group(items);
967
    if (!group) {
968
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
969
        return;
970
    }
971
972
    GSList *rl;
973
    rl = g_slist_copy((GSList *) selection->reprList());
974
    rl = g_slist_sort(rl, (GCompareFunc) sp_repr_compare_position);
975
    rl = g_slist_reverse(rl);
976
977
    for (GSList *l = rl; l != NULL; l = l->next) {
978
        gint minpos;
979
        SPObject *pp, *pc;
980
        Inkscape::XML::Node *repr = (Inkscape::XML::Node *) l->data;
981
        pp = document->getObjectByRepr(sp_repr_parent(repr));
982
        minpos = 0;
983
        g_assert(SP_IS_GROUP(pp));
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
984
        pc = pp->firstChild();
1 by mental
moving trunk for module inkscape
985
        while (!SP_IS_ITEM(pc)) {
986
            minpos += 1;
987
            pc = pc->next;
988
        }
989
        repr->setPosition(minpos);
990
    }
991
992
    g_slist_free(rl);
993
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
994
    DocumentUndo::done(document, SP_VERB_SELECTION_TO_BACK,
995
                       _("Lower to bottom"));
1 by mental
moving trunk for module inkscape
996
}
997
998
void
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
999
sp_undo(SPDesktop *desktop, SPDocument *)
1 by mental
moving trunk for module inkscape
1000
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1001
    if (!DocumentUndo::undo(sp_desktop_document(desktop))) {
1002
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to undo."));
1003
    }
1 by mental
moving trunk for module inkscape
1004
}
1005
1006
void
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
1007
sp_redo(SPDesktop *desktop, SPDocument *)
1 by mental
moving trunk for module inkscape
1008
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1009
    if (!DocumentUndo::redo(sp_desktop_document(desktop))) {
1010
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to redo."));
1011
    }
1 by mental
moving trunk for module inkscape
1012
}
1013
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1014
void sp_selection_cut(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
1015
{
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1016
    sp_selection_copy(desktop);
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1017
    sp_selection_delete(desktop);
1 by mental
moving trunk for module inkscape
1018
}
1019
1020
/**
1021
 * \pre item != NULL
1022
 */
1023
SPCSSAttr *
7645 by pjrm
noop: whitespace
1024
take_style_from_item(SPItem *item)
1 by mental
moving trunk for module inkscape
1025
{
1026
    // write the complete cascaded style, context-free
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1027
    SPCSSAttr *css = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
1 by mental
moving trunk for module inkscape
1028
    if (css == NULL)
1029
        return NULL;
1030
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1031
    if ((SP_IS_GROUP(item) && item->children) ||
1032
        (SP_IS_TEXT(item) && item->children && item->children->next == NULL)) {
1 by mental
moving trunk for module inkscape
1033
        // if this is a text with exactly one tspan child, merge the style of that tspan as well
1034
        // If this is a group, merge the style of its topmost (last) child with style
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1035
        for (SPObject *last_element = item->lastChild(); last_element != NULL; last_element = last_element->getPrev()) {
1036
            if ( last_element->style ) {
7645 by pjrm
noop: whitespace
1037
                SPCSSAttr *temp = sp_css_attr_from_object(last_element, SP_STYLE_FLAG_IFSET);
1 by mental
moving trunk for module inkscape
1038
                if (temp) {
7645 by pjrm
noop: whitespace
1039
                    sp_repr_css_merge(css, temp);
1040
                    sp_repr_css_attr_unref(temp);
1 by mental
moving trunk for module inkscape
1041
                }
1042
                break;
1043
            }
1044
        }
1045
    }
7645 by pjrm
noop: whitespace
1046
    if (!(SP_IS_TEXT(item) || SP_IS_TSPAN(item) || SP_IS_TREF(item) || SP_IS_STRING(item))) {
1 by mental
moving trunk for module inkscape
1047
        // do not copy text properties from non-text objects, it's confusing
7645 by pjrm
noop: whitespace
1048
        css = sp_css_attr_unset_text(css);
1 by mental
moving trunk for module inkscape
1049
    }
1050
1051
    // FIXME: also transform gradient/pattern fills, by forking? NO, this must be nondestructive
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1052
    double ex = item->i2doc_affine().descrim();
1 by mental
moving trunk for module inkscape
1053
    if (ex != 1.0) {
7645 by pjrm
noop: whitespace
1054
        css = sp_css_attr_scale(css, ex);
1 by mental
moving trunk for module inkscape
1055
    }
1056
1057
    return css;
1058
}
1059
1060
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1061
void sp_selection_copy(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
1062
{
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
1063
    Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1064
    cm->copy(desktop);
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
1065
}
4135 by gorodish
Fix for Bug #1823541: Added support for pasting bitmap data from the system clipboard. See bug report for details.
1066
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1067
void sp_selection_paste(SPDesktop *desktop, bool in_place)
1 by mental
moving trunk for module inkscape
1068
{
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
1069
    Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1070
    if (cm->paste(desktop, in_place)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1071
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_PASTE, _("Paste"));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1072
    }
1 by mental
moving trunk for module inkscape
1073
}
1074
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1075
void sp_selection_paste_style(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
1076
{
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
1077
    Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1078
    if (cm->pasteStyle(desktop)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1079
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_PASTE_STYLE, _("Paste style"));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1080
    }
5119 by buliabyak
recurse into groups when pasting lpe
1081
}
1082
1083
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1084
void sp_selection_paste_livepatheffect(SPDesktop *desktop)
3675 by johanengelen
LPE: add Paste LPE verb + menu item. add scale ratios to curve stitch and path-along-path. remove trailing space in verbs.cpp. Fix initialization of BoolParam
1085
{
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
1086
    Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1087
    if (cm->pastePathEffect(desktop)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1088
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_PASTE_LIVEPATHEFFECT,
1089
                           _("Paste live path effect"));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1090
    }
3675 by johanengelen
LPE: add Paste LPE verb + menu item. add scale ratios to curve stitch and path-along-path. remove trailing space in verbs.cpp. Fix initialization of BoolParam
1091
}
1092
5120 by buliabyak
add delete lpe verb, rearrange menu to collect all lpe commands under path
1093
1094
void sp_selection_remove_livepatheffect_impl(SPItem *item)
1095
{
7645 by pjrm
noop: whitespace
1096
    if ( item && SP_IS_LPE_ITEM(item) &&
1097
         sp_lpe_item_has_path_effect(SP_LPE_ITEM(item))) {
5766 by johanengelen
LPE STACKING!
1098
        sp_lpe_item_remove_all_path_effects(SP_LPE_ITEM(item), false);
5120 by buliabyak
add delete lpe verb, rearrange menu to collect all lpe commands under path
1099
    }
1100
}
1101
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1102
void sp_selection_remove_livepatheffect(SPDesktop *desktop)
5120 by buliabyak
add delete lpe verb, rearrange menu to collect all lpe commands under path
1103
{
1104
    if (desktop == NULL) return;
1105
1106
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1107
1108
    // check if something is selected
1109
    if (selection->isEmpty()) {
1110
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to remove live path effects from."));
1111
        return;
1112
    }
1113
1114
    for ( GSList const *itemlist = selection->itemList(); itemlist != NULL; itemlist = g_slist_next(itemlist) ) {
1115
        SPItem *item = reinterpret_cast<SPItem*>(itemlist->data);
1116
1117
        sp_selection_remove_livepatheffect_impl(item);
1118
1119
    }
1120
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1121
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_REMOVE_LIVEPATHEFFECT,
1122
                       _("Remove live path effect"));
5120 by buliabyak
add delete lpe verb, rearrange menu to collect all lpe commands under path
1123
}
1124
7645 by pjrm
noop: whitespace
1125
void sp_selection_remove_filter(SPDesktop *desktop)
5866 by buliabyak
remove filters verb and command
1126
{
1127
    if (desktop == NULL) return;
1128
1129
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1130
1131
    // check if something is selected
1132
    if (selection->isEmpty()) {
1133
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to remove filters from."));
1134
        return;
1135
    }
1136
1137
    SPCSSAttr *css = sp_repr_css_attr_new();
1138
    sp_repr_css_unset_property(css, "filter");
1139
    sp_desktop_set_style(desktop, css);
1140
    sp_repr_css_attr_unref(css);
1141
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1142
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_REMOVE_FILTER,
1143
                       _("Remove filter"));
5866 by buliabyak
remove filters verb and command
1144
}
1145
1146
7645 by pjrm
noop: whitespace
1147
void sp_selection_paste_size(SPDesktop *desktop, bool apply_x, bool apply_y)
298 by buliabyak
pasting size
1148
{
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
1149
    Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1150
    if (cm->pasteSize(desktop, false, apply_x, apply_y)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1151
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_PASTE_SIZE,
1152
                           _("Paste size"));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1153
    }
298 by buliabyak
pasting size
1154
}
1155
7645 by pjrm
noop: whitespace
1156
void sp_selection_paste_size_separately(SPDesktop *desktop, bool apply_x, bool apply_y)
298 by buliabyak
pasting size
1157
{
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
1158
    Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1159
    if (cm->pasteSize(desktop, true, apply_x, apply_y)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1160
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_PASTE_SIZE_SEPARATELY,
1161
                           _("Paste size separately"));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
1162
    }
298 by buliabyak
pasting size
1163
}
1164
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1165
void sp_selection_to_next_layer(SPDesktop *dt, bool suppressDone)
1 by mental
moving trunk for module inkscape
1166
{
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
1167
    Inkscape::Selection *selection = sp_desktop_selection(dt);
1 by mental
moving trunk for module inkscape
1168
1169
    // check if something is selected
1170
    if (selection->isEmpty()) {
1171
        dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to move to the layer above."));
1172
        return;
1173
    }
1174
7645 by pjrm
noop: whitespace
1175
    GSList const *items = g_slist_copy((GSList *) selection->itemList());
1 by mental
moving trunk for module inkscape
1176
802 by buliabyak
patch 1484602 by Niko Kiirala
1177
    bool no_more = false; // Set to true, if no more layers above
1 by mental
moving trunk for module inkscape
1178
    SPObject *next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer());
1179
    if (next) {
1180
        GSList *temp_clip = NULL;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1181
        sp_selection_copy_impl(items, &temp_clip, dt->doc()->getReprDoc());
7645 by pjrm
noop: whitespace
1182
        sp_selection_delete_impl(items, false, false);
781 by buliabyak
patch from Niko Kiirala for bug 1482973
1183
        next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers
1184
        GSList *copied;
7645 by pjrm
noop: whitespace
1185
        if (next) {
1186
            copied = sp_selection_paste_impl(sp_desktop_document(dt), next, &temp_clip);
781 by buliabyak
patch from Niko Kiirala for bug 1482973
1187
        } else {
7645 by pjrm
noop: whitespace
1188
            copied = sp_selection_paste_impl(sp_desktop_document(dt), dt->currentLayer(), &temp_clip);
802 by buliabyak
patch 1484602 by Niko Kiirala
1189
            no_more = true;
781 by buliabyak
patch from Niko Kiirala for bug 1482973
1190
        }
1 by mental
moving trunk for module inkscape
1191
        selection->setReprList((GSList const *) copied);
7645 by pjrm
noop: whitespace
1192
        g_slist_free(copied);
1193
        if (temp_clip) g_slist_free(temp_clip);
802 by buliabyak
patch 1484602 by Niko Kiirala
1194
        if (next) dt->setCurrentLayer(next);
5927 by joncruz
Added duplicate layer command. Fixes bug #171246.
1195
        if ( !suppressDone ) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1196
            DocumentUndo::done(sp_desktop_document(dt), SP_VERB_LAYER_MOVE_TO_NEXT,
1197
                               _("Raise to next layer"));
5927 by joncruz
Added duplicate layer command. Fixes bug #171246.
1198
        }
1 by mental
moving trunk for module inkscape
1199
    } else {
802 by buliabyak
patch 1484602 by Niko Kiirala
1200
        no_more = true;
1201
    }
1202
1203
    if (no_more) {
1 by mental
moving trunk for module inkscape
1204
        dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No more layers above."));
1205
    }
1206
7645 by pjrm
noop: whitespace
1207
    g_slist_free((GSList *) items);
1 by mental
moving trunk for module inkscape
1208
}
1209
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1210
void sp_selection_to_prev_layer(SPDesktop *dt, bool suppressDone)
1 by mental
moving trunk for module inkscape
1211
{
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
1212
    Inkscape::Selection *selection = sp_desktop_selection(dt);
1 by mental
moving trunk for module inkscape
1213
1214
    // check if something is selected
1215
    if (selection->isEmpty()) {
1216
        dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to move to the layer below."));
1217
        return;
1218
    }
1219
7645 by pjrm
noop: whitespace
1220
    GSList const *items = g_slist_copy((GSList *) selection->itemList());
1 by mental
moving trunk for module inkscape
1221
802 by buliabyak
patch 1484602 by Niko Kiirala
1222
    bool no_more = false; // Set to true, if no more layers below
1 by mental
moving trunk for module inkscape
1223
    SPObject *next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer());
1224
    if (next) {
1225
        GSList *temp_clip = NULL;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1226
        sp_selection_copy_impl(items, &temp_clip, dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs
7645 by pjrm
noop: whitespace
1227
        sp_selection_delete_impl(items, false, false);
781 by buliabyak
patch from Niko Kiirala for bug 1482973
1228
        next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers
1229
        GSList *copied;
7645 by pjrm
noop: whitespace
1230
        if (next) {
1231
            copied = sp_selection_paste_impl(sp_desktop_document(dt), next, &temp_clip);
781 by buliabyak
patch from Niko Kiirala for bug 1482973
1232
        } else {
7645 by pjrm
noop: whitespace
1233
            copied = sp_selection_paste_impl(sp_desktop_document(dt), dt->currentLayer(), &temp_clip);
802 by buliabyak
patch 1484602 by Niko Kiirala
1234
            no_more = true;
781 by buliabyak
patch from Niko Kiirala for bug 1482973
1235
        }
1 by mental
moving trunk for module inkscape
1236
        selection->setReprList((GSList const *) copied);
7645 by pjrm
noop: whitespace
1237
        g_slist_free(copied);
1238
        if (temp_clip) g_slist_free(temp_clip);
802 by buliabyak
patch 1484602 by Niko Kiirala
1239
        if (next) dt->setCurrentLayer(next);
5927 by joncruz
Added duplicate layer command. Fixes bug #171246.
1240
        if ( !suppressDone ) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1241
            DocumentUndo::done(sp_desktop_document(dt), SP_VERB_LAYER_MOVE_TO_PREV,
1242
                               _("Lower to previous layer"));
5927 by joncruz
Added duplicate layer command. Fixes bug #171246.
1243
        }
1 by mental
moving trunk for module inkscape
1244
    } else {
802 by buliabyak
patch 1484602 by Niko Kiirala
1245
        no_more = true;
1246
    }
1247
1248
    if (no_more) {
1 by mental
moving trunk for module inkscape
1249
        dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No more layers below."));
1250
    }
1251
7645 by pjrm
noop: whitespace
1252
    g_slist_free((GSList *) items);
1 by mental
moving trunk for module inkscape
1253
}
1254
2424 by buliabyak
make selection_contains_both_clone_and_original reusable
1255
bool
7645 by pjrm
noop: whitespace
1256
selection_contains_original(SPItem *item, Inkscape::Selection *selection)
2425 by buliabyak
some more refactoring
1257
{
1258
    bool contains_original = false;
4025 by joncruz
Warning cleanup
1259
2425 by buliabyak
some more refactoring
1260
    bool is_use = SP_IS_USE(item);
1261
    SPItem *item_use = item;
1262
    SPItem *item_use_first = item;
1263
    while (is_use && item_use && !contains_original)
1264
    {
7645 by pjrm
noop: whitespace
1265
        item_use = sp_use_get_original(SP_USE(item_use));
2425 by buliabyak
some more refactoring
1266
        contains_original |= selection->includes(item_use);
1267
        if (item_use == item_use_first)
1268
            break;
1269
        is_use = SP_IS_USE(item_use);
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
1270
    }
4025 by joncruz
Warning cleanup
1271
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
1272
    // If it's a tref, check whether the object containing the character
1273
    // data is part of the selection
1274
    if (!contains_original && SP_IS_TREF(item)) {
1275
        contains_original = selection->includes(SP_TREF(item)->getObjectReferredTo());
1276
    }
4025 by joncruz
Warning cleanup
1277
2425 by buliabyak
some more refactoring
1278
    return contains_original;
1279
}
1280
1281
1282
bool
7645 by pjrm
noop: whitespace
1283
selection_contains_both_clone_and_original(Inkscape::Selection *selection)
2424 by buliabyak
make selection_contains_both_clone_and_original reusable
1284
{
1285
    bool clone_with_original = false;
1286
    for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
1287
        SPItem *item = SP_ITEM(l->data);
2425 by buliabyak
some more refactoring
1288
        clone_with_original |= selection_contains_original(item, selection);
4025 by joncruz
Warning cleanup
1289
        if (clone_with_original)
2424 by buliabyak
make selection_contains_both_clone_and_original reusable
1290
            break;
1291
    }
1292
    return clone_with_original;
1293
}
1294
36 by buliabyak
transform centers in sp_selection_apply_affine, comments
1295
/** Apply matrix to the selection.  \a set_i2d is normally true, which means objects are in the
1296
original transform, synced with their reprs, and need to jump to the new transform in one go. A
1297
value of set_i2d==false is only used by seltrans when it's dragging objects live (not outlines); in
1298
that case, items are already in the new position, but the repr is in the old, and this function
1299
then simply updates the repr from item->transform.
1300
 */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1301
void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d, bool compensate)
1 by mental
moving trunk for module inkscape
1302
{
1303
    if (selection->isEmpty())
1304
        return;
1305
8911 by Maximilian Albert
Major simplification of 3D box code.
1306
    // For each perspective with a box in selection, check whether all boxes are selected and
1307
    // unlink all non-selected boxes.
1308
    Persp3D *persp;
1309
    Persp3D *transf_persp;
1310
    std::list<Persp3D *> plist = selection->perspList();
1311
    for (std::list<Persp3D *>::iterator i = plist.begin(); i != plist.end(); ++i) {
1312
        persp = (Persp3D *) (*i);
1313
1314
        if (!persp3d_has_all_boxes_in_selection (persp, selection)) {
1315
            std::list<SPBox3D *> selboxes = selection->box3DList(persp);
1316
1317
            // create a new perspective as a copy of the current one and link the selected boxes to it
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1318
            transf_persp = persp3d_create_xml_element (persp->document, persp->perspective_impl);
8911 by Maximilian Albert
Major simplification of 3D box code.
1319
1320
            for (std::list<SPBox3D *>::iterator b = selboxes.begin(); b != selboxes.end(); ++b)
1321
                box3d_switch_perspectives(*b, persp, transf_persp);
1322
        } else {
1323
            transf_persp = persp;
1324
        }
1325
1326
        persp3d_apply_affine_transformation(transf_persp, affine);
1327
    }
1328
1 by mental
moving trunk for module inkscape
1329
    for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
1330
        SPItem *item = SP_ITEM(l->data);
1331
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1332
        Geom::Point old_center(0,0);
149 by rwst
bulk trailing spaces removal. consistency through MD5 of binary
1333
        if (set_i2d && item->isCenterSet())
36 by buliabyak
transform centers in sp_selection_apply_affine, comments
1334
            old_center = item->getCenter();
1335
1 by mental
moving trunk for module inkscape
1336
#if 0 /* Re-enable this once persistent guides have a graphical indication.
7645 by pjrm
noop: whitespace
1337
         At the time of writing, this is the only place to re-enable. */
1 by mental
moving trunk for module inkscape
1338
        sp_item_update_cns(*item, selection->desktop());
1339
#endif
1340
2426 by buliabyak
fix 1332884
1341
        // we're moving both a clone and its original or any ancestor in clone chain?
1342
        bool transform_clone_with_original = selection_contains_original(item, selection);
2132 by buliabyak
patch 1623967, fixes bug 1332888 and the wrong move of original-with-clone selection in transformed group
1343
        // ...both a text-on-path and its path?
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1344
        bool transform_textpath_with_path = (SP_IS_TEXT_TEXTPATH(item) && selection->includes( sp_textpath_get_path_item(SP_TEXTPATH(item->firstChild())) ));
2132 by buliabyak
patch 1623967, fixes bug 1332888 and the wrong move of original-with-clone selection in transformed group
1345
        // ...both a flowtext and its frame?
7645 by pjrm
noop: whitespace
1346
        bool transform_flowtext_with_frame = (SP_IS_FLOWTEXT(item) && selection->includes( SP_FLOWTEXT(item)->get_frame(NULL))); // (only the first frame is checked so far)
2132 by buliabyak
patch 1623967, fixes bug 1332888 and the wrong move of original-with-clone selection in transformed group
1347
        // ...both an offset and its source?
7645 by pjrm
noop: whitespace
1348
        bool transform_offset_with_source = (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref) && selection->includes( sp_offset_get_source(SP_OFFSET(item)) );
4025 by joncruz
Warning cleanup
1349
811 by mjwybrow
* src/selection-chemistry.cpp, src/sp-conn-end-pair.cpp:
1350
        // If we're moving a connector, we want to detach it
1351
        // from shapes that aren't part of the selection, but
1352
        // leave it attached if they are
1353
        if (cc_item_is_connector(item)) {
1354
            SPItem *attItem[2];
1355
            SP_PATH(item)->connEndPair.getAttachedItems(attItem);
4025 by joncruz
Warning cleanup
1356
811 by mjwybrow
* src/selection-chemistry.cpp, src/sp-conn-end-pair.cpp:
1357
            for (int n = 0; n < 2; ++n) {
1358
                if (!selection->includes(attItem[n])) {
1359
                    sp_conn_end_detach(item, n);
1360
                }
1361
            }
1362
        }
4025 by joncruz
Warning cleanup
1363
1 by mental
moving trunk for module inkscape
1364
        // "clones are unmoved when original is moved" preference
6823 by tweenk
Refactored preferences handling into a new version of
1365
        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
1366
        int compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
1 by mental
moving trunk for module inkscape
1367
        bool prefs_unmoved = (compensation == SP_CLONE_COMPENSATION_UNMOVED);
1368
        bool prefs_parallel = (compensation == SP_CLONE_COMPENSATION_PARALLEL);
1369
7645 by pjrm
noop: whitespace
1370
        /* If this is a clone and it's selected along with its original, do not move it;
1371
         * it will feel the transform of its original and respond to it itself.
1372
         * Without this, a clone is doubly transformed, very unintuitive.
1373
         *
1374
         * Same for textpath if we are also doing ANY transform to its path: do not touch textpath,
1375
         * letters cannot be squeezed or rotated anyway, they only refill the changed path.
1376
         * Same for linked offset if we are also moving its source: do not move it. */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1377
        if (transform_textpath_with_path) {
7645 by pjrm
noop: whitespace
1378
            // Restore item->transform field from the repr, in case it was changed by seltrans.
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1379
            item->readAttr( "transform" );
1 by mental
moving trunk for module inkscape
1380
        } else if (transform_flowtext_with_frame) {
1381
            // apply the inverse of the region's transform to the <use> so that the flow remains
1382
            // the same (even though the output itself gets transformed)
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1383
            for ( SPObject *region = item->firstChild() ; region ; region = region->getNext() ) {
1384
                if (SP_IS_FLOWREGION(region) || SP_IS_FLOWREGIONEXCLUDE(region)) {
1385
                    for ( SPObject *use = region->firstChild() ; use ; use = use->getNext() ) {
1386
                        if ( SP_IS_USE(use) ) {
1387
                            SP_USE(use)->doWriteTransform(use->getRepr(), item->transform.inverse(), NULL, compensate);
1388
                        }
1389
                    }
1 by mental
moving trunk for module inkscape
1390
                }
1391
            }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1392
        } else if (transform_clone_with_original || transform_offset_with_source) {
1 by mental
moving trunk for module inkscape
1393
            // We are transforming a clone along with its original. The below matrix juggling is
1394
            // necessary to ensure that they transform as a whole, i.e. the clone's induced
1395
            // transform and its move compensation are both cancelled out.
1396
1397
            // restore item->transform field from the repr, in case it was changed by seltrans
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1398
            item->readAttr( "transform" );
1 by mental
moving trunk for module inkscape
1399
1400
            // calculate the matrix we need to apply to the clone to cancel its induced transform from its original
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1401
            Geom::Affine parent2dt = SP_ITEM(item->parent)->i2dt_affine();
1402
            Geom::Affine t = parent2dt * affine * parent2dt.inverse();
1403
            Geom::Affine t_inv = t.inverse();
1404
            Geom::Affine result = t_inv * item->transform * t;
1 by mental
moving trunk for module inkscape
1405
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1406
            if (transform_clone_with_original && (prefs_parallel || prefs_unmoved) && affine.isTranslation()) {
1 by mental
moving trunk for module inkscape
1407
                // we need to cancel out the move compensation, too
1408
1409
                // find out the clone move, same as in sp_use_move_compensate
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1410
                Geom::Affine parent = sp_use_get_parent_transform(SP_USE(item));
1411
                Geom::Affine clone_move = parent.inverse() * t * parent;
1 by mental
moving trunk for module inkscape
1412
1413
                if (prefs_parallel) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1414
                    Geom::Affine move = result * clone_move * t_inv;
1415
                    item->doWriteTransform(item->getRepr(), move, &move, compensate);
1 by mental
moving trunk for module inkscape
1416
1417
                } else if (prefs_unmoved) {
2132 by buliabyak
patch 1623967, fixes bug 1332888 and the wrong move of original-with-clone selection in transformed group
1418
                    //if (SP_IS_USE(sp_use_get_original(SP_USE(item))))
7032 by verbalshadow
More NR ==> Geom changes
1419
                    //    clone_move = Geom::identity();
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1420
                    Geom::Affine move = result * clone_move;
1421
                    item->doWriteTransform(item->getRepr(), move, &t, compensate);
1422
                }
1423
1424
            } else if (transform_offset_with_source && (prefs_parallel || prefs_unmoved) && affine.isTranslation()){
1425
                Geom::Affine parent = item->transform;
1426
                Geom::Affine offset_move = parent.inverse() * t * parent;
1427
1428
                if (prefs_parallel) {
1429
                    Geom::Affine move = result * offset_move * t_inv;
1430
                    item->doWriteTransform(item->getRepr(), move, &move, compensate);
1431
1432
                } else if (prefs_unmoved) {
1433
                    Geom::Affine move = result * offset_move;
1434
                    item->doWriteTransform(item->getRepr(), move, &t, compensate);
1 by mental
moving trunk for module inkscape
1435
                }
1436
1437
            } else {
1438
                // just apply the result
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1439
                item->doWriteTransform(item->getRepr(), result, &t, compensate);
1 by mental
moving trunk for module inkscape
1440
            }
1441
1442
        } else {
1443
            if (set_i2d) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1444
                item->set_i2d_affine(item->i2dt_affine() * (Geom::Affine)affine);
1 by mental
moving trunk for module inkscape
1445
            }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1446
            item->doWriteTransform(item->getRepr(), item->transform, NULL, compensate);
1 by mental
moving trunk for module inkscape
1447
        }
36 by buliabyak
transform centers in sp_selection_apply_affine, comments
1448
1449
        // if we're moving the actual object, not just updating the repr, we can transform the
1450
        // center by the same matrix (only necessary for non-translations)
7797 by dvlierop2
Make sure that the item center (origin for rotations) does not change due to copy & paste (Fixes bug #320489)
1451
        if (set_i2d && item->isCenterSet() && !(affine.isTranslation() || affine.isIdentity())) {
36 by buliabyak
transform centers in sp_selection_apply_affine, comments
1452
            item->setCenter(old_center * affine);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1453
            item->updateRepr();
36 by buliabyak
transform centers in sp_selection_apply_affine, comments
1454
        }
1 by mental
moving trunk for module inkscape
1455
    }
1456
}
1457
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1458
void sp_selection_remove_transform(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
1459
{
1460
    if (desktop == NULL)
1461
        return;
1462
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
1463
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
1464
1465
    GSList const *l = (GSList *) selection->reprList();
1466
    while (l != NULL) {
5631 by mental
merge inline patch from Jimmy
1467
        ((Inkscape::XML::Node*)l->data)->setAttribute("transform", NULL, false);
1 by mental
moving trunk for module inkscape
1468
        l = l->next;
1469
    }
1470
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1471
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_OBJECT_FLATTEN,
1472
                       _("Remove transform"));
1 by mental
moving trunk for module inkscape
1473
}
1474
1475
void
1476
sp_selection_scale_absolute(Inkscape::Selection *selection,
1477
                            double const x0, double const x1,
1478
                            double const y0, double const y1)
1479
{
1480
    if (selection->isEmpty())
1481
        return;
1482
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1483
    Geom::OptRect bbox = selection->visualBounds();
6891 by Ted Gould
Merge from fe-moved
1484
    if ( !bbox ) {
149 by rwst
bulk trailing spaces removal. consistency through MD5 of binary
1485
        return;
1 by mental
moving trunk for module inkscape
1486
    }
1487
6884 by Ted Gould
Merging from trunk
1488
    Geom::Translate const p2o(-bbox->min());
1 by mental
moving trunk for module inkscape
1489
6884 by Ted Gould
Merging from trunk
1490
    Geom::Scale const newSize(x1 - x0,
7645 by pjrm
noop: whitespace
1491
                              y1 - y0);
6884 by Ted Gould
Merging from trunk
1492
    Geom::Scale const scale( newSize * Geom::Scale(bbox->dimensions()).inverse() );
1493
    Geom::Translate const o2n(x0, y0);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1494
    Geom::Affine const final( p2o * scale * o2n );
1 by mental
moving trunk for module inkscape
1495
1496
    sp_selection_apply_affine(selection, final);
1497
}
1498
1499
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1500
void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point const &align, Geom::Scale const &scale)
1 by mental
moving trunk for module inkscape
1501
{
1502
    if (selection->isEmpty())
1503
        return;
1504
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1505
    Geom::OptRect bbox = selection->visualBounds();
1 by mental
moving trunk for module inkscape
1506
6891 by Ted Gould
Merge from fe-moved
1507
    if ( !bbox ) {
1 by mental
moving trunk for module inkscape
1508
        return;
1509
    }
1510
1511
    // FIXME: ARBITRARY LIMIT: don't try to scale above 1 Mpx, it won't display properly and will crash sooner or later anyway
7032 by verbalshadow
More NR ==> Geom changes
1512
    if ( bbox->dimensions()[Geom::X] * scale[Geom::X] > 1e6  ||
1513
         bbox->dimensions()[Geom::Y] * scale[Geom::Y] > 1e6 )
1 by mental
moving trunk for module inkscape
1514
    {
1515
        return;
1516
    }
1517
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1518
    Geom::Translate const n2d(-align);
1519
    Geom::Translate const d2n(align);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1520
    Geom::Affine const final( n2d * scale * d2n );
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1521
    sp_selection_apply_affine(selection, final);
1522
}
1523
1524
void
1525
sp_selection_rotate_relative(Inkscape::Selection *selection, Geom::Point const &center, gdouble const angle_degrees)
1526
{
1527
    Geom::Translate const d2n(center);
1528
    Geom::Translate const n2d(-center);
1529
    Geom::Rotate const rotate(Geom::Rotate::from_degrees(angle_degrees));
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1530
    Geom::Affine const final( Geom::Affine(n2d) * rotate * d2n );
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1531
    sp_selection_apply_affine(selection, final);
1532
}
1533
1534
void
1535
sp_selection_skew_relative(Inkscape::Selection *selection, Geom::Point const &align, double dx, double dy)
1536
{
1537
    Geom::Translate const d2n(align);
1538
    Geom::Translate const n2d(-align);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1539
    Geom::Affine const skew(1, dy,
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1540
                            dx, 1,
1541
                            0, 0);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1542
    Geom::Affine const final( n2d * skew * d2n );
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1543
    sp_selection_apply_affine(selection, final);
1544
}
1545
7875 by speleo3
new "compensate" param for sp_selection_apply_affine and sp_selection_move_relative to avoid temporary prefs changing
1546
void sp_selection_move_relative(Inkscape::Selection *selection, Geom::Point const &move, bool compensate)
1 by mental
moving trunk for module inkscape
1547
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1548
    sp_selection_apply_affine(selection, Geom::Affine(Geom::Translate(move)), true, compensate);
1 by mental
moving trunk for module inkscape
1549
}
1550
1551
void sp_selection_move_relative(Inkscape::Selection *selection, double dx, double dy)
1552
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1553
    sp_selection_apply_affine(selection, Geom::Affine(Geom::Translate(dx, dy)));
1 by mental
moving trunk for module inkscape
1554
}
1555
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1556
/**
1557
 * @brief Rotates selected objects 90 degrees, either clock-wise or counter-clockwise, depending on the value of ccw
1558
 */
1559
void sp_selection_rotate_90(SPDesktop *desktop, bool ccw)
1560
{
1561
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1562
1563
    if (selection->isEmpty())
1564
        return;
1565
1566
    GSList const *l = selection->itemList();
7032 by verbalshadow
More NR ==> Geom changes
1567
    Geom::Rotate const rot_90(Geom::Point(0, ccw ? 1 : -1)); // pos. or neg. rotation, depending on the value of ccw
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1568
    for (GSList const *l2 = l ; l2 != NULL ; l2 = l2->next) {
1569
        SPItem *item = SP_ITEM(l2->data);
1570
        sp_item_rotate_rel(item, rot_90);
1571
    }
1572
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1573
    DocumentUndo::done(sp_desktop_document(desktop),
1574
                       ccw ? SP_VERB_OBJECT_ROTATE_90_CCW : SP_VERB_OBJECT_ROTATE_90_CW,
1575
                       ccw ? _("Rotate 90&#176; CCW") : _("Rotate 90&#176; CW"));
1 by mental
moving trunk for module inkscape
1576
}
1577
1578
void
1579
sp_selection_rotate(Inkscape::Selection *selection, gdouble const angle_degrees)
1580
{
1581
    if (selection->isEmpty())
1582
        return;
1583
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1584
    boost::optional<Geom::Point> center = selection->center();
2604 by mental
Switch selection bounds and center to use NR::Maybe, addressing most of the
1585
    if (!center) {
1586
        return;
1587
    }
1 by mental
moving trunk for module inkscape
1588
2604 by mental
Switch selection bounds and center to use NR::Maybe, addressing most of the
1589
    sp_selection_rotate_relative(selection, *center, angle_degrees);
1 by mental
moving trunk for module inkscape
1590
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1591
    DocumentUndo::maybeDone(sp_desktop_document(selection->desktop()),
1592
                            ( ( angle_degrees > 0 )
1593
                              ? "selector:rotate:ccw"
1594
                              : "selector:rotate:cw" ),
1595
                            SP_VERB_CONTEXT_SELECT,
1596
                            _("Rotate"));
1 by mental
moving trunk for module inkscape
1597
}
1598
6884 by Ted Gould
Merging from trunk
1599
// helper function:
1600
static
1601
Geom::Point
1602
cornerFarthestFrom(Geom::Rect const &r, Geom::Point const &p){
1603
    Geom::Point m = r.midpoint();
1604
    unsigned i = 0;
1605
    if (p[X] < m[X]) {
1606
        i = 1;
1607
    }
1608
    if (p[Y] < m[Y]) {
1609
        i = 3 - i;
1610
    }
1611
    return r.corner(i);
1612
}
1613
1 by mental
moving trunk for module inkscape
1614
/**
1615
\param  angle   the angle in "angular pixels", i.e. how many visible pixels must move the outermost point of the rotated object
1616
*/
1617
void
1618
sp_selection_rotate_screen(Inkscape::Selection *selection, gdouble angle)
1619
{
1620
    if (selection->isEmpty())
1621
        return;
1622
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1623
    Geom::OptRect bbox = selection->visualBounds();
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1624
    boost::optional<Geom::Point> center = selection->center();
273 by buliabyak
use rotation center in keyboard rotation and transform dialog
1625
2604 by mental
Switch selection bounds and center to use NR::Maybe, addressing most of the
1626
    if ( !bbox || !center ) {
1627
        return;
1628
    }
1 by mental
moving trunk for module inkscape
1629
1630
    gdouble const zoom = selection->desktop()->current_zoom();
1631
    gdouble const zmove = angle / zoom;
6884 by Ted Gould
Merging from trunk
1632
    gdouble const r = Geom::L2(cornerFarthestFrom(*bbox, *center) - *center);
1 by mental
moving trunk for module inkscape
1633
1634
    gdouble const zangle = 180 * atan2(zmove, r) / M_PI;
1635
2604 by mental
Switch selection bounds and center to use NR::Maybe, addressing most of the
1636
    sp_selection_rotate_relative(selection, *center, zangle);
1 by mental
moving trunk for module inkscape
1637
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1638
    DocumentUndo::maybeDone(sp_desktop_document(selection->desktop()),
1639
                            ( (angle > 0)
1640
                              ? "selector:rotate:ccw"
1641
                              : "selector:rotate:cw" ),
1642
                            SP_VERB_CONTEXT_SELECT,
1643
                            _("Rotate by pixels"));
1 by mental
moving trunk for module inkscape
1644
}
1645
1646
void
1647
sp_selection_scale(Inkscape::Selection *selection, gdouble grow)
1648
{
1649
    if (selection->isEmpty())
1650
        return;
1651
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1652
    Geom::OptRect bbox = selection->visualBounds();
2604 by mental
Switch selection bounds and center to use NR::Maybe, addressing most of the
1653
    if (!bbox) {
1654
        return;
1655
    }
1656
6884 by Ted Gould
Merging from trunk
1657
    Geom::Point const center(bbox->midpoint());
1 by mental
moving trunk for module inkscape
1658
1659
    // you can't scale "do nizhe pola" (below zero)
2604 by mental
Switch selection bounds and center to use NR::Maybe, addressing most of the
1660
    double const max_len = bbox->maxExtent();
1 by mental
moving trunk for module inkscape
1661
    if ( max_len + grow <= 1e-3 ) {
1662
        return;
1663
    }
1664
1665
    double const times = 1.0 + grow / max_len;
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1666
    sp_selection_scale_relative(selection, center, Geom::Scale(times, times));
1 by mental
moving trunk for module inkscape
1667
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1668
    DocumentUndo::maybeDone(sp_desktop_document(selection->desktop()),
1669
                            ( (grow > 0)
1670
                              ? "selector:scale:larger"
1671
                              : "selector:scale:smaller" ),
1672
                            SP_VERB_CONTEXT_SELECT,
1673
                            _("Scale"));
1 by mental
moving trunk for module inkscape
1674
}
1675
1676
void
1677
sp_selection_scale_screen(Inkscape::Selection *selection, gdouble grow_pixels)
1678
{
1679
    sp_selection_scale(selection,
1680
                       grow_pixels / selection->desktop()->current_zoom());
1681
}
1682
1683
void
1684
sp_selection_scale_times(Inkscape::Selection *selection, gdouble times)
1685
{
1686
    if (selection->isEmpty())
1687
        return;
1688
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1689
    Geom::OptRect sel_bbox = selection->visualBounds();
2604 by mental
Switch selection bounds and center to use NR::Maybe, addressing most of the
1690
1691
    if (!sel_bbox) {
1692
        return;
1693
    }
1694
6884 by Ted Gould
Merging from trunk
1695
    Geom::Point const center(sel_bbox->midpoint());
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
1696
    sp_selection_scale_relative(selection, center, Geom::Scale(times, times));
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1697
    DocumentUndo::done(sp_desktop_document(selection->desktop()), SP_VERB_CONTEXT_SELECT,
1698
                       _("Scale by whole factor"));
1 by mental
moving trunk for module inkscape
1699
}
1700
1701
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1702
sp_selection_move(SPDesktop *desktop, gdouble dx, gdouble dy)
1 by mental
moving trunk for module inkscape
1703
{
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
1704
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
1705
    if (selection->isEmpty()) {
1706
        return;
1707
    }
1708
1709
    sp_selection_move_relative(selection, dx, dy);
1710
1711
    if (dx == 0) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1712
        DocumentUndo::maybeDone(sp_desktop_document(desktop), "selector:move:vertical", SP_VERB_CONTEXT_SELECT,
1713
                                _("Move vertically"));
1 by mental
moving trunk for module inkscape
1714
    } else if (dy == 0) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1715
        DocumentUndo::maybeDone(sp_desktop_document(desktop), "selector:move:horizontal", SP_VERB_CONTEXT_SELECT,
1716
                                _("Move horizontally"));
1 by mental
moving trunk for module inkscape
1717
    } else {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1718
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SELECT,
1719
                           _("Move"));
1 by mental
moving trunk for module inkscape
1720
    }
1721
}
1722
1723
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1724
sp_selection_move_screen(SPDesktop *desktop, gdouble dx, gdouble dy)
1 by mental
moving trunk for module inkscape
1725
{
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
1726
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
1727
    if (selection->isEmpty()) {
1728
        return;
1729
    }
1730
1731
    // same as sp_selection_move but divide deltas by zoom factor
1732
    gdouble const zoom = desktop->current_zoom();
1733
    gdouble const zdx = dx / zoom;
1734
    gdouble const zdy = dy / zoom;
1735
    sp_selection_move_relative(selection, zdx, zdy);
1736
1737
    if (dx == 0) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1738
        DocumentUndo::maybeDone(sp_desktop_document(desktop), "selector:move:vertical", SP_VERB_CONTEXT_SELECT,
1739
                                _("Move vertically by pixels"));
1 by mental
moving trunk for module inkscape
1740
    } else if (dy == 0) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1741
        DocumentUndo::maybeDone(sp_desktop_document(desktop), "selector:move:horizontal", SP_VERB_CONTEXT_SELECT,
1742
                                _("Move horizontally by pixels"));
1 by mental
moving trunk for module inkscape
1743
    } else {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1744
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SELECT,
1745
                           _("Move"));
1 by mental
moving trunk for module inkscape
1746
    }
1747
}
1748
1749
namespace {
1750
1751
template <typename D>
1752
SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root,
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1753
                  bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive);
1 by mental
moving trunk for module inkscape
1754
1755
template <typename D>
134 by rwst
bulk whitespace removal patch #1198588 by gigaclon
1756
SPItem *next_item_from_list(SPDesktop *desktop, GSList const *items, SPObject *root,
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1757
                  bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive);
1 by mental
moving trunk for module inkscape
1758
1759
struct Forward {
1760
    typedef SPObject *Iterator;
1761
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1762
    static Iterator children(SPObject *o) { return o->firstChild(); }
1763
    static Iterator siblings_after(SPObject *o) { return o->getNext(); }
4025 by joncruz
Warning cleanup
1764
    static void dispose(Iterator /*i*/) {}
1 by mental
moving trunk for module inkscape
1765
1766
    static SPObject *object(Iterator i) { return i; }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1767
    static Iterator next(Iterator i) { return i->getNext(); }
1 by mental
moving trunk for module inkscape
1768
};
1769
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1770
struct ListReverse {
1 by mental
moving trunk for module inkscape
1771
    typedef GSList *Iterator;
1772
1773
    static Iterator children(SPObject *o) {
1774
        return make_list(o->firstChild(), NULL);
1775
    }
1776
    static Iterator siblings_after(SPObject *o) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1777
        return make_list(o->parent->firstChild(), o);
1 by mental
moving trunk for module inkscape
1778
    }
1779
    static void dispose(Iterator i) {
1780
        g_slist_free(i);
1781
    }
1782
1783
    static SPObject *object(Iterator i) {
1784
        return reinterpret_cast<SPObject *>(i->data);
1785
    }
1786
    static Iterator next(Iterator i) { return i->next; }
1787
1788
private:
1789
    static GSList *make_list(SPObject *object, SPObject *limit) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1790
        GSList *list = NULL;
1 by mental
moving trunk for module inkscape
1791
        while ( object != limit ) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1792
            if (!object) { // TODO check if this happens in practice
1793
                g_warning("Unexpected list overrun");
1794
                break;
1795
            }
1 by mental
moving trunk for module inkscape
1796
            list = g_slist_prepend(list, object);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1797
            object = object->getNext();
1 by mental
moving trunk for module inkscape
1798
        }
1799
        return list;
1800
    }
1801
};
1802
1803
}
1804
1805
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1806
sp_selection_item_next(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
1807
{
1808
    g_return_if_fail(desktop != NULL);
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
1809
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
1810
6823 by tweenk
Refactored preferences handling into a new version of
1811
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
1812
    PrefsSelectionContext inlayer = (PrefsSelectionContext)prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER);
1813
    bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true);
1814
    bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true);
1 by mental
moving trunk for module inkscape
1815
1816
    SPObject *root;
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1817
    if (PREFS_SELECTION_ALL != inlayer) {
1818
        root = selection->activeContext();
1 by mental
moving trunk for module inkscape
1819
    } else {
1820
        root = desktop->currentRoot();
1821
    }
1822
1823
    SPItem *item=next_item_from_list<Forward>(desktop, selection->itemList(), root, SP_CYCLING == SP_CYCLE_VISIBLE, inlayer, onlyvisible, onlysensitive);
1824
1825
    if (item) {
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1826
        selection->set(item, PREFS_SELECTION_LAYER_RECURSIVE == inlayer);
1 by mental
moving trunk for module inkscape
1827
        if ( SP_CYCLING == SP_CYCLE_FOCUS ) {
1828
            scroll_to_show_item(desktop, item);
1829
        }
1830
    }
1831
}
1832
1833
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
1834
sp_selection_item_prev(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
1835
{
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
1836
    SPDocument *document = sp_desktop_document(desktop);
1 by mental
moving trunk for module inkscape
1837
    g_return_if_fail(document != NULL);
1838
    g_return_if_fail(desktop != NULL);
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
1839
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
1840
6823 by tweenk
Refactored preferences handling into a new version of
1841
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
1842
    PrefsSelectionContext inlayer = (PrefsSelectionContext) prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER);
1843
    bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true);
1844
    bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true);
1 by mental
moving trunk for module inkscape
1845
1846
    SPObject *root;
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1847
    if (PREFS_SELECTION_ALL != inlayer) {
1848
        root = selection->activeContext();
1 by mental
moving trunk for module inkscape
1849
    } else {
1850
        root = desktop->currentRoot();
1851
    }
1852
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1853
    SPItem *item=next_item_from_list<ListReverse>(desktop, selection->itemList(), root, SP_CYCLING == SP_CYCLE_VISIBLE, inlayer, onlyvisible, onlysensitive);
1 by mental
moving trunk for module inkscape
1854
1855
    if (item) {
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1856
        selection->set(item, PREFS_SELECTION_LAYER_RECURSIVE == inlayer);
1 by mental
moving trunk for module inkscape
1857
        if ( SP_CYCLING == SP_CYCLE_FOCUS ) {
1858
            scroll_to_show_item(desktop, item);
1859
        }
1860
    }
1861
}
1862
3968 by johanengelen
LPE: implement 'edit next LPE parameter'. Accessible through key '7'.
1863
void sp_selection_next_patheffect_param(SPDesktop * dt)
1864
{
1865
    if (!dt) return;
1866
1867
    Inkscape::Selection *selection = sp_desktop_selection(dt);
1868
    if ( selection && !selection->isEmpty() ) {
1869
        SPItem *item = selection->singleItem();
1870
        if ( item && SP_IS_SHAPE(item)) {
5219 by bgk
- Created a SPLPEItem class that handles applying a LPE to an Item
1871
            if (sp_lpe_item_has_path_effect(SP_LPE_ITEM(item))) {
1872
                sp_lpe_item_edit_next_param_oncanvas(SP_LPE_ITEM(item), dt);
3968 by johanengelen
LPE: implement 'edit next LPE parameter'. Accessible through key '7'.
1873
            } else {
1874
                dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("The selection has no applied path effect."));
1875
            }
1876
        }
1877
    }
1878
}
1879
8846.1.1 by Krzysztof Kosiński
First GSoC node tool commit to Bazaar
1880
/*bool has_path_recursive(SPObject *obj)
1881
{
1882
    if (!obj) return false;
1883
    if (SP_IS_PATH(obj)) {
1884
        return true;
1885
    }
1886
    if (SP_IS_GROUP(obj) || SP_IS_OBJECTGROUP(obj)) {
1887
        for (SPObject *c = obj->children; c; c = c->next) {
1888
            if (has_path_recursive(c)) return true;
1889
        }
1890
    }
1891
    return false;
1892
}*/
1893
8981 by Jon A. Cruz
Warning cleanup.
1894
void sp_selection_edit_clip_or_mask(SPDesktop * /*dt*/, bool /*clip*/)
4834 by johanengelen
* on-canvas clip and mask editing :) in the object menu you can find how to edit them.
1895
{
8846.1.1 by Krzysztof Kosiński
First GSoC node tool commit to Bazaar
1896
    return;
1897
    /*if (!dt) return;
1898
    using namespace Inkscape::UI;
4834 by johanengelen
* on-canvas clip and mask editing :) in the object menu you can find how to edit them.
1899
1900
    Inkscape::Selection *selection = sp_desktop_selection(dt);
8846.1.1 by Krzysztof Kosiński
First GSoC node tool commit to Bazaar
1901
    if (!selection || selection->isEmpty()) return;
1902
1903
    GSList const *items = selection->itemList();
1904
    bool has_path = false;
1905
    for (GSList *i = const_cast<GSList*>(items); i; i= i->next) {
1906
        SPItem *item = SP_ITEM(i->data);
1907
        SPObject *search = clip
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1908
            ? (item->clip_ref ? item->clip_ref->getObject() : NULL)
1909
            : item->mask_ref ? item->mask_ref->getObject() : NULL;
8846.1.1 by Krzysztof Kosiński
First GSoC node tool commit to Bazaar
1910
        has_path |= has_path_recursive(search);
1911
        if (has_path) break;
1912
    }
1913
    if (has_path) {
1914
        if (!tools_isactive(dt, TOOLS_NODES)) {
1915
            tools_switch(dt, TOOLS_NODES);
4834 by johanengelen
* on-canvas clip and mask editing :) in the object menu you can find how to edit them.
1916
        }
8846.1.1 by Krzysztof Kosiński
First GSoC node tool commit to Bazaar
1917
        ink_node_tool_set_mode(INK_NODE_TOOL(dt->event_context),
1918
            clip ? NODE_TOOL_EDIT_CLIPPING_PATHS : NODE_TOOL_EDIT_MASKS);
1919
    } else if (clip) {
1920
        dt->messageStack()->flash(Inkscape::WARNING_MESSAGE,
1921
            _("The selection has no applied clip path."));
1922
    } else {
1923
        dt->messageStack()->flash(Inkscape::WARNING_MESSAGE,
1924
            _("The selection has no applied mask."));
1925
    }*/
4834 by johanengelen
* on-canvas clip and mask editing :) in the object menu you can find how to edit them.
1926
}
1927
1928
1 by mental
moving trunk for module inkscape
1929
namespace {
1930
1931
template <typename D>
1932
SPItem *next_item_from_list(SPDesktop *desktop, GSList const *items,
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1933
                            SPObject *root, bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive)
1 by mental
moving trunk for module inkscape
1934
{
1935
    SPObject *current=root;
1936
    while (items) {
1937
        SPItem *item=SP_ITEM(items->data);
1938
        if ( root->isAncestorOf(item) &&
1939
             ( !only_in_viewport || desktop->isWithinViewport(item) ) )
1940
        {
1941
            current = item;
1942
            break;
1943
        }
1944
        items = items->next;
1945
    }
1946
1947
    GSList *path=NULL;
1948
    while ( current != root ) {
1949
        path = g_slist_prepend(path, current);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1950
        current = current->parent;
1 by mental
moving trunk for module inkscape
1951
    }
1952
1953
    SPItem *next;
1954
    // first, try from the current object
1955
    next = next_item<D>(desktop, path, root, only_in_viewport, inlayer, onlyvisible, onlysensitive);
1956
    g_slist_free(path);
1957
1958
    if (!next) { // if we ran out of objects, start over at the root
1959
        next = next_item<D>(desktop, NULL, root, only_in_viewport, inlayer, onlyvisible, onlysensitive);
1960
    }
1961
1962
    return next;
1963
}
1964
1965
template <typename D>
1966
SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root,
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1967
                  bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive)
1 by mental
moving trunk for module inkscape
1968
{
1969
    typename D::Iterator children;
1970
    typename D::Iterator iter;
1971
1972
    SPItem *found=NULL;
1973
1974
    if (path) {
1975
        SPObject *object=reinterpret_cast<SPObject *>(path->data);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
1976
        g_assert(object->parent == root);
1 by mental
moving trunk for module inkscape
1977
        if (desktop->isLayer(object)) {
1978
            found = next_item<D>(desktop, path->next, object, only_in_viewport, inlayer, onlyvisible, onlysensitive);
1979
        }
1980
        iter = children = D::siblings_after(object);
1981
    } else {
1982
        iter = children = D::children(root);
1983
    }
1984
1985
    while ( iter && !found ) {
1986
        SPObject *object=D::object(iter);
1987
        if (desktop->isLayer(object)) {
380 by knutux
patch #1450307 - option for select all to work in layer with it's sub-layers:
1988
            if (PREFS_SELECTION_LAYER != inlayer) { // recurse into sublayers
1 by mental
moving trunk for module inkscape
1989
                found = next_item<D>(desktop, NULL, object, only_in_viewport, inlayer, onlyvisible, onlysensitive);
1990
            }
1991
        } else if ( SP_IS_ITEM(object) &&
1992
                    ( !only_in_viewport || desktop->isWithinViewport(SP_ITEM(object)) ) &&
1993
                    ( !onlyvisible || !desktop->itemIsHidden(SP_ITEM(object))) &&
1994
                    ( !onlysensitive || !SP_ITEM(object)->isLocked()) &&
1995
                    !desktop->isLayer(SP_ITEM(object)) )
1996
        {
1997
            found = SP_ITEM(object);
1998
        }
1999
        iter = D::next(iter);
2000
    }
2001
2002
    D::dispose(children);
2003
2004
    return found;
2005
}
2006
2007
}
2008
2009
/**
2010
 * If \a item is not entirely visible then adjust visible area to centre on the centre on of
2011
 * \a item.
2012
 */
2013
void scroll_to_show_item(SPDesktop *desktop, SPItem *item)
2014
{
6839 by cilix42
Next roud of NR ==> Geom conversion
2015
    Geom::Rect dbox = desktop->get_display_area();
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2016
    Geom::OptRect sbox = item->desktopVisualBounds();
1 by mental
moving trunk for module inkscape
2017
2596 by mental
Merge further bbox work
2018
    if ( sbox && dbox.contains(*sbox) == false ) {
6839 by cilix42
Next roud of NR ==> Geom conversion
2019
        Geom::Point const s_dt = sbox->midpoint();
2020
        Geom::Point const s_w = desktop->d2w(s_dt);
2021
        Geom::Point const d_dt = dbox.midpoint();
2022
        Geom::Point const d_w = desktop->d2w(d_dt);
2023
        Geom::Point const moved_w( d_w - s_w );
1 by mental
moving trunk for module inkscape
2024
        gint const dx = (gint) moved_w[X];
2025
        gint const dy = (gint) moved_w[Y];
2026
        desktop->scroll_world(dx, dy);
2027
    }
2028
}
2029
2030
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2031
void sp_selection_clone(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
2032
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2033
    if (desktop == NULL) {
1 by mental
moving trunk for module inkscape
2034
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2035
    }
1 by mental
moving trunk for module inkscape
2036
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
2037
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
2038
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2039
    Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
2253 by mental
start switching sp_repr_new* over to XML::Document::create*, and rename create methods to match DOM
2040
1 by mental
moving trunk for module inkscape
2041
    // check if something is selected
2042
    if (selection->isEmpty()) {
2043
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select an <b>object</b> to clone."));
2044
        return;
2045
    }
2046
244 by buliabyak
patch by christoph-b3e to clone multiple selected objects
2047
    GSList *reprs = g_slist_copy((GSList *) selection->reprList());
4025 by joncruz
Warning cleanup
2048
244 by buliabyak
patch by christoph-b3e to clone multiple selected objects
2049
    selection->clear();
4025 by joncruz
Warning cleanup
2050
244 by buliabyak
patch by christoph-b3e to clone multiple selected objects
2051
    // sorting items from different parents sorts each parent's subset without possibly mixing them, just what we need
2052
    reprs = g_slist_sort(reprs, (GCompareFunc) sp_repr_compare_position);
2053
2054
    GSList *newsel = NULL;
4025 by joncruz
Warning cleanup
2055
244 by buliabyak
patch by christoph-b3e to clone multiple selected objects
2056
    while (reprs) {
2057
        Inkscape::XML::Node *sel_repr = (Inkscape::XML::Node *) reprs->data;
2058
        Inkscape::XML::Node *parent = sp_repr_parent(sel_repr);
2059
2253 by mental
start switching sp_repr_new* over to XML::Document::create*, and rename create methods to match DOM
2060
        Inkscape::XML::Node *clone = xml_doc->createElement("svg:use");
5631 by mental
merge inline patch from Jimmy
2061
        clone->setAttribute("x", "0", false);
2062
        clone->setAttribute("y", "0", false);
2063
        clone->setAttribute("xlink:href", g_strdup_printf("#%s", sel_repr->attribute("id")), false);
7645 by pjrm
noop: whitespace
2064
5631 by mental
merge inline patch from Jimmy
2065
        clone->setAttribute("inkscape:transform-center-x", sel_repr->attribute("inkscape:transform-center-x"), false);
2066
        clone->setAttribute("inkscape:transform-center-y", sel_repr->attribute("inkscape:transform-center-y"), false);
4025 by joncruz
Warning cleanup
2067
244 by buliabyak
patch by christoph-b3e to clone multiple selected objects
2068
        // add the new clone to the top of the original's parent
2069
        parent->appendChild(clone);
2070
2071
        newsel = g_slist_prepend(newsel, clone);
2072
        reprs = g_slist_remove(reprs, sel_repr);
2073
        Inkscape::GC::release(clone);
1 by mental
moving trunk for module inkscape
2074
    }
4025 by joncruz
Warning cleanup
2075
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2076
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_CLONE,
2077
                       C_("Action", "Clone"));
1 by mental
moving trunk for module inkscape
2078
244 by buliabyak
patch by christoph-b3e to clone multiple selected objects
2079
    selection->setReprList(newsel);
4025 by joncruz
Warning cleanup
2080
244 by buliabyak
patch by christoph-b3e to clone multiple selected objects
2081
    g_slist_free(newsel);
1 by mental
moving trunk for module inkscape
2082
}
2083
2084
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
2085
sp_selection_relink(SPDesktop *desktop)
5948 by buliabyak
new command: relink clone to copied object
2086
{
2087
    if (!desktop)
2088
        return;
2089
2090
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
2091
2092
    if (selection->isEmpty()) {
2093
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>clones</b> to relink."));
2094
        return;
2095
    }
2096
2097
    Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
2098
    const gchar *newid = cm->getFirstObjectID();
2099
    if (!newid) {
2100
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Copy an <b>object</b> to clipboard to relink clones to."));
2101
        return;
2102
    }
7645 by pjrm
noop: whitespace
2103
    gchar *newref = g_strdup_printf("#%s", newid);
5948 by buliabyak
new command: relink clone to copied object
2104
2105
    // Get a copy of current selection.
2106
    bool relinked = false;
2107
    for (GSList *items = (GSList *) selection->itemList();
2108
         items != NULL;
2109
         items = items->next)
2110
    {
2111
        SPItem *item = (SPItem *) items->data;
2112
2113
        if (!SP_IS_USE(item))
2114
            continue;
2115
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2116
        item->getRepr()->setAttribute("xlink:href", newref);
2117
        item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
5948 by buliabyak
new command: relink clone to copied object
2118
        relinked = true;
2119
    }
2120
2121
    g_free(newref);
2122
2123
    if (!relinked) {
2124
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to relink</b> in the selection."));
2125
    } else {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2126
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_UNLINK_CLONE,
2127
                           _("Relink clone"));
5948 by buliabyak
new command: relink clone to copied object
2128
    }
2129
}
2130
2131
2132
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
2133
sp_selection_unlink(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
2134
{
2135
    if (!desktop)
2136
        return;
2137
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
2138
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
2139
2140
    if (selection->isEmpty()) {
5948 by buliabyak
new command: relink clone to copied object
2141
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>clones</b> to unlink."));
1 by mental
moving trunk for module inkscape
2142
        return;
2143
    }
2144
2145
    // Get a copy of current selection.
2146
    GSList *new_select = NULL;
2147
    bool unlinked = false;
2148
    for (GSList *items = g_slist_copy((GSList *) selection->itemList());
2149
         items != NULL;
2150
         items = items->next)
2151
    {
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
2152
        SPItem *item = (SPItem *) items->data;
1 by mental
moving trunk for module inkscape
2153
3261 by gbanaszk
A few additions to ensure that editing trefs is not allowed (and doesn't cause a crash). Also allows all trefs within a selection to be 'unlinked'.
2154
        if (SP_IS_TEXT(item)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2155
            SPObject *tspan = sp_tref_convert_to_tspan(item);
4025 by joncruz
Warning cleanup
2156
2157
            if (tspan) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2158
                item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
3261 by gbanaszk
A few additions to ensure that editing trefs is not allowed (and doesn't cause a crash). Also allows all trefs within a selection to be 'unlinked'.
2159
            }
4025 by joncruz
Warning cleanup
2160
3261 by gbanaszk
A few additions to ensure that editing trefs is not allowed (and doesn't cause a crash). Also allows all trefs within a selection to be 'unlinked'.
2161
            // Set unlink to true, and fall into the next if which
2162
            // will include this text item in the new selection
2163
            unlinked = true;
2164
        }
2165
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
2166
        if (!(SP_IS_USE(item) || SP_IS_TREF(item))) {
2167
            // keep the non-use item in the new selection
2168
            new_select = g_slist_prepend(new_select, item);
1 by mental
moving trunk for module inkscape
2169
            continue;
2170
        }
2171
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
2172
        SPItem *unlink;
4025 by joncruz
Warning cleanup
2173
        if (SP_IS_USE(item)) {
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
2174
            unlink = sp_use_unlink(SP_USE(item));
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2175
            // Unable to unlink use (external or invalid href?)
2176
            if (!unlink) {
2177
                new_select = g_slist_prepend(new_select, item);
2178
                continue;
2179
            }
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
2180
        } else /*if (SP_IS_TREF(use))*/ {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2181
            unlink = SP_ITEM(sp_tref_convert_to_tspan(item));
3227 by cyreve
bug 1243190: add tref element support; limited editing support thus far (patch by gbanaszk)
2182
        }
4025 by joncruz
Warning cleanup
2183
1 by mental
moving trunk for module inkscape
2184
        unlinked = true;
2185
        // Add ungrouped items to the new selection.
2186
        new_select = g_slist_prepend(new_select, unlink);
2187
    }
2188
2189
    if (new_select) { // set new selection
2190
        selection->clear();
2191
        selection->setList(new_select);
2192
        g_slist_free(new_select);
2193
    }
2194
    if (!unlinked) {
2195
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to unlink</b> in the selection."));
2196
    }
2197
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2198
    DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_UNLINK_CLONE,
2199
                       _("Unlink clone"));
1 by mental
moving trunk for module inkscape
2200
}
2201
2202
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
2203
sp_select_clone_original(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
2204
{
2205
    if (desktop == NULL)
2206
        return;
2207
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
2208
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
2209
2210
    SPItem *item = selection->singleItem();
2211
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2212
    gchar const *error = _("Select a <b>clone</b> to go to its original. Select a <b>linked offset</b> to go to its source. Select a <b>text on path</b> to go to the path. Select a <b>flowed text</b> to go to its frame.");
1 by mental
moving trunk for module inkscape
2213
2214
    // Check if other than two objects are selected
2215
    if (g_slist_length((GSList *) selection->itemList()) != 1 || !item) {
2216
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, error);
2217
        return;
2218
    }
2219
2220
    SPItem *original = NULL;
2221
    if (SP_IS_USE(item)) {
7645 by pjrm
noop: whitespace
2222
        original = sp_use_get_original(SP_USE(item));
2223
    } else if (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref) {
2224
        original = sp_offset_get_source(SP_OFFSET(item));
1 by mental
moving trunk for module inkscape
2225
    } else if (SP_IS_TEXT_TEXTPATH(item)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2226
        original = sp_textpath_get_path_item(SP_TEXTPATH(item->firstChild()));
1 by mental
moving trunk for module inkscape
2227
    } else if (SP_IS_FLOWTEXT(item)) {
7645 by pjrm
noop: whitespace
2228
        original = SP_FLOWTEXT(item)->get_frame(NULL); // first frame only
1 by mental
moving trunk for module inkscape
2229
    } else { // it's an object that we don't know what to do with
2230
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, error);
2231
        return;
2232
    }
2233
2234
    if (!original) {
2235
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>Cannot find</b> the object to select (orphaned clone, offset, textpath, flowed text?)"));
2236
        return;
2237
    }
2238
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2239
    for (SPObject *o = original; o && !SP_IS_ROOT(o); o = o->parent) {
7645 by pjrm
noop: whitespace
2240
        if (SP_IS_DEFS(o)) {
1 by mental
moving trunk for module inkscape
2241
            desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The object you're trying to select is <b>not visible</b> (it is in &lt;defs&gt;)"));
2242
            return;
2243
        }
2244
    }
2245
2246
    if (original) {
6823 by tweenk
Refactored preferences handling into a new version of
2247
        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
2248
        bool highlight = prefs->getBool("/options/highlightoriginal/value");
6573 by buliabyak
add flashing line from clone to original on Shift+D
2249
        if (highlight) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2250
            Geom::OptRect a = item->desktopVisualBounds();
2251
            Geom::OptRect b = original->desktopVisualBounds();
6573 by buliabyak
add flashing line from clone to original on Shift+D
2252
            if ( a && b ) {
2253
                // draw a flashing line between the objects
2254
                SPCurve *curve = new SPCurve();
2255
                curve->moveto(a->midpoint());
2256
                curve->lineto(b->midpoint());
2257
2258
                SPCanvasItem * canvasitem = sp_canvas_bpath_new(sp_desktop_tempgroup(desktop), curve);
2259
                sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvasitem), 0x0000ddff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT, 5, 3);
2260
                sp_canvas_item_show(canvasitem);
2261
                curve->unref();
7645 by pjrm
noop: whitespace
2262
                desktop->add_temporary_canvasitem(canvasitem, 1000);
6573 by buliabyak
add flashing line from clone to original on Shift+D
2263
            }
2264
        }
2265
1 by mental
moving trunk for module inkscape
2266
        selection->clear();
2267
        selection->set(original);
2268
        if (SP_CYCLING == SP_CYCLE_FOCUS) {
2269
            scroll_to_show_item(desktop, original);
2270
        }
2271
    }
2272
}
2273
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2274
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
2275
void sp_selection_to_marker(SPDesktop *desktop, bool apply)
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2276
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2277
    if (desktop == NULL) {
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2278
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2279
    }
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2280
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
2281
    SPDocument *doc = sp_desktop_document(desktop);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2282
    Inkscape::XML::Document *xml_doc = doc->getReprDoc();
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2283
2284
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
2285
2286
    // check if something is selected
2287
    if (selection->isEmpty()) {
2288
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to convert to marker."));
2289
        return;
2290
    }
2291
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2292
    doc->ensureUpToDate();
2293
    Geom::OptRect r = selection->visualBounds();
6836 by cilix42
More NR ==> Geom conversion (points and some matrices/transforms)
2294
    boost::optional<Geom::Point> c = selection->center();
6891 by Ted Gould
Merge from fe-moved
2295
    if ( !r || !c ) {
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2296
        return;
2297
    }
2298
2299
    // calculate the transform to be applied to objects to move them to 0,0
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2300
    Geom::Point move_p = Geom::Point(0, doc->getHeight()) - *c;
9012.1.286 by Krzysztof Kosiński
Revert the inverted coordinate system fix. 3D Boxes and guides
2301
    move_p[Geom::Y] = -move_p[Geom::Y];
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2302
    Geom::Affine move = Geom::Affine(Geom::Translate(move_p));
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2303
2304
    GSList *items = g_slist_copy((GSList *) selection->itemList());
2305
7645 by pjrm
noop: whitespace
2306
    items = g_slist_sort(items, (GCompareFunc) sp_object_compare_position);
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2307
2308
    // bottommost object, after sorting
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2309
    SPObject *parent = SP_OBJECT(items->data)->parent;
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2310
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2311
    Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine());
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2312
2313
    // remember the position of the first item
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2314
    gint pos = SP_OBJECT(items->data)->getRepr()->position();
4025 by joncruz
Warning cleanup
2315
    (void)pos; // TODO check why this was remembered
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2316
2317
    // create a list of duplicates
2318
    GSList *repr_copies = NULL;
2319
    for (GSList *i = items; i != NULL; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2320
        Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc);
7645 by pjrm
noop: whitespace
2321
        repr_copies = g_slist_prepend(repr_copies, dup);
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2322
    }
2323
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2324
    Geom::Rect bbox(desktop->dt2doc(r->min()), desktop->dt2doc(r->max()));
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2325
2326
    if (apply) {
2327
        // delete objects so that their clones don't get alerted; this object will be restored shortly
2328
        for (GSList *i = items; i != NULL; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2329
            SPObject *item = reinterpret_cast<SPObject*>(i->data);
7645 by pjrm
noop: whitespace
2330
            item->deleteObject(false);
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2331
        }
2332
    }
2333
2334
    // Hack: Temporarily set clone compensation to unmoved, so that we can move clone-originals
2335
    // without disturbing clones.
2336
    // See ActorAlign::on_button_click() in src/ui/dialog/align-and-distribute.cpp
6823 by tweenk
Refactored preferences handling into a new version of
2337
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
2338
    int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
2339
    prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2340
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2341
    gchar const *mark_id = generate_marker(repr_copies, bbox, doc,
2342
                                           ( Geom::Affine(Geom::Translate(desktop->dt2doc(
6839 by cilix42
Next roud of NR ==> Geom conversion
2343
                                                                              Geom::Point(r->min()[Geom::X],
2344
                                                                                          r->max()[Geom::Y]))))
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2345
                                             * parent_transform.inverse() ),
2346
                                           parent_transform * move);
4025 by joncruz
Warning cleanup
2347
    (void)mark_id;
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2348
2349
    // restore compensation setting
6885 by Ted Gould
From trunk
2350
    prefs->setInt("/options/clonecompensation/value", saved_compensation);
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2351
2352
7645 by pjrm
noop: whitespace
2353
    g_slist_free(items);
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2354
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2355
    DocumentUndo::done(doc, SP_VERB_EDIT_SELECTION_2_MARKER,
2356
                       _("Objects to marker"));
3864 by johanengelen
apply John Cliff's patch [ 1743843 ] Create Marker from Selection Menu Item
2357
}
2358
5124 by cilix42
Add option to treat grups as single objects when converting to guides.
2359
static void sp_selection_to_guides_recursive(SPItem *item, bool deleteitem, bool wholegroups) {
2360
    if (SP_IS_GROUP(item) && !SP_IS_BOX3D(item) && !wholegroups) {
7645 by pjrm
noop: whitespace
2361
        for (GSList *i = sp_item_group_item_list(SP_GROUP(item)); i != NULL; i = i->next) {
5124 by cilix42
Add option to treat grups as single objects when converting to guides.
2362
            sp_selection_to_guides_recursive(SP_ITEM(i->data), deleteitem, wholegroups);
4467 by cilix42
Allow conversion of all selected items to guides (for items other than rectangles or 3D boxes these are simply aligned along the bounding box of the item being converted)
2363
        }
2364
    } else {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2365
        item->convert_item_to_guides();
4514 by cilix42
Add option in Preferences to keep objects after conversion to guides
2366
2367
        if (deleteitem) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2368
            item->deleteObject(true);
4514 by cilix42
Add option in Preferences to keep objects after conversion to guides
2369
        }
4467 by cilix42
Allow conversion of all selected items to guides (for items other than rectangles or 3D boxes these are simply aligned along the bounding box of the item being converted)
2370
    }
2371
}
2372
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
2373
void sp_selection_to_guides(SPDesktop *desktop)
4462 by cilix42
Add possibility to convert objects (only rectangles and 3D boxes currently) to guidelines. Also see corresponding post on the mailing list; in particular, feel free to revert it if this is inappropriate during Frost phase.
2374
{
2375
    if (desktop == NULL)
2376
        return;
2377
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
2378
    SPDocument *doc = sp_desktop_document(desktop);
4462 by cilix42
Add possibility to convert objects (only rectangles and 3D boxes currently) to guidelines. Also see corresponding post on the mailing list; in particular, feel free to revert it if this is inappropriate during Frost phase.
2379
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
2380
    // we need to copy the list because it gets reset when objects are deleted
2381
    GSList *items = g_slist_copy((GSList *) selection->itemList());
4467 by cilix42
Allow conversion of all selected items to guides (for items other than rectangles or 3D boxes these are simply aligned along the bounding box of the item being converted)
2382
2383
    if (!items) {
2384
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to convert to guides."));
2385
        return;
2386
    }
7645 by pjrm
noop: whitespace
2387
6823 by tweenk
Refactored preferences handling into a new version of
2388
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
2389
    bool deleteitem = !prefs->getBool("/tools/cvg_keep_objects", 0);
2390
    bool wholegroups = prefs->getBool("/tools/cvg_convert_whole_groups", 0);
4514 by cilix42
Add option in Preferences to keep objects after conversion to guides
2391
4462 by cilix42
Add possibility to convert objects (only rectangles and 3D boxes currently) to guidelines. Also see corresponding post on the mailing list; in particular, feel free to revert it if this is inappropriate during Frost phase.
2392
    for (GSList const *i = items; i != NULL; i = i->next) {
5124 by cilix42
Add option to treat grups as single objects when converting to guides.
2393
        sp_selection_to_guides_recursive(SP_ITEM(i->data), deleteitem, wholegroups);
4467 by cilix42
Allow conversion of all selected items to guides (for items other than rectangles or 3D boxes these are simply aligned along the bounding box of the item being converted)
2394
    }
2395
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2396
    DocumentUndo::done(doc, SP_VERB_EDIT_SELECTION_2_GUIDES, _("Objects to guides"));
4462 by cilix42
Add possibility to convert objects (only rectangles and 3D boxes currently) to guidelines. Also see corresponding post on the mailing list; in particular, feel free to revert it if this is inappropriate during Frost phase.
2397
}
2398
1 by mental
moving trunk for module inkscape
2399
void
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
2400
sp_selection_tile(SPDesktop *desktop, bool apply)
1 by mental
moving trunk for module inkscape
2401
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2402
    if (desktop == NULL) {
1 by mental
moving trunk for module inkscape
2403
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2404
    }
1 by mental
moving trunk for module inkscape
2405
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
2406
    SPDocument *doc = sp_desktop_document(desktop);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2407
    Inkscape::XML::Document *xml_doc = doc->getReprDoc();
1 by mental
moving trunk for module inkscape
2408
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
2409
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
2410
2411
    // check if something is selected
2412
    if (selection->isEmpty()) {
2413
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to convert to pattern."));
2414
        return;
2415
    }
2416
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2417
    doc->ensureUpToDate();
2418
    Geom::OptRect r = selection->visualBounds();
6891 by Ted Gould
Merge from fe-moved
2419
    if ( !r ) {
1 by mental
moving trunk for module inkscape
2420
        return;
2421
    }
2422
2423
    // calculate the transform to be applied to objects to move them to 0,0
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2424
    Geom::Point move_p = Geom::Point(0, doc->getHeight()) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y]));
9012.1.286 by Krzysztof Kosiński
Revert the inverted coordinate system fix. 3D Boxes and guides
2425
    move_p[Geom::Y] = -move_p[Geom::Y];
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2426
    Geom::Affine move = Geom::Affine(Geom::Translate(move_p));
1 by mental
moving trunk for module inkscape
2427
2428
    GSList *items = g_slist_copy((GSList *) selection->itemList());
2429
7645 by pjrm
noop: whitespace
2430
    items = g_slist_sort(items, (GCompareFunc) sp_object_compare_position);
1 by mental
moving trunk for module inkscape
2431
2432
    // bottommost object, after sorting
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2433
    SPObject *parent = SP_OBJECT(items->data)->parent;
1 by mental
moving trunk for module inkscape
2434
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2435
    Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine());
1666 by buliabyak
fix pattern transform when doing object-to-pattern within a transformed group
2436
1 by mental
moving trunk for module inkscape
2437
    // remember the position of the first item
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2438
    gint pos = SP_OBJECT(items->data)->getRepr()->position();
1 by mental
moving trunk for module inkscape
2439
2440
    // create a list of duplicates
2441
    GSList *repr_copies = NULL;
2442
    for (GSList *i = items; i != NULL; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2443
        Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc);
7645 by pjrm
noop: whitespace
2444
        repr_copies = g_slist_prepend(repr_copies, dup);
1 by mental
moving trunk for module inkscape
2445
    }
4991 by buliabyak
fix 199791
2446
    // restore the z-order after prepends
7645 by pjrm
noop: whitespace
2447
    repr_copies = g_slist_reverse(repr_copies);
1 by mental
moving trunk for module inkscape
2448
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2449
    Geom::Rect bbox(desktop->dt2doc(r->min()), desktop->dt2doc(r->max()));
1 by mental
moving trunk for module inkscape
2450
2451
    if (apply) {
2452
        // delete objects so that their clones don't get alerted; this object will be restored shortly
2453
        for (GSList *i = items; i != NULL; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2454
            SPObject *item = reinterpret_cast<SPObject*>(i->data);
7645 by pjrm
noop: whitespace
2455
            item->deleteObject(false);
1 by mental
moving trunk for module inkscape
2456
        }
2457
    }
2458
2459
    // Hack: Temporarily set clone compensation to unmoved, so that we can move clone-originals
2460
    // without disturbing clones.
2461
    // See ActorAlign::on_button_click() in src/ui/dialog/align-and-distribute.cpp
6823 by tweenk
Refactored preferences handling into a new version of
2462
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
2463
    int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
2464
    prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
1 by mental
moving trunk for module inkscape
2465
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2466
    gchar const *pat_id = pattern_tile(repr_copies, bbox, doc,
2467
                                       ( Geom::Affine(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X],
6887 by Ted Gould
Merge from trunk
2468
                                                                                            r->max()[Geom::Y]))))
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2469
                                         * parent_transform.inverse() ),
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2470
                                       parent_transform * move);
1 by mental
moving trunk for module inkscape
2471
2472
    // restore compensation setting
6885 by Ted Gould
From trunk
2473
    prefs->setInt("/options/clonecompensation/value", saved_compensation);
1 by mental
moving trunk for module inkscape
2474
2475
    if (apply) {
2253 by mental
start switching sp_repr_new* over to XML::Document::create*, and rename create methods to match DOM
2476
        Inkscape::XML::Node *rect = xml_doc->createElement("svg:rect");
1 by mental
moving trunk for module inkscape
2477
        rect->setAttribute("style", g_strdup_printf("stroke:none;fill:url(#%s)", pat_id));
1666 by buliabyak
fix pattern transform when doing object-to-pattern within a transformed group
2478
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2479
        Geom::Point min = bbox.min() * parent_transform.inverse();
2480
        Geom::Point max = bbox.max() * parent_transform.inverse();
1666 by buliabyak
fix pattern transform when doing object-to-pattern within a transformed group
2481
6887 by Ted Gould
Merge from trunk
2482
        sp_repr_set_svg_double(rect, "width", max[Geom::X] - min[Geom::X]);
2483
        sp_repr_set_svg_double(rect, "height", max[Geom::Y] - min[Geom::Y]);
2484
        sp_repr_set_svg_double(rect, "x", min[Geom::X]);
2485
        sp_repr_set_svg_double(rect, "y", min[Geom::Y]);
1 by mental
moving trunk for module inkscape
2486
2487
        // restore parent and position
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2488
        parent->getRepr()->appendChild(rect);
1 by mental
moving trunk for module inkscape
2489
        rect->setPosition(pos > 0 ? pos : 0);
7645 by pjrm
noop: whitespace
2490
        SPItem *rectangle = (SPItem *) sp_desktop_document(desktop)->getObjectByRepr(rect);
1 by mental
moving trunk for module inkscape
2491
2492
        Inkscape::GC::release(rect);
2493
2494
        selection->clear();
2495
        selection->set(rectangle);
2496
    }
2497
7645 by pjrm
noop: whitespace
2498
    g_slist_free(items);
1 by mental
moving trunk for module inkscape
2499
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2500
    DocumentUndo::done(doc, SP_VERB_EDIT_TILE,
2501
                       _("Objects to pattern"));
1 by mental
moving trunk for module inkscape
2502
}
2503
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2504
void sp_selection_untile(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
2505
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2506
    if (desktop == NULL) {
1 by mental
moving trunk for module inkscape
2507
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2508
    }
1 by mental
moving trunk for module inkscape
2509
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
2510
    SPDocument *doc = sp_desktop_document(desktop);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2511
    Inkscape::XML::Document *xml_doc = doc->getReprDoc();
1 by mental
moving trunk for module inkscape
2512
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
2513
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
2514
2515
    // check if something is selected
2516
    if (selection->isEmpty()) {
2517
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select an <b>object with pattern fill</b> to extract objects from."));
2518
        return;
2519
    }
2520
2521
    GSList *new_select = NULL;
2522
2523
    bool did = false;
2524
2525
    for (GSList *items = g_slist_copy((GSList *) selection->itemList());
2526
         items != NULL;
2527
         items = items->next) {
2528
2529
        SPItem *item = (SPItem *) items->data;
2530
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2531
        SPStyle *style = item->style;
1 by mental
moving trunk for module inkscape
2532
3706 by joncruz
Purged fill type enum
2533
        if (!style || !style->fill.isPaintserver())
1 by mental
moving trunk for module inkscape
2534
            continue;
2535
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2536
        SPPaintServer *server = item->style->getFillPaintServer();
1 by mental
moving trunk for module inkscape
2537
2538
        if (!SP_IS_PATTERN(server))
2539
            continue;
2540
2541
        did = true;
2542
7645 by pjrm
noop: whitespace
2543
        SPPattern *pattern = pattern_getroot(SP_PATTERN(server));
1 by mental
moving trunk for module inkscape
2544
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2545
        Geom::Affine pat_transform = pattern_patternTransform(SP_PATTERN(server));
1 by mental
moving trunk for module inkscape
2546
        pat_transform *= item->transform;
2547
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2548
        for (SPObject *child = pattern->firstChild() ; child != NULL; child = child->next ) {
2549
            Inkscape::XML::Node *copy = child->getRepr()->duplicate(xml_doc);
7645 by pjrm
noop: whitespace
2550
            SPItem *i = SP_ITEM(desktop->currentLayer()->appendChildRepr(copy));
1 by mental
moving trunk for module inkscape
2551
2552
           // FIXME: relink clones to the new canvas objects
134 by rwst
bulk whitespace removal patch #1198588 by gigaclon
2553
           // use SPObject::setid when mental finishes it to steal ids of
1 by mental
moving trunk for module inkscape
2554
2555
            // this is needed to make sure the new item has curve (simply requestDisplayUpdate does not work)
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2556
            doc->ensureUpToDate();
1 by mental
moving trunk for module inkscape
2557
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2558
            Geom::Affine transform( i->transform * pat_transform );
2559
            i->doWriteTransform(i->getRepr(), transform);
1 by mental
moving trunk for module inkscape
2560
2561
            new_select = g_slist_prepend(new_select, i);
2562
        }
2563
7645 by pjrm
noop: whitespace
2564
        SPCSSAttr *css = sp_repr_css_attr_new();
2565
        sp_repr_css_set_property(css, "fill", "none");
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2566
        sp_repr_css_change(item->getRepr(), css, "style");
1 by mental
moving trunk for module inkscape
2567
    }
2568
2569
    if (!did) {
2570
        desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No pattern fills</b> in the selection."));
2571
    } else {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2572
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_EDIT_UNTILE,
2573
                           _("Pattern to objects"));
1 by mental
moving trunk for module inkscape
2574
        selection->setList(new_select);
2575
    }
2576
}
2577
2578
void
7645 by pjrm
noop: whitespace
2579
sp_selection_get_export_hints(Inkscape::Selection *selection, char const **filename, float *xdpi, float *ydpi)
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2580
{
2581
    if (selection->isEmpty()) {
2582
        return;
2583
    }
2584
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2585
    GSList const *reprlst = selection->reprList();
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2586
    bool filename_search = TRUE;
2587
    bool xdpi_search = TRUE;
2588
    bool ydpi_search = TRUE;
2589
7645 by pjrm
noop: whitespace
2590
    for (; reprlst != NULL &&
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2591
            filename_search &&
2592
            xdpi_search &&
2593
            ydpi_search;
2594
        reprlst = reprlst->next) {
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2595
        gchar const *dpi_string;
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2596
        Inkscape::XML::Node * repr = (Inkscape::XML::Node *)reprlst->data;
2597
2598
        if (filename_search) {
2599
            *filename = repr->attribute("inkscape:export-filename");
2600
            if (*filename != NULL)
2601
                filename_search = FALSE;
2602
        }
2603
2604
        if (xdpi_search) {
2605
            dpi_string = NULL;
2606
            dpi_string = repr->attribute("inkscape:export-xdpi");
2607
            if (dpi_string != NULL) {
2608
                *xdpi = atof(dpi_string);
2609
                xdpi_search = FALSE;
2610
            }
2611
        }
2612
2613
        if (ydpi_search) {
2614
            dpi_string = NULL;
2615
            dpi_string = repr->attribute("inkscape:export-ydpi");
2616
            if (dpi_string != NULL) {
2617
                *ydpi = atof(dpi_string);
2618
                ydpi_search = FALSE;
2619
            }
2620
        }
2621
    }
2622
}
2623
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2624
void sp_document_get_export_hints(SPDocument *doc, char const **filename, float *xdpi, float *ydpi)
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2625
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2626
    Inkscape::XML::Node * repr = doc->getReprRoot();
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2627
2628
    *filename = repr->attribute("inkscape:export-filename");
2629
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2630
    gchar const *dpi_string = repr->attribute("inkscape:export-xdpi");
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2631
    if (dpi_string != NULL) {
2632
        *xdpi = atof(dpi_string);
2633
    }
2634
2635
    dpi_string = NULL;
2636
    dpi_string = repr->attribute("inkscape:export-ydpi");
2637
    if (dpi_string != NULL) {
2638
        *ydpi = atof(dpi_string);
2639
    }
2640
}
2641
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2642
void sp_selection_create_bitmap_copy(SPDesktop *desktop)
1 by mental
moving trunk for module inkscape
2643
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2644
    if (desktop == NULL) {
1 by mental
moving trunk for module inkscape
2645
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2646
    }
1 by mental
moving trunk for module inkscape
2647
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
2648
    SPDocument *document = sp_desktop_document(desktop);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2649
    Inkscape::XML::Document *xml_doc = document->getReprDoc();
1 by mental
moving trunk for module inkscape
2650
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
2651
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
1 by mental
moving trunk for module inkscape
2652
2653
    // check if something is selected
2654
    if (selection->isEmpty()) {
2655
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to make a bitmap copy."));
2656
        return;
2657
    }
2658
5866 by buliabyak
remove filters verb and command
2659
    desktop->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Rendering bitmap..."));
2660
    // set "busy" cursor
2661
    desktop->setWaitingCursor();
2662
1 by mental
moving trunk for module inkscape
2663
    // Get the bounding box of the selection
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2664
    document->ensureUpToDate();
2665
    Geom::OptRect bbox = selection->visualBounds();
2666
    if (!bbox) {
5866 by buliabyak
remove filters verb and command
2667
        desktop->clearWaitingCursor();
1 by mental
moving trunk for module inkscape
2668
        return; // exceptional situation, so not bother with a translatable error message, just quit quietly
2669
    }
2670
2671
    // List of the items to show; all others will be hidden
7645 by pjrm
noop: whitespace
2672
    GSList *items = g_slist_copy((GSList *) selection->itemList());
1 by mental
moving trunk for module inkscape
2673
2674
    // Sort items so that the topmost comes last
2675
    items = g_slist_sort(items, (GCompareFunc) sp_item_repr_compare_position);
2676
2677
    // Generate a random value from the current time (you may create bitmap from the same object(s)
2678
    // multiple times, and this is done so that they don't clash)
2679
    GTimeVal cu;
7645 by pjrm
noop: whitespace
2680
    g_get_current_time(&cu);
134 by rwst
bulk whitespace removal patch #1198588 by gigaclon
2681
    guint current = (int) (cu.tv_sec * 1000000 + cu.tv_usec) % 1024;
1 by mental
moving trunk for module inkscape
2682
7646 by pjrm
noop: rename a local var
2683
    // Create the filename.
2684
    gchar *const basename = g_strdup_printf("%s-%s-%u.png",
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2685
                                            document->getName(),
2686
                                            SP_OBJECT(items->data)->getRepr()->attribute("id"),
7646 by pjrm
noop: rename a local var
2687
                                            current);
1 by mental
moving trunk for module inkscape
2688
    // Imagemagick is known not to handle spaces in filenames, so we replace anything but letters,
2689
    // digits, and a few other chars, with "_"
7646 by pjrm
noop: rename a local var
2690
    g_strcanon(basename, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.=+~$#@^&!?", '_');
7216 by buliabyak
use the same steps to figure out dir for bitmap copy as in export dialog
2691
2692
    // Build the complete path by adding document base dir, if set, otherwise home dir
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2693
    gchar *directory = NULL;
2694
    if ( document->getURI() ) {
2695
        directory = g_path_get_dirname( document->getURI() );
7216 by buliabyak
use the same steps to figure out dir for bitmap copy as in export dialog
2696
    }
2697
    if (directory == NULL) {
2698
        directory = homedir_path(NULL);
2699
    }
7646 by pjrm
noop: rename a local var
2700
    gchar *filepath = g_build_filename(directory, basename, NULL);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2701
    g_free(directory);
1 by mental
moving trunk for module inkscape
2702
7645 by pjrm
noop: whitespace
2703
    //g_print("%s\n", filepath);
1 by mental
moving trunk for module inkscape
2704
2705
    // Remember parent and z-order of the topmost one
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2706
    gint pos = SP_OBJECT(g_slist_last(items)->data)->getRepr()->position();
2707
    SPObject *parent_object = SP_OBJECT(g_slist_last(items)->data)->parent;
2708
    Inkscape::XML::Node *parent = parent_object->getRepr();
1 by mental
moving trunk for module inkscape
2709
2710
    // Calculate resolution
6823 by tweenk
Refactored preferences handling into a new version of
2711
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1 by mental
moving trunk for module inkscape
2712
    double res;
6885 by Ted Gould
From trunk
2713
    int const prefs_res = prefs->getInt("/options/createbitmap/resolution", 0);
2714
    int const prefs_min = prefs->getInt("/options/createbitmap/minsize", 0);
1 by mental
moving trunk for module inkscape
2715
    if (0 < prefs_res) {
2716
        // If it's given explicitly in prefs, take it
2717
        res = prefs_res;
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2718
    } else if (0 < prefs_min) {
2719
        // If minsize is given, look up minimum bitmap size (default 250 pixels) and calculate resolution from it
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2720
        res = PX_PER_IN * prefs_min / MIN(bbox->width(), bbox->height());
1 by mental
moving trunk for module inkscape
2721
    } else {
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2722
        float hint_xdpi = 0, hint_ydpi = 0;
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2723
        char const *hint_filename;
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2724
        // take resolution hint from the selected objects
7645 by pjrm
noop: whitespace
2725
        sp_selection_get_export_hints(selection, &hint_filename, &hint_xdpi, &hint_ydpi);
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2726
        if (hint_xdpi != 0) {
2727
            res = hint_xdpi;
2728
        } else {
2729
            // take resolution hint from the document
7645 by pjrm
noop: whitespace
2730
            sp_document_get_export_hints(document, &hint_filename, &hint_xdpi, &hint_ydpi);
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2731
            if (hint_xdpi != 0) {
2732
                res = hint_xdpi;
2733
            } else {
2734
                // if all else fails, take the default 90 dpi
2735
                res = PX_PER_IN;
2736
            }
2737
        }
1 by mental
moving trunk for module inkscape
2738
    }
2739
2740
    // The width and height of the bitmap in pixels
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2741
    unsigned width = (unsigned) floor(bbox->width() * res / PX_PER_IN);
2742
    unsigned height =(unsigned) floor(bbox->height() * res / PX_PER_IN);
1 by mental
moving trunk for module inkscape
2743
5866 by buliabyak
remove filters verb and command
2744
    // Find out if we have to run an external filter
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2745
    gchar const *run = NULL;
6885 by Ted Gould
From trunk
2746
    Glib::ustring filter = prefs->getString("/options/createbitmap/filter");
6823 by tweenk
Refactored preferences handling into a new version of
2747
    if (!filter.empty()) {
1 by mental
moving trunk for module inkscape
2748
        // filter command is given;
2749
        // see if we have a parameter to pass to it
6885 by Ted Gould
From trunk
2750
        Glib::ustring param1 = prefs->getString("/options/createbitmap/filter_param1");
6823 by tweenk
Refactored preferences handling into a new version of
2751
        if (!param1.empty()) {
2752
            if (param1[param1.length() - 1] == '%') {
1 by mental
moving trunk for module inkscape
2753
                // if the param string ends with %, interpret it as a percentage of the image's max dimension
2754
                gchar p1[256];
7645 by pjrm
noop: whitespace
2755
                g_ascii_dtostr(p1, 256, ceil(g_ascii_strtod(param1.data(), NULL) * MAX(width, height) / 100));
1 by mental
moving trunk for module inkscape
2756
                // the first param is always the image filename, the second is param1
7645 by pjrm
noop: whitespace
2757
                run = g_strdup_printf("%s \"%s\" %s", filter.data(), filepath, p1);
1 by mental
moving trunk for module inkscape
2758
            } else {
2759
                // otherwise pass the param1 unchanged
7645 by pjrm
noop: whitespace
2760
                run = g_strdup_printf("%s \"%s\" %s", filter.data(), filepath, param1.data());
1 by mental
moving trunk for module inkscape
2761
            }
2762
        } else {
2763
            // run without extra parameter
7645 by pjrm
noop: whitespace
2764
            run = g_strdup_printf("%s \"%s\"", filter.data(), filepath);
1 by mental
moving trunk for module inkscape
2765
        }
2766
    }
2767
2768
    // Calculate the matrix that will be applied to the image so that it exactly overlaps the source objects
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2769
    Geom::Affine eek(SP_ITEM(parent_object)->i2dt_affine());
2770
    Geom::Affine t;
2503 by buliabyak
fix an error in rounding negative coords
2771
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2772
    double shift_x = bbox->min()[Geom::X];
2773
    double shift_y = bbox->max()[Geom::Y];
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2774
    if (res == PX_PER_IN) { // for default 90 dpi, snap it to pixel grid
7645 by pjrm
noop: whitespace
2775
        shift_x = round(shift_x);
9012.1.286 by Krzysztof Kosiński
Revert the inverted coordinate system fix. 3D Boxes and guides
2776
        shift_y = -round(-shift_y); // this gets correct rounding despite coordinate inversion, remove the negations when the inversion is gone
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2777
    }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2778
    t = Geom::Scale(1, -1) * Geom::Translate(shift_x, shift_y) * eek.inverse();  /// @fixme hardcoded doc2dt transform?
1 by mental
moving trunk for module inkscape
2779
2780
    // Do the export
2781
    sp_export_png_file(document, filepath,
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2782
                       bbox->min()[Geom::X], bbox->min()[Geom::Y],
2783
                       bbox->max()[Geom::X], bbox->max()[Geom::Y],
7645 by pjrm
noop: whitespace
2784
                       width, height, res, res,
2785
                       (guint32) 0xffffff00,
2786
                       NULL, NULL,
2787
                       true,  /*bool force_overwrite,*/
2788
                       items);
1 by mental
moving trunk for module inkscape
2789
7645 by pjrm
noop: whitespace
2790
    g_slist_free(items);
1 by mental
moving trunk for module inkscape
2791
2792
    // Run filter, if any
2793
    if (run) {
7645 by pjrm
noop: whitespace
2794
        g_print("Running external filter: %s\n", run);
6084 by JucaBlues
warning cleanup
2795
        int retval;
7645 by pjrm
noop: whitespace
2796
        retval = system(run);
1 by mental
moving trunk for module inkscape
2797
    }
2798
2799
    // Import the image back
7645 by pjrm
noop: whitespace
2800
    GdkPixbuf *pb = gdk_pixbuf_new_from_file(filepath, NULL);
1 by mental
moving trunk for module inkscape
2801
    if (pb) {
2802
        // Create the repr for the image
2253 by mental
start switching sp_repr_new* over to XML::Document::create*, and rename create methods to match DOM
2803
        Inkscape::XML::Node * repr = xml_doc->createElement("svg:image");
9012.1.132 by Krzysztof Kosiński
Always embed bitmap copies created with Alt+B.
2804
        sp_embed_image(repr, pb, "image/png");
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2805
        if (res == PX_PER_IN) { // for default 90 dpi, snap it to pixel grid
2806
            sp_repr_set_svg_double(repr, "width", width);
2807
            sp_repr_set_svg_double(repr, "height", height);
2808
        } else {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2809
            sp_repr_set_svg_double(repr, "width", bbox->width());
2810
            sp_repr_set_svg_double(repr, "height", bbox->height());
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2811
        }
1 by mental
moving trunk for module inkscape
2812
2813
        // Write transform
2466 by mental
refactor sp_svg_transform_write to return a dynamically-allocated string
2814
        gchar *c=sp_svg_transform_write(t);
2815
        repr->setAttribute("transform", c);
2500 by buliabyak
fix mental's typo! found purely by chance
2816
        g_free(c);
1 by mental
moving trunk for module inkscape
2817
2818
        // add the new repr to the parent
2819
        parent->appendChild(repr);
2820
149 by rwst
bulk trailing spaces removal. consistency through MD5 of binary
2821
        // move to the saved position
1 by mental
moving trunk for module inkscape
2822
        repr->setPosition(pos > 0 ? pos + 1 : 1);
2823
2824
        // Set selection to the new image
2825
        selection->clear();
2826
        selection->add(repr);
2827
2828
        // Clean up
2829
        Inkscape::GC::release(repr);
7645 by pjrm
noop: whitespace
2830
        gdk_pixbuf_unref(pb);
1 by mental
moving trunk for module inkscape
2831
2832
        // Complete undoable transaction
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2833
        DocumentUndo::done(document, SP_VERB_SELECTION_CREATE_BITMAP,
2834
                           _("Create bitmap"));
1 by mental
moving trunk for module inkscape
2835
    }
2836
5866 by buliabyak
remove filters verb and command
2837
    desktop->clearWaitingCursor();
2838
7646 by pjrm
noop: rename a local var
2839
    g_free(basename);
7645 by pjrm
noop: whitespace
2840
    g_free(filepath);
1 by mental
moving trunk for module inkscape
2841
}
2842
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2843
/**
5190 by mental
system clipboard support (bug #170185) from Chris Kosiński
2844
 * \brief Creates a mask or clipPath from selection
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2845
 * Two different modes:
2846
 *  if applyToLayer, all selection is moved to DEFS as mask/clippath
2847
 *       and is applied to current layer
2848
 *  otherwise, topmost object is used as mask for other objects
2849
 * If \a apply_clip_path parameter is true, clipPath is created, otherwise mask
4025 by joncruz
Warning cleanup
2850
 *
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2851
 */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2852
void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer)
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2853
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2854
    if (desktop == NULL) {
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2855
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2856
    }
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2857
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
2858
    SPDocument *doc = sp_desktop_document(desktop);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2859
    Inkscape::XML::Document *xml_doc = doc->getReprDoc();
4025 by joncruz
Warning cleanup
2860
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
2861
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2862
2863
    // check if something is selected
2864
    bool is_empty = selection->isEmpty();
2865
    if ( apply_to_layer && is_empty) {
431 by buliabyak
insert clippath/mask item above the unmasked item into the same parent, instead of just putting it on top of everything in the current layer
2866
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to create clippath or mask from."));
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2867
        return;
2868
    } else if (!apply_to_layer && ( is_empty || NULL == selection->itemList()->next )) {
431 by buliabyak
insert clippath/mask item above the unmasked item into the same parent, instead of just putting it on top of everything in the current layer
2869
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select mask object and <b>object(s)</b> to apply clippath or mask to."));
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2870
        return;
2871
    }
2290 by buliabyak
temporary fix: prevent crash when clipping/masking an object with its own clone
2872
4025 by joncruz
Warning cleanup
2873
    // FIXME: temporary patch to prevent crash!
2290 by buliabyak
temporary fix: prevent crash when clipping/masking an object with its own clone
2874
    // Remove this when bboxes are fixed to not blow up on an item clipped/masked with its own clone
7645 by pjrm
noop: whitespace
2875
    bool clone_with_original = selection_contains_both_clone_and_original(selection);
2290 by buliabyak
temporary fix: prevent crash when clipping/masking an object with its own clone
2876
    if (clone_with_original) {
2877
        return; // in this version, you cannot clip/mask an object with its own clone
2878
    }
2879
    // /END FIXME
4025 by joncruz
Warning cleanup
2880
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2881
    doc->ensureUpToDate();
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2882
2883
    GSList *items = g_slist_copy((GSList *) selection->itemList());
4025 by joncruz
Warning cleanup
2884
7645 by pjrm
noop: whitespace
2885
    items = g_slist_sort(items, (GCompareFunc) sp_object_compare_position);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2886
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
2887
    // See lp bug #542004
2888
    selection->clear();
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2889
2890
    // create a list of duplicates
2891
    GSList *mask_items = NULL;
2892
    GSList *apply_to_items = NULL;
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
2893
    GSList *items_to_delete = NULL;
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
2894
    GSList *items_to_select = NULL;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2895
6823 by tweenk
Refactored preferences handling into a new version of
2896
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
2897
    bool topmost = prefs->getBool("/options/maskobject/topmost", true);
2898
    bool remove_original = prefs->getBool("/options/maskobject/remove", true);
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2899
    int grouping = prefs->getInt("/options/maskobject/grouping", PREFS_MASKOBJECT_GROUPING_NONE);
4025 by joncruz
Warning cleanup
2900
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2901
    if (apply_to_layer) {
2902
        // all selected items are used for mask, which is applied to a layer
7645 by pjrm
noop: whitespace
2903
        apply_to_items = g_slist_prepend(apply_to_items, desktop->currentLayer());
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2904
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2905
        for (GSList *i = items; i != NULL; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2906
            Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc);
7645 by pjrm
noop: whitespace
2907
            mask_items = g_slist_prepend(mask_items, dup);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2908
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2909
            SPObject *item = reinterpret_cast<SPObject*>(i->data);
2910
            if (remove_original) {
7645 by pjrm
noop: whitespace
2911
                items_to_delete = g_slist_prepend(items_to_delete, item);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2912
            }
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
2913
            else {
2914
                items_to_select = g_slist_prepend(items_to_select, item);
2915
            }
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2916
        }
2917
    } else if (!topmost) {
2918
        // topmost item is used as a mask, which is applied to other items in a selection
2919
        GSList *i = items;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2920
        Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc);
7645 by pjrm
noop: whitespace
2921
        mask_items = g_slist_prepend(mask_items, dup);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2922
2923
        if (remove_original) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2924
            SPObject *item = reinterpret_cast<SPObject*>(i->data);
7645 by pjrm
noop: whitespace
2925
            items_to_delete = g_slist_prepend(items_to_delete, item);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2926
        }
4025 by joncruz
Warning cleanup
2927
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2928
        for (i = i->next; i != NULL; i = i->next) {
7645 by pjrm
noop: whitespace
2929
            apply_to_items = g_slist_prepend(apply_to_items, i->data);
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
2930
            items_to_select = g_slist_prepend(items_to_select, i->data);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2931
        }
2932
    } else {
2933
        GSList *i = NULL;
2934
        for (i = items; NULL != i->next; i = i->next) {
7645 by pjrm
noop: whitespace
2935
            apply_to_items = g_slist_prepend(apply_to_items, i->data);
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
2936
            items_to_select = g_slist_prepend(items_to_select, i->data);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2937
        }
2938
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2939
        Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc);
7645 by pjrm
noop: whitespace
2940
        mask_items = g_slist_prepend(mask_items, dup);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2941
2942
        if (remove_original) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2943
            SPObject *item = reinterpret_cast<SPObject*>(i->data);
7645 by pjrm
noop: whitespace
2944
            items_to_delete = g_slist_prepend(items_to_delete, item);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
2945
        }
2946
    }
4025 by joncruz
Warning cleanup
2947
7645 by pjrm
noop: whitespace
2948
    g_slist_free(items);
269 by knutux
Mask/Clippath transformations on masking/unmasking
2949
    items = NULL;
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
2950
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2951
    if (apply_to_items && grouping == PREFS_MASKOBJECT_GROUPING_ALL) {
2952
        // group all those objects into one group
2953
        // and apply mask to that
2954
        Inkscape::XML::Node *group = xml_doc->createElement("svg:g");
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
2955
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2956
        // make a note we should ungroup this when unsetting mask
2957
        group->setAttribute("inkscape:groupmode", "maskhelper");
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
2958
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2959
        GSList *reprs_to_group = NULL;
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
2960
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2961
        for (GSList *i = apply_to_items ; NULL != i ; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2962
            reprs_to_group = g_slist_prepend(reprs_to_group, SP_OBJECT(i->data)->getRepr());
2963
            items_to_select = g_slist_remove(items_to_select, i->data);
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2964
        }
2965
        reprs_to_group = g_slist_reverse(reprs_to_group);
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
2966
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2967
        sp_selection_group_impl(reprs_to_group, group, xml_doc, doc);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2968
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
2969
        reprs_to_group = NULL;
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
2970
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2971
        // apply clip/mask only to newly created group
2972
        g_slist_free(apply_to_items);
2973
        apply_to_items = NULL;
2974
        apply_to_items = g_slist_prepend(apply_to_items, doc->getObjectByRepr(group));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
2975
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
2976
        items_to_select = g_slist_prepend(items_to_select, doc->getObjectByRepr(group));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
2977
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
2978
        Inkscape::GC::release(group);
2979
    }
4025 by joncruz
Warning cleanup
2980
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2981
    gchar const *attributeName = apply_clip_path ? "clip-path" : "mask";
269 by knutux
Mask/Clippath transformations on masking/unmasking
2982
    for (GSList *i = apply_to_items; NULL != i; i = i->next) {
2983
        SPItem *item = reinterpret_cast<SPItem *>(i->data);
2984
        // inverted object transform should be applied to a mask object,
2985
        // as mask is calculated in user space (after applying transform)
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2986
        Geom::Affine maskTransform(item->transform.inverse());
269 by knutux
Mask/Clippath transformations on masking/unmasking
2987
2988
        GSList *mask_items_dup = NULL;
2989
        for (GSList *mask_item = mask_items; NULL != mask_item; mask_item = mask_item->next) {
2723 by mental
plumb XML::Document parameter into duplication, courtesy of bryce
2990
            Inkscape::XML::Node *dup = reinterpret_cast<Inkscape::XML::Node *>(mask_item->data)->duplicate(xml_doc);
7645 by pjrm
noop: whitespace
2991
            mask_items_dup = g_slist_prepend(mask_items_dup, dup);
269 by knutux
Mask/Clippath transformations on masking/unmasking
2992
        }
2993
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
2994
        gchar const *mask_id = NULL;
269 by knutux
Mask/Clippath transformations on masking/unmasking
2995
        if (apply_clip_path) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
2996
            mask_id = SPClipPath::create(mask_items_dup, doc, &maskTransform);
269 by knutux
Mask/Clippath transformations on masking/unmasking
2997
        } else {
2723 by mental
plumb XML::Document parameter into duplication, courtesy of bryce
2998
            mask_id = sp_mask_create(mask_items_dup, doc, &maskTransform);
269 by knutux
Mask/Clippath transformations on masking/unmasking
2999
        }
3000
7645 by pjrm
noop: whitespace
3001
        g_slist_free(mask_items_dup);
269 by knutux
Mask/Clippath transformations on masking/unmasking
3002
        mask_items_dup = NULL;
3003
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3004
        Inkscape::XML::Node *current = SP_OBJECT(i->data)->getRepr();
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3005
        // Node to apply mask to
3006
        Inkscape::XML::Node *apply_mask_to = current;
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3007
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3008
        if (grouping == PREFS_MASKOBJECT_GROUPING_SEPARATE) {
3009
            // enclose current node in group, and apply crop/mask on that
3010
            Inkscape::XML::Node *group = xml_doc->createElement("svg:g");
3011
            // make a note we should ungroup this when unsetting mask
3012
            group->setAttribute("inkscape:groupmode", "maskhelper");
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3013
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3014
            Inkscape::XML::Node *spnew = current->duplicate(xml_doc);
3015
            gint position = current->position();
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3016
            items_to_select = g_slist_remove(items_to_select, item);
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3017
            current->parent()->appendChild(group);
3018
            sp_repr_unparent(current);
3019
            group->appendChild(spnew);
3020
            group->setPosition(position);
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3021
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3022
            // Apply clip/mask to group instead
3023
            apply_mask_to = group;
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3024
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3025
            items_to_select = g_slist_prepend(items_to_select, doc->getObjectByRepr(group));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3026
            Inkscape::GC::release(spnew);
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3027
            Inkscape::GC::release(group);
3028
        }
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3029
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3030
        apply_mask_to->setAttribute(attributeName, g_strdup_printf("url(#%s)", mask_id));
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3031
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3032
    }
269 by knutux
Mask/Clippath transformations on masking/unmasking
3033
7645 by pjrm
noop: whitespace
3034
    g_slist_free(mask_items);
3035
    g_slist_free(apply_to_items);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3036
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
3037
    for (GSList *i = items_to_delete; NULL != i; i = i->next) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3038
        SPObject *item = reinterpret_cast<SPObject*>(i->data);
7645 by pjrm
noop: whitespace
3039
        item->deleteObject(false);
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3040
        items_to_select = g_slist_remove(items_to_select, item);
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
3041
    }
7645 by pjrm
noop: whitespace
3042
    g_slist_free(items_to_delete);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3043
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3044
    items_to_select = g_slist_reverse(items_to_select);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3045
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3046
    selection->addList(items_to_select);
3047
    g_slist_free(items_to_select);
1943 by buliabyak
factor out retrieving export hints from selection and document; use that for create_bitmap if no resolution/minsize specified in prefs; for default 90dpi, snap the bitmap to pixel grid; move deleting objects when clipping/masking to the end of function
3048
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3049
    if (apply_clip_path) {
3050
        DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Set clipping path"));
3051
    } else {
3052
        DocumentUndo::done(doc, SP_VERB_OBJECT_SET_MASK, _("Set mask"));
3053
    }
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3054
}
3055
6629 by cilix42
Get rid of a whole bunch of further instances of SP_ACTIVE_DESKTOP (where the desktop is readily available in the calling function)
3056
void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3057
    if (desktop == NULL) {
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3058
        return;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3059
    }
4025 by joncruz
Warning cleanup
3060
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
3061
    SPDocument *doc = sp_desktop_document(desktop);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3062
    Inkscape::XML::Document *xml_doc = doc->getReprDoc();
532 by mental
Get rid of the SP_DT_* macros which do nothing more than provide additional, confusing, names for other functions. If shorter names are desired, the actual functions should be renamed -- or better, made into member functions.
3063
    Inkscape::Selection *selection = sp_desktop_selection(desktop);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3064
3065
    // check if something is selected
3066
    if (selection->isEmpty()) {
431 by buliabyak
insert clippath/mask item above the unmasked item into the same parent, instead of just putting it on top of everything in the current layer
3067
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to remove clippath or mask from."));
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3068
        return;
3069
    }
4025 by joncruz
Warning cleanup
3070
6823 by tweenk
Refactored preferences handling into a new version of
3071
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
6885 by Ted Gould
From trunk
3072
    bool remove_original = prefs->getBool("/options/maskobject/remove", true);
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3073
    bool ungroup_masked = prefs->getBool("/options/maskobject/ungrouping", true);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3074
    doc->ensureUpToDate();
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3075
3988 by pjrm
CodingStyle: const placement. (noop; checked no change to .o file.)
3076
    gchar const *attributeName = apply_clip_path ? "clip-path" : "mask";
7645 by pjrm
noop: whitespace
3077
    std::map<SPObject*,SPItem*> referenced_objects;
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3078
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3079
    GSList *items = g_slist_copy((GSList *) selection->itemList());
3080
    selection->clear();
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3081
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3082
    GSList *items_to_ungroup = NULL;
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3083
    GSList *items_to_select = g_slist_copy(items);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3084
    items_to_select = g_slist_reverse(items_to_select);
3085
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3086
7645 by pjrm
noop: whitespace
3087
    // SPObject* refers to a group containing the clipped path or mask itself,
6386 by dvlierop2
Implement snapping of clipping paths and masks
3088
    // whereas SPItem* refers to the item being clipped or masked
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3089
    for (GSList const *i = items; NULL != i; i = i->next) {
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3090
        if (remove_original) {
3091
            // remember referenced mask/clippath, so orphaned masks can be moved back to document
3092
            SPItem *item = reinterpret_cast<SPItem *>(i->data);
3093
            Inkscape::URIReference *uri_ref = NULL;
4025 by joncruz
Warning cleanup
3094
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3095
            if (apply_clip_path) {
3096
                uri_ref = item->clip_ref;
3097
            } else {
3098
                uri_ref = item->mask_ref;
3099
            }
267 by knutux
Fixes to unmasking:
3100
269 by knutux
Mask/Clippath transformations on masking/unmasking
3101
            // collect distinct mask object (and associate with item to apply transform)
3102
            if (NULL != uri_ref && NULL != uri_ref->getObject()) {
3103
                referenced_objects[uri_ref->getObject()] = item;
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3104
            }
3105
        }
3106
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3107
        SP_OBJECT(i->data)->getRepr()->setAttribute(attributeName, "none");
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3108
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3109
        if (ungroup_masked && SP_IS_GROUP(i->data)) {
3110
                // if we had previously enclosed masked object in group,
3111
                // add it to list so we can ungroup it later
3112
                SPGroup *item = SP_GROUP(i->data);
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3113
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3114
                // ungroup only groups we created when setting clip/mask
3115
                if (item->layerMode() == SPGroup::MASK_HELPER) {
3116
                    items_to_ungroup = g_slist_prepend(items_to_ungroup, item);
3117
                }
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3118
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3119
        }
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3120
    }
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3121
    g_slist_free(items);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3122
267 by knutux
Fixes to unmasking:
3123
    // restore mask objects into a document
269 by knutux
Mask/Clippath transformations on masking/unmasking
3124
    for ( std::map<SPObject*,SPItem*>::iterator it = referenced_objects.begin() ; it != referenced_objects.end() ; ++it) {
6386 by dvlierop2
Implement snapping of clipping paths and masks
3125
        SPObject *obj = (*it).first; // Group containing the clipped paths or masks
267 by knutux
Fixes to unmasking:
3126
        GSList *items_to_move = NULL;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3127
        for ( SPObject *child = obj->firstChild() ; child; child = child->getNext() ) {
7645 by pjrm
noop: whitespace
3128
            // Collect all clipped paths and masks within a single group
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3129
            Inkscape::XML::Node *copy = SP_OBJECT(child)->getRepr()->duplicate(xml_doc);
7645 by pjrm
noop: whitespace
3130
            items_to_move = g_slist_prepend(items_to_move, copy);
267 by knutux
Fixes to unmasking:
3131
        }
3132
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3133
        if (!obj->isReferenced()) {
267 by knutux
Fixes to unmasking:
3134
            // delete from defs if no other object references this mask
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3135
            obj->deleteObject(false);
267 by knutux
Fixes to unmasking:
3136
        }
3137
431 by buliabyak
insert clippath/mask item above the unmasked item into the same parent, instead of just putting it on top of everything in the current layer
3138
        // remember parent and position of the item to which the clippath/mask was applied
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3139
        Inkscape::XML::Node *parent = ((*it).second)->getRepr()->parent();
3140
        gint pos = ((*it).second)->getRepr()->position();
431 by buliabyak
insert clippath/mask item above the unmasked item into the same parent, instead of just putting it on top of everything in the current layer
3141
6386 by dvlierop2
Implement snapping of clipping paths and masks
3142
        // Iterate through all clipped paths / masks
267 by knutux
Fixes to unmasking:
3143
        for (GSList *i = items_to_move; NULL != i; i = i->next) {
431 by buliabyak
insert clippath/mask item above the unmasked item into the same parent, instead of just putting it on top of everything in the current layer
3144
            Inkscape::XML::Node *repr = (Inkscape::XML::Node *)i->data;
3145
3146
            // insert into parent, restore pos
3147
            parent->appendChild(repr);
3148
            repr->setPosition((pos + 1) > 0 ? (pos + 1) : 0);
3149
7645 by pjrm
noop: whitespace
3150
            SPItem *mask_item = (SPItem *) sp_desktop_document(desktop)->getObjectByRepr(repr);
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3151
            items_to_select = g_slist_prepend(items_to_select, mask_item);
431 by buliabyak
insert clippath/mask item above the unmasked item into the same parent, instead of just putting it on top of everything in the current layer
3152
3153
            // transform mask, so it is moved the same spot where mask was applied
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3154
            Geom::Affine transform(mask_item->transform);
269 by knutux
Mask/Clippath transformations on masking/unmasking
3155
            transform *= (*it).second->transform;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3156
            mask_item->doWriteTransform(mask_item->getRepr(), transform);
267 by knutux
Fixes to unmasking:
3157
        }
3158
7645 by pjrm
noop: whitespace
3159
        g_slist_free(items_to_move);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3160
    }
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3161
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3162
    // ungroup marked groups added when setting mask
3163
    for (GSList *i = items_to_ungroup ; NULL != i ; i = i->next) {
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3164
        items_to_select = g_slist_remove(items_to_select, SP_GROUP(i->data));
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3165
        GSList *children = NULL;
3166
        sp_item_group_ungroup(SP_GROUP(i->data), &children, false);
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3167
        items_to_select = g_slist_concat(children, items_to_select);
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3168
    }
9012.1.197 by Jon A. Cruz
Cleanup of SP_ACTIVE_DESKTOP to prepare clipboard code for reuse.
3169
9012.1.38 by Josh Andler
Patch by Martin Sucha to add preferences to for grouping on Clip/Mask
3170
    g_slist_free(items_to_ungroup);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3171
9012.1.204 by Josh Andler
Patch by Martin Sucha for 542004
3172
    // rebuild selection
3173
    items_to_select = g_slist_reverse(items_to_select);
3174
    selection->addList(items_to_select);
3175
    g_slist_free(items_to_select);
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3176
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3177
    if (apply_clip_path) {
3178
        DocumentUndo::done(doc, SP_VERB_OBJECT_UNSET_CLIPPATH, _("Release clipping path"));
3179
    } else {
3180
        DocumentUndo::done(doc, SP_VERB_OBJECT_UNSET_MASK, _("Release mask"));
3181
    }
263 by buliabyak
patch by Andrius R. for (un)clip and (un)mask commands
3182
}
1 by mental
moving trunk for module inkscape
3183
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3184
/**
8952 by Josh Andler
Patch by Alex Leone to add margins to resize page options in Document Properties
3185
 * \param with_margins margins defined in the xml under <sodipodi:namedview>
3186
 *                     "fit-margin-..." attributes.  See SPDocument::fitToRect.
3187
 * \return true if an undoable change should be recorded.
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3188
 */
3189
bool
8952 by Josh Andler
Patch by Alex Leone to add margins to resize page options in Document Properties
3190
fit_canvas_to_selection(SPDesktop *desktop, bool with_margins)
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3191
{
3192
    g_return_val_if_fail(desktop != NULL, false);
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
3193
    SPDocument *doc = sp_desktop_document(desktop);
539 by acspike
Adding fit canvas verbs
3194
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3195
    g_return_val_if_fail(doc != NULL, false);
3196
    g_return_val_if_fail(desktop->selection != NULL, false);
539 by acspike
Adding fit canvas verbs
3197
3873 by pjrm
Fix g_return_if_fail failure: It can validly happen that fit_canvas_to_selection is called when nothing is selected (just like many other verbs). So put new message in status bar and return rather than signalling an error with g_return_if_fail.
3198
    if (desktop->selection->isEmpty()) {
3199
        desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to fit canvas to."));
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3200
        return false;
3873 by pjrm
Fix g_return_if_fail failure: It can validly happen that fit_canvas_to_selection is called when nothing is selected (just like many other verbs). So put new message in status bar and return rather than signalling an error with g_return_if_fail.
3201
    }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3202
    Geom::OptRect const bbox(desktop->selection->visualBounds());
6891 by Ted Gould
Merge from fe-moved
3203
    if (bbox) {
8952 by Josh Andler
Patch by Alex Leone to add margins to resize page options in Document Properties
3204
        doc->fitToRect(*bbox, with_margins);
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3205
        return true;
3206
    } else {
3207
        return false;
3208
    }
3209
}
3210
3211
/**
3212
 * Fit canvas to the bounding box of the selection, as an undoable action.
3213
 */
3214
void
3215
verb_fit_canvas_to_selection(SPDesktop *const desktop)
3216
{
3217
    if (fit_canvas_to_selection(desktop)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3218
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_FIT_CANVAS_TO_SELECTION,
3219
                           _("Fit Page to Selection"));
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3220
    }
3221
}
3222
8952 by Josh Andler
Patch by Alex Leone to add margins to resize page options in Document Properties
3223
/**
3224
 * \param with_margins margins defined in the xml under <sodipodi:namedview>
3225
 *                     "fit-margin-..." attributes.  See SPDocument::fitToRect.
3226
 */
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3227
bool
8952 by Josh Andler
Patch by Alex Leone to add margins to resize page options in Document Properties
3228
fit_canvas_to_drawing(SPDocument *doc, bool with_margins)
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3229
{
3230
    g_return_val_if_fail(doc != NULL, false);
3032 by pjrm
noop: Change fitToRect to take NR::Rect instead of old NRRect. Update callers.
3231
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3232
    doc->ensureUpToDate();
3233
    SPItem const *const root = doc->getRoot();
3234
    Geom::OptRect bbox = root->desktopVisualBounds();
6891 by Ted Gould
Merge from fe-moved
3235
    if (bbox) {
8952 by Josh Andler
Patch by Alex Leone to add margins to resize page options in Document Properties
3236
        doc->fitToRect(*bbox, with_margins);
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3237
        return true;
3238
    } else {
3239
        return false;
3240
    }
3241
}
3242
3243
void
3244
verb_fit_canvas_to_drawing(SPDesktop *desktop)
3245
{
3246
    if (fit_canvas_to_drawing(sp_desktop_document(desktop))) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3247
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_FIT_CANVAS_TO_DRAWING,
3248
                           _("Fit Page to Drawing"));
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3249
    }
3250
}
539 by acspike
Adding fit canvas verbs
3251
8952 by Josh Andler
Patch by Alex Leone to add margins to resize page options in Document Properties
3252
/**
3253
 * Fits canvas to selection or drawing with margins from <sodipodi:namedview>
3254
 * "fit-margin-..." attributes.  See SPDocument::fitToRect and
3255
 * ui/dialog/page-sizer.
3256
 */
539 by acspike
Adding fit canvas verbs
3257
void fit_canvas_to_selection_or_drawing(SPDesktop *desktop) {
3258
    g_return_if_fail(desktop != NULL);
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
3259
    SPDocument *doc = sp_desktop_document(desktop);
539 by acspike
Adding fit canvas verbs
3260
3261
    g_return_if_fail(doc != NULL);
3262
    g_return_if_fail(desktop->selection != NULL);
3263
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3264
    bool const changed = ( desktop->selection->isEmpty()
8952 by Josh Andler
Patch by Alex Leone to add margins to resize page options in Document Properties
3265
                           ? fit_canvas_to_drawing(doc, true)
3266
                           : fit_canvas_to_selection(desktop, true) );
6165 by pjrm
fix a long-standing bug with Undo after Fit canvas to selection/drawing.
3267
    if (changed) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3268
        DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_FIT_CANVAS_TO_SELECTION_OR_DRAWING,
3269
                           _("Fit Page to Selection or Drawing"));
539 by acspike
Adding fit canvas verbs
3270
    }
3271
};
3272
2613 by acspike
add verbs for unlocking and unhiding all objects globaly or within the current layer
3273
static void itemtree_map(void (*f)(SPItem *, SPDesktop *), SPObject *root, SPDesktop *desktop) {
3274
    // don't operate on layers
3275
    if (SP_IS_ITEM(root) && !desktop->isLayer(SP_ITEM(root))) {
3276
        f(SP_ITEM(root), desktop);
3277
    }
3278
    for ( SPObject::SiblingIterator iter = root->firstChild() ; iter ; ++iter ) {
3279
        //don't recurse into locked layers
2615 by acspike
send verb ids into history and remove casting errors
3280
        if (!(SP_IS_ITEM(&*iter) && desktop->isLayer(SP_ITEM(&*iter)) && SP_ITEM(&*iter)->isLocked())) {
2613 by acspike
add verbs for unlocking and unhiding all objects globaly or within the current layer
3281
            itemtree_map(f, iter, desktop);
3282
        }
3283
    }
3284
}
3285
4025 by joncruz
Warning cleanup
3286
static void unlock(SPItem *item, SPDesktop */*desktop*/) {
2613 by acspike
add verbs for unlocking and unhiding all objects globaly or within the current layer
3287
    if (item->isLocked()) {
3288
        item->setLocked(FALSE);
3289
    }
3290
}
3291
3292
static void unhide(SPItem *item, SPDesktop *desktop) {
3293
    if (desktop->itemIsHidden(item)) {
3294
        item->setExplicitlyHidden(FALSE);
3295
    }
3296
}
3297
2616 by acspike
move sp_document_done() out into verbs.cpp
3298
static void process_all(void (*f)(SPItem *, SPDesktop *), SPDesktop *dt, bool layer_only) {
2613 by acspike
add verbs for unlocking and unhiding all objects globaly or within the current layer
3299
    if (!dt) return;
4025 by joncruz
Warning cleanup
3300
2613 by acspike
add verbs for unlocking and unhiding all objects globaly or within the current layer
3301
    SPObject *root;
3302
    if (layer_only) {
3303
        root = dt->currentLayer();
3304
    } else {
3305
        root = dt->currentRoot();
3306
    }
4025 by joncruz
Warning cleanup
3307
2613 by acspike
add verbs for unlocking and unhiding all objects globaly or within the current layer
3308
    itemtree_map(f, root, dt);
2616 by acspike
move sp_document_done() out into verbs.cpp
3309
}
3310
3311
void unlock_all(SPDesktop *dt) {
3312
    process_all(&unlock, dt, true);
3313
}
3314
3315
void unlock_all_in_all_layers(SPDesktop *dt) {
3316
    process_all(&unlock, dt, false);
3317
}
3318
3319
void unhide_all(SPDesktop *dt) {
3320
    process_all(&unhide, dt, true);
3321
}
3322
3323
void unhide_all_in_all_layers(SPDesktop *dt) {
3324
    process_all(&unhide, dt, false);
2613 by acspike
add verbs for unlocking and unhiding all objects globaly or within the current layer
3325
}
3326
3472 by johanengelen
Commit LivePathEffect branch to trunk!
3327
1 by mental
moving trunk for module inkscape
3328
/*
3329
  Local Variables:
3330
  mode:c++
3331
  c-file-style:"stroustrup"
3332
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3333
  indent-tabs-mode:nil
3334
  fill-column:99
3335
  End:
3336
*/
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
3337
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :