46
46
#include "sp-flowtext.h"
47
47
#include "text-editing.h"
49
#include "node-context.h" //For node align/distribute function
49
#include "node-context.h" //For access to ShapeEditor
50
#include "shape-editor.h" //For node align/distribute methods
51
52
#include "tools-switch.h"
116
117
virtual void on_button_click() {
117
118
//Retreive selected objects
118
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
119
SPDesktop *desktop = _dialog.getDesktop();
119
120
if (!desktop) return;
121
122
Inkscape::Selection *selection = sp_desktop_selection(desktop);
152
153
SPItem * thing = *master;
153
154
selected.erase(master);
154
155
//Compute the anchor point
155
NR::Rect b = sp_item_bbox_desktop (thing);
156
mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
157
a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
156
NR::Maybe<NR::Rect> b = sp_item_bbox_desktop (thing);
158
mp = NR::Point(a.mx0 * b->min()[NR::X] + a.mx1 * b->max()[NR::X],
159
a.my0 * b->min()[NR::Y] + a.my1 * b->max()[NR::Y]);
166
171
case AlignAndDistribute::DRAWING:
168
NR::Rect b = sp_item_bbox_desktop
173
NR::Maybe<NR::Rect> b = sp_item_bbox_desktop
169
174
( (SPItem *) sp_document_root (sp_desktop_document (desktop)) );
170
mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
171
a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
176
mp = NR::Point(a.mx0 * b->min()[NR::X] + a.mx1 * b->max()[NR::X],
177
a.my0 * b->min()[NR::Y] + a.my1 * b->max()[NR::Y]);
175
184
case AlignAndDistribute::SELECTION:
177
NR::Rect b = selection->bounds();
178
mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
179
a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
186
NR::Maybe<NR::Rect> b = selection->bounds();
188
mp = NR::Point(a.mx0 * b->min()[NR::X] + a.mx1 * b->max()[NR::X],
189
a.my0 * b->min()[NR::Y] + a.my1 * b->max()[NR::Y]);
203
216
sp_document_ensure_up_to_date(sp_desktop_document (desktop));
204
NR::Rect b = sp_item_bbox_desktop (*it);
205
NR::Point const sp(a.sx0 * b.min()[NR::X] + a.sx1 * b.max()[NR::X],
206
a.sy0 * b.min()[NR::Y] + a.sy1 * b.max()[NR::Y]);
207
NR::Point const mp_rel( mp - sp );
208
if (LInfty(mp_rel) > 1e-9) {
209
sp_item_move_rel(*it, NR::translate(mp_rel));
217
NR::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
219
NR::Point const sp(a.sx0 * b->min()[NR::X] + a.sx1 * b->max()[NR::X],
220
a.sy0 * b->min()[NR::Y] + a.sy1 * b->max()[NR::Y]);
221
NR::Point const mp_rel( mp - sp );
222
if (LInfty(mp_rel) > 1e-9) {
223
sp_item_move_rel(*it, NR::translate(mp_rel));
215
230
prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
218
sp_document_done ( sp_desktop_document (desktop) );
233
sp_document_done ( sp_desktop_document (desktop) , SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
247
BBoxSort(SPItem *pItem, NR::Dim2 orientation, double kBegin, double kEnd) :
263
BBoxSort(SPItem *pItem, NR::Rect bounds, NR::Dim2 orientation, double kBegin, double kEnd) :
249
bbox (sp_item_bbox_desktop (pItem))
251
267
anchor = kBegin * bbox.min()[orientation] + kEnd * bbox.max()[orientation];
285
301
virtual void on_button_click() {
286
302
//Retreive selected objects
287
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
303
SPDesktop *desktop = _dialog.getDesktop();
288
304
if (!desktop) return;
290
306
Inkscape::Selection *selection = sp_desktop_selection(desktop);
306
322
it != selected.end();
309
BBoxSort b (*it, _orientation, _kBegin, _kEnd);
325
NR::Maybe<NR::Rect> bbox = sp_item_bbox_desktop(*it);
327
sorted.push_back(BBoxSort(*it, *bbox, _orientation, _kBegin, _kEnd));
312
330
//sort bbox by anchors
313
331
std::sort(sorted.begin(), sorted.end());
374
392
prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
377
sp_document_done ( sp_desktop_document (desktop) );
395
sp_document_done ( sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
407
426
virtual void on_button_click()
410
if (!SP_ACTIVE_DESKTOP) return;
411
SPEventContext *event_context = sp_desktop_event_context(SP_ACTIVE_DESKTOP);
429
if (!_dialog.getDesktop()) return;
430
SPEventContext *event_context = sp_desktop_event_context(_dialog.getDesktop());
412
431
if (!SP_IS_NODE_CONTEXT (event_context)) return ;
414
Inkscape::NodePath::Path *nodepath = SP_NODE_CONTEXT (event_context)->nodepath;
415
if (!nodepath) return;
417
sp_nodepath_selected_distribute(nodepath, _orientation);
434
SP_NODE_CONTEXT (event_context)->shape_editor->distribute(_orientation);
419
sp_nodepath_selected_align(nodepath, _orientation);
436
SP_NODE_CONTEXT (event_context)->shape_editor->align(_orientation);
470
487
virtual void on_button_click()
472
if (!SP_ACTIVE_DESKTOP) return;
489
if (!_dialog.getDesktop()) return;
474
491
// see comment in ActionAlign above
475
492
int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
478
495
// xGap and yGap are the minimum space required between bounding rectangles.
479
496
double const xGap = removeOverlapXGap.get_value();
480
497
double const yGap = removeOverlapYGap.get_value();
481
removeoverlap(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList(),
498
removeoverlap(sp_desktop_selection(_dialog.getDesktop())->itemList(),
484
501
// restore compensation setting
485
502
prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
487
sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP));
504
sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
505
_("Remove overlaps"));
503
521
virtual void on_button_click()
505
if (!SP_ACTIVE_DESKTOP) return;
523
if (!_dialog.getDesktop()) return;
507
525
// see comment in ActionAlign above
508
526
int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
509
527
prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
511
graphlayout(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
529
graphlayout(sp_desktop_selection(_dialog.getDesktop())->itemList());
513
531
// restore compensation setting
514
532
prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
516
sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP));
534
sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
535
_("Arrange connector network"));
532
551
virtual void on_button_click()
534
if (!SP_ACTIVE_DESKTOP) return;
553
if (!_dialog.getDesktop()) return;
536
555
// see comment in ActionAlign above
537
556
int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
538
557
prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
540
unclump ((GSList *) sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
559
unclump ((GSList *) sp_desktop_selection(_dialog.getDesktop())->itemList());
542
561
// restore compensation setting
543
562
prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
545
sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP));
564
sp_document_done (sp_desktop_document (_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
574
594
//Check 2 or more selected objects
575
595
if (selected.size() < 2) return;
597
NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
577
602
// This bbox is cached between calls to randomize, so that there's no growth nor shrink
578
603
// nor drift on sequential randomizations. Discard cache on global (or better active
579
604
// desktop's) selection_change signal.
580
if (!_dialog.randomize_bbox_set) {
581
_dialog.randomize_bbox = selection->bounds();
582
_dialog.randomize_bbox_set = true;
605
if (!_dialog.randomize_bbox) {
606
_dialog.randomize_bbox = *sel_bbox;
585
609
// see comment in ActionAlign above
593
617
sp_document_ensure_up_to_date(sp_desktop_document (desktop));
594
NR::Rect item_box = sp_item_bbox_desktop (*it);
595
// find new center, staying within bbox
596
double x = _dialog.randomize_bbox.min()[NR::X] + item_box.extent(NR::X)/2 +
597
g_random_double_range (0, _dialog.randomize_bbox.extent(NR::X) - item_box.extent(NR::X));
598
double y = _dialog.randomize_bbox.min()[NR::Y] + item_box.extent(NR::Y)/2 +
599
g_random_double_range (0, _dialog.randomize_bbox.extent(NR::Y) - item_box.extent(NR::Y));
600
// displacement is the new center minus old:
601
NR::Point t = NR::Point (x, y) - 0.5*(item_box.max() + item_box.min());
602
sp_item_move_rel(*it, NR::translate(t));
618
NR::Maybe<NR::Rect> item_box = sp_item_bbox_desktop (*it);
620
// find new center, staying within bbox
621
double x = _dialog.randomize_bbox->min()[NR::X] + item_box->extent(NR::X)/2 +
622
g_random_double_range (0, _dialog.randomize_bbox->extent(NR::X) - item_box->extent(NR::X));
623
double y = _dialog.randomize_bbox->min()[NR::Y] + item_box->extent(NR::Y)/2 +
624
g_random_double_range (0, _dialog.randomize_bbox->extent(NR::Y) - item_box->extent(NR::Y));
625
// displacement is the new center minus old:
626
NR::Point t = NR::Point (x, y) - 0.5*(item_box->max() + item_box->min());
627
sp_item_move_rel(*it, NR::translate(t));
605
631
// restore compensation setting
606
632
prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
608
sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP));
634
sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
635
_("Randomize positions"));
734
767
void on_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection *selection, AlignAndDistribute *daad)
736
daad->randomize_bbox_set = false;
769
daad->randomize_bbox = NR::Nothing();
739
772
/////////////////////////////////////////////////////////
744
777
AlignAndDistribute::AlignAndDistribute()
745
: Dialog ("dialogs.align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE),
746
randomize_bbox (NR::Point (0, 0), NR::Point (0, 0)),
778
: UI::Widget::Panel ("", "dialogs.align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE),
779
randomize_bbox(NR::Nothing()),
747
780
_alignFrame(_("Align")),
748
781
_distributeFrame(_("Distribute")),
749
782
_removeOverlapFrame(_("Remove overlaps")),
875
908
_combo.append_text(_("Drawing"));
876
909
_combo.append_text(_("Selection"));
878
_combo.set_active(6);
911
_combo.set_active(prefs_get_int_attribute("dialogs.align", "align-to", 6));
879
912
_combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_ref_change));
881
914
_anchorBox.pack_start(_anchorLabel);
890
923
_graphLayoutFrame.add(_graphLayoutTable);
891
924
_nodesFrame.add(_nodesTable);
894
Gtk::VBox *vbox = get_vbox();
895
vbox->set_spacing(4);
926
Gtk::Box *contents = _getContents();
927
contents->set_spacing(4);
897
929
// Notebook for individual transformations
899
vbox->pack_start(_alignFrame, true, true);
900
vbox->pack_start(_distributeFrame, true, true);
901
vbox->pack_start(_removeOverlapFrame, true, true);
902
vbox->pack_start(_graphLayoutFrame, true, true);
903
vbox->pack_start(_nodesFrame, true, true);
931
contents->pack_start(_alignFrame, true, true);
932
contents->pack_start(_distributeFrame, true, true);
933
contents->pack_start(_removeOverlapFrame, true, true);
934
contents->pack_start(_graphLayoutFrame, true, true);
935
contents->pack_start(_nodesFrame, true, true);
905
937
//Connect to the global tool change signal
906
938
g_signal_connect (G_OBJECT (INKSCAPE), "set_eventcontext", G_CALLBACK (on_tool_changed), this);
908
940
// Connect to the global selection change, to invalidate cached randomize_bbox
909
941
g_signal_connect (G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this);
910
randomize_bbox = NR::Rect (NR::Point (0, 0), NR::Point (0, 0));
911
randomize_bbox_set = false;
942
randomize_bbox = NR::Nothing();
913
944
show_all_children();
1044
1078
gdouble max = -1e18;
1045
1079
for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
1046
NR::Rect b = sp_item_bbox_desktop (*it);
1047
gdouble dim = b.extent(horizontal ? NR::X : NR::Y);
1080
NR::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
1082
gdouble dim = b->extent(horizontal ? NR::X : NR::Y);
1059
1095
gdouble max = 1e18;
1060
1096
for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
1061
NR::Rect b = sp_item_bbox_desktop (*it);
1062
gdouble dim = b.extent(horizontal ? NR::X : NR::Y);
1097
NR::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
1099
gdouble dim = b->extent(horizontal ? NR::X : NR::Y);