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/visibility.h"
32 #include "canvas/types.h"
33 #include "canvas/fill.h"
34 #include "canvas/outline.h"
35 #include "canvas/lookup_table.h"
37 namespace ArdourCanvas
44 /** The parent class for anything that goes on the canvas.
46 * Items have a position, which is expressed in the coordinates of the parent.
47 * They also have a bounding box, which describes the area in which they have
48 * drawable content, which is expressed in their own coordinates (whose origin
49 * is at the item position).
51 * Any item that is being displayed on a canvas has a pointer to that canvas,
52 * and all except the `root group' have a pointer to their parent group.
55 class LIBCANVAS_API Item : public Fill, public Outline
60 Item (Item *, Duple const& p);
65 /** Render this item to a Cairo context.
66 * @param area Area to draw, in **window** coordinates
68 * Items must convert their own coordinates into window coordinates
69 * because Cairo is limited to a fixed point coordinate space that
70 * does not extend as far as the Ardour timeline. All rendering must
71 * be done using coordinates that do not exceed the (rough) limits
72 * of the canvas' window, to avoid odd errors within Cairo as it
73 * converts doubles into its fixed point format and then tesselates
76 virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
78 /** Adds one or more items to the vector @param items based on their
79 * covering @param point which is in **window** coordinates
81 * Note that Item::add_items_at_window_point() is only intended to be
82 * called on items already looked up in a LookupTable (i.e. by a
83 * parent) and thus known to cover @param point already.
85 * Derived classes may add more items than themselves (e.g. containers).
87 virtual void add_items_at_point (Duple /*point*/, std::vector<Item const *>& items) const;
89 /** Return true if the item covers @param point, false otherwise.
91 * The point is in window coordinates
93 virtual bool covers (Duple const &) const;
95 /** Update _bounding_box and _bounding_box_dirty */
96 virtual void compute_bounding_box () const = 0;
102 void reparent (Item *);
104 /** @return Parent group, or 0 if this is the root group */
105 Item* parent () const {
109 uint32_t depth() const;
110 const Item* closest_ancestor_with (const Item& other) const;
111 bool common_ancestor_within (uint32_t, const Item& other) const;
113 /** returns true if this item is an ancestor of @param candidate,
114 * and false otherwise.
116 bool is_ancestor_of (const Item& candidate) const {
117 return candidate.is_descendant_of (*this);
119 /** returns true if this Item is a descendant of @param candidate,
120 * and false otherwise.
122 bool is_descendant_of (const Item& candidate) const;
124 void set_position (Duple);
125 void set_x_position (Coord);
126 void set_y_position (Coord);
129 /** @return Position of this item in the parent's coordinates */
130 Duple position () const {
134 Duple window_origin() const;
135 Duple canvas_origin() const;
137 ScrollGroup* scroll_parent() const { return _scroll_parent; }
139 boost::optional<Rect> bounding_box () const;
140 Coord height() const;
143 Duple item_to_parent (Duple const &) const;
144 Rect item_to_parent (Rect const &) const;
145 Duple parent_to_item (Duple const &) const;
146 Rect parent_to_item (Rect const &) const;
148 /* XXX: it's a pity these two aren't the same form as item_to_parent etc.,
149 but it makes a bit of a mess in the rest of the code if they are not.
151 void canvas_to_item (Coord &, Coord &) const;
152 void item_to_canvas (Coord &, Coord &) const;
154 Duple canvas_to_item (Duple const&) const;
155 Rect item_to_canvas (Rect const&) const;
156 Duple item_to_canvas (Duple const&) const;
157 Rect canvas_to_item (Rect const&) const;
159 Duple item_to_window (Duple const&, bool rounded = true) const;
160 Duple window_to_item (Duple const&) const;
161 Rect item_to_window (Rect const&, bool rounded = true) const;
162 Rect window_to_item (Rect const&) const;
164 void raise_to_top ();
166 void lower_to_bottom ();
171 /** @return true if this item is visible (ie it will be rendered),
174 bool self_visible () const {
178 bool visible () const;
180 /** @return Our canvas, or 0 if we are not attached to one */
181 Canvas* canvas () const {
185 void set_ignore_events (bool);
186 bool ignore_events () const {
187 return _ignore_events;
190 void set_data (std::string const &, void *);
191 void* get_data (std::string const &) const;
193 /* nested item ("grouping") API */
195 void remove (Item *);
196 void clear (bool with_delete = false);
197 std::list<Item*> const & items () const {
200 void raise_child_to_top (Item *);
201 void raise_child (Item *, int);
202 void lower_child_to_bottom (Item *);
203 void child_changed ();
205 static int default_items_per_cell;
208 /* This is a sigc++ signal because it is solely
209 concerned with GUI stuff and is thus single-threaded
213 struct EventAccumulator {
214 typedef T result_type;
216 result_type operator () (U first, U last) {
217 while (first != last) {
227 sigc::signal1<bool, GdkEvent*, EventAccumulator<bool> > Event;
233 #ifdef CANVAS_COMPATIBILITY
237 const std::string& tooltip () const { return _tooltip; }
238 void set_tooltip (const std::string&);
240 void start_tooltip_timeout ();
241 void stop_tooltip_timeout ();
243 virtual void dump (std::ostream&) const;
244 std::string whatami() const;
248 friend class Outline;
250 /** To be called at the beginning of any property change that
251 * may alter the bounding box of this item
253 void begin_change ();
254 /** To be called at the endof any property change that
255 * may alter the bounding box of this item
258 /** To be called at the beginning of any property change that
259 * does NOT alter the bounding box of this item
261 void begin_visual_change ();
262 /** To be called at the endof any property change that
263 * does NOT alter the bounding box of this item
265 void end_visual_change ();
268 /** parent group; may be 0 if we are the root group or if we have been unparent()ed */
270 /** scroll parent group; may be 0 if we are the root group or if we have been unparent()ed */
271 ScrollGroup* _scroll_parent;
272 /** position of this item in parent coordinates */
274 /** true if this item is visible (ie to be drawn), otherwise false */
276 /** our bounding box before any change that is currently in progress */
277 boost::optional<Rect> _pre_change_bounding_box;
279 /** our bounding box; may be out of date if _bounding_box_dirty is true */
280 mutable boost::optional<Rect> _bounding_box;
281 /** true if _bounding_box might be out of date, false if its definitely not */
282 mutable bool _bounding_box_dirty;
284 /* XXX: this is a bit grubby */
285 std::map<std::string, void *> _data;
287 /* nesting ("grouping") API */
289 void invalidate_lut () const;
290 void clear_items (bool with_delete);
292 void ensure_lut () const;
293 mutable LookupTable* _lut;
294 /* our items, from lowest to highest in the stack */
295 std::list<Item*> _items;
297 void add_child_bounding_boxes() const;
298 void render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
300 Duple scroll_offset() const;
301 Duple position_offset() const;
306 std::string _tooltip;
309 void find_scroll_parent ();
310 void propagate_show_hide ();
313 extern LIBCANVAS_API std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);