~ubuntu-branches/debian/squeeze/inkscape/squeeze

« back to all changes in this revision

Viewing changes to src/ui/dialog/align-and-distribute.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
#include "sp-flowtext.h"
47
47
#include "text-editing.h"
48
48
 
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
50
51
 
51
52
#include "tools-switch.h"
52
53
 
115
116
 
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;
120
121
 
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);
 
157
            if (b) {
 
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]);
 
160
            } else {
 
161
                return;
 
162
            }
158
163
            break;
159
164
        }
160
165
 
165
170
 
166
171
        case AlignAndDistribute::DRAWING:
167
172
        {
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]);
 
175
            if (b) {
 
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]);
 
178
            } else {
 
179
                return;
 
180
            }
172
181
            break;
173
182
        }
174
183
 
175
184
        case AlignAndDistribute::SELECTION:
176
185
        {
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();
 
187
            if (b) {
 
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]);
 
190
            } else {
 
191
                return;
 
192
            }
180
193
            break;
181
194
        }
182
195
 
201
214
             it++)
202
215
        {
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));
210
 
                changed = true;
 
217
            NR::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
 
218
            if (b) {
 
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));
 
224
                    changed = true;
 
225
                }
211
226
            }
212
227
        }
213
228
 
215
230
        prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
216
231
 
217
232
        if (changed) {
218
 
            sp_document_done ( sp_desktop_document (desktop) );
 
233
            sp_document_done ( sp_desktop_document (desktop) , SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
 
234
                               _("Align"));
219
235
        }
220
236
 
221
237
 
244
260
    SPItem *item;
245
261
    float anchor;
246
262
    NR::Rect bbox;
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) :
248
264
        item(pItem),
249
 
        bbox (sp_item_bbox_desktop (pItem))
 
265
        bbox (bounds)
250
266
    {
251
267
        anchor = kBegin * bbox.min()[orientation] + kEnd * bbox.max()[orientation];
252
268
    }
284
300
private :
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;
289
305
 
290
306
        Inkscape::Selection *selection = sp_desktop_selection(desktop);
306
322
            it != selected.end();
307
323
            ++it)
308
324
        {
309
 
            BBoxSort b (*it, _orientation, _kBegin, _kEnd);
310
 
            sorted.push_back(b);
 
325
            NR::Maybe<NR::Rect> bbox = sp_item_bbox_desktop(*it);
 
326
            if (bbox) {
 
327
                sorted.push_back(BBoxSort(*it, *bbox, _orientation, _kBegin, _kEnd));
 
328
            }
311
329
        }
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);
375
393
 
376
394
        if (changed) {
377
 
            sp_document_done ( sp_desktop_document (desktop) );
 
395
            sp_document_done ( sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, 
 
396
                               _("Distribute"));
378
397
        }
379
398
    }
380
399
    guint _index;
407
426
    virtual void on_button_click()
408
427
    {
409
428
 
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 ;
413
432
 
414
 
        Inkscape::NodePath::Path *nodepath = SP_NODE_CONTEXT (event_context)->nodepath;
415
 
        if (!nodepath) return;
416
433
        if (_distribute)
417
 
            sp_nodepath_selected_distribute(nodepath, _orientation);
 
434
            SP_NODE_CONTEXT (event_context)->shape_editor->distribute(_orientation);
418
435
        else
419
 
            sp_nodepath_selected_align(nodepath, _orientation);
 
436
            SP_NODE_CONTEXT (event_context)->shape_editor->align(_orientation);
420
437
 
421
438
    }
422
439
};
469
486
private :
470
487
    virtual void on_button_click()
471
488
    {
472
 
        if (!SP_ACTIVE_DESKTOP) return;
 
489
        if (!_dialog.getDesktop()) return;
473
490
 
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(),
482
499
                      xGap, yGap);
483
500
 
484
501
        // restore compensation setting
485
502
        prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
486
503
 
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"));
488
506
    }
489
507
};
490
508
 
502
520
private :
503
521
    virtual void on_button_click()
504
522
    {
505
 
        if (!SP_ACTIVE_DESKTOP) return;
 
523
        if (!_dialog.getDesktop()) return;
506
524
 
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);
510
528
 
511
 
        graphlayout(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
 
529
        graphlayout(sp_desktop_selection(_dialog.getDesktop())->itemList());
512
530
 
513
531
        // restore compensation setting
514
532
        prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
515
533
 
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"));
517
536
    }
518
537
};
519
538
 
531
550
private :
532
551
    virtual void on_button_click()
533
552
    {
534
 
        if (!SP_ACTIVE_DESKTOP) return;
 
553
        if (!_dialog.getDesktop()) return;
535
554
 
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);
539
558
 
