PageRenderTime 71ms CodeModel.GetById 10ms app.highlight 53ms RepoModel.GetById 2ms app.codeStats 0ms

/gui/window.d

http://github.com/wilkie/djehuty
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}