dialog.hpp (4924B)
1 /* ReaPack: Package manager for REAPER 2 * Copyright (C) 2015-2025 Christian Fillion 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef REAPACK_DIALOG_HPP 19 #define REAPACK_DIALOG_HPP 20 21 #include "serializer.hpp" 22 23 #include <functional> 24 #include <map> 25 #include <memory> 26 #include <set> 27 #include <vector> 28 29 #include <reaper_plugin.h> 30 #include <WDL/wdltypes.h> 31 #include <WDL/wingui/wndsize.h> 32 33 class Control; 34 35 class Dialog { 36 public: 37 typedef std::function<void (INT_PTR)> CloseHandler; 38 39 enum Modality { 40 Modeless, 41 Modal, 42 }; 43 44 enum AnchorFlags { 45 AnchorLeft = 1<<0, 46 AnchorRight = 1<<1, 47 AnchorTop = 1<<2, 48 AnchorBottom = 1<<3, 49 50 AnchorLeftRight = AnchorLeft | AnchorRight, 51 AnchorTopBottom = AnchorTop | AnchorBottom, 52 AnchorAll = AnchorLeftRight | AnchorTopBottom, 53 }; 54 55 template<class T, class... Args> 56 static std::unique_ptr<T> Create(REAPER_PLUGIN_HINSTANCE instance, 57 HWND parent, const CloseHandler &closeHandler, Args&&... args) 58 { 59 auto dlg = std::make_unique<T>(args...); 60 dlg->m_closeHandler = closeHandler; 61 dlg->init(instance, parent, Dialog::Modeless); 62 63 return dlg; 64 } 65 66 template<class T, class... Args> 67 static INT_PTR Show(REAPER_PLUGIN_HINSTANCE instance, HWND parent, Args&&... args) 68 { 69 return std::make_unique<T>(args...)->init(instance, parent, Dialog::Modal); 70 } 71 72 INT_PTR init(REAPER_PLUGIN_HINSTANCE, HWND, const Modality); 73 74 REAPER_PLUGIN_HINSTANCE instance() const { return m_instance; } 75 HWND parent() const { return m_parent; } 76 HWND handle() const { return m_handle; } 77 78 void enable() { enable(m_handle); } 79 void enable(HWND handle) { setEnabled(true, handle); } 80 void disable() { disable(m_handle); } 81 void disable(HWND handle) { setEnabled(false, handle); } 82 void setEnabled(bool enable) { setEnabled(enable, m_handle); } 83 void setEnabled(bool, HWND); 84 bool isChecked(HWND) const; 85 void setChecked(bool, HWND); 86 87 bool isVisible() const; 88 void show(HWND handle = nullptr) { setVisible(true, handle); } 89 void hide(HWND handle = nullptr) { setVisible(false, handle); } 90 void setVisible(bool, HWND = nullptr); 91 92 void close(INT_PTR = 0); 93 void center(); 94 void boundedMove(int x, int y); 95 bool hasFocus() const; 96 void setFocus(); 97 int startTimer(int elapse, int id = 0, bool replace = true); 98 void stopTimer(int id); 99 void setClipboard(const std::string &); 100 void setClipboard(const std::vector<std::string> &); 101 HWND getControl(int idc); 102 void setAnchor(HWND, int flags); 103 void setAnchorPos(HWND, const LONG *left = nullptr, const LONG *top = nullptr, 104 const LONG *right = nullptr, const LONG *bottom = nullptr); 105 const POINT &minimumSize() const { return m_minimumSize; } 106 void setMinimumSize(const POINT &p) { m_minimumSize = p; } 107 108 void restoreState(Serializer::Data &); 109 void saveState(Serializer::Data &) const; 110 111 protected: 112 enum Modifiers { 113 AltModifier = 1<<0, 114 CtrlModifier = 1<<1, 115 ShiftModifier = 1<<2, 116 }; 117 118 Dialog(int templateId); 119 virtual ~Dialog(); 120 121 template<class T, class... Args> 122 T *createControl(int id, Args&&... args) 123 { 124 if(m_controls.count(id)) 125 return nullptr; 126 127 T *ctrl = new T(getControl(id), args...); 128 m_controls.emplace(id, ctrl); 129 130 return ctrl; 131 } 132 133 virtual void onInit(); 134 virtual void onClose(); 135 virtual void onTimer(int id); 136 virtual void onCommand(int id, int event); 137 virtual void onNotify(LPNMHDR, LPARAM); 138 virtual void onContextMenu(HWND, int x, int y); 139 virtual bool onKeyDown(int key, int mods); 140 virtual void onResize(); 141 142 private: 143 static WDL_DLGRET Proc(HWND, UINT, WPARAM, LPARAM); 144 static int HandleKey(MSG *, accelerator_register_t *); 145 146 #ifdef __APPLE__ 147 bool isTextEditUnderMouse() const; 148 #endif 149 150 const int m_template; 151 POINT m_minimumSize; 152 WDL_WndSizer m_resizer; 153 Modality m_mode; 154 155 REAPER_PLUGIN_HINSTANCE m_instance; 156 HWND m_parent; 157 HWND m_handle; 158 159 using ControlPtr = std::unique_ptr<Control>; 160 std::map<int, ControlPtr> m_controls; 161 std::set<int> m_timers; 162 163 CloseHandler m_closeHandler; 164 accelerator_register_t m_accel; 165 }; 166 167 class LockDialog { 168 public: 169 LockDialog(Dialog *dlg) : m_dialog(dlg) 170 { 171 if(m_dialog) 172 m_dialog->disable(); 173 } 174 175 ~LockDialog() 176 { 177 if(m_dialog) 178 m_dialog->enable(); 179 } 180 181 private: 182 Dialog *m_dialog; 183 }; 184 185 #endif