540
 
        unclump ((GSList *) sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
 
559
        unclump ((GSList *) sp_desktop_selection(_dialog.getDesktop())->itemList());
541
560
 
542
561
        // restore compensation setting
543
562
        prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
544
563
 
545
 
        sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP));
 
564
        sp_document_done (sp_desktop_document (_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, 
 
565
                          _("Unclump"));
546
566
    }
547
567
};
548
568
 
560
580
private :
561
581
    virtual void on_button_click()
562
582
    {
563
 
        SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
583
        SPDesktop *desktop = _dialog.getDesktop();
564
584
        if (!desktop) return;
565
585
 
566
586
        Inkscape::Selection *selection = sp_desktop_selection(desktop);
574
594
        //Check 2 or more selected objects
575
595
        if (selected.size() < 2) return;
576
596
 
 
597
        NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
 
598
        if (!sel_bbox) {
 
599
            return;
 
600
        }
 
601
 
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;
583
607
        }
584
608
 
585
609
        // see comment in ActionAlign above
591
615
            ++it)
592
616
        {
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);
 
619
            if (item_box) {
 
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));
 
628
            }
603
629
        }
604
630
 
605
631
        // restore compensation setting
606
632
        prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
607
633
 
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"));
609
636
    }
610
637
};
611
638
 
646
673
    bool _distribute;
647
674
    virtual void on_button_click()
648
675
    {
649
 
        SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
676
        SPDesktop *desktop = _dialog.getDesktop();
650
677
        if (!desktop) return;
651
678
 
652
679
        Inkscape::Selection *selection = sp_desktop_selection(desktop);
700
727
                changed = true;
701
728
            }
702
729
 
 
730
            if (changed) {
 
731
                sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, 
 
732
                                  _("Distribute text baselines"));
 
733
            }
 
734
 
703
735
        } else {
704
736
            for (std::list<SPItem *>::iterator it(selected.begin());
705
737
                 it != selected.end();
714
746
                    changed = true;
715
747
                }
716
748
            }
717
 
        }
718
749
 
719
 
        if (changed) {
720
 
            sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP));
 
750
            if (changed) {
 
751
                sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE, 
 
752
                                  _("Align text baselines"));
 
753
            }
721
754
        }
722
755
    }
723
756
};
733
766
 
734
767
void on_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection *selection, AlignAndDistribute *daad)
735
768
{
736
 
    daad->randomize_bbox_set = false;
 
769
    daad->randomize_bbox = NR::Nothing();
737
770
}
738
771
 
739
772
/////////////////////////////////////////////////////////
742
775
 
743
776
 
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"));
877
910
 
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));
880
913
 
881
914
    _anchorBox.pack_start(_anchorLabel);
890
923
    _graphLayoutFrame.add(_graphLayoutTable);
891
924
    _nodesFrame.add(_nodesTable);
892
925
 
893
 
    // Top level vbox
894
 
    Gtk::VBox *vbox = get_vbox();
895
 
    vbox->set_spacing(4);
 
926
    Gtk::Box *contents = _getContents();
 
927
    contents->set_spacing(4);
896
928
 
897
929
    // Notebook for individual transformations
898
930
 
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);
904
936
 
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);
907
939
 
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();
912
943
 
913
944
    show_all_children();
914
945
 
926
957
}
927
958
 
928
959
void AlignAndDistribute::on_ref_change(){
929
 
//Make blink the master
 
960
 
 
961
    prefs_set_int_attribute("dialogs.align", "align-to", _combo.get_active_row_number());
 
962
 
 
963
    //Make blink the master
930
964
}
931
965
 
932
966
 
1043
1077
    {
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);
1048
 
            if (dim > max) {
1049
 
                max = dim;
1050
 
                master = it;
 
1080
            NR::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
 
1081
            if (b) {
 
1082
                gdouble dim = b->extent(horizontal ? NR::X : NR::Y);
 
1083
                if (dim > max) {
 
1084
                    max = dim;
 
1085
                    master = it;
 
1086
                }
1051
1087
            }
1052
1088
        }
1053
1089
        return master;
1058
1094
    {
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);
1063
 
            if (dim < max) {
1064
 
                max = dim;
1065
 
                master = it;
 
1097
            NR::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
 
1098
            if (b) {
 
1099
                gdouble dim = b->extent(horizontal ? NR::X : NR::Y);
 
1100
                if (dim < max) {
 
1101
                    max = dim;
 
1102
                    master = it;
 
1103
                }
1066
1104
            }
1067
1105
        }
1068
1106
        return master;