/gui/window.d
D | 1068 lines | 643 code | 228 blank | 197 comment | 129 complexity | b3a55e775f35bc0cb0e3154e8e05db21 MD5 | raw file
1/* 2 * window.d 3 * 4 * This module implements a GUI Window class. Widgets can be pushed to this window. 5 * 6 * Author: Dave Wilkinson 7 * Originated: June 24th, 2009 8 * 9 */ 10 11module gui.window; 12 13import gui.widget; 14import gui.application; 15 16import resource.menu; 17 18import platform.vars.view; 19import platform.vars.menu; 20import platform.vars.window; 21 22import scaffold.color; 23import scaffold.window; 24import scaffold.view; 25import scaffold.menu; 26 27import graphics.view; 28import graphics.graphics; 29 30import core.definitions; 31import core.color; 32import core.string; 33import core.event; 34import core.main; 35import core.system; 36 37import interfaces.container; 38 39import binding.c; 40 41// Description: This class implements and abstracts a common window. This window is a control container and a view canvas. 42class Window : Responder, AbstractContainer { 43public: 44 45 // Constructors 46 47 // Description: Will create the window with certain default parameters 48 // windowTitle: The initial title for the window. 49 // windowStyle: The initial style for the window. 50 // color: The initial color for the window. 51 // x: The initial x position of the window. 52 // y: The initial y position of the window. 53 // width: The initial width of the client area of the window. 54 // height: The initial height of the client area of the window. 55 this(string windowTitle, WindowStyle windowStyle, Color color, int x, int y, int width, int height) { 56 _color = color; 57 _window_title = windowTitle.dup; 58 _width = width; 59 _height = height; 60 _x = x; 61 _y = y; 62 _style = windowStyle; 63 _position = WindowPosition.User; 64 } 65 66 // Description: Will create the window with certain default parameters 67 // windowTitle: The initial title for the window. 68 // windowStyle: The initial style for the window. 69 // sysColor: The initial color for the window which is taken from a platform color setting. 70 // x: The initial x position of the window. 71 // y: The initial y position of the window. 72 // width: The initial width of the client area of the window. 73 // height: The initial height of the client area of the window. 74 this(string windowTitle, WindowStyle windowStyle, SystemColor sysColor, int x, int y, int width, int height) { 75 ColorGetSystemColor(_color, sysColor); 76 _window_title = windowTitle.dup; 77 _width = width; 78 _height = height; 79 _x = x; 80 _y = y; 81 _style = windowStyle; 82 _position = WindowPosition.User; 83 } 84 85 this(string windowTitle, WindowStyle windowStyle, Color color, WindowPosition pos, int width, int height) { 86 _color = color; 87 _window_title = windowTitle.dup; 88 _width = width; 89 _height = height; 90 _position = pos; 91 _style = windowStyle; 92 } 93 94 this(string windowTitle, WindowStyle windowStyle, SystemColor sysColor, WindowPosition pos, int width, int height) { 95 ColorGetSystemColor(_color, sysColor); 96 _window_title = windowTitle.dup; 97 _width = width; 98 _height = height; 99 _position = pos; 100 _style = windowStyle; 101 } 102 103 ~this() { 104 uninitialize(); 105 remove(); 106 } 107 108 // Properties 109 110 // Widget Container Margins 111 112 int baseLeft() { 113 return 0; 114 } 115 116 int baseTop() { 117 return 0; 118 } 119 120 121 // Methods // 122 123 // Description: Will get the title of the window. 124 // Returns: The string representing the title. 125 string text() { 126 return _window_title.dup; 127 } 128 129 // Description: Will set the title of the window. 130 // str: The new title. 131 void text(string str) { 132 _window_title = str.dup; 133 134 if (!_inited) { return; } 135 WindowSetTitle(this, &_pfvars); 136 } 137 138 Window nextWindow() { 139 return _nextWindow; 140 } 141 142 // Description: Sets the flag to make the window hidden or visible. 143 // bShow: Pass true to show the window and false to hide it. 144 void visible(bool bShow) { 145 if (_visible == bShow) { return; } 146 147 _visible = !_visible; 148 149 if (_inited) { 150 GuiApplication app = cast(GuiApplication)responder; 151 if (!_visible) { 152 app._windowVisibleCount--; 153 } 154 else { 155 app._windowVisibleCount++; 156 } 157 158 WindowSetVisible(this, &_pfvars, bShow); 159 160 // safe guard: 161 // fights off infection from ZOMBIE PROCESSES!!! 162 if (app.isZombie()) { 163 app.destroyAllWindows(); 164 app.exit(0); 165 } 166 } 167 168 onVisibilityChange(); 169 } 170 171 // Description: Will return whether or not the window is flagged as hidden or visible. The window may not actually be visible due to it not being created or added. 172 // Returns: It will return true when the window is flagged to be visible and false otherwise. 173 bool visible() { 174 return _visible; 175 } 176 177 // Description: Will set the window to take a different state: WindowState.Minimized, WindowState.Maximized, WindowState.Fullscreen, WindowState.Normal 178 // state: A WindowState value representing the new state. 179 void state(WindowState state) { 180 if (_state == state) { return; } 181 182 _state = state; 183 184 if (_nextWindow !is null) { 185 WindowSetState(this, &_pfvars); 186 } 187 188 onStateChange(); 189 } 190 191 // Description: Will return the current state of the window. 192 // Returns: The current WindowState value for the window. 193 WindowState state() { 194 return _state; 195 } 196 197 // Description: Will set the window to take a different style: WindowStyle.Fixed (non-sizable), WindowStyle.Sizable (resizable window), WindowStyle.Popup (borderless). 198 // style: A WindowStyle value representing the new style. 199 void style(WindowStyle style) { 200 if (this.state == WindowState.Fullscreen) 201 { return; } 202 203 _style = style; 204 205 if (_nextWindow !is null) { 206 WindowSetStyle(this, &_pfvars); 207 } 208 } 209 210 // Description: Will return the current style of the window. 211 // Returns: The current WindowStyle value for the window. 212 WindowStyle style() { 213 return _style; 214 } 215 216 // Description: Will return the width of the client area of the window. 217 // Returns: The width of the client area of the window. 218 uint width() { 219 if (_state == WindowState.Fullscreen) { 220 return System.Display.width; 221 } 222 return _width; 223 } 224 225 // Description: Will return the height of the client area of the window. 226 // Returns: The height of the client area of the window. 227 uint height() { 228 if (_state == WindowState.Fullscreen) { 229 return System.Display.height; 230 } 231 return _height; 232 } 233 234 // Description: Will return the x coordinate of the window's position in screen coordinates. Note that this is not the client area, but rather the whole window. 235 // Returns: The x position of the top-left corner of the window. 236 uint x() { 237 if (_state == WindowState.Fullscreen) { 238 return 0; 239 } 240 return _x; 241 } 242 243 // Description: Will return the y coordinate of the window's position in screen coordinates. Note that this is not the client area, but rather the whole window. 244 // Returns: The y position of the top-left corner of the window. 245 uint y() { 246 if (_state == WindowState.Fullscreen) { 247 return 0; 248 } 249 return _y; 250 } 251 252 // Methods 253 254 // Description: Will attempt to destroy the window and its children. It will be removed from the hierarchy. 255 void remove() { 256 if (!_inited) { return; } 257 258 // the window was added 259 // destroy 260 261 // TODO: Fire the event, and allow confirmation 262 // TODO: Add a FORCE DESTROY function method 263 264 _inited = false; 265 266 WindowDestroy(this, &_pfvars); 267 } 268 269 // Description: This function will Size the window to fit a client area with the dimensions given by width and height. 270 // width: The new width of the client area. 271 // height: The new height of the client area. 272 void resize(uint width, uint height) { 273 _width = width; 274 _height = height; 275 276 if (_inited) { 277 WindowRebound(this, &_pfvars); 278 } 279 280 onResize(); 281 } 282 283 // Description: This function will move the window so that the top-left corner of the window (not client area) is set to the point (x,y). 284 // x: The new x coordinate of the top-left corner. 285 // y: The new y coordinate of the top-left corner. 286 void move(uint x, uint y) { 287 _x = x; 288 _y = y; 289 290 if (_inited) { 291 WindowReposition(this, &_pfvars); 292 } 293 294 onMove(); 295 } 296 297 void ClientToScreen(ref int x, ref int y) { 298 if (_inited == false) { return; } 299 WindowClientToScreen(this, &_pfvars, x, y); 300 } 301 302 void ClientToScreen(ref Coord pt) { 303 if (_inited == false) { return; } 304 WindowClientToScreen(this, &_pfvars, pt); 305 } 306 307 void ClientToScreen(ref Rect rt) { 308 if (_inited == false) { return; } 309 WindowClientToScreen(this, &_pfvars, rt); 310 } 311 312 Window parent() { 313 return _parent; 314 } 315 316 // add a child window to this window 317 318 void addWindow(Window window) { 319 /* 320 if (_inited == false) { return; } 321 322 // add the window to the root window list 323 UpdateWindowList(window); 324 325 // mark the parent 326 window._parent = this; 327 328 UpdateChildWindowList(window); 329 330 // add one to the window count 331 ApplicationPlusWindow(cast(GuiApplication)Djehuty.app); 332 333 // add one to the child window count 334 _numChildren++; 335 336 // create the window via platform calls 337 WindowCreate(this, &this._pfvars, window, window._pfvars); 338 339 // create the window's view object 340 window.onInitialize(); 341 342 // call the onAdd event of the new window 343 window.onAdd();*/ 344 345 //PrintChildWindowList(this); 346 } 347 348 // Events // 349 350 // Description: This event will be called when the window is added to the window hierarchy. 351 void onAdd() { 352 } 353 354 // Description: This event will be called when the window is removed from the window hierarchy. 355 void onRemove() { 356 } 357 358 // Description: This event is called when the mouse wheel is scrolled vertically (the common scroll method). 359 // amount: the number of standard 'ticks' that the scroll wheel makes 360 void onMouseWheelY(uint amount) { 361 } 362 363 // Description: This event is called when the mouse wheel is scrolled horizontally. 364 // amount: the number of standard 'ticks' that the scroll wheel makes 365 void onMouseWheelX(uint amount) { 366 } 367 368 // Description: This event is called when the mouse enters the client area of the window 369 void onMouseEnter() { 370 } 371 372 // Description: This event is called when the window is moved, either from the OS or the move() function. 373 void onMove() { 374 } 375 376 // Description: This event is called when the window is hidden or shown. 377 void onVisibilityChange() { 378 } 379 380 // Description: This event is called when the window is maximized, minimized, put into fullscreen, or restored. 381 void onStateChange() { 382 } 383 384 // Description: This event is called when a menu item belonging to the window is activated. 385 // mnu: A reference to the menu that was activated. 386 void onMenu(Menu mnu) { 387 } 388 389 void onInitialize() { 390 _view = new WindowView; 391 _viewVars = _view.createForWindow(this, &_pfvars); 392 } 393 394 void onUninitialize() { 395 _view.destroy(); 396 _view = null; 397 } 398 399 void onDraw() { 400 if (_view !is null) { 401 Graphics g = _view.lock(); 402 403 WindowStartDraw(this, &_pfvars, _view, *_viewVars); 404 405 Brush brush = new Brush(this.color); 406 Pen pen = new Pen(Color.Black); 407 408 g.brush = brush; 409 g.pen = pen; 410 411 g.fillRect(0,0,this.width,this.height); 412 413 brush = new Brush(Color.White); 414 g.brush = brush; 415 416 Widget c = _firstControl; 417 418 if (c !is null) { 419 do { 420 c = c._prevControl; 421 422 c.onDraw(g); 423 } while (c !is _firstControl) 424 } 425 426 WindowEndDraw(this, &_pfvars, _view, *_viewVars); 427 428 _view.unlock(); 429 } 430 } 431 432 void onKeyChar(dchar keyChar) { 433 // dispatch to focused control 434 if (_focused_control !is null) { 435 if (_focused_control.onKeyChar(keyChar)) { 436 onDraw(); 437 } 438 } 439 } 440 441 void onKeyDown(Key key) { 442 // dispatch to focused control 443 if (_focused_control !is null) { 444 if (_focused_control.onKeyDown(key)) { 445 onDraw(); 446 } 447 } 448 } 449 450 void onKeyUp(Key key) { 451 // dispatch to focused control 452 if (_focused_control !is null) { 453 if (_focused_control.onKeyUp(key)) { 454 onDraw(); 455 } 456 } 457 } 458 459 void onMouseLeave() { 460 if (_last_control !is null) { 461 _last_control._hovered = false; 462 if(_last_control.onMouseLeave()) { 463 onDraw(); 464 } 465 _last_control = null; 466 } 467 } 468 469 void onMouseMove() { 470 //select the control to send the message to 471 Widget control; 472 473 if (_captured_control !is null) { 474 control = _captured_control; 475 476 if (controlAtPoint(mouseProps.x, mouseProps.y) is control && control.visible) { 477 //within bounds of control 478 if (!control._hovered) { 479 //currently, hover state says control is outside 480 control._hovered = true; 481 if (control.onMouseEnter() | control.onMouseMove(mouseProps)) { 482 onDraw(); 483 } 484 } 485 else if (control.onMouseMove(mouseProps)) { 486 onDraw(); 487 } 488 } 489 else { 490 //outside bounds of control 491 if (control._hovered) { 492 //currently, hover state says control is inside 493 control._hovered = false; 494 if (control.onMouseLeave() | control.onMouseMove(mouseProps)) { 495 onDraw(); 496 } 497 } 498 else if (control.onMouseMove(mouseProps)) { 499 onDraw(); 500 } 501 } 502 503 //change the cursor to reflect the new control 504 //ChangeCursor(window->captured_control->ctrl_info.ctrl_cursor); 505 506 507 } // no control that has captured the mouse input 508 else if ((control = controlAtPoint(mouseProps.x, mouseProps.y)) !is null) { 509 //when there is a control to pass a MouseLeave to... 510 if (_last_control !is control && _last_control !is null) { 511 control._hovered = true; 512 _last_control._hovered = false; 513 514 if(_last_control.onMouseLeave() | 515 control.onMouseEnter() | control.onMouseMove(mouseProps)) { 516 onDraw(); 517 } 518 } //otherwise, there is just one control to worry about 519 else { 520 if(!control._hovered) { 521 //wasn't hovered over before 522 control._hovered = true; 523 if(control.onMouseEnter() | control.onMouseMove(mouseProps)) { 524 onDraw(); 525 } 526 } 527 else if(control.onMouseMove(mouseProps)) { 528 onDraw(); 529 } 530 } 531 532 //change the cursor to reflect the new control 533 //ChangeCursor(index->ctrl_cursor); 534 535 _last_control = control; 536 537 } 538 else { 539 //mouse is on window, not control 540 541 if (_last_control !is null) { 542 _last_control._hovered = false; 543 if(_last_control.onMouseLeave()) { 544 onDraw(); 545 } 546 _last_control = null; 547 } 548 } 549 } 550 551 // Description: Called when the primary mouse button (usually the left button) is pressed. 552 void onPrimaryMouseDown() { 553 Widget target; 554 bool ret = mouseEventCommon(target); 555 556 _captured_control = target; 557 558 if((target !is null) && (ret | target.onPrimaryMouseDown(mouseProps))) { 559 onDraw(); 560 } 561 } 562 563 // Description: Called when the primary mouse button (usually the left button) is released. 564 void onPrimaryMouseUp() { 565 Widget target; 566 bool ret = mouseEventCommon(target); 567 568 _captured_control = null; 569 570 if((target !is null) && (ret | target.onPrimaryMouseUp(mouseProps))) { 571 onDraw(); 572 } 573 } 574 575 // Description: Called when the secondary mouse button (usually the right button) is pressed. 576 void onSecondaryMouseDown() { 577 Widget target; 578 bool ret = mouseEventCommon(target); 579 580 _captured_control = target; 581 582 if((target !is null) && (ret | target.onSecondaryMouseDown(mouseProps))) { 583 onDraw(); 584 } 585 } 586 587 // Description: Called when the secondary mouse button (usually the right button) is released. 588 void onSecondaryMouseUp() { 589 Widget target; 590 bool ret = mouseEventCommon(target); 591 592 _captured_control = null; 593 594 if((target !is null) && (ret | target.onSecondaryMouseUp(mouseProps))) { 595 onDraw(); 596 } 597 } 598 599 // Description: Called when the tertiary mouse button (usually the middle button) is pressed. 600 void onTertiaryMouseDown() { 601 Widget target; 602 bool ret = mouseEventCommon(target); 603 604 _captured_control = target; 605 606 if((target !is null) && (ret | target.onTertiaryMouseDown(mouseProps))) { 607 onDraw(); 608 } 609 } 610 611 // Description: Called when the tertiary mouse button (usually the middle button) is released. 612 void onTertiaryMouseUp() { 613 Widget target; 614 bool ret = mouseEventCommon(target); 615 616 _captured_control = null; 617 618 if((target !is null) && (ret | target.onTertiaryMouseUp(mouseProps))) { 619 onDraw(); 620 } 621 } 622 623 // Description: This event is called when another uncommon mouse button is pressed down over the window. 624 // button: The identifier of this button. 625 void onOtherMouseDown(uint button) { 626 Widget target; 627 bool ret = mouseEventCommon(target); 628 629 _captured_control = target; 630 631 if((target !is null) && (ret | target.onOtherMouseDown(mouseProps, button))) { 632 onDraw(); 633 } 634 } 635 636 // Description: This event is called when another uncommon mouse button is released over the window. 637 // button: The identifier of this button. 638 void onOtherMouseUp(uint button) { 639 Widget target; 640 bool ret = mouseEventCommon(target); 641 642 _captured_control = null; 643 644 if((target !is null) && (ret | target.onOtherMouseUp(mouseProps, button))) { 645 onDraw(); 646 } 647 } 648 649 void onResize() { 650 ViewResizeForWindow(_view, _viewVars, this, &_pfvars); 651 652 onDraw(); 653 } 654 655 void onLostFocus() { 656 //currently focused control will lose focus 657 if (_focused_control !is null) { 658 _focused_control._focused = false; 659 if (_focused_control.onLostFocus(true)) { 660 onDraw(); 661 } 662 } 663 } 664 665 void onGotFocus() { 666 //currently focused control will regain focus 667 if (_focused_control !is null) { 668 _focused_control._focused = true; 669 if (_focused_control.onGotFocus(true)) { 670 onDraw(); 671 } 672 } 673 } 674 675 // Methods // 676 677 // Description: This will give the preferred position for the window. 678 // Returns: The position this window was created with. 679 WindowPosition position() { 680 return _position; 681 } 682 683 // Description: This will retreive the current window color. 684 // Returns: The color currently associated with the window. 685 Color color() { 686 return _color; 687 } 688 689 // Description: This will set the current window color. 690 // color: The color to associate with the window. 691 void color(ref Color clr) { 692 _color = clr; 693 } 694 695 // Description: This will set the current window color to a specific platform color. 696 // sysColor: The system color index to associate with the window. 697 void color(SystemColor clr) { 698 ColorGetSystemColor(_color, clr); 699 } 700 701 // Description: This will force a redraw of the entire window. 702 void redraw() { 703 onDraw(); 704 } 705 706 // Widget Maintenance // 707 708 // Description: This function will return the visible control at the point given. 709 // x: The x coordinate to start the search. 710 // y: The y coordinate to start the search. 711 // Returns: The top-most visible control at the point (x,y) or null. 712 Widget controlAtPoint(int x, int y) { 713 Widget ctrl = _firstControl; 714 715 if (ctrl !is null) { 716 do { 717 if (ctrl.containsPoint(x,y) && ctrl.visible) { 718 if (ctrl.isContainer()) { 719 Widget innerCtrl = (cast(AbstractContainer)ctrl).controlAtPoint(x,y); 720 if (innerCtrl !is null) { return innerCtrl; } 721 } 722 else { 723 return ctrl; 724 } 725 } 726 ctrl = ctrl._nextControl; 727 } while (ctrl !is _firstControl) 728 } 729 730 return null; 731 } 732 733 override void push(Dispatcher dsp) { 734 if (cast(Widget)dsp !is null) { 735 Widget control = cast(Widget)dsp; 736 737 // do not add a control that is already part of another window 738 if (control.parent !is null) { return; } 739 740 // Set the window it belongs to 741 control._window = this; 742 743 // add to the control linked list 744 if (_firstControl is null && _lastControl is null) { 745 // first control 746 747 _firstControl = control; 748 _lastControl = control; 749 750 control._nextControl = control; 751 control._prevControl = control; 752 } 753 else { 754 // next control 755 control._nextControl = _firstControl; 756 control._prevControl = _lastControl; 757 758 _firstControl._prevControl = control; 759 _lastControl._nextControl = control; 760 761 _firstControl = control; 762 } 763 764 // increase the number of controls 765 _numControls++; 766 767 // set the control's parent 768 control._view = _view; 769 control._container = this; 770 771 super.push(control); 772 773 // call the control's event 774 control.onAdd(); 775 776 return; 777 } 778 779 super.push(dsp); 780 } 781 782 // Description: Removes the control as long as this control is a part of the current window. 783 // control: A reference to the control that should be removed from the window. 784 void removeControl(Widget control) { 785 if (control.isOfWindow(this)) { 786 if (_firstControl is null && _lastControl is null) { 787 // it is the last control 788 _firstControl = null; 789 _lastControl = null; 790 } 791 else { 792 // is it not the last control 793 794 if (_firstControl is control) { 795 _firstControl = _firstControl._nextControl; 796 } 797 798 if (_lastControl is control) { 799 _lastControl = _lastControl._prevControl; 800 } 801 802 control.removeControl; 803 } 804 805 _numControls--; 806 } 807 } 808 809 void removeAll() { 810 // will go through and remove all of the controls 811 812 Widget c = _firstControl; 813 Widget tmp; 814 815 if (c is null) { return; } 816 817 do { 818 tmp = c._nextControl; 819 820 c.removeControl(); 821 822 c = tmp; 823 } while (c !is _firstControl); 824 825 _firstControl = null; 826 _lastControl = null; 827 } 828 829 // Menus // 830 831 // Description: Sets the menu for the window. This menu's subitems will be displayed typically as a menu bar. 832 // mnuMain: A Menu object representing the main menu for the window. Pass null to have no menu. 833 void menu(Menu mnuMain) { 834 _mainMenu = mnuMain; 835 836 if (mnuMain is null) { 837 // remove the menu 838 } 839 else { 840 // Switch out and apply the menu 841 842 // platform specific 843 MenuPlatformVars* mnuVars = MenuGetPlatformVars(mnuMain); 844 WindowSetMenu(mnuVars, this, &_pfvars); 845 } 846 } 847 848 // Description: Gets the current menu for the window. It will return null when no menu is available. 849 // Returns: The Menu object representing the main menu for the window. 850 Menu menu() { 851 return _mainMenu; 852 } 853 854 // public properties 855 856 Mouse mouseProps; 857 858protected: 859 860 final bool mouseEventCommon(out Widget target) { 861 if (_captured_control !is null) { 862 target = _captured_control; 863 } 864 else if ((target = controlAtPoint(mouseProps.x, mouseProps.y)) !is null) { 865 bool ret = false; 866 867 //consider the focus of the control 868 if(_focused_control !is target) { 869 if (_focused_control !is null) { 870 //the current focused control gets unfocused 871 _focused_control._focused = false; 872 ret = _focused_control.onLostFocus(false); 873 } 874 875 //focus this control 876 _focused_control = target; 877 _focused_control._focused = true; 878 879 ret |= _focused_control.onGotFocus(false); 880 } 881 882 return ret; 883 884 //change the cursor to reflect the new control 885 //ChangeCursor(index->ctrl_cursor); 886 } 887 888 return false; 889 } 890 891 package final void uninitialize() { 892 if (_nextWindow is null) { return; } 893 894 onRemove(); 895 896 removeAll(); 897 898 _prevWindow._nextWindow = _nextWindow; 899 _nextWindow._prevWindow = _prevWindow; 900 901 // destroy the window's view object 902 onUninitialize(); 903 904 GuiApplication app = cast(GuiApplication)responder; 905 906 if (app._windowListHead is this && app._windowListTail is this) { 907 app._windowListHead = null; 908 app._windowListTail = null; 909 } 910 else { 911 if (app._windowListHead is this) { 912 app._windowListHead = app._windowListHead._nextWindow; 913 } 914 915 if (app._windowListTail is this) { 916 app._windowListTail = app._windowListHead._prevWindow; 917 } 918 } 919 920 _nextWindow = null; 921 _prevWindow = null; 922 923 // Decrement Window length 924 app._windowCount--; 925 926 // Check to see if this was invisible 927 if (_visible) { 928 // Decrement Window Visible length 929 app._windowVisibleCount--; 930 931 // If there are no visible windows, quit (for now) 932 if (app.isZombie()) { 933 // just kill the app 934 app.destroyAllWindows(); 935 app.exit(0); 936 } 937 } 938 939 // is it a parent window of some kind? 940 // destroy and uninitialize all children 941 if (_firstChild !is null) { 942 Window child = _firstChild; 943 944 do { 945 child.remove(); 946 child = child._nextSibling; 947 } while (child !is _firstChild) 948 } 949 950 // is it a child window of some kind? 951 // unlink it within the sibling list 952 if (_parent !is null) { 953 Window p = _parent; 954 955 p._numChildren--; 956 957 _prevSibling._nextSibling = _nextSibling; 958 _nextSibling._prevSibling = _prevSibling; 959 960 if (p._firstChild is this && p._lastChild is this) { 961 // unreference this, the last child 962 // the parent now has no children 963 p._firstChild = null; 964 p._lastChild = null; 965 } 966 else { 967 if (p._firstChild is this) { 968 p._firstChild = p._firstChild._nextSibling; 969 } 970 971 if (p._lastChild is this) { 972 p._lastChild = p._lastChild._prevSibling; 973 } 974 } 975 } 976 977 _parent = null; 978 _nextSibling = null; 979 _prevSibling = null; 980 _firstChild = null; 981 _lastChild = null; 982 } 983 984 package WindowView _view = null; 985 package ViewPlatformVars* _viewVars; 986 987 Color _color; 988 WindowPosition _position; 989 990 // imposes left and top margins on the window, when set 991 long _constraint_x = 0; 992 long _constraint_y = 0; 993 994 string _window_title; 995 package uint _width, _height; 996 package uint _x, _y; 997 998 package WindowStyle _style; 999 package WindowState _state; 1000 1001private: 1002 1003 // head and tail of the control linked list 1004 Widget _firstControl = null; //head 1005 Widget _lastControl = null; //tail 1006 int _numControls = 0; 1007 1008 Widget _captured_control = null; 1009 Widget _last_control = null; 1010 Widget _focused_control = null; 1011 1012 Menu _mainMenu = null; 1013 1014 // linked list implementation 1015 // to keep track of all windows 1016 package Window _nextWindow = null; 1017 package Window _prevWindow = null; 1018 1019 // children windows will follow suit: 1020 Window _firstChild = null; //head 1021 Window _lastChild = null; //tail 1022 1023 uint _numChildren = 0; // child count 1024 1025 // parent is null when it is a root window 1026 Window _parent = null; 1027 1028 // these may be null when it is an only child 1029 Window _nextSibling = null; 1030 Window _prevSibling = null; 1031 1032 package bool _visible = false; 1033 bool _fullscreen = false; 1034 1035 package bool _inited = false; 1036 1037 package WindowPlatformVars _pfvars; 1038} 1039 1040// Definition: This is a View that defines the graphical client area of a Window. 1041class WindowView : View { 1042 1043 this() { 1044 super(); 1045 } 1046 1047 override void create(int width, int height) { 1048 } 1049 1050protected: 1051 1052 override void _platformCreate() { 1053 ViewCreateForWindow(this, &_pfvars, _window, _windowVars); 1054 } 1055 1056private: 1057 1058 ViewPlatformVars* createForWindow(Window window, WindowPlatformVars* windowVars) { 1059 _window = window; 1060 _windowVars = windowVars; 1061 View.create(window.width, window.height); 1062 1063 return &_pfvars; 1064 } 1065 1066 Window _window; 1067 WindowPlatformVars* _windowVars; 1068}