1 /*
2 * Helper object for showing selected items
3 *
4 * Authors:
5 * bulia byak <bulia@users.sf.net>
6 * Carl Hetherington <inkscape@carlh.net>
7 * Abhishek Sharma
8 *
9 * Copyright (C) 2004 Authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #include <string.h>
16 #include "desktop-handles.h"
17 #include "selection.h"
18 #include "display/sp-canvas-util.h"
19 #include "display/sodipodi-ctrl.h"
20 #include "display/sodipodi-ctrlrect.h"
21 #include "libnrtype/Layout-TNG.h"
22 #include "text-editing.h"
23 #include "sp-text.h"
24 #include "sp-flowtext.h"
25 #include "preferences.h"
26 #include "selcue.h"
28 Inkscape::SelCue::SelCue(SPDesktop *desktop)
29 : _desktop(desktop)
30 {
31 _selection = sp_desktop_selection(_desktop);
33 _sel_changed_connection = _selection->connectChanged(
34 sigc::hide(sigc::mem_fun(*this, &Inkscape::SelCue::_newItemBboxes))
35 );
37 _sel_modified_connection = _selection->connectModified(
38 sigc::hide(sigc::hide(sigc::mem_fun(*this, &Inkscape::SelCue::_updateItemBboxes)))
39 );
41 _updateItemBboxes();
42 }
44 Inkscape::SelCue::~SelCue()
45 {
46 _sel_changed_connection.disconnect();
47 _sel_modified_connection.disconnect();
49 for (std::vector<SPCanvasItem*>::iterator i = _item_bboxes.begin(); i != _item_bboxes.end(); i++) {
50 gtk_object_destroy(*i);
51 }
52 _item_bboxes.clear();
54 for (std::vector<SPCanvasItem*>::iterator i = _text_baselines.begin(); i != _text_baselines.end(); i++) {
55 gtk_object_destroy(*i);
56 }
57 _text_baselines.clear();
58 }
60 void Inkscape::SelCue::_updateItemBboxes()
61 {
62 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
63 gint mode = prefs->getInt("/options/selcue/value", MARK);
64 if (mode == NONE) {
65 return;
66 }
68 g_return_if_fail(_selection != NULL);
70 int prefs_bbox = prefs->getBool("/tools/bounding_box");
71 SPItem::BBoxType bbox_type = !prefs_bbox ?
72 SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX;
74 GSList const *items = _selection->itemList();
75 if (_item_bboxes.size() != g_slist_length((GSList *) items)) {
76 _newItemBboxes();
77 return;
78 }
80 int bcount = 0;
81 for (GSList const *l = _selection->itemList(); l != NULL; l = l->next) {
82 SPItem *item = (SPItem *) l->data;
83 SPCanvasItem* box = _item_bboxes[bcount ++];
85 if (box) {
86 Geom::OptRect const b = item->getBboxDesktop(bbox_type);
88 if (b) {
89 sp_canvas_item_show(box);
90 if (mode == MARK) {
91 SP_CTRL(box)->moveto(Geom::Point(b->min()[Geom::X], b->max()[Geom::Y]));
92 } else if (mode == BBOX) {
93 SP_CTRLRECT(box)->setRectangle(*b);
94 }
95 } else { // no bbox
96 sp_canvas_item_hide(box);
97 }
98 }
99 }
101 _newTextBaselines();
102 }
105 void Inkscape::SelCue::_newItemBboxes()
106 {
107 for (std::vector<SPCanvasItem*>::iterator i = _item_bboxes.begin(); i != _item_bboxes.end(); i++) {
108 gtk_object_destroy(*i);
109 }
110 _item_bboxes.clear();
112 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
113 gint mode = prefs->getInt("/options/selcue/value", MARK);
114 if (mode == NONE) {
115 return;
116 }
118 g_return_if_fail(_selection != NULL);
120 int prefs_bbox = prefs->getBool("/tools/bounding_box");
121 SPItem::BBoxType bbox_type = !prefs_bbox ?
122 SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX;
124 for (GSList const *l = _selection->itemList(); l != NULL; l = l->next) {
125 SPItem *item = (SPItem *) l->data;
127 Geom::OptRect const b = item->getBboxDesktop(bbox_type);
129 SPCanvasItem* box = NULL;
131 if (b) {
132 if (mode == MARK) {
133 box = sp_canvas_item_new(sp_desktop_controls(_desktop),
134 SP_TYPE_CTRL,
135 "mode", SP_CTRL_MODE_XOR,
136 "shape", SP_CTRL_SHAPE_DIAMOND,
137 "size", 5.0,
138 "filled", TRUE,
139 "fill_color", 0x000000ff,
140 "stroked", FALSE,
141 "stroke_color", 0x000000ff,
142 NULL);
143 sp_canvas_item_show(box);
144 SP_CTRL(box)->moveto(Geom::Point(b->min()[Geom::X], b->max()[Geom::Y]));
146 sp_canvas_item_move_to_z(box, 0); // just low enough to not get in the way of other draggable knots
148 } else if (mode == BBOX) {
149 box = sp_canvas_item_new(sp_desktop_controls(_desktop),
150 SP_TYPE_CTRLRECT,
151 NULL);
153 SP_CTRLRECT(box)->setRectangle(*b);
154 SP_CTRLRECT(box)->setColor(0x000000a0, 0, 0);
155 SP_CTRLRECT(box)->setDashed(true);
157 sp_canvas_item_move_to_z(box, 0);
158 }
159 }
161 if (box) {
162 _item_bboxes.push_back(box);
163 }
164 }
166 _newTextBaselines();
167 }
169 void Inkscape::SelCue::_newTextBaselines()
170 {
171 for (std::vector<SPCanvasItem*>::iterator i = _text_baselines.begin(); i != _text_baselines.end(); i++) {
172 gtk_object_destroy(*i);
173 }
174 _text_baselines.clear();
176 for (GSList const *l = _selection->itemList(); l != NULL; l = l->next) {
177 SPItem *item = (SPItem *) l->data;
179 SPCanvasItem* baseline_point = NULL;
180 if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { // visualize baseline
181 Inkscape::Text::Layout const *layout = te_get_layout(item);
182 if (layout != NULL && layout->outputExists()) {
183 boost::optional<Geom::Point> pt = layout->baselineAnchorPoint();
184 if (pt) {
185 baseline_point = sp_canvas_item_new(sp_desktop_controls(_desktop), SP_TYPE_CTRL,
186 "mode", SP_CTRL_MODE_XOR,
187 "size", 4.0,
188 "filled", 0,
189 "stroked", 1,
190 "stroke_color", 0x000000ff,
191 NULL);
193 sp_canvas_item_show(baseline_point);
194 SP_CTRL(baseline_point)->moveto((*pt) * item->i2d_affine());
195 sp_canvas_item_move_to_z(baseline_point, 0);
196 }
197 }
198 }
200 if (baseline_point) {
201 _text_baselines.push_back(baseline_point);
202 }
203 }
204 }
207 /*
208 Local Variables:
209 mode:c++
210 c-file-style:"stroustrup"
211 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
212 indent-tabs-mode:nil
213 fill-column:99
214 End:
215 */
216 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :