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: 15 июн. 2017 г. 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_LSPWIDGET_H_ 23 #define UI_TK_LSPWIDGET_H_ 24 25 namespace lsp 26 { 27 namespace tk 28 { 29 class LSPComplexWidget; 30 31 /** Basic widget class for any widget in the toolkit 32 * 33 */ 34 class LSPWidget: public ws::IEventHandler 35 { 36 public: 37 static const w_class_t metadata; 38 39 protected: 40 enum flags_t 41 { 42 REDRAW_SURFACE = 1 << 0, // Need to redraw surface 43 REDRAW_CHILD = 1 << 1, // Need to redraw child only 44 F_VISIBLE = 1 << 2, // Widget is visible 45 F_REALIZED = 1 << 3, // Widget is realized 46 F_EXPAND = 1 << 4, // Area for the widget should be expanded 47 F_HFILL = 1 << 5, // Widget should desirable fill all the provided area horizontally 48 F_VFILL = 1 << 6, // Widget should desirable fill all the provided area vertically 49 }; 50 51 protected: 52 char *pUID; // Unique widget identifier 53 54 LSPDisplay *pDisplay; 55 ISurface *pSurface; 56 57 LSPComplexWidget *pParent; 58 const w_class_t *pClass; 59 60 realize_t sSize; // Geometry 61 size_t nFlags; // Flags 62 mouse_pointer_t enCursor; 63 64 LSPSlotSet sSlots; // Slots 65 LSPPadding sPadding; 66 67 LSPColor sBgColor; // Widget color 68 LSPFloat sBrightness; // Brightness 69 LSPStyle sStyle; // Style 70 71 //--------------------------------------------------------------------------------- 72 // Slot handlers 73 protected: 74 static status_t slot_mouse_move(LSPWidget *sender, void *ptr, void *data); 75 static status_t slot_mouse_down(LSPWidget *sender, void *ptr, void *data); 76 static status_t slot_mouse_up(LSPWidget *sender, void *ptr, void *data); 77 static status_t slot_mouse_dbl_click(LSPWidget *sender, void *ptr, void *data); 78 static status_t slot_mouse_tri_click(LSPWidget *sender, void *ptr, void *data); 79 static status_t slot_mouse_scroll(LSPWidget *sender, void *ptr, void *data); 80 static status_t slot_mouse_in(LSPWidget *sender, void *ptr, void *data); 81 static status_t slot_mouse_out(LSPWidget *sender, void *ptr, void *data); 82 static status_t slot_key_down(LSPWidget *sender, void *ptr, void *data); 83 static status_t slot_key_up(LSPWidget *sender, void *ptr, void *data); 84 static status_t slot_hide(LSPWidget *sender, void *ptr, void *data); 85 static status_t slot_show(LSPWidget *sender, void *ptr, void *data); 86 static status_t slot_destroy(LSPWidget *sender, void *ptr, void *data); 87 static status_t slot_resize(LSPWidget *sender, void *ptr, void *data); 88 static status_t slot_resize_parent(LSPWidget *sender, void *ptr, void *data); 89 static status_t slot_focus_in(LSPWidget *sender, void *ptr, void *data); 90 static status_t slot_focus_out(LSPWidget *sender, void *ptr, void *data); 91 static status_t slot_drag_request(LSPWidget *sender, void *ptr, void *data); 92 93 //--------------------------------------------------------------------------------- 94 // Interface for nested classes 95 protected: 96 void do_destroy(); 97 98 void unlink_widget(LSPWidget *widget); 99 100 void init_color(color_t value, LSPColor *color); 101 102 //--------------------------------------------------------------------------------- 103 // Construction and destruction 104 public: 105 explicit LSPWidget(LSPDisplay *dpy); 106 virtual ~LSPWidget(); 107 108 /** Initialize wiget 109 * 110 */ 111 virtual status_t init(); 112 113 /** Destroy widget 114 * 115 */ 116 virtual void destroy(); 117 118 //--------------------------------------------------------------------------------- 119 // Metadata, casting and type information 120 public: 121 /** Get widget class 122 * 123 * @return actual widget class metadata 124 */ get_class()125 inline const w_class_t *get_class() const { return pClass; } 126 127 /** Check wheter the widget is instance of some class 128 * 129 * @param wclass widget class 130 * @return true if widget is instance of some class 131 */ 132 bool instance_of(const w_class_t *wclass) const; 133 instance_of(const w_class_t & wclass)134 inline bool instance_of(const w_class_t &wclass) const { return instance_of(&wclass); } 135 136 /** Another way to check if widget is instance of some class 137 * 138 * @return true if widget is instance of some class 139 */ 140 template <class LSPTarget> instance_of()141 inline bool instance_of() const { return instance_of(&LSPTarget::metadata); }; 142 143 /** Cast widget to another type 144 * 145 * @return pointer to widget or NULL if cast failed 146 */ 147 template <class LSPTarget> cast()148 inline LSPTarget *cast() { return instance_of(&LSPTarget::metadata) ? static_cast<LSPTarget *>(this) : NULL; } 149 150 /** Cast widget to another type 151 * 152 * @return pointer to widget or NULL if cast failed 153 */ 154 template <class LSPTarget> cast()155 inline const LSPTarget *cast() const { return instance_of(&LSPTarget::metadata) ? static_cast<const LSPTarget *>(this) : NULL; } 156 157 /** Get pointer to self as pointer to LSPWidget class 158 * 159 * @return pointer to self 160 */ self()161 inline LSPWidget *self() { return this; } 162 163 //--------------------------------------------------------------------------------- 164 // Properties 165 public: 166 /** Get display 167 * 168 * @return display 169 */ display()170 inline LSPDisplay *display() { return pDisplay; }; 171 172 /** Get horizontal coordinate of the left top corner 173 * 174 * @return coordinate of the left corner 175 */ left()176 inline ssize_t left() const { return sSize.nLeft; }; 177 178 /** Get horizontal coordinate of the right bottom corner 179 * 180 * @return value 181 */ right()182 inline ssize_t right() const { return sSize.nLeft + sSize.nWidth; }; 183 184 /** Get vertical coordinate of the left top corner 185 * 186 * @return value 187 */ top()188 inline ssize_t top() const { return sSize.nTop; }; 189 190 /** Get vertical coordinate of the right bottom corner 191 * 192 * @return value 193 */ bottom()194 inline ssize_t bottom() const { return sSize.nTop + sSize.nHeight; }; 195 196 /** Get width of the widget 197 * 198 * @return width of the widget 199 */ width()200 inline ssize_t width() const { return sSize.nWidth; }; 201 202 /** Get height of the widget 203 * 204 * @return height of the widget 205 */ height()206 inline ssize_t height() const { return sSize.nHeight; }; 207 208 /** Get widget dimensions 209 * 210 * @param r real widget dimensions 211 */ get_dimensions(realize_t * r)212 inline void get_dimensions(realize_t *r) { *r = sSize; } 213 214 /** Check if there is redraw request pending 215 * 216 * @return true if there is redraw request pending 217 */ redraw_pending()218 inline bool redraw_pending() const { return nFlags & (REDRAW_SURFACE | REDRAW_CHILD); }; 219 220 /** Check that widget is visible 221 * 222 * @return true if widget is visible 223 */ visible()224 inline bool visible() const { return nFlags & F_VISIBLE; }; 225 226 /** Check that widget is hidden 227 * 228 * @return true if widget is visible 229 */ hidden()230 inline bool hidden() const { return !(nFlags & F_VISIBLE); }; invisible()231 inline bool invisible() const { return !(nFlags & F_VISIBLE); }; 232 233 /** Get expanding flag: true if container should desirable expand area provided for the widget 234 * 235 * @return expanding flag 236 */ expand()237 inline bool expand() const { return nFlags & F_EXPAND; } 238 239 /** Get fill flag: true if container should desirable fill all provided area with widget 240 * 241 * @return fill flag 242 */ fill()243 inline bool fill() const { return (nFlags & (F_HFILL | F_VFILL)) == (F_HFILL | F_VFILL); } 244 245 /** Get horizontal fill flag: true if container should horizontally fill all provided area with widget 246 * 247 * @return horizontal fill flag 248 */ hfill()249 inline bool hfill() const { return nFlags & F_HFILL; } 250 251 /** Get vertical fill flag: true if container should vertically fill all provided area with widget 252 * 253 * @return vertical fill flag 254 */ vfill()255 inline bool vfill() const { return nFlags & F_VFILL; } 256 257 /** Check that widget has focus 258 * 259 * @return widget focus 260 */ 261 virtual bool has_focus() const; 262 263 /** Check that widget has focus 264 * 265 * @return widget focus 266 */ focused()267 inline bool focused() const { return has_focus(); }; 268 269 /** Check that widget is visible 270 * 271 * @return true if widget is visible 272 */ is_visible()273 inline bool is_visible() const { return nFlags & F_VISIBLE; }; 274 275 /** Check that widget is realized 276 * 277 * @return true if widget is realized 278 */ is_realized()279 inline bool is_realized() const { return nFlags & F_REALIZED; }; 280 281 /** Get horizontal coordinate of the left top corner relative to the parent widget 282 * 283 * @return the value 284 */ 285 ssize_t relative_left() const; 286 287 /** Get horizontal coordinate of the right bottom corner relative to the parent widget 288 * 289 * @return the value 290 */ 291 ssize_t relative_right() const; 292 293 /** Get vertical coordinate of the left top corner relative to the parent widget 294 * 295 * @return the value 296 */ 297 ssize_t relative_top() const; 298 299 /** Get vertical coordinate of the right bottom corner relative to the parent widget 300 * 301 * @return the value 302 */ 303 ssize_t relative_bottom() const; 304 305 /** 306 * Get unique widget identifier for DOM search 307 * @return unique widget identifier for DOM search 308 */ unique_id()309 inline const char *unique_id() const { return pUID; } 310 311 /** Check that specified window coordinate lies within widget's bounds 312 * Always returns false for invisible widgets 313 * 314 * @param x x coordinate 315 * @param y y coordinate 316 * @return true on success 317 */ 318 virtual bool inside(ssize_t x, ssize_t y); 319 320 /** Get parent widget 321 * 322 * @return parent widget 323 */ parent()324 inline LSPComplexWidget *parent() { return pParent; } 325 326 /** Get slots 327 * 328 * @return slots 329 */ slots()330 inline LSPSlotSet *slots() { return &sSlots; } 331 332 /** Get slot 333 * 334 * @param id slot identifier 335 * @return pointer to slot or NULL 336 */ slot(ui_slot_t id)337 inline LSPSlot *slot(ui_slot_t id) { return sSlots.slot(id); } 338 339 /** Get mouse pointer 340 * 341 * @return mouse pointer 342 */ cursor()343 inline mouse_pointer_t cursor() const { return enCursor; } 344 345 /** Get active curstor 346 * 347 * @return active cursor 348 */ 349 virtual mouse_pointer_t active_cursor() const; 350 351 /** Get widget padding 352 * 353 * @return widget padding 354 */ padding()355 inline LSPPadding *padding() { return &sPadding; }; 356 357 /** 358 * Get background color of the widget 359 * @return background color of the widget 360 */ bg_color()361 inline LSPColor *bg_color() { return &sBgColor; } 362 363 /** 364 * Return widget's style 365 * @return widget's style 366 */ style()367 inline LSPStyle *style() { return &sStyle; } 368 369 /** 370 * Get brightness 371 * @return brightness 372 */ brightness()373 inline float brightness() const { return sBrightness.get(); } 374 375 //--------------------------------------------------------------------------------- 376 // Manipulation 377 public: 378 /** 379 * Set unique widget identifier for DOM search 380 * @param uid unique widget identifier for DOM search 381 * @return status of operation 382 */ 383 status_t set_unique_id(const char *uid); 384 385 /** Query widget for redraw 386 * 387 * @param flags redraw flags 388 */ 389 virtual void query_draw(size_t flags = REDRAW_SURFACE); 390 391 /** 392 * Put the widget to the destroy queue of the main loop 393 * @return status of operation 394 */ 395 virtual status_t queue_destroy(); 396 397 /** Query widget for resize 398 * 399 */ 400 virtual void query_resize(); 401 402 /** Set expanding flag 403 * 404 * @param value expanding flag value 405 */ 406 virtual void set_expand(bool value = true); 407 408 /** Set fill flag 409 * 410 * @param value filling flag value 411 */ 412 virtual void set_fill(bool value = true); 413 414 /** Set horizontal fill flag 415 * 416 * @param value horizontal filling flag value 417 */ 418 virtual void set_hfill(bool value = true); 419 420 /** Set vertical fill flag 421 * 422 * @param value vertical filling flag value 423 */ 424 virtual void set_vfill(bool value = true); 425 426 /** 427 * Set brightness of the widget 428 * @param brightness brightness 429 * @return previous value 430 */ set_brightness(float brightness)431 inline float set_brightness(float brightness) { return sBrightness.set(brightness); } 432 433 /** Set mouse pointer 434 * 435 * @param mp mouse pointer 436 * @return mouse pointer 437 */ 438 virtual status_t set_cursor(mouse_pointer_t mp); 439 440 /** Get widget surface 441 * 442 * @param s base surface 443 * @return widget surface or NULL 444 */ 445 ISurface *get_surface(ISurface *s); 446 447 /** Get widget surface 448 * 449 * @param s base surface 450 * @param width requested width 451 * @param height requested height 452 * @return widget surface or NULL 453 */ 454 ISurface *get_surface(ISurface *s, ssize_t width, ssize_t height); 455 456 /** Render widget to the external surface 457 * 458 * @param surface surface to perform rendering 459 * @param force force child rendering 460 */ 461 virtual void render(ISurface *s, bool force); 462 463 /** Draw widget on the internal surface 464 * 465 * @param surface surface to perform drawing 466 */ 467 virtual void draw(ISurface *s); 468 469 /** Realize widget 470 * 471 * @param r widget realization parameters 472 */ 473 virtual void realize(const realize_t *r); 474 475 /** Request for size 476 * 477 * @param r minimum and maximum dimensions of the widget 478 */ 479 virtual void size_request(size_request_t *r); 480 481 /** Hide widget 482 * 483 */ 484 virtual bool hide(); 485 486 /** Show widget 487 * 488 */ 489 virtual bool show(); 490 491 /** Set widget visibility 492 * 493 * @param visible widget visibility 494 */ 495 virtual void set_visible(bool visible=true); 496 497 /** Set focus on widget 498 * 499 * @param focus focusing parameter 500 * @return status of operation 501 */ 502 virtual status_t set_focus(bool focus = true); 503 504 /** Kill focus on widget 505 * 506 * @return status of operation 507 */ kill_focus()508 inline status_t kill_focus() { return set_focus(false); }; 509 510 /** Kill focus on widget 511 * 512 * @return status of operation 513 */ take_focus()514 inline status_t take_focus() { return set_focus(true); }; 515 516 /** Mark this widget to be currently pointed by mouse 517 * 518 * @return status of operation 519 */ 520 status_t mark_pointed(); 521 522 /** Invert focus 523 * 524 * @return status of operation 525 */ 526 virtual status_t toggle_focus(); 527 528 /** Set widget invisibility 529 * 530 * @param invisible widget invisibility 531 */ 532 inline void set_invisible(bool invisible=true) { set_visible(!invisible); } 533 534 /** Handle UI event from the display 535 * 536 * @param e UI event 537 * @return status of operation 538 */ 539 virtual status_t handle_event(const ws_event_t *e); 540 541 /** Set parent widget of this widget 542 * 543 * @param parent parent widget 544 */ 545 void set_parent(LSPComplexWidget *parent); 546 547 /** Commit widet redraw 548 * 549 */ 550 virtual void commit_redraw(); 551 552 /** Get most top-level widget 553 * 554 * @return most top-level widget 555 */ 556 LSPWidget *toplevel(); 557 558 //--------------------------------------------------------------------------------- 559 // Event handling 560 public: 561 /** Widget has taken focus 562 * 563 * @param e event 564 * @return status of operation 565 */ 566 virtual status_t on_focus_in(const ws_event_t *e); 567 568 /** Widget has lost focus 569 * 570 * @param e event 571 * @return status of operation 572 */ 573 virtual status_t on_focus_out(const ws_event_t *e); 574 575 /** Handle key press event 576 * @param e event 577 * @return status of operation 578 */ 579 virtual status_t on_key_down(const ws_event_t *e); 580 581 /** Handle key release event 582 * @param e event 583 * @return status of operation 584 */ 585 virtual status_t on_key_up(const ws_event_t *e); 586 587 /** Handle mouse button press event 588 * @param e event 589 * @return status of operation 590 */ 591 virtual status_t on_mouse_down(const ws_event_t *e); 592 593 /** Handle mouse button release event 594 * @param e event 595 * @return status of operation 596 */ 597 virtual status_t on_mouse_up(const ws_event_t *e); 598 599 /** Handle mouse motion event 600 * @param e event 601 * @return status of operation 602 */ 603 virtual status_t on_mouse_move(const ws_event_t *e); 604 605 /** Handle mouse cursor moved into the zone of widget 606 * 607 * @param e mouse event that triggered MouseIn 608 * @return status of operation 609 */ 610 virtual status_t on_mouse_in(const ws_event_t *e); 611 612 /** Handle mouse cursor moved outside the zone of widget 613 * 614 * @param e mouse event that triggered MouseIn 615 * @return status of operation 616 */ 617 virtual status_t on_mouse_out(const ws_event_t *e); 618 619 /** Handle mouse scroll event 620 * 621 * @param e event 622 * @return status of operation 623 */ 624 virtual status_t on_mouse_scroll(const ws_event_t *e); 625 626 /** Handle mouse double click event 627 * 628 * @param e event 629 * @return status of operation 630 */ 631 virtual status_t on_mouse_dbl_click(const ws_event_t *e); 632 633 /** Handle mouse triple click 634 * 635 * @param e event 636 * @return status of operation 637 */ 638 virtual status_t on_mouse_tri_click(const ws_event_t *e); 639 640 /** Geometry has changed: size or position 641 * 642 * @param e event 643 * @return status of operation 644 */ 645 virtual status_t on_resize(const realize_t *r); 646 647 /** Geometry of parent widget has changed: size or position 648 * 649 * @param e event 650 * @return status of operation 651 */ 652 virtual status_t on_resize_parent(const realize_t *r); 653 654 /** The widget becomes hidden 655 * 656 * @return status of operation 657 */ 658 virtual status_t on_hide(); 659 660 /** The widget becomes visible 661 * 662 * @return status of operation 663 */ 664 virtual status_t on_show(); 665 666 /** The widget becomes destroyed 667 * 668 * @return status of operation 669 */ 670 virtual status_t on_destroy(); 671 672 /** 673 * Process the drag request event 674 * @param e drag request event 675 * @param ctype NULL-terminated list of provided content types 676 * @return status of operation 677 */ 678 virtual status_t on_drag_request(const ws_event_t *e, const char * const *ctype); 679 }; 680 681 template <class LSPTarget> widget_cast(LSPWidget * src)682 inline LSPTarget *widget_cast(LSPWidget *src) 683 { 684 return ((src != NULL) && (src->instance_of(&LSPTarget::metadata))) ? static_cast<LSPTarget *>(src) : NULL; 685 } 686 687 template <class LSPTarget> widget_cast(const LSPWidget * src)688 inline const LSPTarget *widget_cast(const LSPWidget *src) 689 { 690 return ((src != NULL) && (src->instance_of(&LSPTarget::metadata))) ? static_cast<const LSPTarget *>(src) : NULL; 691 } 692 693 template <class LSPTarget> widget_ptrcast(void * src)694 inline LSPTarget *widget_ptrcast(void *src) 695 { 696 LSPWidget *w = (src != NULL) ? static_cast<LSPWidget *>(src) : NULL; 697 return ((w != NULL) && (w->instance_of(&LSPTarget::metadata))) ? static_cast<LSPTarget *>(w) : NULL; 698 } 699 700 template <class LSPTarget> widget_ptrcast(const void * src)701 inline const LSPTarget *widget_ptrcast(const void *src) 702 { 703 const LSPWidget *w = (src != NULL) ? static_cast<const LSPWidget *>(src) : NULL; 704 return ((w != NULL) && (w->instance_of(&LSPTarget::metadata))) ? static_cast<const LSPTarget *>(w) : NULL; 705 } 706 } 707 708 } /* namespace lsp */ 709 710 #endif /* UI_TK_LSPWIDGET_H_ */ 711