//////////////////////////////////////////////////////////////// // // // Neoforce Controls // // // //////////////////////////////////////////////////////////////// // // // File: TextBox.cs // // // // Version: 0.7 // // // // Date: 11/09/2010 // // // // Author: Tom Shane // // // //////////////////////////////////////////////////////////////// // // // Copyright (c) by Tom Shane // // // //////////////////////////////////////////////////////////////// #region //// Using ///////////// using Microsoft.Xna.Framework; //////////////////////////////////////////////////////////////////////////// using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using System; using System.Text; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using Microsoft.Xna.Framework.GamerServices; //////////////////////////////////////////////////////////////////////////// #endregion namespace TomShane.Neoforce.Controls { #region //// Enums ///////////// //////////////////////////////////////////////////////////////////////////// public enum TextBoxMode { Normal, Password, Multiline } //////////////////////////////////////////////////////////////////////////// #endregion #region //// Classes /////////// //////////////////////////////////////////////////////////////////////////// public class TextBox : ClipControl { #region //// Structs /////////// //////////////////////////////////////////////////////////////////////////// private struct Selection { private int start; private int end; public int Start { get { if (start > end && start != -1 && end != -1) return end; else return start; } set { start = value; } } public int End { get { if (end < start && start != -1 && end != -1) return start; else return end; } set { end = value; } } public bool IsEmpty { get { return Start == -1 && End == -1; } } public int Length { get { return IsEmpty ? 0 : (End - Start); } } public Selection(int start, int end) { this.start = start; this.end = end; } public void Clear() { Start = -1; End = -1; } } //////////////////////////////////////////////////////////////////////////// #endregion #region //// Consts //////////// //////////////////////////////////////////////////////////////////////////// private const string skTextBox = "TextBox"; private const string lrTextBox = "Control"; private const string lrCursor = "Cursor"; private const string crDefault = "Default"; private const string crText = "Text"; //////////////////////////////////////////////////////////////////////////// #endregion #region //// Fields //////////// //////////////////////////////////////////////////////////////////////////// private bool showCursor = false; private double flashTime = 0; private int posx = 0; private int posy = 0; private char passwordChar = '•'; private TextBoxMode mode = TextBoxMode.Normal; private string shownText = ""; private bool readOnly = false; private bool drawBorders = true; private Selection selection = new Selection(-1, -1); private bool caretVisible = true; private ScrollBar horz = null; private ScrollBar vert = null; private List lines = new List(); private int linesDrawn = 0; private int charsDrawn = 0; private SpriteFont font = null; private bool wordWrap = false; private ScrollBars scrollBars = ScrollBars.Both; private string Separator = "\n"; private string text = ""; private string buffer = ""; private bool autoSelection = true; //////////////////////////////////////////////////////////////////////////// #endregion #region //// Properties //////// //////////////////////////////////////////////////////////////////////////// private int PosX { get { return posx; } set { posx = value; if (posx < 0) posx = 0; if (posx > Lines[PosY].Length) posx = Lines[PosY].Length; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int PosY { get { return posy; } set { posy = value; if (posy < 0) posy = 0; if (posy > Lines.Count - 1) posy = Lines.Count - 1; PosX = PosX; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int Pos { get { return GetPos(PosX, PosY); } set { PosY = GetPosY(value); PosX = GetPosX(value); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// //>>>> public virtual bool WordWrap { get { return wordWrap; } set { wordWrap = value; if (ClientArea != null) ClientArea.Invalidate(); SetupBars(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual ScrollBars ScrollBars { get { return scrollBars; } set { scrollBars = value; SetupBars(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual char PasswordChar { get { return passwordChar; } set { passwordChar = value; if (ClientArea != null) ClientArea.Invalidate(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual bool CaretVisible { get { return caretVisible; } set { caretVisible = value; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual TextBoxMode Mode { get { return mode; } set { if (value != TextBoxMode.Multiline) { Text = Text.Replace(Separator, ""); } mode = value; selection.Clear(); if (ClientArea != null) ClientArea.Invalidate(); SetupBars(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual bool ReadOnly { get { return readOnly; } set { readOnly = value; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual bool DrawBorders { get { return drawBorders; } set { drawBorders = value; if (ClientArea != null) ClientArea.Invalidate(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual int CursorPosition { get { return Pos; } set { Pos = value; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual string SelectedText { get { if (selection.IsEmpty) { return ""; } else { return Text.Substring(selection.Start, selection.Length); } } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual int SelectionStart { get { if (selection.IsEmpty) { return Pos; } else { return selection.Start; } } set { Pos = value; if (Pos < 0) Pos = 0; if (Pos > Text.Length) Pos = Text.Length; selection.Start = Pos; if (selection.End == -1) selection.End = Pos; ClientArea.Invalidate(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual bool AutoSelection { get { return autoSelection; } set { autoSelection = value; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual int SelectionLength { get { return selection.Length; } set { if (value == 0) { selection.End = selection.Start; } else if (selection.IsEmpty) { selection.Start = 0; selection.End = value; } else if (!selection.IsEmpty) { selection.End = selection.Start + value; } if (!selection.IsEmpty) { if (selection.Start < 0) selection.Start = 0; if (selection.Start > Text.Length) selection.Start = Text.Length; if (selection.End < 0) selection.End = 0; if (selection.End > Text.Length) selection.End = Text.Length; } ClientArea.Invalidate(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private List Lines { get { return lines; } set { lines = value; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public override string Text { get { return text; } set { if (wordWrap) value = WrapWords(value, ClientWidth); if (mode != TextBoxMode.Multiline && value != null) { value = value.Replace(Separator, ""); } text = value; if (!Suspended) OnTextChanged(new EventArgs()); lines = SplitLines(text); if (ClientArea != null) ClientArea.Invalidate(); SetupBars(); ProcessScrolling(); } } //////////////////////////////////////////////////////////////////////////// #endregion #region //// Construstors ////// //////////////////////////////////////////////////////////////////////////// public TextBox(Manager manager) : base(manager) { CheckLayer(Skin, lrCursor); SetDefaultSize(128, 20); Lines.Add(""); ClientArea.Draw += new DrawEventHandler(ClientArea_Draw); vert = new ScrollBar(manager, Orientation.Vertical); horz = new ScrollBar(manager, Orientation.Horizontal); } //////////////////////////////////////////////////////////////////////////// #endregion #region //// Methods /////////// //////////////////////////////////////////////////////////////////////////// public override void Init() { base.Init(); vert.Init(); vert.Range = 1; vert.PageSize = 1; vert.Value = 0; vert.Anchor = Anchors.Top | Anchors.Right | Anchors.Bottom; vert.ValueChanged += new EventHandler(sb_ValueChanged); horz.Init(); horz.Range = ClientArea.Width; horz.PageSize = ClientArea.Width; horz.Value = 0; horz.Anchor = Anchors.Right | Anchors.Left | Anchors.Bottom; horz.ValueChanged += new EventHandler(sb_ValueChanged); horz.Visible = false; vert.Visible = false; Add(vert, false); Add(horz, false); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected internal override void InitSkin() { base.InitSkin(); Skin = new SkinControl(Manager.Skin.Controls[skTextBox]); #if (!XBOX && !XBOX_FAKE) Cursor = Manager.Skin.Cursors[crText].Resource; #endif font = (Skin.Layers[lrTextBox].Text != null) ? Skin.Layers[lrTextBox].Text.Font.Resource : null; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void DrawControl(Renderer renderer, Rectangle rect, GameTime gameTime) { if (drawBorders) { base.DrawControl(renderer, rect, gameTime); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int GetFitChars(string text, int width) { int ret = text.Length; int size = 0; for (int i = 0; i < text.Length; i++) { size = (int)font.MeasureString(text.Substring(0, i)).X; if (size > width) { ret = i; break; } } return ret; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private void DeterminePages() { if (ClientArea != null) { int sizey = (int)font.LineSpacing; linesDrawn = (int)(ClientArea.Height / sizey); if (linesDrawn > Lines.Count) linesDrawn = Lines.Count; charsDrawn = ClientArea.Width - 1; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private string GetMaxLine() { int max = 0; int x = 0; for (int i = 0; i < Lines.Count; i++) { if (Lines[i].Length > max) { max = Lines[i].Length; x = i; } } return Lines.Count > 0 ? Lines[x] : ""; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void ClientArea_Draw(object sender, DrawEventArgs e) { SkinLayer layer = Skin.Layers[lrTextBox]; Color col = Skin.Layers[lrTextBox].Text.Colors.Enabled; SkinLayer cursor = Skin.Layers[lrCursor]; Alignment al = mode == TextBoxMode.Multiline ? Alignment.TopLeft : Alignment.MiddleLeft; Renderer renderer = e.Renderer; Rectangle r = e.Rectangle; bool drawsel = !selection.IsEmpty; string tmpText = ""; font = (Skin.Layers[lrTextBox].Text != null) ? Skin.Layers[lrTextBox].Text.Font.Resource : null; if (Text != null && font != null) { DeterminePages(); if (mode == TextBoxMode.Multiline) { shownText = Text; tmpText = Lines[PosY]; } else if (mode == TextBoxMode.Password) { shownText = ""; for (int i = 0; i < Text.Length; i++) { shownText = shownText + passwordChar; } tmpText = shownText; } else { shownText = Text; tmpText = Lines[PosY]; } if (TextColor != UndefinedColor && ControlState != ControlState.Disabled) { col = TextColor; } if (mode != TextBoxMode.Multiline) { linesDrawn = 0; vert.Value = 0; } if (drawsel) { DrawSelection(e.Renderer, r); /* renderer.End(); renderer.SpriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None); renderer.SpriteBatch.GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = true; renderer.SpriteBatch.GraphicsDevice.RenderState.SourceBlend = Blend.DestinationColor; renderer.SpriteBatch.GraphicsDevice.RenderState.DestinationBlend = Blend.SourceColor; renderer.SpriteBatch.GraphicsDevice.RenderState.BlendFunction = BlendFunction.Subtract; //renderer.SpriteBatch.GraphicsDevice.RenderState.AlphaFunction = CompareFunction.Equal; //renderer.SpriteBatch.GraphicsDevice.RenderState.AlphaSourceBlend = Blend.One; //renderer.SpriteBatch.GraphicsDevice.RenderState.AlphaDestinationBlend = Blend.DestinationAlpha; */ } int sizey = (int)font.LineSpacing; if (showCursor && caretVisible) { Vector2 size = Vector2.Zero; if (PosX > 0 && PosX <= tmpText.Length) { size = font.MeasureString(tmpText.Substring(0, PosX)); } if (size.Y == 0) { size = font.MeasureString(" "); size.X = 0; } int m = r.Height - font.LineSpacing; Rectangle rc = new Rectangle(r.Left - horz.Value + (int)size.X, r.Top + m / 2, cursor.Width, font.LineSpacing); if (mode == TextBoxMode.Multiline) { rc = new Rectangle(r.Left + (int)size.X - horz.Value, r.Top + (int)((PosY - vert.Value) * font.LineSpacing), cursor.Width, font.LineSpacing); } cursor.Alignment = al; renderer.DrawLayer(cursor, rc, col, 0); } for (int i = 0; i < linesDrawn + 1; i++) { int ii = i + vert.Value; if (ii >= Lines.Count || ii < 0) break; if (Lines[ii] != "") { if (mode == TextBoxMode.Multiline) { renderer.DrawString(font, Lines[ii], r.Left - horz.Value, r.Top + (i * sizey), col); } else { Rectangle rx = new Rectangle(r.Left - horz.Value, r.Top, r.Width, r.Height); renderer.DrawString(font, shownText, rx, col, al, false); } } } /* if (drawsel) { renderer.End(); renderer.Begin(BlendingMode.Premultiplied); }*/ } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int GetStringWidth(string text, int count) { if (count > text.Length) count = text.Length; return (int)font.MeasureString(text.Substring(0, count)).X; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private void ProcessScrolling() { if (vert != null && horz != null) { vert.PageSize = linesDrawn; horz.PageSize = charsDrawn; if (horz.PageSize > horz.Range) horz.PageSize = horz.Range; if (PosY >= vert.Value + vert.PageSize) { vert.Value = (PosY + 1) - vert.PageSize; } else if (PosY < vert.Value) { vert.Value = PosY; } if (GetStringWidth(Lines[PosY], PosX) >= horz.Value + horz.PageSize) { horz.Value = (GetStringWidth(Lines[PosY], PosX) + 1) - horz.PageSize; } else if (GetStringWidth(Lines[PosY], PosX) < horz.Value) { horz.Value = GetStringWidth(Lines[PosY], PosX) - horz.PageSize; } } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private void DrawSelection(Renderer renderer, Rectangle rect) { if (!selection.IsEmpty) { int s = selection.Start; int e = selection.End; int sl = GetPosY(s); int el = GetPosY(e); int sc = GetPosX(s); int ec = GetPosX(e); int hgt = font.LineSpacing; int start = sl; int end = el; if (start < vert.Value) start = vert.Value; if (end > vert.Value + linesDrawn) end = vert.Value + linesDrawn; for (int i = start; i <= end; i++) { Rectangle r = Rectangle.Empty; if (mode == TextBoxMode.Normal) { int m = ClientArea.Height - font.LineSpacing; r = new Rectangle(rect.Left - horz.Value + (int)font.MeasureString(Lines[i].Substring(0, sc)).X, rect.Top + m / 2, (int)font.MeasureString(Lines[i].Substring(0, ec + 0)).X - (int)font.MeasureString(Lines[i].Substring(0, sc)).X, hgt); } else if (sl == el) { r = new Rectangle(rect.Left - horz.Value + (int)font.MeasureString(Lines[i].Substring(0, sc)).X, rect.Top + (i - vert.Value) * hgt, (int)font.MeasureString(Lines[i].Substring(0, ec + 0)).X - (int)font.MeasureString(Lines[i].Substring(0, sc)).X, hgt); } else { if (i == sl) r = new Rectangle(rect.Left - horz.Value + (int)font.MeasureString(Lines[i].Substring(0, sc)).X, rect.Top + (i - vert.Value) * hgt, (int)font.MeasureString(Lines[i]).X - (int)font.MeasureString(Lines[i].Substring(0, sc)).X, hgt); else if (i == el) r = new Rectangle(rect.Left - horz.Value, rect.Top + (i - vert.Value) * hgt, (int)font.MeasureString(Lines[i].Substring(0, ec + 0)).X, hgt); else r = new Rectangle(rect.Left - horz.Value, rect.Top + (i - vert.Value) * hgt, (int)font.MeasureString(Lines[i]).X, hgt); } renderer.Draw(Manager.Skin.Images["Control"].Resource, r, Color.FromNonPremultiplied(160, 160, 160, 128)); } } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected internal override void Update(GameTime gameTime) { base.Update(gameTime); bool sc = showCursor; showCursor = Focused; if (Focused) { flashTime += gameTime.ElapsedGameTime.TotalSeconds; showCursor = flashTime < 0.5; if (flashTime > 1) flashTime = 0; } if (sc != showCursor) ClientArea.Invalidate(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int FindPrevWord(string text) { bool letter = false; int p = Pos - 1; if (p < 0) p = 0; if (p >= text.Length) p = text.Length - 1; for (int i = p; i >= 0; i--) { if (char.IsLetterOrDigit(text[i])) { letter = true; continue; } if (letter && !char.IsLetterOrDigit(text[i])) { return i + 1; } } return 0; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int FindNextWord(string text) { bool space = false; for (int i = Pos; i < text.Length - 1; i++) { if (!char.IsLetterOrDigit(text[i])) { space = true; continue; } if (space && char.IsLetterOrDigit(text[i])) { return i; } } return text.Length; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int GetPosY(int pos) { if (pos >= Text.Length) return Lines.Count - 1; int p = pos; for (int i = 0; i < Lines.Count; i++) { p -= Lines[i].Length + Separator.Length; if (p < 0) { p = p + Lines[i].Length + Separator.Length; return i; } } return 0; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int GetPosX(int pos) { if (pos >= Text.Length) return Lines[Lines.Count - 1].Length; int p = pos; for (int i = 0; i < Lines.Count; i++) { p -= Lines[i].Length + Separator.Length; if (p < 0) { p = p + Lines[i].Length + Separator.Length; return p; } } return 0; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int GetPos(int x, int y) { int p = 0; for (int i = 0; i < y; i++) { p += Lines[i].Length + Separator.Length; } p += x; return p; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private int CharAtPos(Point pos) { int x = pos.X; int y = pos.Y; int px = 0; int py = 0; if (mode == TextBoxMode.Multiline) { py = vert.Value + (int)((y - ClientTop) / font.LineSpacing); if (py < 0) py = 0; if (py >= Lines.Count) py = Lines.Count - 1; } else { py = 0; } string str = mode == TextBoxMode.Multiline ? Lines[py] : shownText; if (str != null && str != "") { for (int i = 1; i <= Lines[py].Length; i++) { Vector2 v = font.MeasureString(str.Substring(0, i)) - (font.MeasureString(str[i - 1].ToString()) / 3); if (x <= (ClientLeft + (int)v.X) - horz.Value) { px = i - 1; break; } } if (x > ClientLeft + ((int)font.MeasureString(str).X) - horz.Value - (font.MeasureString(str[str.Length - 1].ToString()).X / 3)) px = str.Length; } return GetPos(px, py); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); flashTime = 0; Pos = CharAtPos(e.Position); selection.Clear(); if (e.Button == MouseButton.Left && caretVisible && mode != TextBoxMode.Password) { selection.Start = Pos; selection.End = Pos; } ClientArea.Invalidate(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); if (e.Button == MouseButton.Left && !selection.IsEmpty && mode != TextBoxMode.Password && selection.Length < Text.Length) { int pos = CharAtPos(e.Position); selection.End = CharAtPos(e.Position); Pos = pos; ClientArea.Invalidate(); ProcessScrolling(); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (e.Button == MouseButton.Left && !selection.IsEmpty && mode != TextBoxMode.Password) { if (selection.Length == 0) selection.Clear(); } } //////////////////////////////////////////////////////////////////////////// protected override void OnMouseScroll(MouseEventArgs e) { if (Mode != TextBoxMode.Multiline) { base.OnMouseScroll(e); return; } if (e.ScrollDirection == MouseScrollDirection.Down) vert.ScrollDown(); else vert.ScrollUp(); base.OnMouseScroll(e); } //////////////////////////////////////////////////////////////////////////// protected override void OnKeyPress(KeyEventArgs e) { flashTime = 0; if (Manager.UseGuide && Guide.IsVisible) return; if (!e.Handled) { if (e.Key == Keys.A && e.Control && mode != TextBoxMode.Password) { SelectAll(); } if (e.Key == Keys.Up) { e.Handled = true; if (e.Shift && selection.IsEmpty && mode != TextBoxMode.Password) { selection.Start = Pos; } if (!e.Control) { PosY -= 1; } } else if (e.Key == Keys.Down) { e.Handled = true; if (e.Shift && selection.IsEmpty && mode != TextBoxMode.Password) { selection.Start = Pos; } if (!e.Control) { PosY += 1; } } else if (e.Key == Keys.Back && !readOnly) { e.Handled = true; if (!selection.IsEmpty) { Text = Text.Remove(selection.Start, selection.Length); Pos = selection.Start; } else if (Text.Length > 0 && Pos > 0) { Pos -= 1; Text = Text.Remove(Pos, 1); } selection.Clear(); } else if (e.Key == Keys.Delete && !readOnly) { e.Handled = true; if (!selection.IsEmpty) { Text = Text.Remove(selection.Start, selection.Length); Pos = selection.Start; } else if (Pos < Text.Length) { Text = Text.Remove(Pos, 1); } selection.Clear(); } else if (e.Key == Keys.Left) { e.Handled = true; if (e.Shift && selection.IsEmpty && mode != TextBoxMode.Password) { selection.Start = Pos; } if (!e.Control) { Pos -= 1; } if (e.Control) { Pos = FindPrevWord(shownText); } } else if (e.Key == Keys.Right) { e.Handled = true; if (e.Shift && selection.IsEmpty && mode != TextBoxMode.Password) { selection.Start = Pos; } if (!e.Control) { Pos += 1; } if (e.Control) { Pos = FindNextWord(shownText); } } else if (e.Key == Keys.Home) { e.Handled = true; if (e.Shift && selection.IsEmpty && mode != TextBoxMode.Password) { selection.Start = Pos; } if (!e.Control) { PosX = 0; } if (e.Control) { Pos = 0; } } else if (e.Key == Keys.End) { e.Handled = true; if (e.Shift && selection.IsEmpty && mode != TextBoxMode.Password) { selection.Start = Pos; } if (!e.Control) { PosX = Lines[PosY].Length; } if (e.Control) { Pos = Text.Length; } } else if (e.Key == Keys.PageUp) { e.Handled = true; if (e.Shift && selection.IsEmpty && mode != TextBoxMode.Password) { selection.Start = Pos; } if (!e.Control) { PosY -= linesDrawn; } } else if (e.Key == Keys.PageDown) { e.Handled = true; if (e.Shift && selection.IsEmpty && mode != TextBoxMode.Password) { selection.Start = Pos; } if (!e.Control) { PosY += linesDrawn; } } else if (e.Key == Keys.Enter && mode == TextBoxMode.Multiline && !readOnly) { e.Handled = true; Text = Text.Insert(Pos, Separator); PosX = 0; PosY += 1; } else if (e.Key == Keys.Tab) { } else if (!readOnly && !e.Control) { string c = Manager.KeyboardLayout.GetKey(e); if (selection.IsEmpty) { Text = Text.Insert(Pos, c); if (c != "") PosX += 1; } else { if (Text.Length > 0) { Text = Text.Remove(selection.Start, selection.Length); Text = Text.Insert(selection.Start, c); Pos = selection.Start + 1; } selection.Clear(); } } if (e.Shift && !selection.IsEmpty) { selection.End = Pos; } /* * TODO: Fix * MONOTODO: Fix if (e.Control && e.Key == Keys.C && mode != TextBoxMode.Password) { #if (!XBOX && !XBOX_FAKE) System.Windows.Forms.Clipboard.Clear(); if (mode != TextBoxMode.Password && !selection.IsEmpty) { System.Windows.Forms.Clipboard.SetText((Text.Substring(selection.Start, selection.Length)).Replace("\n", Environment.NewLine)); } #endif } else if (e.Control && e.Key == Keys.V && !readOnly && mode != TextBoxMode.Password) { #if (!XBOX && !XBOX_FAKE) string t = System.Windows.Forms.Clipboard.GetText().Replace(Environment.NewLine, "\n"); if (selection.IsEmpty) { Text = Text.Insert(Pos, t); Pos = Pos + t.Length; } else { Text = Text.Remove(selection.Start, selection.Length); Text = Text.Insert(selection.Start, t); PosX = selection.Start + t.Length; selection.Clear(); } #endif } */ if ((!e.Shift && !e.Control) || Text.Length <= 0) { selection.Clear(); } if (e.Control && e.Key == Keys.Down) { e.Handled = true; HandleGuide(PlayerIndex.One); } flashTime = 0; if (ClientArea != null) ClientArea.Invalidate(); DeterminePages(); ProcessScrolling(); } base.OnKeyPress(e); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void OnGamePadDown(GamePadEventArgs e) { if (Manager.UseGuide && Guide.IsVisible) return; if (!e.Handled) { if (e.Button == GamePadActions.Click) { e.Handled = true; HandleGuide(e.PlayerIndex); } } base.OnGamePadDown(e); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private void HandleGuide(PlayerIndex pi) { if (Manager.UseGuide && !Guide.IsVisible) { Guide.BeginShowKeyboardInput(pi, "Enter Text", "", Text, GetText, pi.ToString()); } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private void GetText(IAsyncResult result) { string res = Guide.EndShowKeyboardInput(result); Text = res != null ? res : ""; Pos = text.Length; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private void SetupBars() { DeterminePages(); if (vert != null) vert.Range = Lines.Count; if (horz != null) { horz.Range = (int)font.MeasureString(GetMaxLine()).X; if (horz.Range == 0) horz.Range = ClientArea.Width; } if (vert != null) { vert.Left = Width - 16 - 2; vert.Top = 2; vert.Height = Height - 4 - 16; if (Height < 50 || (scrollBars != ScrollBars.Both && scrollBars != ScrollBars.Vertical)) vert.Visible = false; else if ((scrollBars == ScrollBars.Vertical || scrollBars == ScrollBars.Both) && mode == TextBoxMode.Multiline) vert.Visible = true; } if (horz != null) { horz.Left = 2; horz.Top = Height - 16 - 2; horz.Width = Width - 4 - 16; if (Width < 50 || wordWrap || (scrollBars != ScrollBars.Both && scrollBars != ScrollBars.Horizontal)) horz.Visible = false; else if ((scrollBars == ScrollBars.Horizontal || scrollBars == ScrollBars.Both) && mode == TextBoxMode.Multiline && !wordWrap) horz.Visible = true; } AdjustMargins(); if (vert != null) vert.PageSize = linesDrawn; if (horz != null) horz.PageSize = charsDrawn; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void AdjustMargins() { if (horz != null && !horz.Visible) { vert.Height = Height - 4; ClientMargins = new Margins(ClientMargins.Left, ClientMargins.Top, ClientMargins.Right, Skin.ClientMargins.Bottom); } else { ClientMargins = new Margins(ClientMargins.Left, ClientMargins.Top, ClientMargins.Right, 18 + Skin.ClientMargins.Bottom); } if (vert != null && !vert.Visible) { horz.Width = Width - 4; ClientMargins = new Margins(ClientMargins.Left, ClientMargins.Top, Skin.ClientMargins.Right, ClientMargins.Bottom); } else { ClientMargins = new Margins(ClientMargins.Left, ClientMargins.Top, 18 + Skin.ClientMargins.Right, ClientMargins.Bottom); } base.AdjustMargins(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void OnResize(ResizeEventArgs e) { base.OnResize(e); selection.Clear(); SetupBars(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private string WrapWords(string text, int size) { string ret = ""; string line = ""; string[] words = text.Replace("\v", "").Split(" ".ToCharArray()); for (int i = 0; i < words.Length; i++) { if (font.MeasureString(line + words[i]).X > size) { ret += line + "\n"; line = words[i] + " "; } else { line += words[i] + " "; } } ret += line; return ret.Remove(ret.Length - 1, 1); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// public virtual void SelectAll() { if (text.Length > 0) { selection.Start = 0; selection.End = Text.Length; } } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// private List SplitLines(string text) { if (buffer != text) { buffer = text; List list = new List(); string[] s = text.Split(new char[] { Separator[0] }); list.Clear(); //Before adding the lines back in, we will want to first, measure the lines, and split words if needed... list.AddRange(s); if (posy < 0) posy = 0; if (posy > list.Count - 1) posy = list.Count - 1; if (posx < 0) posx = 0; if (posx > list[PosY].Length) posx = list[PosY].Length; return list; } else return lines; } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// void sb_ValueChanged(object sender, EventArgs e) { ClientArea.Invalidate(); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void OnFocusLost(EventArgs e) { selection.Clear(); ClientArea.Invalidate(); base.OnFocusLost(e); } //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// protected override void OnFocusGained(EventArgs e) { if (!readOnly && autoSelection) { SelectAll(); ClientArea.Invalidate(); } base.OnFocusGained(e); } //////////////////////////////////////////////////////////////////////////// #endregion } //////////////////////////////////////////////////////////////////////////// #endregion }