mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 12:30:32 +00:00
926 lines
33 KiB
C#
926 lines
33 KiB
C#
using System;
|
|
using Orvid.Graphics;
|
|
using OForms.Controls;
|
|
using System.Collections.Generic;
|
|
|
|
namespace OForms.Windows
|
|
{
|
|
/// <summary>
|
|
/// The class that represents a single window.
|
|
/// </summary>
|
|
public class Window : IDisposable
|
|
{
|
|
/// <summary>
|
|
/// The name of the window.
|
|
/// </summary>
|
|
public string Name;
|
|
/// <summary>
|
|
/// The parent WindowManager of this window.
|
|
/// </summary>
|
|
public WindowManager Parent;
|
|
/// <summary>
|
|
/// The location of the window. Use this internally only
|
|
/// if you are reading the location. If you are changing
|
|
/// the location, use the public Location property instead,
|
|
/// so that the bounds, get properly reset.
|
|
/// </summary>
|
|
private Vec2 iLocation;
|
|
/// <summary>
|
|
/// The location of the window.
|
|
/// </summary>
|
|
public Vec2 Location
|
|
{
|
|
get
|
|
{
|
|
return iLocation;
|
|
}
|
|
set
|
|
{
|
|
Parent.NeedToRedrawAll = true;
|
|
iLocation = value;
|
|
ComputeBounds();
|
|
// Doesn't change the physical size,
|
|
// so buffers don't get reset.
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// The minimum allowable window size in the X direction.
|
|
/// </summary>
|
|
private const int MinXWindowSize = 50;
|
|
/// <summary>
|
|
/// The minimum allowable window size in the Y direction.
|
|
/// </summary>
|
|
private const int MinYWindowSize = 40;
|
|
/// <summary>
|
|
/// The size of the window. Use this internally only
|
|
/// if you are reading the size. If you are changing
|
|
/// the size, use the public Size property instead,
|
|
/// so that the bounds, and buffers get properly reset.
|
|
/// </summary>
|
|
private Vec2 iSize;
|
|
/// <summary>
|
|
/// The size of the window.
|
|
/// </summary>
|
|
public Vec2 Size
|
|
{
|
|
get
|
|
{
|
|
return iSize;
|
|
}
|
|
set
|
|
{
|
|
Parent.NeedToRedrawAll = true;
|
|
if (value.X < MinXWindowSize)
|
|
{
|
|
value.X = MinXWindowSize;
|
|
}
|
|
if (value.Y < MinYWindowSize)
|
|
{
|
|
value.Y = MinYWindowSize;
|
|
}
|
|
iSize = value;
|
|
ComputeBounds();
|
|
ResetBuffers();
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// The Bounds of this window.
|
|
/// </summary>
|
|
public BoundingBox Bounds;
|
|
/// <summary>
|
|
/// The BoundingBox for the window's contents.
|
|
/// </summary>
|
|
private BoundingBox ContentBounds;
|
|
/// <summary>
|
|
/// The BoundingBox for the header of the window.
|
|
/// </summary>
|
|
private BoundingBox HeaderBounds;
|
|
/// <summary>
|
|
/// The BoundingBox for the Close button.
|
|
/// </summary>
|
|
private BoundingBox CloseButtonBounds;
|
|
/// <summary>
|
|
/// The BoundingBox for the Maximize/Restore button.
|
|
/// </summary>
|
|
private BoundingBox MaxButtonBounds;
|
|
/// <summary>
|
|
/// The BoundingBox for the Minimize button.
|
|
/// </summary>
|
|
private BoundingBox MinButtonBounds;
|
|
/// <summary>
|
|
/// The height of the header. (in pixels)
|
|
/// </summary>
|
|
private const int HeaderHeight = 15;
|
|
/// <summary>
|
|
/// The thickness of the window border. (in pixels)
|
|
/// </summary>
|
|
private const int WindowBorderSize = 1;
|
|
/// <summary>
|
|
/// The overall buffer for the window.
|
|
/// </summary>
|
|
private Image WindowBuffer;
|
|
/// <summary>
|
|
/// The buffer for the content of the window.
|
|
/// </summary>
|
|
private Image ContentBuffer;
|
|
/// <summary>
|
|
/// The buffer for the header of the window.
|
|
/// </summary>
|
|
private Image HeaderBuffer;
|
|
/// <summary>
|
|
/// True if this is the currently active window.
|
|
/// </summary>
|
|
private bool isActiveWindow = false;
|
|
/// <summary>
|
|
/// True if this is the currently active window.
|
|
/// </summary>
|
|
public bool IsActiveWindow
|
|
{
|
|
get
|
|
{
|
|
return isActiveWindow;
|
|
}
|
|
set
|
|
{
|
|
if (value != isActiveWindow)
|
|
{
|
|
if (value)
|
|
{
|
|
FadingIn = true;
|
|
}
|
|
isActiveWindow = value;
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// True if the window is in the process of being dragged.
|
|
/// </summary>
|
|
private bool IsDragging = false;
|
|
/// <summary>
|
|
/// True if the window should fade in when selected.
|
|
/// </summary>
|
|
public bool ShouldFadeIn = true;
|
|
/// <summary>
|
|
/// True if we are fading in.
|
|
/// </summary>
|
|
private bool FadingIn = false;
|
|
/// <summary>
|
|
/// The current state of the window.
|
|
/// Don't use this field, use CurrentState
|
|
/// instead.
|
|
/// </summary>
|
|
private WindowState iCurrentState = WindowState.Normal;
|
|
/// <summary>
|
|
/// The current WindowState of the window.
|
|
/// </summary>
|
|
public WindowState CurrentState
|
|
{
|
|
get
|
|
{
|
|
return iCurrentState;
|
|
}
|
|
set
|
|
{
|
|
if (iCurrentState != value)
|
|
{
|
|
if (iCurrentState == WindowState.Maximized)
|
|
{
|
|
if (value == WindowState.Minimized)
|
|
{
|
|
WasMaximized = true;
|
|
iCurrentState = value;
|
|
}
|
|
else // It means window state is normal.
|
|
{
|
|
WasMaximized = false;
|
|
this.Location = PrevLoc;
|
|
this.Size = PrevSize;
|
|
iCurrentState = value;
|
|
}
|
|
}
|
|
// Should only be set to normal from the minimized state.
|
|
else if (iCurrentState == WindowState.Minimized)
|
|
{
|
|
if (WasMaximized)
|
|
{
|
|
iCurrentState = WindowState.Maximized;
|
|
}
|
|
else
|
|
{
|
|
iCurrentState = value;
|
|
}
|
|
}
|
|
else if (iCurrentState == WindowState.Normal)
|
|
{
|
|
if (value == WindowState.Maximized)
|
|
{
|
|
PrevLoc = iLocation;
|
|
this.Location = Vec2.Zero;
|
|
PrevSize = iSize;
|
|
this.Size = new Vec2(Parent.Size.X, Parent.Size.Y - WindowManager.TaskBarHeight);
|
|
iCurrentState = WindowState.Maximized;
|
|
}
|
|
else
|
|
{
|
|
iCurrentState = value;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("Unknown WindowState!");
|
|
}
|
|
ResetBuffers();
|
|
ComputeBounds();
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Location of the window before it was maximized.
|
|
/// </summary>
|
|
private Vec2 PrevLoc;
|
|
/// <summary>
|
|
/// Size of the window before it was maximized.
|
|
/// </summary>
|
|
private Vec2 PrevSize;
|
|
/// <summary>
|
|
/// True if the window was Maximized when the window got Minimized.
|
|
/// </summary>
|
|
private bool WasMaximized = false;
|
|
/// <summary>
|
|
/// True if we're currently resizing.
|
|
/// </summary>
|
|
private bool IsResizing = false;
|
|
/// <summary>
|
|
/// The size of the window when resizing started.
|
|
/// </summary>
|
|
private Vec2 InitSizeOnResizeStart;
|
|
/// <summary>
|
|
/// The location of the mouse when resizing started.
|
|
/// </summary>
|
|
private Vec2 InitResizeLocation;
|
|
/// <summary>
|
|
/// The location of the window when window dragging started.
|
|
/// </summary>
|
|
private Vec2 InitWindowLocOnDragStart;
|
|
/// <summary>
|
|
/// The location of the mouse when window dragging started.
|
|
/// </summary>
|
|
private Vec2 InitDraggingLocation;
|
|
/// <summary>
|
|
/// True if the last mouse move event had the mouse in
|
|
/// the window header.
|
|
/// </summary>
|
|
private bool WasInHeader = false;
|
|
/// <summary>
|
|
/// True if the last mouse move event had the mouse
|
|
/// over the Close button.
|
|
/// </summary>
|
|
private bool WasOverClose = false;
|
|
/// <summary>
|
|
/// True if the last mouse move event had the mouse
|
|
/// over the Maximize/Restore button.
|
|
/// </summary>
|
|
private bool WasOverMax = false;
|
|
/// <summary>
|
|
/// True if the last mouse move event had the mouse
|
|
/// over the Minimize button.
|
|
/// </summary>
|
|
private bool WasOverMin = false;
|
|
/// <summary>
|
|
/// The color to clear the ContentBuffer with when the window is inactive.
|
|
/// </summary>
|
|
public Pixel ClearInactiveColor = Colors.Brown;
|
|
/// <summary>
|
|
/// The color to clear the ContentBuffer with when the window is active.
|
|
/// </summary>
|
|
public Pixel ClearColor = Colors.Brown;
|
|
/// <summary>
|
|
/// True if the header has been drawn.
|
|
/// </summary>
|
|
private bool DrawnHeader = false;
|
|
/// <summary>
|
|
/// The controls in the window.
|
|
/// </summary>
|
|
public List<Control> Controls = new List<Control>();
|
|
|
|
|
|
#region Colors
|
|
/// <summary>
|
|
/// The current background color of the Close button.
|
|
/// </summary>
|
|
private Pixel CurCloseButtonColor = Colors.Red;
|
|
/// <summary>
|
|
/// The current background color of the Maximize/Restore button.
|
|
/// </summary>
|
|
private Pixel CurMaxButtonColor = Colors.Red;
|
|
/// <summary>
|
|
/// The current background color of the Minimize button.
|
|
/// </summary>
|
|
private Pixel CurMinButtonColor = Colors.Red;
|
|
|
|
#region Default Colors
|
|
/// <summary>
|
|
/// The default background color of the Close button.
|
|
/// </summary>
|
|
private static Pixel DefaultCloseButtonColor = Colors.Red;
|
|
/// <summary>
|
|
/// The default background color of the Maximize/Restore button.
|
|
/// </summary>
|
|
private static Pixel DefaultMaxButtonColor = Colors.Red;
|
|
/// <summary>
|
|
/// The default background color of the Minimize button.
|
|
/// </summary>
|
|
private static Pixel DefaultMinButtonColor = Colors.Red;
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
/// The default constructor for a window.
|
|
/// </summary>
|
|
/// <param name="loc">The initial location of the window.</param>
|
|
/// <param name="size">The size of the window.</param>
|
|
/// <param name="name">The name of the window.</param>
|
|
public Window(Vec2 loc, Vec2 size, string name)
|
|
{
|
|
iLocation = loc;
|
|
iSize = size;
|
|
Name = name;
|
|
ResetBuffers();
|
|
ComputeBounds();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a string representing this window.
|
|
/// </summary>
|
|
/// <returns>The window as a string.</returns>
|
|
public override string ToString()
|
|
{
|
|
return this.Name;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Closes this window.
|
|
/// </summary>
|
|
public void Close()
|
|
{
|
|
Parent.CloseWindow(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Does the actual closing of this window.
|
|
/// </summary>
|
|
internal void DoClose()
|
|
{
|
|
foreach (Control c in Controls)
|
|
{
|
|
c.DoClosing();
|
|
}
|
|
this.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disposes of all of the resources used by this window.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
this.Bounds = null;
|
|
this.CloseButtonBounds = null;
|
|
this.ContentBounds = null;
|
|
this.ContentBuffer = null;
|
|
foreach (Control c in Controls)
|
|
{
|
|
c.DoBeforeDispose();
|
|
c.Dispose();
|
|
c.DoAfterDispose();
|
|
}
|
|
this.Controls = null;
|
|
this.HeaderBounds = null;
|
|
this.HeaderBuffer = null;
|
|
this.MaxButtonBounds = null;
|
|
this.MinButtonBounds = null;
|
|
this.Parent = null;
|
|
this.WindowBuffer = null;
|
|
this.Name = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resets all of the buffers, and redraws the HeaderBuffer.
|
|
/// </summary>
|
|
private void ResetBuffers()
|
|
{
|
|
WindowBuffer = new Image(iSize);
|
|
WindowBuffer.Clear(Colors.BurlyWood);
|
|
DrawnHeader = false;
|
|
|
|
RedrawHeader(); // Draw the header.
|
|
|
|
ContentBuffer = new Image(new Vec2(iSize.X - WindowBorderSize - WindowBorderSize, iSize.Y - HeaderHeight));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Redraws the header.
|
|
/// </summary>
|
|
private void RedrawHeader()
|
|
{
|
|
HeaderBuffer = new Image(new Vec2(iSize.X, HeaderHeight));
|
|
HeaderBuffer.Clear(Colors.BlueViolet);
|
|
DrawnHeader = false;
|
|
|
|
//HeaderBuffer.DrawString(new Vec2(3, 3), Name, WindowManager.WindowFont, 10, Orvid.Graphics.FontSupport.FontStyle.Normal, Colors.Black);
|
|
|
|
RedrawCloseButton();
|
|
RedrawMaxRestButton();
|
|
RedrawMinButton();
|
|
}
|
|
|
|
#region Draw Close Button
|
|
/// <summary>
|
|
/// Re-Draws the Close button on the HeaderBuffer.
|
|
/// </summary>
|
|
private void RedrawCloseButton()
|
|
{
|
|
Vec2 tl = new Vec2(iSize.X - HeaderHeight + 2, WindowBorderSize + 1);
|
|
Vec2 tr = new Vec2(iSize.X - WindowBorderSize - 2, WindowBorderSize + 1);
|
|
Vec2 br = new Vec2(iSize.X - WindowBorderSize - 2, HeaderHeight - 2);
|
|
Vec2 bl = new Vec2(iSize.X - HeaderHeight + 2, HeaderHeight - 2);
|
|
HeaderBuffer.DrawRectangle(tl, br, CurCloseButtonColor);
|
|
HeaderBuffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, Colors.Green);
|
|
HeaderBuffer.DrawLine(new Vec2(iSize.X - WindowBorderSize - 4, WindowBorderSize + 3), new Vec2(iSize.X - HeaderHeight + 4, HeaderHeight - 4), Colors.Green);
|
|
HeaderBuffer.DrawLine(new Vec2(iSize.X - HeaderHeight + 4, WindowBorderSize + 3), new Vec2(iSize.X - WindowBorderSize - 4, HeaderHeight - 4), Colors.Green);
|
|
DrawnHeader = false;
|
|
}
|
|
#endregion
|
|
|
|
#region Draw Maximize/Restore Button
|
|
/// <summary>
|
|
/// Re-Draws the Maximize/Restore button on the HeaderBuffer.
|
|
/// </summary>
|
|
private void RedrawMaxRestButton()
|
|
{
|
|
Vec2 tl = new Vec2(iSize.X - (HeaderHeight + HeaderHeight - 2), WindowBorderSize + 1);
|
|
Vec2 tr = new Vec2(iSize.X - (HeaderHeight + WindowBorderSize + 2), WindowBorderSize + 1);
|
|
Vec2 br = new Vec2(iSize.X - (HeaderHeight + WindowBorderSize + 2), HeaderHeight - 2);
|
|
Vec2 bl = new Vec2(iSize.X - (HeaderHeight + HeaderHeight - 2), HeaderHeight - 2);
|
|
if (CurrentState == WindowState.Maximized) // Draw Restore Button.
|
|
{
|
|
#region Draw Restore Button
|
|
HeaderBuffer.DrawRectangle(tl, br, CurMaxButtonColor);
|
|
HeaderBuffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, Colors.Green);
|
|
HeaderBuffer.DrawLines(new Vec2[] {
|
|
new Vec2(tl.X + 4, tl.Y + 2),
|
|
new Vec2(tr.X - 2, tr.Y + 2),
|
|
new Vec2(tr.X - 2, tr.Y + 3),
|
|
new Vec2(tl.X + 4, tl.Y + 3),
|
|
new Vec2(tl.X + 4, tl.Y + 5),
|
|
new Vec2(tl.X + 2, tl.Y + 5),
|
|
new Vec2(tl.X + 2, bl.Y - 2),
|
|
new Vec2(tr.X - 4, bl.Y - 2),
|
|
new Vec2(tr.X - 4, tl.Y + 5),
|
|
new Vec2(tl.X + 4, tl.Y + 5),
|
|
new Vec2(tl.X + 4, tl.Y + 6),
|
|
new Vec2(tl.X + 2, tl.Y + 6),
|
|
new Vec2(tr.X - 4, tl.Y + 6),
|
|
new Vec2(tr.X - 4, tl.Y + 7),
|
|
new Vec2(tr.X - 2, tl.Y + 7),
|
|
new Vec2(tr.X - 2, tl.Y + 2),
|
|
}, Colors.Green);
|
|
#endregion
|
|
}
|
|
else // Draw Maximize Button.
|
|
{
|
|
#region Draw Maximize Button
|
|
HeaderBuffer.DrawRectangle(tl, br, CurMaxButtonColor);
|
|
HeaderBuffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, Colors.Green);
|
|
HeaderBuffer.DrawLines(new Vec2[] {
|
|
new Vec2(tl.X + 2, tl.Y + 2),
|
|
new Vec2(tr.X - 2, tr.Y + 2),
|
|
new Vec2(br.X - 2, br.Y - 2),
|
|
new Vec2(bl.X + 2, bl.Y - 2),
|
|
new Vec2(tl.X + 2, tl.Y + 2),
|
|
}, Colors.Green);
|
|
HeaderBuffer.DrawLine(new Vec2(tl.X + 2, tl.Y + 3), new Vec2(tr.X - 2, tr.Y + 3), Colors.Green);
|
|
#endregion
|
|
}
|
|
DrawnHeader = false;
|
|
}
|
|
#endregion
|
|
|
|
#region Redraw Minimize Button
|
|
/// <summary>
|
|
/// Re-Draws the Minimize button on the HeaderBuffer.
|
|
/// </summary>
|
|
private void RedrawMinButton()
|
|
{
|
|
Vec2 tl = new Vec2(iSize.X - (HeaderHeight + HeaderHeight + HeaderHeight - 2), WindowBorderSize + 1);
|
|
Vec2 tr = new Vec2(iSize.X - (HeaderHeight + HeaderHeight + WindowBorderSize + 2), WindowBorderSize + 1);
|
|
Vec2 br = new Vec2(iSize.X - (HeaderHeight + HeaderHeight + WindowBorderSize + 2), HeaderHeight - 2);
|
|
Vec2 bl = new Vec2(iSize.X - (HeaderHeight + HeaderHeight + HeaderHeight - 2), HeaderHeight - 2);
|
|
HeaderBuffer.DrawRectangle(tl, br, CurMinButtonColor);
|
|
HeaderBuffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, Colors.Green);
|
|
HeaderBuffer.DrawLine(new Vec2(br.X - 3, br.Y - 2), new Vec2(bl.X + 3, bl.Y - 2), Colors.Green);
|
|
HeaderBuffer.DrawLine(new Vec2(br.X - 3, br.Y - 3), new Vec2(bl.X + 3, bl.Y - 3), Colors.Green);
|
|
DrawnHeader = false;
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Re-Computes all of the bounding boxes.
|
|
/// </summary>
|
|
private void ComputeBounds()
|
|
{
|
|
this.Bounds = new BoundingBox(
|
|
iLocation.X,
|
|
iLocation.X + iSize.X,
|
|
iLocation.Y + iSize.Y,
|
|
iLocation.Y
|
|
);
|
|
this.HeaderBounds = new BoundingBox(
|
|
iLocation.X,
|
|
iLocation.X + iSize.X,
|
|
iLocation.Y + HeaderHeight,
|
|
iLocation.Y
|
|
);
|
|
this.ContentBounds = new BoundingBox(
|
|
iLocation.X + WindowBorderSize,
|
|
iLocation.X + (iSize.X - WindowBorderSize - WindowBorderSize),
|
|
iLocation.Y + (iSize.Y - HeaderHeight),
|
|
iLocation.Y + HeaderHeight
|
|
);
|
|
|
|
this.CloseButtonBounds = new BoundingBox(
|
|
iLocation.X + (iSize.X - HeaderHeight + 2),
|
|
iLocation.X + (iSize.X - WindowBorderSize - 2),
|
|
iLocation.Y + (HeaderHeight - 2),
|
|
iLocation.Y + (WindowBorderSize + 1)
|
|
);
|
|
this.MaxButtonBounds = new BoundingBox(
|
|
iLocation.X + (iSize.X - (HeaderHeight + HeaderHeight - 2)),
|
|
iLocation.X + (iSize.X - (HeaderHeight + WindowBorderSize + 2)),
|
|
iLocation.Y + (HeaderHeight - 2),
|
|
iLocation.Y + (WindowBorderSize + 1)
|
|
);
|
|
this.MinButtonBounds = new BoundingBox(
|
|
iLocation.X + (iSize.X - (HeaderHeight + HeaderHeight + HeaderHeight - 2)),
|
|
iLocation.X + (iSize.X - (HeaderHeight + HeaderHeight + WindowBorderSize + 2)),
|
|
iLocation.Y + (HeaderHeight - 2),
|
|
iLocation.Y + (WindowBorderSize + 1)
|
|
);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws this window on the specified image.
|
|
/// </summary>
|
|
/// <param name="i">The image to draw the window to.</param>
|
|
internal void Draw(Image i)
|
|
{
|
|
if (!DrawnHeader)
|
|
{
|
|
WindowBuffer.DrawImage(Vec2.Zero, HeaderBuffer);
|
|
WindowBuffer.DrawLine(Vec2.Zero, new Vec2(iSize.X - WindowBorderSize, 0), Colors.Black);
|
|
WindowBuffer.DrawLine(new Vec2(iSize.X - WindowBorderSize, 0), iSize - WindowBorderSize, Colors.Black);
|
|
WindowBuffer.DrawLine(new Vec2(0, iSize.Y - WindowBorderSize), Vec2.Zero, Colors.Black);
|
|
DrawnHeader = true;
|
|
}
|
|
|
|
if (IsActiveWindow)
|
|
{
|
|
if (FadingIn)
|
|
{
|
|
ContentBuffer.Clear(new Pixel(ClearColor.R, ClearColor.G, ClearColor.B, 128));
|
|
FadingIn = false;
|
|
}
|
|
else
|
|
{
|
|
ContentBuffer.Clear(ClearColor);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ContentBuffer.Clear(ClearInactiveColor);
|
|
}
|
|
foreach (Control c in Controls)
|
|
{
|
|
c.Draw(ContentBuffer);
|
|
}
|
|
WindowBuffer.DrawImage(new Vec2(WindowBorderSize, HeaderHeight), ContentBuffer);
|
|
WindowBuffer.DrawLine(iSize - WindowBorderSize, new Vec2(0, iSize.Y - WindowBorderSize), Colors.Black);
|
|
WindowBuffer.DrawLine(new Vec2(WindowBorderSize, HeaderHeight), new Vec2(iSize.X - WindowBorderSize - 1, HeaderHeight), new Pixel(214, 211, 206, 255));
|
|
|
|
i.DrawImage(iLocation, WindowBuffer);
|
|
}
|
|
|
|
|
|
#region Do Events
|
|
/// <summary>
|
|
/// Processes a MouseClick event.
|
|
/// </summary>
|
|
/// <param name="loc">The location of the mouse.</param>
|
|
/// <param name="button">The buttons that are pressed.</param>
|
|
internal void DoClick(Vec2 loc, MouseButtons button)
|
|
{
|
|
if (IsActiveWindow)
|
|
{
|
|
if (ContentBounds.IsInBounds(loc))
|
|
{
|
|
Vec2 RelativeLoc;
|
|
foreach (Control c in Controls)
|
|
{
|
|
RelativeLoc = new Vec2(loc.X - Location.X - WindowBorderSize, loc.Y - Location.Y - HeaderHeight);
|
|
if (c.Bounds.IsInBounds(RelativeLoc))
|
|
{
|
|
c.DoClick(RelativeLoc, button);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (HeaderBounds.IsInBounds(loc))
|
|
{
|
|
if (CloseButtonBounds.IsInBounds(loc))
|
|
{
|
|
this.Close();
|
|
}
|
|
else if (MaxButtonBounds.IsInBounds(loc))
|
|
{
|
|
if (CurrentState == WindowState.Maximized)
|
|
{
|
|
Parent.RestoreWindow(this);
|
|
}
|
|
else
|
|
{
|
|
Parent.MaximizeWindow(this);
|
|
}
|
|
}
|
|
else if (MinButtonBounds.IsInBounds(loc))
|
|
{
|
|
Parent.MinimizeWindow(this);
|
|
}
|
|
}
|
|
else // Window border was clicked, and we don't care about it.
|
|
{
|
|
//throw new Exception("Unknown part of the window clicked!");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Parent.BringWindowToFront(this);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes a MouseUp event.
|
|
/// </summary>
|
|
/// <param name="loc">The location of the mouse.</param>
|
|
/// <param name="button">The buttons that are still pressed down.</param>
|
|
internal void DoMouseUp(Vec2 loc, MouseButtons button)
|
|
{
|
|
if (IsDragging)
|
|
{
|
|
IsDragging = false;
|
|
InitDraggingLocation = null;
|
|
InitWindowLocOnDragStart = null;
|
|
}
|
|
else if (IsResizing)
|
|
{
|
|
IsResizing = false;
|
|
InitResizeLocation = null;
|
|
InitSizeOnResizeStart = null;
|
|
}
|
|
else
|
|
{
|
|
Vec2 RelativeLoc;
|
|
foreach (Control c in Controls)
|
|
{
|
|
if (c.IsMouseDown)
|
|
{
|
|
RelativeLoc = new Vec2(loc.X - Location.X - WindowBorderSize, loc.Y - Location.Y - HeaderHeight);
|
|
c.IsMouseDown = false;
|
|
c.DoMouseUp(RelativeLoc, button);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes a MouseDown event.
|
|
/// </summary>
|
|
/// <param name="loc">The location of the mouse.</param>
|
|
/// <param name="button">The buttons that are down.</param>
|
|
internal void DoMouseDown(Vec2 loc, MouseButtons button)
|
|
{
|
|
if (ContentBounds.IsInBounds(loc))
|
|
{
|
|
Vec2 RelativeLoc;
|
|
foreach (Control c in Controls)
|
|
{
|
|
RelativeLoc = new Vec2(loc.X - Location.X - WindowBorderSize, loc.Y - Location.Y - HeaderHeight);
|
|
if (c.Bounds.IsInBounds(RelativeLoc))
|
|
{
|
|
c.IsMouseDown = true;
|
|
c.DoMouseDown(RelativeLoc, button);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (HeaderBounds.IsInBounds(loc))
|
|
{
|
|
IsDragging = true;
|
|
InitDraggingLocation = loc;
|
|
InitWindowLocOnDragStart = this.iLocation;
|
|
}
|
|
else // The border of the window was pressed, begin resize.
|
|
{
|
|
IsResizing = true;
|
|
InitSizeOnResizeStart = this.iSize;
|
|
InitResizeLocation = loc;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Checks if we were over buttons,
|
|
/// and reset their colors if needed.
|
|
/// </summary>
|
|
private void CheckOldButtons()
|
|
{
|
|
if (WasOverClose)
|
|
{
|
|
CurCloseButtonColor = DefaultCloseButtonColor;
|
|
WasOverClose = false;
|
|
RedrawCloseButton();
|
|
}
|
|
else if (WasOverMax)
|
|
{
|
|
CurMaxButtonColor = DefaultMaxButtonColor;
|
|
WasOverMax = false;
|
|
RedrawMaxRestButton();
|
|
}
|
|
else if (WasOverMin)
|
|
{
|
|
CurMinButtonColor = DefaultMinButtonColor;
|
|
WasOverMin = false;
|
|
RedrawMinButton();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes a MouseMove event.
|
|
/// </summary>
|
|
/// <param name="newLoc">The new location of the mouse.</param>
|
|
/// <param name="button">The buttons on the mouse that are pressed.</param>
|
|
internal void DoMouseMove(Vec2 newLoc, MouseButtons button)
|
|
{
|
|
if (IsDragging)
|
|
{
|
|
Vec2 Transform = newLoc - InitDraggingLocation;
|
|
this.Location = InitWindowLocOnDragStart + Transform;
|
|
}
|
|
else if (IsResizing)
|
|
{
|
|
Vec2 Transform = newLoc - InitResizeLocation;
|
|
this.Size = InitSizeOnResizeStart + Transform;
|
|
}
|
|
else
|
|
{
|
|
if (WasInHeader)
|
|
{
|
|
if (HeaderBounds.IsInBounds(newLoc))
|
|
{
|
|
if (CloseButtonBounds.IsInBounds(newLoc))
|
|
{
|
|
if (!WasOverClose)
|
|
{
|
|
CheckOldButtons();
|
|
CurCloseButtonColor = Colors.Brown;
|
|
WasOverClose = true;
|
|
RedrawCloseButton();
|
|
return;
|
|
}
|
|
// Otherwise we've already done whats
|
|
// needed for being over the close button.
|
|
return;
|
|
}
|
|
else if (MaxButtonBounds.IsInBounds(newLoc))
|
|
{
|
|
if (!WasOverMax)
|
|
{
|
|
CheckOldButtons();
|
|
CurMaxButtonColor = Colors.Brown;
|
|
WasOverMax = true;
|
|
RedrawMaxRestButton();
|
|
return;
|
|
}
|
|
// Otherwise we've already done whats
|
|
// needed for being over the maximize/restore button.
|
|
return;
|
|
}
|
|
else if (MinButtonBounds.IsInBounds(newLoc))
|
|
{
|
|
if (!WasOverMin)
|
|
{
|
|
CheckOldButtons();
|
|
CurMinButtonColor = Colors.Brown;
|
|
WasOverMin = true;
|
|
RedrawMinButton();
|
|
return;
|
|
}
|
|
// Otherwise we've already done whats
|
|
// needed for being over the minimize button.
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
CheckOldButtons();
|
|
}
|
|
}
|
|
else // It's not in the header anymore.
|
|
{
|
|
CheckOldButtons();
|
|
WasInHeader = false;
|
|
}
|
|
}
|
|
if (ContentBounds.IsInBounds(newLoc))
|
|
{
|
|
Vec2 RelativeLoc;
|
|
foreach (Control c in Controls)
|
|
{
|
|
RelativeLoc = new Vec2(newLoc.X - Location.X - WindowBorderSize, newLoc.Y - Location.Y - HeaderHeight);
|
|
if (!c.IsIn)
|
|
{
|
|
if (c.Bounds.IsInBounds(RelativeLoc))
|
|
{
|
|
c.IsIn = true;
|
|
c.DoMouseEnter(RelativeLoc, button);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!c.Bounds.IsInBounds(RelativeLoc))
|
|
{
|
|
c.IsIn = false;
|
|
c.DoMouseLeave(RelativeLoc, button);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (HeaderBounds.IsInBounds(newLoc))
|
|
{
|
|
WasInHeader = true;
|
|
if (CloseButtonBounds.IsInBounds(newLoc))
|
|
{
|
|
CurCloseButtonColor = Colors.Brown;
|
|
WasOverClose = true;
|
|
RedrawCloseButton();
|
|
}
|
|
else if (MaxButtonBounds.IsInBounds(newLoc))
|
|
{
|
|
CurMaxButtonColor = Colors.Brown;
|
|
WasOverMax = true;
|
|
RedrawMaxRestButton();
|
|
}
|
|
else if (MinButtonBounds.IsInBounds(newLoc))
|
|
{
|
|
CurMinButtonColor = Colors.Brown;
|
|
WasOverMin = true;
|
|
RedrawMinButton();
|
|
}
|
|
}
|
|
else // the mouse was in the window border.
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
public static bool operator ==(Window w, Window w2)
|
|
{
|
|
if (w.Name == w2.Name && w.Size == w2.Size && w.Location == w2.Location)
|
|
{
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static bool operator !=(Window w, Window w2)
|
|
{
|
|
return ((w == w2) == false);
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
return (this == (Window)obj);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return base.GetHashCode();
|
|
}
|
|
}
|
|
}
|