1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2
3 #ifndef SPECTMORPH_WINDOW_HH
4 #define SPECTMORPH_WINDOW_HH
5
6 #include "smwidget.hh"
7 #include "pugl/pugl.h"
8 #include "smnativefiledialog.hh"
9 #include <memory>
10 #include <functional>
11
12 namespace SpectMorph
13 {
14
15 struct CairoGL;
16 class NativeFileDialog;
17 struct Menu;
18 class Shortcut;
19 class EventLoop;
20
21 class Window : public Widget
22 {
23 protected:
24 PuglView *view;
25 std::unique_ptr<CairoGL> cairo_gl;
26 bool draw_grid;
27 bool have_file_dialog = false;
28 std::function<void(std::string)> file_dialog_callback;
29 std::unique_ptr<NativeFileDialog> native_file_dialog;
30 Widget *mouse_widget = nullptr;
31 Widget *enter_widget = nullptr;
32 Widget *menu_widget = nullptr;
33 Widget *keyboard_focus_widget = nullptr;
34 bool keyboard_focus_release_on_click = false;
35 Widget *dialog_widget = nullptr;
36 std::unique_ptr<Window> popup_window;
37 double global_scale;
38 Rect update_region;
39 bool update_full_redraw = false;
40 bool debug_update_region = false;
41 EventLoop *m_event_loop = nullptr;
42 double last_click_time = 0;
43 unsigned last_click_button = 0;
44 Point last_click_pos;
45 unsigned mouse_buttons_pressed = 0;
46
47 std::vector<Shortcut *> shortcuts;
48
49 std::function<void()> m_close_callback;
50
51 Widget *find_widget_xy (double ex, double ey);
52 void on_button_event (const PuglEventButton& event);
53 void on_motion_event (const PuglEventMotion& event);
54 void on_scroll_event (const PuglEventScroll& event);
55 void on_key_event (const PuglEventKey& event);
56 void on_expose_event (const PuglEventExpose& event);
57 void on_close_event (const PuglEventClose& event);
58 void on_configure_event (const PuglEventConfigure& event);
59
60 public:
61 Window (EventLoop& event_loop, const std::string& title, int width, int height, PuglNativeWindow parent = 0, bool resize = false, PuglNativeWindow transient_parent = 0);
62 virtual ~Window();
63
64 std::vector<Widget *> crawl_widgets();
65 void on_event (const PuglEvent *event);
66 void on_resize (int *width, int *height);
67 void process_events();
68 EventLoop *event_loop() const;
69 void show();
70 void open_file_dialog (const std::string& title, const FileDialogFormats& formats, std::function<void(std::string)> callback);
71 void save_file_dialog (const std::string& title, const FileDialogFormats& formats, std::function<void(std::string)> callback);
72 void on_file_selected (const std::string& filename);
73 void need_update (Widget *widget, const Rect *changed_rect = nullptr);
74 void on_widget_deleted (Widget *widget);
75 void set_menu_widget (Widget *widget);
76 void set_keyboard_focus (Widget *widget, bool release_on_click = false);
77 bool has_keyboard_focus (Widget *widget);
78 void set_dialog_widget (Widget *widget);
79 void set_close_callback (const std::function<void()>& callback);
80 void set_popup_window (Window *window);
81 void add_shortcut (Shortcut *shortcut);
82 void remove_shortcut (Shortcut *shortcut);
83 Window *window() override;
84 PuglNativeWindow native_window();
85
86 void fill_zoom_menu (Menu *menu);
87 void set_gui_scaling (double s);
88 double gui_scaling();
89
90 void get_scaled_size (int *w, int *h);
91
92 Signal<> signal_update_size;
93 };
94
95 /* helper to remove all nullptr entries from a vector */
96 template<class T>
97 void
cleanup_null(std::vector<T * > & vec)98 cleanup_null (std::vector<T *>& vec)
99 {
100 std::vector<T *> new_vec;
101 for (auto object : vec)
102 if (object)
103 new_vec.push_back (object);
104
105 if (vec.size() > new_vec.size())
106 vec = new_vec;
107 }
108
109 }
110
111 #endif
112