Lua Script Example to toggle monitor section
[ardour.git] / libs / canvas / canvas / item.h
1 /*
2     Copyright (C) 2011-2013 Paul Davis
3     Original Author: Carl Hetherington <cth@carlh.net>
4
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.
9
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.
14
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.
18 */
19
20 #ifndef __CANVAS_ITEM_H__
21 #define __CANVAS_ITEM_H__
22
23 #include <stdint.h>
24
25 #include <gdk/gdk.h>
26
27 #include <cairomm/context.h>
28
29 #include "pbd/signals.h"
30
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"
36
37 namespace ArdourCanvas
38 {
39 struct Rect;
40
41 class Canvas;
42 class ScrollGroup;
43
44 /** The parent class for anything that goes on the canvas.
45  *
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).
50  *
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.
53  */
54
55 class LIBCANVAS_API Item : public Fill, public Outline
56 {
57 public:
58         Item (Canvas *);
59         Item (Item *);
60         Item (Item *, Duple const& p);
61         virtual ~Item ();
62
63         void redraw () const;
64
65         /** Render this item to a Cairo context.
66          *  @param area Area to draw, in **window** coordinates
67          *
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
74          *  the results.
75          */
76         virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
77
78         /** Item has changed will be rendered in next render pass so give item a
79          * chance to perhaps schedule work in another thread etc.
80          *
81          *  @param area Area to draw, in **window** coordinates
82          */
83         virtual void prepare_for_render (Rect const & area) const { }
84
85         /** Adds one or more items to the vector @param items based on their
86          * covering @param point which is in **window** coordinates
87          *
88          * Note that Item::add_items_at_window_point() is only intended to be
89          * called on items already looked up in a LookupTable (i.e. by a
90          * parent) and thus known to cover @param point already.
91          *
92          * Derived classes may add more items than themselves (e.g. containers).
93          */
94         virtual void add_items_at_point (Duple /*point*/, std::vector<Item const *>& items) const;
95
96         /** Return true if the item covers @param point, false otherwise.
97          *
98          * The point is in window coordinates
99          */
100         virtual bool covers (Duple const &) const;
101
102         /** Update _bounding_box and _bounding_box_dirty */
103         virtual void compute_bounding_box () const = 0;
104
105         void grab ();
106         void ungrab ();
107
108         void unparent ();
109         void reparent (Item *, bool already_added = false);
110
111         /** @return Parent group, or 0 if this is the root group */
112         Item* parent () const {
113                 return _parent;
114         }
115
116         uint32_t depth() const;
117         const Item* closest_ancestor_with (const Item& other) const;
118         bool common_ancestor_within (uint32_t, const Item& other) const;
119
120         /** returns true if this item is an ancestor of @param candidate,
121          * and false otherwise.
122          */
123         bool is_ancestor_of (const Item& candidate) const {
124                 return candidate.is_descendant_of (*this);
125         }
126         /** returns true if this Item is a descendant of @param candidate,
127          * and false otherwise.
128          */
129         bool is_descendant_of (const Item& candidate) const;
130
131         void set_position (Duple);
132         void set_x_position (Coord);
133         void set_y_position (Coord);
134         void move (Duple);
135
136         /** @return Position of this item in the parent's coordinates */
137         Duple position () const {
138                 return _position;
139         }
140
141         Duple window_origin() const;
142         Duple canvas_origin() const;
143
144         ScrollGroup* scroll_parent() const { return _scroll_parent; }
145
146         /* item implementations can override this if they need to */
147         virtual Rect size_request() const { return bounding_box (true); }
148         virtual void size_allocate (Rect const&);
149
150         /** bounding box is the public API to get the size of the item.
151            If @param for_own_purposes is false, then it will return the
152            allocated bounding box (if there is one) in preference to the
153            one that would naturally be computed by the item.
154         */
155         Rect bounding_box (bool for_own_purposes = false) const;
156         Rect allocation() const { return _allocation; }
157
158         Coord height() const;
159         Coord width() const;
160
161         Duple item_to_parent (Duple const &) const;
162         Rect item_to_parent (Rect const &) const;
163         Duple parent_to_item (Duple const &) const;
164         Rect parent_to_item (Rect const &) const;
165
166         /* XXX: it's a pity these two aren't the same form as item_to_parent etc.,
167            but it makes a bit of a mess in the rest of the code if they are not.
168         */
169         void canvas_to_item (Coord &, Coord &) const;
170         void item_to_canvas (Coord &, Coord &) const;
171
172         Duple canvas_to_item (Duple const&) const;
173         Rect item_to_canvas (Rect const&) const;
174         Duple item_to_canvas (Duple const&) const;
175         Rect canvas_to_item (Rect const&) const;
176
177         Duple item_to_window (Duple const&, bool rounded = true) const;
178         Duple window_to_item (Duple const&) const;
179         Rect item_to_window (Rect const&, bool rounded = true) const;
180         Rect window_to_item (Rect const&) const;
181
182         void raise_to_top ();
183         void raise (int);
184         void lower_to_bottom ();
185
186         virtual void hide ();
187         virtual void show ();
188
189         /** @return true if this item is visible (ie it will be rendered),
190          *  otherwise false
191          */
192         bool self_visible () const {
193                 return _visible;
194         }
195
196         bool visible () const;
197
198         /** @return Our canvas, or 0 if we are not attached to one */
199         Canvas* canvas () const {
200                 return _canvas;
201         }
202
203         void set_ignore_events (bool);
204         bool ignore_events () const {
205                 return _ignore_events;
206         }
207
208         void set_data (std::string const &, void *);
209         void* get_data (std::string const &) const;
210
211         /* nested item ("grouping") API */
212         void add (Item *);
213         void add_front (Item *);
214         void remove (Item *);
215         void clear (bool with_delete = false);
216         std::list<Item*> const & items () const {
217                 return _items;
218         }
219         void raise_child_to_top (Item *);
220         void raise_child (Item *, int);
221         void lower_child_to_bottom (Item *);
222         virtual void child_changed ();
223
224         static int default_items_per_cell;
225
226
227         /* This is a sigc++ signal because it is solely
228            concerned with GUI stuff and is thus single-threaded
229         */
230
231         template <class T>
232         struct EventAccumulator {
233                 typedef T result_type;
234                 template <class U>
235                 result_type operator () (U first, U last) {
236                         while (first != last) {
237                                 if (*first) {
238                                         return true;
239                                 }
240                                 ++first;
241                         }
242                         return false;
243                 }
244         };
245
246         sigc::signal1<bool, GdkEvent*, EventAccumulator<bool> > Event;
247
248 #ifdef CANVAS_DEBUG
249         std::string name;
250 #endif
251
252 #ifdef CANVAS_COMPATIBILITY
253         void grab_focus ();
254 #endif
255
256         const std::string& tooltip () const { return _tooltip; }
257         void set_tooltip (const std::string&);
258
259         void start_tooltip_timeout ();
260         void stop_tooltip_timeout ();
261
262         virtual void dump (std::ostream&) const;
263         std::string whatami() const;
264
265 protected:
266         friend class Fill;
267         friend class Outline;
268
269         /** To be called at the beginning of any property change that
270          *  may alter the bounding box of this item
271          */
272         void begin_change ();
273         /** To be called at the endof any property change that
274          *  may alter the bounding box of this item
275          */
276         void end_change ();
277         /** To be called at the beginning of any property change that
278          *  does NOT alter the bounding box of this item
279          */
280         void begin_visual_change ();
281         /** To be called at the endof any property change that
282          *  does NOT alter the bounding box of this item
283          */
284         void end_visual_change ();
285
286         Canvas* _canvas;
287         /** parent group; may be 0 if we are the root group or if we have been unparent()ed */
288         Item* _parent;
289         /** scroll parent group; may be 0 if we are the root group or if we have been unparent()ed */
290         ScrollGroup* _scroll_parent;
291         /** position of this item in parent coordinates */
292         Duple _position;
293         /** true if this item is visible (ie to be drawn), otherwise false */
294         bool _visible;
295         /** our bounding box before any change that is currently in progress */
296         Rect _pre_change_bounding_box;
297
298         /** our bounding box; may be out of date if _bounding_box_dirty is true */
299         mutable Rect _bounding_box;
300         /** true if _bounding_box might be out of date, false if its definitely not */
301         mutable bool _bounding_box_dirty;
302         Rect _allocation;
303
304         /* XXX: this is a bit grubby */
305         std::map<std::string, void *> _data;
306
307         /* nesting ("grouping") API */
308
309         void invalidate_lut () const;
310         void clear_items (bool with_delete);
311
312         void ensure_lut () const;
313         mutable LookupTable* _lut;
314         /* our items, from lowest to highest in the stack */
315         std::list<Item*> _items;
316
317         void add_child_bounding_boxes (bool include_hidden = false) const;
318         void render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
319         void prepare_for_render_children (Rect const & area) const;
320
321         Duple scroll_offset() const;
322         Duple position_offset() const;
323
324 private:
325         void init ();
326
327         std::string _tooltip;
328         bool _ignore_events;
329
330         void find_scroll_parent ();
331         void propagate_show_hide ();
332 };
333
334 extern LIBCANVAS_API std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);
335
336 }
337
338
339 #endif