Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / selcue.cpp
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();
105 void Inkscape::SelCue::_newItemBboxes()
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;
123     
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();
169 void Inkscape::SelCue::_newTextBaselines()
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     }
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 :