Warning, file /graphics/glaxnimate/src/gui/tools/base.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <map> 0010 #include <memory> 0011 0012 #include <QMouseEvent> 0013 #include <QKeyEvent> 0014 #include <QAction> 0015 0016 #include "glaxnimate_app.hpp" 0017 #include "graphics/document_scene.hpp" 0018 #include "graphics/document_node_graphics_item.hpp" 0019 #include "graphics/handle.hpp" 0020 #include "widgets/canvas.hpp" 0021 #include "widgets/scalable_button.hpp" 0022 #include "widgets/dialogs/selection_manager.hpp" 0023 0024 namespace glaxnimate::gui::tools { 0025 0026 struct Event 0027 { 0028 Canvas* view; 0029 graphics::DocumentScene* scene; 0030 glaxnimate::gui::SelectionManager* window; 0031 0032 void repaint() const 0033 { 0034 view->viewport()->update(); 0035 } 0036 }; 0037 0038 struct MouseEvent : Event 0039 { 0040 /// Originating Qt event 0041 QMouseEvent* event; 0042 /// Mouse position in scene coordinates 0043 QPointF scene_pos; 0044 0045 /// Mouse press that started the event (also available in move events) 0046 Qt::MouseButton press_button; 0047 /// Position of when the button has been pressed (scene coordinates) 0048 QPointF press_scene_pos; 0049 /// Position of when the button has been pressed (screen coordinates) 0050 QPoint press_screen_pos; 0051 /// Position of the last known mouse position (scene coordinates) 0052 QPointF last_scene_pos; 0053 /// Position of the last known mouse position (screen coordinates) 0054 QPoint last_screen_pos; 0055 0056 /// Modifiers being held during the event 0057 Qt::KeyboardModifiers modifiers() const { return event->modifiers(); } 0058 /// Button that triggered press/release 0059 Qt::MouseButton button() const { return event->button(); } 0060 /// Buttons being held during the event 0061 Qt::MouseButtons buttons() const { return event->buttons(); } 0062 /// Position of the event in view coordinates 0063 #if QT_VERSION_MAJOR < 6 0064 const QPointF& pos() const { return event->localPos(); } 0065 #else 0066 QPointF pos() const { return event->position(); } 0067 #endif 0068 /// Tell the Qt event that it should not propagate 0069 void accept() const { event->accept(); } 0070 0071 /// Use the default behaviour for this event (useful to select items etc) 0072 void forward_to_scene() const; 0073 }; 0074 0075 struct PaintEvent : Event 0076 { 0077 QPainter* painter; 0078 QPalette palette; 0079 }; 0080 0081 struct KeyEvent : public Event 0082 { 0083 QKeyEvent* event; 0084 0085 Qt::KeyboardModifiers modifiers() const { return event->modifiers(); } 0086 int key() const { return event->key(); } 0087 QString text() const { return event->text(); } 0088 void accept() const { event->accept(); } 0089 }; 0090 0091 using Priority = int; 0092 0093 class Tool : public QObject 0094 { 0095 Q_OBJECT 0096 0097 public: 0098 using SelectionMode = graphics::DocumentNodeGraphicsItem::SelectionMode; 0099 0100 virtual ~Tool() = default; 0101 0102 virtual QString id() const = 0; 0103 virtual QIcon icon() const = 0; 0104 virtual QString name() const = 0; 0105 virtual QString tooltip() const { return name(); } 0106 virtual QKeySequence key_sequence() const = 0; 0107 0108 QAction* get_action(); 0109 0110 /** 0111 * \pre get_action() called before calling this 0112 */ 0113 ScalableButton* get_button(); 0114 0115 QWidget* get_settings_widget(); 0116 0117 /** 0118 * \pre get_action and get_button already called 0119 */ 0120 void retranslate(); 0121 0122 virtual void mouse_press(const MouseEvent& event) = 0; 0123 virtual void mouse_move(const MouseEvent& event) = 0; 0124 virtual void mouse_release(const MouseEvent& event) = 0; 0125 virtual void mouse_double_click(const MouseEvent& event) = 0; 0126 virtual void paint(const PaintEvent& event) = 0; 0127 virtual void key_press(const KeyEvent& event) = 0; 0128 virtual void key_release(const KeyEvent& event) { Q_UNUSED(event); } 0129 virtual QCursor cursor() = 0; 0130 virtual void enable_event(const Event& event) = 0; 0131 virtual void disable_event(const Event& event) = 0; 0132 virtual void close_document_event(const Event& event) { Q_UNUSED(event); } 0133 virtual void shape_style_change_event(const Event& event) { Q_UNUSED(event); } 0134 0135 virtual void on_selected(graphics::DocumentScene* scene, model::VisualNode* node) { Q_UNUSED(scene); Q_UNUSED(node); } 0136 virtual void on_deselected(graphics::DocumentScene* scene, model::VisualNode* node); 0137 // Brief called once the GUI has been fully initialized 0138 virtual void initialize(const Event& event) { Q_UNUSED(event); } 0139 0140 virtual int group() const noexcept = 0; 0141 0142 protected: 0143 struct UnderMouse 0144 { 0145 graphics::MoveHandle* handle = nullptr; 0146 std::vector<graphics::DocumentNodeGraphicsItem*> nodes; 0147 }; 0148 0149 UnderMouse under_mouse(const MouseEvent& event, bool only_selectable, SelectionMode mode) const; 0150 graphics::MoveHandle* handle_under_mouse(const MouseEvent& event) const; 0151 0152 virtual QWidget* on_create_widget() = 0; 0153 virtual void on_translate() {} 0154 0155 QVariantMap settings_values; 0156 0157 static constexpr Priority max_priority = std::numeric_limits<Priority>::min(); 0158 0159 void edit_clicked(const MouseEvent& event); 0160 0161 Q_SIGNALS: 0162 void cursor_changed(const QCursor&); 0163 0164 private: 0165 QAction* action = nullptr; 0166 ScalableButton* button = nullptr; 0167 QWidget* settings_widget = nullptr; 0168 0169 // friend Canvas; 0170 }; 0171 0172 0173 class Registry 0174 { 0175 public: 0176 enum Group 0177 { 0178 Core, 0179 Draw, 0180 Shape, 0181 Style, 0182 User 0183 }; 0184 0185 using container = std::map<int, std::multimap<Priority, std::unique_ptr<Tool>>>; 0186 using iterator = container::const_iterator; 0187 using mapped_type = container::mapped_type; 0188 0189 static Registry& instance() 0190 { 0191 static Registry instance; 0192 return instance; 0193 } 0194 0195 iterator begin() const { return tools.begin(); } 0196 iterator end() const { return tools.end(); } 0197 0198 void register_tool(int group, qreal priority, std::unique_ptr<Tool> tool) 0199 { 0200 by_id[tool->id()] = tool.get(); 0201 tools[group].emplace(priority, std::move(tool)); 0202 } 0203 0204 Tool* tool(const QString& id) const 0205 { 0206 auto it = by_id.find(id); 0207 if ( it == by_id.end() ) 0208 return nullptr; 0209 return it->second; 0210 } 0211 0212 const mapped_type& operator[](Group g) const 0213 { 0214 return tools.at(g); 0215 } 0216 0217 private: 0218 Registry() = default; 0219 Registry(const Registry&) = delete; 0220 ~Registry() = default; 0221 0222 container tools; 0223 std::map<QString, Tool*> by_id; 0224 }; 0225 0226 0227 0228 template<class T> 0229 class Autoreg 0230 { 0231 public: 0232 Autoreg(Priority priority) 0233 { 0234 Registry::instance().register_tool(T::static_group(), priority, std::make_unique<T>()); 0235 } 0236 }; 0237 0238 0239 } // namespace glaxnimate::gui::tools