Merge lp:~mc.../inkscape/mc-selection-transform into lp:~inkscape.dev/inkscape/trunk
- mc-selection-transform
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~mc.../inkscape/mc-selection-transform |
Merge into: | lp:~inkscape.dev/inkscape/trunk |
Diff against target: |
3772 lines (+882/-872) 3 files modified
src/selection-chemistry.cpp (+865/-872) src/selection.cpp (+7/-0) src/selection.h (+10/-0) |
To merge this branch: | bzr merge lp:~mc.../inkscape/mc-selection-transform |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jabiertxof | code | Approve | |
Review via email: mp+269893@code.launchpad.net |
Commit message
Description of the change
Refactoring of sp_selection_
Jabiertxof (jabiertxof) wrote : | # |
I put three minor things about coding style previouly someone review me. AlsoNathan ping me about dont "clangformat" merges, till become accepted. Anyway I read your comment and help me a lot in the review. I do not a usage review, ping me if you want me to compile to give a second try.
Unmerged revisions
- 14347. By Mc
-
more clang-format because i can never get the spacing right
- 14346. By Mc
-
final comments and refactor
- 14345. By Mc
-
refactor + fixed linked offsets
- 14344. By Mc
-
I was not /that/ far yesterday at 4am. Ready to be tested !
- 14343. By Mc
-
works better than previously, but there is still some strange behavior
- 14342. By Mc
-
Wait a minute, is that really working ? Have those several hours with paper and pen, filling pages with matrix multiplications, not been in vain ?
Just kidding, still WIP. make a clone of clone, move the original and first clone, the second moves unexpectedly.
But still, the fact that the first clone behaves right is already pretty cool !
- 14341. By Mc
-
I'm so confused right now.
- 14340. By Mc
-
does not break anything yet. I still have to fix the case where i resize a (original+(clone in a group)) selection
- 14339. By Mc
-
clang-format src/selection-
chemistry. cpp - 14338. By Mc
-
add includes_deeply helper function to test if an object is selected, even indirectly
Preview Diff
1 | === modified file 'src/selection-chemistry.cpp' | |||
2 | --- src/selection-chemistry.cpp 2015-05-26 20:27:00 +0000 | |||
3 | +++ src/selection-chemistry.cpp 2015-09-02 11:21:15 +0000 | |||
4 | @@ -12,15 +12,16 @@ | |||
5 | 12 | * Abhishek Sharma | 12 | * Abhishek Sharma |
6 | 13 | * Kris De Gussem <Kris.DeGussem@gmail.com> | 13 | * Kris De Gussem <Kris.DeGussem@gmail.com> |
7 | 14 | * Tavmjong Bah <tavmjong@free.fr> (Symbol additions) | 14 | * Tavmjong Bah <tavmjong@free.fr> (Symbol additions) |
8 | 15 | * Marc Jeanmougin <marc@jeanmougin.fr> | ||
9 | 15 | * | 16 | * |
11 | 16 | * Copyright (C) 1999-2010,2012 authors | 17 | * Copyright (C) 1999-2010,2012,2015 authors |
12 | 17 | * Copyright (C) 2001-2002 Ximian, Inc. | 18 | * Copyright (C) 2001-2002 Ximian, Inc. |
13 | 18 | * | 19 | * |
14 | 19 | * Released under GNU GPL, read the file 'COPYING' for more information | 20 | * Released under GNU GPL, read the file 'COPYING' for more information |
15 | 20 | */ | 21 | */ |
16 | 21 | 22 | ||
17 | 22 | #ifdef HAVE_CONFIG_H | 23 | #ifdef HAVE_CONFIG_H |
19 | 23 | # include "config.h" | 24 | #include "config.h" |
20 | 24 | #endif | 25 | #endif |
21 | 25 | 26 | ||
22 | 26 | #include <gtkmm/clipboard.h> | 27 | #include <gtkmm/clipboard.h> |
23 | @@ -131,14 +132,12 @@ | |||
24 | 131 | 132 | ||
25 | 132 | // helper for printing error messages, regardless of whether we have a GUI or not | 133 | // helper for printing error messages, regardless of whether we have a GUI or not |
26 | 133 | // If desktop == NULL, errors will be shown on stderr | 134 | // If desktop == NULL, errors will be shown on stderr |
29 | 134 | static void | 135 | static void selection_display_message(SPDesktop *desktop, Inkscape::MessageType msgType, Glib::ustring const &msg) |
28 | 135 | selection_display_message(SPDesktop *desktop, Inkscape::MessageType msgType, Glib::ustring const &msg) | ||
30 | 136 | { | 136 | { |
31 | 137 | if (desktop) { | 137 | if (desktop) { |
32 | 138 | desktop->messageStack()->flash(msgType, msg); | 138 | desktop->messageStack()->flash(msgType, msg); |
33 | 139 | } else { | 139 | } else { |
36 | 140 | if (msgType == Inkscape::IMMEDIATE_MESSAGE || | 140 | if (msgType == Inkscape::IMMEDIATE_MESSAGE || msgType == Inkscape::WARNING_MESSAGE || |
35 | 141 | msgType == Inkscape::WARNING_MESSAGE || | ||
37 | 142 | msgType == Inkscape::ERROR_MESSAGE) { | 141 | msgType == Inkscape::ERROR_MESSAGE) { |
38 | 143 | g_printerr("%s\n", msg.c_str()); | 142 | g_printerr("%s\n", msg.c_str()); |
39 | 144 | } | 143 | } |
40 | @@ -150,7 +149,7 @@ | |||
41 | 150 | void SelectionHelper::selectAll(SPDesktop *dt) | 149 | void SelectionHelper::selectAll(SPDesktop *dt) |
42 | 151 | { | 150 | { |
43 | 152 | if (tools_isactive(dt, TOOLS_NODES)) { | 151 | if (tools_isactive(dt, TOOLS_NODES)) { |
45 | 153 | NodeTool *nt = static_cast<NodeTool*>(dt->event_context); | 152 | NodeTool *nt = static_cast<NodeTool *>(dt->event_context); |
46 | 154 | if (!nt->_multipath->empty()) { | 153 | if (!nt->_multipath->empty()) { |
47 | 155 | nt->_multipath->selectSubpaths(); | 154 | nt->_multipath->selectSubpaths(); |
48 | 156 | return; | 155 | return; |
49 | @@ -162,7 +161,7 @@ | |||
50 | 162 | void SelectionHelper::selectAllInAll(SPDesktop *dt) | 161 | void SelectionHelper::selectAllInAll(SPDesktop *dt) |
51 | 163 | { | 162 | { |
52 | 164 | if (tools_isactive(dt, TOOLS_NODES)) { | 163 | if (tools_isactive(dt, TOOLS_NODES)) { |
54 | 165 | NodeTool *nt = static_cast<NodeTool*>(dt->event_context); | 164 | NodeTool *nt = static_cast<NodeTool *>(dt->event_context); |
55 | 166 | nt->_selected_nodes->selectAll(); | 165 | nt->_selected_nodes->selectAll(); |
56 | 167 | } else { | 166 | } else { |
57 | 168 | sp_edit_select_all_in_all_layers(dt); | 167 | sp_edit_select_all_in_all_layers(dt); |
58 | @@ -173,7 +172,7 @@ | |||
59 | 173 | { | 172 | { |
60 | 174 | NodeTool *nt = NULL; | 173 | NodeTool *nt = NULL; |
61 | 175 | if (tools_isactive(dt, TOOLS_NODES)) { | 174 | if (tools_isactive(dt, TOOLS_NODES)) { |
63 | 176 | nt = static_cast<NodeTool*>(dt->event_context); | 175 | nt = static_cast<NodeTool *>(dt->event_context); |
64 | 177 | } | 176 | } |
65 | 178 | 177 | ||
66 | 179 | if (nt && !nt->_selected_nodes->empty()) { | 178 | if (nt && !nt->_selected_nodes->empty()) { |
67 | @@ -186,35 +185,20 @@ | |||
68 | 186 | } | 185 | } |
69 | 187 | } | 186 | } |
70 | 188 | 187 | ||
95 | 189 | void SelectionHelper::selectSameFillStroke(SPDesktop *dt) | 188 | void SelectionHelper::selectSameFillStroke(SPDesktop *dt) { sp_select_same_fill_stroke_style(dt, true, true, true); } |
96 | 190 | { | 189 | |
97 | 191 | sp_select_same_fill_stroke_style(dt, true, true, true); | 190 | void SelectionHelper::selectSameFillColor(SPDesktop *dt) { sp_select_same_fill_stroke_style(dt, true, false, false); } |
98 | 192 | } | 191 | |
99 | 193 | 192 | void SelectionHelper::selectSameStrokeColor(SPDesktop *dt) { sp_select_same_fill_stroke_style(dt, false, true, false); } | |
100 | 194 | void SelectionHelper::selectSameFillColor(SPDesktop *dt) | 193 | |
101 | 195 | { | 194 | void SelectionHelper::selectSameStrokeStyle(SPDesktop *dt) { sp_select_same_fill_stroke_style(dt, false, false, true); } |
102 | 196 | sp_select_same_fill_stroke_style(dt, true, false, false); | 195 | |
103 | 197 | } | 196 | void SelectionHelper::selectSameObjectType(SPDesktop *dt) { sp_select_same_object_type(dt); } |
80 | 198 | |||
81 | 199 | void SelectionHelper::selectSameStrokeColor(SPDesktop *dt) | ||
82 | 200 | { | ||
83 | 201 | sp_select_same_fill_stroke_style(dt, false, true, false); | ||
84 | 202 | } | ||
85 | 203 | |||
86 | 204 | void SelectionHelper::selectSameStrokeStyle(SPDesktop *dt) | ||
87 | 205 | { | ||
88 | 206 | sp_select_same_fill_stroke_style(dt, false, false, true); | ||
89 | 207 | } | ||
90 | 208 | |||
91 | 209 | void SelectionHelper::selectSameObjectType(SPDesktop *dt) | ||
92 | 210 | { | ||
93 | 211 | sp_select_same_object_type(dt); | ||
94 | 212 | } | ||
104 | 213 | 197 | ||
105 | 214 | void SelectionHelper::invert(SPDesktop *dt) | 198 | void SelectionHelper::invert(SPDesktop *dt) |
106 | 215 | { | 199 | { |
107 | 216 | if (tools_isactive(dt, TOOLS_NODES)) { | 200 | if (tools_isactive(dt, TOOLS_NODES)) { |
109 | 217 | NodeTool *nt = static_cast<NodeTool*>(dt->event_context); | 201 | NodeTool *nt = static_cast<NodeTool *>(dt->event_context); |
110 | 218 | nt->_multipath->invertSelectionInSubpaths(); | 202 | nt->_multipath->invertSelectionInSubpaths(); |
111 | 219 | } else { | 203 | } else { |
112 | 220 | sp_edit_invert(dt); | 204 | sp_edit_invert(dt); |
113 | @@ -224,7 +208,7 @@ | |||
114 | 224 | void SelectionHelper::invertAllInAll(SPDesktop *dt) | 208 | void SelectionHelper::invertAllInAll(SPDesktop *dt) |
115 | 225 | { | 209 | { |
116 | 226 | if (tools_isactive(dt, TOOLS_NODES)) { | 210 | if (tools_isactive(dt, TOOLS_NODES)) { |
118 | 227 | NodeTool *nt = static_cast<NodeTool*>(dt->event_context); | 211 | NodeTool *nt = static_cast<NodeTool *>(dt->event_context); |
119 | 228 | nt->_selected_nodes->invertSelection(); | 212 | nt->_selected_nodes->invertSelection(); |
120 | 229 | } else { | 213 | } else { |
121 | 230 | sp_edit_invert_in_all_layers(dt); | 214 | sp_edit_invert_in_all_layers(dt); |
122 | @@ -235,7 +219,7 @@ | |||
123 | 235 | { | 219 | { |
124 | 236 | // TODO make this a virtual method of event context! | 220 | // TODO make this a virtual method of event context! |
125 | 237 | if (tools_isactive(dt, TOOLS_NODES)) { | 221 | if (tools_isactive(dt, TOOLS_NODES)) { |
127 | 238 | NodeTool *nt = static_cast<NodeTool*>(dt->event_context); | 222 | NodeTool *nt = static_cast<NodeTool *>(dt->event_context); |
128 | 239 | nt->_multipath->reverseSubpaths(); | 223 | nt->_multipath->reverseSubpaths(); |
129 | 240 | } else { | 224 | } else { |
130 | 241 | sp_selected_path_reverse(dt); | 225 | sp_selected_path_reverse(dt); |
131 | @@ -246,10 +230,9 @@ | |||
132 | 246 | { | 230 | { |
133 | 247 | Inkscape::UI::Tools::ToolBase *ec = dt->event_context; | 231 | Inkscape::UI::Tools::ToolBase *ec = dt->event_context; |
134 | 248 | if (tools_isactive(dt, TOOLS_NODES)) { | 232 | if (tools_isactive(dt, TOOLS_NODES)) { |
136 | 249 | NodeTool *nt = static_cast<NodeTool*>(dt->event_context); | 233 | NodeTool *nt = static_cast<NodeTool *>(dt->event_context); |
137 | 250 | nt->_multipath->shiftSelection(1); | 234 | nt->_multipath->shiftSelection(1); |
140 | 251 | } else if (tools_isactive(dt, TOOLS_GRADIENT) | 235 | } else if (tools_isactive(dt, TOOLS_GRADIENT) && ec->_grdrag->isNonEmpty()) { |
139 | 252 | && ec->_grdrag->isNonEmpty()) { | ||
141 | 253 | Inkscape::UI::Tools::sp_gradient_context_select_next(ec); | 236 | Inkscape::UI::Tools::sp_gradient_context_select_next(ec); |
142 | 254 | } else { | 237 | } else { |
143 | 255 | sp_selection_item_next(dt); | 238 | sp_selection_item_next(dt); |
144 | @@ -260,10 +243,9 @@ | |||
145 | 260 | { | 243 | { |
146 | 261 | Inkscape::UI::Tools::ToolBase *ec = dt->event_context; | 244 | Inkscape::UI::Tools::ToolBase *ec = dt->event_context; |
147 | 262 | if (tools_isactive(dt, TOOLS_NODES)) { | 245 | if (tools_isactive(dt, TOOLS_NODES)) { |
149 | 263 | NodeTool *nt = static_cast<NodeTool*>(dt->event_context); | 246 | NodeTool *nt = static_cast<NodeTool *>(dt->event_context); |
150 | 264 | nt->_multipath->shiftSelection(-1); | 247 | nt->_multipath->shiftSelection(-1); |
153 | 265 | } else if (tools_isactive(dt, TOOLS_GRADIENT) | 248 | } else if (tools_isactive(dt, TOOLS_GRADIENT) && ec->_grdrag->isNonEmpty()) { |
152 | 266 | && ec->_grdrag->isNonEmpty()) { | ||
154 | 267 | Inkscape::UI::Tools::sp_gradient_context_select_prev(ec); | 249 | Inkscape::UI::Tools::sp_gradient_context_select_prev(ec); |
155 | 268 | } else { | 250 | } else { |
156 | 269 | sp_selection_item_prev(dt); | 251 | sp_selection_item_prev(dt); |
157 | @@ -273,23 +255,20 @@ | |||
158 | 273 | /* | 255 | /* |
159 | 274 | * Fixes the current selection, removing locked objects from it | 256 | * Fixes the current selection, removing locked objects from it |
160 | 275 | */ | 257 | */ |
162 | 276 | void SelectionHelper::fixSelection(SPDesktop *dt) | 258 | void SelectionHelper::fixSelection(SPDesktop *dt) |
163 | 277 | { | 259 | { |
165 | 278 | if(!dt) | 260 | if (!dt) |
166 | 279 | return; | 261 | return; |
167 | 280 | 262 | ||
168 | 281 | Inkscape::Selection *selection = dt->getSelection(); | 263 | Inkscape::Selection *selection = dt->getSelection(); |
175 | 282 | 264 | ||
176 | 283 | std::vector<SPItem*> items ; | 265 | std::vector<SPItem *> items; |
177 | 284 | 266 | ||
178 | 285 | std::vector<SPItem*> const selList = selection->itemList(); | 267 | std::vector<SPItem *> const selList = selection->itemList(); |
179 | 286 | 268 | ||
180 | 287 | for( std::vector<SPItem*>::const_reverse_iterator i = selList.rbegin(); i != selList.rend(); i++ ) { | 269 | for (std::vector<SPItem *>::const_reverse_iterator i = selList.rbegin(); i != selList.rend(); i++) { |
181 | 288 | SPItem *item = *i; | 270 | SPItem *item = *i; |
186 | 289 | if( item && | 271 | if (item && !dt->isLayer(item) && (!item->isLocked())) { |
183 | 290 | !dt->isLayer(item) && | ||
184 | 291 | (!item->isLocked())) | ||
185 | 292 | { | ||
187 | 293 | items.push_back(item); | 272 | items.push_back(item); |
188 | 294 | } | 273 | } |
189 | 295 | } | 274 | } |
190 | @@ -304,7 +283,8 @@ | |||
191 | 304 | * Copies repr and its inherited css style elements, along with the accumulated transform 'full_t', | 283 | * Copies repr and its inherited css style elements, along with the accumulated transform 'full_t', |
192 | 305 | * then prepends the copy to 'clip'. | 284 | * then prepends the copy to 'clip'. |
193 | 306 | */ | 285 | */ |
195 | 307 | static void sp_selection_copy_one(Inkscape::XML::Node *repr, Geom::Affine full_t, std::vector<Inkscape::XML::Node*> &clip, Inkscape::XML::Document* xml_doc) | 286 | static void sp_selection_copy_one(Inkscape::XML::Node *repr, Geom::Affine full_t, |
196 | 287 | std::vector<Inkscape::XML::Node *> &clip, Inkscape::XML::Document *xml_doc) | ||
197 | 308 | { | 288 | { |
198 | 309 | Inkscape::XML::Node *copy = repr->duplicate(xml_doc); | 289 | Inkscape::XML::Node *copy = repr->duplicate(xml_doc); |
199 | 310 | 290 | ||
200 | @@ -316,21 +296,22 @@ | |||
201 | 316 | // write the complete accumulated transform passed to us | 296 | // write the complete accumulated transform passed to us |
202 | 317 | // (we're dealing with unattached repr, so we write to its attr | 297 | // (we're dealing with unattached repr, so we write to its attr |
203 | 318 | // instead of using sp_item_set_transform) | 298 | // instead of using sp_item_set_transform) |
205 | 319 | gchar *affinestr=sp_svg_transform_write(full_t); | 299 | gchar *affinestr = sp_svg_transform_write(full_t); |
206 | 320 | copy->setAttribute("transform", affinestr); | 300 | copy->setAttribute("transform", affinestr); |
207 | 321 | g_free(affinestr); | 301 | g_free(affinestr); |
208 | 322 | 302 | ||
210 | 323 | clip.insert(clip.begin(),copy); | 303 | clip.insert(clip.begin(), copy); |
211 | 324 | } | 304 | } |
212 | 325 | 305 | ||
214 | 326 | static void sp_selection_copy_impl(std::vector<SPItem*> const &items, std::vector<Inkscape::XML::Node*> &clip, Inkscape::XML::Document* xml_doc) | 306 | static void sp_selection_copy_impl(std::vector<SPItem *> const &items, std::vector<Inkscape::XML::Node *> &clip, |
215 | 307 | Inkscape::XML::Document *xml_doc) | ||
216 | 327 | { | 308 | { |
217 | 328 | // Sort items: | 309 | // Sort items: |
220 | 329 | std::vector<SPItem*> sorted_items(items); | 310 | std::vector<SPItem *> sorted_items(items); |
221 | 330 | sort(sorted_items.begin(),sorted_items.end(),sp_object_compare_position_bool); | 311 | sort(sorted_items.begin(), sorted_items.end(), sp_object_compare_position_bool); |
222 | 331 | 312 | ||
223 | 332 | // Copy item reprs: | 313 | // Copy item reprs: |
225 | 333 | for (std::vector<SPItem*>::const_iterator i = sorted_items.begin(); i != sorted_items.end(); i++) { | 314 | for (std::vector<SPItem *>::const_iterator i = sorted_items.begin(); i != sorted_items.end(); i++) { |
226 | 334 | SPItem *item = *i; | 315 | SPItem *item = *i; |
227 | 335 | if (item) { | 316 | if (item) { |
228 | 336 | sp_selection_copy_one(item->getRepr(), item->i2doc_affine(), clip, xml_doc); | 317 | sp_selection_copy_one(item->getRepr(), item->i2doc_affine(), clip, xml_doc); |
229 | @@ -338,20 +319,21 @@ | |||
230 | 338 | g_assert_not_reached(); | 319 | g_assert_not_reached(); |
231 | 339 | } | 320 | } |
232 | 340 | } | 321 | } |
234 | 341 | reverse(clip.begin(),clip.end()); | 322 | reverse(clip.begin(), clip.end()); |
235 | 342 | } | 323 | } |
236 | 343 | 324 | ||
237 | 344 | // TODO check if parent parameter should be changed to SPItem, of if the code should handle non-items. | 325 | // TODO check if parent parameter should be changed to SPItem, of if the code should handle non-items. |
239 | 345 | static std::vector<Inkscape::XML::Node*> sp_selection_paste_impl(SPDocument *doc, SPObject *parent, std::vector<Inkscape::XML::Node*> &clip) | 326 | static std::vector<Inkscape::XML::Node *> sp_selection_paste_impl(SPDocument *doc, SPObject *parent, |
240 | 327 | std::vector<Inkscape::XML::Node *> &clip) | ||
241 | 346 | { | 328 | { |
242 | 347 | Inkscape::XML::Document *xml_doc = doc->getReprDoc(); | 329 | Inkscape::XML::Document *xml_doc = doc->getReprDoc(); |
243 | 348 | 330 | ||
244 | 349 | SPItem *parentItem = dynamic_cast<SPItem *>(parent); | 331 | SPItem *parentItem = dynamic_cast<SPItem *>(parent); |
245 | 350 | g_assert(parentItem != NULL); | 332 | g_assert(parentItem != NULL); |
246 | 351 | 333 | ||
248 | 352 | std::vector<Inkscape::XML::Node*> copied; | 334 | std::vector<Inkscape::XML::Node *> copied; |
249 | 353 | // add objects to document | 335 | // add objects to document |
251 | 354 | for (std::vector<Inkscape::XML::Node*>::const_iterator l = clip.begin(); l != clip.end(); l++) { | 336 | for (std::vector<Inkscape::XML::Node *>::const_iterator l = clip.begin(); l != clip.end(); l++) { |
252 | 355 | Inkscape::XML::Node *repr = *l; | 337 | Inkscape::XML::Node *repr = *l; |
253 | 356 | Inkscape::XML::Node *copy = repr->duplicate(xml_doc); | 338 | Inkscape::XML::Node *copy = repr->duplicate(xml_doc); |
254 | 357 | 339 | ||
255 | @@ -364,7 +346,7 @@ | |||
256 | 364 | sp_svg_transform_read(t_str, &item_t); | 346 | sp_svg_transform_read(t_str, &item_t); |
257 | 365 | item_t *= local.inverse(); | 347 | item_t *= local.inverse(); |
258 | 366 | // (we're dealing with unattached repr, so we write to its attr instead of using sp_item_set_transform) | 348 | // (we're dealing with unattached repr, so we write to its attr instead of using sp_item_set_transform) |
260 | 367 | gchar *affinestr=sp_svg_transform_write(item_t); | 349 | gchar *affinestr = sp_svg_transform_write(item_t); |
261 | 368 | copy->setAttribute("transform", affinestr); | 350 | copy->setAttribute("transform", affinestr); |
262 | 369 | g_free(affinestr); | 351 | g_free(affinestr); |
263 | 370 | } | 352 | } |
264 | @@ -376,12 +358,13 @@ | |||
265 | 376 | return copied; | 358 | return copied; |
266 | 377 | } | 359 | } |
267 | 378 | 360 | ||
269 | 379 | static void sp_selection_delete_impl(std::vector<SPItem*> const &items, bool propagate = true, bool propagate_descendants = true) | 361 | static void sp_selection_delete_impl(std::vector<SPItem *> const &items, bool propagate = true, |
270 | 362 | bool propagate_descendants = true) | ||
271 | 380 | { | 363 | { |
273 | 381 | for (std::vector<SPItem*>::const_iterator i = items.begin(); i != items.end(); i++) { | 364 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
274 | 382 | sp_object_ref(*i, NULL); | 365 | sp_object_ref(*i, NULL); |
275 | 383 | } | 366 | } |
277 | 384 | for (std::vector<SPItem*>::const_iterator i = items.begin(); i != items.end(); i++) { | 367 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
278 | 385 | SPItem *item = *i; | 368 | SPItem *item = *i; |
279 | 386 | item->deleteObject(propagate, propagate_descendants); | 369 | item->deleteObject(propagate, propagate_descendants); |
280 | 387 | sp_object_unref(item, NULL); | 370 | sp_object_unref(item, NULL); |
281 | @@ -397,8 +380,7 @@ | |||
282 | 397 | 380 | ||
283 | 398 | if (tools_isactive(desktop, TOOLS_TEXT)) | 381 | if (tools_isactive(desktop, TOOLS_TEXT)) |
284 | 399 | if (Inkscape::UI::Tools::sp_text_delete_selection(desktop->event_context)) { | 382 | if (Inkscape::UI::Tools::sp_text_delete_selection(desktop->event_context)) { |
287 | 400 | DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_TEXT, | 383 | DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_TEXT, _("Delete text")); |
286 | 401 | _("Delete text")); | ||
288 | 402 | return; | 384 | return; |
289 | 403 | } | 385 | } |
290 | 404 | 386 | ||
291 | @@ -409,7 +391,7 @@ | |||
292 | 409 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("<b>Nothing</b> was deleted.")); | 391 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("<b>Nothing</b> was deleted.")); |
293 | 410 | return; | 392 | return; |
294 | 411 | } | 393 | } |
296 | 412 | std::vector<SPItem*> selected(selection->itemList()); | 394 | std::vector<SPItem *> selected(selection->itemList()); |
297 | 413 | selection->clear(); | 395 | selection->clear(); |
298 | 414 | sp_selection_delete_impl(selected); | 396 | sp_selection_delete_impl(selected); |
299 | 415 | desktop->currentLayer()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); | 397 | desktop->currentLayer()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); |
300 | @@ -420,10 +402,9 @@ | |||
301 | 420 | * associated selection context. For example: deleting an object | 402 | * associated selection context. For example: deleting an object |
302 | 421 | * while moving it around the canvas. | 403 | * while moving it around the canvas. |
303 | 422 | */ | 404 | */ |
305 | 423 | tools_switch( desktop, tools_active( desktop ) ); | 405 | tools_switch(desktop, tools_active(desktop)); |
306 | 424 | 406 | ||
309 | 425 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_DELETE, | 407 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_DELETE, _("Delete")); |
308 | 426 | _("Delete")); | ||
310 | 427 | } | 408 | } |
311 | 428 | 409 | ||
312 | 429 | static void add_ids_recursive(std::vector<const gchar *> &ids, SPObject *obj) | 410 | static void add_ids_recursive(std::vector<const gchar *> &ids, SPObject *obj) |
313 | @@ -432,7 +413,7 @@ | |||
314 | 432 | ids.push_back(obj->getId()); | 413 | ids.push_back(obj->getId()); |
315 | 433 | 414 | ||
316 | 434 | if (dynamic_cast<SPGroup *>(obj)) { | 415 | if (dynamic_cast<SPGroup *>(obj)) { |
318 | 435 | for (SPObject *child = obj->firstChild() ; child; child = child->getNext() ) { | 416 | for (SPObject *child = obj->firstChild(); child; child = child->getNext()) { |
319 | 436 | add_ids_recursive(ids, child); | 417 | add_ids_recursive(ids, child); |
320 | 437 | } | 418 | } |
321 | 438 | } | 419 | } |
322 | @@ -446,7 +427,7 @@ | |||
323 | 446 | } | 427 | } |
324 | 447 | 428 | ||
325 | 448 | SPDocument *doc = desktop->doc(); | 429 | SPDocument *doc = desktop->doc(); |
327 | 449 | Inkscape::XML::Document* xml_doc = doc->getReprDoc(); | 430 | Inkscape::XML::Document *xml_doc = doc->getReprDoc(); |
328 | 450 | Inkscape::Selection *selection = desktop->getSelection(); | 431 | Inkscape::Selection *selection = desktop->getSelection(); |
329 | 451 | 432 | ||
330 | 452 | // check if something is selected | 433 | // check if something is selected |
331 | @@ -454,9 +435,9 @@ | |||
332 | 454 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to duplicate.")); | 435 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to duplicate.")); |
333 | 455 | return; | 436 | return; |
334 | 456 | } | 437 | } |
336 | 457 | std::vector<Inkscape::XML::Node*> reprs(selection->reprList()); | 438 | std::vector<Inkscape::XML::Node *> reprs(selection->reprList()); |
337 | 458 | 439 | ||
339 | 459 | if(duplicateLayer){ | 440 | if (duplicateLayer) { |
340 | 460 | reprs.clear(); | 441 | reprs.clear(); |
341 | 461 | reprs.push_back(desktop->currentLayer()->getRepr()); | 442 | reprs.push_back(desktop->currentLayer()->getRepr()); |
342 | 462 | } | 443 | } |
343 | @@ -465,9 +446,9 @@ | |||
344 | 465 | 446 | ||
345 | 466 | // sorting items from different parents sorts each parent's subset without possibly mixing | 447 | // sorting items from different parents sorts each parent's subset without possibly mixing |
346 | 467 | // them, just what we need | 448 | // them, just what we need |
348 | 468 | sort(reprs.begin(),reprs.end(),sp_repr_compare_position_bool); | 449 | sort(reprs.begin(), reprs.end(), sp_repr_compare_position_bool); |
349 | 469 | 450 | ||
351 | 470 | std::vector<Inkscape::XML::Node*> newsel; | 451 | std::vector<Inkscape::XML::Node *> newsel; |
352 | 471 | 452 | ||
353 | 472 | std::vector<const gchar *> old_ids; | 453 | std::vector<const gchar *> old_ids; |
354 | 473 | std::vector<const gchar *> new_ids; | 454 | std::vector<const gchar *> new_ids; |
355 | @@ -475,15 +456,15 @@ | |||
356 | 475 | bool relink_clones = prefs->getBool("/options/relinkclonesonduplicate/value"); | 456 | bool relink_clones = prefs->getBool("/options/relinkclonesonduplicate/value"); |
357 | 476 | const bool fork_livepatheffects = prefs->getBool("/options/forklpeonduplicate/value", true); | 457 | const bool fork_livepatheffects = prefs->getBool("/options/forklpeonduplicate/value", true); |
358 | 477 | 458 | ||
360 | 478 | for(std::vector<Inkscape::XML::Node*>::const_iterator i=reprs.begin();i!=reprs.end();i++){ | 459 | for (std::vector<Inkscape::XML::Node *>::const_iterator i = reprs.begin(); i != reprs.end(); i++) { |
361 | 479 | Inkscape::XML::Node *old_repr = *i; | 460 | Inkscape::XML::Node *old_repr = *i; |
362 | 480 | Inkscape::XML::Node *parent = old_repr->parent(); | 461 | Inkscape::XML::Node *parent = old_repr->parent(); |
363 | 481 | Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); | 462 | Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); |
364 | 482 | 463 | ||
366 | 483 | if(! duplicateLayer) | 464 | if (!duplicateLayer) |
367 | 484 | parent->appendChild(copy); | 465 | parent->appendChild(copy); |
368 | 485 | else | 466 | else |
370 | 486 | parent->addChild(copy, old_repr); | 467 | parent->addChild(copy, old_repr); |
371 | 487 | 468 | ||
372 | 488 | if (relink_clones) { | 469 | if (relink_clones) { |
373 | 489 | SPObject *old_obj = doc->getObjectByRepr(old_repr); | 470 | SPObject *old_obj = doc->getObjectByRepr(old_repr); |
374 | @@ -519,7 +500,8 @@ | |||
375 | 519 | for (unsigned int j = 0; j < old_ids.size(); j++) { | 500 | for (unsigned int j = 0; j < old_ids.size(); j++) { |
376 | 520 | if (!strcmp(orig->getId(), old_ids[j])) { | 501 | if (!strcmp(orig->getId(), old_ids[j])) { |
377 | 521 | // we have both orig and clone in selection, relink | 502 | // we have both orig and clone in selection, relink |
379 | 522 | // std::cout << id << " old, its ori: " << orig->getId() << "; will relink:" << new_ids[i] << " to " << new_ids[j] << "\n"; | 503 | // std::cout << id << " old, its ori: " << orig->getId() << "; will relink:" << new_ids[i] << " |
380 | 504 | // to " << new_ids[j] << "\n"; | ||
381 | 523 | SPObject *new_clone = doc->getObjectById(new_ids[i]); | 505 | SPObject *new_clone = doc->getObjectById(new_ids[i]); |
382 | 524 | new_clone->getRepr()->setAttribute("xlink:href", Glib::ustring("#") + new_ids[j]); | 506 | new_clone->getRepr()->setAttribute("xlink:href", Glib::ustring("#") + new_ids[j]); |
383 | 525 | new_clone->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); | 507 | new_clone->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); |
384 | @@ -530,8 +512,9 @@ | |||
385 | 530 | if (offset) { | 512 | if (offset) { |
386 | 531 | for (guint j = 0; j < old_ids.size(); j++) { | 513 | for (guint j = 0; j < old_ids.size(); j++) { |
387 | 532 | gchar *source_href = offset->sourceHref; | 514 | gchar *source_href = offset->sourceHref; |
390 | 533 | if (source_href && source_href[0]=='#' && !strcmp(source_href+1, old_ids[j])) { | 515 | if (source_href && source_href[0] == '#' && !strcmp(source_href + 1, old_ids[j])) { |
391 | 534 | doc->getObjectById(new_ids[i])->getRepr()->setAttribute("xlink:href", Glib::ustring("#") + new_ids[j]); | 516 | doc->getObjectById(new_ids[i])->getRepr()->setAttribute("xlink:href", |
392 | 517 | Glib::ustring("#") + new_ids[j]); | ||
393 | 535 | } | 518 | } |
394 | 536 | } | 519 | } |
395 | 537 | } | 520 | } |
396 | @@ -540,16 +523,15 @@ | |||
397 | 540 | } | 523 | } |
398 | 541 | 524 | ||
399 | 542 | 525 | ||
403 | 543 | if ( !suppressDone ) { | 526 | if (!suppressDone) { |
404 | 544 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_DUPLICATE, | 527 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_DUPLICATE, _("Duplicate")); |
402 | 545 | _("Duplicate")); | ||
405 | 546 | } | 528 | } |
407 | 547 | if(!duplicateLayer) | 529 | if (!duplicateLayer) |
408 | 548 | selection->setReprList(newsel); | 530 | selection->setReprList(newsel); |
413 | 549 | else{ | 531 | else { |
414 | 550 | SPObject* new_layer = doc->getObjectByRepr(newsel[0]); | 532 | SPObject *new_layer = doc->getObjectByRepr(newsel[0]); |
415 | 551 | gchar* name = g_strdup_printf(_("%s copy"), new_layer->label()); | 533 | gchar *name = g_strdup_printf(_("%s copy"), new_layer->label()); |
416 | 552 | desktop->layer_manager->renameLayer( new_layer, name, TRUE ); | 534 | desktop->layer_manager->renameLayer(new_layer, name, TRUE); |
417 | 553 | g_free(name); | 535 | g_free(name); |
418 | 554 | } | 536 | } |
419 | 555 | } | 537 | } |
420 | @@ -564,14 +546,13 @@ | |||
421 | 564 | 546 | ||
422 | 565 | SPGroup *group = dynamic_cast<SPGroup *>(selection->layers()->currentLayer()); | 547 | SPGroup *group = dynamic_cast<SPGroup *>(selection->layers()->currentLayer()); |
423 | 566 | g_return_if_fail(group != NULL); | 548 | g_return_if_fail(group != NULL); |
425 | 567 | std::vector<SPItem*> items = sp_item_group_item_list(group); | 549 | std::vector<SPItem *> items = sp_item_group_item_list(group); |
426 | 568 | 550 | ||
428 | 569 | for(unsigned int i = 0; i < items.size(); i++){ | 551 | for (unsigned int i = 0; i < items.size(); i++) { |
429 | 570 | items[i]->deleteObject(); | 552 | items[i]->deleteObject(); |
430 | 571 | } | 553 | } |
431 | 572 | 554 | ||
434 | 573 | DocumentUndo::done(doc, SP_VERB_EDIT_CLEAR_ALL, | 555 | DocumentUndo::done(doc, SP_VERB_EDIT_CLEAR_ALL, _("Delete all")); |
433 | 574 | _("Delete all")); | ||
435 | 575 | } | 556 | } |
436 | 576 | 557 | ||
437 | 577 | /* | 558 | /* |
438 | @@ -584,18 +565,15 @@ | |||
439 | 584 | * onlysensitive - TRUE includes only non-locked items | 565 | * onlysensitive - TRUE includes only non-locked items |
440 | 585 | * ingroups - TRUE to recursively get grouped items children | 566 | * ingroups - TRUE to recursively get grouped items children |
441 | 586 | */ | 567 | */ |
443 | 587 | std::vector<SPItem*> &get_all_items(std::vector<SPItem*> &list, SPObject *from, SPDesktop *desktop, bool onlyvisible, bool onlysensitive, bool ingroups, std::vector<SPItem*> const &exclude) | 568 | std::vector<SPItem *> &get_all_items(std::vector<SPItem *> &list, SPObject *from, SPDesktop *desktop, bool onlyvisible, |
444 | 569 | bool onlysensitive, bool ingroups, std::vector<SPItem *> const &exclude) | ||
445 | 588 | { | 570 | { |
447 | 589 | for ( SPObject *child = from->firstChild() ; child; child = child->getNext() ) { | 571 | for (SPObject *child = from->firstChild(); child; child = child->getNext()) { |
448 | 590 | SPItem *item = dynamic_cast<SPItem *>(child); | 572 | SPItem *item = dynamic_cast<SPItem *>(child); |
452 | 591 | if (item && | 573 | if (item && !desktop->isLayer(item) && (!onlysensitive || !item->isLocked()) && |
450 | 592 | !desktop->isLayer(item) && | ||
451 | 593 | (!onlysensitive || !item->isLocked()) && | ||
453 | 594 | (!onlyvisible || !desktop->itemIsHidden(item)) && | 574 | (!onlyvisible || !desktop->itemIsHidden(item)) && |
458 | 595 | (exclude.empty() || exclude.end() == std::find(exclude.begin(),exclude.end(),child)) | 575 | (exclude.empty() || exclude.end() == std::find(exclude.begin(), exclude.end(), child))) { |
459 | 596 | ) | 576 | list.insert(list.begin(), item); |
456 | 597 | { | ||
457 | 598 | list.insert(list.begin(),item); | ||
460 | 599 | } | 577 | } |
461 | 600 | 578 | ||
462 | 601 | if (ingroups || (item && desktop->isLayer(item))) { | 579 | if (ingroups || (item && desktop->isLayer(item))) { |
463 | @@ -616,13 +594,14 @@ | |||
464 | 616 | g_return_if_fail(dynamic_cast<SPGroup *>(dt->currentLayer())); | 594 | g_return_if_fail(dynamic_cast<SPGroup *>(dt->currentLayer())); |
465 | 617 | 595 | ||
466 | 618 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); | 596 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
468 | 619 | PrefsSelectionContext inlayer = (PrefsSelectionContext) prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER); | 597 | PrefsSelectionContext inlayer = |
469 | 598 | (PrefsSelectionContext)prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER); | ||
470 | 620 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); | 599 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); |
471 | 621 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); | 600 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); |
472 | 622 | 601 | ||
474 | 623 | std::vector<SPItem*> items ; | 602 | std::vector<SPItem *> items; |
475 | 624 | 603 | ||
477 | 625 | std::vector<SPItem*> exclude; | 604 | std::vector<SPItem *> exclude; |
478 | 626 | if (invert) { | 605 | if (invert) { |
479 | 627 | exclude = selection->itemList(); | 606 | exclude = selection->itemList(); |
480 | 628 | } | 607 | } |
481 | @@ -632,73 +611,62 @@ | |||
482 | 632 | 611 | ||
483 | 633 | switch (inlayer) { | 612 | switch (inlayer) { |
484 | 634 | case PREFS_SELECTION_LAYER: { | 613 | case PREFS_SELECTION_LAYER: { |
499 | 635 | if ( (onlysensitive && dynamic_cast<SPItem *>(dt->currentLayer())->isLocked()) || | 614 | if ((onlysensitive && dynamic_cast<SPItem *>(dt->currentLayer())->isLocked()) || |
500 | 636 | (onlyvisible && dt->itemIsHidden(dynamic_cast<SPItem *>(dt->currentLayer()))) ) | 615 | (onlyvisible && dt->itemIsHidden(dynamic_cast<SPItem *>(dt->currentLayer())))) |
501 | 637 | return; | 616 | return; |
502 | 638 | 617 | ||
503 | 639 | std::vector<SPItem*> all_items = sp_item_group_item_list(dynamic_cast<SPGroup *>(dt->currentLayer())); | 618 | std::vector<SPItem *> all_items = sp_item_group_item_list(dynamic_cast<SPGroup *>(dt->currentLayer())); |
504 | 640 | 619 | ||
505 | 641 | for (std::vector<SPItem*>::const_reverse_iterator i=all_items.rbegin();i!=all_items.rend();i++) { | 620 | for (std::vector<SPItem *>::const_reverse_iterator i = all_items.rbegin(); i != all_items.rend(); i++) { |
506 | 642 | SPItem *item = *i; | 621 | SPItem *item = *i; |
507 | 643 | 622 | ||
508 | 644 | if (item && (!onlysensitive || !item->isLocked())) { | 623 | if (item && (!onlysensitive || !item->isLocked())) { |
509 | 645 | if (!onlyvisible || !dt->itemIsHidden(item)) { | 624 | if (!onlyvisible || !dt->itemIsHidden(item)) { |
510 | 646 | if (!dt->isLayer(item)) { | 625 | if (!dt->isLayer(item)) { |
511 | 647 | if (!invert || exclude.end() == std::find(exclude.begin(),exclude.end(),item)) { | 626 | if (!invert || exclude.end() == std::find(exclude.begin(), exclude.end(), item)) { |
512 | 648 | items.push_back(item); // leave it in the list | 627 | items.push_back(item); // leave it in the list |
513 | 628 | } | ||
514 | 649 | } | 629 | } |
515 | 650 | } | 630 | } |
516 | 651 | } | 631 | } |
517 | 652 | } | 632 | } |
518 | 653 | } | ||
519 | 654 | 633 | ||
520 | 655 | break; | 634 | break; |
521 | 656 | } | 635 | } |
522 | 657 | case PREFS_SELECTION_LAYER_RECURSIVE: { | 636 | case PREFS_SELECTION_LAYER_RECURSIVE: { |
524 | 658 | std::vector<SPItem*> x; | 637 | std::vector<SPItem *> x; |
525 | 659 | items = get_all_items(x, dt->currentLayer(), dt, onlyvisible, onlysensitive, FALSE, exclude); | 638 | items = get_all_items(x, dt->currentLayer(), dt, onlyvisible, onlysensitive, FALSE, exclude); |
526 | 660 | break; | 639 | break; |
527 | 661 | } | 640 | } |
528 | 662 | default: { | 641 | default: { |
530 | 663 | std::vector<SPItem*> x; | 642 | std::vector<SPItem *> x; |
531 | 664 | items = get_all_items(x, dt->currentRoot(), dt, onlyvisible, onlysensitive, FALSE, exclude); | 643 | items = get_all_items(x, dt->currentRoot(), dt, onlyvisible, onlysensitive, FALSE, exclude); |
532 | 665 | break; | 644 | break; |
534 | 666 | } | 645 | } |
535 | 667 | } | 646 | } |
536 | 668 | 647 | ||
537 | 669 | selection->setList(items); | 648 | selection->setList(items); |
564 | 670 | 649 | } | |
565 | 671 | } | 650 | |
566 | 672 | 651 | void sp_edit_select_all(SPDesktop *desktop) { sp_edit_select_all_full(desktop, false, false); } | |
567 | 673 | void sp_edit_select_all(SPDesktop *desktop) | 652 | |
568 | 674 | { | 653 | void sp_edit_select_all_in_all_layers(SPDesktop *desktop) { sp_edit_select_all_full(desktop, true, false); } |
569 | 675 | sp_edit_select_all_full(desktop, false, false); | 654 | |
570 | 676 | } | 655 | void sp_edit_invert(SPDesktop *desktop) { sp_edit_select_all_full(desktop, false, true); } |
571 | 677 | 656 | ||
572 | 678 | void sp_edit_select_all_in_all_layers(SPDesktop *desktop) | 657 | void sp_edit_invert_in_all_layers(SPDesktop *desktop) { sp_edit_select_all_full(desktop, true, true); } |
573 | 679 | { | 658 | |
574 | 680 | sp_edit_select_all_full(desktop, true, false); | 659 | static void sp_selection_group_impl(std::vector<Inkscape::XML::Node *> p, Inkscape::XML::Node *group, |
575 | 681 | } | 660 | Inkscape::XML::Document *xml_doc, SPDocument *doc) |
576 | 682 | 661 | { | |
577 | 683 | void sp_edit_invert(SPDesktop *desktop) | 662 | |
578 | 684 | { | 663 | sort(p.begin(), p.end(), sp_repr_compare_position_bool); |
553 | 685 | sp_edit_select_all_full(desktop, false, true); | ||
554 | 686 | } | ||
555 | 687 | |||
556 | 688 | void sp_edit_invert_in_all_layers(SPDesktop *desktop) | ||
557 | 689 | { | ||
558 | 690 | sp_edit_select_all_full(desktop, true, true); | ||
559 | 691 | } | ||
560 | 692 | |||
561 | 693 | static void sp_selection_group_impl(std::vector<Inkscape::XML::Node*> p, Inkscape::XML::Node *group, Inkscape::XML::Document *xml_doc, SPDocument *doc) { | ||
562 | 694 | |||
563 | 695 | sort(p.begin(),p.end(),sp_repr_compare_position_bool); | ||
579 | 696 | 664 | ||
580 | 697 | // Remember the position and parent of the topmost object. | 665 | // Remember the position and parent of the topmost object. |
581 | 698 | gint topmost = p.back()->position(); | 666 | gint topmost = p.back()->position(); |
582 | 699 | Inkscape::XML::Node *topmost_parent = p.back()->parent(); | 667 | Inkscape::XML::Node *topmost_parent = p.back()->parent(); |
583 | 700 | 668 | ||
585 | 701 | for(std::vector<Inkscape::XML::Node*>::const_iterator i = p.begin(); i != p.end(); i++){ | 669 | for (std::vector<Inkscape::XML::Node *>::const_iterator i = p.begin(); i != p.end(); i++) { |
586 | 702 | Inkscape::XML::Node *current = *i; | 670 | Inkscape::XML::Node *current = *i; |
587 | 703 | 671 | ||
588 | 704 | if (current->parent() == topmost_parent) { | 672 | if (current->parent() == topmost_parent) { |
589 | @@ -706,12 +674,14 @@ | |||
590 | 706 | sp_repr_unparent(current); | 674 | sp_repr_unparent(current); |
591 | 707 | group->appendChild(spnew); | 675 | group->appendChild(spnew); |
592 | 708 | Inkscape::GC::release(spnew); | 676 | Inkscape::GC::release(spnew); |
596 | 709 | topmost --; // only reduce count for those items deleted from topmost_parent | 677 | topmost--; // only reduce count for those items deleted from topmost_parent |
597 | 710 | } else { // move it to topmost_parent first | 678 | } else { // move it to topmost_parent first |
598 | 711 | std::vector<Inkscape::XML::Node*> temp_clip; | 679 | std::vector<Inkscape::XML::Node *> temp_clip; |
599 | 712 | 680 | ||
602 | 713 | // At this point, current may already have no item, due to its being a clone whose original is already moved away | 681 | // At this point, current may already have no item, due to its being a clone whose original is already moved |
603 | 714 | // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent transform | 682 | // away |
604 | 683 | // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent | ||
605 | 684 | // transform | ||
606 | 715 | gchar const *t_str = current->attribute("transform"); | 685 | gchar const *t_str = current->attribute("transform"); |
607 | 716 | Geom::Affine item_t(Geom::identity()); | 686 | Geom::Affine item_t(Geom::identity()); |
608 | 717 | if (t_str) | 687 | if (t_str) |
609 | @@ -728,8 +698,10 @@ | |||
610 | 728 | sp_repr_unparent(current); | 698 | sp_repr_unparent(current); |
611 | 729 | 699 | ||
612 | 730 | // paste into topmost_parent (temporarily) | 700 | // paste into topmost_parent (temporarily) |
615 | 731 | std::vector<Inkscape::XML::Node*> copied = sp_selection_paste_impl(doc, doc->getObjectByRepr(topmost_parent), temp_clip); | 701 | std::vector<Inkscape::XML::Node *> copied = |
616 | 732 | if (!temp_clip.empty())temp_clip.clear() ; | 702 | sp_selection_paste_impl(doc, doc->getObjectByRepr(topmost_parent), temp_clip); |
617 | 703 | if (!temp_clip.empty()) | ||
618 | 704 | temp_clip.clear(); | ||
619 | 733 | if (!copied.empty()) { // if success, | 705 | if (!copied.empty()) { // if success, |
620 | 734 | // take pasted object (now in topmost_parent) | 706 | // take pasted object (now in topmost_parent) |
621 | 735 | Inkscape::XML::Node *in_topmost = copied.back(); | 707 | Inkscape::XML::Node *in_topmost = copied.back(); |
622 | @@ -763,7 +735,7 @@ | |||
623 | 763 | return; | 735 | return; |
624 | 764 | } | 736 | } |
625 | 765 | 737 | ||
627 | 766 | std::vector<Inkscape::XML::Node*> p (selection->reprList()); | 738 | std::vector<Inkscape::XML::Node *> p(selection->reprList()); |
628 | 767 | 739 | ||
629 | 768 | selection->clear(); | 740 | selection->clear(); |
630 | 769 | 741 | ||
631 | @@ -771,14 +743,14 @@ | |||
632 | 771 | 743 | ||
633 | 772 | sp_selection_group_impl(p, group, xml_doc, doc); | 744 | sp_selection_group_impl(p, group, xml_doc, doc); |
634 | 773 | 745 | ||
637 | 774 | DocumentUndo::done(doc, SP_VERB_SELECTION_GROUP, | 746 | DocumentUndo::done(doc, SP_VERB_SELECTION_GROUP, C_("Verb", "Group")); |
636 | 775 | C_("Verb", "Group")); | ||
638 | 776 | 747 | ||
639 | 777 | selection->set(group); | 748 | selection->set(group); |
640 | 778 | Inkscape::GC::release(group); | 749 | Inkscape::GC::release(group); |
641 | 779 | } | 750 | } |
642 | 780 | 751 | ||
644 | 781 | static gint clone_depth_descending(gconstpointer a, gconstpointer b) { | 752 | static gint clone_depth_descending(gconstpointer a, gconstpointer b) |
645 | 753 | { | ||
646 | 782 | SPUse *use_a = static_cast<SPUse *>(const_cast<gpointer>(a)); | 754 | SPUse *use_a = static_cast<SPUse *>(const_cast<gpointer>(a)); |
647 | 783 | SPUse *use_b = static_cast<SPUse *>(const_cast<gpointer>(b)); | 755 | SPUse *use_b = static_cast<SPUse *>(const_cast<gpointer>(b)); |
648 | 784 | int depth_a = use_a->cloneDepth(); | 756 | int depth_a = use_a->cloneDepth(); |
649 | @@ -799,10 +771,10 @@ | |||
650 | 799 | } | 771 | } |
651 | 800 | 772 | ||
652 | 801 | // first check whether there is anything to ungroup | 773 | // first check whether there is anything to ungroup |
655 | 802 | std::vector<SPItem*> old_select = selection->itemList(); | 774 | std::vector<SPItem *> old_select = selection->itemList(); |
656 | 803 | std::vector<SPItem*> new_select; | 775 | std::vector<SPItem *> new_select; |
657 | 804 | GSList *groups = NULL; | 776 | GSList *groups = NULL; |
659 | 805 | for (std::vector<SPItem*>::const_iterator item = old_select.begin(); item!=old_select.end(); item++) { | 777 | for (std::vector<SPItem *>::const_iterator item = old_select.begin(); item != old_select.end(); item++) { |
660 | 806 | SPItem *obj = *item; | 778 | SPItem *obj = *item; |
661 | 807 | if (dynamic_cast<SPGroup *>(obj)) { | 779 | if (dynamic_cast<SPGroup *>(obj)) { |
662 | 808 | groups = g_slist_prepend(groups, obj); | 780 | groups = g_slist_prepend(groups, obj); |
663 | @@ -815,13 +787,13 @@ | |||
664 | 815 | return; | 787 | return; |
665 | 816 | } | 788 | } |
666 | 817 | 789 | ||
668 | 818 | std::vector<SPItem*> items(old_select); | 790 | std::vector<SPItem *> items(old_select); |
669 | 819 | selection->clear(); | 791 | selection->clear(); |
670 | 820 | 792 | ||
671 | 821 | // If any of the clones refer to the groups, unlink them and replace them with successors | 793 | // If any of the clones refer to the groups, unlink them and replace them with successors |
672 | 822 | // in the items list. | 794 | // in the items list. |
673 | 823 | GSList *clones_to_unlink = NULL; | 795 | GSList *clones_to_unlink = NULL; |
675 | 824 | for (std::vector<SPItem*>::const_iterator item = items.begin(); item != items.end(); item++) { | 796 | for (std::vector<SPItem *>::const_iterator item = items.begin(); item != items.end(); item++) { |
676 | 825 | SPUse *use = dynamic_cast<SPUse *>(*item); | 797 | SPUse *use = dynamic_cast<SPUse *>(*item); |
677 | 826 | 798 | ||
678 | 827 | SPItem *original = use; | 799 | SPItem *original = use; |
679 | @@ -841,21 +813,21 @@ | |||
680 | 841 | 813 | ||
681 | 842 | for (GSList *item = clones_to_unlink; item; item = item->next) { | 814 | for (GSList *item = clones_to_unlink; item; item = item->next) { |
682 | 843 | SPUse *use = static_cast<SPUse *>(item->data); | 815 | SPUse *use = static_cast<SPUse *>(item->data); |
684 | 844 | std::vector<SPItem*>::iterator items_node = std::find(items.begin(),items.end(), item->data); | 816 | std::vector<SPItem *>::iterator items_node = std::find(items.begin(), items.end(), item->data); |
685 | 845 | *items_node = use->unlink(); | 817 | *items_node = use->unlink(); |
686 | 846 | } | 818 | } |
687 | 847 | g_slist_free(clones_to_unlink); | 819 | g_slist_free(clones_to_unlink); |
688 | 848 | 820 | ||
689 | 849 | // do the actual work | 821 | // do the actual work |
691 | 850 | for (std::vector<SPItem*>::iterator item = items.begin(); item != items.end(); item++) { | 822 | for (std::vector<SPItem *>::iterator item = items.begin(); item != items.end(); item++) { |
692 | 851 | SPItem *obj = *item; | 823 | SPItem *obj = *item; |
693 | 852 | 824 | ||
694 | 853 | // ungroup only the groups marked earlier | 825 | // ungroup only the groups marked earlier |
695 | 854 | if (g_slist_find(groups, *item) != NULL) { | 826 | if (g_slist_find(groups, *item) != NULL) { |
697 | 855 | std::vector<SPItem*> children; | 827 | std::vector<SPItem *> children; |
698 | 856 | sp_item_group_ungroup(dynamic_cast<SPGroup *>(obj), children, false); | 828 | sp_item_group_ungroup(dynamic_cast<SPGroup *>(obj), children, false); |
699 | 857 | // add the items resulting from ungrouping to the selection | 829 | // add the items resulting from ungrouping to the selection |
701 | 858 | new_select.insert(new_select.end(),children.begin(),children.end()); | 830 | new_select.insert(new_select.end(), children.begin(), children.end()); |
702 | 859 | *item = NULL; // zero out the original pointer, which is no longer valid | 831 | *item = NULL; // zero out the original pointer, which is no longer valid |
703 | 860 | } else { | 832 | } else { |
704 | 861 | // if not a group, keep in the selection | 833 | // if not a group, keep in the selection |
705 | @@ -865,24 +837,22 @@ | |||
706 | 865 | 837 | ||
707 | 866 | selection->addList(new_select); | 838 | selection->addList(new_select); |
708 | 867 | 839 | ||
711 | 868 | DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_UNGROUP, | 840 | DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_UNGROUP, _("Ungroup")); |
710 | 869 | _("Ungroup")); | ||
712 | 870 | } | 841 | } |
713 | 871 | 842 | ||
714 | 872 | /** Replace all groups in the list with their member objects, recursively; returns a new list, frees old */ | 843 | /** Replace all groups in the list with their member objects, recursively; returns a new list, frees old */ |
717 | 873 | std::vector<SPItem*> | 844 | std::vector<SPItem *> sp_degroup_list(std::vector<SPItem *> &items) |
716 | 874 | sp_degroup_list(std::vector<SPItem*> &items) | ||
718 | 875 | { | 845 | { |
720 | 876 | std::vector<SPItem*> out; | 846 | std::vector<SPItem *> out; |
721 | 877 | bool has_groups = false; | 847 | bool has_groups = false; |
723 | 878 | for (std::vector<SPItem*>::const_iterator item=items.begin();item!=items.end();item++) { | 848 | for (std::vector<SPItem *>::const_iterator item = items.begin(); item != items.end(); item++) { |
724 | 879 | SPGroup *group = dynamic_cast<SPGroup *>(*item); | 849 | SPGroup *group = dynamic_cast<SPGroup *>(*item); |
725 | 880 | if (!group) { | 850 | if (!group) { |
726 | 881 | out.push_back(*item); | 851 | out.push_back(*item); |
727 | 882 | } else { | 852 | } else { |
728 | 883 | has_groups = true; | 853 | has_groups = true; |
731 | 884 | std::vector<SPItem*> members = sp_item_group_item_list(group); | 854 | std::vector<SPItem *> members = sp_item_group_item_list(group); |
732 | 885 | for (std::vector<SPItem*>::const_iterator member=members.begin();member!=members.end();member++) { | 855 | for (std::vector<SPItem *>::const_iterator member = members.begin(); member != members.end(); member++) { |
733 | 886 | out.push_back(*member); | 856 | out.push_back(*member); |
734 | 887 | } | 857 | } |
735 | 888 | members.clear(); | 858 | members.clear(); |
736 | @@ -898,8 +868,7 @@ | |||
737 | 898 | 868 | ||
738 | 899 | 869 | ||
739 | 900 | /** If items in the list have a common parent, return it, otherwise return NULL */ | 870 | /** If items in the list have a common parent, return it, otherwise return NULL */ |
742 | 901 | static SPGroup * | 871 | static SPGroup *sp_item_list_common_parent_group(std::vector<SPItem *> const items) |
741 | 902 | sp_item_list_common_parent_group(std::vector<SPItem*> const items) | ||
743 | 903 | { | 872 | { |
744 | 904 | if (items.empty()) { | 873 | if (items.empty()) { |
745 | 905 | return NULL; | 874 | return NULL; |
746 | @@ -909,8 +878,9 @@ | |||
747 | 909 | if (!dynamic_cast<SPGroup *>(parent)) { | 878 | if (!dynamic_cast<SPGroup *>(parent)) { |
748 | 910 | return NULL; | 879 | return NULL; |
749 | 911 | } | 880 | } |
752 | 912 | for (std::vector<SPItem*>::const_iterator item=items.begin();item!=items.end();item++) { | 881 | for (std::vector<SPItem *>::const_iterator item = items.begin(); item != items.end(); item++) { |
753 | 913 | if((*item)==items[0])continue; | 882 | if ((*item) == items[0]) |
754 | 883 | continue; | ||
755 | 914 | if ((*item)->parent != parent) { | 884 | if ((*item)->parent != parent) { |
756 | 915 | return NULL; | 885 | return NULL; |
757 | 916 | } | 886 | } |
758 | @@ -920,13 +890,12 @@ | |||
759 | 920 | } | 890 | } |
760 | 921 | 891 | ||
761 | 922 | /** Finds out the minimum common bbox of the selected items. */ | 892 | /** Finds out the minimum common bbox of the selected items. */ |
764 | 923 | static Geom::OptRect | 893 | static Geom::OptRect enclose_items(std::vector<SPItem *> const &items) |
763 | 924 | enclose_items(std::vector<SPItem*> const &items) | ||
765 | 925 | { | 894 | { |
766 | 926 | g_assert(!items.empty()); | 895 | g_assert(!items.empty()); |
767 | 927 | 896 | ||
768 | 928 | Geom::OptRect r; | 897 | Geom::OptRect r; |
770 | 929 | for (std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();i++) { | 898 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
771 | 930 | r.unionWith((*i)->desktopVisualBounds()); | 899 | r.unionWith((*i)->desktopVisualBounds()); |
772 | 931 | } | 900 | } |
773 | 932 | return r; | 901 | return r; |
774 | @@ -936,7 +905,7 @@ | |||
775 | 936 | static SPObject *prev_sibling(SPObject *child) | 905 | static SPObject *prev_sibling(SPObject *child) |
776 | 937 | { | 906 | { |
777 | 938 | SPObject *prev = 0; | 907 | SPObject *prev = 0; |
779 | 939 | if ( child && dynamic_cast<SPGroup *>(child->parent) ) { | 908 | if (child && dynamic_cast<SPGroup *>(child->parent)) { |
780 | 940 | prev = child->getPrev(); | 909 | prev = child->getPrev(); |
781 | 941 | } | 910 | } |
782 | 942 | return prev; | 911 | return prev; |
783 | @@ -944,14 +913,12 @@ | |||
784 | 944 | 913 | ||
785 | 945 | bool sp_item_repr_compare_position_bool(SPObject const *first, SPObject const *second) | 914 | bool sp_item_repr_compare_position_bool(SPObject const *first, SPObject const *second) |
786 | 946 | { | 915 | { |
789 | 947 | return sp_repr_compare_position(((SPItem*)first)->getRepr(), | 916 | return sp_repr_compare_position(((SPItem *)first)->getRepr(), ((SPItem *)second)->getRepr()) < 0; |
788 | 948 | ((SPItem*)second)->getRepr())<0; | ||
790 | 949 | } | 917 | } |
791 | 950 | 918 | ||
794 | 951 | void | 919 | void sp_selection_raise(Inkscape::Selection *selection, SPDesktop *desktop) |
793 | 952 | sp_selection_raise(Inkscape::Selection *selection, SPDesktop *desktop) | ||
795 | 953 | { | 920 | { |
797 | 954 | std::vector<SPItem*> items= selection->itemList(); | 921 | std::vector<SPItem *> items = selection->itemList(); |
798 | 955 | if (items.empty()) { | 922 | if (items.empty()) { |
799 | 956 | selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise.")); | 923 | selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise.")); |
800 | 957 | return; | 924 | return; |
801 | @@ -959,22 +926,23 @@ | |||
802 | 959 | 926 | ||
803 | 960 | SPGroup const *group = sp_item_list_common_parent_group(items); | 927 | SPGroup const *group = sp_item_list_common_parent_group(items); |
804 | 961 | if (!group) { | 928 | if (!group) { |
806 | 962 | selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>.")); | 929 | selection_display_message(desktop, Inkscape::ERROR_MESSAGE, |
807 | 930 | _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>.")); | ||
808 | 963 | return; | 931 | return; |
809 | 964 | } | 932 | } |
810 | 965 | 933 | ||
811 | 966 | Inkscape::XML::Node *grepr = const_cast<Inkscape::XML::Node *>(group->getRepr()); | 934 | Inkscape::XML::Node *grepr = const_cast<Inkscape::XML::Node *>(group->getRepr()); |
812 | 967 | 935 | ||
813 | 968 | /* Construct reverse-ordered list of selected children. */ | 936 | /* Construct reverse-ordered list of selected children. */ |
816 | 969 | std::vector<SPItem*> rev(items); | 937 | std::vector<SPItem *> rev(items); |
817 | 970 | sort(rev.begin(),rev.end(),sp_item_repr_compare_position_bool); | 938 | sort(rev.begin(), rev.end(), sp_item_repr_compare_position_bool); |
818 | 971 | 939 | ||
819 | 972 | // Determine the common bbox of the selected items. | 940 | // Determine the common bbox of the selected items. |
820 | 973 | Geom::OptRect selected = enclose_items(items); | 941 | Geom::OptRect selected = enclose_items(items); |
821 | 974 | 942 | ||
822 | 975 | // Iterate over all objects in the selection (starting from top). | 943 | // Iterate over all objects in the selection (starting from top). |
823 | 976 | if (selected) { | 944 | if (selected) { |
825 | 977 | for (std::vector<SPItem*>::const_iterator item=rev.begin();item!=rev.end();item++) { | 945 | for (std::vector<SPItem *>::const_iterator item = rev.begin(); item != rev.end(); item++) { |
826 | 978 | SPObject *child = *item; | 946 | SPObject *child = *item; |
827 | 979 | // for each selected object, find the next sibling | 947 | // for each selected object, find the next sibling |
828 | 980 | for (SPObject *newref = child->next; newref; newref = newref->next) { | 948 | for (SPObject *newref = child->next; newref; newref = newref->next) { |
829 | @@ -982,9 +950,9 @@ | |||
830 | 982 | SPItem *newItem = dynamic_cast<SPItem *>(newref); | 950 | SPItem *newItem = dynamic_cast<SPItem *>(newref); |
831 | 983 | if (newItem) { | 951 | if (newItem) { |
832 | 984 | Geom::OptRect newref_bbox = newItem->desktopVisualBounds(); | 952 | Geom::OptRect newref_bbox = newItem->desktopVisualBounds(); |
834 | 985 | if ( newref_bbox && selected->intersects(*newref_bbox) ) { | 953 | if (newref_bbox && selected->intersects(*newref_bbox)) { |
835 | 986 | // AND if it's not one of our selected objects, | 954 | // AND if it's not one of our selected objects, |
837 | 987 | if ( std::find(items.begin(),items.end(),newref)==items.end()) { | 955 | if (std::find(items.begin(), items.end(), newref) == items.end()) { |
838 | 988 | // move the selected object after that sibling | 956 | // move the selected object after that sibling |
839 | 989 | grepr->changeOrder(child->getRepr(), newref->getRepr()); | 957 | grepr->changeOrder(child->getRepr(), newref->getRepr()); |
840 | 990 | } | 958 | } |
841 | @@ -995,7 +963,7 @@ | |||
842 | 995 | } | 963 | } |
843 | 996 | } | 964 | } |
844 | 997 | DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_RAISE, | 965 | DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_RAISE, |
846 | 998 | //TRANSLATORS: "Raise" means "to raise an object" in the undo history | 966 | // TRANSLATORS: "Raise" means "to raise an object" in the undo history |
847 | 999 | C_("Undo action", "Raise")); | 967 | C_("Undo action", "Raise")); |
848 | 1000 | } | 968 | } |
849 | 1001 | 969 | ||
850 | @@ -1008,29 +976,29 @@ | |||
851 | 1008 | return; | 976 | return; |
852 | 1009 | } | 977 | } |
853 | 1010 | 978 | ||
855 | 1011 | std::vector<SPItem*> items = selection->itemList(); | 979 | std::vector<SPItem *> items = selection->itemList(); |
856 | 1012 | 980 | ||
857 | 1013 | SPGroup const *group = sp_item_list_common_parent_group(items); | 981 | SPGroup const *group = sp_item_list_common_parent_group(items); |
858 | 1014 | if (!group) { | 982 | if (!group) { |
860 | 1015 | selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>.")); | 983 | selection_display_message(desktop, Inkscape::ERROR_MESSAGE, |
861 | 984 | _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>.")); | ||
862 | 1016 | return; | 985 | return; |
863 | 1017 | } | 986 | } |
864 | 1018 | 987 | ||
867 | 1019 | std::vector<Inkscape::XML::Node*> rl(selection->reprList()); | 988 | std::vector<Inkscape::XML::Node *> rl(selection->reprList()); |
868 | 1020 | sort(rl.begin(),rl.end(),sp_repr_compare_position_bool); | 989 | sort(rl.begin(), rl.end(), sp_repr_compare_position_bool); |
869 | 1021 | 990 | ||
872 | 1022 | for (std::vector<Inkscape::XML::Node*>::const_iterator l=rl.begin(); l!=rl.end();l++) { | 991 | for (std::vector<Inkscape::XML::Node *>::const_iterator l = rl.begin(); l != rl.end(); l++) { |
873 | 1023 | Inkscape::XML::Node *repr =(*l); | 992 | Inkscape::XML::Node *repr = (*l); |
874 | 1024 | repr->setPosition(-1); | 993 | repr->setPosition(-1); |
875 | 1025 | } | 994 | } |
876 | 1026 | 995 | ||
879 | 1027 | DocumentUndo::done(document, SP_VERB_SELECTION_TO_FRONT, | 996 | DocumentUndo::done(document, SP_VERB_SELECTION_TO_FRONT, _("Raise to top")); |
878 | 1028 | _("Raise to top")); | ||
880 | 1029 | } | 997 | } |
881 | 1030 | 998 | ||
882 | 1031 | void sp_selection_lower(Inkscape::Selection *selection, SPDesktop *desktop) | 999 | void sp_selection_lower(Inkscape::Selection *selection, SPDesktop *desktop) |
883 | 1032 | { | 1000 | { |
885 | 1033 | std::vector<SPItem*> items = selection->itemList(); | 1001 | std::vector<SPItem *> items = selection->itemList(); |
886 | 1034 | if (items.empty()) { | 1002 | if (items.empty()) { |
887 | 1035 | selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower.")); | 1003 | selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower.")); |
888 | 1036 | return; | 1004 | return; |
889 | @@ -1038,7 +1006,8 @@ | |||
890 | 1038 | 1006 | ||
891 | 1039 | SPGroup const *group = sp_item_list_common_parent_group(items); | 1007 | SPGroup const *group = sp_item_list_common_parent_group(items); |
892 | 1040 | if (!group) { | 1008 | if (!group) { |
894 | 1041 | selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>.")); | 1009 | selection_display_message(desktop, Inkscape::ERROR_MESSAGE, |
895 | 1010 | _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>.")); | ||
896 | 1042 | return; | 1011 | return; |
897 | 1043 | } | 1012 | } |
898 | 1044 | 1013 | ||
899 | @@ -1048,12 +1017,12 @@ | |||
900 | 1048 | Geom::OptRect selected = enclose_items(items); | 1017 | Geom::OptRect selected = enclose_items(items); |
901 | 1049 | 1018 | ||
902 | 1050 | /* Construct direct-ordered list of selected children. */ | 1019 | /* Construct direct-ordered list of selected children. */ |
905 | 1051 | std::vector<SPItem*> rev(items); | 1020 | std::vector<SPItem *> rev(items); |
906 | 1052 | sort(rev.begin(),rev.end(),sp_item_repr_compare_position_bool); | 1021 | sort(rev.begin(), rev.end(), sp_item_repr_compare_position_bool); |
907 | 1053 | 1022 | ||
908 | 1054 | // Iterate over all objects in the selection (starting from top). | 1023 | // Iterate over all objects in the selection (starting from top). |
909 | 1055 | if (selected) { | 1024 | if (selected) { |
911 | 1056 | for (std::vector<SPItem*>::const_reverse_iterator item=rev.rbegin();item!=rev.rend();item++) { | 1025 | for (std::vector<SPItem *>::const_reverse_iterator item = rev.rbegin(); item != rev.rend(); item++) { |
912 | 1057 | SPObject *child = *item; | 1026 | SPObject *child = *item; |
913 | 1058 | // for each selected object, find the prev sibling | 1027 | // for each selected object, find the prev sibling |
914 | 1059 | for (SPObject *newref = prev_sibling(child); newref; newref = prev_sibling(newref)) { | 1028 | for (SPObject *newref = prev_sibling(child); newref; newref = prev_sibling(newref)) { |
915 | @@ -1061,9 +1030,9 @@ | |||
916 | 1061 | SPItem *newItem = dynamic_cast<SPItem *>(newref); | 1030 | SPItem *newItem = dynamic_cast<SPItem *>(newref); |
917 | 1062 | if (newItem) { | 1031 | if (newItem) { |
918 | 1063 | Geom::OptRect ref_bbox = newItem->desktopVisualBounds(); | 1032 | Geom::OptRect ref_bbox = newItem->desktopVisualBounds(); |
920 | 1064 | if ( ref_bbox && selected->intersects(*ref_bbox) ) { | 1033 | if (ref_bbox && selected->intersects(*ref_bbox)) { |
921 | 1065 | // AND if it's not one of our selected objects, | 1034 | // AND if it's not one of our selected objects, |
923 | 1066 | if (items.end()==std::find(items.begin(),items.end(),newref)) { | 1035 | if (items.end() == std::find(items.begin(), items.end(), newref)) { |
924 | 1067 | // move the selected object before that sibling | 1036 | // move the selected object before that sibling |
925 | 1068 | SPObject *put_after = prev_sibling(newref); | 1037 | SPObject *put_after = prev_sibling(newref); |
926 | 1069 | if (put_after) | 1038 | if (put_after) |
927 | @@ -1079,7 +1048,7 @@ | |||
928 | 1079 | } | 1048 | } |
929 | 1080 | 1049 | ||
930 | 1081 | DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_LOWER, | 1050 | DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_LOWER, |
932 | 1082 | //TRANSLATORS: "Lower" means "to lower an object" in the undo history | 1051 | // TRANSLATORS: "Lower" means "to lower an object" in the undo history |
933 | 1083 | C_("Undo action", "Lower")); | 1052 | C_("Undo action", "Lower")); |
934 | 1084 | } | 1053 | } |
935 | 1085 | 1054 | ||
936 | @@ -1092,18 +1061,19 @@ | |||
937 | 1092 | return; | 1061 | return; |
938 | 1093 | } | 1062 | } |
939 | 1094 | 1063 | ||
941 | 1095 | std::vector<SPItem*> items =selection->itemList(); | 1064 | std::vector<SPItem *> items = selection->itemList(); |
942 | 1096 | 1065 | ||
943 | 1097 | SPGroup const *group = sp_item_list_common_parent_group(items); | 1066 | SPGroup const *group = sp_item_list_common_parent_group(items); |
944 | 1098 | if (!group) { | 1067 | if (!group) { |
946 | 1099 | selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>.")); | 1068 | selection_display_message(desktop, Inkscape::ERROR_MESSAGE, |
947 | 1069 | _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>.")); | ||
948 | 1100 | return; | 1070 | return; |
949 | 1101 | } | 1071 | } |
950 | 1102 | 1072 | ||
953 | 1103 | std::vector<Inkscape::XML::Node*> rl(selection->reprList()); | 1073 | std::vector<Inkscape::XML::Node *> rl(selection->reprList()); |
954 | 1104 | sort(rl.begin(),rl.end(),sp_repr_compare_position_bool); | 1074 | sort(rl.begin(), rl.end(), sp_repr_compare_position_bool); |
955 | 1105 | 1075 | ||
957 | 1106 | for (std::vector<Inkscape::XML::Node*>::const_reverse_iterator l=rl.rbegin();l!=rl.rend();l++) { | 1076 | for (std::vector<Inkscape::XML::Node *>::const_reverse_iterator l = rl.rbegin(); l != rl.rend(); l++) { |
958 | 1107 | gint minpos; | 1077 | gint minpos; |
959 | 1108 | SPObject *pp, *pc; | 1078 | SPObject *pp, *pc; |
960 | 1109 | Inkscape::XML::Node *repr = (*l); | 1079 | Inkscape::XML::Node *repr = (*l); |
961 | @@ -1118,26 +1088,25 @@ | |||
962 | 1118 | repr->setPosition(minpos); | 1088 | repr->setPosition(minpos); |
963 | 1119 | } | 1089 | } |
964 | 1120 | 1090 | ||
967 | 1121 | DocumentUndo::done(document, SP_VERB_SELECTION_TO_BACK, | 1091 | DocumentUndo::done(document, SP_VERB_SELECTION_TO_BACK, _("Lower to bottom")); |
966 | 1122 | _("Lower to bottom")); | ||
968 | 1123 | } | 1092 | } |
969 | 1124 | 1093 | ||
972 | 1125 | void | 1094 | void sp_undo(SPDesktop *desktop, SPDocument *) |
971 | 1126 | sp_undo(SPDesktop *desktop, SPDocument *) | ||
973 | 1127 | { | 1095 | { |
974 | 1128 | // No re/undo while dragging, too dangerous. | 1096 | // No re/undo while dragging, too dangerous. |
976 | 1129 | if(desktop->getCanvas()->is_dragging) return; | 1097 | if (desktop->getCanvas()->is_dragging) |
977 | 1098 | return; | ||
978 | 1130 | 1099 | ||
979 | 1131 | if (!DocumentUndo::undo(desktop->getDocument())) { | 1100 | if (!DocumentUndo::undo(desktop->getDocument())) { |
980 | 1132 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to undo.")); | 1101 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to undo.")); |
981 | 1133 | } | 1102 | } |
982 | 1134 | } | 1103 | } |
983 | 1135 | 1104 | ||
986 | 1136 | void | 1105 | void sp_redo(SPDesktop *desktop, SPDocument *) |
985 | 1137 | sp_redo(SPDesktop *desktop, SPDocument *) | ||
987 | 1138 | { | 1106 | { |
988 | 1139 | // No re/undo while dragging, too dangerous. | 1107 | // No re/undo while dragging, too dangerous. |
990 | 1140 | if(desktop->getCanvas()->is_dragging) return; | 1108 | if (desktop->getCanvas()->is_dragging) |
991 | 1109 | return; | ||
992 | 1141 | 1110 | ||
993 | 1142 | if (!DocumentUndo::redo(desktop->getDocument())) { | 1111 | if (!DocumentUndo::redo(desktop->getDocument())) { |
994 | 1143 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to redo.")); | 1112 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Nothing to redo.")); |
995 | @@ -1153,8 +1122,7 @@ | |||
996 | 1153 | /** | 1122 | /** |
997 | 1154 | * \pre item != NULL | 1123 | * \pre item != NULL |
998 | 1155 | */ | 1124 | */ |
1001 | 1156 | SPCSSAttr * | 1125 | SPCSSAttr *take_style_from_item(SPObject *object) |
1000 | 1157 | take_style_from_item(SPObject *object) | ||
1002 | 1158 | { | 1126 | { |
1003 | 1159 | // CPPIFY: | 1127 | // CPPIFY: |
1004 | 1160 | // This function should only take SPItems, but currently SPString is not an Item. | 1128 | // This function should only take SPItems, but currently SPString is not an Item. |
1005 | @@ -1168,8 +1136,9 @@ | |||
1006 | 1168 | (dynamic_cast<SPText *>(object) && object->children && object->children->next == NULL)) { | 1136 | (dynamic_cast<SPText *>(object) && object->children && object->children->next == NULL)) { |
1007 | 1169 | // if this is a text with exactly one tspan child, merge the style of that tspan as well | 1137 | // if this is a text with exactly one tspan child, merge the style of that tspan as well |
1008 | 1170 | // If this is a group, merge the style of its topmost (last) child with style | 1138 | // If this is a group, merge the style of its topmost (last) child with style |
1011 | 1171 | for (SPObject *last_element = object->lastChild(); last_element != NULL; last_element = last_element->getPrev()) { | 1139 | for (SPObject *last_element = object->lastChild(); last_element != NULL; |
1012 | 1172 | if ( last_element->style ) { | 1140 | last_element = last_element->getPrev()) { |
1013 | 1141 | if (last_element->style) { | ||
1014 | 1173 | SPCSSAttr *temp = sp_css_attr_from_object(last_element, SP_STYLE_FLAG_IFSET); | 1142 | SPCSSAttr *temp = sp_css_attr_from_object(last_element, SP_STYLE_FLAG_IFSET); |
1015 | 1174 | if (temp) { | 1143 | if (temp) { |
1016 | 1175 | sp_repr_css_merge(css, temp); | 1144 | sp_repr_css_merge(css, temp); |
1017 | @@ -1183,7 +1152,8 @@ | |||
1018 | 1183 | // Remove black-listed properties (those that should not be used in a default style) | 1152 | // Remove black-listed properties (those that should not be used in a default style) |
1019 | 1184 | css = sp_css_attr_unset_blacklist(css); | 1153 | css = sp_css_attr_unset_blacklist(css); |
1020 | 1185 | 1154 | ||
1022 | 1186 | if (!(dynamic_cast<SPText *>(object) || dynamic_cast<SPTSpan *>(object) || dynamic_cast<SPTRef *>(object) || dynamic_cast<SPString *>(object))) { | 1155 | if (!(dynamic_cast<SPText *>(object) || dynamic_cast<SPTSpan *>(object) || dynamic_cast<SPTRef *>(object) || |
1023 | 1156 | dynamic_cast<SPString *>(object))) { | ||
1024 | 1187 | // do not copy text properties from non-text objects, it's confusing | 1157 | // do not copy text properties from non-text objects, it's confusing |
1025 | 1188 | css = sp_css_attr_unset_text(css); | 1158 | css = sp_css_attr_unset_text(css); |
1026 | 1189 | } | 1159 | } |
1027 | @@ -1229,16 +1199,15 @@ | |||
1028 | 1229 | { | 1199 | { |
1029 | 1230 | Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); | 1200 | Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); |
1030 | 1231 | if (cm->pastePathEffect(desktop)) { | 1201 | if (cm->pastePathEffect(desktop)) { |
1033 | 1232 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_PASTE_LIVEPATHEFFECT, | 1202 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_PASTE_LIVEPATHEFFECT, _("Paste live path effect")); |
1032 | 1233 | _("Paste live path effect")); | ||
1034 | 1234 | } | 1203 | } |
1035 | 1235 | } | 1204 | } |
1036 | 1236 | 1205 | ||
1037 | 1237 | 1206 | ||
1038 | 1238 | static void sp_selection_remove_livepatheffect_impl(SPItem *item) | 1207 | static void sp_selection_remove_livepatheffect_impl(SPItem *item) |
1039 | 1239 | { | 1208 | { |
1042 | 1240 | if ( SPLPEItem *lpeitem = dynamic_cast<SPLPEItem*>(item) ) { | 1209 | if (SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item)) { |
1043 | 1241 | if ( lpeitem->hasPathEffect() ) { | 1210 | if (lpeitem->hasPathEffect()) { |
1044 | 1242 | lpeitem->removeAllPathEffects(false); | 1211 | lpeitem->removeAllPathEffects(false); |
1045 | 1243 | } | 1212 | } |
1046 | 1244 | } | 1213 | } |
1047 | @@ -1246,30 +1215,31 @@ | |||
1048 | 1246 | 1215 | ||
1049 | 1247 | void sp_selection_remove_livepatheffect(SPDesktop *desktop) | 1216 | void sp_selection_remove_livepatheffect(SPDesktop *desktop) |
1050 | 1248 | { | 1217 | { |
1052 | 1249 | if (desktop == NULL) return; | 1218 | if (desktop == NULL) |
1053 | 1219 | return; | ||
1054 | 1250 | 1220 | ||
1055 | 1251 | Inkscape::Selection *selection = desktop->getSelection(); | 1221 | Inkscape::Selection *selection = desktop->getSelection(); |
1056 | 1252 | 1222 | ||
1057 | 1253 | // check if something is selected | 1223 | // check if something is selected |
1058 | 1254 | if (selection->isEmpty()) { | 1224 | if (selection->isEmpty()) { |
1060 | 1255 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to remove live path effects from.")); | 1225 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
1061 | 1226 | _("Select <b>object(s)</b> to remove live path effects from.")); | ||
1062 | 1256 | return; | 1227 | return; |
1063 | 1257 | } | 1228 | } |
1066 | 1258 | std::vector<SPItem*> list=selection->itemList(); | 1229 | std::vector<SPItem *> list = selection->itemList(); |
1067 | 1259 | for ( std::vector<SPItem*>::const_iterator itemlist=list.begin();itemlist!=list.end();itemlist++) { | 1230 | for (std::vector<SPItem *>::const_iterator itemlist = list.begin(); itemlist != list.end(); itemlist++) { |
1068 | 1260 | SPItem *item = *itemlist; | 1231 | SPItem *item = *itemlist; |
1069 | 1261 | 1232 | ||
1070 | 1262 | sp_selection_remove_livepatheffect_impl(item); | 1233 | sp_selection_remove_livepatheffect_impl(item); |
1071 | 1263 | |||
1072 | 1264 | } | 1234 | } |
1073 | 1265 | 1235 | ||
1076 | 1266 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_REMOVE_LIVEPATHEFFECT, | 1236 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_REMOVE_LIVEPATHEFFECT, _("Remove live path effect")); |
1075 | 1267 | _("Remove live path effect")); | ||
1077 | 1268 | } | 1237 | } |
1078 | 1269 | 1238 | ||
1079 | 1270 | void sp_selection_remove_filter(SPDesktop *desktop) | 1239 | void sp_selection_remove_filter(SPDesktop *desktop) |
1080 | 1271 | { | 1240 | { |
1082 | 1272 | if (desktop == NULL) return; | 1241 | if (desktop == NULL) |
1083 | 1242 | return; | ||
1084 | 1273 | 1243 | ||
1085 | 1274 | Inkscape::Selection *selection = desktop->getSelection(); | 1244 | Inkscape::Selection *selection = desktop->getSelection(); |
1086 | 1275 | 1245 | ||
1087 | @@ -1284,8 +1254,7 @@ | |||
1088 | 1284 | sp_desktop_set_style(desktop, css); | 1254 | sp_desktop_set_style(desktop, css); |
1089 | 1285 | sp_repr_css_attr_unref(css); | 1255 | sp_repr_css_attr_unref(css); |
1090 | 1286 | 1256 | ||
1093 | 1287 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_REMOVE_FILTER, | 1257 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_REMOVE_FILTER, _("Remove filter")); |
1092 | 1288 | _("Remove filter")); | ||
1094 | 1289 | } | 1258 | } |
1095 | 1290 | 1259 | ||
1096 | 1291 | 1260 | ||
1097 | @@ -1293,8 +1262,7 @@ | |||
1098 | 1293 | { | 1262 | { |
1099 | 1294 | Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); | 1263 | Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); |
1100 | 1295 | if (cm->pasteSize(desktop, false, apply_x, apply_y)) { | 1264 | if (cm->pasteSize(desktop, false, apply_x, apply_y)) { |
1103 | 1296 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_PASTE_SIZE, | 1265 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_PASTE_SIZE, _("Paste size")); |
1102 | 1297 | _("Paste size")); | ||
1104 | 1298 | } | 1266 | } |
1105 | 1299 | } | 1267 | } |
1106 | 1300 | 1268 | ||
1107 | @@ -1302,8 +1270,7 @@ | |||
1108 | 1302 | { | 1270 | { |
1109 | 1303 | Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); | 1271 | Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); |
1110 | 1304 | if (cm->pasteSize(desktop, true, apply_x, apply_y)) { | 1272 | if (cm->pasteSize(desktop, true, apply_x, apply_y)) { |
1113 | 1305 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_PASTE_SIZE_SEPARATELY, | 1273 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_PASTE_SIZE_SEPARATELY, _("Paste size separately")); |
1112 | 1306 | _("Paste size separately")); | ||
1114 | 1307 | } | 1274 | } |
1115 | 1308 | } | 1275 | } |
1116 | 1309 | 1276 | ||
1117 | @@ -1311,16 +1278,15 @@ | |||
1118 | 1311 | * Ensures that the clones of objects are not modified when moving objects between layers. | 1278 | * Ensures that the clones of objects are not modified when moving objects between layers. |
1119 | 1312 | * Calls the same function as ungroup | 1279 | * Calls the same function as ungroup |
1120 | 1313 | */ | 1280 | */ |
1122 | 1314 | void sp_selection_change_layer_maintain_clones(std::vector<SPItem*> const &items,SPObject *where) | 1281 | void sp_selection_change_layer_maintain_clones(std::vector<SPItem *> const &items, SPObject *where) |
1123 | 1315 | { | 1282 | { |
1125 | 1316 | for (std::vector<SPItem*>::const_iterator i = items.begin(); i != items.end(); i++) { | 1283 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
1126 | 1317 | SPItem *item = *i; | 1284 | SPItem *item = *i; |
1127 | 1318 | if (item) { | 1285 | if (item) { |
1128 | 1319 | SPItem *oldparent = dynamic_cast<SPItem *>(item->parent); | 1286 | SPItem *oldparent = dynamic_cast<SPItem *>(item->parent); |
1129 | 1320 | SPItem *newparent = dynamic_cast<SPItem *>(where); | 1287 | SPItem *newparent = dynamic_cast<SPItem *>(where); |
1130 | 1321 | sp_item_group_ungroup_handle_clones(item, | 1288 | sp_item_group_ungroup_handle_clones(item, |
1133 | 1322 | (oldparent->i2doc_affine()) | 1289 | (oldparent->i2doc_affine()) * ((newparent->i2doc_affine()).inverse())); |
1132 | 1323 | *((newparent->i2doc_affine()).inverse())); | ||
1134 | 1324 | } | 1290 | } |
1135 | 1325 | } | 1291 | } |
1136 | 1326 | } | 1292 | } |
1137 | @@ -1336,17 +1302,18 @@ | |||
1138 | 1336 | return; | 1302 | return; |
1139 | 1337 | } | 1303 | } |
1140 | 1338 | 1304 | ||
1142 | 1339 | std::vector<SPItem*> items(selection->itemList()); | 1305 | std::vector<SPItem *> items(selection->itemList()); |
1143 | 1340 | 1306 | ||
1144 | 1341 | bool no_more = false; // Set to true, if no more layers above | 1307 | bool no_more = false; // Set to true, if no more layers above |
1146 | 1342 | SPObject *next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); | 1308 | SPObject *next = Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); |
1147 | 1343 | if (next) { | 1309 | if (next) { |
1150 | 1344 | sp_selection_change_layer_maintain_clones(items,next); | 1310 | sp_selection_change_layer_maintain_clones(items, next); |
1151 | 1345 | std::vector<Inkscape::XML::Node*> temp_clip; | 1311 | std::vector<Inkscape::XML::Node *> temp_clip; |
1152 | 1346 | sp_selection_copy_impl(items, temp_clip, dt->doc()->getReprDoc()); | 1312 | sp_selection_copy_impl(items, temp_clip, dt->doc()->getReprDoc()); |
1153 | 1347 | sp_selection_delete_impl(items, false, false); | 1313 | sp_selection_delete_impl(items, false, false); |
1156 | 1348 | next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers | 1314 | next = |
1157 | 1349 | std::vector<Inkscape::XML::Node*> copied; | 1315 | Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers |
1158 | 1316 | std::vector<Inkscape::XML::Node *> copied; | ||
1159 | 1350 | if (next) { | 1317 | if (next) { |
1160 | 1351 | copied = sp_selection_paste_impl(dt->getDocument(), next, temp_clip); | 1318 | copied = sp_selection_paste_impl(dt->getDocument(), next, temp_clip); |
1161 | 1352 | } else { | 1319 | } else { |
1162 | @@ -1354,10 +1321,10 @@ | |||
1163 | 1354 | no_more = true; | 1321 | no_more = true; |
1164 | 1355 | } | 1322 | } |
1165 | 1356 | selection->setReprList(copied); | 1323 | selection->setReprList(copied); |
1170 | 1357 | if (next) dt->setCurrentLayer(next); | 1324 | if (next) |
1171 | 1358 | if ( !suppressDone ) { | 1325 | dt->setCurrentLayer(next); |
1172 | 1359 | DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_MOVE_TO_NEXT, | 1326 | if (!suppressDone) { |
1173 | 1360 | _("Raise to next layer")); | 1327 | DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_MOVE_TO_NEXT, _("Raise to next layer")); |
1174 | 1361 | } | 1328 | } |
1175 | 1362 | } else { | 1329 | } else { |
1176 | 1363 | no_more = true; | 1330 | no_more = true; |
1177 | @@ -1366,7 +1333,6 @@ | |||
1178 | 1366 | if (no_more) { | 1333 | if (no_more) { |
1179 | 1367 | dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No more layers above.")); | 1334 | dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No more layers above.")); |
1180 | 1368 | } | 1335 | } |
1181 | 1369 | |||
1182 | 1370 | } | 1336 | } |
1183 | 1371 | 1337 | ||
1184 | 1372 | void sp_selection_to_prev_layer(SPDesktop *dt, bool suppressDone) | 1338 | void sp_selection_to_prev_layer(SPDesktop *dt, bool suppressDone) |
1185 | @@ -1379,28 +1345,30 @@ | |||
1186 | 1379 | return; | 1345 | return; |
1187 | 1380 | } | 1346 | } |
1188 | 1381 | 1347 | ||
1190 | 1382 | const std::vector<SPItem*> items(selection->itemList()); | 1348 | const std::vector<SPItem *> items(selection->itemList()); |
1191 | 1383 | 1349 | ||
1192 | 1384 | bool no_more = false; // Set to true, if no more layers below | 1350 | bool no_more = false; // Set to true, if no more layers below |
1194 | 1385 | SPObject *next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); | 1351 | SPObject *next = Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); |
1195 | 1386 | if (next) { | 1352 | if (next) { |
1199 | 1387 | sp_selection_change_layer_maintain_clones(items,next); | 1353 | sp_selection_change_layer_maintain_clones(items, next); |
1200 | 1388 | std::vector<Inkscape::XML::Node*> temp_clip; | 1354 | std::vector<Inkscape::XML::Node *> temp_clip; |
1201 | 1389 | sp_selection_copy_impl(items, temp_clip, dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs | 1355 | sp_selection_copy_impl(items, temp_clip, |
1202 | 1356 | dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs | ||
1203 | 1390 | sp_selection_delete_impl(items, false, false); | 1357 | sp_selection_delete_impl(items, false, false); |
1206 | 1391 | next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers | 1358 | next = Inkscape::previous_layer(dt->currentRoot(), |
1207 | 1392 | std::vector<Inkscape::XML::Node*> copied; | 1359 | dt->currentLayer()); // Fixes bug 1482973: crash while moving layers |
1208 | 1360 | std::vector<Inkscape::XML::Node *> copied; | ||
1209 | 1393 | if (next) { | 1361 | if (next) { |
1210 | 1394 | copied = sp_selection_paste_impl(dt->getDocument(), next, temp_clip); | 1362 | copied = sp_selection_paste_impl(dt->getDocument(), next, temp_clip); |
1211 | 1395 | } else { | 1363 | } else { |
1212 | 1396 | copied = sp_selection_paste_impl(dt->getDocument(), dt->currentLayer(), temp_clip); | 1364 | copied = sp_selection_paste_impl(dt->getDocument(), dt->currentLayer(), temp_clip); |
1213 | 1397 | no_more = true; | 1365 | no_more = true; |
1214 | 1398 | } | 1366 | } |
1220 | 1399 | selection->setReprList( copied); | 1367 | selection->setReprList(copied); |
1221 | 1400 | if (next) dt->setCurrentLayer(next); | 1368 | if (next) |
1222 | 1401 | if ( !suppressDone ) { | 1369 | dt->setCurrentLayer(next); |
1223 | 1402 | DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_MOVE_TO_PREV, | 1370 | if (!suppressDone) { |
1224 | 1403 | _("Lower to previous layer")); | 1371 | DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_MOVE_TO_PREV, _("Lower to previous layer")); |
1225 | 1404 | } | 1372 | } |
1226 | 1405 | } else { | 1373 | } else { |
1227 | 1406 | no_more = true; | 1374 | no_more = true; |
1228 | @@ -1421,34 +1389,34 @@ | |||
1229 | 1421 | return; | 1389 | return; |
1230 | 1422 | } | 1390 | } |
1231 | 1423 | 1391 | ||
1233 | 1424 | std::vector<SPItem*> items(selection->itemList()); | 1392 | std::vector<SPItem *> items(selection->itemList()); |
1234 | 1425 | 1393 | ||
1235 | 1426 | if (moveto) { | 1394 | if (moveto) { |
1239 | 1427 | sp_selection_change_layer_maintain_clones(items,moveto); | 1395 | sp_selection_change_layer_maintain_clones(items, moveto); |
1240 | 1428 | std::vector<Inkscape::XML::Node*> temp_clip; | 1396 | std::vector<Inkscape::XML::Node *> temp_clip; |
1241 | 1429 | sp_selection_copy_impl(items, temp_clip, dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs | 1397 | sp_selection_copy_impl(items, temp_clip, |
1242 | 1398 | dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs | ||
1243 | 1430 | sp_selection_delete_impl(items, false, false); | 1399 | sp_selection_delete_impl(items, false, false); |
1245 | 1431 | std::vector<Inkscape::XML::Node*> copied = sp_selection_paste_impl(dt->getDocument(), moveto, temp_clip); | 1400 | std::vector<Inkscape::XML::Node *> copied = sp_selection_paste_impl(dt->getDocument(), moveto, temp_clip); |
1246 | 1432 | selection->setReprList(copied); | 1401 | selection->setReprList(copied); |
1252 | 1433 | if (!temp_clip.empty()) temp_clip.clear(); | 1402 | if (!temp_clip.empty()) |
1253 | 1434 | if (moveto) dt->setCurrentLayer(moveto); | 1403 | temp_clip.clear(); |
1254 | 1435 | if ( !suppressDone ) { | 1404 | if (moveto) |
1255 | 1436 | DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_MOVE_TO, | 1405 | dt->setCurrentLayer(moveto); |
1256 | 1437 | _("Move selection to layer")); | 1406 | if (!suppressDone) { |
1257 | 1407 | DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_MOVE_TO, _("Move selection to layer")); | ||
1258 | 1438 | } | 1408 | } |
1259 | 1439 | } | 1409 | } |
1260 | 1440 | } | 1410 | } |
1261 | 1441 | 1411 | ||
1264 | 1442 | static bool | 1412 | static bool selection_contains_original(SPItem *item, Inkscape::Selection *selection) |
1263 | 1443 | selection_contains_original(SPItem *item, Inkscape::Selection *selection) | ||
1265 | 1444 | { | 1413 | { |
1266 | 1445 | bool contains_original = false; | 1414 | bool contains_original = false; |
1267 | 1446 | 1415 | ||
1268 | 1447 | SPItem *item_use = item; | 1416 | SPItem *item_use = item; |
1269 | 1448 | SPItem *item_use_first = item; | 1417 | SPItem *item_use_first = item; |
1270 | 1449 | SPUse *use = dynamic_cast<SPUse *>(item_use); | 1418 | SPUse *use = dynamic_cast<SPUse *>(item_use); |
1273 | 1450 | while (use && item_use && !contains_original) | 1419 | while (use && item_use && !contains_original) { |
1272 | 1451 | { | ||
1274 | 1452 | item_use = use->get_original(); | 1420 | item_use = use->get_original(); |
1275 | 1453 | use = dynamic_cast<SPUse *>(item_use); | 1421 | use = dynamic_cast<SPUse *>(item_use); |
1276 | 1454 | contains_original |= selection->includes(item_use); | 1422 | contains_original |= selection->includes(item_use); |
1277 | @@ -1467,12 +1435,11 @@ | |||
1278 | 1467 | } | 1435 | } |
1279 | 1468 | 1436 | ||
1280 | 1469 | 1437 | ||
1283 | 1470 | static bool | 1438 | static bool selection_contains_both_clone_and_original(Inkscape::Selection *selection) |
1282 | 1471 | selection_contains_both_clone_and_original(Inkscape::Selection *selection) | ||
1284 | 1472 | { | 1439 | { |
1285 | 1473 | bool clone_with_original = false; | 1440 | bool clone_with_original = false; |
1288 | 1474 | std::vector<SPItem*> items = selection->itemList(); | 1441 | std::vector<SPItem *> items = selection->itemList(); |
1289 | 1475 | for (std::vector<SPItem*>::const_iterator l=items.begin();l!=items.end() ;l++) { | 1442 | for (std::vector<SPItem *>::const_iterator l = items.begin(); l != items.end(); l++) { |
1290 | 1476 | SPItem *item = *l; | 1443 | SPItem *item = *l; |
1291 | 1477 | if (item) { | 1444 | if (item) { |
1292 | 1478 | clone_with_original |= selection_contains_original(item, selection); | 1445 | clone_with_original |= selection_contains_original(item, selection); |
1293 | @@ -1483,13 +1450,149 @@ | |||
1294 | 1483 | return clone_with_original; | 1450 | return clone_with_original; |
1295 | 1484 | } | 1451 | } |
1296 | 1485 | 1452 | ||
1297 | 1453 | /* This function is called by sp_selection_apply_affine. | ||
1298 | 1454 | It takes all elements in selection, looks for all clones (or linked offsets) that are also in the | ||
1299 | 1455 | selection (either directly selected or in a selected group) | ||
1300 | 1456 | |||
1301 | 1457 | The matrix magic in it is designed so that any transformation (translation or other) is handled | ||
1302 | 1458 | with any selections in a coherent way. | ||
1303 | 1459 | |||
1304 | 1460 | Note that if affine is a translation, then SPUse::compensate is involved in a subtle way and we | ||
1305 | 1461 | have to account for it. | ||
1306 | 1462 | |||
1307 | 1463 | If you want to modify this function, please watch carefully for regressions, and take extra care | ||
1308 | 1464 | to have the right advertised transforms so that clones of clones behave well. | ||
1309 | 1465 | |||
1310 | 1466 | There are 10 cases to test. | ||
1311 | 1467 | */ | ||
1312 | 1468 | static void prevent_clone_double_transform(Inkscape::Selection *selection, SPItem *parent, Geom::Affine affine, | ||
1313 | 1469 | bool compensate) | ||
1314 | 1470 | { | ||
1315 | 1471 | // "clones are unmoved when original is moved" preference | ||
1316 | 1472 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); | ||
1317 | 1473 | int compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); | ||
1318 | 1474 | bool prefs_unmoved = (compensation == SP_CLONE_COMPENSATION_UNMOVED); | ||
1319 | 1475 | bool prefs_parallel = (compensation == SP_CLONE_COMPENSATION_PARALLEL); | ||
1320 | 1476 | |||
1321 | 1477 | // calculate the matrix we need to apply to the clone to cancel its induced transform from its original | ||
1322 | 1478 | if (!dynamic_cast<SPItem *>(parent->parent)) | ||
1323 | 1479 | return; | ||
1324 | 1480 | Geom::Affine parent2dt = dynamic_cast<SPItem *>(parent->parent)->i2dt_affine(); | ||
1325 | 1481 | Geom::Affine t = parent2dt * affine * parent2dt.inverse(); | ||
1326 | 1482 | Geom::Affine t_inv = t.inverse(); | ||
1327 | 1483 | |||
1328 | 1484 | for (std::list<SPObject *>::const_iterator refd = parent->hrefList.begin(); refd != parent->hrefList.end(); | ||
1329 | 1485 | refd++) { | ||
1330 | 1486 | SPItem *item = dynamic_cast<SPItem *>(*refd); | ||
1331 | 1487 | if (!item || item->cloned) | ||
1332 | 1488 | continue; | ||
1333 | 1489 | bool transform_offset_with_source = false; | ||
1334 | 1490 | bool transform_clone_with_original = false; | ||
1335 | 1491 | bool transform_deep_offset_with_source = false; | ||
1336 | 1492 | bool transform_deep_clone_with_original = false; | ||
1337 | 1493 | |||
1338 | 1494 | SPUse *useitem = dynamic_cast<SPUse *>(item); | ||
1339 | 1495 | SPOffset *off = dynamic_cast<SPOffset *>(item); | ||
1340 | 1496 | if (off && off->sourceHref && sp_offset_get_source(off) == parent) { | ||
1341 | 1497 | // We transform a linked offset and (directly) its original | ||
1342 | 1498 | transform_offset_with_source = selection->includes(off); | ||
1343 | 1499 | transform_deep_offset_with_source = selection->includes_deeply(off); | ||
1344 | 1500 | } else if (useitem && useitem->get_original() == parent) { | ||
1345 | 1501 | // We are transforming a clone along with its original. | ||
1346 | 1502 | transform_clone_with_original = selection->includes(useitem); | ||
1347 | 1503 | transform_deep_clone_with_original = selection->includes_deeply(useitem); | ||
1348 | 1504 | } else | ||
1349 | 1505 | continue; | ||
1350 | 1506 | |||
1351 | 1507 | // restore item->transform field from the repr, in case it was changed by seltrans | ||
1352 | 1508 | item->readAttr("transform"); | ||
1353 | 1509 | |||
1354 | 1510 | if (transform_clone_with_original || transform_offset_with_source) { | ||
1355 | 1511 | // case 1: the clone and the original are directly selected. | ||
1356 | 1512 | |||
1357 | 1513 | Geom::Affine result = t_inv * item->transform * t; | ||
1358 | 1514 | |||
1359 | 1515 | if (transform_clone_with_original && (prefs_parallel || prefs_unmoved) && affine.isTranslation()) { | ||
1360 | 1516 | // 1.1: translation, clone | ||
1361 | 1517 | // find out the clone move, same as in SPUse::move_compensate | ||
1362 | 1518 | Geom::Affine parent = useitem->get_parent_transform(); | ||
1363 | 1519 | Geom::Affine clone_move = parent.inverse() * t * parent; | ||
1364 | 1520 | |||
1365 | 1521 | if (prefs_parallel) { | ||
1366 | 1522 | Geom::Affine move = result * clone_move * t_inv; | ||
1367 | 1523 | item->doWriteTransform(item->getRepr(), move, &move, compensate); | ||
1368 | 1524 | |||
1369 | 1525 | } else if (prefs_unmoved) { | ||
1370 | 1526 | Geom::Affine move = result * clone_move; | ||
1371 | 1527 | item->doWriteTransform(item->getRepr(), move, &t, compensate); | ||
1372 | 1528 | } | ||
1373 | 1529 | |||
1374 | 1530 | } else if (transform_offset_with_source && (prefs_parallel || prefs_unmoved) && affine.isTranslation()) { | ||
1375 | 1531 | // 1.2: translation, offset | ||
1376 | 1532 | Geom::Affine parent = item->transform; | ||
1377 | 1533 | Geom::Affine offset_move = parent.inverse() * t * parent; | ||
1378 | 1534 | |||
1379 | 1535 | if (prefs_parallel) { | ||
1380 | 1536 | Geom::Affine move = result * offset_move * t_inv; | ||
1381 | 1537 | item->doWriteTransform(item->getRepr(), move, &move, compensate); | ||
1382 | 1538 | |||
1383 | 1539 | } else if (prefs_unmoved) { | ||
1384 | 1540 | Geom::Affine move = result * offset_move; | ||
1385 | 1541 | item->doWriteTransform(item->getRepr(), move, &t, compensate); | ||
1386 | 1542 | } | ||
1387 | 1543 | } else { // 1.3: affine is no translation, just apply the result | ||
1388 | 1544 | item->doWriteTransform(item->getRepr(), result, &t, compensate); | ||
1389 | 1545 | } | ||
1390 | 1546 | } else if (transform_deep_clone_with_original || transform_deep_offset_with_source) { | ||
1391 | 1547 | // case 2: The original is selected, and the clone is somewhere in a selected group. | ||
1392 | 1548 | if (transform_deep_clone_with_original && (prefs_parallel || prefs_unmoved) && affine.isTranslation()) { | ||
1393 | 1549 | // 2.1: translation, clone | ||
1394 | 1550 | |||
1395 | 1551 | Geom::Affine parent = useitem->get_parent_transform(); | ||
1396 | 1552 | Geom::Affine clone_move = parent.inverse() * t * parent; | ||
1397 | 1553 | |||
1398 | 1554 | if (prefs_parallel) { | ||
1399 | 1555 | Geom::Affine move = t_inv * item->transform * t_inv * clone_move; | ||
1400 | 1556 | item->doWriteTransform(item->getRepr(), move, &move, compensate); | ||
1401 | 1557 | |||
1402 | 1558 | } else if (prefs_unmoved) { | ||
1403 | 1559 | Geom::Affine move = t_inv * item->transform * clone_move; | ||
1404 | 1560 | Geom::Affine move_a = Geom::Affine::identity(); | ||
1405 | 1561 | item->doWriteTransform(item->getRepr(), move, &move_a, compensate); | ||
1406 | 1562 | } | ||
1407 | 1563 | } else if (transform_deep_offset_with_source && (prefs_parallel || prefs_unmoved) && | ||
1408 | 1564 | affine.isTranslation()) { | ||
1409 | 1565 | // 2.2: translation, offset | ||
1410 | 1566 | Geom::Affine parent = item->transform; | ||
1411 | 1567 | Geom::Affine offset_move = parent.inverse() * t * parent; | ||
1412 | 1568 | Geom::Affine result = t_inv * item->transform * t_inv; | ||
1413 | 1569 | |||
1414 | 1570 | if (prefs_parallel) { | ||
1415 | 1571 | Geom::Affine move = result * offset_move; | ||
1416 | 1572 | item->doWriteTransform(item->getRepr(), move, &move, compensate); | ||
1417 | 1573 | |||
1418 | 1574 | } else if (prefs_unmoved) { | ||
1419 | 1575 | Geom::Affine move = result * t * offset_move; | ||
1420 | 1576 | Geom::Affine move_a = Geom::Affine::identity(); | ||
1421 | 1577 | item->doWriteTransform(item->getRepr(), move, &move_a, compensate); | ||
1422 | 1578 | } | ||
1423 | 1579 | } else { // 2.3: affine is no translation | ||
1424 | 1580 | Geom::Affine move = parent2dt * affine.inverse() * parent2dt.inverse() * item->transform; | ||
1425 | 1581 | item->doWriteTransform(item->getRepr(), move, &move, compensate); | ||
1426 | 1582 | } | ||
1427 | 1583 | } | ||
1428 | 1584 | } | ||
1429 | 1585 | } | ||
1430 | 1586 | |||
1431 | 1587 | |||
1432 | 1486 | /** Apply matrix to the selection. \a set_i2d is normally true, which means objects are in the | 1588 | /** Apply matrix to the selection. \a set_i2d is normally true, which means objects are in the |
1433 | 1487 | original transform, synced with their reprs, and need to jump to the new transform in one go. A | 1589 | original transform, synced with their reprs, and need to jump to the new transform in one go. A |
1434 | 1488 | value of set_i2d==false is only used by seltrans when it's dragging objects live (not outlines); in | 1590 | value of set_i2d==false is only used by seltrans when it's dragging objects live (not outlines); in |
1435 | 1489 | that case, items are already in the new position, but the repr is in the old, and this function | 1591 | that case, items are already in the new position, but the repr is in the old, and this function |
1436 | 1490 | then simply updates the repr from item->transform. | 1592 | then simply updates the repr from item->transform. |
1437 | 1491 | */ | 1593 | */ |
1439 | 1492 | void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d, bool compensate, bool adjust_transf_center) | 1594 | void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d, |
1440 | 1595 | bool compensate, bool adjust_transf_center) | ||
1441 | 1493 | { | 1596 | { |
1442 | 1494 | if (selection->isEmpty()) | 1597 | if (selection->isEmpty()) |
1443 | 1495 | return; | 1598 | return; |
1444 | @@ -1500,13 +1603,13 @@ | |||
1445 | 1500 | Persp3D *transf_persp; | 1603 | Persp3D *transf_persp; |
1446 | 1501 | std::list<Persp3D *> plist = selection->perspList(); | 1604 | std::list<Persp3D *> plist = selection->perspList(); |
1447 | 1502 | for (std::list<Persp3D *>::iterator i = plist.begin(); i != plist.end(); ++i) { | 1605 | for (std::list<Persp3D *>::iterator i = plist.begin(); i != plist.end(); ++i) { |
1449 | 1503 | persp = (Persp3D *) (*i); | 1606 | persp = (Persp3D *)(*i); |
1450 | 1504 | 1607 | ||
1452 | 1505 | if (!persp3d_has_all_boxes_in_selection (persp, selection)) { | 1608 | if (!persp3d_has_all_boxes_in_selection(persp, selection)) { |
1453 | 1506 | std::list<SPBox3D *> selboxes = selection->box3DList(persp); | 1609 | std::list<SPBox3D *> selboxes = selection->box3DList(persp); |
1454 | 1507 | 1610 | ||
1455 | 1508 | // create a new perspective as a copy of the current one and link the selected boxes to it | 1611 | // create a new perspective as a copy of the current one and link the selected boxes to it |
1457 | 1509 | transf_persp = persp3d_create_xml_element (persp->document, persp->perspective_impl); | 1612 | transf_persp = persp3d_create_xml_element(persp->document, persp->perspective_impl); |
1458 | 1510 | 1613 | ||
1459 | 1511 | for (std::list<SPBox3D *>::iterator b = selboxes.begin(); b != selboxes.end(); ++b) | 1614 | for (std::list<SPBox3D *>::iterator b = selboxes.begin(); b != selboxes.end(); ++b) |
1460 | 1512 | box3d_switch_perspectives(*b, persp, transf_persp); | 1615 | box3d_switch_perspectives(*b, persp, transf_persp); |
1461 | @@ -1516,38 +1619,49 @@ | |||
1462 | 1516 | 1619 | ||
1463 | 1517 | persp3d_apply_affine_transformation(transf_persp, affine); | 1620 | persp3d_apply_affine_transformation(transf_persp, affine); |
1464 | 1518 | } | 1621 | } |
1467 | 1519 | std::vector<SPItem*> items = selection->itemList(); | 1622 | std::vector<SPItem *> items = selection->itemList(); |
1468 | 1520 | for (std::vector<SPItem*>::const_iterator l=items.begin();l!=items.end() ;l++) { | 1623 | for (std::vector<SPItem *>::const_iterator l = items.begin(); l != items.end(); l++) { |
1469 | 1521 | SPItem *item = *l; | 1624 | SPItem *item = *l; |
1470 | 1522 | 1625 | ||
1472 | 1523 | if( dynamic_cast<SPRoot *>(item) ) { | 1626 | if (dynamic_cast<SPRoot *>(item)) { |
1473 | 1524 | // An SVG element cannot have a transform. We could change 'x' and 'y' in response | 1627 | // An SVG element cannot have a transform. We could change 'x' and 'y' in response |
1474 | 1525 | // to a translation... but leave that for another day. | 1628 | // to a translation... but leave that for another day. |
1476 | 1526 | selection->desktop()->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Cannot transform an embedded SVG.")); | 1629 | selection->desktop()->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
1477 | 1630 | _("Cannot transform an embedded SVG.")); | ||
1478 | 1527 | break; | 1631 | break; |
1479 | 1528 | } | 1632 | } |
1480 | 1529 | 1633 | ||
1482 | 1530 | Geom::Point old_center(0,0); | 1634 | Geom::Point old_center(0, 0); |
1483 | 1531 | if (set_i2d && item->isCenterSet()) | 1635 | if (set_i2d && item->isCenterSet()) |
1484 | 1532 | old_center = item->getCenter(); | 1636 | old_center = item->getCenter(); |
1485 | 1533 | 1637 | ||
1487 | 1534 | #if 0 /* Re-enable this once persistent guides have a graphical indication. | 1638 | #if 0 /* Re-enable this once persistent guides have a graphical indication. \ |
1488 | 1535 | At the time of writing, this is the only place to re-enable. */ | 1639 | At the time of writing, this is the only place to re-enable. */ |
1489 | 1536 | sp_item_update_cns(*item, selection->desktop()); | 1640 | sp_item_update_cns(*item, selection->desktop()); |
1490 | 1537 | #endif | 1641 | #endif |
1491 | 1538 | 1642 | ||
1504 | 1539 | // we're moving both a clone and its original or any ancestor in clone chain? | 1643 | // everyting is taken care of in prevent_clone_double_transform for the two first cases, |
1505 | 1540 | bool transform_clone_with_original = selection_contains_original(item, selection); | 1644 | // *after* the transformation is applied to the original. |
1506 | 1541 | 1645 | ||
1507 | 1542 | // ...both a text-on-path and its path? | 1646 | // Tests if we're moving both a clone and its original... |
1508 | 1543 | bool transform_textpath_with_path = ((dynamic_cast<SPText *>(item) && item->firstChild() && dynamic_cast<SPTextPath *>(item->firstChild())) | 1647 | if (selection_contains_original(item, selection)) |
1509 | 1544 | && selection->includes( sp_textpath_get_path_item(dynamic_cast<SPTextPath *>(item->firstChild())) )); | 1648 | continue; |
1510 | 1545 | 1649 | ||
1511 | 1546 | // ...both a flowtext and its frame? | 1650 | // ...both an offset and its source... |
1512 | 1547 | bool transform_flowtext_with_frame = (dynamic_cast<SPFlowtext *>(item) && selection->includes( dynamic_cast<SPFlowtext *>(item)->get_frame(NULL))); // (only the first frame is checked so far) | 1651 | if ((dynamic_cast<SPOffset *>(item) && dynamic_cast<SPOffset *>(item)->sourceHref) && |
1513 | 1548 | 1652 | selection->includes(sp_offset_get_source(dynamic_cast<SPOffset *>(item)))) | |
1514 | 1549 | // ...both an offset and its source? | 1653 | continue; |
1515 | 1550 | bool transform_offset_with_source = (dynamic_cast<SPOffset *>(item) && dynamic_cast<SPOffset *>(item)->sourceHref) && selection->includes( sp_offset_get_source(dynamic_cast<SPOffset *>(item)) ); | 1654 | |
1516 | 1655 | // ...both a text-on-path and its path... | ||
1517 | 1656 | bool transform_textpath_with_path = | ||
1518 | 1657 | ((dynamic_cast<SPText *>(item) && item->firstChild() && dynamic_cast<SPTextPath *>(item->firstChild())) && | ||
1519 | 1658 | selection->includes(sp_textpath_get_path_item(dynamic_cast<SPTextPath *>(item->firstChild())))); | ||
1520 | 1659 | |||
1521 | 1660 | // ...both a flowtext and its frame... | ||
1522 | 1661 | bool transform_flowtext_with_frame = (dynamic_cast<SPFlowtext *>(item) && | ||
1523 | 1662 | selection->includes(dynamic_cast<SPFlowtext *>(item)->get_frame( | ||
1524 | 1663 | NULL))); // (only the first frame is checked so far) | ||
1525 | 1664 | |||
1526 | 1551 | 1665 | ||
1527 | 1552 | // If we're moving a connector, we want to detach it | 1666 | // If we're moving a connector, we want to detach it |
1528 | 1553 | // from shapes that aren't part of the selection, but | 1667 | // from shapes that aren't part of the selection, but |
1529 | @@ -1555,7 +1669,7 @@ | |||
1530 | 1555 | if (Inkscape::UI::Tools::cc_item_is_connector(item)) { | 1669 | if (Inkscape::UI::Tools::cc_item_is_connector(item)) { |
1531 | 1556 | SPPath *path = dynamic_cast<SPPath *>(item); | 1670 | SPPath *path = dynamic_cast<SPPath *>(item); |
1532 | 1557 | if (path) { | 1671 | if (path) { |
1534 | 1558 | SPItem *attItem[2] = {0, 0}; | 1672 | SPItem *attItem[2] = { 0, 0 }; |
1535 | 1559 | path->connEndPair.getAttachedItems(attItem); | 1673 | path->connEndPair.getAttachedItems(attItem); |
1536 | 1560 | for (int n = 0; n < 2; ++n) { | 1674 | for (int n = 0; n < 2; ++n) { |
1537 | 1561 | if (!selection->includes(attItem[n])) { | 1675 | if (!selection->includes(attItem[n])) { |
1538 | @@ -1567,12 +1681,6 @@ | |||
1539 | 1567 | } | 1681 | } |
1540 | 1568 | } | 1682 | } |
1541 | 1569 | 1683 | ||
1542 | 1570 | // "clones are unmoved when original is moved" preference | ||
1543 | 1571 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); | ||
1544 | 1572 | int compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); | ||
1545 | 1573 | bool prefs_unmoved = (compensation == SP_CLONE_COMPENSATION_UNMOVED); | ||
1546 | 1574 | bool prefs_parallel = (compensation == SP_CLONE_COMPENSATION_PARALLEL); | ||
1547 | 1575 | |||
1548 | 1576 | /* If this is a clone and it's selected along with its original, do not move it; | 1684 | /* If this is a clone and it's selected along with its original, do not move it; |
1549 | 1577 | * it will feel the transform of its original and respond to it itself. | 1685 | * it will feel the transform of its original and respond to it itself. |
1550 | 1578 | * Without this, a clone is doubly transformed, very unintuitive. | 1686 | * Without this, a clone is doubly transformed, very unintuitive. |
1551 | @@ -1582,86 +1690,20 @@ | |||
1552 | 1582 | * Same for linked offset if we are also moving its source: do not move it. */ | 1690 | * Same for linked offset if we are also moving its source: do not move it. */ |
1553 | 1583 | if (transform_textpath_with_path) { | 1691 | if (transform_textpath_with_path) { |
1554 | 1584 | // Restore item->transform field from the repr, in case it was changed by seltrans. | 1692 | // Restore item->transform field from the repr, in case it was changed by seltrans. |
1556 | 1585 | item->readAttr( "transform" ); | 1693 | item->readAttr("transform"); |
1557 | 1586 | } else if (transform_flowtext_with_frame) { | 1694 | } else if (transform_flowtext_with_frame) { |
1558 | 1587 | // apply the inverse of the region's transform to the <use> so that the flow remains | 1695 | // apply the inverse of the region's transform to the <use> so that the flow remains |
1559 | 1588 | // the same (even though the output itself gets transformed) | 1696 | // the same (even though the output itself gets transformed) |
1561 | 1589 | for ( SPObject *region = item->firstChild() ; region ; region = region->getNext() ) { | 1697 | for (SPObject *region = item->firstChild(); region; region = region->getNext()) { |
1562 | 1590 | if (dynamic_cast<SPFlowregion *>(region) || dynamic_cast<SPFlowregionExclude *>(region)) { | 1698 | if (dynamic_cast<SPFlowregion *>(region) || dynamic_cast<SPFlowregionExclude *>(region)) { |
1564 | 1591 | for ( SPObject *item = region->firstChild() ; item ; item = item->getNext() ) { | 1699 | for (SPObject *item = region->firstChild(); item; item = item->getNext()) { |
1565 | 1592 | SPUse *use = dynamic_cast<SPUse *>(item); | 1700 | SPUse *use = dynamic_cast<SPUse *>(item); |
1567 | 1593 | if ( use ) { | 1701 | if (use) { |
1568 | 1594 | use->doWriteTransform(use->getRepr(), use->transform.inverse(), NULL, compensate); | 1702 | use->doWriteTransform(use->getRepr(), use->transform.inverse(), NULL, compensate); |
1569 | 1595 | } | 1703 | } |
1570 | 1596 | } | 1704 | } |
1571 | 1597 | } | 1705 | } |
1572 | 1598 | } | 1706 | } |
1573 | 1599 | } else if (transform_clone_with_original || transform_offset_with_source) { | ||
1574 | 1600 | // We are transforming a clone along with its original. The below matrix juggling is | ||
1575 | 1601 | // necessary to ensure that they transform as a whole, i.e. the clone's induced | ||
1576 | 1602 | // transform and its move compensation are both cancelled out. | ||
1577 | 1603 | |||
1578 | 1604 | // restore item->transform field from the repr, in case it was changed by seltrans | ||
1579 | 1605 | item->readAttr( "transform" ); | ||
1580 | 1606 | |||
1581 | 1607 | // calculate the matrix we need to apply to the clone to cancel its induced transform from its original | ||
1582 | 1608 | Geom::Affine parent2dt; | ||
1583 | 1609 | { | ||
1584 | 1610 | SPItem *parentItem = dynamic_cast<SPItem *>(item->parent); | ||
1585 | 1611 | if (parentItem) { | ||
1586 | 1612 | parent2dt = parentItem->i2dt_affine(); | ||
1587 | 1613 | } else { | ||
1588 | 1614 | g_assert_not_reached(); | ||
1589 | 1615 | } | ||
1590 | 1616 | } | ||
1591 | 1617 | Geom::Affine t = parent2dt * affine * parent2dt.inverse(); | ||
1592 | 1618 | Geom::Affine t_inv = t.inverse(); | ||
1593 | 1619 | Geom::Affine result = t_inv * item->transform * t; | ||
1594 | 1620 | |||
1595 | 1621 | if (transform_clone_with_original && (prefs_parallel || prefs_unmoved) && affine.isTranslation()) { | ||
1596 | 1622 | // we need to cancel out the move compensation, too | ||
1597 | 1623 | |||
1598 | 1624 | // find out the clone move, same as in sp_use_move_compensate | ||
1599 | 1625 | Geom::Affine parent; | ||
1600 | 1626 | { | ||
1601 | 1627 | SPUse *use = dynamic_cast<SPUse *>(item); | ||
1602 | 1628 | if (use) { | ||
1603 | 1629 | parent = use->get_parent_transform(); | ||
1604 | 1630 | } else { | ||
1605 | 1631 | g_assert_not_reached(); | ||
1606 | 1632 | } | ||
1607 | 1633 | } | ||
1608 | 1634 | Geom::Affine clone_move = parent.inverse() * t * parent; | ||
1609 | 1635 | |||
1610 | 1636 | if (prefs_parallel) { | ||
1611 | 1637 | Geom::Affine move = result * clone_move * t_inv; | ||
1612 | 1638 | item->doWriteTransform(item->getRepr(), move, &move, compensate); | ||
1613 | 1639 | |||
1614 | 1640 | } else if (prefs_unmoved) { | ||
1615 | 1641 | //if (dynamic_cast<SPUse *>(sp_use_get_original(dynamic_cast<SPUse *>(item)))) | ||
1616 | 1642 | // clone_move = Geom::identity(); | ||
1617 | 1643 | Geom::Affine move = result * clone_move; | ||
1618 | 1644 | item->doWriteTransform(item->getRepr(), move, &t, compensate); | ||
1619 | 1645 | } | ||
1620 | 1646 | |||
1621 | 1647 | } else if (transform_offset_with_source && (prefs_parallel || prefs_unmoved) && affine.isTranslation()){ | ||
1622 | 1648 | Geom::Affine parent = item->transform; | ||
1623 | 1649 | Geom::Affine offset_move = parent.inverse() * t * parent; | ||
1624 | 1650 | |||
1625 | 1651 | if (prefs_parallel) { | ||
1626 | 1652 | Geom::Affine move = result * offset_move * t_inv; | ||
1627 | 1653 | item->doWriteTransform(item->getRepr(), move, &move, compensate); | ||
1628 | 1654 | |||
1629 | 1655 | } else if (prefs_unmoved) { | ||
1630 | 1656 | Geom::Affine move = result * offset_move; | ||
1631 | 1657 | item->doWriteTransform(item->getRepr(), move, &t, compensate); | ||
1632 | 1658 | } | ||
1633 | 1659 | |||
1634 | 1660 | } else { | ||
1635 | 1661 | // just apply the result | ||
1636 | 1662 | item->doWriteTransform(item->getRepr(), result, &t, compensate); | ||
1637 | 1663 | } | ||
1638 | 1664 | |||
1639 | 1665 | } else { | 1707 | } else { |
1640 | 1666 | if (set_i2d) { | 1708 | if (set_i2d) { |
1641 | 1667 | item->set_i2d_affine(item->i2dt_affine() * (Geom::Affine)affine); | 1709 | item->set_i2d_affine(item->i2dt_affine() * (Geom::Affine)affine); |
1642 | @@ -1669,7 +1711,11 @@ | |||
1643 | 1669 | item->doWriteTransform(item->getRepr(), item->transform, NULL, compensate); | 1711 | item->doWriteTransform(item->getRepr(), item->transform, NULL, compensate); |
1644 | 1670 | } | 1712 | } |
1645 | 1671 | 1713 | ||
1647 | 1672 | if (adjust_transf_center) { // The transformation center should not be touched in case of pasting or importing, which is allowed by this if clause | 1714 | // taking care of clones and linked offsets |
1648 | 1715 | prevent_clone_double_transform(selection, item, affine, compensate); | ||
1649 | 1716 | |||
1650 | 1717 | if (adjust_transf_center) { // The transformation center should not be touched in case of pasting or importing, | ||
1651 | 1718 | // which is allowed by this if clause | ||
1652 | 1673 | // if we're moving the actual object, not just updating the repr, we can transform the | 1719 | // if we're moving the actual object, not just updating the repr, we can transform the |
1653 | 1674 | // center by the same matrix (only necessary for non-translations) | 1720 | // center by the same matrix (only necessary for non-translations) |
1654 | 1675 | if (set_i2d && item->isCenterSet() && !(affine.isTranslation() || affine.isIdentity())) { | 1721 | if (set_i2d && item->isCenterSet() && !(affine.isTranslation() || affine.isIdentity())) { |
1655 | @@ -1687,35 +1733,31 @@ | |||
1656 | 1687 | 1733 | ||
1657 | 1688 | Inkscape::Selection *selection = desktop->getSelection(); | 1734 | Inkscape::Selection *selection = desktop->getSelection(); |
1658 | 1689 | 1735 | ||
1661 | 1690 | std::vector<Inkscape::XML::Node*> items = selection->reprList(); | 1736 | std::vector<Inkscape::XML::Node *> items = selection->reprList(); |
1662 | 1691 | for (std::vector<Inkscape::XML::Node*>::const_iterator l=items.begin();l!=items.end() ;l++) { | 1737 | for (std::vector<Inkscape::XML::Node *>::const_iterator l = items.begin(); l != items.end(); l++) { |
1663 | 1692 | (*l)->setAttribute("transform", NULL, false); | 1738 | (*l)->setAttribute("transform", NULL, false); |
1664 | 1693 | } | 1739 | } |
1665 | 1694 | 1740 | ||
1668 | 1695 | DocumentUndo::done(desktop->getDocument(), SP_VERB_OBJECT_FLATTEN, | 1741 | DocumentUndo::done(desktop->getDocument(), SP_VERB_OBJECT_FLATTEN, _("Remove transform")); |
1667 | 1696 | _("Remove transform")); | ||
1669 | 1697 | } | 1742 | } |
1670 | 1698 | 1743 | ||
1675 | 1699 | void | 1744 | void sp_selection_scale_absolute(Inkscape::Selection *selection, double const x0, double const x1, double const y0, |
1676 | 1700 | sp_selection_scale_absolute(Inkscape::Selection *selection, | 1745 | double const y1) |
1673 | 1701 | double const x0, double const x1, | ||
1674 | 1702 | double const y0, double const y1) | ||
1677 | 1703 | { | 1746 | { |
1678 | 1704 | if (selection->isEmpty()) | 1747 | if (selection->isEmpty()) |
1679 | 1705 | return; | 1748 | return; |
1680 | 1706 | 1749 | ||
1681 | 1707 | Geom::OptRect bbox = selection->visualBounds(); | 1750 | Geom::OptRect bbox = selection->visualBounds(); |
1683 | 1708 | if ( !bbox ) { | 1751 | if (!bbox) { |
1684 | 1709 | return; | 1752 | return; |
1685 | 1710 | } | 1753 | } |
1686 | 1711 | 1754 | ||
1687 | 1712 | Geom::Translate const p2o(-bbox->min()); | 1755 | Geom::Translate const p2o(-bbox->min()); |
1688 | 1713 | 1756 | ||
1692 | 1714 | Geom::Scale const newSize(x1 - x0, | 1757 | Geom::Scale const newSize(x1 - x0, y1 - y0); |
1693 | 1715 | y1 - y0); | 1758 | Geom::Scale const scale(newSize * Geom::Scale(bbox->dimensions()).inverse()); |
1691 | 1716 | Geom::Scale const scale( newSize * Geom::Scale(bbox->dimensions()).inverse() ); | ||
1694 | 1717 | Geom::Translate const o2n(x0, y0); | 1759 | Geom::Translate const o2n(x0, y0); |
1696 | 1718 | Geom::Affine const final( p2o * scale * o2n ); | 1760 | Geom::Affine const final(p2o * scale * o2n); |
1697 | 1719 | 1761 | ||
1698 | 1720 | sp_selection_apply_affine(selection, final); | 1762 | sp_selection_apply_affine(selection, final); |
1699 | 1721 | } | 1763 | } |
1700 | @@ -1728,42 +1770,38 @@ | |||
1701 | 1728 | 1770 | ||
1702 | 1729 | Geom::OptRect bbox = selection->visualBounds(); | 1771 | Geom::OptRect bbox = selection->visualBounds(); |
1703 | 1730 | 1772 | ||
1705 | 1731 | if ( !bbox ) { | 1773 | if (!bbox) { |
1706 | 1732 | return; | 1774 | return; |
1707 | 1733 | } | 1775 | } |
1708 | 1734 | 1776 | ||
1713 | 1735 | // FIXME: ARBITRARY LIMIT: don't try to scale above 1 Mpx, it won't display properly and will crash sooner or later anyway | 1777 | // FIXME: ARBITRARY LIMIT: don't try to scale above 1 Mpx, it won't display properly and will crash sooner or later |
1714 | 1736 | if ( bbox->dimensions()[Geom::X] * scale[Geom::X] > 1e6 || | 1778 | // anyway |
1715 | 1737 | bbox->dimensions()[Geom::Y] * scale[Geom::Y] > 1e6 ) | 1779 | if (bbox->dimensions()[Geom::X] * scale[Geom::X] > 1e6 || bbox->dimensions()[Geom::Y] * scale[Geom::Y] > 1e6) { |
1712 | 1738 | { | ||
1716 | 1739 | return; | 1780 | return; |
1717 | 1740 | } | 1781 | } |
1718 | 1741 | 1782 | ||
1719 | 1742 | Geom::Translate const n2d(-align); | 1783 | Geom::Translate const n2d(-align); |
1720 | 1743 | Geom::Translate const d2n(align); | 1784 | Geom::Translate const d2n(align); |
1722 | 1744 | Geom::Affine const final( n2d * scale * d2n ); | 1785 | Geom::Affine const final(n2d * scale * d2n); |
1723 | 1745 | sp_selection_apply_affine(selection, final); | 1786 | sp_selection_apply_affine(selection, final); |
1724 | 1746 | } | 1787 | } |
1725 | 1747 | 1788 | ||
1728 | 1748 | void | 1789 | void sp_selection_rotate_relative(Inkscape::Selection *selection, Geom::Point const ¢er, |
1729 | 1749 | sp_selection_rotate_relative(Inkscape::Selection *selection, Geom::Point const ¢er, gdouble const angle_degrees) | 1790 | gdouble const angle_degrees) |
1730 | 1750 | { | 1791 | { |
1731 | 1751 | Geom::Translate const d2n(center); | 1792 | Geom::Translate const d2n(center); |
1732 | 1752 | Geom::Translate const n2d(-center); | 1793 | Geom::Translate const n2d(-center); |
1733 | 1753 | Geom::Rotate const rotate(Geom::Rotate::from_degrees(angle_degrees)); | 1794 | Geom::Rotate const rotate(Geom::Rotate::from_degrees(angle_degrees)); |
1735 | 1754 | Geom::Affine const final( Geom::Affine(n2d) * rotate * d2n ); | 1795 | Geom::Affine const final(Geom::Affine(n2d) * rotate * d2n); |
1736 | 1755 | sp_selection_apply_affine(selection, final); | 1796 | sp_selection_apply_affine(selection, final); |
1737 | 1756 | } | 1797 | } |
1738 | 1757 | 1798 | ||
1741 | 1758 | void | 1799 | void sp_selection_skew_relative(Inkscape::Selection *selection, Geom::Point const &align, double dx, double dy) |
1740 | 1759 | sp_selection_skew_relative(Inkscape::Selection *selection, Geom::Point const &align, double dx, double dy) | ||
1742 | 1760 | { | 1800 | { |
1743 | 1761 | Geom::Translate const d2n(align); | 1801 | Geom::Translate const d2n(align); |
1744 | 1762 | Geom::Translate const n2d(-align); | 1802 | Geom::Translate const n2d(-align); |
1749 | 1763 | Geom::Affine const skew(1, dy, | 1803 | Geom::Affine const skew(1, dy, dx, 1, 0, 0); |
1750 | 1764 | dx, 1, | 1804 | Geom::Affine const final(n2d * skew * d2n); |
1747 | 1765 | 0, 0); | ||
1748 | 1766 | Geom::Affine const final( n2d * skew * d2n ); | ||
1751 | 1767 | sp_selection_apply_affine(selection, final); | 1805 | sp_selection_apply_affine(selection, final); |
1752 | 1768 | } | 1806 | } |
1753 | 1769 | 1807 | ||
1754 | @@ -1787,9 +1825,9 @@ | |||
1755 | 1787 | if (selection->isEmpty()) | 1825 | if (selection->isEmpty()) |
1756 | 1788 | return; | 1826 | return; |
1757 | 1789 | 1827 | ||
1759 | 1790 | std::vector<SPItem*> items = selection->itemList(); | 1828 | std::vector<SPItem *> items = selection->itemList(); |
1760 | 1791 | Geom::Rotate const rot_90(Geom::Point(0, ccw ? 1 : -1)); // pos. or neg. rotation, depending on the value of ccw | 1829 | Geom::Rotate const rot_90(Geom::Point(0, ccw ? 1 : -1)); // pos. or neg. rotation, depending on the value of ccw |
1762 | 1792 | for (std::vector<SPItem*>::const_iterator l=items.begin();l!=items.end() ;l++) { | 1830 | for (std::vector<SPItem *>::const_iterator l = items.begin(); l != items.end(); l++) { |
1763 | 1793 | SPItem *item = *l; | 1831 | SPItem *item = *l; |
1764 | 1794 | if (item) { | 1832 | if (item) { |
1765 | 1795 | sp_item_rotate_rel(item, rot_90); | 1833 | sp_item_rotate_rel(item, rot_90); |
1766 | @@ -1798,13 +1836,11 @@ | |||
1767 | 1798 | } | 1836 | } |
1768 | 1799 | } | 1837 | } |
1769 | 1800 | 1838 | ||
1772 | 1801 | DocumentUndo::done(desktop->getDocument(), | 1839 | DocumentUndo::done(desktop->getDocument(), ccw ? SP_VERB_OBJECT_ROTATE_90_CCW : SP_VERB_OBJECT_ROTATE_90_CW, |
1771 | 1802 | ccw ? SP_VERB_OBJECT_ROTATE_90_CCW : SP_VERB_OBJECT_ROTATE_90_CW, | ||
1773 | 1803 | ccw ? _("Rotate 90\xc2\xb0 CCW") : _("Rotate 90\xc2\xb0 CW")); | 1840 | ccw ? _("Rotate 90\xc2\xb0 CCW") : _("Rotate 90\xc2\xb0 CW")); |
1774 | 1804 | } | 1841 | } |
1775 | 1805 | 1842 | ||
1778 | 1806 | void | 1843 | void sp_selection_rotate(Inkscape::Selection *selection, gdouble const angle_degrees) |
1777 | 1807 | sp_selection_rotate(Inkscape::Selection *selection, gdouble const angle_degrees) | ||
1779 | 1808 | { | 1844 | { |
1780 | 1809 | if (selection->isEmpty()) | 1845 | if (selection->isEmpty()) |
1781 | 1810 | return; | 1846 | return; |
1782 | @@ -1817,11 +1853,8 @@ | |||
1783 | 1817 | sp_selection_rotate_relative(selection, *center, angle_degrees); | 1853 | sp_selection_rotate_relative(selection, *center, angle_degrees); |
1784 | 1818 | 1854 | ||
1785 | 1819 | DocumentUndo::maybeDone(selection->desktop()->getDocument(), | 1855 | DocumentUndo::maybeDone(selection->desktop()->getDocument(), |
1791 | 1820 | ( ( angle_degrees > 0 ) | 1856 | ((angle_degrees > 0) ? "selector:rotate:ccw" : "selector:rotate:cw"), |
1792 | 1821 | ? "selector:rotate:ccw" | 1857 | SP_VERB_CONTEXT_SELECT, _("Rotate")); |
1788 | 1822 | : "selector:rotate:cw" ), | ||
1789 | 1823 | SP_VERB_CONTEXT_SELECT, | ||
1790 | 1824 | _("Rotate")); | ||
1793 | 1825 | } | 1858 | } |
1794 | 1826 | 1859 | ||
1795 | 1827 | /* | 1860 | /* |
1796 | @@ -1846,42 +1879,39 @@ | |||
1797 | 1846 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); | 1879 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); |
1798 | 1847 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); | 1880 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); |
1799 | 1848 | bool ingroups = TRUE; | 1881 | bool ingroups = TRUE; |
1803 | 1849 | std::vector<SPItem*> x,y; | 1882 | std::vector<SPItem *> x, y; |
1804 | 1850 | std::vector<SPItem*> all_list = get_all_items(x, desktop->currentRoot(), desktop, onlyvisible, onlysensitive, ingroups, y); | 1883 | std::vector<SPItem *> all_list = |
1805 | 1851 | std::vector<SPItem*> all_matches; | 1884 | get_all_items(x, desktop->currentRoot(), desktop, onlyvisible, onlysensitive, ingroups, y); |
1806 | 1885 | std::vector<SPItem *> all_matches; | ||
1807 | 1852 | 1886 | ||
1808 | 1853 | Inkscape::Selection *selection = desktop->getSelection(); | 1887 | Inkscape::Selection *selection = desktop->getSelection(); |
1810 | 1854 | std::vector<SPItem*> items = selection->itemList(); | 1888 | std::vector<SPItem *> items = selection->itemList(); |
1811 | 1855 | 1889 | ||
1815 | 1856 | std::vector<SPItem*> tmp; | 1890 | std::vector<SPItem *> tmp; |
1816 | 1857 | for (std::vector<SPItem*>::const_iterator iter=all_list.begin();iter!=all_list.end();iter++) { | 1891 | for (std::vector<SPItem *>::const_iterator iter = all_list.begin(); iter != all_list.end(); iter++) { |
1817 | 1858 | if(!SP_IS_GROUP(*iter)){ | 1892 | if (!SP_IS_GROUP(*iter)) { |
1818 | 1859 | tmp.push_back(*iter); | 1893 | tmp.push_back(*iter); |
1819 | 1860 | } | 1894 | } |
1820 | 1861 | } | 1895 | } |
1822 | 1862 | all_list=tmp; | 1896 | all_list = tmp; |
1823 | 1863 | 1897 | ||
1825 | 1864 | for (std::vector<SPItem*>::const_iterator sel_iter=items.begin();sel_iter!=items.end();sel_iter++) { | 1898 | for (std::vector<SPItem *>::const_iterator sel_iter = items.begin(); sel_iter != items.end(); sel_iter++) { |
1826 | 1865 | SPItem *sel = *sel_iter; | 1899 | SPItem *sel = *sel_iter; |
1828 | 1866 | std::vector<SPItem*> matches = all_list; | 1900 | std::vector<SPItem *> matches = all_list; |
1829 | 1867 | if (fill && stroke && style) { | 1901 | if (fill && stroke && style) { |
1830 | 1868 | matches = sp_get_same_style(sel, matches); | 1902 | matches = sp_get_same_style(sel, matches); |
1833 | 1869 | } | 1903 | } else if (fill) { |
1832 | 1870 | else if (fill) { | ||
1834 | 1871 | matches = sp_get_same_style(sel, matches, SP_FILL_COLOR); | 1904 | matches = sp_get_same_style(sel, matches, SP_FILL_COLOR); |
1837 | 1872 | } | 1905 | } else if (stroke) { |
1836 | 1873 | else if (stroke) { | ||
1838 | 1874 | matches = sp_get_same_style(sel, matches, SP_STROKE_COLOR); | 1906 | matches = sp_get_same_style(sel, matches, SP_STROKE_COLOR); |
1844 | 1875 | } | 1907 | } else if (style) { |
1845 | 1876 | else if (style) { | 1908 | matches = sp_get_same_style(sel, matches, SP_STROKE_STYLE_ALL); |
1846 | 1877 | matches = sp_get_same_style(sel, matches,SP_STROKE_STYLE_ALL); | 1909 | } |
1847 | 1878 | } | 1910 | all_matches.insert(all_matches.end(), matches.begin(), matches.end()); |
1843 | 1879 | all_matches.insert(all_matches.end(), matches.begin(),matches.end()); | ||
1848 | 1880 | } | 1911 | } |
1849 | 1881 | 1912 | ||
1850 | 1882 | selection->clear(); | 1913 | selection->clear(); |
1851 | 1883 | selection->setList(all_matches); | 1914 | selection->setList(all_matches); |
1852 | 1884 | |||
1853 | 1885 | } | 1915 | } |
1854 | 1886 | 1916 | ||
1855 | 1887 | 1917 | ||
1856 | @@ -1902,14 +1932,15 @@ | |||
1857 | 1902 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); | 1932 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); |
1858 | 1903 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); | 1933 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); |
1859 | 1904 | bool ingroups = TRUE; | 1934 | bool ingroups = TRUE; |
1863 | 1905 | std::vector<SPItem*> x,y; | 1935 | std::vector<SPItem *> x, y; |
1864 | 1906 | std::vector<SPItem*> all_list = get_all_items(x, desktop->currentRoot(), desktop, onlyvisible, onlysensitive, ingroups, y); | 1936 | std::vector<SPItem *> all_list = |
1865 | 1907 | std::vector<SPItem*> matches = all_list; | 1937 | get_all_items(x, desktop->currentRoot(), desktop, onlyvisible, onlysensitive, ingroups, y); |
1866 | 1938 | std::vector<SPItem *> matches = all_list; | ||
1867 | 1908 | 1939 | ||
1868 | 1909 | Inkscape::Selection *selection = desktop->getSelection(); | 1940 | Inkscape::Selection *selection = desktop->getSelection(); |
1869 | 1910 | 1941 | ||
1872 | 1911 | std::vector<SPItem*> items=selection->itemList(); | 1942 | std::vector<SPItem *> items = selection->itemList(); |
1873 | 1912 | for (std::vector<SPItem*>::const_iterator sel_iter=items.begin();sel_iter!=items.end();sel_iter++) { | 1943 | for (std::vector<SPItem *>::const_iterator sel_iter = items.begin(); sel_iter != items.end(); sel_iter++) { |
1874 | 1913 | SPItem *sel = *sel_iter; | 1944 | SPItem *sel = *sel_iter; |
1875 | 1914 | if (sel) { | 1945 | if (sel) { |
1876 | 1915 | matches = sp_get_same_object_type(sel, matches); | 1946 | matches = sp_get_same_object_type(sel, matches); |
1877 | @@ -1920,7 +1951,6 @@ | |||
1878 | 1920 | 1951 | ||
1879 | 1921 | selection->clear(); | 1952 | selection->clear(); |
1880 | 1922 | selection->setList(matches); | 1953 | selection->setList(matches); |
1881 | 1923 | |||
1882 | 1924 | } | 1954 | } |
1883 | 1925 | 1955 | ||
1884 | 1926 | 1956 | ||
1885 | @@ -1929,14 +1959,15 @@ | |||
1886 | 1929 | * Find all items in src list that have the same fill or stroke style as sel | 1959 | * Find all items in src list that have the same fill or stroke style as sel |
1887 | 1930 | * Return the list of matching items | 1960 | * Return the list of matching items |
1888 | 1931 | */ | 1961 | */ |
1890 | 1932 | std::vector<SPItem*> sp_get_same_fill_or_stroke_color(SPItem *sel, std::vector<SPItem*> &src, SPSelectStrokeStyleType type) | 1962 | std::vector<SPItem *> sp_get_same_fill_or_stroke_color(SPItem *sel, std::vector<SPItem *> &src, |
1891 | 1963 | SPSelectStrokeStyleType type) | ||
1892 | 1933 | { | 1964 | { |
1894 | 1934 | std::vector<SPItem*> matches ; | 1965 | std::vector<SPItem *> matches; |
1895 | 1935 | gboolean match = false; | 1966 | gboolean match = false; |
1896 | 1936 | 1967 | ||
1897 | 1937 | SPIPaint *sel_paint = (type == SP_FILL_COLOR) ? &(sel->style->fill) : &(sel->style->stroke); | 1968 | SPIPaint *sel_paint = (type == SP_FILL_COLOR) ? &(sel->style->fill) : &(sel->style->stroke); |
1898 | 1938 | 1969 | ||
1900 | 1939 | for (std::vector<SPItem*>::const_reverse_iterator i=src.rbegin();i!=src.rend();i++) { | 1970 | for (std::vector<SPItem *>::const_reverse_iterator i = src.rbegin(); i != src.rend(); i++) { |
1901 | 1940 | SPItem *iter = *i; | 1971 | SPItem *iter = *i; |
1902 | 1941 | if (iter) { | 1972 | if (iter) { |
1903 | 1942 | SPIPaint *iter_paint = (type == SP_FILL_COLOR) ? &(iter->style->fill) : &(iter->style->stroke); | 1973 | SPIPaint *iter_paint = (type == SP_FILL_COLOR) ? &(iter->style->fill) : &(iter->style->stroke); |
1904 | @@ -1952,10 +1983,11 @@ | |||
1905 | 1952 | (type == SP_FILL_COLOR) ? iter->style->getFillPaintServer() : iter->style->getStrokePaintServer(); | 1983 | (type == SP_FILL_COLOR) ? iter->style->getFillPaintServer() : iter->style->getStrokePaintServer(); |
1906 | 1953 | 1984 | ||
1907 | 1954 | if ((dynamic_cast<SPLinearGradient *>(sel_server) || dynamic_cast<SPRadialGradient *>(sel_server) || | 1985 | if ((dynamic_cast<SPLinearGradient *>(sel_server) || dynamic_cast<SPRadialGradient *>(sel_server) || |
1910 | 1955 | (dynamic_cast<SPGradient *>(sel_server) && dynamic_cast<SPGradient *>(sel_server)->getVector()->isSwatch())) | 1986 | (dynamic_cast<SPGradient *>(sel_server) && |
1911 | 1956 | && | 1987 | dynamic_cast<SPGradient *>(sel_server)->getVector()->isSwatch())) && |
1912 | 1957 | (dynamic_cast<SPLinearGradient *>(iter_server) || dynamic_cast<SPRadialGradient *>(iter_server) || | 1988 | (dynamic_cast<SPLinearGradient *>(iter_server) || dynamic_cast<SPRadialGradient *>(iter_server) || |
1914 | 1958 | (dynamic_cast<SPGradient *>(iter_server) && dynamic_cast<SPGradient *>(iter_server)->getVector()->isSwatch()))) { | 1989 | (dynamic_cast<SPGradient *>(iter_server) && |
1915 | 1990 | dynamic_cast<SPGradient *>(iter_server)->getVector()->isSwatch()))) { | ||
1916 | 1959 | SPGradient *sel_vector = dynamic_cast<SPGradient *>(sel_server)->getVector(); | 1991 | SPGradient *sel_vector = dynamic_cast<SPGradient *>(sel_server)->getVector(); |
1917 | 1960 | SPGradient *iter_vector = dynamic_cast<SPGradient *>(iter_server)->getVector(); | 1992 | SPGradient *iter_vector = dynamic_cast<SPGradient *>(iter_server)->getVector(); |
1918 | 1961 | if (sel_vector == iter_vector) { | 1993 | if (sel_vector == iter_vector) { |
1919 | @@ -1986,16 +2018,16 @@ | |||
1920 | 1986 | return matches; | 2018 | return matches; |
1921 | 1987 | } | 2019 | } |
1922 | 1988 | 2020 | ||
1924 | 1989 | static bool item_type_match (SPItem *i, SPItem *j) | 2021 | static bool item_type_match(SPItem *i, SPItem *j) |
1925 | 1990 | { | 2022 | { |
1928 | 1991 | if ( dynamic_cast<SPRect *>(i)) { | 2023 | if (dynamic_cast<SPRect *>(i)) { |
1929 | 1992 | return ( dynamic_cast<SPRect *>(j) ); | 2024 | return (dynamic_cast<SPRect *>(j)); |
1930 | 1993 | 2025 | ||
1931 | 1994 | } else if (dynamic_cast<SPGenericEllipse *>(i)) { | 2026 | } else if (dynamic_cast<SPGenericEllipse *>(i)) { |
1932 | 1995 | return (dynamic_cast<SPGenericEllipse *>(j)); | 2027 | return (dynamic_cast<SPGenericEllipse *>(j)); |
1933 | 1996 | 2028 | ||
1934 | 1997 | } else if (dynamic_cast<SPStar *>(i) || dynamic_cast<SPPolygon *>(i)) { | 2029 | } else if (dynamic_cast<SPStar *>(i) || dynamic_cast<SPPolygon *>(i)) { |
1936 | 1998 | return (dynamic_cast<SPStar *>(j) || dynamic_cast<SPPolygon *>(j)) ; | 2030 | return (dynamic_cast<SPStar *>(j) || dynamic_cast<SPPolygon *>(j)); |
1937 | 1999 | 2031 | ||
1938 | 2000 | } else if (dynamic_cast<SPSpiral *>(i)) { | 2032 | } else if (dynamic_cast<SPSpiral *>(i)) { |
1939 | 2001 | return (dynamic_cast<SPSpiral *>(j)); | 2033 | return (dynamic_cast<SPSpiral *>(j)); |
1940 | @@ -2003,21 +2035,22 @@ | |||
1941 | 2003 | } else if (dynamic_cast<SPPath *>(i) || dynamic_cast<SPLine *>(i) || dynamic_cast<SPPolyLine *>(i)) { | 2035 | } else if (dynamic_cast<SPPath *>(i) || dynamic_cast<SPLine *>(i) || dynamic_cast<SPPolyLine *>(i)) { |
1942 | 2004 | return (dynamic_cast<SPPath *>(j) || dynamic_cast<SPLine *>(j) || dynamic_cast<SPPolyLine *>(j)); | 2036 | return (dynamic_cast<SPPath *>(j) || dynamic_cast<SPLine *>(j) || dynamic_cast<SPPolyLine *>(j)); |
1943 | 2005 | 2037 | ||
1946 | 2006 | } else if (dynamic_cast<SPText *>(i) || dynamic_cast<SPFlowtext *>(i) || dynamic_cast<SPTSpan *>(i) || dynamic_cast<SPTRef *>(i) || dynamic_cast<SPString *>(i)) { | 2038 | } else if (dynamic_cast<SPText *>(i) || dynamic_cast<SPFlowtext *>(i) || dynamic_cast<SPTSpan *>(i) || |
1947 | 2007 | return (dynamic_cast<SPText *>(j) || dynamic_cast<SPFlowtext *>(j) || dynamic_cast<SPTSpan *>(j) || dynamic_cast<SPTRef *>(j) || dynamic_cast<SPString *>(j)); | 2039 | dynamic_cast<SPTRef *>(i) || dynamic_cast<SPString *>(i)) { |
1948 | 2040 | return (dynamic_cast<SPText *>(j) || dynamic_cast<SPFlowtext *>(j) || dynamic_cast<SPTSpan *>(j) || | ||
1949 | 2041 | dynamic_cast<SPTRef *>(j) || dynamic_cast<SPString *>(j)); | ||
1950 | 2008 | 2042 | ||
1953 | 2009 | } else if (dynamic_cast<SPUse *>(i)) { | 2043 | } else if (dynamic_cast<SPUse *>(i)) { |
1954 | 2010 | return (dynamic_cast<SPUse *>(j)) ; | 2044 | return (dynamic_cast<SPUse *>(j)); |
1955 | 2011 | 2045 | ||
1956 | 2012 | } else if (dynamic_cast<SPImage *>(i)) { | 2046 | } else if (dynamic_cast<SPImage *>(i)) { |
1957 | 2013 | return (dynamic_cast<SPImage *>(j)); | 2047 | return (dynamic_cast<SPImage *>(j)); |
1958 | 2014 | 2048 | ||
1960 | 2015 | } else if (dynamic_cast<SPOffset *>(i) && dynamic_cast<SPOffset *>(i)->sourceHref) { // Linked offset | 2049 | } else if (dynamic_cast<SPOffset *>(i) && dynamic_cast<SPOffset *>(i)->sourceHref) { // Linked offset |
1961 | 2016 | return (dynamic_cast<SPOffset *>(j) && dynamic_cast<SPOffset *>(j)->sourceHref); | 2050 | return (dynamic_cast<SPOffset *>(j) && dynamic_cast<SPOffset *>(j)->sourceHref); |
1962 | 2017 | 2051 | ||
1964 | 2018 | } else if (dynamic_cast<SPOffset *>(i) && !dynamic_cast<SPOffset *>(i)->sourceHref) { // Dynamic offset | 2052 | } else if (dynamic_cast<SPOffset *>(i) && !dynamic_cast<SPOffset *>(i)->sourceHref) { // Dynamic offset |
1965 | 2019 | return (dynamic_cast<SPOffset *>(j) && !dynamic_cast<SPOffset *>(j)->sourceHref); | 2053 | return (dynamic_cast<SPOffset *>(j) && !dynamic_cast<SPOffset *>(j)->sourceHref); |
1966 | 2020 | |||
1967 | 2021 | } | 2054 | } |
1968 | 2022 | 2055 | ||
1969 | 2023 | return false; | 2056 | return false; |
1970 | @@ -2027,11 +2060,11 @@ | |||
1971 | 2027 | * Find all items in src list that have the same object type as sel by type | 2060 | * Find all items in src list that have the same object type as sel by type |
1972 | 2028 | * Return the list of matching items | 2061 | * Return the list of matching items |
1973 | 2029 | */ | 2062 | */ |
1975 | 2030 | std::vector<SPItem*> sp_get_same_object_type(SPItem *sel, std::vector<SPItem*> &src) | 2063 | std::vector<SPItem *> sp_get_same_object_type(SPItem *sel, std::vector<SPItem *> &src) |
1976 | 2031 | { | 2064 | { |
1978 | 2032 | std::vector<SPItem*> matches; | 2065 | std::vector<SPItem *> matches; |
1979 | 2033 | 2066 | ||
1981 | 2034 | for (std::vector<SPItem*>::const_reverse_iterator i=src.rbegin();i!=src.rend();i++) { | 2067 | for (std::vector<SPItem *>::const_reverse_iterator i = src.rbegin(); i != src.rend(); i++) { |
1982 | 2035 | SPItem *item = *i; | 2068 | SPItem *item = *i; |
1983 | 2036 | if (item && item_type_match(sel, item) && !item->cloned) { | 2069 | if (item && item_type_match(sel, item) && !item->cloned) { |
1984 | 2037 | matches.push_back(item); | 2070 | matches.push_back(item); |
1985 | @@ -2046,9 +2079,9 @@ | |||
1986 | 2046 | * Find all items in src list that have the same stroke style as sel by type | 2079 | * Find all items in src list that have the same stroke style as sel by type |
1987 | 2047 | * Return the list of matching items | 2080 | * Return the list of matching items |
1988 | 2048 | */ | 2081 | */ |
1990 | 2049 | std::vector<SPItem*> sp_get_same_style(SPItem *sel, std::vector<SPItem*> &src, SPSelectStrokeStyleType type) | 2082 | std::vector<SPItem *> sp_get_same_style(SPItem *sel, std::vector<SPItem *> &src, SPSelectStrokeStyleType type) |
1991 | 2050 | { | 2083 | { |
1993 | 2051 | std::vector<SPItem*> matches; | 2084 | std::vector<SPItem *> matches; |
1994 | 2052 | bool match = false; | 2085 | bool match = false; |
1995 | 2053 | 2086 | ||
1996 | 2054 | SPStyle *sel_style = sel->style; | 2087 | SPStyle *sel_style = sel->style; |
1997 | @@ -2064,28 +2097,28 @@ | |||
1998 | 2064 | * Stroke width needs to handle transformations, so call this function | 2097 | * Stroke width needs to handle transformations, so call this function |
1999 | 2065 | * to get the transformed stroke width | 2098 | * to get the transformed stroke width |
2000 | 2066 | */ | 2099 | */ |
2002 | 2067 | std::vector<SPItem*> objects; | 2100 | std::vector<SPItem *> objects; |
2003 | 2068 | SPStyle *sel_style_for_width = NULL; | 2101 | SPStyle *sel_style_for_width = NULL; |
2005 | 2069 | if (type == SP_STROKE_STYLE_WIDTH || type == SP_STROKE_STYLE_ALL || type==SP_STYLE_ALL ) { | 2102 | if (type == SP_STROKE_STYLE_WIDTH || type == SP_STROKE_STYLE_ALL || type == SP_STYLE_ALL) { |
2006 | 2070 | objects.push_back(sel); | 2103 | objects.push_back(sel); |
2007 | 2071 | sel_style_for_width = new SPStyle(SP_ACTIVE_DOCUMENT); | 2104 | sel_style_for_width = new SPStyle(SP_ACTIVE_DOCUMENT); |
2009 | 2072 | objects_query_strokewidth (objects, sel_style_for_width); | 2105 | objects_query_strokewidth(objects, sel_style_for_width); |
2010 | 2073 | } | 2106 | } |
2011 | 2074 | bool match_g; | 2107 | bool match_g; |
2013 | 2075 | for (std::vector<SPItem*>::const_iterator i=src.begin();i!=src.end();i++) { | 2108 | for (std::vector<SPItem *>::const_iterator i = src.begin(); i != src.end(); i++) { |
2014 | 2076 | SPItem *iter = *i; | 2109 | SPItem *iter = *i; |
2015 | 2077 | if (iter) { | 2110 | if (iter) { |
2017 | 2078 | match_g=true; | 2111 | match_g = true; |
2018 | 2079 | SPStyle *iter_style = iter->style; | 2112 | SPStyle *iter_style = iter->style; |
2019 | 2080 | match = true; | 2113 | match = true; |
2020 | 2081 | 2114 | ||
2022 | 2082 | if (type == SP_STROKE_STYLE_WIDTH|| type == SP_STROKE_STYLE_ALL|| type==SP_STYLE_ALL) { | 2115 | if (type == SP_STROKE_STYLE_WIDTH || type == SP_STROKE_STYLE_ALL || type == SP_STYLE_ALL) { |
2023 | 2083 | match = (sel_style->stroke_width.set == iter_style->stroke_width.set); | 2116 | match = (sel_style->stroke_width.set == iter_style->stroke_width.set); |
2024 | 2084 | if (sel_style->stroke_width.set && iter_style->stroke_width.set) { | 2117 | if (sel_style->stroke_width.set && iter_style->stroke_width.set) { |
2027 | 2085 | std::vector<SPItem*> objects; | 2118 | std::vector<SPItem *> objects; |
2028 | 2086 | objects.insert(objects.begin(),iter); | 2119 | objects.insert(objects.begin(), iter); |
2029 | 2087 | SPStyle tmp_style(SP_ACTIVE_DOCUMENT); | 2120 | SPStyle tmp_style(SP_ACTIVE_DOCUMENT); |
2031 | 2088 | objects_query_strokewidth (objects, &tmp_style); | 2121 | objects_query_strokewidth(objects, &tmp_style); |
2032 | 2089 | 2122 | ||
2033 | 2090 | if (sel_style_for_width) { | 2123 | if (sel_style_for_width) { |
2034 | 2091 | match = (sel_style_for_width->stroke_width.computed == tmp_style.stroke_width.computed); | 2124 | match = (sel_style_for_width->stroke_width.computed == tmp_style.stroke_width.computed); |
2035 | @@ -2093,16 +2126,16 @@ | |||
2036 | 2093 | } | 2126 | } |
2037 | 2094 | } | 2127 | } |
2038 | 2095 | match_g = match_g && match; | 2128 | match_g = match_g && match; |
2040 | 2096 | if (type == SP_STROKE_STYLE_DASHES|| type == SP_STROKE_STYLE_ALL || type==SP_STYLE_ALL) { | 2129 | if (type == SP_STROKE_STYLE_DASHES || type == SP_STROKE_STYLE_ALL || type == SP_STYLE_ALL) { |
2041 | 2097 | match = (sel_style->stroke_dasharray.set == iter_style->stroke_dasharray.set); | 2130 | match = (sel_style->stroke_dasharray.set == iter_style->stroke_dasharray.set); |
2042 | 2098 | if (sel_style->stroke_dasharray.set && iter_style->stroke_dasharray.set) { | 2131 | if (sel_style->stroke_dasharray.set && iter_style->stroke_dasharray.set) { |
2043 | 2099 | match = (sel_style->stroke_dasharray.values == iter_style->stroke_dasharray.values); | 2132 | match = (sel_style->stroke_dasharray.values == iter_style->stroke_dasharray.values); |
2044 | 2100 | } | 2133 | } |
2045 | 2101 | } | 2134 | } |
2046 | 2102 | match_g = match_g && match; | 2135 | match_g = match_g && match; |
2048 | 2103 | if (type == SP_STROKE_STYLE_MARKERS|| type == SP_STROKE_STYLE_ALL|| type==SP_STYLE_ALL) { | 2136 | if (type == SP_STROKE_STYLE_MARKERS || type == SP_STROKE_STYLE_ALL || type == SP_STYLE_ALL) { |
2049 | 2104 | match = true; | 2137 | match = true; |
2051 | 2105 | int len = sizeof(sel_style->marker)/sizeof(SPIString); | 2138 | int len = sizeof(sel_style->marker) / sizeof(SPIString); |
2052 | 2106 | for (int i = 0; i < len; i++) { | 2139 | for (int i = 0; i < len; i++) { |
2053 | 2107 | match = (sel_style->marker_ptrs[i]->set == iter_style->marker_ptrs[i]->set); | 2140 | match = (sel_style->marker_ptrs[i]->set == iter_style->marker_ptrs[i]->set); |
2054 | 2108 | if (sel_style->marker_ptrs[i]->set && iter_style->marker_ptrs[i]->set && | 2141 | if (sel_style->marker_ptrs[i]->set && iter_style->marker_ptrs[i]->set && |
2055 | @@ -2112,24 +2145,25 @@ | |||
2056 | 2112 | } | 2145 | } |
2057 | 2113 | } | 2146 | } |
2058 | 2114 | } | 2147 | } |
2060 | 2115 | match_g = match_g && match; | 2148 | match_g = match_g && match; |
2061 | 2116 | if (match_g) { | 2149 | if (match_g) { |
2064 | 2117 | while (iter->cloned) iter=dynamic_cast<SPItem *>(iter->parent); | 2150 | while (iter->cloned) |
2065 | 2118 | matches.insert(matches.begin(),iter); | 2151 | iter = dynamic_cast<SPItem *>(iter->parent); |
2066 | 2152 | matches.insert(matches.begin(), iter); | ||
2067 | 2119 | } | 2153 | } |
2068 | 2120 | } else { | 2154 | } else { |
2069 | 2121 | g_assert_not_reached(); | 2155 | g_assert_not_reached(); |
2070 | 2122 | } | 2156 | } |
2071 | 2123 | } | 2157 | } |
2072 | 2124 | 2158 | ||
2074 | 2125 | if( sel_style_for_width != NULL ) delete sel_style_for_width; | 2159 | if (sel_style_for_width != NULL) |
2075 | 2160 | delete sel_style_for_width; | ||
2076 | 2126 | return matches; | 2161 | return matches; |
2077 | 2127 | } | 2162 | } |
2078 | 2128 | 2163 | ||
2079 | 2129 | // helper function: | 2164 | // helper function: |
2083 | 2130 | static | 2165 | static Geom::Point cornerFarthestFrom(Geom::Rect const &r, Geom::Point const &p) |
2084 | 2131 | Geom::Point | 2166 | { |
2082 | 2132 | cornerFarthestFrom(Geom::Rect const &r, Geom::Point const &p){ | ||
2085 | 2133 | Geom::Point m = r.midpoint(); | 2167 | Geom::Point m = r.midpoint(); |
2086 | 2134 | unsigned i = 0; | 2168 | unsigned i = 0; |
2087 | 2135 | if (p[X] < m[X]) { | 2169 | if (p[X] < m[X]) { |
2088 | @@ -2142,10 +2176,10 @@ | |||
2089 | 2142 | } | 2176 | } |
2090 | 2143 | 2177 | ||
2091 | 2144 | /** | 2178 | /** |
2093 | 2145 | \param angle the angle in "angular pixels", i.e. how many visible pixels must move the outermost point of the rotated object | 2179 | \param angle the angle in "angular pixels", i.e. how many visible pixels must move the outermost point of the rotated |
2094 | 2180 | object | ||
2095 | 2146 | */ | 2181 | */ |
2098 | 2147 | void | 2182 | void sp_selection_rotate_screen(Inkscape::Selection *selection, gdouble angle) |
2097 | 2148 | sp_selection_rotate_screen(Inkscape::Selection *selection, gdouble angle) | ||
2099 | 2149 | { | 2183 | { |
2100 | 2150 | if (selection->isEmpty()) | 2184 | if (selection->isEmpty()) |
2101 | 2151 | return; | 2185 | return; |
2102 | @@ -2153,7 +2187,7 @@ | |||
2103 | 2153 | Geom::OptRect bbox = selection->visualBounds(); | 2187 | Geom::OptRect bbox = selection->visualBounds(); |
2104 | 2154 | boost::optional<Geom::Point> center = selection->center(); | 2188 | boost::optional<Geom::Point> center = selection->center(); |
2105 | 2155 | 2189 | ||
2107 | 2156 | if ( !bbox || !center ) { | 2190 | if (!bbox || !center) { |
2108 | 2157 | return; | 2191 | return; |
2109 | 2158 | } | 2192 | } |
2110 | 2159 | 2193 | ||
2111 | @@ -2166,15 +2200,11 @@ | |||
2112 | 2166 | sp_selection_rotate_relative(selection, *center, zangle); | 2200 | sp_selection_rotate_relative(selection, *center, zangle); |
2113 | 2167 | 2201 | ||
2114 | 2168 | DocumentUndo::maybeDone(selection->desktop()->getDocument(), | 2202 | DocumentUndo::maybeDone(selection->desktop()->getDocument(), |
2119 | 2169 | ( (angle > 0) | 2203 | ((angle > 0) ? "selector:rotate:ccw" : "selector:rotate:cw"), SP_VERB_CONTEXT_SELECT, |
2116 | 2170 | ? "selector:rotate:ccw" | ||
2117 | 2171 | : "selector:rotate:cw" ), | ||
2118 | 2172 | SP_VERB_CONTEXT_SELECT, | ||
2120 | 2173 | _("Rotate by pixels")); | 2204 | _("Rotate by pixels")); |
2121 | 2174 | } | 2205 | } |
2122 | 2175 | 2206 | ||
2125 | 2176 | void | 2207 | void sp_selection_scale(Inkscape::Selection *selection, gdouble grow) |
2124 | 2177 | sp_selection_scale(Inkscape::Selection *selection, gdouble grow) | ||
2126 | 2178 | { | 2208 | { |
2127 | 2179 | if (selection->isEmpty()) | 2209 | if (selection->isEmpty()) |
2128 | 2180 | return; | 2210 | return; |
2129 | @@ -2188,7 +2218,7 @@ | |||
2130 | 2188 | 2218 | ||
2131 | 2189 | // you can't scale "do nizhe pola" (below zero) | 2219 | // you can't scale "do nizhe pola" (below zero) |
2132 | 2190 | double const max_len = bbox->maxExtent(); | 2220 | double const max_len = bbox->maxExtent(); |
2134 | 2191 | if ( max_len + grow <= 1e-3 ) { | 2221 | if (max_len + grow <= 1e-3) { |
2135 | 2192 | return; | 2222 | return; |
2136 | 2193 | } | 2223 | } |
2137 | 2194 | 2224 | ||
2138 | @@ -2196,22 +2226,16 @@ | |||
2139 | 2196 | sp_selection_scale_relative(selection, center, Geom::Scale(times, times)); | 2226 | sp_selection_scale_relative(selection, center, Geom::Scale(times, times)); |
2140 | 2197 | 2227 | ||
2141 | 2198 | DocumentUndo::maybeDone(selection->desktop()->getDocument(), | 2228 | DocumentUndo::maybeDone(selection->desktop()->getDocument(), |
2146 | 2199 | ( (grow > 0) | 2229 | ((grow > 0) ? "selector:scale:larger" : "selector:scale:smaller"), SP_VERB_CONTEXT_SELECT, |
2143 | 2200 | ? "selector:scale:larger" | ||
2144 | 2201 | : "selector:scale:smaller" ), | ||
2145 | 2202 | SP_VERB_CONTEXT_SELECT, | ||
2147 | 2203 | _("Scale")); | 2230 | _("Scale")); |
2148 | 2204 | } | 2231 | } |
2149 | 2205 | 2232 | ||
2152 | 2206 | void | 2233 | void sp_selection_scale_screen(Inkscape::Selection *selection, gdouble grow_pixels) |
2151 | 2207 | sp_selection_scale_screen(Inkscape::Selection *selection, gdouble grow_pixels) | ||
2153 | 2208 | { | 2234 | { |
2156 | 2209 | sp_selection_scale(selection, | 2235 | sp_selection_scale(selection, grow_pixels / selection->desktop()->current_zoom()); |
2155 | 2210 | grow_pixels / selection->desktop()->current_zoom()); | ||
2157 | 2211 | } | 2236 | } |
2158 | 2212 | 2237 | ||
2161 | 2213 | void | 2238 | void sp_selection_scale_times(Inkscape::Selection *selection, gdouble times) |
2160 | 2214 | sp_selection_scale_times(Inkscape::Selection *selection, gdouble times) | ||
2162 | 2215 | { | 2239 | { |
2163 | 2216 | if (selection->isEmpty()) | 2240 | if (selection->isEmpty()) |
2164 | 2217 | return; | 2241 | return; |
2165 | @@ -2224,12 +2248,10 @@ | |||
2166 | 2224 | 2248 | ||
2167 | 2225 | Geom::Point const center(sel_bbox->midpoint()); | 2249 | Geom::Point const center(sel_bbox->midpoint()); |
2168 | 2226 | sp_selection_scale_relative(selection, center, Geom::Scale(times, times)); | 2250 | sp_selection_scale_relative(selection, center, Geom::Scale(times, times)); |
2171 | 2227 | DocumentUndo::done(selection->desktop()->getDocument(), SP_VERB_CONTEXT_SELECT, | 2251 | DocumentUndo::done(selection->desktop()->getDocument(), SP_VERB_CONTEXT_SELECT, _("Scale by whole factor")); |
2170 | 2228 | _("Scale by whole factor")); | ||
2172 | 2229 | } | 2252 | } |
2173 | 2230 | 2253 | ||
2176 | 2231 | void | 2254 | void sp_selection_move(Inkscape::Selection *selection, gdouble dx, gdouble dy) |
2175 | 2232 | sp_selection_move(Inkscape::Selection *selection, gdouble dx, gdouble dy) | ||
2177 | 2233 | { | 2255 | { |
2178 | 2234 | if (selection->isEmpty()) { | 2256 | if (selection->isEmpty()) { |
2179 | 2235 | return; | 2257 | return; |
2180 | @@ -2239,19 +2261,15 @@ | |||
2181 | 2239 | 2261 | ||
2182 | 2240 | SPDocument *doc = selection->layers()->getDocument(); | 2262 | SPDocument *doc = selection->layers()->getDocument(); |
2183 | 2241 | if (dx == 0) { | 2263 | if (dx == 0) { |
2186 | 2242 | DocumentUndo::maybeDone(doc, "selector:move:vertical", SP_VERB_CONTEXT_SELECT, | 2264 | DocumentUndo::maybeDone(doc, "selector:move:vertical", SP_VERB_CONTEXT_SELECT, _("Move vertically")); |
2185 | 2243 | _("Move vertically")); | ||
2187 | 2244 | } else if (dy == 0) { | 2265 | } else if (dy == 0) { |
2190 | 2245 | DocumentUndo::maybeDone(doc, "selector:move:horizontal", SP_VERB_CONTEXT_SELECT, | 2266 | DocumentUndo::maybeDone(doc, "selector:move:horizontal", SP_VERB_CONTEXT_SELECT, _("Move horizontally")); |
2189 | 2246 | _("Move horizontally")); | ||
2191 | 2247 | } else { | 2267 | } else { |
2194 | 2248 | DocumentUndo::done(doc, SP_VERB_CONTEXT_SELECT, | 2268 | DocumentUndo::done(doc, SP_VERB_CONTEXT_SELECT, _("Move")); |
2193 | 2249 | _("Move")); | ||
2195 | 2250 | } | 2269 | } |
2196 | 2251 | } | 2270 | } |
2197 | 2252 | 2271 | ||
2200 | 2253 | void | 2272 | void sp_selection_move_screen(Inkscape::Selection *selection, gdouble dx, gdouble dy) |
2199 | 2254 | sp_selection_move_screen(Inkscape::Selection *selection, gdouble dx, gdouble dy) | ||
2201 | 2255 | { | 2273 | { |
2202 | 2256 | if (selection->isEmpty() || !selection->desktop()) { | 2274 | if (selection->isEmpty() || !selection->desktop()) { |
2203 | 2257 | return; | 2275 | return; |
2204 | @@ -2265,14 +2283,12 @@ | |||
2205 | 2265 | 2283 | ||
2206 | 2266 | SPDocument *doc = selection->layers()->getDocument(); | 2284 | SPDocument *doc = selection->layers()->getDocument(); |
2207 | 2267 | if (dx == 0) { | 2285 | if (dx == 0) { |
2210 | 2268 | DocumentUndo::maybeDone(doc, "selector:move:vertical", SP_VERB_CONTEXT_SELECT, | 2286 | DocumentUndo::maybeDone(doc, "selector:move:vertical", SP_VERB_CONTEXT_SELECT, _("Move vertically by pixels")); |
2209 | 2269 | _("Move vertically by pixels")); | ||
2211 | 2270 | } else if (dy == 0) { | 2287 | } else if (dy == 0) { |
2212 | 2271 | DocumentUndo::maybeDone(doc, "selector:move:horizontal", SP_VERB_CONTEXT_SELECT, | 2288 | DocumentUndo::maybeDone(doc, "selector:move:horizontal", SP_VERB_CONTEXT_SELECT, |
2213 | 2272 | _("Move horizontally by pixels")); | 2289 | _("Move horizontally by pixels")); |
2214 | 2273 | } else { | 2290 | } else { |
2217 | 2274 | DocumentUndo::done(doc, SP_VERB_CONTEXT_SELECT, | 2291 | DocumentUndo::done(doc, SP_VERB_CONTEXT_SELECT, _("Move")); |
2216 | 2275 | _("Move")); | ||
2218 | 2276 | } | 2292 | } |
2219 | 2277 | } | 2293 | } |
2220 | 2278 | 2294 | ||
2221 | @@ -2292,25 +2308,18 @@ | |||
2222 | 2292 | typedef struct ListReverse { | 2308 | typedef struct ListReverse { |
2223 | 2293 | typedef GSList *Iterator; | 2309 | typedef GSList *Iterator; |
2224 | 2294 | 2310 | ||
2234 | 2295 | static Iterator children(SPObject *o) { | 2311 | static Iterator children(SPObject *o) { return make_list(o->firstChild(), NULL); } |
2235 | 2296 | return make_list(o->firstChild(), NULL); | 2312 | static Iterator siblings_after(SPObject *o) { return make_list(o->parent->firstChild(), o); } |
2236 | 2297 | } | 2313 | static void dispose(Iterator i) { g_slist_free(i); } |
2228 | 2298 | static Iterator siblings_after(SPObject *o) { | ||
2229 | 2299 | return make_list(o->parent->firstChild(), o); | ||
2230 | 2300 | } | ||
2231 | 2301 | static void dispose(Iterator i) { | ||
2232 | 2302 | g_slist_free(i); | ||
2233 | 2303 | } | ||
2237 | 2304 | 2314 | ||
2241 | 2305 | static SPObject *object(Iterator i) { | 2315 | static SPObject *object(Iterator i) { return reinterpret_cast<SPObject *>(i->data); } |
2239 | 2306 | return reinterpret_cast<SPObject *>(i->data); | ||
2240 | 2307 | } | ||
2242 | 2308 | static Iterator next(Iterator i) { return i->next; } | 2316 | static Iterator next(Iterator i) { return i->next; } |
2243 | 2309 | 2317 | ||
2246 | 2310 | private: | 2318 | private: |
2247 | 2311 | static GSList *make_list(SPObject *object, SPObject *limit) { | 2319 | static GSList *make_list(SPObject *object, SPObject *limit) |
2248 | 2320 | { | ||
2249 | 2312 | GSList *list = NULL; | 2321 | GSList *list = NULL; |
2251 | 2313 | while ( object != limit ) { | 2322 | while (object != limit) { |
2252 | 2314 | if (!object) { // TODO check if this happens in practice | 2323 | if (!object) { // TODO check if this happens in practice |
2253 | 2315 | g_warning("Unexpected list overrun"); | 2324 | g_warning("Unexpected list overrun"); |
2254 | 2316 | break; | 2325 | break; |
2255 | @@ -2325,16 +2334,16 @@ | |||
2256 | 2325 | 2334 | ||
2257 | 2326 | 2335 | ||
2258 | 2327 | template <typename D> | 2336 | template <typename D> |
2261 | 2328 | SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root, | 2337 | SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root, bool only_in_viewport, |
2262 | 2329 | bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive) | 2338 | PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive) |
2263 | 2330 | { | 2339 | { |
2264 | 2331 | typename D::Iterator children; | 2340 | typename D::Iterator children; |
2265 | 2332 | typename D::Iterator iter; | 2341 | typename D::Iterator iter; |
2266 | 2333 | 2342 | ||
2268 | 2334 | SPItem *found=NULL; | 2343 | SPItem *found = NULL; |
2269 | 2335 | 2344 | ||
2270 | 2336 | if (path) { | 2345 | if (path) { |
2272 | 2337 | SPObject *object=reinterpret_cast<SPObject *>(path->data); | 2346 | SPObject *object = reinterpret_cast<SPObject *>(path->data); |
2273 | 2338 | g_assert(object->parent == root); | 2347 | g_assert(object->parent == root); |
2274 | 2339 | if (desktop->isLayer(object)) { | 2348 | if (desktop->isLayer(object)) { |
2275 | 2340 | found = next_item<D>(desktop, path->next, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); | 2349 | found = next_item<D>(desktop, path->next, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); |
2276 | @@ -2344,20 +2353,17 @@ | |||
2277 | 2344 | iter = children = D::children(root); | 2353 | iter = children = D::children(root); |
2278 | 2345 | } | 2354 | } |
2279 | 2346 | 2355 | ||
2282 | 2347 | while ( iter && !found ) { | 2356 | while (iter && !found) { |
2283 | 2348 | SPObject *object=D::object(iter); | 2357 | SPObject *object = D::object(iter); |
2284 | 2349 | if (desktop->isLayer(object)) { | 2358 | if (desktop->isLayer(object)) { |
2285 | 2350 | if (PREFS_SELECTION_LAYER != inlayer) { // recurse into sublayers | 2359 | if (PREFS_SELECTION_LAYER != inlayer) { // recurse into sublayers |
2286 | 2351 | found = next_item<D>(desktop, NULL, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); | 2360 | found = next_item<D>(desktop, NULL, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); |
2287 | 2352 | } | 2361 | } |
2288 | 2353 | } else { | 2362 | } else { |
2289 | 2354 | SPItem *item = dynamic_cast<SPItem *>(object); | 2363 | SPItem *item = dynamic_cast<SPItem *>(object); |
2296 | 2355 | if ( item && | 2364 | if (item && (!only_in_viewport || desktop->isWithinViewport(item)) && |
2297 | 2356 | ( !only_in_viewport || desktop->isWithinViewport(item) ) && | 2365 | (!onlyvisible || !desktop->itemIsHidden(item)) && (!onlysensitive || !item->isLocked()) && |
2298 | 2357 | ( !onlyvisible || !desktop->itemIsHidden(item)) && | 2366 | !desktop->isLayer(item)) { |
2293 | 2358 | ( !onlysensitive || !item->isLocked()) && | ||
2294 | 2359 | !desktop->isLayer(item) ) | ||
2295 | 2360 | { | ||
2299 | 2361 | found = item; | 2367 | found = item; |
2300 | 2362 | } | 2368 | } |
2301 | 2363 | } | 2369 | } |
2302 | @@ -2371,22 +2377,20 @@ | |||
2303 | 2371 | 2377 | ||
2304 | 2372 | 2378 | ||
2305 | 2373 | template <typename D> | 2379 | template <typename D> |
2308 | 2374 | SPItem *next_item_from_list(SPDesktop *desktop, std::vector<SPItem*> const items, | 2380 | SPItem *next_item_from_list(SPDesktop *desktop, std::vector<SPItem *> const items, SPObject *root, |
2309 | 2375 | SPObject *root, bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive) | 2381 | bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive) |
2310 | 2376 | { | 2382 | { |
2313 | 2377 | SPObject *current=root; | 2383 | SPObject *current = root; |
2314 | 2378 | for(std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();i++) { | 2384 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2315 | 2379 | SPItem *item = *i; | 2385 | SPItem *item = *i; |
2319 | 2380 | if ( root->isAncestorOf(item) && | 2386 | if (root->isAncestorOf(item) && (!only_in_viewport || desktop->isWithinViewport(item))) { |
2317 | 2381 | ( !only_in_viewport || desktop->isWithinViewport(item) ) ) | ||
2318 | 2382 | { | ||
2320 | 2383 | current = item; | 2387 | current = item; |
2321 | 2384 | break; | 2388 | break; |
2322 | 2385 | } | 2389 | } |
2323 | 2386 | } | 2390 | } |
2324 | 2387 | 2391 | ||
2327 | 2388 | GSList *path=NULL; | 2392 | GSList *path = NULL; |
2328 | 2389 | while ( current != root ) { | 2393 | while (current != root) { |
2329 | 2390 | path = g_slist_prepend(path, current); | 2394 | path = g_slist_prepend(path, current); |
2330 | 2391 | current = current->parent; | 2395 | current = current->parent; |
2331 | 2392 | } | 2396 | } |
2332 | @@ -2403,14 +2407,14 @@ | |||
2333 | 2403 | return next; | 2407 | return next; |
2334 | 2404 | } | 2408 | } |
2335 | 2405 | 2409 | ||
2338 | 2406 | void | 2410 | void sp_selection_item_next(SPDesktop *desktop) |
2337 | 2407 | sp_selection_item_next(SPDesktop *desktop) | ||
2339 | 2408 | { | 2411 | { |
2340 | 2409 | g_return_if_fail(desktop != NULL); | 2412 | g_return_if_fail(desktop != NULL); |
2341 | 2410 | Inkscape::Selection *selection = desktop->getSelection(); | 2413 | Inkscape::Selection *selection = desktop->getSelection(); |
2342 | 2411 | 2414 | ||
2343 | 2412 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); | 2415 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
2345 | 2413 | PrefsSelectionContext inlayer = (PrefsSelectionContext)prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER); | 2416 | PrefsSelectionContext inlayer = |
2346 | 2417 | (PrefsSelectionContext)prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER); | ||
2347 | 2414 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); | 2418 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); |
2348 | 2415 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); | 2419 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); |
2349 | 2416 | 2420 | ||
2350 | @@ -2421,18 +2425,18 @@ | |||
2351 | 2421 | root = desktop->currentRoot(); | 2425 | root = desktop->currentRoot(); |
2352 | 2422 | } | 2426 | } |
2353 | 2423 | 2427 | ||
2355 | 2424 | SPItem *item=next_item_from_list<Forward>(desktop, selection->itemList(), root, SP_CYCLING == SP_CYCLE_VISIBLE, inlayer, onlyvisible, onlysensitive); | 2428 | SPItem *item = next_item_from_list<Forward>(desktop, selection->itemList(), root, SP_CYCLING == SP_CYCLE_VISIBLE, |
2356 | 2429 | inlayer, onlyvisible, onlysensitive); | ||
2357 | 2425 | 2430 | ||
2358 | 2426 | if (item) { | 2431 | if (item) { |
2359 | 2427 | selection->set(item, PREFS_SELECTION_LAYER_RECURSIVE == inlayer); | 2432 | selection->set(item, PREFS_SELECTION_LAYER_RECURSIVE == inlayer); |
2361 | 2428 | if ( SP_CYCLING == SP_CYCLE_FOCUS ) { | 2433 | if (SP_CYCLING == SP_CYCLE_FOCUS) { |
2362 | 2429 | scroll_to_show_item(desktop, item); | 2434 | scroll_to_show_item(desktop, item); |
2363 | 2430 | } | 2435 | } |
2364 | 2431 | } | 2436 | } |
2365 | 2432 | } | 2437 | } |
2366 | 2433 | 2438 | ||
2369 | 2434 | void | 2439 | void sp_selection_item_prev(SPDesktop *desktop) |
2368 | 2435 | sp_selection_item_prev(SPDesktop *desktop) | ||
2370 | 2436 | { | 2440 | { |
2371 | 2437 | SPDocument *document = desktop->getDocument(); | 2441 | SPDocument *document = desktop->getDocument(); |
2372 | 2438 | g_return_if_fail(document != NULL); | 2442 | g_return_if_fail(document != NULL); |
2373 | @@ -2440,7 +2444,8 @@ | |||
2374 | 2440 | Inkscape::Selection *selection = desktop->getSelection(); | 2444 | Inkscape::Selection *selection = desktop->getSelection(); |
2375 | 2441 | 2445 | ||
2376 | 2442 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); | 2446 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
2378 | 2443 | PrefsSelectionContext inlayer = (PrefsSelectionContext) prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER); | 2447 | PrefsSelectionContext inlayer = |
2379 | 2448 | (PrefsSelectionContext)prefs->getInt("/options/kbselection/inlayer", PREFS_SELECTION_LAYER); | ||
2380 | 2444 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); | 2449 | bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); |
2381 | 2445 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); | 2450 | bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); |
2382 | 2446 | 2451 | ||
2383 | @@ -2451,24 +2456,26 @@ | |||
2384 | 2451 | root = desktop->currentRoot(); | 2456 | root = desktop->currentRoot(); |
2385 | 2452 | } | 2457 | } |
2386 | 2453 | 2458 | ||
2388 | 2454 | SPItem *item=next_item_from_list<ListReverse>(desktop, selection->itemList(), root, SP_CYCLING == SP_CYCLE_VISIBLE, inlayer, onlyvisible, onlysensitive); | 2459 | SPItem *item = next_item_from_list<ListReverse>( |
2389 | 2460 | desktop, selection->itemList(), root, SP_CYCLING == SP_CYCLE_VISIBLE, inlayer, onlyvisible, onlysensitive); | ||
2390 | 2455 | 2461 | ||
2391 | 2456 | if (item) { | 2462 | if (item) { |
2392 | 2457 | selection->set(item, PREFS_SELECTION_LAYER_RECURSIVE == inlayer); | 2463 | selection->set(item, PREFS_SELECTION_LAYER_RECURSIVE == inlayer); |
2394 | 2458 | if ( SP_CYCLING == SP_CYCLE_FOCUS ) { | 2464 | if (SP_CYCLING == SP_CYCLE_FOCUS) { |
2395 | 2459 | scroll_to_show_item(desktop, item); | 2465 | scroll_to_show_item(desktop, item); |
2396 | 2460 | } | 2466 | } |
2397 | 2461 | } | 2467 | } |
2398 | 2462 | } | 2468 | } |
2399 | 2463 | 2469 | ||
2401 | 2464 | void sp_selection_next_patheffect_param(SPDesktop * dt) | 2470 | void sp_selection_next_patheffect_param(SPDesktop *dt) |
2402 | 2465 | { | 2471 | { |
2404 | 2466 | if (!dt) return; | 2472 | if (!dt) |
2405 | 2473 | return; | ||
2406 | 2467 | 2474 | ||
2407 | 2468 | Inkscape::Selection *selection = dt->getSelection(); | 2475 | Inkscape::Selection *selection = dt->getSelection(); |
2409 | 2469 | if ( selection && !selection->isEmpty() ) { | 2476 | if (selection && !selection->isEmpty()) { |
2410 | 2470 | SPItem *item = selection->singleItem(); | 2477 | SPItem *item = selection->singleItem(); |
2412 | 2471 | if ( SPLPEItem *lpeitem = dynamic_cast<SPLPEItem*>(item) ) { | 2478 | if (SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item)) { |
2413 | 2472 | if (lpeitem->hasPathEffect()) { | 2479 | if (lpeitem->hasPathEffect()) { |
2414 | 2473 | lpeitem->editNextParamOncanvas(dt); | 2480 | lpeitem->editNextParamOncanvas(dt); |
2415 | 2474 | } else { | 2481 | } else { |
2416 | @@ -2528,8 +2535,6 @@ | |||
2417 | 2528 | 2535 | ||
2418 | 2529 | 2536 | ||
2419 | 2530 | 2537 | ||
2420 | 2531 | |||
2421 | 2532 | |||
2422 | 2533 | /** | 2538 | /** |
2423 | 2534 | * If \a item is not entirely visible then adjust visible area to centre on the centre on of | 2539 | * If \a item is not entirely visible then adjust visible area to centre on the centre on of |
2424 | 2535 | * \a item. | 2540 | * \a item. |
2425 | @@ -2539,14 +2544,14 @@ | |||
2426 | 2539 | Geom::Rect dbox = desktop->get_display_area(); | 2544 | Geom::Rect dbox = desktop->get_display_area(); |
2427 | 2540 | Geom::OptRect sbox = item->desktopVisualBounds(); | 2545 | Geom::OptRect sbox = item->desktopVisualBounds(); |
2428 | 2541 | 2546 | ||
2430 | 2542 | if ( sbox && dbox.contains(*sbox) == false ) { | 2547 | if (sbox && dbox.contains(*sbox) == false) { |
2431 | 2543 | Geom::Point const s_dt = sbox->midpoint(); | 2548 | Geom::Point const s_dt = sbox->midpoint(); |
2432 | 2544 | Geom::Point const s_w = desktop->d2w(s_dt); | 2549 | Geom::Point const s_w = desktop->d2w(s_dt); |
2433 | 2545 | Geom::Point const d_dt = dbox.midpoint(); | 2550 | Geom::Point const d_dt = dbox.midpoint(); |
2434 | 2546 | Geom::Point const d_w = desktop->d2w(d_dt); | 2551 | Geom::Point const d_w = desktop->d2w(d_dt); |
2438 | 2547 | Geom::Point const moved_w( d_w - s_w ); | 2552 | Geom::Point const moved_w(d_w - s_w); |
2439 | 2548 | gint const dx = (gint) moved_w[X]; | 2553 | gint const dx = (gint)moved_w[X]; |
2440 | 2549 | gint const dy = (gint) moved_w[Y]; | 2554 | gint const dy = (gint)moved_w[Y]; |
2441 | 2550 | desktop->scroll_world(dx, dy); | 2555 | desktop->scroll_world(dx, dy); |
2442 | 2551 | } | 2556 | } |
2443 | 2552 | } | 2557 | } |
2444 | @@ -2568,17 +2573,17 @@ | |||
2445 | 2568 | return; | 2573 | return; |
2446 | 2569 | } | 2574 | } |
2447 | 2570 | 2575 | ||
2449 | 2571 | std::vector<Inkscape::XML::Node*> reprs (selection->reprList()); | 2576 | std::vector<Inkscape::XML::Node *> reprs(selection->reprList()); |
2450 | 2572 | 2577 | ||
2451 | 2573 | selection->clear(); | 2578 | selection->clear(); |
2452 | 2574 | 2579 | ||
2453 | 2575 | // sorting items from different parents sorts each parent's subset without possibly mixing them, just what we need | 2580 | // sorting items from different parents sorts each parent's subset without possibly mixing them, just what we need |
2460 | 2576 | sort(reprs.begin(),reprs.end(),sp_repr_compare_position_bool); | 2581 | sort(reprs.begin(), reprs.end(), sp_repr_compare_position_bool); |
2461 | 2577 | 2582 | ||
2462 | 2578 | std::vector<Inkscape::XML::Node*> newsel; | 2583 | std::vector<Inkscape::XML::Node *> newsel; |
2463 | 2579 | 2584 | ||
2464 | 2580 | for(std::vector<Inkscape::XML::Node*>::const_iterator i=reprs.begin();i!=reprs.end();i++){ | 2585 | for (std::vector<Inkscape::XML::Node *>::const_iterator i = reprs.begin(); i != reprs.end(); i++) { |
2465 | 2581 | Inkscape::XML::Node *sel_repr = *i; | 2586 | Inkscape::XML::Node *sel_repr = *i; |
2466 | 2582 | Inkscape::XML::Node *parent = sel_repr->parent(); | 2587 | Inkscape::XML::Node *parent = sel_repr->parent(); |
2467 | 2583 | 2588 | ||
2468 | 2584 | Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); | 2589 | Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); |
2469 | @@ -2598,14 +2603,12 @@ | |||
2470 | 2598 | Inkscape::GC::release(clone); | 2603 | Inkscape::GC::release(clone); |
2471 | 2599 | } | 2604 | } |
2472 | 2600 | 2605 | ||
2475 | 2601 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_CLONE, | 2606 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_CLONE, C_("Action", "Clone")); |
2474 | 2602 | C_("Action", "Clone")); | ||
2476 | 2603 | 2607 | ||
2477 | 2604 | selection->setReprList(newsel); | 2608 | selection->setReprList(newsel); |
2478 | 2605 | } | 2609 | } |
2479 | 2606 | 2610 | ||
2482 | 2607 | void | 2611 | void sp_selection_relink(SPDesktop *desktop) |
2481 | 2608 | sp_selection_relink(SPDesktop *desktop) | ||
2483 | 2609 | { | 2612 | { |
2484 | 2610 | if (!desktop) | 2613 | if (!desktop) |
2485 | 2611 | return; | 2614 | return; |
2486 | @@ -2620,15 +2623,16 @@ | |||
2487 | 2620 | Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); | 2623 | Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); |
2488 | 2621 | const gchar *newid = cm->getFirstObjectID(); | 2624 | const gchar *newid = cm->getFirstObjectID(); |
2489 | 2622 | if (!newid) { | 2625 | if (!newid) { |
2491 | 2623 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Copy an <b>object</b> to clipboard to relink clones to.")); | 2626 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
2492 | 2627 | _("Copy an <b>object</b> to clipboard to relink clones to.")); | ||
2493 | 2624 | return; | 2628 | return; |
2494 | 2625 | } | 2629 | } |
2495 | 2626 | gchar *newref = g_strdup_printf("#%s", newid); | 2630 | gchar *newref = g_strdup_printf("#%s", newid); |
2496 | 2627 | 2631 | ||
2497 | 2628 | // Get a copy of current selection. | 2632 | // Get a copy of current selection. |
2498 | 2629 | bool relinked = false; | 2633 | bool relinked = false; |
2501 | 2630 | std::vector<SPItem*> items=selection->itemList(); | 2634 | std::vector<SPItem *> items = selection->itemList(); |
2502 | 2631 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){ | 2635 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2503 | 2632 | SPItem *item = *i; | 2636 | SPItem *item = *i; |
2504 | 2633 | 2637 | ||
2505 | 2634 | if (dynamic_cast<SPUse *>(item)) { | 2638 | if (dynamic_cast<SPUse *>(item)) { |
2506 | @@ -2643,14 +2647,12 @@ | |||
2507 | 2643 | if (!relinked) { | 2647 | if (!relinked) { |
2508 | 2644 | desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to relink</b> in the selection.")); | 2648 | desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to relink</b> in the selection.")); |
2509 | 2645 | } else { | 2649 | } else { |
2512 | 2646 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_UNLINK_CLONE, | 2650 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_UNLINK_CLONE, _("Relink clone")); |
2511 | 2647 | _("Relink clone")); | ||
2513 | 2648 | } | 2651 | } |
2514 | 2649 | } | 2652 | } |
2515 | 2650 | 2653 | ||
2516 | 2651 | 2654 | ||
2519 | 2652 | void | 2655 | void sp_selection_unlink(SPDesktop *desktop) |
2518 | 2653 | sp_selection_unlink(SPDesktop *desktop) | ||
2520 | 2654 | { | 2656 | { |
2521 | 2655 | if (!desktop) | 2657 | if (!desktop) |
2522 | 2656 | return; | 2658 | return; |
2523 | @@ -2663,10 +2665,10 @@ | |||
2524 | 2663 | } | 2665 | } |
2525 | 2664 | 2666 | ||
2526 | 2665 | // Get a copy of current selection. | 2667 | // Get a copy of current selection. |
2528 | 2666 | std::vector<SPItem*> new_select; | 2668 | std::vector<SPItem *> new_select; |
2529 | 2667 | bool unlinked = false; | 2669 | bool unlinked = false; |
2532 | 2668 | std::vector<SPItem*> items=selection->itemList(); | 2670 | std::vector<SPItem *> items = selection->itemList(); |
2533 | 2669 | for (std::vector<SPItem*>::const_reverse_iterator i=items.rbegin();i!=items.rend();i++){ | 2671 | for (std::vector<SPItem *>::const_reverse_iterator i = items.rbegin(); i != items.rend(); i++) { |
2534 | 2670 | SPItem *item = *i; | 2672 | SPItem *item = *i; |
2535 | 2671 | 2673 | ||
2536 | 2672 | if (dynamic_cast<SPText *>(item)) { | 2674 | if (dynamic_cast<SPText *>(item)) { |
2537 | @@ -2714,12 +2716,10 @@ | |||
2538 | 2714 | desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to unlink</b> in the selection.")); | 2716 | desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to unlink</b> in the selection.")); |
2539 | 2715 | } | 2717 | } |
2540 | 2716 | 2718 | ||
2543 | 2717 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_UNLINK_CLONE, | 2719 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_UNLINK_CLONE, _("Unlink clone")); |
2542 | 2718 | _("Unlink clone")); | ||
2544 | 2719 | } | 2720 | } |
2545 | 2720 | 2721 | ||
2548 | 2721 | void | 2722 | void sp_select_clone_original(SPDesktop *desktop) |
2547 | 2722 | sp_select_clone_original(SPDesktop *desktop) | ||
2549 | 2723 | { | 2723 | { |
2550 | 2724 | if (desktop == NULL) | 2724 | if (desktop == NULL) |
2551 | 2725 | return; | 2725 | return; |
2552 | @@ -2728,11 +2728,13 @@ | |||
2553 | 2728 | 2728 | ||
2554 | 2729 | SPItem *item = selection->singleItem(); | 2729 | SPItem *item = selection->singleItem(); |
2555 | 2730 | 2730 | ||
2557 | 2731 | 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."); | 2731 | gchar const *error = |
2558 | 2732 | _("Select a <b>clone</b> to go to its original. Select a <b>linked offset</b> to go to its source. Select a " | ||
2559 | 2733 | "<b>text on path</b> to go to the path. Select a <b>flowed text</b> to go to its frame."); | ||
2560 | 2732 | 2734 | ||
2561 | 2733 | // Check if other than two objects are selected | 2735 | // Check if other than two objects are selected |
2562 | 2734 | 2736 | ||
2564 | 2735 | std::vector<SPItem*> items=selection->itemList(); | 2737 | std::vector<SPItem *> items = selection->itemList(); |
2565 | 2736 | if (items.size() != 1 || !item) { | 2738 | if (items.size() != 1 || !item) { |
2566 | 2737 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, error); | 2739 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, error); |
2567 | 2738 | return; | 2740 | return; |
2568 | @@ -2759,10 +2761,12 @@ | |||
2569 | 2759 | SPLPEItem *lpeItem = dynamic_cast<SPLPEItem *>(item); | 2761 | SPLPEItem *lpeItem = dynamic_cast<SPLPEItem *>(item); |
2570 | 2760 | if (lpeItem) { | 2762 | if (lpeItem) { |
2571 | 2761 | // check if the applied LPE is Clone original, if so, go to the refered path | 2763 | // check if the applied LPE is Clone original, if so, go to the refered path |
2573 | 2762 | Inkscape::LivePathEffect::Effect* lpe = lpeItem->getPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL); | 2764 | Inkscape::LivePathEffect::Effect *lpe = |
2574 | 2765 | lpeItem->getPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL); | ||
2575 | 2763 | if (lpe) { | 2766 | if (lpe) { |
2576 | 2764 | Inkscape::LivePathEffect::Parameter *lpeparam = lpe->getParameter("linkedpath"); | 2767 | Inkscape::LivePathEffect::Parameter *lpeparam = lpe->getParameter("linkedpath"); |
2578 | 2765 | if (Inkscape::LivePathEffect::OriginalPathParam *pathparam = dynamic_cast<Inkscape::LivePathEffect::OriginalPathParam *>(lpeparam)) { | 2768 | if (Inkscape::LivePathEffect::OriginalPathParam *pathparam = |
2579 | 2769 | dynamic_cast<Inkscape::LivePathEffect::OriginalPathParam *>(lpeparam)) { | ||
2580 | 2766 | original = pathparam->getObject(); | 2770 | original = pathparam->getObject(); |
2581 | 2767 | } | 2771 | } |
2582 | 2768 | } | 2772 | } |
2583 | @@ -2778,13 +2782,17 @@ | |||
2584 | 2778 | } | 2782 | } |
2585 | 2779 | 2783 | ||
2586 | 2780 | if (!original) { | 2784 | if (!original) { |
2588 | 2781 | desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>Cannot find</b> the object to select (orphaned clone, offset, textpath, flowed text?)")); | 2785 | desktop->messageStack()->flash( |
2589 | 2786 | Inkscape::ERROR_MESSAGE, | ||
2590 | 2787 | _("<b>Cannot find</b> the object to select (orphaned clone, offset, textpath, flowed text?)")); | ||
2591 | 2782 | return; | 2788 | return; |
2592 | 2783 | } | 2789 | } |
2593 | 2784 | 2790 | ||
2594 | 2785 | for (SPObject *o = original; o && !dynamic_cast<SPRoot *>(o); o = o->parent) { | 2791 | for (SPObject *o = original; o && !dynamic_cast<SPRoot *>(o); o = o->parent) { |
2595 | 2786 | if (dynamic_cast<SPDefs *>(o)) { | 2792 | if (dynamic_cast<SPDefs *>(o)) { |
2597 | 2787 | desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The object you're trying to select is <b>not visible</b> (it is in <defs>)")); | 2793 | desktop->messageStack()->flash( |
2598 | 2794 | Inkscape::ERROR_MESSAGE, | ||
2599 | 2795 | _("The object you're trying to select is <b>not visible</b> (it is in <defs>)")); | ||
2600 | 2788 | return; | 2796 | return; |
2601 | 2789 | } | 2797 | } |
2602 | 2790 | } | 2798 | } |
2603 | @@ -2795,14 +2803,15 @@ | |||
2604 | 2795 | if (highlight) { | 2803 | if (highlight) { |
2605 | 2796 | Geom::OptRect a = item->desktopVisualBounds(); | 2804 | Geom::OptRect a = item->desktopVisualBounds(); |
2606 | 2797 | Geom::OptRect b = original->desktopVisualBounds(); | 2805 | Geom::OptRect b = original->desktopVisualBounds(); |
2608 | 2798 | if ( a && b ) { | 2806 | if (a && b) { |
2609 | 2799 | // draw a flashing line between the objects | 2807 | // draw a flashing line between the objects |
2610 | 2800 | SPCurve *curve = new SPCurve(); | 2808 | SPCurve *curve = new SPCurve(); |
2611 | 2801 | curve->moveto(a->midpoint()); | 2809 | curve->moveto(a->midpoint()); |
2612 | 2802 | curve->lineto(b->midpoint()); | 2810 | curve->lineto(b->midpoint()); |
2613 | 2803 | 2811 | ||
2616 | 2804 | SPCanvasItem * canvasitem = sp_canvas_bpath_new(desktop->getTempGroup(), curve); | 2812 | SPCanvasItem *canvasitem = sp_canvas_bpath_new(desktop->getTempGroup(), curve); |
2617 | 2805 | sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvasitem), 0x0000ddff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT, 5, 3); | 2813 | sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvasitem), 0x0000ddff, 1.0, SP_STROKE_LINEJOIN_MITER, |
2618 | 2814 | SP_STROKE_LINECAP_BUTT, 5, 3); | ||
2619 | 2806 | sp_canvas_item_show(canvasitem); | 2815 | sp_canvas_item_show(canvasitem); |
2620 | 2807 | curve->unref(); | 2816 | curve->unref(); |
2621 | 2808 | desktop->add_temporary_canvasitem(canvasitem, 1000); | 2817 | desktop->add_temporary_canvasitem(canvasitem, 1000); |
2622 | @@ -2829,9 +2838,9 @@ | |||
2623 | 2829 | Inkscape::Selection *selection = desktop->getSelection(); | 2838 | Inkscape::Selection *selection = desktop->getSelection(); |
2624 | 2830 | 2839 | ||
2625 | 2831 | Inkscape::SVGOStringStream os; | 2840 | Inkscape::SVGOStringStream os; |
2629 | 2832 | SPObject * firstItem = NULL; | 2841 | SPObject *firstItem = NULL; |
2630 | 2833 | std::vector<SPItem*> items=selection->itemList(); | 2842 | std::vector<SPItem *> items = selection->itemList(); |
2631 | 2834 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){ | 2843 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2632 | 2835 | if (SP_IS_SHAPE(*i) || SP_IS_TEXT(*i)) { | 2844 | if (SP_IS_SHAPE(*i) || SP_IS_TEXT(*i)) { |
2633 | 2836 | if (firstItem) { | 2845 | if (firstItem) { |
2634 | 2837 | os << "|"; | 2846 | os << "|"; |
2635 | @@ -2850,7 +2859,8 @@ | |||
2636 | 2850 | { | 2859 | { |
2637 | 2851 | lpe_repr->setAttribute("effect", "fill_between_many"); | 2860 | lpe_repr->setAttribute("effect", "fill_between_many"); |
2638 | 2852 | lpe_repr->setAttribute("linkedpaths", os.str()); | 2861 | lpe_repr->setAttribute("linkedpaths", os.str()); |
2640 | 2853 | desktop->doc()->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to <defs> and assigns the 'id' attribute | 2862 | desktop->doc()->getDefs()->getRepr()->addChild(lpe_repr, |
2641 | 2863 | NULL); // adds to <defs> and assigns the 'id' attribute | ||
2642 | 2854 | } | 2864 | } |
2643 | 2855 | std::string lpe_id_href = std::string("#") + lpe_repr->attribute("id"); | 2865 | std::string lpe_id_href = std::string("#") + lpe_repr->attribute("id"); |
2644 | 2856 | Inkscape::GC::release(lpe_repr); | 2866 | Inkscape::GC::release(lpe_repr); |
2645 | @@ -2899,25 +2909,25 @@ | |||
2646 | 2899 | doc->ensureUpToDate(); | 2909 | doc->ensureUpToDate(); |
2647 | 2900 | Geom::OptRect r = selection->visualBounds(); | 2910 | Geom::OptRect r = selection->visualBounds(); |
2648 | 2901 | boost::optional<Geom::Point> c = selection->center(); | 2911 | boost::optional<Geom::Point> c = selection->center(); |
2650 | 2902 | if ( !r || !c ) { | 2912 | if (!r || !c) { |
2651 | 2903 | return; | 2913 | return; |
2652 | 2904 | } | 2914 | } |
2653 | 2905 | 2915 | ||
2654 | 2906 | // FIXME: Inverted Y coodinate | 2916 | // FIXME: Inverted Y coodinate |
2656 | 2907 | Geom::Point doc_height( 0, doc->getHeight().value("px")); | 2917 | Geom::Point doc_height(0, doc->getHeight().value("px")); |
2657 | 2908 | 2918 | ||
2658 | 2909 | // calculate the transform to be applied to objects to move them to 0,0 | 2919 | // calculate the transform to be applied to objects to move them to 0,0 |
2660 | 2910 | Geom::Point corner( r->min()[Geom::X], r->max()[Geom::Y] ); // FIXME: Inverted Y coodinate | 2920 | Geom::Point corner(r->min()[Geom::X], r->max()[Geom::Y]); // FIXME: Inverted Y coodinate |
2661 | 2911 | Geom::Point move_p = doc_height - corner; | 2921 | Geom::Point move_p = doc_height - corner; |
2662 | 2912 | move_p[Geom::Y] = -move_p[Geom::Y]; | 2922 | move_p[Geom::Y] = -move_p[Geom::Y]; |
2663 | 2913 | Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); | 2923 | Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); |
2664 | 2914 | 2924 | ||
2666 | 2915 | Geom::Point center( *c - corner ); // As defined by rotation center | 2925 | Geom::Point center(*c - corner); // As defined by rotation center |
2667 | 2916 | center[Geom::Y] = -center[Geom::Y]; | 2926 | center[Geom::Y] = -center[Geom::Y]; |
2668 | 2917 | 2927 | ||
2670 | 2918 | std::vector<SPItem*> items(selection->itemList()); | 2928 | std::vector<SPItem *> items(selection->itemList()); |
2671 | 2919 | 2929 | ||
2673 | 2920 | //items = g_slist_sort(items, (GCompareFunc) sp_object_compare_position); // Why needed? | 2930 | // items = g_slist_sort(items, (GCompareFunc) sp_object_compare_position); // Why needed? |
2674 | 2921 | 2931 | ||
2675 | 2922 | // bottommost object, after sorting | 2932 | // bottommost object, after sorting |
2676 | 2923 | SPObject *parent = items[0]->parent; | 2933 | SPObject *parent = items[0]->parent; |
2677 | @@ -2933,8 +2943,8 @@ | |||
2678 | 2933 | } | 2943 | } |
2679 | 2934 | 2944 | ||
2680 | 2935 | // Create a list of duplicates, to be pasted inside marker element. | 2945 | // Create a list of duplicates, to be pasted inside marker element. |
2683 | 2936 | std::vector<Inkscape::XML::Node*> repr_copies; | 2946 | std::vector<Inkscape::XML::Node *> repr_copies; |
2684 | 2937 | for (std::vector<SPItem*>::const_reverse_iterator i=items.rbegin();i!=items.rend();i++){ | 2947 | for (std::vector<SPItem *>::const_reverse_iterator i = items.rbegin(); i != items.rend(); i++) { |
2685 | 2938 | Inkscape::XML::Node *dup = (*i)->getRepr()->duplicate(xml_doc); | 2948 | Inkscape::XML::Node *dup = (*i)->getRepr()->duplicate(xml_doc); |
2686 | 2939 | repr_copies.push_back(dup); | 2949 | repr_copies.push_back(dup); |
2687 | 2940 | } | 2950 | } |
2688 | @@ -2944,7 +2954,7 @@ | |||
2689 | 2944 | if (apply) { | 2954 | if (apply) { |
2690 | 2945 | // Delete objects so that their clones don't get alerted; | 2955 | // Delete objects so that their clones don't get alerted; |
2691 | 2946 | // the objects will be restored inside the marker element. | 2956 | // the objects will be restored inside the marker element. |
2693 | 2947 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){ | 2957 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2694 | 2948 | SPObject *item = *i; | 2958 | SPObject *item = *i; |
2695 | 2949 | item->deleteObject(false); | 2959 | item->deleteObject(false); |
2696 | 2950 | } | 2960 | } |
2697 | @@ -2965,15 +2975,15 @@ | |||
2698 | 2965 | 2975 | ||
2699 | 2966 | 2976 | ||
2700 | 2967 | 2977 | ||
2703 | 2968 | DocumentUndo::done(doc, SP_VERB_EDIT_SELECTION_2_MARKER, | 2978 | DocumentUndo::done(doc, SP_VERB_EDIT_SELECTION_2_MARKER, _("Objects to marker")); |
2702 | 2969 | _("Objects to marker")); | ||
2704 | 2970 | } | 2979 | } |
2705 | 2971 | 2980 | ||
2707 | 2972 | static void sp_selection_to_guides_recursive(SPItem *item, bool wholegroups) { | 2981 | static void sp_selection_to_guides_recursive(SPItem *item, bool wholegroups) |
2708 | 2982 | { | ||
2709 | 2973 | SPGroup *group = dynamic_cast<SPGroup *>(item); | 2983 | SPGroup *group = dynamic_cast<SPGroup *>(item); |
2710 | 2974 | if (group && !dynamic_cast<SPBox3D *>(item) && !wholegroups) { | 2984 | if (group && !dynamic_cast<SPBox3D *>(item) && !wholegroups) { |
2713 | 2975 | std::vector<SPItem*> items=sp_item_group_item_list(group); | 2985 | std::vector<SPItem *> items = sp_item_group_item_list(group); |
2714 | 2976 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){ | 2986 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2715 | 2977 | sp_selection_to_guides_recursive(*i, wholegroups); | 2987 | sp_selection_to_guides_recursive(*i, wholegroups); |
2716 | 2978 | } | 2988 | } |
2717 | 2979 | } else { | 2989 | } else { |
2718 | @@ -2989,7 +2999,7 @@ | |||
2719 | 2989 | SPDocument *doc = desktop->getDocument(); | 2999 | SPDocument *doc = desktop->getDocument(); |
2720 | 2990 | Inkscape::Selection *selection = desktop->getSelection(); | 3000 | Inkscape::Selection *selection = desktop->getSelection(); |
2721 | 2991 | // we need to copy the list because it gets reset when objects are deleted | 3001 | // we need to copy the list because it gets reset when objects are deleted |
2723 | 2992 | std::vector<SPItem*> items(selection->itemList()); | 3002 | std::vector<SPItem *> items(selection->itemList()); |
2724 | 2993 | 3003 | ||
2725 | 2994 | if (items.empty()) { | 3004 | if (items.empty()) { |
2726 | 2995 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to convert to guides.")); | 3005 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to convert to guides.")); |
2727 | @@ -3004,7 +3014,7 @@ | |||
2728 | 3004 | // and its entry in the selection list is invalid (crash). | 3014 | // and its entry in the selection list is invalid (crash). |
2729 | 3005 | // Therefore: first convert all, then delete all. | 3015 | // Therefore: first convert all, then delete all. |
2730 | 3006 | 3016 | ||
2732 | 3007 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){ | 3017 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2733 | 3008 | sp_selection_to_guides_recursive(*i, wholegroups); | 3018 | sp_selection_to_guides_recursive(*i, wholegroups); |
2734 | 3009 | } | 3019 | } |
2735 | 3010 | 3020 | ||
2736 | @@ -3018,7 +3028,7 @@ | |||
2737 | 3018 | 3028 | ||
2738 | 3019 | /* | 3029 | /* |
2739 | 3020 | * Convert objects to <symbol>. How that happens depends on what is selected: | 3030 | * Convert objects to <symbol>. How that happens depends on what is selected: |
2741 | 3021 | * | 3031 | * |
2742 | 3022 | * 1) A random selection of objects will be embedded into a single <symbol> element. | 3032 | * 1) A random selection of objects will be embedded into a single <symbol> element. |
2743 | 3023 | * | 3033 | * |
2744 | 3024 | * 2) Except, a single <g> will have its content directly embedded into a <symbol>; the 'id' and | 3034 | * 2) Except, a single <g> will have its content directly embedded into a <symbol>; the 'id' and |
2745 | @@ -3036,7 +3046,7 @@ | |||
2746 | 3036 | * For SVG2, set 'refX' 'refY' to object center (with compensating shift in <use> | 3046 | * For SVG2, set 'refX' 'refY' to object center (with compensating shift in <use> |
2747 | 3037 | * transformation). | 3047 | * transformation). |
2748 | 3038 | */ | 3048 | */ |
2750 | 3039 | void sp_selection_symbol(SPDesktop *desktop, bool /*apply*/ ) | 3049 | void sp_selection_symbol(SPDesktop *desktop, bool /*apply*/) |
2751 | 3040 | { | 3050 | { |
2752 | 3041 | if (desktop == NULL) { | 3051 | if (desktop == NULL) { |
2753 | 3042 | return; | 3052 | return; |
2754 | @@ -3049,13 +3059,13 @@ | |||
2755 | 3049 | 3059 | ||
2756 | 3050 | // Check if something is selected. | 3060 | // Check if something is selected. |
2757 | 3051 | if (selection->isEmpty()) { | 3061 | if (selection->isEmpty()) { |
2760 | 3052 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>objects</b> to convert to symbol.")); | 3062 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>objects</b> to convert to symbol.")); |
2761 | 3053 | return; | 3063 | return; |
2762 | 3054 | } | 3064 | } |
2763 | 3055 | 3065 | ||
2764 | 3056 | doc->ensureUpToDate(); | 3066 | doc->ensureUpToDate(); |
2765 | 3057 | 3067 | ||
2767 | 3058 | std::vector<SPObject*> items(selection->list()); | 3068 | std::vector<SPObject *> items(selection->list()); |
2768 | 3059 | 3069 | ||
2769 | 3060 | // Keep track of parent, this is where <use> will be inserted. | 3070 | // Keep track of parent, this is where <use> will be inserted. |
2770 | 3061 | Inkscape::XML::Node *the_first_repr = items[0]->getRepr(); | 3071 | Inkscape::XML::Node *the_first_repr = items[0]->getRepr(); |
2771 | @@ -3065,16 +3075,16 @@ | |||
2772 | 3065 | bool single_group = false; | 3075 | bool single_group = false; |
2773 | 3066 | SPGroup *the_group = NULL; | 3076 | SPGroup *the_group = NULL; |
2774 | 3067 | Geom::Affine transform; | 3077 | Geom::Affine transform; |
2776 | 3068 | if( items.size() == 1 ) { | 3078 | if (items.size() == 1) { |
2777 | 3069 | SPObject *object = items[0]; | 3079 | SPObject *object = items[0]; |
2778 | 3070 | the_group = dynamic_cast<SPGroup *>(object); | 3080 | the_group = dynamic_cast<SPGroup *>(object); |
2780 | 3071 | if ( the_group ) { | 3081 | if (the_group) { |
2781 | 3072 | single_group = true; | 3082 | single_group = true; |
2782 | 3073 | 3083 | ||
2784 | 3074 | if( !sp_svg_transform_read( object->getAttribute("transform"), &transform )) | 3084 | if (!sp_svg_transform_read(object->getAttribute("transform"), &transform)) |
2785 | 3075 | transform = Geom::identity(); | 3085 | transform = Geom::identity(); |
2786 | 3076 | 3086 | ||
2788 | 3077 | if( transform.isTranslation() ) { | 3087 | if (transform.isTranslation()) { |
2789 | 3078 | 3088 | ||
2790 | 3079 | // Create new list from group children. | 3089 | // Create new list from group children. |
2791 | 3080 | items = object->childList(false); | 3090 | items = object->childList(false); |
2792 | @@ -3083,7 +3093,8 @@ | |||
2793 | 3083 | // without disturbing clones. | 3093 | // without disturbing clones. |
2794 | 3084 | // See ActorAlign::on_button_click() in src/ui/dialog/align-and-distribute.cpp | 3094 | // See ActorAlign::on_button_click() in src/ui/dialog/align-and-distribute.cpp |
2795 | 3085 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); | 3095 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
2797 | 3086 | int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); | 3096 | int saved_compensation = |
2798 | 3097 | prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); | ||
2799 | 3087 | prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); | 3098 | prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); |
2800 | 3088 | 3099 | ||
2801 | 3089 | // Remove transform on group, updating clones. | 3100 | // Remove transform on group, updating clones. |
2802 | @@ -3101,11 +3112,11 @@ | |||
2803 | 3101 | defsrepr->appendChild(symbol_repr); | 3112 | defsrepr->appendChild(symbol_repr); |
2804 | 3102 | 3113 | ||
2805 | 3103 | // For a single group, copy relevant attributes. | 3114 | // For a single group, copy relevant attributes. |
2807 | 3104 | if( single_group ) { | 3115 | if (single_group) { |
2808 | 3105 | 3116 | ||
2812 | 3106 | symbol_repr->setAttribute("style", the_group->getAttribute("style")); | 3117 | symbol_repr->setAttribute("style", the_group->getAttribute("style")); |
2813 | 3107 | symbol_repr->setAttribute("class", the_group->getAttribute("class")); | 3118 | symbol_repr->setAttribute("class", the_group->getAttribute("class")); |
2814 | 3108 | symbol_repr->setAttribute("id", the_group->getAttribute("id") ); | 3119 | symbol_repr->setAttribute("id", the_group->getAttribute("id")); |
2815 | 3109 | 3120 | ||
2816 | 3110 | // This should eventually be replaced by 'refX' and 'refY' once SVG WG approves it. | 3121 | // This should eventually be replaced by 'refX' and 'refY' once SVG WG approves it. |
2817 | 3111 | // It is done here for round-tripping | 3122 | // It is done here for round-tripping |
2818 | @@ -3118,30 +3129,29 @@ | |||
2819 | 3118 | Glib::ustring id = symbol_repr->attribute("id"); | 3129 | Glib::ustring id = symbol_repr->attribute("id"); |
2820 | 3119 | id += "_transform"; | 3130 | id += "_transform"; |
2821 | 3120 | the_group->setAttribute("id", id); | 3131 | the_group->setAttribute("id", id); |
2822 | 3121 | |||
2823 | 3122 | } | 3132 | } |
2824 | 3123 | 3133 | ||
2825 | 3124 | // Move selected items to new <symbol> | 3134 | // Move selected items to new <symbol> |
2830 | 3125 | for (std::vector<SPObject*>::const_iterator i=items.begin();i!=items.end();i++){ | 3135 | for (std::vector<SPObject *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2831 | 3126 | Inkscape::XML::Node *repr = (*i)->getRepr(); | 3136 | Inkscape::XML::Node *repr = (*i)->getRepr(); |
2832 | 3127 | repr->parent()->removeChild(repr); | 3137 | repr->parent()->removeChild(repr); |
2833 | 3128 | symbol_repr->addChild(repr,NULL); | 3138 | symbol_repr->addChild(repr, NULL); |
2834 | 3129 | } | 3139 | } |
2835 | 3130 | 3140 | ||
2837 | 3131 | if( single_group && transform.isTranslation() ) { | 3141 | if (single_group && transform.isTranslation()) { |
2838 | 3132 | the_group->deleteObject(true); | 3142 | the_group->deleteObject(true); |
2839 | 3133 | } | 3143 | } |
2840 | 3134 | 3144 | ||
2841 | 3135 | // Create <use> pointing to new symbol (to replace the moved objects). | 3145 | // Create <use> pointing to new symbol (to replace the moved objects). |
2842 | 3136 | Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); | 3146 | Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); |
2843 | 3137 | 3147 | ||
2845 | 3138 | clone->setAttribute("xlink:href", Glib::ustring("#")+symbol_repr->attribute("id"), false); | 3148 | clone->setAttribute("xlink:href", Glib::ustring("#") + symbol_repr->attribute("id"), false); |
2846 | 3139 | 3149 | ||
2847 | 3140 | the_parent_repr->appendChild(clone); | 3150 | the_parent_repr->appendChild(clone); |
2848 | 3141 | 3151 | ||
2852 | 3142 | if( single_group && transform.isTranslation() ) { | 3152 | if (single_group && transform.isTranslation()) { |
2853 | 3143 | if( !transform.isIdentity() ) | 3153 | if (!transform.isIdentity()) |
2854 | 3144 | clone->setAttribute("transform", sp_svg_transform_write( transform )); | 3154 | clone->setAttribute("transform", sp_svg_transform_write(transform)); |
2855 | 3145 | } | 3155 | } |
2856 | 3146 | 3156 | ||
2857 | 3147 | // Change selection to new <use> element. | 3157 | // Change selection to new <use> element. |
2858 | @@ -3173,12 +3183,13 @@ | |||
2859 | 3173 | return; | 3183 | return; |
2860 | 3174 | } | 3184 | } |
2861 | 3175 | 3185 | ||
2864 | 3176 | SPObject* symbol = selection->single(); | 3186 | SPObject *symbol = selection->single(); |
2865 | 3177 | 3187 | ||
2866 | 3178 | // Make sure we have only one object in selection. | 3188 | // Make sure we have only one object in selection. |
2867 | 3179 | // Require that we really have a <symbol>. | 3189 | // Require that we really have a <symbol>. |
2870 | 3180 | if( symbol == NULL || !dynamic_cast<SPSymbol *>( symbol )) { | 3190 | if (symbol == NULL || !dynamic_cast<SPSymbol *>(symbol)) { |
2871 | 3181 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select only one <b>symbol</b> in Symbol dialog to convert to group.")); | 3191 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
2872 | 3192 | _("Select only one <b>symbol</b> in Symbol dialog to convert to group.")); | ||
2873 | 3182 | return; | 3193 | return; |
2874 | 3183 | } | 3194 | } |
2875 | 3184 | 3195 | ||
2876 | @@ -3189,36 +3200,33 @@ | |||
2877 | 3189 | desktop->currentLayer()->getRepr()->appendChild(group); | 3200 | desktop->currentLayer()->getRepr()->appendChild(group); |
2878 | 3190 | 3201 | ||
2879 | 3191 | // Move all children of symbol to group | 3202 | // Move all children of symbol to group |
2881 | 3192 | std::vector<SPObject*> children = symbol->childList(false); | 3203 | std::vector<SPObject *> children = symbol->childList(false); |
2882 | 3193 | 3204 | ||
2883 | 3194 | // Converting a group to a symbol inserts a group for non-translational transform. | 3205 | // Converting a group to a symbol inserts a group for non-translational transform. |
2884 | 3195 | // In converting a symbol back to a group we strip out the inserted group (or any other | 3206 | // In converting a symbol back to a group we strip out the inserted group (or any other |
2885 | 3196 | // group that only adds a transform to the symbol content). | 3207 | // group that only adds a transform to the symbol content). |
2887 | 3197 | if( children.size() == 1 ) { | 3208 | if (children.size() == 1) { |
2888 | 3198 | SPObject *object = children[0]; | 3209 | SPObject *object = children[0]; |
2892 | 3199 | if ( dynamic_cast<SPGroup *>( object ) ) { | 3210 | if (dynamic_cast<SPGroup *>(object)) { |
2893 | 3200 | if( object->getAttribute("style") == NULL || | 3211 | if (object->getAttribute("style") == NULL || object->getAttribute("class") == NULL) { |
2891 | 3201 | object->getAttribute("class") == NULL ) { | ||
2894 | 3202 | 3212 | ||
2895 | 3203 | group->setAttribute("transform", object->getAttribute("transform")); | 3213 | group->setAttribute("transform", object->getAttribute("transform")); |
2896 | 3204 | children = object->childList(false); | 3214 | children = object->childList(false); |
2897 | 3205 | } | 3215 | } |
2898 | 3206 | } | 3216 | } |
2899 | 3207 | } | 3217 | } |
2902 | 3208 | 3218 | ||
2903 | 3209 | for (std::vector<SPObject*>::const_reverse_iterator i=children.rbegin();i!=children.rend();i++){ | 3219 | for (std::vector<SPObject *>::const_reverse_iterator i = children.rbegin(); i != children.rend(); i++) { |
2904 | 3210 | Inkscape::XML::Node *repr = (*i)->getRepr(); | 3220 | Inkscape::XML::Node *repr = (*i)->getRepr(); |
2905 | 3211 | repr->parent()->removeChild(repr); | 3221 | repr->parent()->removeChild(repr); |
2907 | 3212 | group->addChild(repr,NULL); | 3222 | group->addChild(repr, NULL); |
2908 | 3213 | } | 3223 | } |
2909 | 3214 | 3224 | ||
2910 | 3215 | // Copy relevant attributes | 3225 | // Copy relevant attributes |
2911 | 3216 | group->setAttribute("style", symbol->getAttribute("style")); | 3226 | group->setAttribute("style", symbol->getAttribute("style")); |
2912 | 3217 | group->setAttribute("class", symbol->getAttribute("class")); | 3227 | group->setAttribute("class", symbol->getAttribute("class")); |
2917 | 3218 | group->setAttribute("inkscape:transform-center-x", | 3228 | group->setAttribute("inkscape:transform-center-x", symbol->getAttribute("inkscape:transform-center-x")); |
2918 | 3219 | symbol->getAttribute("inkscape:transform-center-x")); | 3229 | group->setAttribute("inkscape:transform-center-y", symbol->getAttribute("inkscape:transform-center-y")); |
2915 | 3220 | group->setAttribute("inkscape:transform-center-y", | ||
2916 | 3221 | symbol->getAttribute("inkscape:transform-center-y")); | ||
2919 | 3222 | 3230 | ||
2920 | 3223 | 3231 | ||
2921 | 3224 | // Need to delete <symbol>; all <use> elements that referenced <symbol> should | 3232 | // Need to delete <symbol>; all <use> elements that referenced <symbol> should |
2922 | @@ -3237,8 +3245,7 @@ | |||
2923 | 3237 | DocumentUndo::done(doc, SP_VERB_EDIT_UNSYMBOL, _("Group from symbol")); | 3245 | DocumentUndo::done(doc, SP_VERB_EDIT_UNSYMBOL, _("Group from symbol")); |
2924 | 3238 | } | 3246 | } |
2925 | 3239 | 3247 | ||
2928 | 3240 | void | 3248 | void sp_selection_tile(SPDesktop *desktop, bool apply) |
2927 | 3241 | sp_selection_tile(SPDesktop *desktop, bool apply) | ||
2929 | 3242 | { | 3249 | { |
2930 | 3243 | // sp_selection_to_marker has similar code | 3250 | // sp_selection_to_marker has similar code |
2931 | 3244 | if (desktop == NULL) { | 3251 | if (desktop == NULL) { |
2932 | @@ -3258,22 +3265,23 @@ | |||
2933 | 3258 | 3265 | ||
2934 | 3259 | doc->ensureUpToDate(); | 3266 | doc->ensureUpToDate(); |
2935 | 3260 | Geom::OptRect r = selection->visualBounds(); | 3267 | Geom::OptRect r = selection->visualBounds(); |
2937 | 3261 | if ( !r ) { | 3268 | if (!r) { |
2938 | 3262 | return; | 3269 | return; |
2939 | 3263 | } | 3270 | } |
2940 | 3264 | 3271 | ||
2941 | 3265 | // calculate the transform to be applied to objects to move them to 0,0 | 3272 | // calculate the transform to be applied to objects to move them to 0,0 |
2943 | 3266 | Geom::Point move_p = Geom::Point(0, doc->getHeight().value("px")) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); | 3273 | Geom::Point move_p = |
2944 | 3274 | Geom::Point(0, doc->getHeight().value("px")) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); | ||
2945 | 3267 | move_p[Geom::Y] = -move_p[Geom::Y]; | 3275 | move_p[Geom::Y] = -move_p[Geom::Y]; |
2946 | 3268 | Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); | 3276 | Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); |
2947 | 3269 | 3277 | ||
2949 | 3270 | std::vector<SPItem*> items (selection->itemList()); | 3278 | std::vector<SPItem *> items(selection->itemList()); |
2950 | 3271 | 3279 | ||
2952 | 3272 | sort(items.begin(),items.end(),sp_object_compare_position_bool); | 3280 | sort(items.begin(), items.end(), sp_object_compare_position_bool); |
2953 | 3273 | 3281 | ||
2954 | 3274 | // bottommost object, after sorting | 3282 | // bottommost object, after sorting |
2955 | 3275 | SPObject *parent = items[0]->parent; | 3283 | SPObject *parent = items[0]->parent; |
2957 | 3276 | 3284 | ||
2958 | 3277 | 3285 | ||
2959 | 3278 | Geom::Affine parent_transform; | 3286 | Geom::Affine parent_transform; |
2960 | 3279 | { | 3287 | { |
2961 | @@ -3289,8 +3297,8 @@ | |||
2962 | 3289 | gint pos = items[0]->getRepr()->position(); | 3297 | gint pos = items[0]->getRepr()->position(); |
2963 | 3290 | 3298 | ||
2964 | 3291 | // create a list of duplicates | 3299 | // create a list of duplicates |
2967 | 3292 | std::vector<Inkscape::XML::Node*> repr_copies; | 3300 | std::vector<Inkscape::XML::Node *> repr_copies; |
2968 | 3293 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){ | 3301 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2969 | 3294 | Inkscape::XML::Node *dup = (*i)->getRepr()->duplicate(xml_doc); | 3302 | Inkscape::XML::Node *dup = (*i)->getRepr()->duplicate(xml_doc); |
2970 | 3295 | repr_copies.push_back(dup); | 3303 | repr_copies.push_back(dup); |
2971 | 3296 | } | 3304 | } |
2972 | @@ -3299,7 +3307,7 @@ | |||
2973 | 3299 | 3307 | ||
2974 | 3300 | if (apply) { | 3308 | if (apply) { |
2975 | 3301 | // delete objects so that their clones don't get alerted; this object will be restored shortly | 3309 | // delete objects so that their clones don't get alerted; this object will be restored shortly |
2977 | 3302 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){ | 3310 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
2978 | 3303 | SPObject *item = *i; | 3311 | SPObject *item = *i; |
2979 | 3304 | item->deleteObject(false); | 3312 | item->deleteObject(false); |
2980 | 3305 | } | 3313 | } |
2981 | @@ -3312,11 +3320,11 @@ | |||
2982 | 3312 | int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); | 3320 | int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); |
2983 | 3313 | prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); | 3321 | prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); |
2984 | 3314 | 3322 | ||
2990 | 3315 | gchar const *pat_id = SPPattern::produce(repr_copies, bbox, doc, | 3323 | gchar const *pat_id = SPPattern::produce( |
2991 | 3316 | ( Geom::Affine(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X], | 3324 | repr_copies, bbox, doc, |
2992 | 3317 | r->max()[Geom::Y])))) | 3325 | (Geom::Affine(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X], r->max()[Geom::Y])))) * |
2993 | 3318 | * parent_transform.inverse() ), | 3326 | parent_transform.inverse()), |
2994 | 3319 | parent_transform * move); | 3327 | parent_transform * move); |
2995 | 3320 | 3328 | ||
2996 | 3321 | // restore compensation setting | 3329 | // restore compensation setting |
2997 | 3322 | prefs->setInt("/options/clonecompensation/value", saved_compensation); | 3330 | prefs->setInt("/options/clonecompensation/value", saved_compensation); |
2998 | @@ -3347,8 +3355,7 @@ | |||
2999 | 3347 | } | 3355 | } |
3000 | 3348 | 3356 | ||
3001 | 3349 | 3357 | ||
3004 | 3350 | DocumentUndo::done(doc, SP_VERB_EDIT_TILE, | 3358 | DocumentUndo::done(doc, SP_VERB_EDIT_TILE, _("Objects to pattern")); |
3003 | 3351 | _("Objects to pattern")); | ||
3005 | 3352 | } | 3359 | } |
3006 | 3353 | 3360 | ||
3007 | 3354 | void sp_selection_untile(SPDesktop *desktop) | 3361 | void sp_selection_untile(SPDesktop *desktop) |
3008 | @@ -3364,16 +3371,17 @@ | |||
3009 | 3364 | 3371 | ||
3010 | 3365 | // check if something is selected | 3372 | // check if something is selected |
3011 | 3366 | if (selection->isEmpty()) { | 3373 | if (selection->isEmpty()) { |
3013 | 3367 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select an <b>object with pattern fill</b> to extract objects from.")); | 3374 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
3014 | 3375 | _("Select an <b>object with pattern fill</b> to extract objects from.")); | ||
3015 | 3368 | return; | 3376 | return; |
3016 | 3369 | } | 3377 | } |
3017 | 3370 | 3378 | ||
3019 | 3371 | std::vector<SPItem*> new_select; | 3379 | std::vector<SPItem *> new_select; |
3020 | 3372 | 3380 | ||
3021 | 3373 | bool did = false; | 3381 | bool did = false; |
3022 | 3374 | 3382 | ||
3025 | 3375 | std::vector<SPItem*> items(selection->itemList()); | 3383 | std::vector<SPItem *> items(selection->itemList()); |
3026 | 3376 | for (std::vector<SPItem*>::const_reverse_iterator i=items.rbegin();i!=items.rend();i++){ | 3384 | for (std::vector<SPItem *>::const_reverse_iterator i = items.rbegin(); i != items.rend(); i++) { |
3027 | 3377 | SPItem *item = *i; | 3385 | SPItem *item = *i; |
3028 | 3378 | 3386 | ||
3029 | 3379 | SPStyle *style = item->style; | 3387 | SPStyle *style = item->style; |
3030 | @@ -3395,19 +3403,19 @@ | |||
3031 | 3395 | Geom::Affine pat_transform = basePat->getTransform(); | 3403 | Geom::Affine pat_transform = basePat->getTransform(); |
3032 | 3396 | pat_transform *= item->transform; | 3404 | pat_transform *= item->transform; |
3033 | 3397 | 3405 | ||
3035 | 3398 | for (SPObject *child = pattern->firstChild() ; child != NULL; child = child->next ) { | 3406 | for (SPObject *child = pattern->firstChild(); child != NULL; child = child->next) { |
3036 | 3399 | if (dynamic_cast<SPItem *>(child)) { | 3407 | if (dynamic_cast<SPItem *>(child)) { |
3037 | 3400 | Inkscape::XML::Node *copy = child->getRepr()->duplicate(xml_doc); | 3408 | Inkscape::XML::Node *copy = child->getRepr()->duplicate(xml_doc); |
3038 | 3401 | SPItem *i = dynamic_cast<SPItem *>(desktop->currentLayer()->appendChildRepr(copy)); | 3409 | SPItem *i = dynamic_cast<SPItem *>(desktop->currentLayer()->appendChildRepr(copy)); |
3039 | 3402 | 3410 | ||
3042 | 3403 | // FIXME: relink clones to the new canvas objects | 3411 | // FIXME: relink clones to the new canvas objects |
3043 | 3404 | // use SPObject::setid when mental finishes it to steal ids of | 3412 | // use SPObject::setid when mental finishes it to steal ids of |
3044 | 3405 | 3413 | ||
3045 | 3406 | // this is needed to make sure the new item has curve (simply requestDisplayUpdate does not work) | 3414 | // this is needed to make sure the new item has curve (simply requestDisplayUpdate does not work) |
3046 | 3407 | doc->ensureUpToDate(); | 3415 | doc->ensureUpToDate(); |
3047 | 3408 | 3416 | ||
3048 | 3409 | if (i) { | 3417 | if (i) { |
3050 | 3410 | Geom::Affine transform( i->transform * pat_transform ); | 3418 | Geom::Affine transform(i->transform * pat_transform); |
3051 | 3411 | i->doWriteTransform(i->getRepr(), transform); | 3419 | i->doWriteTransform(i->getRepr(), transform); |
3052 | 3412 | 3420 | ||
3053 | 3413 | new_select.push_back(i); | 3421 | new_select.push_back(i); |
3054 | @@ -3425,8 +3433,7 @@ | |||
3055 | 3425 | if (!did) { | 3433 | if (!did) { |
3056 | 3426 | desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No pattern fills</b> in the selection.")); | 3434 | desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No pattern fills</b> in the selection.")); |
3057 | 3427 | } else { | 3435 | } else { |
3060 | 3428 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_UNTILE, | 3436 | DocumentUndo::done(desktop->getDocument(), SP_VERB_EDIT_UNTILE, _("Pattern to objects")); |
3059 | 3429 | _("Pattern to objects")); | ||
3061 | 3430 | selection->setList(new_select); | 3437 | selection->setList(new_select); |
3062 | 3431 | } | 3438 | } |
3063 | 3432 | } | 3439 | } |
3064 | @@ -3437,22 +3444,22 @@ | |||
3065 | 3437 | return; | 3444 | return; |
3066 | 3438 | } | 3445 | } |
3067 | 3439 | 3446 | ||
3069 | 3440 | std::vector<Inkscape::XML::Node*> const reprlst = selection->reprList(); | 3447 | std::vector<Inkscape::XML::Node *> const reprlst = selection->reprList(); |
3070 | 3441 | bool filename_search = TRUE; | 3448 | bool filename_search = TRUE; |
3071 | 3442 | bool xdpi_search = TRUE; | 3449 | bool xdpi_search = TRUE; |
3072 | 3443 | bool ydpi_search = TRUE; | 3450 | bool ydpi_search = TRUE; |
3073 | 3444 | 3451 | ||
3075 | 3445 | for (std::vector<Inkscape::XML::Node*>::const_iterator i=reprlst.begin();filename_search&&xdpi_search&&ydpi_search&&i!=reprlst.end();i++){ | 3452 | for (std::vector<Inkscape::XML::Node *>::const_iterator i = reprlst.begin(); |
3076 | 3453 | filename_search && xdpi_search && ydpi_search && i != reprlst.end(); i++) { | ||
3077 | 3446 | gchar const *dpi_string; | 3454 | gchar const *dpi_string; |
3078 | 3447 | Inkscape::XML::Node *repr = *i; | 3455 | Inkscape::XML::Node *repr = *i; |
3079 | 3448 | 3456 | ||
3080 | 3449 | if (filename_search) { | 3457 | if (filename_search) { |
3083 | 3450 | const gchar* tmp = repr->attribute("inkscape:export-filename"); | 3458 | const gchar *tmp = repr->attribute("inkscape:export-filename"); |
3084 | 3451 | if (tmp){ | 3459 | if (tmp) { |
3085 | 3452 | filename = tmp; | 3460 | filename = tmp; |
3086 | 3453 | filename_search = FALSE; | 3461 | filename_search = FALSE; |
3089 | 3454 | } | 3462 | } else { |
3088 | 3455 | else{ | ||
3090 | 3456 | filename.clear(); | 3463 | filename.clear(); |
3091 | 3457 | } | 3464 | } |
3092 | 3458 | } | 3465 | } |
3093 | @@ -3477,15 +3484,12 @@ | |||
3094 | 3477 | 3484 | ||
3095 | 3478 | void sp_document_get_export_hints(SPDocument *doc, Glib::ustring &filename, float *xdpi, float *ydpi) | 3485 | void sp_document_get_export_hints(SPDocument *doc, Glib::ustring &filename, float *xdpi, float *ydpi) |
3096 | 3479 | { | 3486 | { |
3098 | 3480 | Inkscape::XML::Node * repr = doc->getReprRoot(); | 3487 | Inkscape::XML::Node *repr = doc->getReprRoot(); |
3099 | 3481 | 3488 | ||
3103 | 3482 | const gchar* tmp = repr->attribute("inkscape:export-filename"); | 3489 | const gchar *tmp = repr->attribute("inkscape:export-filename"); |
3104 | 3483 | if(tmp) | 3490 | if (tmp) { |
3102 | 3484 | { | ||
3105 | 3485 | filename = tmp; | 3491 | filename = tmp; |
3109 | 3486 | } | 3492 | } else { |
3107 | 3487 | else | ||
3108 | 3488 | { | ||
3110 | 3489 | filename.clear(); | 3493 | filename.clear(); |
3111 | 3490 | } | 3494 | } |
3112 | 3491 | gchar const *dpi_string = repr->attribute("inkscape:export-xdpi"); | 3495 | gchar const *dpi_string = repr->attribute("inkscape:export-xdpi"); |
3113 | @@ -3530,30 +3534,28 @@ | |||
3114 | 3530 | } | 3534 | } |
3115 | 3531 | 3535 | ||
3116 | 3532 | // List of the items to show; all others will be hidden | 3536 | // List of the items to show; all others will be hidden |
3118 | 3533 | std::vector<SPItem*> items(selection->itemList()); | 3537 | std::vector<SPItem *> items(selection->itemList()); |
3119 | 3534 | 3538 | ||
3120 | 3535 | // Sort items so that the topmost comes last | 3539 | // Sort items so that the topmost comes last |
3122 | 3536 | sort(items.begin(),items.end(),sp_item_repr_compare_position_bool); | 3540 | sort(items.begin(), items.end(), sp_item_repr_compare_position_bool); |
3123 | 3537 | 3541 | ||
3124 | 3538 | // Generate a random value from the current time (you may create bitmap from the same object(s) | 3542 | // Generate a random value from the current time (you may create bitmap from the same object(s) |
3125 | 3539 | // multiple times, and this is done so that they don't clash) | 3543 | // multiple times, and this is done so that they don't clash) |
3126 | 3540 | GTimeVal cu; | 3544 | GTimeVal cu; |
3127 | 3541 | g_get_current_time(&cu); | 3545 | g_get_current_time(&cu); |
3129 | 3542 | guint current = (int) (cu.tv_sec * 1000000 + cu.tv_usec) % 1024; | 3546 | guint current = (int)(cu.tv_sec * 1000000 + cu.tv_usec) % 1024; |
3130 | 3543 | 3547 | ||
3131 | 3544 | // Create the filename. | 3548 | // Create the filename. |
3136 | 3545 | gchar *const basename = g_strdup_printf("%s-%s-%u.png", | 3549 | gchar *const basename = |
3137 | 3546 | document->getName(), | 3550 | g_strdup_printf("%s-%s-%u.png", document->getName(), items[0]->getRepr()->attribute("id"), current); |
3134 | 3547 | items[0]->getRepr()->attribute("id"), | ||
3135 | 3548 | current); | ||
3138 | 3549 | // Imagemagick is known not to handle spaces in filenames, so we replace anything but letters, | 3551 | // Imagemagick is known not to handle spaces in filenames, so we replace anything but letters, |
3139 | 3550 | // digits, and a few other chars, with "_" | 3552 | // digits, and a few other chars, with "_" |
3140 | 3551 | g_strcanon(basename, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.=+~$#@^&!?", '_'); | 3553 | g_strcanon(basename, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.=+~$#@^&!?", '_'); |
3141 | 3552 | 3554 | ||
3142 | 3553 | // Build the complete path by adding document base dir, if set, otherwise home dir | 3555 | // Build the complete path by adding document base dir, if set, otherwise home dir |
3143 | 3554 | gchar *directory = NULL; | 3556 | gchar *directory = NULL; |
3146 | 3555 | if ( document->getURI() ) { | 3557 | if (document->getURI()) { |
3147 | 3556 | directory = g_path_get_dirname( document->getURI() ); | 3558 | directory = g_path_get_dirname(document->getURI()); |
3148 | 3557 | } | 3559 | } |
3149 | 3558 | if (directory == NULL) { | 3560 | if (directory == NULL) { |
3150 | 3559 | directory = INKSCAPE.homedir_path(NULL); | 3561 | directory = INKSCAPE.homedir_path(NULL); |
3151 | @@ -3561,7 +3563,7 @@ | |||
3152 | 3561 | gchar *filepath = g_build_filename(directory, basename, NULL); | 3563 | gchar *filepath = g_build_filename(directory, basename, NULL); |
3153 | 3562 | g_free(directory); | 3564 | g_free(directory); |
3154 | 3563 | 3565 | ||
3156 | 3564 | //g_print("%s\n", filepath); | 3566 | // g_print("%s\n", filepath); |
3157 | 3565 | 3567 | ||
3158 | 3566 | // Remember parent and z-order of the topmost one | 3568 | // Remember parent and z-order of the topmost one |
3159 | 3567 | gint pos = items.back()->getRepr()->position(); | 3569 | gint pos = items.back()->getRepr()->position(); |
3160 | @@ -3599,8 +3601,8 @@ | |||
3161 | 3599 | } | 3601 | } |
3162 | 3600 | 3602 | ||
3163 | 3601 | // The width and height of the bitmap in pixels | 3603 | // The width and height of the bitmap in pixels |
3166 | 3602 | unsigned width = (unsigned) floor(bbox->width() * Inkscape::Util::Quantity::convert(res, "px", "in")); | 3604 | unsigned width = (unsigned)floor(bbox->width() * Inkscape::Util::Quantity::convert(res, "px", "in")); |
3167 | 3603 | unsigned height =(unsigned) floor(bbox->height() * Inkscape::Util::Quantity::convert(res, "px", "in")); | 3605 | unsigned height = (unsigned)floor(bbox->height() * Inkscape::Util::Quantity::convert(res, "px", "in")); |
3168 | 3604 | 3606 | ||
3169 | 3605 | // Find out if we have to run an external filter | 3607 | // Find out if we have to run an external filter |
3170 | 3606 | gchar const *run = NULL; | 3608 | gchar const *run = NULL; |
3171 | @@ -3642,19 +3644,16 @@ | |||
3172 | 3642 | double shift_y = bbox->max()[Geom::Y]; | 3644 | double shift_y = bbox->max()[Geom::Y]; |
3173 | 3643 | if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid | 3645 | if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid |
3174 | 3644 | shift_x = round(shift_x); | 3646 | shift_x = round(shift_x); |
3176 | 3645 | shift_y = -round(-shift_y); // this gets correct rounding despite coordinate inversion, remove the negations when the inversion is gone | 3647 | shift_y = -round(-shift_y); // this gets correct rounding despite coordinate inversion, remove the negations |
3177 | 3648 | // when the inversion is gone | ||
3178 | 3646 | } | 3649 | } |
3180 | 3647 | t = Geom::Scale(1, -1) * Geom::Translate(shift_x, shift_y) * eek.inverse(); /// @fixme hardcoded doc2dt transform? | 3650 | t = Geom::Scale(1, -1) * Geom::Translate(shift_x, shift_y) * eek.inverse(); /// @fixme hardcoded doc2dt transform? |
3181 | 3648 | 3651 | ||
3182 | 3649 | // TODO: avoid roundtrip via file | 3652 | // TODO: avoid roundtrip via file |
3183 | 3650 | // Do the export | 3653 | // Do the export |
3191 | 3651 | sp_export_png_file(document, filepath, | 3654 | sp_export_png_file(document, filepath, bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], |
3192 | 3652 | bbox->min()[Geom::X], bbox->min()[Geom::Y], | 3655 | bbox->max()[Geom::Y], width, height, res, res, (guint32)0xffffff00, NULL, NULL, |
3193 | 3653 | bbox->max()[Geom::X], bbox->max()[Geom::Y], | 3656 | true, /*bool force_overwrite,*/ |
3187 | 3654 | width, height, res, res, | ||
3188 | 3655 | (guint32) 0xffffff00, | ||
3189 | 3656 | NULL, NULL, | ||
3190 | 3657 | true, /*bool force_overwrite,*/ | ||
3194 | 3658 | items); | 3657 | items); |
3195 | 3659 | 3658 | ||
3196 | 3660 | // Run filter, if any | 3659 | // Run filter, if any |
3197 | @@ -3662,7 +3661,7 @@ | |||
3198 | 3662 | g_print("Running external filter: %s\n", run); | 3661 | g_print("Running external filter: %s\n", run); |
3199 | 3663 | int result = system(run); | 3662 | int result = system(run); |
3200 | 3664 | 3663 | ||
3202 | 3665 | if(result == -1) | 3664 | if (result == -1) |
3203 | 3666 | g_warning("Could not run external filter: %s\n", run); | 3665 | g_warning("Could not run external filter: %s\n", run); |
3204 | 3667 | } | 3666 | } |
3205 | 3668 | 3667 | ||
3206 | @@ -3671,7 +3670,7 @@ | |||
3207 | 3671 | if (pb) { | 3670 | if (pb) { |
3208 | 3672 | // Create the repr for the image | 3671 | // Create the repr for the image |
3209 | 3673 | // TODO: avoid unnecessary roundtrip between data URI and decoded pixbuf | 3672 | // TODO: avoid unnecessary roundtrip between data URI and decoded pixbuf |
3211 | 3674 | Inkscape::XML::Node * repr = xml_doc->createElement("svg:image"); | 3673 | Inkscape::XML::Node *repr = xml_doc->createElement("svg:image"); |
3212 | 3675 | sp_embed_image(repr, pb); | 3674 | sp_embed_image(repr, pb); |
3213 | 3676 | if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid | 3675 | if (res == Inkscape::Util::Quantity::convert(1, "in", "px")) { // for default 96 dpi, snap it to pixel grid |
3214 | 3677 | sp_repr_set_svg_double(repr, "width", width); | 3676 | sp_repr_set_svg_double(repr, "width", width); |
3215 | @@ -3682,7 +3681,7 @@ | |||
3216 | 3682 | } | 3681 | } |
3217 | 3683 | 3682 | ||
3218 | 3684 | // Write transform | 3683 | // Write transform |
3220 | 3685 | gchar *c=sp_svg_transform_write(t); | 3684 | gchar *c = sp_svg_transform_write(t); |
3221 | 3686 | repr->setAttribute("transform", c); | 3685 | repr->setAttribute("transform", c); |
3222 | 3687 | g_free(c); | 3686 | g_free(c); |
3223 | 3688 | 3687 | ||
3224 | @@ -3701,8 +3700,7 @@ | |||
3225 | 3701 | g_object_unref(pb); | 3700 | g_object_unref(pb); |
3226 | 3702 | 3701 | ||
3227 | 3703 | // Complete undoable transaction | 3702 | // Complete undoable transaction |
3230 | 3704 | DocumentUndo::done(document, SP_VERB_SELECTION_CREATE_BITMAP, | 3703 | DocumentUndo::done(document, SP_VERB_SELECTION_CREATE_BITMAP, _("Create bitmap")); |
3229 | 3705 | _("Create bitmap")); | ||
3231 | 3706 | } | 3704 | } |
3232 | 3707 | 3705 | ||
3233 | 3708 | desktop->clearWaitingCursor(); | 3706 | desktop->clearWaitingCursor(); |
3234 | @@ -3722,18 +3720,19 @@ | |||
3235 | 3722 | if (desktop == NULL) { | 3720 | if (desktop == NULL) { |
3236 | 3723 | return; | 3721 | return; |
3237 | 3724 | } | 3722 | } |
3239 | 3725 | SPDocument* doc = desktop->getDocument(); | 3723 | SPDocument *doc = desktop->getDocument(); |
3240 | 3726 | Inkscape::XML::Document *xml_doc = doc->getReprDoc(); | 3724 | Inkscape::XML::Document *xml_doc = doc->getReprDoc(); |
3241 | 3727 | 3725 | ||
3242 | 3728 | Inkscape::Selection *selection = desktop->getSelection(); | 3726 | Inkscape::Selection *selection = desktop->getSelection(); |
3243 | 3729 | if (selection->isEmpty()) { | 3727 | if (selection->isEmpty()) { |
3245 | 3730 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to create clippath or mask from.")); | 3728 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
3246 | 3729 | _("Select <b>object(s)</b> to create clippath or mask from.")); | ||
3247 | 3731 | return; | 3730 | return; |
3248 | 3732 | } | 3731 | } |
3253 | 3733 | 3732 | ||
3254 | 3734 | std::vector<Inkscape::XML::Node*> p(selection->reprList()); | 3733 | std::vector<Inkscape::XML::Node *> p(selection->reprList()); |
3255 | 3735 | 3734 | ||
3256 | 3736 | sort(p.begin(),p.end(),sp_repr_compare_position_bool); | 3735 | sort(p.begin(), p.end(), sp_repr_compare_position_bool); |
3257 | 3737 | 3736 | ||
3258 | 3738 | selection->clear(); | 3737 | selection->clear(); |
3259 | 3739 | 3738 | ||
3260 | @@ -3742,21 +3741,23 @@ | |||
3261 | 3742 | 3741 | ||
3262 | 3743 | Inkscape::XML::Node *inner = xml_doc->createElement("svg:g"); | 3742 | Inkscape::XML::Node *inner = xml_doc->createElement("svg:g"); |
3263 | 3744 | inner->setAttribute("inkscape:label", "Clip"); | 3743 | inner->setAttribute("inkscape:label", "Clip"); |
3267 | 3745 | 3744 | ||
3268 | 3746 | for(std::vector<Inkscape::XML::Node*>::const_iterator i=p.begin();i!=p.end();i++){ | 3745 | for (std::vector<Inkscape::XML::Node *>::const_iterator i = p.begin(); i != p.end(); i++) { |
3269 | 3747 | Inkscape::XML::Node *current = *i; | 3746 | Inkscape::XML::Node *current = *i; |
3270 | 3748 | 3747 | ||
3271 | 3749 | if (current->parent() == topmost_parent) { | 3748 | if (current->parent() == topmost_parent) { |
3272 | 3750 | Inkscape::XML::Node *spnew = current->duplicate(xml_doc); | 3749 | Inkscape::XML::Node *spnew = current->duplicate(xml_doc); |
3273 | 3751 | sp_repr_unparent(current); | 3750 | sp_repr_unparent(current); |
3274 | 3752 | inner->appendChild(spnew); | 3751 | inner->appendChild(spnew); |
3275 | 3753 | Inkscape::GC::release(spnew); | 3752 | Inkscape::GC::release(spnew); |
3279 | 3754 | topmost --; // only reduce count for those items deleted from topmost_parent | 3753 | topmost--; // only reduce count for those items deleted from topmost_parent |
3280 | 3755 | } else { // move it to topmost_parent first | 3754 | } else { // move it to topmost_parent first |
3281 | 3756 | std::vector<Inkscape::XML::Node*> temp_clip; | 3755 | std::vector<Inkscape::XML::Node *> temp_clip; |
3282 | 3757 | 3756 | ||
3285 | 3758 | // At this point, current may already have no item, due to its being a clone whose original is already moved away | 3757 | // At this point, current may already have no item, due to its being a clone whose original is already moved |
3286 | 3759 | // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent transform | 3758 | // away |
3287 | 3759 | // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent | ||
3288 | 3760 | // transform | ||
3289 | 3760 | gchar const *t_str = current->attribute("transform"); | 3761 | gchar const *t_str = current->attribute("transform"); |
3290 | 3761 | Geom::Affine item_t(Geom::identity()); | 3762 | Geom::Affine item_t(Geom::identity()); |
3291 | 3762 | if (t_str) | 3763 | if (t_str) |
3292 | @@ -3773,7 +3774,8 @@ | |||
3293 | 3773 | sp_repr_unparent(current); | 3774 | sp_repr_unparent(current); |
3294 | 3774 | 3775 | ||
3295 | 3775 | // paste into topmost_parent (temporarily) | 3776 | // paste into topmost_parent (temporarily) |
3297 | 3776 | std::vector<Inkscape::XML::Node*> copied = sp_selection_paste_impl(doc, doc->getObjectByRepr(topmost_parent), temp_clip); | 3777 | std::vector<Inkscape::XML::Node *> copied = |
3298 | 3778 | sp_selection_paste_impl(doc, doc->getObjectByRepr(topmost_parent), temp_clip); | ||
3299 | 3777 | if (!copied.empty()) { // if success, | 3779 | if (!copied.empty()) { // if success, |
3300 | 3778 | // take pasted object (now in topmost_parent) | 3780 | // take pasted object (now in topmost_parent) |
3301 | 3779 | Inkscape::XML::Node *in_topmost = copied.back(); | 3781 | Inkscape::XML::Node *in_topmost = copied.back(); |
3302 | @@ -3787,12 +3789,12 @@ | |||
3303 | 3787 | } | 3789 | } |
3304 | 3788 | } | 3790 | } |
3305 | 3789 | } | 3791 | } |
3307 | 3790 | 3792 | ||
3308 | 3791 | Inkscape::XML::Node *outer = xml_doc->createElement("svg:g"); | 3793 | Inkscape::XML::Node *outer = xml_doc->createElement("svg:g"); |
3309 | 3792 | outer->appendChild(inner); | 3794 | outer->appendChild(inner); |
3310 | 3793 | topmost_parent->appendChild(outer); | 3795 | topmost_parent->appendChild(outer); |
3311 | 3794 | outer->setPosition(topmost + 1); | 3796 | outer->setPosition(topmost + 1); |
3313 | 3795 | 3797 | ||
3314 | 3796 | Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); | 3798 | Inkscape::XML::Node *clone = xml_doc->createElement("svg:use"); |
3315 | 3797 | clone->setAttribute("x", "0", false); | 3799 | clone->setAttribute("x", "0", false); |
3316 | 3798 | clone->setAttribute("y", "0", false); | 3800 | clone->setAttribute("y", "0", false); |
3317 | @@ -3802,16 +3804,16 @@ | |||
3318 | 3802 | clone->setAttribute("inkscape:transform-center-y", inner->attribute("inkscape:transform-center-y"), false); | 3804 | clone->setAttribute("inkscape:transform-center-y", inner->attribute("inkscape:transform-center-y"), false); |
3319 | 3803 | 3805 | ||
3320 | 3804 | const Geom::Affine maskTransform(Geom::Affine::identity()); | 3806 | const Geom::Affine maskTransform(Geom::Affine::identity()); |
3322 | 3805 | std::vector<Inkscape::XML::Node*> templist; | 3807 | std::vector<Inkscape::XML::Node *> templist; |
3323 | 3806 | templist.push_back(clone); | 3808 | templist.push_back(clone); |
3324 | 3807 | // add the new clone to the top of the original's parent | 3809 | // add the new clone to the top of the original's parent |
3325 | 3808 | gchar const *mask_id = SPClipPath::create(templist, doc, &maskTransform); | 3810 | gchar const *mask_id = SPClipPath::create(templist, doc, &maskTransform); |
3328 | 3809 | 3811 | ||
3329 | 3810 | 3812 | ||
3330 | 3811 | outer->setAttribute("clip-path", g_strdup_printf("url(#%s)", mask_id)); | 3813 | outer->setAttribute("clip-path", g_strdup_printf("url(#%s)", mask_id)); |
3331 | 3812 | 3814 | ||
3332 | 3813 | Inkscape::GC::release(clone); | 3815 | Inkscape::GC::release(clone); |
3334 | 3814 | 3816 | ||
3335 | 3815 | selection->set(outer); | 3817 | selection->set(outer); |
3336 | 3816 | DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Create Clip Group")); | 3818 | DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Create Clip Group")); |
3337 | 3817 | } | 3819 | } |
3338 | @@ -3838,11 +3840,13 @@ | |||
3339 | 3838 | 3840 | ||
3340 | 3839 | // check if something is selected | 3841 | // check if something is selected |
3341 | 3840 | bool is_empty = selection->isEmpty(); | 3842 | bool is_empty = selection->isEmpty(); |
3344 | 3841 | if ( apply_to_layer && is_empty) { | 3843 | if (apply_to_layer && is_empty) { |
3345 | 3842 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to create clippath or mask from.")); | 3844 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
3346 | 3845 | _("Select <b>object(s)</b> to create clippath or mask from.")); | ||
3347 | 3843 | return; | 3846 | return; |
3350 | 3844 | } else if (!apply_to_layer && ( is_empty || selection->itemList().size()==1 )) { | 3847 | } else if (!apply_to_layer && (is_empty || selection->itemList().size() == 1)) { |
3351 | 3845 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select mask object and <b>object(s)</b> to apply clippath or mask to.")); | 3848 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
3352 | 3849 | _("Select mask object and <b>object(s)</b> to apply clippath or mask to.")); | ||
3353 | 3846 | return; | 3850 | return; |
3354 | 3847 | } | 3851 | } |
3355 | 3848 | 3852 | ||
3356 | @@ -3856,18 +3860,18 @@ | |||
3357 | 3856 | 3860 | ||
3358 | 3857 | doc->ensureUpToDate(); | 3861 | doc->ensureUpToDate(); |
3359 | 3858 | 3862 | ||
3361 | 3859 | std::vector<SPItem*> items(selection->itemList()); | 3863 | std::vector<SPItem *> items(selection->itemList()); |
3362 | 3860 | 3864 | ||
3364 | 3861 | sort(items.begin(),items.end(),sp_object_compare_position_bool); | 3865 | sort(items.begin(), items.end(), sp_object_compare_position_bool); |
3365 | 3862 | 3866 | ||
3366 | 3863 | // See lp bug #542004 | 3867 | // See lp bug #542004 |
3367 | 3864 | selection->clear(); | 3868 | selection->clear(); |
3368 | 3865 | 3869 | ||
3369 | 3866 | // create a list of duplicates | 3870 | // create a list of duplicates |
3374 | 3867 | std::vector<Inkscape::XML::Node*> mask_items; | 3871 | std::vector<Inkscape::XML::Node *> mask_items; |
3375 | 3868 | std::vector<SPItem*> apply_to_items; | 3872 | std::vector<SPItem *> apply_to_items; |
3376 | 3869 | std::vector<SPItem*> items_to_delete; | 3873 | std::vector<SPItem *> items_to_delete; |
3377 | 3870 | std::vector<SPItem*> items_to_select; | 3874 | std::vector<SPItem *> items_to_select; |
3378 | 3871 | 3875 | ||
3379 | 3872 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); | 3876 | Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
3380 | 3873 | bool topmost = prefs->getBool("/options/maskobject/topmost", true); | 3877 | bool topmost = prefs->getBool("/options/maskobject/topmost", true); |
3381 | @@ -3879,12 +3883,11 @@ | |||
3382 | 3879 | apply_to_items.push_back(SP_ITEM(desktop->currentLayer())); | 3883 | apply_to_items.push_back(SP_ITEM(desktop->currentLayer())); |
3383 | 3880 | } | 3884 | } |
3384 | 3881 | 3885 | ||
3389 | 3882 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++) { | 3886 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
3390 | 3883 | if((!topmost && !apply_to_layer && *i == items.front()) | 3887 | if ((!topmost && !apply_to_layer && *i == items.front()) || |
3391 | 3884 | || (topmost && !apply_to_layer && *i == items.back()) | 3888 | (topmost && !apply_to_layer && *i == items.back()) || apply_to_layer) { |
3388 | 3885 | || apply_to_layer){ | ||
3392 | 3886 | 3889 | ||
3394 | 3887 | Geom::Affine oldtr=(*i)->transform; | 3890 | Geom::Affine oldtr = (*i)->transform; |
3395 | 3888 | (*i)->doWriteTransform((*i)->getRepr(), (*i)->i2doc_affine()); | 3891 | (*i)->doWriteTransform((*i)->getRepr(), (*i)->i2doc_affine()); |
3396 | 3889 | Inkscape::XML::Node *dup = (*i)->getRepr()->duplicate(xml_doc); | 3892 | Inkscape::XML::Node *dup = (*i)->getRepr()->duplicate(xml_doc); |
3397 | 3890 | (*i)->doWriteTransform((*i)->getRepr(), oldtr); | 3893 | (*i)->doWriteTransform((*i)->getRepr(), oldtr); |
3398 | @@ -3892,12 +3895,11 @@ | |||
3399 | 3892 | 3895 | ||
3400 | 3893 | if (remove_original) { | 3896 | if (remove_original) { |
3401 | 3894 | items_to_delete.push_back(*i); | 3897 | items_to_delete.push_back(*i); |
3404 | 3895 | } | 3898 | } else { |
3403 | 3896 | else { | ||
3405 | 3897 | items_to_select.push_back(*i); | 3899 | items_to_select.push_back(*i); |
3406 | 3898 | } | 3900 | } |
3409 | 3899 | continue; | 3901 | continue; |
3410 | 3900 | }else{ | 3902 | } else { |
3411 | 3901 | apply_to_items.push_back(*i); | 3903 | apply_to_items.push_back(*i); |
3412 | 3902 | items_to_select.push_back(*i); | 3904 | items_to_select.push_back(*i); |
3413 | 3903 | } | 3905 | } |
3414 | @@ -3913,9 +3915,9 @@ | |||
3415 | 3913 | // make a note we should ungroup this when unsetting mask | 3915 | // make a note we should ungroup this when unsetting mask |
3416 | 3914 | group->setAttribute("inkscape:groupmode", "maskhelper"); | 3916 | group->setAttribute("inkscape:groupmode", "maskhelper"); |
3417 | 3915 | 3917 | ||
3421 | 3916 | std::vector<Inkscape::XML::Node*> reprs_to_group; | 3918 | std::vector<Inkscape::XML::Node *> reprs_to_group; |
3422 | 3917 | for (std::vector<SPItem*>::const_iterator i = apply_to_items.begin(); i != apply_to_items.end(); i++) { | 3919 | for (std::vector<SPItem *>::const_iterator i = apply_to_items.begin(); i != apply_to_items.end(); i++) { |
3423 | 3918 | reprs_to_group.push_back(static_cast<SPObject*>(*i)->getRepr()); | 3920 | reprs_to_group.push_back(static_cast<SPObject *>(*i)->getRepr()); |
3424 | 3919 | } | 3921 | } |
3425 | 3920 | items_to_select.clear(); | 3922 | items_to_select.clear(); |
3426 | 3921 | 3923 | ||
3427 | @@ -3923,9 +3925,9 @@ | |||
3428 | 3923 | 3925 | ||
3429 | 3924 | // apply clip/mask only to newly created group | 3926 | // apply clip/mask only to newly created group |
3430 | 3925 | apply_to_items.clear(); | 3927 | apply_to_items.clear(); |
3432 | 3926 | apply_to_items.push_back(dynamic_cast<SPItem*>(doc->getObjectByRepr(group))); | 3928 | apply_to_items.push_back(dynamic_cast<SPItem *>(doc->getObjectByRepr(group))); |
3433 | 3927 | 3929 | ||
3435 | 3928 | items_to_select.push_back((SPItem*)(doc->getObjectByRepr(group))); | 3930 | items_to_select.push_back((SPItem *)(doc->getObjectByRepr(group))); |
3436 | 3929 | 3931 | ||
3437 | 3930 | Inkscape::GC::release(group); | 3932 | Inkscape::GC::release(group); |
3438 | 3931 | } | 3933 | } |
3439 | @@ -3935,13 +3937,13 @@ | |||
3440 | 3935 | 3937 | ||
3441 | 3936 | 3938 | ||
3442 | 3937 | gchar const *attributeName = apply_clip_path ? "clip-path" : "mask"; | 3939 | gchar const *attributeName = apply_clip_path ? "clip-path" : "mask"; |
3444 | 3938 | for (std::vector<SPItem*>::const_reverse_iterator i = apply_to_items.rbegin(); i != apply_to_items.rend(); i++) { | 3940 | for (std::vector<SPItem *>::const_reverse_iterator i = apply_to_items.rbegin(); i != apply_to_items.rend(); i++) { |
3445 | 3939 | SPItem *item = reinterpret_cast<SPItem *>(*i); | 3941 | SPItem *item = reinterpret_cast<SPItem *>(*i); |
3446 | 3940 | // inverted object transform should be applied to a mask object, | 3942 | // inverted object transform should be applied to a mask object, |
3447 | 3941 | // as mask is calculated in user space (after applying transform) | 3943 | // as mask is calculated in user space (after applying transform) |
3451 | 3942 | std::vector<Inkscape::XML::Node*> mask_items_dup; | 3944 | std::vector<Inkscape::XML::Node *> mask_items_dup; |
3452 | 3943 | for(std::vector<Inkscape::XML::Node*>::const_iterator it=mask_items.begin();it!=mask_items.end();it++) | 3945 | for (std::vector<Inkscape::XML::Node *>::const_iterator it = mask_items.begin(); it != mask_items.end(); it++) |
3453 | 3944 | mask_items_dup.push_back((*it)->duplicate(xml_doc)); | 3946 | mask_items_dup.push_back((*it)->duplicate(xml_doc)); |
3454 | 3945 | Inkscape::XML::Node *current = SP_OBJECT(*i)->getRepr(); | 3947 | Inkscape::XML::Node *current = SP_OBJECT(*i)->getRepr(); |
3455 | 3946 | // Node to apply mask to | 3948 | // Node to apply mask to |
3456 | 3947 | Inkscape::XML::Node *apply_mask_to = current; | 3949 | Inkscape::XML::Node *apply_mask_to = current; |
3457 | @@ -3962,7 +3964,7 @@ | |||
3458 | 3962 | // Apply clip/mask to group instead | 3964 | // Apply clip/mask to group instead |
3459 | 3963 | apply_mask_to = group; | 3965 | apply_mask_to = group; |
3460 | 3964 | 3966 | ||
3462 | 3965 | items_to_select.push_back(item = (SPItem*)(doc->getObjectByRepr(group))); | 3967 | items_to_select.push_back(item = (SPItem *)(doc->getObjectByRepr(group))); |
3463 | 3966 | Inkscape::GC::release(spnew); | 3968 | Inkscape::GC::release(spnew); |
3464 | 3967 | Inkscape::GC::release(group); | 3969 | Inkscape::GC::release(group); |
3465 | 3968 | } | 3970 | } |
3466 | @@ -3977,11 +3979,10 @@ | |||
3467 | 3977 | } | 3979 | } |
3468 | 3978 | 3980 | ||
3469 | 3979 | apply_mask_to->setAttribute(attributeName, Glib::ustring("url(#") + mask_id + ')'); | 3981 | apply_mask_to->setAttribute(attributeName, Glib::ustring("url(#") + mask_id + ')'); |
3470 | 3980 | |||
3471 | 3981 | } | 3982 | } |
3472 | 3982 | 3983 | ||
3475 | 3983 | for (std::vector<SPItem*>::const_iterator i = items_to_delete.begin(); i != items_to_delete.end(); i++) { | 3984 | for (std::vector<SPItem *>::const_iterator i = items_to_delete.begin(); i != items_to_delete.end(); i++) { |
3476 | 3984 | SPObject *item = reinterpret_cast<SPObject*>(*i); | 3985 | SPObject *item = reinterpret_cast<SPObject *>(*i); |
3477 | 3985 | item->deleteObject(false); | 3986 | item->deleteObject(false); |
3478 | 3986 | items_to_select.erase(remove(items_to_select.begin(), items_to_select.end(), item), items_to_select.end()); | 3987 | items_to_select.erase(remove(items_to_select.begin(), items_to_select.end(), item), items_to_select.end()); |
3479 | 3987 | } | 3988 | } |
3480 | @@ -3995,7 +3996,8 @@ | |||
3481 | 3995 | } | 3996 | } |
3482 | 3996 | } | 3997 | } |
3483 | 3997 | 3998 | ||
3485 | 3998 | void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { | 3999 | void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) |
3486 | 4000 | { | ||
3487 | 3999 | if (desktop == NULL) { | 4001 | if (desktop == NULL) { |
3488 | 4000 | return; | 4002 | return; |
3489 | 4001 | } | 4003 | } |
3490 | @@ -4006,7 +4008,8 @@ | |||
3491 | 4006 | 4008 | ||
3492 | 4007 | // check if something is selected | 4009 | // check if something is selected |
3493 | 4008 | if (selection->isEmpty()) { | 4010 | if (selection->isEmpty()) { |
3495 | 4009 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to remove clippath or mask from.")); | 4011 | desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, |
3496 | 4012 | _("Select <b>object(s)</b> to remove clippath or mask from.")); | ||
3497 | 4010 | return; | 4013 | return; |
3498 | 4011 | } | 4014 | } |
3499 | 4012 | 4015 | ||
3500 | @@ -4016,18 +4019,18 @@ | |||
3501 | 4016 | doc->ensureUpToDate(); | 4019 | doc->ensureUpToDate(); |
3502 | 4017 | 4020 | ||
3503 | 4018 | gchar const *attributeName = apply_clip_path ? "clip-path" : "mask"; | 4021 | gchar const *attributeName = apply_clip_path ? "clip-path" : "mask"; |
3505 | 4019 | std::map<SPObject*,SPItem*> referenced_objects; | 4022 | std::map<SPObject *, SPItem *> referenced_objects; |
3506 | 4020 | 4023 | ||
3508 | 4021 | std::vector<SPItem*> items(selection->itemList()); | 4024 | std::vector<SPItem *> items(selection->itemList()); |
3509 | 4022 | selection->clear(); | 4025 | selection->clear(); |
3510 | 4023 | 4026 | ||
3511 | 4024 | GSList *items_to_ungroup = NULL; | 4027 | GSList *items_to_ungroup = NULL; |
3513 | 4025 | std::vector<SPItem*> items_to_select(items); | 4028 | std::vector<SPItem *> items_to_select(items); |
3514 | 4026 | 4029 | ||
3515 | 4027 | 4030 | ||
3516 | 4028 | // SPObject* refers to a group containing the clipped path or mask itself, | 4031 | // SPObject* refers to a group containing the clipped path or mask itself, |
3517 | 4029 | // whereas SPItem* refers to the item being clipped or masked | 4032 | // whereas SPItem* refers to the item being clipped or masked |
3519 | 4030 | for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){ | 4033 | for (std::vector<SPItem *>::const_iterator i = items.begin(); i != items.end(); i++) { |
3520 | 4031 | if (remove_original) { | 4034 | if (remove_original) { |
3521 | 4032 | // remember referenced mask/clippath, so orphaned masks can be moved back to document | 4035 | // remember referenced mask/clippath, so orphaned masks can be moved back to document |
3522 | 4033 | SPItem *item = *i; | 4036 | SPItem *item = *i; |
3523 | @@ -4049,26 +4052,25 @@ | |||
3524 | 4049 | 4052 | ||
3525 | 4050 | SPGroup *group = dynamic_cast<SPGroup *>(*i); | 4053 | SPGroup *group = dynamic_cast<SPGroup *>(*i); |
3526 | 4051 | if (ungroup_masked && group) { | 4054 | if (ungroup_masked && group) { |
3535 | 4052 | // if we had previously enclosed masked object in group, | 4055 | // if we had previously enclosed masked object in group, |
3536 | 4053 | // add it to list so we can ungroup it later | 4056 | // add it to list so we can ungroup it later |
3537 | 4054 | 4057 | ||
3538 | 4055 | // ungroup only groups we created when setting clip/mask | 4058 | // ungroup only groups we created when setting clip/mask |
3539 | 4056 | if (group->layerMode() == SPGroup::MASK_HELPER) { | 4059 | if (group->layerMode() == SPGroup::MASK_HELPER) { |
3540 | 4057 | items_to_ungroup = g_slist_prepend(items_to_ungroup, group); | 4060 | items_to_ungroup = g_slist_prepend(items_to_ungroup, group); |
3541 | 4058 | } | 4061 | } |
3534 | 4059 | |||
3542 | 4060 | } | 4062 | } |
3543 | 4061 | } | 4063 | } |
3544 | 4062 | 4064 | ||
3545 | 4063 | // restore mask objects into a document | 4065 | // restore mask objects into a document |
3547 | 4064 | for ( std::map<SPObject*,SPItem*>::iterator it = referenced_objects.begin() ; it != referenced_objects.end() ; ++it) { | 4066 | for (std::map<SPObject *, SPItem *>::iterator it = referenced_objects.begin(); it != referenced_objects.end(); |
3548 | 4067 | ++it) { | ||
3549 | 4065 | SPObject *obj = (*it).first; // Group containing the clipped paths or masks | 4068 | SPObject *obj = (*it).first; // Group containing the clipped paths or masks |
3550 | 4066 | GSList *items_to_move = NULL; | 4069 | GSList *items_to_move = NULL; |
3552 | 4067 | for ( SPObject *child = obj->firstChild() ; child; child = child->getNext() ) { | 4070 | for (SPObject *child = obj->firstChild(); child; child = child->getNext()) { |
3553 | 4068 | // Collect all clipped paths and masks within a single group | 4071 | // Collect all clipped paths and masks within a single group |
3554 | 4069 | Inkscape::XML::Node *copy = child->getRepr()->duplicate(xml_doc); | 4072 | Inkscape::XML::Node *copy = child->getRepr()->duplicate(xml_doc); |
3557 | 4070 | if(copy->attribute("inkscape:original-d") && copy->attribute("inkscape:path-effect")) | 4073 | if (copy->attribute("inkscape:original-d") && copy->attribute("inkscape:path-effect")) { |
3556 | 4071 | { | ||
3558 | 4072 | copy->setAttribute("d", copy->attribute("inkscape:original-d")); | 4074 | copy->setAttribute("d", copy->attribute("inkscape:original-d")); |
3559 | 4073 | } | 4075 | } |
3560 | 4074 | items_to_move = g_slist_prepend(items_to_move, copy); | 4076 | items_to_move = g_slist_prepend(items_to_move, copy); |
3561 | @@ -4104,13 +4106,13 @@ | |||
3562 | 4104 | } | 4106 | } |
3563 | 4105 | 4107 | ||
3564 | 4106 | // ungroup marked groups added when setting mask | 4108 | // ungroup marked groups added when setting mask |
3566 | 4107 | for (GSList *i = items_to_ungroup ; NULL != i ; i = i->next) { | 4109 | for (GSList *i = items_to_ungroup; NULL != i; i = i->next) { |
3567 | 4108 | SPGroup *group = dynamic_cast<SPGroup *>(static_cast<SPObject *>(i->data)); | 4110 | SPGroup *group = dynamic_cast<SPGroup *>(static_cast<SPObject *>(i->data)); |
3568 | 4109 | if (group) { | 4111 | if (group) { |
3569 | 4110 | items_to_select.erase(remove(items_to_select.begin(), items_to_select.end(), group), items_to_select.end()); | 4112 | items_to_select.erase(remove(items_to_select.begin(), items_to_select.end(), group), items_to_select.end()); |
3571 | 4111 | std::vector<SPItem*> children; | 4113 | std::vector<SPItem *> children; |
3572 | 4112 | sp_item_group_ungroup(group, children, false); | 4114 | sp_item_group_ungroup(group, children, false); |
3574 | 4113 | items_to_select.insert(items_to_select.end(),children.rbegin(),children.rend()); | 4115 | items_to_select.insert(items_to_select.end(), children.rbegin(), children.rend()); |
3575 | 4114 | } else { | 4116 | } else { |
3576 | 4115 | g_assert_not_reached(); | 4117 | g_assert_not_reached(); |
3577 | 4116 | } | 4118 | } |
3578 | @@ -4133,8 +4135,7 @@ | |||
3579 | 4133 | * "fit-margin-..." attributes. See SPDocument::fitToRect. | 4135 | * "fit-margin-..." attributes. See SPDocument::fitToRect. |
3580 | 4134 | * \return true if an undoable change should be recorded. | 4136 | * \return true if an undoable change should be recorded. |
3581 | 4135 | */ | 4137 | */ |
3584 | 4136 | bool | 4138 | bool fit_canvas_to_selection(SPDesktop *desktop, bool with_margins) |
3583 | 4137 | fit_canvas_to_selection(SPDesktop *desktop, bool with_margins) | ||
3585 | 4138 | { | 4139 | { |
3586 | 4139 | g_return_val_if_fail(desktop != NULL, false); | 4140 | g_return_val_if_fail(desktop != NULL, false); |
3587 | 4140 | SPDocument *doc = desktop->getDocument(); | 4141 | SPDocument *doc = desktop->getDocument(); |
3588 | @@ -4158,12 +4159,10 @@ | |||
3589 | 4158 | /** | 4159 | /** |
3590 | 4159 | * Fit canvas to the bounding box of the selection, as an undoable action. | 4160 | * Fit canvas to the bounding box of the selection, as an undoable action. |
3591 | 4160 | */ | 4161 | */ |
3594 | 4161 | void | 4162 | void verb_fit_canvas_to_selection(SPDesktop *const desktop) |
3593 | 4162 | verb_fit_canvas_to_selection(SPDesktop *const desktop) | ||
3595 | 4163 | { | 4163 | { |
3596 | 4164 | if (fit_canvas_to_selection(desktop)) { | 4164 | if (fit_canvas_to_selection(desktop)) { |
3599 | 4165 | DocumentUndo::done(desktop->getDocument(), SP_VERB_FIT_CANVAS_TO_SELECTION, | 4165 | DocumentUndo::done(desktop->getDocument(), SP_VERB_FIT_CANVAS_TO_SELECTION, _("Fit Page to Selection")); |
3598 | 4166 | _("Fit Page to Selection")); | ||
3600 | 4167 | } | 4166 | } |
3601 | 4168 | } | 4167 | } |
3602 | 4169 | 4168 | ||
3603 | @@ -4171,8 +4170,7 @@ | |||
3604 | 4171 | * \param with_margins margins defined in the xml under <sodipodi:namedview> | 4170 | * \param with_margins margins defined in the xml under <sodipodi:namedview> |
3605 | 4172 | * "fit-margin-..." attributes. See SPDocument::fitToRect. | 4171 | * "fit-margin-..." attributes. See SPDocument::fitToRect. |
3606 | 4173 | */ | 4172 | */ |
3609 | 4174 | bool | 4173 | bool fit_canvas_to_drawing(SPDocument *doc, bool with_margins) |
3608 | 4175 | fit_canvas_to_drawing(SPDocument *doc, bool with_margins) | ||
3610 | 4176 | { | 4174 | { |
3611 | 4177 | g_return_val_if_fail(doc != NULL, false); | 4175 | g_return_val_if_fail(doc != NULL, false); |
3612 | 4178 | 4176 | ||
3613 | @@ -4187,12 +4185,10 @@ | |||
3614 | 4187 | } | 4185 | } |
3615 | 4188 | } | 4186 | } |
3616 | 4189 | 4187 | ||
3619 | 4190 | void | 4188 | void verb_fit_canvas_to_drawing(SPDesktop *desktop) |
3618 | 4191 | verb_fit_canvas_to_drawing(SPDesktop *desktop) | ||
3620 | 4192 | { | 4189 | { |
3621 | 4193 | if (fit_canvas_to_drawing(desktop->getDocument())) { | 4190 | if (fit_canvas_to_drawing(desktop->getDocument())) { |
3624 | 4194 | DocumentUndo::done(desktop->getDocument(), SP_VERB_FIT_CANVAS_TO_DRAWING, | 4191 | DocumentUndo::done(desktop->getDocument(), SP_VERB_FIT_CANVAS_TO_DRAWING, _("Fit Page to Drawing")); |
3623 | 4195 | _("Fit Page to Drawing")); | ||
3625 | 4196 | } | 4192 | } |
3626 | 4197 | } | 4193 | } |
3627 | 4198 | 4194 | ||
3628 | @@ -4201,23 +4197,24 @@ | |||
3629 | 4201 | * "fit-margin-..." attributes. See SPDocument::fitToRect and | 4197 | * "fit-margin-..." attributes. See SPDocument::fitToRect and |
3630 | 4202 | * ui/dialog/page-sizer. | 4198 | * ui/dialog/page-sizer. |
3631 | 4203 | */ | 4199 | */ |
3633 | 4204 | void fit_canvas_to_selection_or_drawing(SPDesktop *desktop) { | 4200 | void fit_canvas_to_selection_or_drawing(SPDesktop *desktop) |
3634 | 4201 | { | ||
3635 | 4205 | g_return_if_fail(desktop != NULL); | 4202 | g_return_if_fail(desktop != NULL); |
3636 | 4206 | SPDocument *doc = desktop->getDocument(); | 4203 | SPDocument *doc = desktop->getDocument(); |
3637 | 4207 | 4204 | ||
3638 | 4208 | g_return_if_fail(doc != NULL); | 4205 | g_return_if_fail(doc != NULL); |
3639 | 4209 | g_return_if_fail(desktop->selection != NULL); | 4206 | g_return_if_fail(desktop->selection != NULL); |
3640 | 4210 | 4207 | ||
3644 | 4211 | bool const changed = ( desktop->selection->isEmpty() | 4208 | bool const changed = |
3645 | 4212 | ? fit_canvas_to_drawing(doc, true) | 4209 | (desktop->selection->isEmpty() ? fit_canvas_to_drawing(doc, true) : fit_canvas_to_selection(desktop, true)); |
3643 | 4213 | : fit_canvas_to_selection(desktop, true) ); | ||
3646 | 4214 | if (changed) { | 4210 | if (changed) { |
3647 | 4215 | DocumentUndo::done(desktop->getDocument(), SP_VERB_FIT_CANVAS_TO_SELECTION_OR_DRAWING, | 4211 | DocumentUndo::done(desktop->getDocument(), SP_VERB_FIT_CANVAS_TO_SELECTION_OR_DRAWING, |
3648 | 4216 | _("Fit Page to Selection or Drawing")); | 4212 | _("Fit Page to Selection or Drawing")); |
3649 | 4217 | } | 4213 | } |
3650 | 4218 | }; | 4214 | }; |
3651 | 4219 | 4215 | ||
3653 | 4220 | static void itemtree_map(void (*f)(SPItem *, SPDesktop *), SPObject *root, SPDesktop *desktop) { | 4216 | static void itemtree_map(void (*f)(SPItem *, SPDesktop *), SPObject *root, SPDesktop *desktop) |
3654 | 4217 | { | ||
3655 | 4221 | // don't operate on layers | 4218 | // don't operate on layers |
3656 | 4222 | { | 4219 | { |
3657 | 4223 | SPItem *item = dynamic_cast<SPItem *>(root); | 4220 | SPItem *item = dynamic_cast<SPItem *>(root); |
3658 | @@ -4225,8 +4222,8 @@ | |||
3659 | 4225 | f(item, desktop); | 4222 | f(item, desktop); |
3660 | 4226 | } | 4223 | } |
3661 | 4227 | } | 4224 | } |
3664 | 4228 | for ( SPObject::SiblingIterator iter = root->firstChild() ; iter ; ++iter ) { | 4225 | for (SPObject::SiblingIterator iter = root->firstChild(); iter; ++iter) { |
3665 | 4229 | //don't recurse into locked layers | 4226 | // don't recurse into locked layers |
3666 | 4230 | SPItem *item = dynamic_cast<SPItem *>(&*iter); | 4227 | SPItem *item = dynamic_cast<SPItem *>(&*iter); |
3667 | 4231 | if (!(item && desktop->isLayer(item) && item->isLocked())) { | 4228 | if (!(item && desktop->isLayer(item) && item->isLocked())) { |
3668 | 4232 | itemtree_map(f, iter, desktop); | 4229 | itemtree_map(f, iter, desktop); |
3669 | @@ -4234,20 +4231,24 @@ | |||
3670 | 4234 | } | 4231 | } |
3671 | 4235 | } | 4232 | } |
3672 | 4236 | 4233 | ||
3674 | 4237 | static void unlock(SPItem *item, SPDesktop */*desktop*/) { | 4234 | static void unlock(SPItem *item, SPDesktop * /*desktop*/) |
3675 | 4235 | { | ||
3676 | 4238 | if (item->isLocked()) { | 4236 | if (item->isLocked()) { |
3677 | 4239 | item->setLocked(FALSE); | 4237 | item->setLocked(FALSE); |
3678 | 4240 | } | 4238 | } |
3679 | 4241 | } | 4239 | } |
3680 | 4242 | 4240 | ||
3682 | 4243 | static void unhide(SPItem *item, SPDesktop *desktop) { | 4241 | static void unhide(SPItem *item, SPDesktop *desktop) |
3683 | 4242 | { | ||
3684 | 4244 | if (desktop->itemIsHidden(item)) { | 4243 | if (desktop->itemIsHidden(item)) { |
3685 | 4245 | item->setExplicitlyHidden(FALSE); | 4244 | item->setExplicitlyHidden(FALSE); |
3686 | 4246 | } | 4245 | } |
3687 | 4247 | } | 4246 | } |
3688 | 4248 | 4247 | ||
3691 | 4249 | static void process_all(void (*f)(SPItem *, SPDesktop *), SPDesktop *dt, bool layer_only) { | 4248 | static void process_all(void (*f)(SPItem *, SPDesktop *), SPDesktop *dt, bool layer_only) |
3692 | 4250 | if (!dt) return; | 4249 | { |
3693 | 4250 | if (!dt) | ||
3694 | 4251 | return; | ||
3695 | 4251 | 4252 | ||
3696 | 4252 | SPObject *root; | 4253 | SPObject *root; |
3697 | 4253 | if (layer_only) { | 4254 | if (layer_only) { |
3698 | @@ -4259,21 +4260,13 @@ | |||
3699 | 4259 | itemtree_map(f, root, dt); | 4260 | itemtree_map(f, root, dt); |
3700 | 4260 | } | 4261 | } |
3701 | 4261 | 4262 | ||
3717 | 4262 | void unlock_all(SPDesktop *dt) { | 4263 | void unlock_all(SPDesktop *dt) { process_all(&unlock, dt, true); } |
3718 | 4263 | process_all(&unlock, dt, true); | 4264 | |
3719 | 4264 | } | 4265 | void unlock_all_in_all_layers(SPDesktop *dt) { process_all(&unlock, dt, false); } |
3720 | 4265 | 4266 | ||
3721 | 4266 | void unlock_all_in_all_layers(SPDesktop *dt) { | 4267 | void unhide_all(SPDesktop *dt) { process_all(&unhide, dt, true); } |
3722 | 4267 | process_all(&unlock, dt, false); | 4268 | |
3723 | 4268 | } | 4269 | void unhide_all_in_all_layers(SPDesktop *dt) { process_all(&unhide, dt, false); } |
3709 | 4269 | |||
3710 | 4270 | void unhide_all(SPDesktop *dt) { | ||
3711 | 4271 | process_all(&unhide, dt, true); | ||
3712 | 4272 | } | ||
3713 | 4273 | |||
3714 | 4274 | void unhide_all_in_all_layers(SPDesktop *dt) { | ||
3715 | 4275 | process_all(&unhide, dt, false); | ||
3716 | 4276 | } | ||
3724 | 4277 | 4270 | ||
3725 | 4278 | 4271 | ||
3726 | 4279 | /* | 4272 | /* |
3727 | 4280 | 4273 | ||
3728 | === modified file 'src/selection.cpp' | |||
3729 | --- src/selection.cpp 2015-05-12 22:12:43 +0000 | |||
3730 | +++ src/selection.cpp 2015-09-02 11:21:15 +0000 | |||
3731 | @@ -30,6 +30,7 @@ | |||
3732 | 30 | 30 | ||
3733 | 31 | #include "sp-shape.h" | 31 | #include "sp-shape.h" |
3734 | 32 | #include "sp-path.h" | 32 | #include "sp-path.h" |
3735 | 33 | #include "sp-root.h" | ||
3736 | 33 | #include "sp-item-group.h" | 34 | #include "sp-item-group.h" |
3737 | 34 | #include "box3d.h" | 35 | #include "box3d.h" |
3738 | 35 | #include "box3d.h" | 36 | #include "box3d.h" |
3739 | @@ -151,6 +152,12 @@ | |||
3740 | 151 | return ( _objs_set.find(obj)!=_objs_set.end() ); | 152 | return ( _objs_set.find(obj)!=_objs_set.end() ); |
3741 | 152 | } | 153 | } |
3742 | 153 | 154 | ||
3743 | 155 | bool Selection::includes_deeply(SPObject *obj) const{ | ||
3744 | 156 | if(!obj || dynamic_cast<SPRoot*>(obj)){return false;} | ||
3745 | 157 | return (includes(obj) || includes_deeply(obj->parent)); | ||
3746 | 158 | } | ||
3747 | 159 | |||
3748 | 160 | |||
3749 | 154 | void Selection::add(SPObject *obj, bool persist_selection_context/* = false */) { | 161 | void Selection::add(SPObject *obj, bool persist_selection_context/* = false */) { |
3750 | 155 | g_return_if_fail(obj != NULL); | 162 | g_return_if_fail(obj != NULL); |
3751 | 156 | g_return_if_fail(SP_IS_OBJECT(obj)); | 163 | g_return_if_fail(SP_IS_OBJECT(obj)); |
3752 | 157 | 164 | ||
3753 | === modified file 'src/selection.h' | |||
3754 | --- src/selection.h 2015-04-29 22:29:17 +0000 | |||
3755 | +++ src/selection.h 2015-09-02 11:21:15 +0000 | |||
3756 | @@ -209,6 +209,16 @@ | |||
3757 | 209 | } | 209 | } |
3758 | 210 | 210 | ||
3759 | 211 | /** | 211 | /** |
3760 | 212 | * Returns true if the given item is descendant of a selected item. | ||
3761 | 213 | */ | ||
3762 | 214 | bool includes_deeply(SPObject *obj) const; | ||
3763 | 215 | bool includes_deeply(XML::Node *repr) const { | ||
3764 | 216 | return includes_deeply(_objectForXMLNode(repr)); | ||
3765 | 217 | } | ||
3766 | 218 | |||
3767 | 219 | |||
3768 | 220 | |||
3769 | 221 | /** | ||
3770 | 212 | * Returns a single selected object. | 222 | * Returns a single selected object. |
3771 | 213 | * | 223 | * |
3772 | 214 | * @return NULL unless exactly one object is selected | 224 | * @return NULL unless exactly one object is selected |
NB: The diff is huge because i made a clang-format to have all the presentation right, the only non-whitespace parts are lines 1297-1651 and 3728+