using System;
using Orvid.Graphics;
namespace OForms.Windows
{
///
/// The class that represents the Taskbar.
///
internal class Taskbar
{
///
/// The internal buffer of the taskbar.
///
private Image Buffer;
///
/// All of the windows in the taskbar.
///
public Window[] Windows;
///
/// The parent window manager of the taskbar.
///
private WindowManager Manager;
///
/// The location of the taskbar on the window manager.
///
private Vec2 TaskbarLocation;
///
/// The bounds of the taskbar.
///
public BoundingBox Bounds;
///
/// The color to clear the back of the taskbar with.
///
public Pixel TaskbarClearColor = Colors.Coral;
///
/// The color to outline the taskbar with.
///
public Pixel TaskbarOutlineColor = Colors.Crimson;
///
/// The color to draw an inactive window's back in.
///
public Pixel WindowInactiveBackColor = Colors.Brown;
///
/// The color to draw an inactive window's outline in.
///
public Pixel WindowInactiveLineColor = Colors.Blue;
///
/// The color to draw the active window's back in.
///
public Pixel WindowActiveBackColor = Colors.Green;
///
/// The color to draw the active window's outline in.
///
public Pixel WindowActiveLineColor = Colors.Black;
///
/// The color to draw the back of an over active window's back in.
///
public Pixel WindowActiveOverBackColor = Colors.CadetBlue;
///
/// The color to draw the back of an over inactive window's back in.
///
public Pixel WindowInactiveOverBackColor = Colors.Chocolate;
///
/// The color to draw the text on the taskbar in.
///
public Pixel TaskbarTextColor = Colors.Black;
///
/// The default width of a button for a window.
///
private const int WindowButtonWidth = 160;
///
/// The margin around a window button.
///
private const int WindowButtonMargin = 1;
///
/// The height of the taskbar.
///
public const int TaskBarHeight = 20;
///
/// The maximum width for the text on a window button.
///
public const int MaxTextWidth = WindowButtonWidth - 6;
///
/// The bounds of all of the window buttons.
///
internal BoundingBox[] WindowButtonBounds;
///
/// The index of the button that the mouse is over.
///
internal int overButtonIndx = 0;
///
/// True if the over button has been drawn.
///
private bool DrawnOverButton = false;
///
/// True if the taskbar needs to be re-drawn.
///
internal bool Modified = true;
///
/// True if the mouse was over a window button.
///
internal bool WasOverButton = false;
///
/// True if the taskbar has been drawn since it was modified.
///
private bool Drawn = false;
///
/// The default constructor
///
/// The parent window manager.
public Taskbar(WindowManager mangr)
{
this.Windows = new Window[0];
this.Manager = mangr;
this.Bounds = new BoundingBox(0, mangr.Size.X, mangr.Size.Y, mangr.Size.Y - TaskBarHeight);
this.Buffer = new Image(mangr.Size.X, WindowManager.TaskBarHeight + 1);
this.Buffer.Clear(TaskbarClearColor);
this.WindowButtonBounds = new BoundingBox[0];
this.TaskbarLocation = new Vec2(0, Manager.Size.Y - TaskBarHeight);
}
///
/// Adds the specified window to the taskbar.
///
/// The window to add.
public void AddWindow(Window w)
{
Window[] tmp = new Window[Windows.Length + 1];
Array.Copy(Windows, tmp, Windows.Length);
tmp[tmp.Length - 1] = w;
Windows = tmp;
Modified = true;
Drawn = false;
}
///
/// Removes the specified window from the taskbar.
///
/// The window to remove.
public void RemoveWindow(Window w)
{
uint i;
for (i = 0; i < Windows.Length; i++)
{
if (Windows[i] == w)
{
break;
}
}
Window[] tmp = new Window[Windows.Length - 1];
Array.Copy(Windows, tmp, i);
Array.Copy(Windows, i + 1, tmp, i, Windows.Length - i - 1);
Windows = tmp;
Modified = true;
Drawn = false;
}
///
/// Redraws the Buffer.
///
private void RedrawBuffer()
{
WindowButtonBounds = new BoundingBox[Windows.Length];
Buffer.Clear(TaskbarClearColor);
int loc = 20;
if (Windows.Length * (WindowButtonWidth + (2 * WindowButtonMargin)) < Manager.Size.X - 20)
{
#region No Dynamic Size
Vec2 tl;
Vec2 tr;
Vec2 br;
Vec2 bl;
Window w;
for (uint ind = 0; ind < Windows.Length; ind++)
{
w = Windows[ind];
tl = new Vec2(
loc + WindowButtonMargin,
(TaskBarHeight - (TaskBarHeight - 2 - WindowButtonMargin))
);
tr = new Vec2(
loc + WindowButtonMargin + WindowButtonWidth,
(TaskBarHeight - (TaskBarHeight - 2 - WindowButtonMargin))
);
br = new Vec2(
loc + WindowButtonMargin + WindowButtonWidth,
(TaskBarHeight - 2 - WindowButtonMargin)
);
bl = new Vec2(
loc + WindowButtonMargin,
(TaskBarHeight - 2 - WindowButtonMargin)
);
WindowButtonBounds[ind] = new BoundingBox(
loc + WindowButtonMargin,
loc + WindowButtonMargin + WindowButtonWidth,
Manager.Size.Y - (TaskBarHeight - (TaskBarHeight - 2 - WindowButtonMargin)),
Manager.Size.Y - (TaskBarHeight - 2 - WindowButtonMargin)
);
if (w.IsActiveWindow && w.CurrentState != WindowState.Minimized)
{
Buffer.DrawRectangle(tl, br, WindowActiveBackColor);
Buffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, WindowActiveLineColor);
}
else
{
Buffer.DrawRectangle(tl, br, WindowInactiveBackColor);
Buffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, WindowInactiveLineColor);
}
DrawWindowName(WindowButtonBounds[ind], w);
loc += WindowButtonMargin + WindowButtonMargin + WindowButtonWidth;
}
#endregion
}
else
{
#region Dynamic Size
uint len = (uint)Manager.Size.X - 20;
int ButtonWidth = (int)Math.Floor((double)((len / Windows.Length) - 2));
if (ButtonWidth > 5)
{
Vec2 tl;
Vec2 tr;
Vec2 br;
Vec2 bl;
Window w;
for (uint ind = 0; ind < Windows.Length; ind++)
{
w = Windows[ind];
tl = new Vec2(
loc + WindowButtonMargin,
(TaskBarHeight - (TaskBarHeight - 2 - WindowButtonMargin))
);
tr = new Vec2(
loc + WindowButtonMargin + ButtonWidth,
(TaskBarHeight - (TaskBarHeight - 2 - WindowButtonMargin))
);
br = new Vec2(
loc + WindowButtonMargin + ButtonWidth,
(TaskBarHeight - 2 - WindowButtonMargin)
);
bl = new Vec2(
loc + WindowButtonMargin,
(TaskBarHeight - 2 - WindowButtonMargin)
);
WindowButtonBounds[ind] = new BoundingBox(
loc + WindowButtonMargin,
loc + WindowButtonMargin + ButtonWidth,
Manager.Size.Y - (TaskBarHeight - (TaskBarHeight - 2 - WindowButtonMargin)),
Manager.Size.Y - (TaskBarHeight - 2 - WindowButtonMargin)
);
if (w.IsActiveWindow && w.CurrentState != WindowState.Minimized)
{
Buffer.DrawRectangle(tl, br, WindowActiveBackColor);
Buffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, WindowActiveLineColor);
}
else
{
Buffer.DrawRectangle(tl, br, WindowInactiveBackColor);
Buffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, WindowInactiveLineColor);
}
DrawWindowName(WindowButtonBounds[ind], w);
loc += WindowButtonMargin + WindowButtonMargin + ButtonWidth;
}
}
else
{
Buffer.DrawRectangle(new Vec2(24, 4), new Vec2(Buffer.Width - 10, Buffer.Height - 4), Colors.Cyan);
}
#endregion
}
Modified = false;
Drawn = true;
}
///
/// Draws the window's name on the taskbar,
/// using the specified bounds.
///
/// Bounds to use.
/// Window to draw.
private void DrawWindowName(BoundingBox bounds, Window w)
{
BoundingBox bnds = bounds - TaskbarLocation;
//throw new Exception();
//if (WindowManager.WindowFont.GetFontMetrics().StringWidth(w.Name) > bnds.Width - 6)
//{
// // Doesn't fit on the button, need to remove some characters.
// string s = w.Name.Substring(0, w.Name.Length - 3) + "...";
// while (WindowManager.WindowFont.GetFontMetrics().StringWidth(s) > bnds.Width - 6)
// {
// if (s.Length == 3)
// {
// s = "."; // button is to small to have a name drawn.
// break;
// }
// else
// {
// // It's 4 to make up for the 3 extra characters we add.
// s = s.Substring(0, s.Length - 4) + "...";
// }
// }
// //throw new Exception();
// Buffer.DrawString(new Vec2(bnds.Left + 2, bnds.Bottom + 2), s, WindowManager.WindowFont, 10, Orvid.Graphics.FontSupport.FontStyle.Normal, TaskbarTextColor);
//}
//else // Fits on button.
//{
// Buffer.DrawString(new Vec2(bnds.Left + 2, bnds.Bottom + 2), w.Name, WindowManager.WindowFont, 10, Orvid.Graphics.FontSupport.FontStyle.Normal, TaskbarTextColor);
//}
}
///
/// Draws the taskbar on the specified image.
///
/// The image to draw on.
public void Draw(Image i)
{
if (Modified)
{
RedrawBuffer();
}
i.DrawImage(TaskbarLocation, Buffer);
Drawn = true;
}
///
/// Undraws the over WindowButton.
///
/// Bounds of the window to undraw.
/// The window to undraw.
internal void UndrawOverButton(BoundingBox bounds, Window w)
{
Vec2 tl = new Vec2(bounds.Left, bounds.Bottom) - TaskbarLocation;
Vec2 tr = new Vec2(bounds.Right, bounds.Bottom) - TaskbarLocation;
Vec2 br = new Vec2(bounds.Right, bounds.Top) - TaskbarLocation;
Vec2 bl = new Vec2(bounds.Left, bounds.Top) - TaskbarLocation;
if (w.IsActiveWindow && w.CurrentState != WindowState.Minimized)
{
Buffer.DrawRectangle(tl, br, WindowActiveBackColor);
Buffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, WindowActiveLineColor);
}
else
{
Buffer.DrawRectangle(tl, br, WindowInactiveBackColor);
Buffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, WindowInactiveLineColor);
}
DrawWindowName(bounds, w);
WasOverButton = false;
}
///
/// Draws the over WindowButton.
///
/// The bounds of the window to draw.
/// The window to draw.
private void DrawOverButton(BoundingBox bounds, Window w)
{
Vec2 tl = new Vec2(bounds.Left, bounds.Bottom) - TaskbarLocation;
Vec2 tr = new Vec2(bounds.Right, bounds.Bottom) - TaskbarLocation;
Vec2 br = new Vec2(bounds.Right, bounds.Top) - TaskbarLocation;
Vec2 bl = new Vec2(bounds.Left, bounds.Top) - TaskbarLocation;
if (w.IsActiveWindow && w.CurrentState != WindowState.Minimized)
{
Buffer.DrawRectangle(tl, br, WindowActiveOverBackColor);
Buffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, WindowActiveLineColor);
}
else
{
Buffer.DrawRectangle(tl, br, WindowInactiveOverBackColor);
Buffer.DrawLines(new Vec2[] { tl, tr, br, bl, tl }, WindowInactiveLineColor);
}
DrawWindowName(bounds, w);
WasOverButton = true;
}
///
/// Processes the mouse move event.
///
/// Location of the mouse.
internal void DoMouseMove(Vec2 loc)
{
if (!Drawn)
{
RedrawBuffer();
}
if (!WasOverButton)
{
for (int i = 0; i < Windows.Length; i++)
{
if (WindowButtonBounds[i].IsInBounds(loc))
{
DrawOverButton(WindowButtonBounds[i], Windows[i]);
overButtonIndx = i;
return;
}
}
}
else
{
if (!WindowButtonBounds[overButtonIndx].IsInBounds(loc) || !DrawnOverButton)
{
UndrawOverButton(WindowButtonBounds[overButtonIndx], Windows[overButtonIndx]);
for (int i = 0; i < Windows.Length; i++)
{
if (WindowButtonBounds[i].IsInBounds(loc))
{
DrawOverButton(WindowButtonBounds[i], Windows[i]);
overButtonIndx = i;
return;
}
}
overButtonIndx = 0;
DrawnOverButton = true;
return;
}
}
}
///
/// Processes a click event.
///
/// The location of the mouse.
/// The buttons that are pressed.
internal void DoClick(Vec2 loc, MouseButtons buttons)
{
if (!Drawn)
{
RedrawBuffer();
}
if (WasOverButton)
{
if (WindowButtonBounds[overButtonIndx].IsInBounds(loc))
{
if (Windows[overButtonIndx].IsActiveWindow)
{
Manager.MinimizeWindow(Windows[overButtonIndx]);
}
else if (Windows[overButtonIndx].CurrentState == WindowState.Minimized)
{
Manager.RestoreWindow(Windows[overButtonIndx]);
}
else
{
Manager.BringWindowToFront(Windows[overButtonIndx]);
}
DrawnOverButton = false;
DoMouseMove(loc);
}
else
{
for (int i = 0; i < Windows.Length; i++)
{
if (WindowButtonBounds[i].IsInBounds(loc))
{
DrawOverButton(WindowButtonBounds[i], Windows[i]);
overButtonIndx = i;
DrawnOverButton = false;
if (Windows[i].IsActiveWindow)
{
Manager.MinimizeWindow(Windows[i]);
}
else if (Windows[i].CurrentState == WindowState.Minimized)
{
Manager.RestoreWindow(Windows[i]);
}
else
{
Manager.BringWindowToFront(Windows[i]);
}
DoMouseMove(loc);
return;
}
}
}
}
else
{
for (int i = 0; i < Windows.Length; i++)
{
if (WindowButtonBounds[i].IsInBounds(loc))
{
DrawOverButton(WindowButtonBounds[i], Windows[i]);
overButtonIndx = i;
DrawnOverButton = false;
if (Windows[i].IsActiveWindow)
{
Manager.MinimizeWindow(Windows[i]);
}
else if (Windows[i].CurrentState == WindowState.Minimized)
{
Manager.RestoreWindow(Windows[i]);
}
else
{
Manager.BringWindowToFront(Windows[i]);
}
DoMouseMove(loc);
return;
}
}
}
}
}
}