1 #include "pbd/compose.h"
2 #include "pbd/stacktrace.h"
3 #include "pbd/convert.h"
5 #include "ardour/utils.h"
7 #include "canvas/group.h"
8 #include "canvas/item.h"
9 #include "canvas/canvas.h"
10 #include "canvas/debug.h"
14 using namespace ArdourCanvas;
16 Item::Item (Canvas* canvas)
23 Item::Item (Group* parent)
24 : _canvas (parent->canvas ())
30 Item::Item (Group* parent, Duple position)
31 : _canvas (parent->canvas())
33 , _position (position)
42 _bounding_box_dirty = true;
43 _ignore_events = false;
49 DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this));
55 _canvas->item_going_away (this, _bounding_box);
59 _parent->remove (this);
64 Item::item_to_parent (ArdourCanvas::Rect const & r) const
66 return r.translate (_position);
70 Item::item_to_canvas (ArdourCanvas::Rect const & r) const
72 Item const * i = this;
76 offset = offset.translate (i->position());
80 return r.translate (offset);
84 Item::item_to_canvas (ArdourCanvas::Duple const & d) const
86 Item const * i = this;
90 offset = offset.translate (i->position());
94 return d.translate (offset);
98 Item::canvas_to_item (ArdourCanvas::Duple const & d) const
100 Item const * i = this;
104 offset = offset.translate (-(i->position()));
108 return d.translate (offset);
112 Item::item_to_canvas (Coord& x, Coord& y) const
114 Duple d = item_to_canvas (Duple (x, y));
121 Item::canvas_to_item (Coord& x, Coord& y) const
123 Duple d = canvas_to_item (Duple (x, y));
129 /** Set the position of this item in the parent's coordinates */
131 Item::set_position (Duple p)
133 boost::optional<ArdourCanvas::Rect> bbox = bounding_box ();
134 boost::optional<ArdourCanvas::Rect> pre_change_parent_bounding_box;
137 /* see the comment in Canvas::item_moved() to understand
138 * why we use the parent's bounding box here.
140 pre_change_parent_bounding_box = item_to_parent (bbox.get());
145 _canvas->item_moved (this, pre_change_parent_bounding_box);
148 _parent->child_changed ();
153 Item::set_x_position (Coord x)
155 set_position (Duple (x, _position.y));
159 Item::set_y_position (Coord y)
161 set_position (Duple (_position.x, y));
165 Item::raise_to_top ()
168 _parent->raise_child_to_top (this);
172 Item::raise (int levels)
175 _parent->raise_child (this, levels);
179 Item::lower_to_bottom ()
182 _parent->lower_child_to_bottom (this);
189 _canvas->item_shown_or_hidden (this);
196 _canvas->item_shown_or_hidden (this);
200 Item::item_to_parent (Duple const & d) const
202 return d.translate (_position);
206 Item::parent_to_item (Duple const & d) const
208 return d.translate (- _position);
212 Item::parent_to_item (ArdourCanvas::Rect const & d) const
214 return d.translate (- _position);
225 Item::reparent (Group* new_parent)
228 _parent->remove (this);
233 _parent = new_parent;
234 _canvas = _parent->canvas ();
244 /** @return Bounding box in this item's coordinates */
245 boost::optional<ArdourCanvas::Rect>
246 Item::bounding_box () const
248 if (_bounding_box_dirty) {
249 compute_bounding_box ();
252 assert (!_bounding_box_dirty);
253 return _bounding_box;
257 Item::height () const
259 boost::optional<ArdourCanvas::Rect> bb = bounding_box();
262 return bb->height ();
270 boost::optional<ArdourCanvas::Rect> bb = bounding_box().get();
279 /* XXX may be called even if bbox is not changing ... bit grotty */
281 Item::begin_change ()
283 _pre_change_bounding_box = bounding_box ();
289 _canvas->item_changed (this, _pre_change_bounding_box);
292 _parent->child_changed ();
297 Item::move (Duple movement)
299 set_position (position() + movement);
306 _canvas->grab (this);
317 Item::set_data (string const & key, void* data)
323 Item::get_data (string const & key) const
325 map<string, void*>::const_iterator i = _data.find (key);
326 if (i == _data.end ()) {
334 Item::set_ignore_events (bool ignore)
336 _ignore_events = ignore;
340 Item::dump (ostream& o) const
342 boost::optional<ArdourCanvas::Rect> bb = bounding_box();
344 o << _canvas->indent() << whatami() << ' ' << this;
345 o << " @ " << position();
354 o << endl << _canvas->indent() << "\tbbox: " << bb.get();
355 o << endl << _canvas->indent() << "\tCANVAS bbox: " << item_to_canvas (bb.get());
364 Item::whatami () const
366 std::string type = demangle (typeid (*this).name());
367 return type.substr (type.find_last_of (':') + 1);
371 ArdourCanvas::operator<< (ostream& o, const Item& i)