]> O.S.I.I.S - jp/crowedit.git/commitdiff
moves with foldings
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 7 Oct 2021 11:29:43 +0000 (11:29 +0000)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Thu, 7 Oct 2021 11:29:43 +0000 (11:29 +0000)
CrowEditBase/src/Editor.cs
CrowEditBase/src/SourceEditor.cs

index 180866e7ce189ba23be1da05b47d8e9a8a90d9dc..9d3e25816acf5a5f6af7f6e4bd36a9208b5ea1bf 100644 (file)
@@ -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);
                /// <summary>
                /// Moves cursor one char to the left.
                /// </summary>
@@ -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;
+               /// <summary>
+               /// on screen visible line bounded by the client rectangle
+               /// </summary>
+               protected int visibleLines => (int)((double)ClientRectangle.Height / lineHeight);
+               /// <summary>
+               /// total line count
+               /// </summary>
+               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) {
index 6e9b473ffde44acb9b5a4694676855e5bbba4c58..edca959636ee9776231c6c98717c858a26fac3e4 100644 (file)
@@ -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<SyntaxNode> 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<SyntaxNode> 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<SyntaxNode> 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)) {