//////////////////////////////////////////////////////////////// // // // Neoforce Controls // // // //////////////////////////////////////////////////////////////// // // // File: Console.cs // // // // Version: 0.7 // // // // Date: 11/09/2010 // // // // Author: Tom Shane // // // //////////////////////////////////////////////////////////////// // // // Copyright (c) by Tom Shane // // // //////////////////////////////////////////////////////////////// #region //// Using ///////////// //////////////////////////////////////////////////////////////////////////// using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.Collections; using System.Collections.Generic; using Microsoft.Xna.Framework.GamerServices; //////////////////////////////////////////////////////////////////////////// #endregion namespace TomShane.Neoforce.Controls { public struct ConsoleMessage { public string Text; public byte Channel; public DateTime Time; public string Sender; public ConsoleMessage(string sender, string text, byte channel) { this.Text = text; this.Channel = channel; this.Time = DateTime.Now; this.Sender = sender; } } public class ChannelList : EventedList { #region //// Indexers ////////// //////////////////////////////////////////////////////////////////////////// public ConsoleChannel this[string name] { get { for (int i = 0; i < this.Count; i++) { ConsoleChannel s = (ConsoleChannel)this[i]; if (s.Name.ToLower() == name.ToLower()) { return s; } } return default(ConsoleChannel); } set { for (int i = 0; i < this.Count; i++) { ConsoleChannel s = (ConsoleChannel)this[i]; if (s.Name.ToLower() == name.ToLower()) { this[i] = value; } } } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public ConsoleChannel this[byte index] { get { for (int i = 0; i < this.Count; i++) { ConsoleChannel s = (ConsoleChannel)this[i]; if (s.Index == index) { return s; } } return default(ConsoleChannel); } set { for (int i = 0; i < this.Count; i++) { ConsoleChannel s = (ConsoleChannel)this[i]; if (s.Index == index) { this[i] = value; } } } } //////////////////////////////////////////////////////////////////////////// #endregion } public class ConsoleChannel { private string name; private byte index; private Color color; public ConsoleChannel(byte index, string name, Color color) { this.name = name; this.index = index; this.color = color; } public virtual byte Index { get { return index; } set { index = value; } } public virtual Color Color { get { return color; } set { color = value; } } public virtual string Name { get { return name; } set { name = value; } } } [Flags] public enum ConsoleMessageFormats { None = 0x00, ChannelName = 0x01, TimeStamp = 0x02, Sender = 0x03, All = Sender | ChannelName | TimeStamp } public class Console : Container { #region //// Fields //////////// //////////////////////////////////////////////////////////////////////////// private TextBox txtMain = null; private ComboBox cmbMain; private EventedList buffer = new EventedList(); private ChannelList channels = new ChannelList(); private List filter = new List(); private ConsoleMessageFormats messageFormat = ConsoleMessageFormats.None; private bool channelsVisible = true; private bool textBoxVisible = true; private string sender; //////////////////////////////////////////////////////////////////////////// #endregion #region //// Properties //////// public string Sender { get { return sender; } set { sender = value; } } //////////////////////////////////////////////////////////////////////////// public virtual EventedList MessageBuffer { get { return buffer; } set { buffer.ItemAdded -= new EventHandler(buffer_ItemAdded); buffer = value; buffer.ItemAdded += new EventHandler(buffer_ItemAdded); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual ChannelList Channels { get { return channels; } set { channels.ItemAdded -= new EventHandler(channels_ItemAdded); channels = value; channels.ItemAdded += new EventHandler(channels_ItemAdded); channels_ItemAdded(null, null); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual List ChannelFilter { get { return filter; } set { filter = value; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual byte SelectedChannel { set { cmbMain.Text = channels[value].Name; } get { return channels[cmbMain.Text].Index; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual ConsoleMessageFormats MessageFormat { get { return messageFormat; } set { messageFormat = value; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual bool ChannelsVisible { get { return channelsVisible; } set { cmbMain.Visible = channelsVisible = value; if (value && !textBoxVisible) TextBoxVisible = false; PositionControls(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual bool TextBoxVisible { get { return textBoxVisible; } set { txtMain.Visible = textBoxVisible = value; txtMain.Focused = true; if (!value && channelsVisible) ChannelsVisible = false; PositionControls(); } } //////////////////////////////////////////////////////////////////////////// #endregion #region //// Events //////////// //////////////////////////////////////////////////////////////////////////// public event ConsoleMessageEventHandler MessageSent; //////////////////////////////////////////////////////////////////////////// #endregion #region //// Construstors ////// //////////////////////////////////////////////////////////////////////////// public Console(Manager manager) : base(manager) { Width = 320; Height = 160; MinimumHeight = 64; MinimumWidth = 64; CanFocus = false; Resizable = false; Movable = false; cmbMain = new ComboBox(manager); cmbMain.Init(); cmbMain.Top = Height - cmbMain.Height; cmbMain.Left = 0; cmbMain.Width = 128; cmbMain.Anchor = Anchors.Left | Anchors.Bottom; cmbMain.Detached = false; cmbMain.DrawSelection = false; cmbMain.Visible = channelsVisible; Add(cmbMain, false); txtMain = new TextBox(manager); txtMain.Init(); txtMain.Top = Height - txtMain.Height; txtMain.Left = cmbMain.Width + 1; txtMain.Anchor = Anchors.Left | Anchors.Bottom | Anchors.Right; txtMain.Detached = false; txtMain.Visible = textBoxVisible; txtMain.KeyDown += new KeyEventHandler(txtMain_KeyDown); txtMain.GamePadDown += new GamePadEventHandler(txtMain_GamePadDown); txtMain.FocusGained += new EventHandler(txtMain_FocusGained); Add(txtMain, false); VerticalScrollBar.Top = 2; VerticalScrollBar.Left = Width - 18; VerticalScrollBar.Range = 1; VerticalScrollBar.PageSize = 1; VerticalScrollBar.ValueChanged += new EventHandler(VerticalScrollBar_ValueChanged); VerticalScrollBar.Visible = true; ClientArea.Draw += new DrawEventHandler(ClientArea_Draw); buffer.ItemAdded += new EventHandler(buffer_ItemAdded); channels.ItemAdded += new EventHandler(channels_ItemAdded); channels.ItemRemoved += new EventHandler(channels_ItemRemoved); PositionControls(); } //////////////////////////////////////////////////////////////////////////// #endregion #region //// Methods /////////// //////////////////////////////////////////////////////////////////////////// private void PositionControls() { if (txtMain != null) { txtMain.Left = channelsVisible ? cmbMain.Width + 1 : 0; txtMain.Width = channelsVisible ? Width - cmbMain.Width - 1 : Width; if (textBoxVisible) { ClientMargins = new Margins(Skin.ClientMargins.Left, Skin.ClientMargins.Top + 4, VerticalScrollBar.Width + 6, txtMain.Height + 4); VerticalScrollBar.Height = Height - txtMain.Height - 5; } else { ClientMargins = new Margins(Skin.ClientMargins.Left, Skin.ClientMargins.Top + 4, VerticalScrollBar.Width + 6, 2); VerticalScrollBar.Height = Height - 4; } Invalidate(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public override void Init() { base.Init(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected internal override void InitSkin() { base.InitSkin(); Skin = new SkinControl(Manager.Skin.Controls["Console"]); PositionControls(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected internal override void Update(GameTime gameTime) { base.Update(gameTime); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void ClientArea_Draw(object sender, DrawEventArgs e) { SpriteFont font = Skin.Layers[0].Text.Font.Resource; Rectangle r = new Rectangle(e.Rectangle.Left, e.Rectangle.Top, e.Rectangle.Width, e.Rectangle.Height); int pos = 0; if (buffer.Count > 0) { EventedList b = GetFilteredBuffer(filter); int c = b.Count; int s = (VerticalScrollBar.Value + VerticalScrollBar.PageSize); int f = s - VerticalScrollBar.PageSize; if (b.Count > 0) { for (int i = s - 1; i >= f; i--) { { int x = 4; int y = r.Bottom - (pos + 1) * ((int)font.LineSpacing + 0); string msg = ((ConsoleMessage)b[i]).Text; string pre = ""; ConsoleChannel ch = (channels[((ConsoleMessage)b[i]).Channel] as ConsoleChannel); if ((messageFormat & ConsoleMessageFormats.ChannelName) == ConsoleMessageFormats.ChannelName) { pre += string.Format("[{0}]", channels[((ConsoleMessage)b[i]).Channel].Name); } if ((messageFormat & ConsoleMessageFormats.Sender) == ConsoleMessageFormats.Sender) { pre += string.Format("[{0}]", ((ConsoleMessage)b[i]).Sender); } if ((messageFormat & ConsoleMessageFormats.TimeStamp) == ConsoleMessageFormats.TimeStamp) { pre = string.Format("[{0}]", ((ConsoleMessage)b[i]).Time.ToLongTimeString()) + pre; } if (pre != "") msg = pre + ": " + msg; e.Renderer.DrawString(font, msg, x, y, ch.Color); pos += 1; } } } } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void DrawControl(Renderer renderer, Rectangle rect, GameTime gameTime) { int h = txtMain.Visible ? (txtMain.Height + 1) : 0; Rectangle r = new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height - h); base.DrawControl(renderer, r, gameTime); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void txtMain_FocusGained(object sender, EventArgs e) { ConsoleChannel ch = channels[cmbMain.Text]; if (ch != null) txtMain.TextColor = ch.Color; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void txtMain_KeyDown(object sender, KeyEventArgs e) { SendMessage(e); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void txtMain_GamePadDown(object sender, GamePadEventArgs e) { SendMessage(e); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private void SendMessage(EventArgs x) { if (Manager.UseGuide && Guide.IsVisible) return; KeyEventArgs k = new KeyEventArgs(); GamePadEventArgs g = new GamePadEventArgs(PlayerIndex.One); if (x is KeyEventArgs) k = x as KeyEventArgs; else if (x is GamePadEventArgs) g = x as GamePadEventArgs; ConsoleChannel ch = channels[cmbMain.Text]; if (ch != null) { txtMain.TextColor = ch.Color; string message = txtMain.Text; if ((k.Key == Microsoft.Xna.Framework.Input.Keys.Enter || g.Button == GamePadActions.Press) && message != null && message != "") { x.Handled = true; ConsoleMessageEventArgs me = new ConsoleMessageEventArgs(new ConsoleMessage(sender, message, ch.Index)); OnMessageSent(me); buffer.Add(new ConsoleMessage(sender, me.Message.Text, me.Message.Channel)); txtMain.Text = ""; ClientArea.Invalidate(); CalcScrolling(); } } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected virtual void OnMessageSent(ConsoleMessageEventArgs e) { if (MessageSent != null) MessageSent.Invoke(this, e); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void channels_ItemAdded(object sender, EventArgs e) { cmbMain.Items.Clear(); for (int i = 0; i < channels.Count; i++) { cmbMain.Items.Add((channels[i] as ConsoleChannel).Name); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void channels_ItemRemoved(object sender, EventArgs e) { cmbMain.Items.Clear(); for (int i = 0; i < channels.Count; i++) { cmbMain.Items.Add((channels[i] as ConsoleChannel).Name); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void buffer_ItemAdded(object sender, EventArgs e) { CalcScrolling(); ClientArea.Invalidate(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private void CalcScrolling() { if (VerticalScrollBar != null) { int line = Skin.Layers[0].Text.Font.Resource.LineSpacing; int c = GetFilteredBuffer(filter).Count; int p = (int)Math.Ceiling(ClientArea.ClientHeight / (float)line); VerticalScrollBar.Range = c == 0 ? 1 : c; VerticalScrollBar.PageSize = c == 0 ? 1 : p; VerticalScrollBar.Value = VerticalScrollBar.Range; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void VerticalScrollBar_ValueChanged(object sender, EventArgs e) { ClientArea.Invalidate(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void OnResize(ResizeEventArgs e) { CalcScrolling(); base.OnResize(e); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private EventedList GetFilteredBuffer(List filter) { EventedList ret = new EventedList(); if (filter.Count > 0) { for (int i = 0; i < buffer.Count; i++) { if (filter.Contains(((ConsoleMessage)buffer[i]).Channel)) { ret.Add(buffer[i]); } } return ret; } else return buffer; } //////////////////////////////////////////////////////////////////////////// #endregion } }