1 #pragma once
2 #include "canvas.hpp"
3 #include "drag_selection.hpp"
4 #include "grid.hpp"
5 #include "marker.hpp"
6 #include "triangle_renderer.hpp"
7 #include "selectables_renderer.hpp"
8 #include "util/msd_animator.hpp"
9 #include <gtkmm.h>
10 #include <glm/glm.hpp>
11 #include "appearance.hpp"
12 #include "annotation.hpp"
13 #include "snap_filter.hpp"
14 #include "picture_renderer.hpp"
15 #include "selection_filter.hpp"
16 
17 namespace horizon {
18 class CanvasGL : public Canvas, public Gtk::GLArea {
19     friend Grid;
20     friend DragSelection;
21     friend SelectablesRenderer;
22     friend TriangleRenderer;
23     friend MarkerRenderer;
24     friend Markers;
25     friend CanvasAnnotation;
26     friend PictureRenderer;
27 
28 public:
29     CanvasGL();
30 
31     enum class SelectionMode { HOVER, NORMAL };
32     void set_selection_mode(SelectionMode mode);
33     SelectionMode get_selection_mode() const;
34     typedef sigc::signal<void, SelectionMode> type_signal_selection_mode_changed;
signal_selection_mode_changed()35     type_signal_selection_mode_changed signal_selection_mode_changed()
36     {
37         return s_signal_selection_mode_changed;
38     }
39 
40     enum class SelectionTool { BOX, LASSO, PAINT };
41     SelectionTool selection_tool = SelectionTool::BOX;
42 
43     enum class SelectionQualifier { INCLUDE_ORIGIN, INCLUDE_BOX, TOUCH_BOX, AUTO };
44     SelectionQualifier selection_qualifier = SelectionQualifier::INCLUDE_ORIGIN;
45 
46     enum class HighlightMode { HIGHLIGHT, DIM, SHADOW };
47     void set_highlight_mode(HighlightMode mode);
48     HighlightMode get_highlight_mode() const;
49     void set_highlight_enabled(bool x);
50     void set_highlight_on_top(bool on_top);
51 
52     enum class LayerMode { AS_IS, WORK_ONLY, SHADOW_OTHER };
53     void set_layer_mode(LayerMode mode);
54 
55     std::set<SelectableRef> get_selection();
56     void set_selection(const std::set<SelectableRef> &sel, bool emit = true);
57     void select_all();
58     void set_cursor_pos(const Coordi &c);
59     void set_cursor_external(bool v);
60     Coordi get_cursor_pos();
61     Coordf get_cursor_pos_win();
62     Target get_current_target();
63     void set_selection_allowed(bool a);
64     std::pair<float, Coordf> get_scale_and_offset();
65     void set_scale_and_offset(float sc, Coordf ofs);
66     Coordi snap_to_grid(const Coordi &c, unsigned int div = 1) const;
67 
68     void set_flip_view(bool fl);
69     bool get_flip_view() const override;
70 
71     void set_view_angle(float a);
72     float get_view_angle() const override;
73 
74     void set_cursor_size(float size);
75     void set_cursor_size(Appearance::CursorSize);
76 
77     void clear() override;
78 
79     typedef sigc::signal<void> type_signal_selection_changed;
signal_selection_changed()80     type_signal_selection_changed signal_selection_changed()
81     {
82         return s_signal_selection_changed;
83     }
84 
signal_hover_selection_changed()85     type_signal_selection_changed signal_hover_selection_changed()
86     {
87         return s_signal_hover_selection_changed;
88     }
89 
90     typedef sigc::signal<void, const Coordi &> type_signal_cursor_moved;
signal_cursor_moved()91     type_signal_cursor_moved signal_cursor_moved()
92     {
93         return s_signal_cursor_moved;
94     }
95 
96     typedef sigc::signal<void, unsigned int> type_signal_grid_mul_changed;
signal_grid_mul_changed()97     type_signal_grid_mul_changed signal_grid_mul_changed()
98     {
99         return s_signal_grid_mul_changed;
100     }
get_grid_mul() const101     unsigned int get_grid_mul() const
102     {
103         return grid.mul;
104     }
105 
106     typedef sigc::signal<std::string, const SelectableRef &> type_signal_request_display_name;
signal_request_display_name()107     type_signal_request_display_name signal_request_display_name()
108     {
109         return s_signal_request_display_name;
110     }
111 
112     typedef sigc::signal<void, bool &> type_signal_can_steal_focus;
signal_can_steal_focus()113     type_signal_can_steal_focus signal_can_steal_focus()
114     {
115         return s_signal_can_steal_focus;
116     }
117 
118     typedef sigc::signal<void> type_signal_scale_changed;
signal_scale_changed()119     type_signal_scale_changed signal_scale_changed()
120     {
121         return s_signal_scale_changed;
122     }
123 
124     void center_and_zoom(const Coordf &center, float scale = -1);
125     void zoom_to_bbox(const Coordf &a, const Coordf &b);
126     void zoom_to_bbox(const std::pair<Coordf, Coordf> &bb);
127     void ensure_min_size(float w, float h);
128     void zoom_to(const Coordf &c, float inc);
129 
property_work_layer()130     Glib::PropertyProxy<int> property_work_layer()
131     {
132         return p_property_work_layer.get_proxy();
133     }
property_layer_opacity()134     Glib::PropertyProxy<float> property_layer_opacity()
135     {
136         return p_property_layer_opacity.get_proxy();
137     }
property_layer_opacity() const138     Glib::PropertyProxy_ReadOnly<float> property_layer_opacity() const
139     {
140         return Glib::PropertyProxy_ReadOnly<float>(this, "layer-opacity");
141     }
142     Markers markers;
143     void update_markers() override;
144 
145     std::set<SelectableRef> get_selection_at(const Coordi &c);
146     Coordf screen2canvas(const Coordf &p) const;
147     void update_cursor_pos(double x, double y);
148 
149     const Appearance &get_appearance() const;
150     void set_appearance(const Appearance &a);
151     const Color &get_color(ColorP colorp) const;
152 
153     bool touchpad_pan = false;
154 
155     bool smooth_zoom = true;
156     bool snap_to_targets = true;
157 
158     float zoom_base = 1.5;
159 
160     void inhibit_drag_selection();
161 
162     int _animate_step(GdkFrameClock *frame_clock);
163 
get_width() const164     float get_width() const
165     {
166         return m_width;
167     }
get_height() const168     float get_height() const
169     {
170         return m_height;
171     }
172 
173     CanvasAnnotation *create_annotation();
174     void remove_annotation(CanvasAnnotation *a);
175     bool layer_is_annotation(int l) const;
176 
177     std::set<SnapFilter> snap_filter;
178 
179     void set_grid_spacing(uint64_t x, uint64_t y);
180     void set_grid_spacing(uint64_t s);
181     Coordi get_grid_spacing() const;
182     void set_grid_origin(const Coordi &c);
183 
184     SelectionFilter selection_filter;
185 
186     bool layer_is_visible(int layer) const;
187     bool layer_is_visible(LayerRange layer) const;
188 
189     void set_colors2(const std::vector<ColorI> &c);
190 
191     int get_last_grid_div() const;
192 
193     void append_target(const Target &target);
194 
195 protected:
196     void push() override;
197     void request_push() override;
198 
199 private:
200     static const int MAT3_XX = 0;
201     static const int MAT3_X0 = 2;
202     static const int MAT3_YY = 4;
203     static const int MAT3_Y0 = 5;
204 
205     float m_width, m_height;
206     glm::mat3 screenmat;
207     float scale = 1e-5;
208     Coord<float> offset;
209     glm::mat3 viewmat;
210     glm::mat3 viewmat_noflip;
211     bool flip_view = false;
212     float view_angle = 0;
213     void update_viewmat();
214     Coordf canvas2screen(const Coordf &p) const;
215 
216     Coord<float> cursor_pos;
217     Coord<int64_t> cursor_pos_grid;
218     bool cursor_external = false;
219 
220     GLuint renderbuffer;
221     GLuint stencilrenderbuffer;
222     GLuint fbo;
223     bool needs_resize = false;
224     enum PushFilter {
225         PF_NONE = 0,
226         PF_TRIANGLES = (1 << 0),
227         PF_CURSOR = (1 << 1),
228         PF_SELECTABLES = (1 << 2),
229         PF_MARKER = (1 << 3),
230         PF_DRAG_SELECTION = (1 << 4),
231         PF_ALL = 0xff
232     };
233     PushFilter push_filter = PF_ALL;
234     void request_push(PushFilter filter);
235 
236     void resize_buffers();
237 
238     Grid grid;
239     DragSelection drag_selection;
240     SelectablesRenderer selectables_renderer;
241     TriangleRenderer triangle_renderer;
242 
243     MarkerRenderer marker_renderer;
244 
245     PictureRenderer picture_renderer;
246 
247     void pan_drag_begin(GdkEventButton *button_event);
248     void pan_drag_end(GdkEventButton *button_event);
249     void pan_drag_move(GdkEventMotion *motion_event);
250     void pan_drag_move(GdkEventScroll *scroll_event);
251     void pan_zoom(GdkEventScroll *scroll_event, bool to_cursor = true);
252     void start_smooth_zoom(const Coordf &c, float inc);
253     void cursor_move(GdkEvent *motion_event);
254     void hover_prelight_update(GdkEvent *motion_event);
255     bool pan_dragging = false;
256     Coord<float> pan_pointer_pos_orig;
257     Coord<float> pan_offset_orig;
258 
259     void set_scale(float x, float y, float new_scale);
260 
261     bool selection_allowed = true;
262     Glib::Property<int> p_property_work_layer;
263     Glib::Property<float> p_property_layer_opacity;
264 
265     Gtk::Menu *clarify_menu;
266 
267     HighlightMode highlight_mode = HighlightMode::HIGHLIGHT;
268     bool highlight_enabled = false;
269     bool highlight_on_top = false;
270     Appearance appearance;
271 
272     LayerMode layer_mode = LayerMode::AS_IS;
273 
274     bool drag_selection_inhibited = false;
275 
276     MSDAnimator zoom_animator;
277     float zoom_animation_scale_orig = 1;
278     Coordf zoom_animation_pos;
279 
280     Gdk::ModifierType grid_fine_modifier = Gdk::MOD1_MASK;
281     float cursor_size = 20;
282 
283     static const int first_annotation_layer = 20000;
284     int annotation_layer_current = first_annotation_layer;
285     std::map<int, CanvasAnnotation> annotations;
286 
287     void draw_bitmap_text(const Coordf &p, float scale, const std::string &rtext, int angle, ColorP color,
288                           int layer) override;
289     std::pair<Coordf, Coordf> measure_bitmap_text(const std::string &text) const override;
290     void draw_bitmap_text_box(const Placement &q, float width, float height, const std::string &s, ColorP color,
291                               int layer, TextBoxMode mode) override;
292 
293     SelectionMode selection_mode = SelectionMode::HOVER;
294 
295     Glib::RefPtr<Gtk::GestureZoom> gesture_zoom;
296     void zoom_gesture_begin_cb(GdkEventSequence *seq);
297     void zoom_gesture_update_cb(GdkEventSequence *seq);
298     Coord<float> gesture_zoom_pos_orig;
299     Coord<float> gesture_zoom_offset_orig;
300     float gesture_zoom_scale_orig = 1;
301 
302     Glib::RefPtr<Gtk::GestureDrag> gesture_drag;
303     Coord<float> gesture_drag_offset_orig;
304 
305     void drag_gesture_begin_cb(GdkEventSequence *seq);
306     void drag_gesture_update_cb(GdkEventSequence *seq);
307 
308     bool can_snap_to_target(const Target &t) const;
309 
310     std::vector<ColorI> colors2;
311 
312     bool can_set_scale() const;
313 
314     int last_grid_div = 1;
315 
316 protected:
317     void on_size_allocate(Gtk::Allocation &alloc) override;
318     void on_realize() override;
319     bool on_render(const Glib::RefPtr<Gdk::GLContext> &context) override;
320     bool on_button_press_event(GdkEventButton *button_event) override;
321     bool on_button_release_event(GdkEventButton *button_event) override;
322     bool on_motion_notify_event(GdkEventMotion *motion_event) override;
323     bool on_scroll_event(GdkEventScroll *scroll_event) override;
324     Glib::RefPtr<Gdk::GLContext> on_create_context() override;
325 
326     type_signal_selection_changed s_signal_selection_changed;
327     type_signal_selection_changed s_signal_hover_selection_changed;
328     type_signal_selection_mode_changed s_signal_selection_mode_changed;
329     type_signal_cursor_moved s_signal_cursor_moved;
330     type_signal_grid_mul_changed s_signal_grid_mul_changed;
331     type_signal_request_display_name s_signal_request_display_name;
332     type_signal_can_steal_focus s_signal_can_steal_focus;
333     type_signal_scale_changed s_signal_scale_changed;
334 };
335 } // namespace horizon
336