// SPDX-License-Identifier: GPL-2.0-or-later #ifndef INKSCAPE_UI_WIDGET_CANVAS_H #define INKSCAPE_UI_WIDGET_CANVAS_H /* * Authors: * Tavmjong Bah * PBS * * Copyright (C) 2022 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include <2geom/rect.h> #include <2geom/int-rect.h> #include "display/rendermode.h" class SPDesktop; namespace Inkscape { class CanvasItem; class CanvasItemGroup; class Drawing; namespace UI { namespace Widget { class CanvasPrivate; /** * A Gtk::DrawingArea widget for Inkscape's canvas. */ class Canvas : public Gtk::DrawingArea { using parent_type = Gtk::DrawingArea; public: Canvas(); ~Canvas() override; /* Configuration */ // Desktop (Todo: Remove.) void set_desktop(SPDesktop *desktop) { _desktop = desktop; } SPDesktop *get_desktop() const { return _desktop; } // Drawing void set_drawing(Inkscape::Drawing *drawing); // Canvas item root CanvasItemGroup *get_canvas_item_root() const { return _canvas_item_root; } // Geometry void set_pos (const Geom::IntPoint &pos); void set_pos (const Geom::Point &fpos) { set_pos(fpos.round()); } void set_affine(const Geom::Affine &affine); const Geom::IntPoint& get_pos () const {return _pos;} const Geom::Affine& get_affine() const {return _affine;} // Background void set_background_color(guint32 rgba); void set_background_checkerboard(guint32 rgba = 0xC4C4C4FF, bool use_alpha = false); // Rendering modes void set_render_mode(Inkscape::RenderMode mode); void set_color_mode (Inkscape::ColorMode mode); void set_split_mode (Inkscape::SplitMode mode); Inkscape::RenderMode get_render_mode() const { return _render_mode; } Inkscape::ColorMode get_color_mode() const { return _color_mode; } Inkscape::SplitMode get_split_mode() const { return _split_mode; } // CMS void set_cms_key(std::string key) { _cms_key = std::move(key); _cms_active = !_cms_key.empty(); } const std::string& get_cms_key() const { return _cms_key; } void set_cms_active(bool active) { _cms_active = active; } bool get_cms_active() const { return _cms_active; } /* Observers */ // Geometry Geom::IntPoint get_dimensions() const; bool world_point_inside_canvas(Geom::Point const &world) const; // desktop-events.cpp Geom::Point canvas_to_world(Geom::Point const &window) const; Geom::IntRect get_area_world() const; // State bool is_dragging() const { return _is_dragging; } // selection-chemistry.cpp // Encapsulation leaks Cairo::RefPtr get_backing_store() const; // canvas-item-rotate.cpp Cairo::RefPtr get_background_pattern() const { return _background; } // canvas-item-rect.cpp, canvas-item-ctrl.cpp /* Methods */ // Invalidation void redraw_all(); // Mark everything as having changed. void redraw_area(Geom::Rect& area); // Mark a rectangle of world space as having changed. void redraw_area(int x0, int y0, int x1, int y1); void redraw_area(Geom::Coord x0, Geom::Coord y0, Geom::Coord x1, Geom::Coord y1); void request_update(); // Mark geometry as needing recalculation. // Gobblers (tool-base.cpp) int gobble_key_events(guint keyval, guint mask); void gobble_motion_events(guint mask); // Callback run on destructor of any canvas item void canvas_item_destructed(Inkscape::CanvasItem *item); // State Inkscape::CanvasItem *get_current_canvas_item() const { return _current_canvas_item; } void set_current_canvas_item(Inkscape::CanvasItem *item) { _current_canvas_item = item; } Inkscape::CanvasItem *get_grabbed_canvas_item() const { return _grabbed_canvas_item; } void set_grabbed_canvas_item(Inkscape::CanvasItem *item, Gdk::EventMask mask) { _grabbed_canvas_item = item; _grabbed_event_mask = mask; } void set_drawing_disabled(bool disable); // Disable during path ops, etc. void set_all_enter_events(bool on) { _all_enter_events = on; } protected: void get_preferred_width_vfunc (int &minimum_width, int &natural_width ) const override; void get_preferred_height_vfunc(int &minimum_height, int &natural_height) const override; // Event handlers bool on_scroll_event (GdkEventScroll* ) override; bool on_button_event (GdkEventButton* ); bool on_button_press_event (GdkEventButton* ) override; bool on_button_release_event(GdkEventButton* ) override; bool on_enter_notify_event (GdkEventCrossing*) override; bool on_leave_notify_event (GdkEventCrossing*) override; bool on_focus_in_event (GdkEventFocus* ) override; bool on_key_press_event (GdkEventKey* ) override; bool on_key_release_event (GdkEventKey* ) override; bool on_motion_notify_event (GdkEventMotion* ) override; void on_realize() override; void on_unrealize() override; void on_size_allocate(Gtk::Allocation&) override; bool on_draw(const Cairo::RefPtr&) override; private: /* Configuration */ // Desktop SPDesktop *_desktop = nullptr; // Drawing Inkscape::Drawing *_drawing = nullptr; // Canvas item root CanvasItemGroup *_canvas_item_root = nullptr; // Geometry Geom::IntPoint _pos; ///< Coordinates of top-left pixel of canvas view within canvas. Geom::Affine _affine; ///< The affine that we have been requested to draw at. // Background Cairo::RefPtr _background; ///< The background of the widget. // Rendering modes Inkscape::RenderMode _render_mode = Inkscape::RenderMode::NORMAL; Inkscape::SplitMode _split_mode = Inkscape::SplitMode::NORMAL; Inkscape::ColorMode _color_mode = Inkscape::ColorMode::NORMAL; // CMS std::string _cms_key; bool _cms_active = false; /* Internal state */ // Event handling/item picking GdkEvent _pick_event; ///< Event used to find currently selected item. bool _in_repick; ///< For tracking recursion of pick_current_item(). bool _left_grabbed_item; ///< ? bool _all_enter_events; ///< Keep all enter events. Only set true in connector-tool.cpp. bool _is_dragging; ///< Used in selection-chemistry to block undo/redo. int _state; ///< Last known modifier state (SHIFT, CTRL, etc.). Inkscape::CanvasItem *_current_canvas_item; ///< Item containing cursor, nullptr if none. Inkscape::CanvasItem *_current_canvas_item_new; ///< Item to become _current_item, nullptr if none. Inkscape::CanvasItem *_grabbed_canvas_item; ///< Item that holds a pointer grab; nullptr if none. Gdk::EventMask _grabbed_event_mask; // Drawing bool _drawing_disabled = false; ///< Disable drawing during critical operations bool _need_update = true; // Set true so setting CanvasItem bounds are calculated at least once. // Split view Inkscape::SplitDirection _split_direction; Geom::Point _split_position; Inkscape::SplitDirection _hover_direction; bool _split_dragging; Geom::Point _split_drag_start; void add_clippath(const Cairo::RefPtr&); void set_cursor(); // Opaque pointer to implementation friend class CanvasPrivate; std::unique_ptr d; }; } // namespace Widget } // namespace UI } // namespace Inkscape #endif // INKSCAPE_UI_WIDGET_CANVAS_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:fileencoding=utf-8:textwidth=99 :