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