1 /* 2 * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/> 3 * (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com> 4 * 5 * This file is part of lsp-plugins 6 * Created on: 1 окт. 2019 г. 7 * 8 * lsp-plugins is free software: you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation, either version 3 of the License, or 11 * any later version. 12 * 13 * lsp-plugins is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public License 19 * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>. 20 */ 21 22 #ifndef UI_TK_SYS_LSPSTYLE_H_ 23 #define UI_TK_SYS_LSPSTYLE_H_ 24 25 namespace lsp 26 { 27 namespace tk 28 { 29 /** 30 * Style Listener 31 */ 32 class IStyleListener 33 { 34 public: 35 virtual ~IStyleListener(); 36 37 public: 38 /** 39 * Notify about property value change 40 * @param property property identifier 41 */ 42 virtual void notify(ui_atom_t property); 43 }; 44 45 /** 46 * Some widget style. Allows nesting 47 */ 48 class LSPStyle 49 { 50 protected: 51 enum flags_t 52 { 53 F_DEFAULT = 1 << 0, 54 F_NTF_LISTENERS = 1 << 1, 55 F_NTF_CHILDREN = 1 << 2 56 }; 57 58 typedef struct property_t 59 { 60 ui_atom_t id; // Unique identifier of property 61 ssize_t type; // Type of property 62 size_t refs; // Number of references 63 size_t changes; // Number of changes 64 size_t flags; // Flags 65 LSPStyle *owner; // Style that is owning a property 66 union 67 { 68 ssize_t iValue; 69 float fValue; 70 bool bValue; 71 char *sValue; 72 } v; 73 } property_t; 74 75 typedef struct listener_t 76 { 77 ui_atom_t nId; // Property identifier 78 IStyleListener *pListener; // Listener 79 } listener_t; 80 81 private: 82 cvector<LSPStyle> vParents; 83 cvector<LSPStyle> vChildren; 84 cstorage<property_t> vProperties; 85 cstorage<listener_t> vListeners; 86 ssize_t nLock; 87 bool bDelayed; 88 89 public: 90 explicit LSPStyle(); 91 virtual ~LSPStyle(); 92 93 status_t init(); 94 void destroy(); 95 96 protected: 97 void undef_property(property_t *property); 98 void do_destroy(); 99 void delayed_notify(); 100 property_t *get_property_recursive(ui_atom_t id); 101 property_t *get_parent_property(ui_atom_t id); 102 property_t *get_property(ui_atom_t id); 103 status_t set_property(ui_atom_t id, property_t *src); 104 status_t sync_property(property_t *p); 105 property_t *create_property(ui_atom_t id, const property_t *src); 106 property_t *create_property(ui_atom_t id, ui_property_type_t type); 107 status_t set_property_default(property_t *dst); 108 status_t copy_property(property_t *dst, const property_t *src); 109 get_property(ui_atom_t id)110 inline const property_t *get_property(ui_atom_t id) const { return const_cast<LSPStyle *>(this)->get_property(id); }; get_property_recursive(ui_atom_t id)111 inline const property_t *get_property_recursive(ui_atom_t id) const { return const_cast<LSPStyle *>(this)->get_property_recursive(id); }; 112 113 void sync(); 114 void notify_change(property_t *prop); 115 void notify_children(property_t *prop); 116 void notify_listeners(property_t *prop); 117 118 public: 119 /** 120 * Get number of parent styles 121 * @return number of parent styles 122 */ parents()123 inline size_t parents() const { return vParents.size(); } 124 125 /** 126 * Get parent style 127 * @param idx sequential number of parent style starting with 0 128 * @return parent style or NULL if does not exist 129 */ parent(size_t idx)130 inline LSPStyle *parent(size_t idx) { return vParents.get(idx); }; 131 132 /** 133 * Set parent style 134 * @param parent parent style 135 * @param idx parent index, negative value means last 136 * @return status of operation 137 */ 138 status_t add_parent(LSPStyle *parent, ssize_t idx = -1); 139 140 /** 141 * Remove the parent style 142 * @param parent parent style to remove 143 * @return status of operation 144 */ 145 status_t remove_parent(LSPStyle *parent); 146 147 /** 148 * Check whether style has a parent 149 * @param parent parent style 150 * @param recursive flag that indicates that a recursive search should be performed 151 * @return true if style has a parent 152 */ 153 bool has_parent(LSPStyle *parent, bool recursive = false); 154 155 /** 156 * Get number of child styles 157 * @return number of child styles 158 */ children()159 inline size_t children() const { return vChildren.size(); } 160 161 /** 162 * Get child style 163 * @param idx sequential number of child style starting with 0 164 * @return child style or NULL if does not exist 165 */ child(size_t idx)166 inline LSPStyle *child(size_t idx) { return vChildren.get(idx); }; 167 168 /** 169 * Add child style 170 * @param child child style 171 * @param idx child index, negative value means last 172 * @return status of operation 173 */ 174 status_t add_child(LSPStyle *child, ssize_t idx = -1); 175 176 /** Remove child style 177 * 178 * @param child child style to remove 179 * @return status of operation 180 */ 181 status_t remove_child(LSPStyle *child); 182 183 /** 184 * Check whether style has a child 185 * @param child child style 186 * @param recursive flag that indicates that a recursive search should be performed 187 * @return true if style has a child 188 */ 189 bool has_child(LSPStyle *child, bool recursive = false); 190 191 public: 192 /** 193 * Bind listener to property 194 * @param id property identifier 195 * @return status of operation 196 */ 197 status_t bind(ui_atom_t id, ui_property_type_t type, IStyleListener *listener); 198 bind_int(ui_atom_t id,IStyleListener * listener)199 inline status_t bind_int(ui_atom_t id, IStyleListener *listener) { return bind(id, PT_INT, listener); }; bind_float(ui_atom_t id,IStyleListener * listener)200 inline status_t bind_float(ui_atom_t id, IStyleListener *listener) { return bind(id, PT_FLOAT, listener); }; bind_bool(ui_atom_t id,IStyleListener * listener)201 inline status_t bind_bool(ui_atom_t id, IStyleListener *listener) { return bind(id, PT_BOOL, listener); }; bind_string(ui_atom_t id,IStyleListener * listener)202 inline status_t bind_string(ui_atom_t id, IStyleListener *listener) { return bind(id, PT_STRING, listener); }; 203 204 /** 205 * Check that listener is already bound to the property 206 * @param id property identifier 207 * @param listener listener 208 * @return true if listener is bound 209 */ 210 bool is_bound(ui_atom_t id, IStyleListener *listener) const; 211 212 /** 213 * Unbind listener from a property 214 * @param id property identifier 215 * @param listener property listener 216 * @return status of operation 217 */ 218 status_t unbind(ui_atom_t id, IStyleListener *listener); 219 220 public: 221 /** 222 * Return overall number of properties 223 * @return overall number of properties 224 */ properties()225 inline size_t properties() const { return vProperties.size(); } 226 227 /** 228 * Return overall number of listeners 229 * @return overall number of listeners 230 */ listeners()231 inline size_t listeners() const { return vListeners.size(); } 232 233 public: 234 /** 235 * Start transactional update of properties. 236 * All listeners and children will be notified 237 * only after transaction becomes completed 238 */ 239 void begin(); 240 241 /** 242 * End transactional update of properties. 243 * All listeners and children will be notified 244 */ 245 void end(); 246 247 status_t get_int(ui_atom_t id, ssize_t *dst) const; 248 status_t get_float(ui_atom_t id, float *dst) const; 249 status_t get_bool(ui_atom_t id, bool *dst) const; 250 status_t get_string(ui_atom_t id, LSPString *dst) const; 251 status_t get_string(ui_atom_t id, const char **dst) const; 252 bool exists(ui_atom_t id) const; 253 bool is_default(ui_atom_t id) const; 254 ssize_t get_type(ui_atom_t id) const; 255 256 status_t set_int(ui_atom_t id, ssize_t value); 257 status_t set_float(ui_atom_t id, float value); 258 status_t set_bool(ui_atom_t id, bool value); 259 status_t set_string(ui_atom_t id, const LSPString *value); 260 status_t set_string(ui_atom_t id, const char *value); 261 status_t set_default(ui_atom_t id); 262 }; 263 264 } /* namespace tk */ 265 } /* namespace lsp */ 266 267 #endif /* UI_TK_SYS_LSPSTYLE_H_ */ 268