2 Copyright (C) 2011-2013 Paul Davis
3 Original 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 #ifndef __CANVAS_ITEM_H__
21 #define __CANVAS_ITEM_H__
27 #include <cairomm/context.h>
29 #include "pbd/signals.h"
31 #include "canvas/types.h"
33 namespace ArdourCanvas
40 /** The parent class for anything that goes on the canvas.
42 * Items have a position, which is expressed in the coordinates of the parent.
43 * They also have a bounding box, which describes the area in which they have
44 * drawable content, which is expressed in their own coordinates (whose origin
45 * is at the item position).
47 * Any item that is being displayed on a canvas has a pointer to that canvas,
48 * and all except the `root group' have a pointer to their parent group.
56 Item (Group *, Duple);
59 /** Render this item to a Cairo context.
60 * @param area Area to draw, in **window** coordinates
62 * Items must convert their own coordinates into window coordinates
63 * because Cairo is limited to a fixed point coordinate space that
64 * does not extend as far as the Ardour timeline. All rendering must
65 * be done using coordinates that do not exceed the (rough) limits
66 * of the canvas' window, to avoid odd errors within Cairo as it
67 * converts doubles into its fixed point format and then tesselates
70 virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
72 virtual void add_items_at_point (Duple, std::vector<Item const *>& items) const {
73 items.push_back (this);
76 /** Update _bounding_box and _bounding_box_dirty */
77 virtual void compute_bounding_box () const = 0;
83 void reparent (Group *);
85 /** @return Parent group, or 0 if this is the root group */
86 Group* parent () const {
90 void set_position (Duple);
91 void set_x_position (Coord);
92 void set_y_position (Coord);
95 /** @return Position of this item in the parent's coordinates */
96 Duple position () const {
100 boost::optional<Rect> bounding_box () const;
101 Coord height() const;
104 Duple item_to_parent (Duple const &) const;
105 Rect item_to_parent (Rect const &) const;
106 Duple parent_to_item (Duple const &) const;
107 Rect parent_to_item (Rect const &) const;
108 /* XXX: it's a pity these aren't the same form as item_to_parent etc.,
109 but it makes a bit of a mess in the rest of the code if they are not.
112 void canvas_to_item (Coord &, Coord &) const;
113 Duple canvas_to_item (Duple const &) const;
114 void item_to_canvas (Coord &, Coord &) const;
115 Rect item_to_canvas (Rect const &) const;
116 Rect canvas_to_item (Rect const &) const;
117 Duple item_to_canvas (Duple const &) const;
119 Duple item_to_window (Duple const&) const;
120 Duple window_to_item (Duple const&) const;
121 Rect item_to_window (Rect const&) const;
123 void raise_to_top ();
125 void lower_to_bottom ();
130 /** @return true if this item is visible (ie it will be rendered),
133 bool visible () const {
137 /** @return Our canvas, or 0 if we are not attached to one */
138 Canvas* canvas () const {
142 void set_ignore_events (bool);
143 bool ignore_events () const {
144 return _ignore_events;
147 void set_data (std::string const &, void *);
148 void* get_data (std::string const &) const;
150 /* This is a sigc++ signal because it is solely
151 concerned with GUI stuff and is thus single-threaded
155 struct EventAccumulator {
156 typedef T result_type;
158 result_type operator () (U first, U last) {
159 while (first != last) {
169 sigc::signal1<bool, GdkEvent*, EventAccumulator<bool> > Event;
175 #ifdef CANVAS_COMPATIBILITY
179 virtual void dump (std::ostream&) const;
180 std::string whatami() const;
184 /** To be called at the beginning of any property change that
185 * may alter the bounding box of this item
187 void begin_change ();
188 /** To be called at the endof any property change that
189 * may alter the bounding box of this item
192 /** To be called at the beginning of any property change that
193 * does NOT alter the bounding box of this item
195 void begin_visual_change ();
196 /** To be called at the endof any property change that
197 * does NOT alter the bounding box of this item
199 void end_visual_change ();
202 /** parent group; may be 0 if we are the root group or if we have been unparent()ed */
204 /** position of this item in parent coordinates */
206 /** true if this item is visible (ie to be drawn), otherwise false */
208 /** our bounding box before any change that is currently in progress */
209 boost::optional<Rect> _pre_change_bounding_box;
211 /** our bounding box; may be out of date if _bounding_box_dirty is true */
212 mutable boost::optional<Rect> _bounding_box;
213 /** true if _bounding_box might be out of date, false if its definitely not */
214 mutable bool _bounding_box_dirty;
216 /* XXX: this is a bit grubby */
217 std::map<std::string, void *> _data;
225 extern std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);