fix merge conflicts with master
[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/types.h"
32
33 namespace ArdourCanvas
34 {
35
36 class Canvas;
37 class Group;
38 class Rect;     
39
40 /** The parent class for anything that goes on the canvas.
41  *
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).
46  *
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.
49  */
50         
51 class Item
52 {
53 public:
54         Item (Canvas *);
55         Item (Group *);
56         Item (Group *, Duple);
57         virtual ~Item ();
58
59         /** Render this item to a Cairo context.
60          *  @param area Area to draw, in **window** coordinates
61          *
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
68          *  the results.
69          */
70         virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
71
72         virtual void add_items_at_point (Duple, std::vector<Item const *>& items) const {
73                 items.push_back (this);
74         }
75
76         /** Update _bounding_box and _bounding_box_dirty */
77         virtual void compute_bounding_box () const = 0;
78
79         void grab ();
80         void ungrab ();
81         
82         void unparent ();
83         void reparent (Group *);
84
85         /** @return Parent group, or 0 if this is the root group */
86         Group* parent () const {
87                 return _parent;
88         }
89
90         void set_position (Duple);
91         void set_x_position (Coord);
92         void set_y_position (Coord);
93         void move (Duple);
94
95         /** @return Position of this item in the parent's coordinates */
96         Duple position () const {
97                 return _position;
98         }
99
100         boost::optional<Rect> bounding_box () const;
101         Coord height() const;
102         Coord width() const;
103
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.
110         */
111
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;
118
119         Duple item_to_window (Duple const&) const;
120         Duple window_to_item (Duple const&) const;
121         Rect item_to_window (Rect const&) const;
122
123         void raise_to_top ();
124         void raise (int);
125         void lower_to_bottom ();
126
127         void hide ();
128         void show ();
129
130         /** @return true if this item is visible (ie it will be rendered),
131          *  otherwise false
132          */
133         bool visible () const {
134                 return _visible;
135         }
136
137         /** @return Our canvas, or 0 if we are not attached to one */
138         Canvas* canvas () const {
139                 return _canvas;
140         }
141
142         void set_ignore_events (bool);
143         bool ignore_events () const {
144                 return _ignore_events;
145         }
146
147         void set_data (std::string const &, void *);
148         void* get_data (std::string const &) const;
149         
150         /* This is a sigc++ signal because it is solely
151            concerned with GUI stuff and is thus single-threaded
152         */
153
154         template <class T>
155         struct EventAccumulator {
156                 typedef T result_type;
157                 template <class U>
158                 result_type operator () (U first, U last) {
159                         while (first != last) {
160                                 if (*first) {
161                                         return true;
162                                 }
163                                 ++first;
164                         }
165                         return false;
166                 }
167         };
168         
169         sigc::signal1<bool, GdkEvent*, EventAccumulator<bool> > Event;
170
171 #ifdef CANVAS_DEBUG
172         std::string name;
173 #endif
174         
175 #ifdef CANVAS_COMPATIBILITY
176         void grab_focus ();
177 #endif  
178
179         virtual void dump (std::ostream&) const;
180         std::string whatami() const;
181
182 protected:
183
184         /** To be called at the beginning of any property change that
185          *  may alter the bounding box of this item
186          */
187         void begin_change ();
188         /** To be called at the endof any property change that
189          *  may alter the bounding box of this item
190          */
191         void end_change ();
192         /** To be called at the beginning of any property change that
193          *  does NOT alter the bounding box of this item
194          */
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
198          */
199         void end_visual_change ();
200
201         Canvas* _canvas;
202         /** parent group; may be 0 if we are the root group or if we have been unparent()ed */
203         Group* _parent;
204         /** position of this item in parent coordinates */
205         Duple _position;
206         /** true if this item is visible (ie to be drawn), otherwise false */
207         bool _visible;
208         /** our bounding box before any change that is currently in progress */
209         boost::optional<Rect> _pre_change_bounding_box;
210
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;
215
216         /* XXX: this is a bit grubby */
217         std::map<std::string, void *> _data;
218
219 private:
220         void init ();
221
222         bool _ignore_events;
223 };
224
225 extern std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);
226
227 }
228
229
230 #endif