From: Jean-Philippe Bruyère Date: Thu, 7 Oct 2021 11:29:43 +0000 (+0000) Subject: moves with foldings X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=5c1d1809bff9f4ac2294bdbb3a2147567e052fb7;p=jp%2Fcrowedit.git moves with foldings --- diff --git a/CrowEditBase/src/Editor.cs b/CrowEditBase/src/Editor.cs index 180866e..9d3e258 100644 --- a/CrowEditBase/src/Editor.cs +++ b/CrowEditBase/src/Editor.cs @@ -180,7 +180,10 @@ namespace Crow } } + protected double lineHeight => fe.Ascent + fe.Descent; + protected virtual int getAbsoluteLineIndexFromVisualLineMove (int startLine, int visualLineDiff) + => Math.Min (Math.Max (0, startLine + visualLineDiff), visualLineCount - 1); /// /// Moves cursor one char to the left. /// @@ -191,7 +194,8 @@ namespace Crow if (loc.Column == 0) { if (loc.Line == 0) return false; - CurrentLoc = new CharLocation (loc.Line - 1, lines[loc.Line - 1].Length); + int newLine = getAbsoluteLineIndexFromVisualLineMove (loc.Line, -1); + CurrentLoc = new CharLocation (newLine, lines[newLine].Length); }else CurrentLoc = new CharLocation (loc.Line, loc.Column - 1); return true; @@ -202,14 +206,15 @@ namespace Crow if (loc.Column == lines[loc.Line].Length) { if (loc.Line == lines.Count - 1) return false; - CurrentLoc = new CharLocation (loc.Line + 1, 0); + CurrentLoc = new CharLocation ( + getAbsoluteLineIndexFromVisualLineMove (loc.Line, 1), 0); } else CurrentLoc = new CharLocation (loc.Line, loc.Column + 1); return true; } public bool LineMove (int lineDiff) { CharLocation loc = CurrentLoc.Value; - int newLine = Math.Min (Math.Max (0, loc.Line + lineDiff), lines.Count - 1); + int newLine = getAbsoluteLineIndexFromVisualLineMove (loc.Line, lineDiff); if (newLine == loc.Line) return false; @@ -227,7 +232,6 @@ namespace Crow return true; } - protected int visibleLines => (int)((double)ClientRectangle.Height / (fe.Ascent + fe.Descent)); public void GotoWordStart(){ int pos = lines.GetAbsolutePosition (CurrentLoc.Value); //skip white spaces @@ -246,7 +250,6 @@ namespace Crow pos++; CurrentLoc = lines.GetLocation (pos); } - protected void detectLineBreak () { mixedLineBreak = false; @@ -264,7 +267,6 @@ namespace Crow } } } - protected void getLines () { if (lines == null) lines = new LineCollection (10); @@ -316,14 +318,20 @@ namespace Crow } } public bool SelectionIsEmpty => selectionStart.HasValue ? Selection.IsEmpty : true; - - protected virtual int lineCount => lines.Count; + /// + /// on screen visible line bounded by the client rectangle + /// + protected int visibleLines => (int)((double)ClientRectangle.Height / lineHeight); + /// + /// total line count + /// + protected virtual int visualLineCount => lines.Count; protected virtual void measureTextBounds (Context gr) { fe = gr.FontExtents; te = new TextExtents (); - cachedTextSize.Height = (int)Math.Ceiling ((fe.Ascent + fe.Descent) * Math.Max (1, lineCount)); + cachedTextSize.Height = (int)Math.Ceiling (lineHeight * Math.Max (1, visualLineCount)); TextExtents tmp = default; int longestLine = 0; @@ -468,9 +476,9 @@ namespace Crow gr.Translate (ScrollX, ScrollY); } protected int getLineIndex (Point mouseLocalPos) => - (int)Math.Min (Math.Max (0, Math.Floor ((mouseLocalPos.Y + ScrollY)/ (fe.Ascent + fe.Descent))), lines.Count - 1); + (int)Math.Min (Math.Max (0, Math.Floor ((mouseLocalPos.Y + ScrollY)/ lineHeight)), visualLineCount - 1); protected int getVisualLineIndex (Point mouseLocalPos) => - (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / (fe.Ascent + fe.Descent))), visibleLines - 1); + (int)Math.Min (Math.Max (0, Math.Floor (mouseLocalPos.Y / lineHeight)), visibleLines - 1); protected virtual void updateHoverLocation (Point mouseLocalPos) { int hoverLine = getLineIndex (mouseLocalPos); @@ -486,7 +494,7 @@ namespace Crow } protected virtual bool cancelLinePrint (double lineHeght, double y, int clientHeight) => false; RectangleD? textCursor = null; - protected virtual int visualCurrentLine => CurrentLoc.Value.Line; + protected virtual int visualCurrentLine => CurrentLoc.HasValue ? CurrentLoc.Value.Line : 0; public virtual bool DrawCursor (Context ctx, out Rectangle rect) { if (CurrentLoc == null) { @@ -505,8 +513,6 @@ namespace Crow textCursor = null; } - - double lineHeight = fe.Ascent + fe.Descent; textCursor = computeTextCursor (new RectangleD (CurrentLoc.Value.VisualCharXPosition, lineHeight * visualCurrentLine, 1.0, lineHeight)); if (textCursor == null) { diff --git a/CrowEditBase/src/SourceEditor.cs b/CrowEditBase/src/SourceEditor.cs index 6e9b473..edca959 100644 --- a/CrowEditBase/src/SourceEditor.cs +++ b/CrowEditBase/src/SourceEditor.cs @@ -161,8 +161,7 @@ namespace Crow } e.Handled = true; - } else if (!e.Handled && HasFocus && e.Button == MouseButton.Left) - visualLine = hoverVisualLine; + } base.onMouseDown (sender, e); } @@ -189,9 +188,8 @@ namespace Crow updateHoverLocation (mLoc); if (mouseIsInMargin) { - double lineHeight = fe.Ascent + fe.Descent; Rectangle rFold = new Rectangle (leftMargin - foldMargin - leftMarginRightGap, - (int)(lineHeight * hoverVisualLine + lineHeight / 2.0 - foldSize / 2.0) - ScrollY, foldSize, foldSize); + (int)(lineHeight * getVisualLine(hoverLoc.Value.Line) + lineHeight / 2.0 - foldSize / 2.0) - ScrollY, foldSize, foldSize); mouseIsInFoldRect = rFold.ContainsOrIsEqual (mLoc); RegisterForRedraw(); return; @@ -205,9 +203,9 @@ namespace Crow RegisterForRedraw (); } } - int hoverVisualLine, visualLine; + //int hoverVisualLine, visualLine; protected override void updateHoverLocation (Point mouseLocalPos) { - hoverVisualLine = getLineIndex (mouseLocalPos); + int hoverVisualLine = getLineIndex (mouseLocalPos); int hoverLine = hoverVisualLine + countFoldedLinesUntil (hoverVisualLine); NotifyValueChanged("MouseY", mouseLocalPos.Y + ScrollY); NotifyValueChanged("ScrollY", ScrollY); @@ -226,6 +224,56 @@ namespace Crow updateLocation (gr, ClientRectangle.Width, ref hoverLoc); } } + int getVisualLine (int absoluteLine) { + if (!(Document is SourceDocument doc)) + return absoluteLine; + int foldedLines = 0; + IEnumerator foldsEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator(); + bool notEndOfFolds = foldsEnum.MoveNext(); + while (notEndOfFolds && foldsEnum.Current.StartLine < absoluteLine) { + if (foldsEnum.Current.isFolded) { + foldedLines += foldsEnum.Current.LineCount - 1; + SyntaxNode nextNode = foldsEnum.Current.NextSiblingOrParentsNextSibling; + if (nextNode == null) + break; + notEndOfFolds = foldsEnum.MoveNext(); + while (notEndOfFolds && foldsEnum.Current.StartLine < nextNode.StartLine) + notEndOfFolds = foldsEnum.MoveNext(); + } else + notEndOfFolds = foldsEnum.MoveNext(); + } + return absoluteLine - foldedLines; + } + int countFoldedLinesUntil (int visualLine) { + if (!(Document is SourceDocument doc)) + return 0; + int foldedLines = 0; + IEnumerator nodeEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator (); + if (!nodeEnum.MoveNext()) + return 0; + + int l = 0; + while (l < visualLine + foldedLines) { + if (nodeEnum.Current.StartLine == l) { + if (nodeEnum.Current.isFolded) { + foldedLines += nodeEnum.Current.lineCount - 1; + SyntaxNode nextNode = nodeEnum.Current.NextSiblingOrParentsNextSibling; + if (nextNode == null || !nodeEnum.MoveNext()) + return foldedLines; + + while (nodeEnum.Current.StartLine < nextNode.StartLine) { + if (!nodeEnum.MoveNext()) + return foldedLines; + } + + } else if (!nodeEnum.MoveNext()) + return foldedLines; + } + l ++; + } + //Console.WriteLine ($"visualLine: {visualLine} foldedLines: {foldedLines}"); + return foldedLines; + } public override void onKeyDown(object sender, KeyEventArgs e) { @@ -297,17 +345,27 @@ namespace Crow base.onKeyDown(sender, e); } - - - protected override int lineCount + protected override int getAbsoluteLineIndexFromVisualLineMove (int startLine, int visualLineDiff) { + int newVl = Math.Min (Math.Max (0, getVisualLine (startLine) + visualLineDiff), visualLineCount - 1); + return newVl + countFoldedLinesUntil (newVl); + } + /*public override bool LineMove (int lineDiff) { + CharLocation loc = CurrentLoc.Value; + int newLine = getAbsoluteLineIndexFromVisualLineMove (loc.Line, lineDiff); + if (newLine == loc.Line) + return false; + return base.LineMove (newLine - loc.Line); + }*/ + + protected override int visualLineCount { get { if (!(Document is SourceDocument doc)) - return base.lineCount; + return base.visualLineCount; return lines.Count - countFoldedLinesUntil (lines.Count); } } - protected override int visualCurrentLine => visualLine; + protected override int visualCurrentLine => CurrentLoc.HasValue ? getVisualLine (CurrentLoc.Value.Line) : 0; protected override void updateMaxScrolls (LayoutingType layout) { updateMargin(); Rectangle cb = ClientRectangle; @@ -325,36 +383,6 @@ namespace Crow } } - int countFoldedLinesUntil (int visualLine) { - if (!(Document is SourceDocument doc)) - return 0; - int foldedLines = 0; - IEnumerator nodeEnum = doc.SyntaxRootNode.FoldableNodes.GetEnumerator (); - if (!nodeEnum.MoveNext()) - return 0; - - int l = 0; - while (l < visualLine + foldedLines) { - if (nodeEnum.Current.StartLine == l) { - if (nodeEnum.Current.isFolded) { - foldedLines += nodeEnum.Current.lineCount - 1; - SyntaxNode nextNode = nodeEnum.Current.NextSiblingOrParentsNextSibling; - if (nextNode == null || !nodeEnum.MoveNext()) - return foldedLines; - - while (nodeEnum.Current.StartLine < nextNode.StartLine) { - if (!nodeEnum.MoveNext()) - return foldedLines; - } - - } else if (!nodeEnum.MoveNext()) - return foldedLines; - } - l ++; - } - //Console.WriteLine ($"visualLine: {visualLine} foldedLines: {foldedLines}"); - return foldedLines; - } protected override void drawContent (Context gr) { if (!(Document is SourceDocument doc)) {