From 137749098ac20b4ea84ced1151dbd6d7f56766ed Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Wed, 15 Apr 2015 12:02:25 +0200 Subject: Multiline TextBox --- src/GraphicObjects/TextBox.cs | 337 ++++++++---------------------------------- 1 file changed, 63 insertions(+), 274 deletions(-) (limited to 'src/GraphicObjects/TextBox.cs') diff --git a/src/GraphicObjects/TextBox.cs b/src/GraphicObjects/TextBox.cs index 70d841aa..be7cdab9 100644 --- a/src/GraphicObjects/TextBox.cs +++ b/src/GraphicObjects/TextBox.cs @@ -8,6 +8,7 @@ using System.Diagnostics; using System.Xml.Serialization; using System.Globalization; using System.ComponentModel; +using System.Runtime.InteropServices; namespace go { @@ -36,33 +37,6 @@ namespace go set { _capitalOn = value; } } - #region private fields - Color selColor; - Color selFontColor; - Point mouseLocalPos; //mouse coord in widget space, filled only when clicked - int _currentPos; //0 based cursor position in string - double textCursorPos; //cursor position in cairo units in widget client coord. - double SelStartCursorPos = -1; - double SelEndCursorPos = -1; - bool SelectionInProgress = false; - #endregion - - [XmlAttributeAttribute()][DefaultValue("SkyBlue")] - public virtual Color SelectionBackground { - get { return selColor; } - set { - selColor = value; - registerForGraphicUpdate (); - } - } - [XmlAttributeAttribute()][DefaultValue("Black")] - public virtual Color SelectionForeground { - get { return selFontColor; } - set { - selFontColor = value; - registerForGraphicUpdate (); - } - } #region GraphicObject overrides [XmlIgnore]public override bool HasFocus //trigger update when lost focus to errase text beam @@ -84,12 +58,12 @@ namespace go set { base.Focusable = value; } } [XmlAttributeAttribute()][DefaultValue("White")] - public virtual Color Background { + public override Color Background { get { return base.Background; } set { base.Background = value; } } [XmlAttributeAttribute()][DefaultValue("Black")] - public virtual Color Foreground { + public override Color Foreground { get { return base.Foreground; } set { base.Foreground = value; } } @@ -99,66 +73,20 @@ namespace go base.onDraw (gr); // gr.FontOptions.Antialias = Antialias.Subpixel; // gr.FontOptions.HintMetrics = HintMetrics.On; - gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); - gr.SetFontSize (Font.Size); +// gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); +// gr.SetFontSize (Font.Size); FontExtents fe = gr.FontExtents; - #region draw text cursor - if (mouseLocalPos > 0) - { - computeTextCursor(gr); - - if (SelectionInProgress) - { - selReleasePos = currentPos; - SelEndCursorPos = textCursorPos; - } - else if (selBeginPos < 0) - { - selBeginPos = currentPos; - SelStartCursorPos = textCursorPos; - selReleasePos = -1; - } - else - computeTextCursorPosition(gr); - - } - else - computeTextCursorPosition(gr); - - if (HasFocus) - { - //TODO: - gr.Color = Foreground; - gr.LineWidth = 2; - gr.MoveTo(new PointD(textCursorPos + rText.X, rText.Y )); - gr.LineTo(new PointD(textCursorPos + rText.X, rText.Y + fe.Height)); - gr.Stroke(); - } - - #endregion - - if (selReleasePos >= 0) - { - gr.Color = selColor; - Rectangle selRect = - new Rectangle((int)SelStartCursorPos + rText.X, (int)(rText.Y), (int)(SelEndCursorPos - SelStartCursorPos), (int)fe.Height); - gr.Rectangle(selRect); - gr.Fill(); - gr.Color = selFontColor; - } - else - gr.Color = Foreground; - gr.MoveTo(rText.X, rText.Y + fe.Ascent); - #if _WIN32 || _WIN64 - gr.ShowText(txt); - #elif __linux__ - gr.ShowText(Text); - #endif - gr.Fill(); +// gr.MoveTo(rText.X, rText.Y + fe.Ascent); +// #if _WIN32 || _WIN64 +// gr.ShowText(txt); +// #elif __linux__ +// gr.ShowText(Text); +// #endif +// gr.Fill(); } #endregion @@ -169,26 +97,6 @@ namespace go { TextChanged (this, e); } - - - [XmlIgnore]public int currentPos{ - get { return _currentPos; } - set { _currentPos = value; } - } - [XmlIgnore]public int selBeginPos; - [XmlIgnore]public int selReleasePos; - [XmlIgnore]public int selectionStart //ordered selection start and end positions - { - get { return selReleasePos < 0 ? selBeginPos : Math.Min(selBeginPos, selReleasePos); } - } - [XmlIgnore]public int selectionEnd - { get { return selReleasePos < 0 ? selReleasePos : Math.Max(selBeginPos, selReleasePos); } } - [XmlIgnore]public string selectedText - { get { return selectionEnd < 0 ? null : Text.Substring(selectionStart, selectionEnd - selectionStart); } } - [XmlIgnore]public bool selectionIsEmpty - { get { return string.IsNullOrEmpty(selectedText); } } - - #region Keyboard handling public override void onKeyDown (object sender, KeyboardKeyEventArgs e) @@ -202,32 +110,19 @@ namespace go case Key.Back: if (!selectionIsEmpty) { - Text = Text.Remove(selectionStart, selectionEnd - selectionStart); - selReleasePos = -1; - currentPos = selBeginPos; - } - else if (currentPos > 0) - { - currentPos--; - Text = Text.Remove(currentPos, 1); +// Text = Text.Remove(selectionStart, selectionEnd - selectionStart); +// selReleasePos = -1; +// currentCol = selBeginPos; } + else + this.DeleteChar(); break; case Key.Clear: break; case Key.Delete: - if (!selectionIsEmpty) - { - Text = Text.Remove(selectionStart, selectionEnd - selectionStart); - selReleasePos = -1; - currentPos = selBeginPos; - } - else if (currentPos < Text.Length) - Text = Text.Remove(currentPos, 1); - break; - case Key.Down: - break; - case Key.End: - currentPos = Text.Length; + if (selectionIsEmpty) + currentCol++; + this.DeleteChar (); break; case Key.Enter: case Key.KeypadEnter: @@ -235,17 +130,33 @@ namespace go break; case Key.Escape: Text = ""; - currentPos = 0; - selReleasePos = -1; + currentCol = 0; + selRelease = -1; break; case Key.Home: - currentPos = 0; + //TODO + if (e.Control) + currentLine = 0; + currentCol = 0; + break; + case Key.End: + if (e.Control) + currentLine = int.MaxValue; + currentCol = int.MaxValue; break; case Key.Insert: break; - case Key.Left: - if (currentPos > 0) - currentPos--; + case Key.Left: + currentCol--; + break; + case Key.Right: + currentCol++; + break; + case Key.Up: + currentLine--; + break; + case Key.Down: + currentLine++; break; case Key.Menu: break; @@ -257,49 +168,43 @@ namespace go break; case Key.RWin: break; - case Key.Right: - if (currentPos < Text.Length) - currentPos++; - break; case Key.Tab: - Text = Text.Insert(currentPos, "\t"); - currentPos++; - break; - case Key.Up: + this.Insert("\t"); break; case Key.KeypadDecimal: - Text = Text.Insert(currentPos, new string(new char[] - { Convert.ToChar(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator) })); - currentPos++; + this.Insert ("."); break; case Key.Space: - Text = Text.Insert(currentPos, " "); - currentPos++; + this.Insert(" "); break; case Key.KeypadDivide: case Key.Slash: - Text = Text.Insert(currentPos, "/"); - currentPos++; + this.Insert("/"); break; case Key.KeypadMultiply: - Text = Text.Insert(currentPos, "*"); - currentPos++; + this.Insert("*"); break; case Key.KeypadMinus: case Key.Minus: - Text = Text.Insert(currentPos, "-"); - currentPos++; + this.Insert("-"); break; case Key.KeypadPlus: case Key.Plus: - Text = Text.Insert(currentPos, "+"); - currentPos++; + this.Insert("+"); + break; + case Key.ShiftLeft: + case Key.ShiftRight: + case Key.AltLeft: + case Key.AltRight: + break; + case Key.Semicolon: + this.Insert(";"); break; default: if (!selectionIsEmpty) { - Text = Text.Remove(selectionStart, selectionEnd - selectionStart); - currentPos = selBeginPos; +// Text = Text.Remove(selectionStart, selectionEnd - selectionStart); +// currentCol = selBeginPos; } string k = "?"; @@ -307,136 +212,20 @@ namespace go k = ((int)key - 67).ToString(); else if ((char)key >= 109 && (char)key <= 118) k = ((int)key - 109).ToString(); - else if (capitalOn) + else if (e.Shift) k = key.ToString(); else k = key.ToString().ToLower(); - Text = Text.Insert(currentPos, k); - currentPos++; + this.Insert (k); - selReleasePos = -1; - selBeginPos = currentPos; + selRelease = -1; + selBegin.X = currentCol; break; } registerForGraphicUpdate(); } #endregion - - #region Mouse handling - public override void onMouseEnter (object sender, MouseMoveEventArgs e) - { -// SelectionInProgress = true; -// mouseLocalPos = e.Position - ScreenCoordBounds.TopLeft - rText.TopLeft; -// registerForGraphicUpdate(); - - base.onMouseEnter (sender, e); - } - public override void onMouseLeave (object sender, MouseMoveEventArgs e) - { - base.onMouseLeave (sender, e); - } - public override void onMouseMove (object sender, MouseMoveEventArgs e) - { - base.onMouseMove (sender, e); - - if ((sender as OpenTKGameWindow).activeWidget != this) - return; - - SelectionInProgress = true; - mouseLocalPos = e.Position - ScreenCoordinates(rText).TopLeft; - registerForGraphicUpdate(); - - } - public override void onMouseButtonDown (object sender, MouseButtonEventArgs e) - { - if (this.HasFocus){ - mouseLocalPos = e.Position - ScreenCoordinates(rText).TopLeft - rText.TopLeft; - selBeginPos = -1; - selReleasePos = -1; - }else{ - selBeginPos = 0; - selReleasePos = Text.Length; - } - - //done at the end to set 'hasFocus' value after testing it - base.onMouseButtonDown (sender, e); - - registerForGraphicUpdate(); - } - public override void onMouseButtonUp (object sender, MouseButtonEventArgs e) - { - base.onMouseButtonUp (sender, e); - SelectionInProgress = false; - } - #endregion - - void computeTextCursor(Context gr) - { - FontExtents fe = gr.FontExtents; - TextExtents te; - - double cPos = 0f; - for (int i = 0; i < _text.Length; i++) - { -#if _WIN32 || _WIN64 - byte[] c = System.Text.UTF8Encoding.UTF8.GetBytes(Text.Substring(i, 1)); - te = gr.TextExtents(c); -#elif __linux__ - te = gr.TextExtents(Text.Substring(i, 1)); -#endif - double halfWidth = te.XAdvance / 2; - - if (mouseLocalPos.X <= cPos + halfWidth) - { - currentPos = i; - textCursorPos = cPos; - mouseLocalPos = -1; - return; - } - - cPos += te.XAdvance; - } - currentPos = _text.Length; - textCursorPos = cPos; - - //reset mouseLocalPos - mouseLocalPos = -1; - } - void computeTextCursorPosition(Context gr) - { - FontExtents fe = gr.FontExtents; - TextExtents te; - - double cPos = 0f; - - int limit = currentPos; - - if (selectionEnd > 0) - limit = Math.Max(currentPos, selectionEnd); - - for (int i = 0; i <= limit; i++) - { - if (i == currentPos) - textCursorPos = cPos; - if (i == selectionStart) - SelStartCursorPos = cPos; - if (i == selectionEnd) - SelEndCursorPos = cPos; - - if (i < Text.Length) - { -#if _WIN32 || _WIN64 - byte[] c = System.Text.UTF8Encoding.UTF8.GetBytes(Text.Substring(i, 1)); - te = gr.TextExtents(c); -#elif __linux__ - te = gr.TextExtents(Text.Substring(i,1)); -#endif - cPos += te.XAdvance; - } - } - - } } } -- cgit v1.3.1-4-g156e