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; } } } } } }