2 Copyright (C) 2011-2013 Paul Davis
3 Author: Carl Hetherington <cth@carlh.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "pbd/compose.h"
21 #include "pbd/stacktrace.h"
22 #include "pbd/convert.h"
24 #include "ardour/utils.h"
26 #include "canvas/group.h"
27 #include "canvas/item.h"
28 #include "canvas/canvas.h"
29 #include "canvas/debug.h"
33 using namespace ArdourCanvas;
35 Item::Item (Canvas* canvas)
42 Item::Item (Group* parent)
43 : _canvas (parent->canvas ())
49 Item::Item (Group* parent, Duple position)
50 : _canvas (parent->canvas())
52 , _position (position)
61 _bounding_box_dirty = true;
62 _ignore_events = false;
68 DEBUG_TRACE (DEBUG::CanvasItems, string_compose ("new canvas item %1\n", this));
74 _parent->remove (this);
78 _canvas->item_going_away (this, _bounding_box);
83 Item::item_to_parent (ArdourCanvas::Rect const & r) const
85 return r.translate (_position);
89 Item::item_to_canvas (ArdourCanvas::Rect const & r) const
91 Item const * i = this;
95 offset = offset.translate (i->position());
99 return r.translate (offset);
103 Item::item_to_canvas (ArdourCanvas::Duple const & d) const
105 Item const * i = this;
109 offset = offset.translate (i->position());
113 return d.translate (offset);
117 Item::canvas_to_item (ArdourCanvas::Duple const & d) const
119 Item const * i = this;
123 offset = offset.translate (-(i->position()));
127 return d.translate (offset);
131 Item::canvas_to_item (ArdourCanvas::Rect const & d) const
133 Item const * i = this;
137 offset = offset.translate (-(i->position()));
141 return d.translate (offset);
145 Item::item_to_canvas (Coord& x, Coord& y) const
147 Duple d = item_to_canvas (Duple (x, y));
154 Item::canvas_to_item (Coord& x, Coord& y) const
156 Duple d = canvas_to_item (Duple (x, y));
163 Item::item_to_window (ArdourCanvas::Duple const & d) const
165 return _canvas->canvas_to_window (item_to_canvas (d));
169 Item::window_to_item (ArdourCanvas::Duple const & d) const
171 return _canvas->window_to_canvas (canvas_to_item (d));
175 Item::item_to_window (ArdourCanvas::Rect const & r) const
177 return _canvas->canvas_to_window (item_to_canvas (r));
180 /** Set the position of this item in the parent's coordinates */
182 Item::set_position (Duple p)
184 boost::optional<ArdourCanvas::Rect> bbox = bounding_box ();
185 boost::optional<ArdourCanvas::Rect> pre_change_parent_bounding_box;
188 /* see the comment in Canvas::item_moved() to understand
189 * why we use the parent's bounding box here.
191 pre_change_parent_bounding_box = item_to_parent (bbox.get());
196 _canvas->item_moved (this, pre_change_parent_bounding_box);
199 _parent->child_changed ();
204 Item::set_x_position (Coord x)
206 set_position (Duple (x, _position.y));
210 Item::set_y_position (Coord y)
212 set_position (Duple (_position.x, y));
216 Item::raise_to_top ()
219 _parent->raise_child_to_top (this);
223 Item::raise (int levels)
226 _parent->raise_child (this, levels);
230 Item::lower_to_bottom ()
233 _parent->lower_child_to_bottom (this);
240 _canvas->item_shown_or_hidden (this);
247 _canvas->item_shown_or_hidden (this);
251 Item::item_to_parent (Duple const & d) const
253 return d.translate (_position);
257 Item::parent_to_item (Duple const & d) const
259 return d.translate (- _position);
263 Item::parent_to_item (ArdourCanvas::Rect const & d) const
265 return d.translate (- _position);
275 Item::reparent (Group* new_parent)
277 assert (_canvas == _parent->canvas());
280 _parent->remove (this);
285 _parent = new_parent;
286 _canvas = _parent->canvas ();
296 /** @return Bounding box in this item's coordinates */
297 boost::optional<ArdourCanvas::Rect>
298 Item::bounding_box () const
300 if (_bounding_box_dirty) {
301 compute_bounding_box ();
304 assert (!_bounding_box_dirty);
305 return _bounding_box;
309 Item::height () const
311 boost::optional<ArdourCanvas::Rect> bb = bounding_box();
314 return bb->height ();
322 boost::optional<ArdourCanvas::Rect> bb = bounding_box().get();
332 Item::begin_change ()
334 _pre_change_bounding_box = bounding_box ();
340 _canvas->item_changed (this, _pre_change_bounding_box);
343 _parent->child_changed ();
348 Item::begin_visual_change ()
353 Item::end_visual_change ()
355 _canvas->item_visual_property_changed (this);
359 Item::move (Duple movement)
361 set_position (position() + movement);
368 _canvas->grab (this);
379 Item::set_data (string const & key, void* data)
385 Item::get_data (string const & key) const
387 map<string, void*>::const_iterator i = _data.find (key);
388 if (i == _data.end ()) {
396 Item::set_ignore_events (bool ignore)
398 _ignore_events = ignore;
402 Item::dump (ostream& o) const
404 boost::optional<ArdourCanvas::Rect> bb = bounding_box();
406 o << _canvas->indent() << whatami() << ' ' << this << " Visible ? " << _visible;
407 o << " @ " << position();
416 o << endl << _canvas->indent() << "\tbbox: " << bb.get();
417 o << endl << _canvas->indent() << "\tCANVAS bbox: " << item_to_canvas (bb.get());
426 Item::whatami () const
428 std::string type = demangle (typeid (*this).name());
429 return type.substr (type.find_last_of (':') + 1);
433 ArdourCanvas::operator<< (ostream& o, const Item& i)