}
}
+ 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>
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;
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;
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
pos++;
CurrentLoc = lines.GetLocation (pos);
}
-
protected void detectLineBreak () {
mixedLineBreak = false;
}
}
}
-
protected void getLines () {
if (lines == null)
lines = new LineCollection (10);
}
}
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;
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);
}
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) {
textCursor = null;
}
-
- double lineHeight = fe.Ascent + fe.Descent;
textCursor = computeTextCursor (new RectangleD (CurrentLoc.Value.VisualCharXPosition, lineHeight * visualCurrentLine, 1.0, lineHeight));
if (textCursor == null) {
}
e.Handled = true;
- } else if (!e.Handled && HasFocus && e.Button == MouseButton.Left)
- visualLine = hoverVisualLine;
+ }
base.onMouseDown (sender, e);
}
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;
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);
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)
{
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;
}
}
- 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)) {