summaryrefslogtreecommitdiffstats
path: root/src/display/control/canvas-item.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/display/control/canvas-item.h')
-rw-r--r--src/display/control/canvas-item.h169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/display/control/canvas-item.h b/src/display/control/canvas-item.h
new file mode 100644
index 0000000..fc34176
--- /dev/null
+++ b/src/display/control/canvas-item.h
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#ifndef SEEN_CANVAS_ITEM_H
+#define SEEN_CANVAS_ITEM_H
+
+/**
+ * Abstract base class for on-canvas control items.
+ */
+
+/*
+ * Author:
+ * Tavmjong Bah
+ *
+ * Copyright (C) 2020 Tavmjong Bah
+ *
+ * Rewrite of SPCanvasItem
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ *
+ * A note about coordinates:
+ *
+ * 1. Canvas items are constructed using document (SVG) coordinates.
+ * 2. Calculations are made in canvas units, which is equivalent of SVG units multiplied by zoom factor.
+ * This is true for bounds and closest distance calculations.
+ * 3 Drawing is done in screen units which is the same as canvas units but translated.
+ * The document and canvas origins overlap.
+ * The affine contains only scaling and rotating components.
+ */
+
+#include <cstdint>
+#include <boost/intrusive/list.hpp>
+#include <2geom/rect.h>
+#include <sigc++/sigc++.h>
+
+#include <gdkmm/device.h> // Gdk::EventMask
+#include <gdk/gdk.h> // GdkEvent
+
+#include "canvas-item-enums.h"
+#include "canvas-item-buffer.h"
+#include "canvas-item-context.h"
+
+class SPItem;
+
+namespace Inkscape {
+
+inline constexpr uint32_t CANVAS_ITEM_COLORS[] = { 0x0000ff7f, 0xff00007f, 0xffff007f };
+
+namespace UI::Widget { class Canvas; }
+class CanvasItemGroup;
+
+class CanvasItem
+{
+public:
+ CanvasItem(CanvasItemContext *context);
+ CanvasItem(CanvasItemGroup *parent);
+ CanvasItem(CanvasItem const &) = delete;
+ CanvasItem &operator=(CanvasItem const &) = delete;
+ void unlink();
+
+ // Structure
+ UI::Widget::Canvas *get_canvas() const { return _context->canvas(); }
+ CanvasItemGroup *get_parent() const { return _parent; }
+ bool is_descendant_of(CanvasItem const *ancestor) const;
+
+ // Z Position
+ void set_z_position(int zpos);
+ void raise_to_top(); // Move to top of group (last entry).
+ void lower_to_bottom(); // Move to bottom of group (first entry).
+
+ // Geometry
+ void request_update();
+ void update(bool propagate);
+ virtual void visit_page_rects(std::function<void(Geom::Rect const &)> const &) const {}
+ Geom::OptRect const &get_bounds() const { return _bounds; }
+
+ // Selection
+ virtual bool contains(Geom::Point const &p, double tolerance = 0) { return _bounds && _bounds->interiorContains(p); }
+ void grab(Gdk::EventMask event_mask, Glib::RefPtr<Gdk::Cursor> const & = {});
+ void ungrab();
+
+ // Display
+ void render(Inkscape::CanvasItemBuffer &buf) const;
+ bool is_visible() const { return _visible; }
+ virtual void set_visible(bool visible);
+ void show() { set_visible(true); }
+ void hide() { set_visible(false); }
+ void request_redraw(); // queue redraw request
+
+ // Properties
+ virtual void set_fill(uint32_t rgba);
+ void set_fill(CanvasItemColor color) { set_fill(CANVAS_ITEM_COLORS[color]); }
+ virtual void set_stroke(uint32_t rgba);
+ void set_stroke(CanvasItemColor color) { set_stroke(CANVAS_ITEM_COLORS[color]); }
+ void set_name(std::string &&name) { _name = std::move(name); }
+ std::string const &get_name() const { return _name; }
+ void update_canvas_item_ctrl_sizes(int size_index);
+
+ // Events
+ void set_pickable(bool pickable) { _pickable = pickable; }
+ bool is_pickable() const { return _pickable; }
+ sigc::connection connect_event(sigc::slot<bool(GdkEvent*)> const &slot) {
+ return _event_signal.connect(slot);
+ }
+ virtual bool handle_event(GdkEvent *event) {
+ return _event_signal.emit(event); // Default just emits event.
+ }
+
+ // Recursively print CanvasItem tree.
+ void canvas_item_print_tree(int level = 0, int zorder = 0) const;
+
+ // Boost linked list member hook, speeds deletion.
+ boost::intrusive::list_member_hook<> member_hook;
+
+protected:
+ friend class CanvasItemGroup;
+
+ virtual ~CanvasItem();
+
+ // Structure
+ CanvasItemContext *_context;
+ CanvasItemGroup *_parent;
+
+ // Geometry
+ Geom::OptRect _bounds;
+ bool _need_update = false;
+ Geom::Affine const &affine() const { return _context->affine(); }
+ virtual void _update(bool propagate) = 0;
+ virtual void _mark_net_invisible();
+
+ // Display
+ bool _visible = true;
+ bool _net_visible = true;
+ virtual void _render(Inkscape::CanvasItemBuffer &buf) const = 0;
+
+ // Selection
+ bool _pickable = false; // Most items are just for display and are not pickable!
+
+ // Properties
+ uint32_t _fill = CANVAS_ITEM_COLORS[CANVAS_ITEM_SECONDARY];
+ uint32_t _stroke = CANVAS_ITEM_COLORS[CANVAS_ITEM_PRIMARY];
+ std::string _name; // For debugging
+
+ // Events
+ sigc::signal<bool (GdkEvent*)> _event_signal;
+
+ // Snapshotting
+ template<typename F>
+ void defer(F &&f) { _context->defer(std::forward<F>(f)); }
+};
+
+} // namespace Inkscape
+
+// Todo: Move to lib2geom.
+inline auto &operator<<(std::ostream &s, Geom::OptRect const &rect)
+{
+ return rect ? (s << *rect) : (s << "(empty)");
+}
+
+#endif // SEEN_CANVAS_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :