public DocumentLocation PointToLocation (double xp, double yp, bool endAtEol = false) { lineNumber = System.Math.Min (margin.YToLine (yp + margin.textEditor.VAdjustment.Value), margin.Document.LineCount); line = lineNumber <= margin.Document.LineCount ? margin.Document.GetLine (lineNumber) : null; if (line == null) return DocumentLocation.Empty; int offset = line.Offset; xp -= margin.TextStartPosition; xp += margin.textEditor.HAdjustment.Value; xp *= Pango.Scale.PangoScale; if (xp < 0) return new DocumentLocation (lineNumber, DocumentLocation.MinColumn); int column = DocumentLocation.MinColumn; ISyntaxMode mode = margin.Document.SyntaxMode != null && margin.textEditor.Options.EnableSyntaxHighlighting ? margin.Document.SyntaxMode : new SyntaxMode (margin.Document); IEnumerable<FoldSegment> foldings = margin.Document.GetStartFoldings (line); bool done = false; Pango.Layout measueLayout = null; try { restart: int logicalRulerColumn = line.GetLogicalColumn (margin.textEditor.GetTextEditorData (), margin.textEditor.Options.RulerColumn); foreach (FoldSegment folding in foldings.Where(f => f.IsFolded)) { int foldOffset = folding.StartLine.Offset + folding.Column - 1; if (foldOffset < offset) continue; layoutWrapper = margin.CreateLinePartLayout (mode, line, logicalRulerColumn, line.Offset, foldOffset - offset, -1, -1); done |= ConsumeLayout ((int)(xp - xPos), 0); if (done) break; int height, width; layoutWrapper.Layout.GetPixelSize (out width, out height); xPos += width * (int)Pango.Scale.PangoScale; if (measueLayout == null) { measueLayout = PangoUtil.CreateLayout (margin.textEditor, folding.Description); measueLayout.FontDescription = margin.textEditor.Options.Font; } int delta; measueLayout.GetPixelSize (out delta, out height); delta *= (int)Pango.Scale.PangoScale; xPos += delta; if (xPos - delta / 2 >= xp) { index = foldOffset - offset; done = true; break; } offset = folding.EndLine.Offset + folding.EndColumn - 1; DocumentLocation foldingEndLocation = margin.Document.OffsetToLocation (offset); lineNumber = foldingEndLocation.Line; column = foldingEndLocation.Column; if (xPos >= xp) { index = 0; done = true; break; } if (folding.EndLine != line) { line = folding.EndLine; foldings = margin.Document.GetStartFoldings (line); goto restart; } } if (!done) { layoutWrapper = margin.CreateLinePartLayout (mode, line, logicalRulerColumn, offset, line.Offset + line.Length - offset, -1, -1); if (!ConsumeLayout ((int)(xp - xPos), 0)) { if (endAtEol) return DocumentLocation.Empty; } } } finally { if (measueLayout != null) measueLayout.Dispose (); } return new DocumentLocation (lineNumber, column + index); }
public DocumentLocation VisualToDocumentLocation (int xp, int yp) { if (line == null) return DocumentLocation.Empty; int offset = line.Offset; yp %= margin.LineHeight; xp -= margin.TextStartPosition; xp += (int)margin.textEditor.HAdjustment.Value; xp *= (int)Pango.Scale.PangoScale; yp *= (int)Pango.Scale.PangoScale; yp = System.Math.Max (0, yp); if (xp < 0) return new DocumentLocation (lineNumber, 0); int column = 0; SyntaxMode mode = margin.Document.SyntaxMode != null && margin.textEditor.Options.EnableSyntaxHighlighting ? margin.Document.SyntaxMode : SyntaxMode.Default; IEnumerable<FoldSegment> foldings = margin.Document.GetStartFoldings (line); bool done = false; Pango.Layout measueLayout = null; restart: foreach (FoldSegment folding in foldings.Where (f => f.IsFolded)) { int foldOffset = folding.StartLine.Offset + folding.Column; if (foldOffset < offset) continue; layoutWrapper = margin.CreateLinePartLayout (mode, line, line.Offset, foldOffset - offset, -1, -1); done |= ConsumeLayout (xp - xPos, yp); if (done) break; int height, width; layoutWrapper.Layout.GetPixelSize (out width, out height); xPos += width * (int)Pango.Scale.PangoScale; if (measueLayout == null) { measueLayout = PangoUtil.CreateLayout (margin.textEditor, folding.Description); measueLayout.FontDescription = margin.textEditor.Options.Font; } int delta; measueLayout.GetPixelSize (out delta, out height); delta *= (int)Pango.Scale.PangoScale; xPos += delta; if (xPos - delta / 2 >= xp) { index = foldOffset - offset; done = true; break; } offset = folding.EndLine.Offset + folding.EndColumn; DocumentLocation foldingEndLocation = margin.Document.OffsetToLocation (offset); lineNumber = foldingEndLocation.Line; column = foldingEndLocation.Column; if (xPos >= xp) { index = 0; done = true; break; } if (folding.EndLine != line) { line = folding.EndLine; foldings = margin.Document.GetStartFoldings (line); goto restart; } } if (!done) { layoutWrapper = margin.CreateLinePartLayout (mode, line, offset, line.Offset + line.EditableLength - offset, -1, -1); ConsumeLayout (xp - xPos, yp); } if (measueLayout != null) measueLayout.Dispose (); return new DocumentLocation (lineNumber, column + index); }