#include "pbd/signals.h"
+#include "canvas/visibility.h"
#include "canvas/types.h"
-
-class XMLNode;
+#include "canvas/fill.h"
+#include "canvas/outline.h"
+#include "canvas/lookup_table.h"
namespace ArdourCanvas
{
+struct Rect;
class Canvas;
-class Group;
-class Rect;
+class ScrollGroup;
/** The parent class for anything that goes on the canvas.
*
* and all except the `root group' have a pointer to their parent group.
*/
-class Item
+class LIBCANVAS_API Item : public Fill, public Outline
{
public:
Item (Canvas *);
- Item (Group *);
- Item (Group *, Duple);
+ Item (Item *);
+ Item (Item *, Duple const& p);
virtual ~Item ();
+ void redraw () const;
+
/** Render this item to a Cairo context.
- * @param area Area to draw in this item's coordinates.
+ * @param area Area to draw, in **window** coordinates
+ *
+ * Items must convert their own coordinates into window coordinates
+ * because Cairo is limited to a fixed point coordinate space that
+ * does not extend as far as the Ardour timeline. All rendering must
+ * be done using coordinates that do not exceed the (rough) limits
+ * of the canvas' window, to avoid odd errors within Cairo as it
+ * converts doubles into its fixed point format and then tesselates
+ * the results.
*/
virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
- virtual void add_items_at_point (Duple, std::vector<Item const *>& items) const {
- items.push_back (this);
- }
+ /** Adds one or more items to the vector @param items based on their
+ * covering @param point which is in **window** coordinates
+ *
+ * Note that Item::add_items_at_window_point() is only intended to be
+ * called on items already looked up in a LookupTable (i.e. by a
+ * parent) and thus known to cover @param point already.
+ *
+ * Derived classes may add more items than themselves (e.g. containers).
+ */
+ virtual void add_items_at_point (Duple /*point*/, std::vector<Item const *>& items) const;
+
+ virtual bool covers (Duple const &) const;
/** Update _bounding_box and _bounding_box_dirty */
virtual void compute_bounding_box () const = 0;
- virtual XMLNode* get_state () const = 0;
- virtual void set_state (XMLNode const *) = 0;
-
void grab ();
void ungrab ();
- void add_item_state (XMLNode *) const;
- void set_item_state (XMLNode const *);
-
void unparent ();
- void reparent (Group *);
+ void reparent (Item *);
/** @return Parent group, or 0 if this is the root group */
- Group* parent () const {
+ Item* parent () const {
return _parent;
}
+
+ uint32_t depth() const;
+ const Item* closest_ancestor_with (const Item& other) const;
+ bool common_ancestor_within (uint32_t, const Item& other) const;
+
+ /** returns true if this item is an ancestor of @param candidate,
+ * and false otherwise.
+ */
+ bool is_ancestor_of (const Item& candidate) const {
+ return candidate.is_descendant_of (*this);
+ }
+ /** returns true if this Item is a descendant of @param candidate,
+ * and false otherwise.
+ */
+ bool is_descendant_of (const Item& candidate) const;
void set_position (Duple);
void set_x_position (Coord);
return _position;
}
+ Duple window_origin() const;
+ Duple canvas_origin() const;
+
+ ScrollGroup* scroll_parent() const { return _scroll_parent; }
+
boost::optional<Rect> bounding_box () const;
Coord height() const;
Coord width() const;
Rect item_to_parent (Rect const &) const;
Duple parent_to_item (Duple const &) const;
Rect parent_to_item (Rect const &) const;
- /* XXX: it's a pity these aren't the same form as item_to_parent etc.,
+
+ /* XXX: it's a pity these two aren't the same form as item_to_parent etc.,
but it makes a bit of a mess in the rest of the code if they are not.
*/
-
void canvas_to_item (Coord &, Coord &) const;
- Duple canvas_to_item (Duple const &) const;
void item_to_canvas (Coord &, Coord &) const;
- Rect item_to_canvas (Rect const &) const;
- Duple item_to_canvas (Duple const &) const;
+ Duple canvas_to_item (Duple const&) const;
+ Rect item_to_canvas (Rect const&) const;
+ Duple item_to_canvas (Duple const&) const;
+ Rect canvas_to_item (Rect const&) const;
+
+ Duple item_to_window (Duple const&, bool rounded = true) const;
+ Duple window_to_item (Duple const&) const;
+ Rect item_to_window (Rect const&) const;
+ Rect window_to_item (Rect const&) const;
+
void raise_to_top ();
void raise (int);
void lower_to_bottom ();
void set_data (std::string const &, void *);
void* get_data (std::string const &) const;
+
+ /* nested item ("grouping") API */
+ void add (Item *);
+ void remove (Item *);
+ void clear (bool with_delete = false);
+ std::list<Item*> const & items () const {
+ return _items;
+ }
+ void raise_child_to_top (Item *);
+ void raise_child (Item *, int);
+ void lower_child_to_bottom (Item *);
+ void child_changed ();
+
+ static int default_items_per_cell;
+
/* This is a sigc++ signal because it is solely
concerned with GUI stuff and is thus single-threaded
std::string whatami() const;
protected:
+ friend class Fill;
+ friend class Outline;
+ /** To be called at the beginning of any property change that
+ * may alter the bounding box of this item
+ */
void begin_change ();
+ /** To be called at the endof any property change that
+ * may alter the bounding box of this item
+ */
void end_change ();
+ /** To be called at the beginning of any property change that
+ * does NOT alter the bounding box of this item
+ */
+ void begin_visual_change ();
+ /** To be called at the endof any property change that
+ * does NOT alter the bounding box of this item
+ */
+ void end_visual_change ();
Canvas* _canvas;
/** parent group; may be 0 if we are the root group or if we have been unparent()ed */
- Group* _parent;
+ Item* _parent;
+ /** scroll parent group; may be 0 if we are the root group or if we have been unparent()ed */
+ ScrollGroup* _scroll_parent;
/** position of this item in parent coordinates */
Duple _position;
/** true if this item is visible (ie to be drawn), otherwise false */
/* XXX: this is a bit grubby */
std::map<std::string, void *> _data;
+ /* nesting ("grouping") API */
+
+ void invalidate_lut () const;
+ void clear_items (bool with_delete);
+
+ void ensure_lut () const;
+ mutable LookupTable* _lut;
+ /* our items, from lowest to highest in the stack */
+ std::list<Item*> _items;
+
+ void add_child_bounding_boxes() const;
+ void render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
+
private:
void init ();
bool _ignore_events;
+
+ Duple scroll_offset() const;
+ Duple position_offset() const;
+
+ void find_scroll_parent ();
};
-extern std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);
+extern LIBCANVAS_API std::ostream& operator<< (std::ostream&, const ArdourCanvas::Item&);
}