594 lines
22 KiB
C#
594 lines
22 KiB
C#
////////////////////////////////////////////////////////////////
|
|
// //
|
|
// 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;
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#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<ConsoleChannel>
|
|
{
|
|
|
|
#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<ConsoleMessage> buffer = new EventedList<ConsoleMessage>();
|
|
private ChannelList channels = new ChannelList();
|
|
private List<byte> filter = new List<byte>();
|
|
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<ConsoleMessage> 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<byte> 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<ConsoleMessage> 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)
|
|
{
|
|
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<ConsoleMessage> GetFilteredBuffer(List<byte> filter)
|
|
{
|
|
EventedList<ConsoleMessage> ret = new EventedList<ConsoleMessage>();
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|