1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605
|
/*
* Copyright (C) 2024 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2024 Vladimir Sadovnikov <sadko4u@gmail.com>
*
* This file is part of lsp-tk-lib
* Created on: 1 окт. 2019 г.
*
* lsp-tk-lib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* lsp-tk-lib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lsp-tk-lib. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef LSP_PLUG_IN_TK_STYLE_STYLE_H_
#define LSP_PLUG_IN_TK_STYLE_STYLE_H_
#ifndef LSP_PLUG_IN_TK_IMPL
#error "use <lsp-plug.in/tk/tk.h>"
#endif
#include <lsp-plug.in/runtime/LSPString.h>
#include <lsp-plug.in/lltl/parray.h>
#include <lsp-plug.in/lltl/darray.h>
namespace lsp
{
namespace tk
{
class Schema;
class Property;
/**
* Some widget style. Allows nesting
*/
class Style
{
private:
friend class IStyleFactory;
friend class Schema;
friend class Property;
protected:
enum flags_t
{
F_OVERRIDDEN = 1 << 0, // Property has been locally overridden by client
F_NTF_LISTENERS = 1 << 1, // Property requires notification of listeners
F_NTF_CHILDREN = 1 << 2, // Property requires notification of children
};
enum style_flags_t
{
S_DELAYED = 1 << 0, // Delayed notification
S_OVERRIDE = 1 << 1, // Force overrides
S_CONFIGURED = 1 << 2, // The changes to style have been configured
};
typedef struct property_t
{
atom_t id; // Unique identifier of property
property_type_t type; // Type of property
ssize_t refs; // Number of references
size_t changes; // Number of changes
size_t flags; // Flags
Style *owner; // Style that is owning a property
union
{
ssize_t iValue;
float fValue;
bool bValue;
char *sValue;
} v; // Actual property value
union
{
ssize_t iValue;
float fValue;
bool bValue;
char *sValue;
} dv; // Property local default value
} property_t;
typedef struct listener_t
{
atom_t nId; // Property identifier
bool bNotify; // Delayed notify flag
IStyleListener *pListener; // Listener
} listener_t;
typedef struct prop_sync_t
{
property_t *pProperty; // Property of this style
property_t *pParent; // Property of parent style
} property_sync_t;
typedef struct client_t
{
atom_t nId;
Property *pClient;
} client_t;
private:
lltl::parray<Style> vParents;
lltl::parray<Style> vChildren;
lltl::darray<property_t> vProperties;
lltl::darray<listener_t> vListeners;
lltl::parray<IStyleListener> vLocks;
mutable Schema *pSchema;
size_t nFlags;
char *sName;
char *sDflParents;
public:
explicit Style(Schema *schema, const char *name, const char *parents);
Style(const Style &) = delete;
Style(Style &&) = delete;
virtual ~Style();
Style & operator = (const Style &) = delete;
Style & operator = (Style &&) = delete;
virtual status_t init();
void destroy();
protected:
void undef_property(property_t *property);
void do_destroy();
void delayed_notify();
property_t *get_property_recursive(atom_t id);
property_t *get_parent_property(atom_t id);
property_t *get_property(atom_t id);
status_t set_property(atom_t id, property_t *src);
status_t sync_property(property_t *p);
property_t *create_property(atom_t id, const property_t *src, size_t flags);
property_t *create_property(atom_t id, property_type_t type, size_t flags);
status_t set_property_default(property_t *dst);
status_t copy_property(property_t *dst, const property_t *src);
status_t update_default_value(property_t *p, const property_t *src);
inline const property_t *get_property(atom_t id) const { return const_cast<Style *>(this)->get_property(id); };
inline const property_t *get_property_recursive(atom_t id) const { return const_cast<Style *>(this)->get_property_recursive(id); };
void synchronize();
void notify_change(property_t *prop);
void notify_children(property_t *prop);
size_t notify_children_delayed(property_t *prop);
void notify_listeners(property_t *prop);
size_t notify_listeners_delayed(property_t *prop);
void deref_property(property_t *prop);
status_t inheritance_tree(lltl::parray<Style> *dst);
bool set_configured(bool set);
inline const char *name() const { return sName; }
inline const char *default_parents() const { return sDflParents; }
inline bool configured() const { return nFlags & S_CONFIGURED; }
public:
/** Set override mode for the style
*
* @param set overide mode (true/false)
* @return previous mode
*/
bool set_override(bool set);
/**
* Get associated schema
* @return schema
*/
inline Schema *schema() { return pSchema; }
/**
* Get associated schema
* @return schema
*/
inline Schema *schema() const { return pSchema; }
/**
* Get number of parent styles
* @return number of parent styles
*/
inline size_t parents() const { return vParents.size(); }
/**
* Get parent style
* @param idx sequential number of parent style starting with 0
* @return parent style or NULL if does not exist
*/
inline Style *parent(size_t idx) { return vParents.get(idx); }
/**
* Check sync mode
* @return true if sync mode
*/
bool config_mode() const;
/**
* Check sync mode
* @return true if sync mode
*/
bool override_mode() const;
/**
* Set parent style
* @param parent parent style
* @param idx parent index, negative value means last
* @return status of operation
*/
status_t add_parent(Style *parent, ssize_t idx = -1);
/**
* Inject parent style as having most priority against others
* @param parent parent style to inject
* @return status of operation
*/
inline status_t inject_parent(Style *parent) { return add_parent(parent, -1); }
/**
* Remove the parent style
* @param parent parent style to remove
* @return status of operation
*/
status_t remove_parent(Style *parent);
/**
* Remove all parents
* @return status of operation
*/
status_t remove_all_parents();
/**
* Check whether style has a parent
* @param parent parent style
* @param recursive flag that indicates that a recursive search should be performed
* @return true if style has a parent
*/
bool has_parent(Style *parent, bool recursive = false);
/**
* Get number of child styles
* @return number of child styles
*/
inline size_t children() const { return vChildren.size(); }
/**
* Get child style
* @param idx sequential number of child style starting with 0
* @return child style or NULL if does not exist
*/
inline Style *child(size_t idx) { return vChildren.get(idx); };
/**
* Add child style
* @param child child style
* @param idx child index, negative value means last
* @return status of operation
*/
status_t add_child(Style *child, ssize_t idx = -1);
/** Remove child style
*
* @param child child style to remove
* @return status of operation
*/
status_t remove_child(Style *child);
/**
* Remove all parents
* @return status of operation
*/
status_t remove_all_children();
/**
* Check whether style has a child
* @param child child style
* @param recursive flag that indicates that a recursive search should be performed
* @return true if style has a child
*/
bool has_child(Style *child, bool recursive = false);
/**
* Set default parent styles of the class
* @param parents string with comma-separated list of default parent classes
* @return status of operation
*/
status_t set_default_parents(const char *parents);
status_t set_default_parents(const LSPString *parents);
public:
/**
* Bind listener to property
* @param id property identifier
* @return status of operation
*/
status_t bind(atom_t id, property_type_t type, IStyleListener *listener);
status_t bind(const char *id, property_type_t type, IStyleListener *listener);
status_t bind(const LSPString *id, property_type_t type, IStyleListener *listener);
/**
* Bind listener to integer property
* @param id property identifier
* @return status of operation
*/
inline status_t bind_int(atom_t id, IStyleListener *listener) { return bind(id, PT_INT, listener); }
inline status_t bind_int(const char *id, IStyleListener *listener) { return bind(id, PT_INT, listener); }
inline status_t bind_int(const LSPString *id, IStyleListener *listener) { return bind(id, PT_INT, listener); }
/**
* Bind listener to floating-point property
* @param id property identifier
* @return status of operation
*/
inline status_t bind_float(atom_t id, IStyleListener *listener) { return bind(id, PT_FLOAT, listener); }
inline status_t bind_float(const char *id, IStyleListener *listener) { return bind(id, PT_FLOAT, listener); }
inline status_t bind_float(const LSPString *id, IStyleListener *listener) { return bind(id, PT_FLOAT, listener); }
/**
* Bind listener to boolean property
* @param id property identifier
* @return status of operation
*/
inline status_t bind_bool(atom_t id, IStyleListener *listener) { return bind(id, PT_BOOL, listener); }
inline status_t bind_bool(const char *id, IStyleListener *listener) { return bind(id, PT_BOOL, listener); }
inline status_t bind_bool(const LSPString *id, IStyleListener *listener) { return bind(id, PT_BOOL, listener); }
/**
* Bind listener to string property
* @param id property identifier
* @return status of operation
*/
inline status_t bind_string(atom_t id, IStyleListener *listener) { return bind(id, PT_STRING, listener); }
inline status_t bind_string(const char *id, IStyleListener *listener) { return bind(id, PT_STRING, listener); }
inline status_t bind_string(const LSPString *id, IStyleListener *listener) { return bind(id, PT_STRING, listener); }
/**
* Check that listener is already bound to the property
* @param id property identifier
* @param listener listener
* @return true if listener is bound
*/
bool is_bound(atom_t id, IStyleListener *listener) const;
bool is_bound(const char *id, IStyleListener *listener) const;
bool is_bound(const LSPString *id, IStyleListener *listener) const;
/**
* Unbind listener from a property
* @param id property identifier
* @param listener property listener
* @return status of operation
*/
status_t unbind(atom_t id, IStyleListener *listener);
status_t unbind(const char *id, IStyleListener *listener);
status_t unbind(const LSPString *id, IStyleListener *listener);
public:
/**
* Return overall number of local properties
* @return overall number of local properties
*/
inline size_t properties() const { return vProperties.size(); }
/**
* Return overall number of property listener bindings
* @return overall number of listener bindings
*/
inline size_t listeners() const { return vListeners.size(); }
public:
/**
* Start transactional update of properties.
* All listeners and children will be notified
* only after transaction becomes completed
* @return status of operation
*/
status_t begin();
/**
* Start transactional update of properties.
* All listeners and children will be notified
* only after transaction becomes completed
* @param listener the listener excluded from notification
* @return status of operation
*/
status_t begin(IStyleListener *listener);
/**
* End transactional update of properties.
* All listeners and children will be notified
* @return status of operation
*/
status_t end();
/**
* Get integer property
* @param id property identifier
* @param dst pointer to store result
* @return status of operation
*/
status_t get_int(atom_t id, ssize_t *dst) const;
status_t get_int(const char *id, ssize_t *dst) const;
status_t get_int(const LSPString *id, ssize_t *dst) const;
/**
* Get floating-point property
* @param id property identifier
* @param dst pointer to store result
* @return status of operation
*/
status_t get_float(atom_t id, float *dst) const;
status_t get_float(const char *id, float *dst) const;
status_t get_float(const LSPString *id, float *dst) const;
/**
* Get boolean property
* @param id property identifier
* @param dst pointer to store result
* @return status of operation
*/
status_t get_bool(atom_t id, bool *dst) const;
status_t get_bool(const char *id, bool *dst) const;
status_t get_bool(const LSPString *id, bool *dst) const;
/**
* Get string property
* @param id property identifier
* @param dst pointer to store result
* @return status of operation
*/
status_t get_string(atom_t id, LSPString *dst) const;
status_t get_string(const char *id, LSPString *dst) const;
status_t get_string(const LSPString *id, LSPString *dst) const;
/**
* Get string property
* @param id property identifier
* @param dst pointer to store UTF-8 encoded result
* @return status of operation
*/
status_t get_string(atom_t id, const char **dst) const;
status_t get_string(const char *id, const char **dst) const;
status_t get_string(const LSPString *id, const char **dst) const;
/**
* Check whether property exists in the whole style tree
* @param id property identifier
* @return true if this style or parent styles contain such property
*/
bool exists(atom_t id) const;
bool exists(const char *id) const;
bool exists(const LSPString *id) const;
/**
* Check whether property has been locally overridden
* @param id property identifier
* @return true if property has been locally overridden
*/
bool is_overridden(atom_t id) const;
bool is_overridden(const char *id) const;
bool is_overridden(const LSPString *id) const;
/**
* Get property type for the whole style tree
* @param id property identifier
* @return actual property type or PT_UNKNOWN if property has not been found
*/
property_type_t get_type(atom_t id) const;
property_type_t get_type(const char *id) const;
property_type_t get_type(const LSPString *id) const;
/**
* Assign value to integer property
* @param id property identifier
* @param value the value to assign
* @return status of operation
*/
status_t set_int(atom_t id, ssize_t value);
status_t set_int(const char *id, ssize_t value);
status_t set_int(const LSPString *id, ssize_t value);
/**
* Assign value to floating-point property
* @param id property identifier
* @param value the value to assign
* @return status of operation
*/
status_t set_float(atom_t id, float value);
status_t set_float(const char *id, float value);
status_t set_float(const LSPString *id, float value);
/**
* Assign value to boolean property
* @param id property identifier
* @param value the value to assign
* @return status of operation
*/
status_t set_bool(atom_t id, bool value);
status_t set_bool(const char *id, bool value);
status_t set_bool(const LSPString *id, bool value);
/**
* Assign value to string property
* @param id property identifier
* @param value the value to assign
* @return status of operation
*/
status_t set_string(atom_t id, const LSPString *value);
status_t set_string(const char *id, const LSPString *value);
status_t set_string(const LSPString *id, const LSPString *value);
/**
* Assign value to string property
* @param id property identifier
* @param value the UTF-8 encoded value to assign
* @return status of operation
*/
status_t set_string(atom_t id, const char *value);
status_t set_string(const char *id, const char *value);
status_t set_string(const LSPString *id, const char *value);
/**
* Reset property to it's default value.
* If property is overridden by parent, it's value is taken.
* If property has no overrides, default value passed on create()
* is taken. Otherwise 0/0.0f/false/empty string will be assigned.
*
* @param id property identifier
* @return status of operation
*/
status_t set_default(atom_t id);
status_t set_default(const char *id);
status_t set_default(const LSPString *id);
/**
* Remove locally-created property
* @param id property identifier
* @return status of operation
*/
status_t remove(atom_t id);
status_t remove(const char *id);
status_t remove(const LSPString *id);
/**
* Get atom identifier by name
* @param name atom name
* @return atom identifier or negative error code
*/
atom_t atom_id(const char *name) const;
/**
* Get atom identifier by name
* @param name atom name
* @return atom identifier or negative error code
*/
atom_t atom_id(const LSPString *name) const;
/**
* Get atom name by identifier
* @param name atom name or NULL
* @return atom identifier
*/
const char *atom_name(atom_t id) const;
};
#define LSP_TK_STYLE_DEF_BEGIN(Name, Parent) \
class Name : public Parent \
{ \
public: \
explicit Name(::lsp::tk::Schema *schema, const char *name, const char *parents); \
Name(const Name &) = delete; \
Name(Name &&) = delete; \
Name & operator = (const Name &) = delete; \
Name & operator = (Name &&) = delete; \
\
public: \
virtual ::lsp::status_t init(); \
\
protected:
#define LSP_TK_STYLE_DEF_END \
}; \
#define LSP_TK_STYLE_IMPL_BEGIN(Name, Parent) \
Name::Name(::lsp::tk::Schema *schema, const char *name, const char *parents): Parent(schema, name, parents) {} \
\
status_t Name::init() \
{ \
::lsp::status_t res = Parent::init(); \
if (res != ::lsp::STATUS_OK) \
return res;
#define LSP_TK_STYLE_IMPL_END \
return res; \
} \
} /* namespace tk */
} /* namespace lsp */
#endif /* LSP_PLUG_IN_TK_STYLE_STYLE_H_ */
|