initCommands ();
- getLines();
-
Thread t = new Thread (backgroundThreadFunc);
t.IsBackground = true;
t.Start ();
}
#region Label
- protected string _text = "";
+
int targetColumn = -1;//handle line changes with long->short->long line length sequence.
protected CharLocation? hoverLoc = null;
/// </summary>
/// <param name="position">Absolute character position in text.</param>
public void SetCursorPosition (int position) {
- CharLocation loc = lines.GetLocation (position);
- loc.Column = Math.Min (loc.Column, lines[loc.Line].Length);
+ CharLocation loc = document.GetLocation (position);
+ loc.Column = Math.Min (loc.Column, document.GetLine (loc.Line).Length);
CurrentLoc = loc;
}
Color selForeground, selBackground;
- protected LineCollection lines;
+
protected bool textMeasureIsUpToDate = false;
- protected object linesMutex = new object ();
- protected string LineBreak = null;
+ //protected object linesMutex = new object ();
+
protected Size cachedTextSize = default (Size);
- protected bool mixedLineBreak = false;
+
protected FontExtents fe;
protected TextExtents te;
if (loc.Line == 0)
return false;
int newLine = getAbsoluteLineIndexFromVisualLineMove (loc.Line, -1);
- CurrentLoc = new CharLocation (newLine, lines[newLine].Length);
+ CurrentLoc = new CharLocation (newLine, document.GetLine (newLine).Length);
}else
CurrentLoc = new CharLocation (loc.Line, loc.Column - 1);
return true;
public bool MoveRight () {
targetColumn = -1;
CharLocation loc = CurrentLoc.Value;
- if (loc.Column == lines[loc.Line].Length) {
- if (loc.Line == lines.Count - 1)
+ if (loc.Column == document.GetLine (loc.Line).Length) {
+ if (loc.Line == document.LinesCount - 1)
return false;
CurrentLoc = new CharLocation (
getAbsoluteLineIndexFromVisualLineMove (loc.Line, 1), 0);
if (newLine == loc.Line)
return false;
- if (loc.Column > lines[newLine].Length) {
+ if (loc.Column > document.GetLine (newLine).Length) {
if (targetColumn < 0)
targetColumn = loc.Column;
- CurrentLoc = new CharLocation (newLine, lines[newLine].Length);
+ CurrentLoc = new CharLocation (newLine, document.GetLine (newLine).Length);
} else if (targetColumn < 0)
CurrentLoc = new CharLocation (newLine, loc.Column);
- else if (targetColumn > lines[newLine].Length)
- CurrentLoc = new CharLocation (newLine, lines[newLine].Length);
+ else if (targetColumn > document.GetLine (newLine).Length)
+ CurrentLoc = new CharLocation (newLine, document.GetLine (newLine).Length);
else
CurrentLoc = new CharLocation (newLine, targetColumn);
return true;
}
- public void GotoWordStart(){
- int pos = lines.GetAbsolutePosition (CurrentLoc.Value);
- //skip white spaces
- while (pos > 0 && !char.IsLetterOrDigit (_text[pos-1]))
- pos--;
- while (pos > 0 && char.IsLetterOrDigit (_text[pos-1]))
- pos--;
- CurrentLoc = lines.GetLocation (pos);
- }
- public void GotoWordEnd(){
- int pos = lines.GetAbsolutePosition (CurrentLoc.Value);
- //skip white spaces
- while (pos < _text.Length -1 && !char.IsLetterOrDigit (_text[pos]))
- pos++;
- while (pos < _text.Length - 1 && char.IsLetterOrDigit (_text[pos]))
- pos++;
- CurrentLoc = lines.GetLocation (pos);
- }
- protected void detectLineBreak () {
- mixedLineBreak = false;
-
- if (lines.Count == 0 || lines[0].LineBreakLength == 0) {
- LineBreak = Environment.NewLine;
- return;
- }
- LineBreak = _text.GetLineBreak (lines[0]).ToString ();
- for (int i = 1; i < lines.Count; i++) {
- ReadOnlySpan<char> lb = _text.GetLineBreak (lines[i]);
- if (!lb.SequenceEqual (LineBreak)) {
- mixedLineBreak = true;
- break;
- }
- }
- }
- protected void getLines () {
- if (lines == null)
- lines = new LineCollection (10);
- else
- lines.Clear ();
-
- if (string.IsNullOrEmpty (_text))
- lines.Add (new TextLine (0, 0, 0));
- else
- lines.Update (_text);
- }
/// <summary>
/// Current Selected text span. May be used to set current position, or current selection.
/// </summary>
if (value.IsEmpty)
selectionStart = null;
else
- selectionStart = lines.GetLocation (value.Start);
- CurrentLoc = lines.GetLocation (value.End);
+ selectionStart = document.GetLocation (value.Start);
+ CurrentLoc = document.GetLocation (value.End);
}
get {
if (CurrentLoc == null)
selEnd = CurrentLoc.Value;
}
}
- return new TextSpan (lines.GetAbsolutePosition (selStart), lines.GetAbsolutePosition (selEnd));
+ return new TextSpan (document.GetAbsolutePosition (selStart), document.GetAbsolutePosition (selEnd));
}
}
public string SelectedText {
get {
TextSpan selection = Selection;
- return selection.IsEmpty ? "" : _text.AsSpan (selection.Start, selection.Length).ToString ();
+ return selection.IsEmpty ? "" : document.GetText (selection).ToString ();
}
}
public bool SelectionIsEmpty => selectionStart.HasValue ? Selection.IsEmpty : true;
/// <summary>
/// total line count
/// </summary>
- protected virtual int visualLineCount => lines.Count;
+ protected virtual int visualLineCount => document.LinesCount;
protected virtual void measureTextBounds (Context gr) {
fe = gr.FontExtents;
te = new TextExtents ();
- cachedTextSize.Height = (int)Math.Ceiling (lineHeight * Math.Max (1, visualLineCount));
-
- TextExtents tmp = default;
- int longestLine = 0;
- for (int i = 0; i < lines.Count; i++) {
- if (lines[i].LengthInPixel < 0) {
- if (lines[i].Length == 0)
- lines.UpdateLineLengthInPixel (i, 0);// (int)Math.Ceiling (fe.MaxXAdvance);
- else {
- gr.TextExtents (_text.GetLine (lines[i]), App.TabulationSize, out tmp);
- lines.UpdateLineLengthInPixel (i, (int)Math.Ceiling (tmp.XAdvance));
+ document.EnterReadLock();
+ try {
+
+ cachedTextSize.Height = (int)Math.Ceiling (lineHeight * Math.Max (1, visualLineCount));
+
+ TextExtents tmp = default;
+ int longestLine = 0;
+ for (int i = 0; i < document.LinesCount; i++) {
+ TextLine l = document.GetLine (i);
+ if (l.LengthInPixel < 0) {
+ if (l.Length == 0)
+ l.LengthInPixel = 0;// (int)Math.Ceiling (fe.MaxXAdvance);
+ else {
+ gr.TextExtents (document.GetText (l), App.TabulationSize, out tmp);
+ l.LengthInPixel = (int)Math.Ceiling (tmp.XAdvance);
+ }
}
+ if (l.LengthInPixel > document.GetLine (longestLine).LengthInPixel)
+ longestLine = i;
}
- if (lines[i].LengthInPixel > lines[longestLine].LengthInPixel)
- longestLine = i;
- }
- cachedTextSize.Width = lines[longestLine].LengthInPixel;
- textMeasureIsUpToDate = true;
+ cachedTextSize.Width = document.GetLine (longestLine).LengthInPixel;
+ textMeasureIsUpToDate = true;
- updateMaxScrolls (LayoutingType.Height);
- updateMaxScrolls (LayoutingType.Width);
+ updateMaxScrolls (LayoutingType.Height);
+ updateMaxScrolls (LayoutingType.Width);
+ } finally {
+ document.ExitReadLock ();
+ }
}
protected virtual void drawContent (Context gr) {
gr.Translate (-ScrollX, -ScrollY);
CharLocation selStart = default, selEnd = default;
bool selectionNotEmpty = false;
- //if (HasFocus) {
- if (currentLoc?.Column < 0) {
- updateLocation (gr, cb.Width, ref currentLoc);
- NotifyValueChanged ("CurrentColumn", CurrentColumn);
- } else
- updateLocation (gr, cb.Width, ref currentLoc);
- if (selectionStart.HasValue) {
- updateLocation (gr, cb.Width, ref selectionStart);
- if (CurrentLoc.Value != selectionStart.Value)
- selectionNotEmpty = true;
- }
- if (selectionNotEmpty) {
- if (CurrentLoc.Value.Line < selectionStart.Value.Line) {
- selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
- } else if (CurrentLoc.Value.Line > selectionStart.Value.Line) {
- selStart = selectionStart.Value;
- selEnd = CurrentLoc.Value;
- } else if (CurrentLoc.Value.Column < selectionStart.Value.Column) {
- selStart = CurrentLoc.Value;
- selEnd = selectionStart.Value;
- } else {
- selStart = selectionStart.Value;
- selEnd = CurrentLoc.Value;
+ document.EnterReadLock();
+ try {
+ //if (HasFocus) {
+ if (currentLoc?.Column < 0) {
+ updateLocation (gr, cb.Width, ref currentLoc);
+ NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ } else
+ updateLocation (gr, cb.Width, ref currentLoc);
+ if (selectionStart.HasValue) {
+ updateLocation (gr, cb.Width, ref selectionStart);
+ if (CurrentLoc.Value != selectionStart.Value)
+ selectionNotEmpty = true;
}
- } else
- IFace.forceTextCursor = true;
- //}
-
- if (!string.IsNullOrEmpty (_text)) {
- Foreground?.SetAsSource (IFace, gr);
-
- TextExtents extents;
- Span<byte> bytes = stackalloc byte[128];
- double y = 0;
-
- for (int i = 0; i < lines.Count; i++) {
- if (!cancelLinePrint (lineHeight, y, cb.Height)) {
- int encodedBytes = -1;
- if (lines[i].Length > 0) {
- int size = lines[i].Length * 4 + 1;
- if (bytes.Length < size)
- bytes = size > 512 ? new byte[size] : stackalloc byte[size];
-
- encodedBytes = Crow.Text.Encoding.ToUtf8 (_text.GetLine (lines[i]), bytes);
- bytes[encodedBytes++] = 0;
-
- if (lines[i].LengthInPixel < 0) {
- gr.TextExtents (bytes.Slice (0, encodedBytes), out extents);
- lines.UpdateLineLengthInPixel (i, (int)extents.XAdvance);
- }
+ if (selectionNotEmpty) {
+ if (CurrentLoc.Value.Line < selectionStart.Value.Line) {
+ selStart = CurrentLoc.Value;
+ selEnd = selectionStart.Value;
+ } else if (CurrentLoc.Value.Line > selectionStart.Value.Line) {
+ selStart = selectionStart.Value;
+ selEnd = CurrentLoc.Value;
+ } else if (CurrentLoc.Value.Column < selectionStart.Value.Column) {
+ selStart = CurrentLoc.Value;
+ selEnd = selectionStart.Value;
+ } else {
+ selStart = selectionStart.Value;
+ selEnd = CurrentLoc.Value;
}
-
- RectangleD lineRect = new RectangleD (
- (int)cb.X,
- y + cb.Top, lines[i].LengthInPixel, lineHeight);
-
- if (encodedBytes > 0) {
- gr.MoveTo (lineRect.X, lineRect.Y + fe.Ascent);
- gr.ShowText (bytes.Slice (0, encodedBytes));
- }
- /********** DEBUG TextLineCollection *************
- gr.SetSource (Colors.Red);
- gr.SetFontSize (9);
- gr.MoveTo (700, lineRect.Y + fe.Ascent);
- gr.ShowText ($"({lines[i].Start}, {lines[i].End}, {lines[i].EndIncludingLineBreak})");
- gr.SetFontSize (Font.Size);
- Foreground.SetAsSource (IFace, gr);
- ********** DEBUG TextLineCollection *************/
-
- if (selectionNotEmpty) {
- RectangleD selRect = lineRect;
-
- if (i >= selStart.Line && i <= selEnd.Line) {
- if (selStart.Line == selEnd.Line) {
- selRect.X = selStart.VisualCharXPosition + cb.X;
- selRect.Width = selEnd.VisualCharXPosition - selStart.VisualCharXPosition;
- } else if (i == selStart.Line) {
- double newX = selStart.VisualCharXPosition + cb.X;
- selRect.Width -= (newX - selRect.X) - 10.0;
- selRect.X = newX;
- } else if (i == selEnd.Line) {
- selRect.Width = selEnd.VisualCharXPosition - selRect.X + cb.X;
- } else
- selRect.Width += 10.0;
- } else {
- y += lineHeight;
- continue;
+ } else
+ IFace.forceTextCursor = true;
+ //}
+
+ if (document.Lenght > 0) {
+ Foreground?.SetAsSource (IFace, gr);
+
+ TextExtents extents;
+ Span<byte> bytes = stackalloc byte[128];
+ double y = 0;
+
+ for (int i = 0; i < document.LinesCount; i++) {
+ if (!cancelLinePrint (lineHeight, y, cb.Height)) {
+ int encodedBytes = -1;
+ TextLine l = document.GetLine (i);
+ if (l.Length > 0) {
+ int size = l.Length * 4 + 1;
+ if (bytes.Length < size)
+ bytes = size > 512 ? new byte[size] : stackalloc byte[size];
+
+ encodedBytes = Crow.Text.Encoding.ToUtf8 (document.GetText (l), bytes);
+ bytes[encodedBytes++] = 0;
+
+ if (l.LengthInPixel < 0) {
+ gr.TextExtents (bytes.Slice (0, encodedBytes), out extents);
+ l.LengthInPixel = (int)extents.XAdvance;
+ }
}
- gr.SetSource (selBackground);
- gr.Rectangle (selRect);
- if (encodedBytes < 0)
- gr.Fill ();
- else {
- gr.FillPreserve ();
- gr.Save ();
- gr.Clip ();
- gr.SetSource (SelectionForeground);
+ RectangleD lineRect = new RectangleD (
+ (int)cb.X,
+ y + cb.Top, l.LengthInPixel, lineHeight);
+
+ if (encodedBytes > 0) {
gr.MoveTo (lineRect.X, lineRect.Y + fe.Ascent);
gr.ShowText (bytes.Slice (0, encodedBytes));
- gr.Restore ();
}
+ /********** DEBUG TextLineCollection *************
+ gr.SetSource (Colors.Red);
+ gr.SetFontSize (9);
+ gr.MoveTo (700, lineRect.Y + fe.Ascent);
+ gr.ShowText ($"({lines[i].Start}, {lines[i].End}, {lines[i].EndIncludingLineBreak})");
+ gr.SetFontSize (Font.Size);
Foreground.SetAsSource (IFace, gr);
+ ********** DEBUG TextLineCollection *************/
+
+ if (selectionNotEmpty) {
+ RectangleD selRect = lineRect;
+
+ if (i >= selStart.Line && i <= selEnd.Line) {
+ if (selStart.Line == selEnd.Line) {
+ selRect.X = selStart.VisualCharXPosition + cb.X;
+ selRect.Width = selEnd.VisualCharXPosition - selStart.VisualCharXPosition;
+ } else if (i == selStart.Line) {
+ double newX = selStart.VisualCharXPosition + cb.X;
+ selRect.Width -= (newX - selRect.X) - 10.0;
+ selRect.X = newX;
+ } else if (i == selEnd.Line) {
+ selRect.Width = selEnd.VisualCharXPosition - selRect.X + cb.X;
+ } else
+ selRect.Width += 10.0;
+ } else {
+ y += lineHeight;
+ continue;
+ }
+
+ gr.SetSource (selBackground);
+ gr.Rectangle (selRect);
+ if (encodedBytes < 0)
+ gr.Fill ();
+ else {
+ gr.FillPreserve ();
+ gr.Save ();
+ gr.Clip ();
+ gr.SetSource (SelectionForeground);
+ gr.MoveTo (lineRect.X, lineRect.Y + fe.Ascent);
+ gr.ShowText (bytes.Slice (0, encodedBytes));
+ gr.Restore ();
+ }
+ Foreground.SetAsSource (IFace, gr);
+ }
}
+ y += lineHeight;
}
- y += lineHeight;
}
+ } finally {
+ document.ExitReadLock ();
}
gr.Translate (ScrollX, ScrollY);
}
if (!CurrentLoc.Value.HasVisualX) {
setFontForContext (ctx);
- lock (linesMutex) {
- if (currentLoc?.Column < 0) {
- updateLocation (ctx, ClientRectangle.Width, ref currentLoc);
- NotifyValueChanged ("CurrentColumn", CurrentColumn);
- } else
- updateLocation (ctx, ClientRectangle.Width, ref currentLoc);
- }
+
+ if (currentLoc?.Column < 0) {
+ updateLocation (ctx, ClientRectangle.Width, ref currentLoc);
+ NotifyValueChanged ("CurrentColumn", CurrentColumn);
+ } else
+ updateLocation (ctx, ClientRectangle.Width, ref currentLoc);
+
textCursor = null;
}
return false;
}
//}
+
Rectangle c = ScreenCoordinates (textCursor.Value + Slot.Position + ClientRectangle.Position);
ctx.ResetClip ();
Foreground.SetAsSource (IFace, ctx, c);
//Console.WriteLine ($"updateLocation: {loc} text:{_text.Length}");
if (loc.HasVisualX)
return;
- TextLine ls = lines[loc.Line];
- ReadOnlySpan<char> curLine = _text.GetLine (ls);
+ TextLine ls = document.GetLine (loc.Line);
+ ReadOnlySpan<char> curLine = document.GetText (ls);
double cPos = 0;
if (loc.Column >= 0) {
base.OnLayoutChanges (layoutType);
updateMaxScrolls (layoutType);
}
- public override bool UpdateLayout (LayoutingType layoutType) {
+ /*public override bool UpdateLayout (LayoutingType layoutType) {
if ((LayoutingType.Sizing | layoutType) != LayoutingType.None) {
if (!System.Threading.Monitor.TryEnter (linesMutex))
return false;
} finally {
System.Threading.Monitor.Exit (linesMutex);
}
- }
+ }*/
public override int measureRawSize(LayoutingType lt)
{
DbgLogger.StartEvent(DbgEvtType.GOMeasure, this, lt);
try {
- if ((bool)lines?.IsEmpty)
- getLines ();
-
if (!textMeasureIsUpToDate) {
using (Context gr = new Context (IFace.surf)) {
setFontForContext (gr);
DbgLogger.EndEvent(DbgEvtType.GOMeasure);
}
}
-
+ public override void Paint (Context ctx) {
+ base.Paint (ctx);
+ IFace.forceTextCursor = true;
+ }
protected override void onDraw (Context gr)
{
//base.onDraw (gr);
setFontForContext (gr);
if (!textMeasureIsUpToDate) {
- lock (linesMutex)
- measureTextBounds (gr);
+ measureTextBounds (gr);
}
if (ClipToClientRect) {
gr.Clip ();
}
- lock (linesMutex)
- drawContent (gr);
+ drawContent (gr);
if (ClipToClientRect)
gr.Restore ();
if (e.Button != MouseButton.Left || !HasFocus)
return;
- GotoWordStart ();
- selectionStart = CurrentLoc;
- GotoWordEnd ();
+ selectionStart = document.GetWordStart (CurrentLoc.Value);
+ CurrentLoc = document.GetWordEnd (CurrentLoc.Value);
RegisterForRedraw ();
}
#endregion
#region Keyboard handling
+ public override void onKeyPress (object sender, KeyPressEventArgs e) {
+ base.onKeyPress (sender, e);
+
+ TextSpan selection = Selection;
+ update (new TextChange (selection.Start, selection.Length, e.KeyChar.ToString ()));
+
+ /*Insert (e.KeyChar.ToString());
+
+ SelRelease = -1;
+ SelBegin = new Point(CurrentColumn, SelBegin.Y);
+
+ RegisterForGraphicUpdate();*/
+ }
public override void onKeyDown (object sender, KeyEventArgs e) {
Key key = e.Key;
TextSpan selection = Selection;
- switch (key) {
- case Key.Backspace:
- if (selection.IsEmpty) {
- if (selection.Start == 0)
- return;
- if (CurrentLoc.Value.Column == 0) {
- int lbLength = lines[CurrentLoc.Value.Line - 1].LineBreakLength;
- update (new TextChange (selection.Start - lbLength, lbLength, ""));
- }else
- update (new TextChange (selection.Start - 1, 1, ""));
- } else
- update (new TextChange (selection.Start, selection.Length, ""));
- break;
- case Key.Delete:
- if (selection.IsEmpty) {
- if (selection.Start == _text.Length)
- return;
- if (CurrentLoc.Value.Column >= lines[CurrentLoc.Value.Line].Length)
- update (new TextChange (selection.Start, lines[CurrentLoc.Value.Line].LineBreakLength, ""));
+
+ /*document.EnterReadLock();
+ try {*/
+ switch (key) {
+ case Key.Backspace:
+ if (selection.IsEmpty) {
+ if (selection.Start == 0)
+ return;
+ if (CurrentLoc.Value.Column == 0) {
+ int lbLength = document.GetLine (CurrentLoc.Value.Line - 1).LineBreakLength;
+ update (new TextChange (selection.Start - lbLength, lbLength, ""));
+ }else
+ update (new TextChange (selection.Start - 1, 1, ""));
+ } else
+ update (new TextChange (selection.Start, selection.Length, ""));
+ break;
+ case Key.Delete:
+ if (selection.IsEmpty) {
+ if (selection.Start == document.Lenght)
+ return;
+ if (CurrentLoc.Value.Column >= document.GetLine (CurrentLoc.Value.Line).Length)
+ update (new TextChange (selection.Start, document.GetLine (CurrentLoc.Value.Line).LineBreakLength, ""));
+ else
+ update (new TextChange (selection.Start, 1, ""));
+ } else {
+ if (e.Modifiers == Modifier.Shift)
+ IFace.Clipboard = SelectedText;
+ update (new TextChange (selection.Start, selection.Length, ""));
+ }
+ break;
+ case Key.Insert:
+ if (e.Modifiers.HasFlag (Modifier.Shift))
+ Paste ();
+ else if (e.Modifiers.HasFlag (Modifier.Control))
+ Copy ();
+ break;
+ case Key.KeypadEnter:
+ case Key.Enter:
+ update (new TextChange (selection.Start, selection.Length, document.GetLineBreak ()));
+ break;
+ case Key.Escape:
+ selectionStart = null;
+ CurrentLoc = document.GetLocation (selection.Start);
+ RegisterForRedraw ();
+ break;
+ case Key.Tab:
+ update (new TextChange (selection.Start, selection.Length, App.IndentWithSpace ? new string(' ', App.TabulationSize) : "\t"));
+ break;
+ case Key.PageUp:
+ checkShift (e);
+ LineMove (-visibleLines);
+ RegisterForRedraw ();
+ break;
+ case Key.PageDown:
+ checkShift (e);
+ LineMove (visibleLines);
+ RegisterForRedraw ();
+ break;
+ case Key.Home:
+ targetColumn = -1;
+ checkShift (e);
+ if (e.Modifiers.HasFlag (Modifier.Control))
+ CurrentLoc = new CharLocation (0, 0);
else
- update (new TextChange (selection.Start, 1, ""));
- } else {
- if (e.Modifiers == Modifier.Shift)
- IFace.Clipboard = SelectedText;
- update (new TextChange (selection.Start, selection.Length, ""));
- }
- break;
- case Key.Insert:
- if (e.Modifiers.HasFlag (Modifier.Shift))
- Paste ();
- else if (e.Modifiers.HasFlag (Modifier.Control))
- Copy ();
- break;
- case Key.KeypadEnter:
- case Key.Enter:
- if (string.IsNullOrEmpty (LineBreak))
- detectLineBreak ();
- update (new TextChange (selection.Start, selection.Length, LineBreak));
- break;
- case Key.Escape:
- selectionStart = null;
- CurrentLoc = lines.GetLocation (selection.Start);
- RegisterForRedraw ();
- break;
- case Key.Tab:
- update (new TextChange (selection.Start, selection.Length, App.IndentWithSpace ? new string(' ', App.TabulationSize) : "\t"));
- break;
- case Key.PageUp:
- checkShift (e);
- LineMove (-visibleLines);
- RegisterForRedraw ();
- break;
- case Key.PageDown:
- checkShift (e);
- LineMove (visibleLines);
- RegisterForRedraw ();
- break;
- case Key.Home:
- targetColumn = -1;
- checkShift (e);
- if (e.Modifiers.HasFlag (Modifier.Control))
- CurrentLoc = new CharLocation (0, 0);
- else
- CurrentLoc = new CharLocation (CurrentLoc.Value.Line, 0);
- RegisterForRedraw ();
- break;
- case Key.End:
- checkShift (e);
- int l = e.Modifiers.HasFlag (Modifier.Control) ? lines.Count - 1 : CurrentLoc.Value.Line;
- CurrentLoc = new CharLocation (l, lines[l].Length);
- RegisterForRedraw ();
- break;
- case Key.Left:
- checkShift (e);
- if (e.Modifiers.HasFlag (Modifier.Control))
- GotoWordStart ();
- else
- MoveLeft ();
- RegisterForRedraw ();
- break;
- case Key.Right:
- checkShift (e);
- if (e.Modifiers.HasFlag (Modifier.Control))
- GotoWordEnd ();
- else
- MoveRight ();
- RegisterForRedraw ();
- break;
- case Key.Up:
- checkShift (e);
- LineMove (-1);
- RegisterForRedraw ();
- break;
- case Key.Down:
- checkShift (e);
- LineMove (1);
- RegisterForRedraw ();
- break;
- case Key.A:
- if (e.Modifiers.HasFlag (Modifier.Control)) {
- selectionStart = new CharLocation (0, 0);
- CurrentLoc = new CharLocation (lines.Count - 1, lines[lines.Count - 1].Length);
+ CurrentLoc = new CharLocation (CurrentLoc.Value.Line, 0);
+ RegisterForRedraw ();
+ break;
+ case Key.End:
+ checkShift (e);
+ int l = e.Modifiers.HasFlag (Modifier.Control) ? document.LinesCount - 1 : CurrentLoc.Value.Line;
+ CurrentLoc = new CharLocation (l, document.GetLine (l).Length);
+ RegisterForRedraw ();
+ break;
+ case Key.Left:
+ checkShift (e);
+ if (e.Modifiers.HasFlag (Modifier.Control))
+ CurrentLoc = document.GetWordStart (CurrentLoc.Value);
+ else
+ MoveLeft ();
+ RegisterForRedraw ();
+ break;
+ case Key.Right:
+ checkShift (e);
+ if (e.Modifiers.HasFlag (Modifier.Control))
+ CurrentLoc = document.GetWordEnd (CurrentLoc.Value);
+ else
+ MoveRight ();
+ RegisterForRedraw ();
+ break;
+ case Key.Up:
+ checkShift (e);
+ LineMove (-1);
+ RegisterForRedraw ();
+ break;
+ case Key.Down:
+ checkShift (e);
+ LineMove (1);
+ RegisterForRedraw ();
+ break;
+ case Key.A:
+ if (e.Modifiers.HasFlag (Modifier.Control)) {
+ selectionStart = new CharLocation (0, 0);
+ CurrentLoc = document.EndLocation;
+ }
+ break;
+ default:
+ base.onKeyDown (sender, e);
+ return;
}
- break;
- default:
- base.onKeyDown (sender, e);
- return;
- }
- autoAdjustScroll = true;
- IFace.forceTextCursor = true;
- e.Handled = true;
+ autoAdjustScroll = true;
+ IFace.forceTextCursor = true;
+ e.Handled = true;
+ /*} finally {
+ document.ExitReadLock ();
+ }*/
}
#endregion
#endregion
update (new TextChange (selection.Start, selection.Length, IFace.Clipboard));
}
- #region Keyboard handling
- public override void onKeyPress (object sender, KeyPressEventArgs e) {
- base.onKeyPress (sender, e);
-
- TextSpan selection = Selection;
- update (new TextChange (selection.Start, selection.Length, e.KeyChar.ToString ()));
-
- /*Insert (e.KeyChar.ToString());
-
- SelRelease = -1;
- SelBegin = new Point(CurrentColumn, SelBegin.Y);
-
- RegisterForGraphicUpdate();*/
- }
- #endregion
-
protected void update (TextChange change) {
- lock (linesMutex) {
- ReadOnlySpan<char> src = _text.AsSpan ();
- Span<char> tmp = stackalloc char[src.Length + (change.ChangedText.Length - change.Length)];
- //Console.WriteLine ($"{Text.Length,-4} {change.Start,-4} {change.Length,-4} {change.ChangedText.Length,-4} tmp:{tmp.Length,-4}");
- src.Slice (0, change.Start).CopyTo (tmp);
- change.ChangedText.AsSpan ().CopyTo (tmp.Slice (change.Start));
- src.Slice (change.End).CopyTo (tmp.Slice (change.Start + change.ChangedText.Length));
-
- _text = tmp.ToString ();
- lines.Update (change);
- //lines.Update (_text);
- selectionStart = null;
+ OnTextChanged (this, new TextChangeEventArgs (change));
- CurrentLoc = lines.GetLocation (change.Start + change.ChangedText.Length);
- textMeasureIsUpToDate = false;
- IFace.forceTextCursor = true;
- }
+ selectionStart = null;
+ CurrentLoc = document.GetLocation (change.Start + change.ChangedText.Length);
- OnTextChanged (this, new TextChangeEventArgs (change));
+ textMeasureIsUpToDate = false;
+ IFace.forceTextCursor = true;
+ autoAdjustScroll = true;
RegisterForGraphicUpdate ();
}
#endregion
-
}
}
\ No newline at end of file
base.OnTextChanged(sender, e);
if (Document is SourceDocument srcdoc)
- srcdoc.updateCurrentTokAndNode (lines.GetAbsolutePosition(CurrentLoc.Value));
+ srcdoc.updateCurrentTokAndNode (CurrentLoc.Value);
if (!disableSuggestions && HasFocus)
tryGetSuggestions ();
protected void tryGetSuggestions () {
if (currentLoc.HasValue && Document is SourceDocument srcDoc) {
- IList suggs = srcDoc.GetSuggestions (lines.GetAbsolutePosition (CurrentLoc.Value));
+ IList suggs = srcDoc.GetSuggestions (CurrentLoc.Value);
if (suggs != null && suggs.Count == 1 && (
(suggs[0] is System.Reflection.MemberInfo mi && mi.Name == srcDoc.CurrentTokenString) ||
(suggs[0].ToString() == srcDoc.CurrentTokenString)
void updateMargin () {
leftMargin = leftMarginGap;
if (App.PrintLineNumbers)
- leftMargin += (int)Math.Ceiling((double)lines.Count.ToString().Length * fe.MaxXAdvance) + 6;
+ leftMargin += (int)Math.Ceiling((double)(Document == null ? 1 : Document.LinesCount.ToString().Length) * fe.MaxXAdvance) + 6;
if (App.FoldingEnabled)
leftMargin += foldMargin;
leftMargin += leftMarginRightGap;
fold = fold.Parent;
fold?.UnfoldToTheTop();
if (Document is SourceDocument doc)
- doc.updateCurrentTokAndNode (lines.GetAbsolutePosition(currentLoc.Value));
+ doc.updateCurrentTokAndNode (currentLoc.Value);
}
NotifyValueChanged ("CurrentLine", CurrentLine);
NotifyValueChanged ("CurrentColumn", CurrentColumn);
{
DbgLogger.StartEvent(DbgEvtType.GOMeasure, this, lt);
try {
- if ((bool)lines?.IsEmpty)
- getLines ();
-
updateMargin ();
if (!textMeasureIsUpToDate) {
{
TextSpan selection = Selection;
- if (SelectionIsEmpty) {
- if (suggestionsActive) {
- switch (e.Key) {
- case Key.Escape:
- hideOverlay ();
- return;
- case Key.Left:
- case Key.Right:
- hideOverlay ();
- break;
- case Key.End:
- case Key.Home:
- case Key.Down:
- case Key.Up:
- case Key.PageDown:
- case Key.PageUp:
- overlay.onKeyDown (this, e);
- return;
- case Key.Tab:
- case Key.Enter:
- case Key.KeypadEnter:
- completeToken ();
+ /*Document.EnterReadLock();
+ try {*/
+ if (SelectionIsEmpty) {
+ if (suggestionsActive) {
+ switch (e.Key) {
+ case Key.Escape:
+ hideOverlay ();
+ return;
+ case Key.Left:
+ case Key.Right:
+ hideOverlay ();
+ break;
+ case Key.End:
+ case Key.Home:
+ case Key.Down:
+ case Key.Up:
+ case Key.PageDown:
+ case Key.PageUp:
+ overlay.onKeyDown (this, e);
+ return;
+ case Key.Tab:
+ case Key.Enter:
+ case Key.KeypadEnter:
+ completeToken ();
+ return;
+ }
+ } else if (e.Key == Key.Space && e.Modifiers.HasFlag (Modifier.Control)) {
+ tryGetSuggestions ();
return;
}
- } else if (e.Key == Key.Space && e.Modifiers.HasFlag (Modifier.Control)) {
- tryGetSuggestions ();
- return;
- }
- } else if (e.Key == Key.Tab && !selection.IsEmpty) {
- int lineStart = lines.GetLocation (selection.Start).Line;
- CharLocation locEnd = lines.GetLocation (selection.End);
- int lineEnd = locEnd.Column == 0 ? Math.Max (0, locEnd.Line - 1) : locEnd.Line;
-
- disableSuggestions = true;
-
- if ( e.Modifiers == Modifier.Shift) {
- for (int l = lineStart; l <= lineEnd; l++) {
- if (_text[lines[l].Start] == '\t')
- update (new TextChange (lines[l].Start, 1, ""));
- else if (Char.IsWhiteSpace (_text[lines[l].Start])) {
- int i = 1;
- while (i < lines[l].Length && i < App.TabulationSize && Char.IsWhiteSpace (_text[i]))
- i++;
- update (new TextChange (lines[l].Start, i, ""));
+ } else if (e.Key == Key.Tab && !selection.IsEmpty) {
+ int lineStart = Document.GetLocation (selection.Start).Line;
+ CharLocation locEnd = Document.GetLocation (selection.End);
+ int lineEnd = locEnd.Column == 0 ? Math.Max (0, locEnd.Line - 1) : locEnd.Line;
+
+ disableSuggestions = true;
+
+ if ( e.Modifiers == Modifier.Shift) {
+ for (int l = lineStart; l <= lineEnd; l++) {
+ TextLine li = Document.GetLine (l);
+ if (Document.GetChar (li.Start) == '\t')
+ update (new TextChange (li.Start, 1, ""));
+ else if (Char.IsWhiteSpace (Document.GetChar (li.Start))) {
+ int i = 1;
+ while (i < li.Length && i < App.TabulationSize && Char.IsWhiteSpace (Document.GetChar (i)))
+ i++;
+ update (new TextChange (li.Start, i, ""));
+ }
}
- }
- }else{
- for (int l = lineStart; l <= lineEnd; l++)
- update (new TextChange (lines[l].Start, 0, "\t"));
- }
+ }else{
+ for (int l = lineStart; l <= lineEnd; l++)
+ update (new TextChange (Document.GetLine (l).Start, 0, "\t"));
+ }
- selectionStart = new CharLocation (lineStart, 0);
- CurrentLoc = new CharLocation (lineEnd, lines[lineEnd].Length);
+ selectionStart = new CharLocation (lineStart, 0);
+ CurrentLoc = new CharLocation (lineEnd, Document.GetLine (lineEnd).Length);
- disableSuggestions = false;
+ disableSuggestions = false;
- return;
- }
- if (Document is SourceDocument doc) {
- switch (e.Key) {
- case Key.F3:
- doc.SyntaxRootNode?.Dump();
- break;
- case Key.Enter:
- case Key.KeypadEnter:
- //doc.updateCurrentTokAndNode (Selection.Start);
- Console.WriteLine ($"*** Current Token: {doc.CurrentToken} Current Node: {doc.CurrentNode}");
- if (string.IsNullOrEmpty (LineBreak))
- detectLineBreak ();
- update (new TextChange (selection.Start, selection.Length, LineBreak));
- autoAdjustScroll = true;
- IFace.forceTextCursor = true;
- e.Handled = true;
- return;
+ return;
+ }
+ if (Document is SourceDocument doc) {
+ switch (e.Key) {
+ case Key.F3:
+ doc.SyntaxRootNode?.Dump();
+ break;
+ case Key.Enter:
+ case Key.KeypadEnter:
+ //doc.updateCurrentTokAndNode (Selection.Start);
+ Console.WriteLine ($"*** Current Token: {doc.CurrentToken} Current Node: {doc.CurrentNode}");
+ update (new TextChange (selection.Start, selection.Length, Document.GetLineBreak ()));
+ autoAdjustScroll = true;
+ IFace.forceTextCursor = true;
+ e.Handled = true;
+ return;
+ }
}
- }
- base.onKeyDown(sender, e);
+ base.onKeyDown(sender, e);
+ /*} finally {
+ Document.ExitReadLock ();
+ }*/
}
get {
if (!(Document is SourceDocument doc))
return base.visualLineCount;
- return lines.Count - countFoldedLinesUntil (lines.Count);
+ return Document.LinesCount - countFoldedLinesUntil (Document.LinesCount);
}
}
protected override int visualCurrentLine => CurrentLoc.HasValue ? getVisualLine (CurrentLoc.Value.Line) : 0;
bool printLineNumbers = App.PrintLineNumbers;
Color marginBG = App.MarginBackground;
Color marginFG = Colors.Ivory;
- double lineNumWidth = gr.TextExtents (lines.Count.ToString()).Width;
+ double lineNumWidth = gr.TextExtents (Document.LinesCount.ToString()).Width;
Rectangle cb = ClientRectangle;
RectangleD marginRect = new RectangleD (cb.X + ScrollX, cb.Y, leftMargin - leftMarginRightGap, lineHeight);
if (CurrentNode != null) {
TextSpan nodeSpan = CurrentNode.Span;
- nodeStart = lines.GetLocation (nodeSpan.Start);
+ nodeStart = Document.GetLocation (nodeSpan.Start);
updateLocation (gr, cb.Width, ref nodeStart);
- nodeEnd = lines.GetLocation (nodeSpan.End);
+ nodeEnd = Document.GetLocation (nodeSpan.End);
updateLocation (gr, cb.Width, ref nodeEnd);
}
#if DEBUG_NODES
bool notEndOfNodes = nodeEnum.MoveNext();
int l = 0;
- while (l < lines.Count) {
+ while (l < Document.LinesCount) {
//if (!cancelLinePrint (lineHeight, lineHeight * y, cb.Height)) {
bool foldable = false;
//buff = sourceBytes.Slice (lines[l].Start, lines[l].Length);
- while (tok.Start < lines[l].End) {
+ while (tok.Start < Document.GetLine (l).End) {
buff = sourceBytes.Slice (tok.Start, tok.Length);
gr.SetSource (doc.GetColorForToken (tok.Type));
if (foldable && curNode.isFolded) {
TextSpan ns = curNode.Span;
l = curNode.StartLine + curNode.LineCount;
- while (tok.End <= lines[l].Start) {
+ while (tok.End <= Document.GetLine (l).Start) {
if (++tokPtr >= doc.Tokens.Length)
break;
tok = doc.Tokens[tokPtr];