private void UpdateBlocks() { if (blocks.Count == 0) { return; } // While something is visible after last block... while (!blocks.Last().IsLast&& blocks.Last().Position.Y + blockHeight - VerticalOffset < ActualHeight) { int firstLineIndex = blocks.Last().LineEndIndex + 1; int lastLineIndex = firstLineIndex + maxLineCountInBlock - 1; lastLineIndex = lastLineIndex <= totalLineCount - 1 ? lastLineIndex : totalLineCount - 1; int fisrCharIndex = blocks.Last().CharEndIndex + 1; int lastCharIndex = TextUtilities.GetLastCharIndexFromLineIndex(Text, lastLineIndex); // to be optimized (forward search) if (lastCharIndex <= fisrCharIndex) { blocks.Last().IsLast = true; return; } InnerTextBlock block = new InnerTextBlock( fisrCharIndex, lastCharIndex, blocks.Last().LineEndIndex + 1, lastLineIndex, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); blocks.Add(block); FormatBlock(block, blocks.Count > 1 ? blocks[blocks.Count - 2] : null); } }
/// <summary> /// Formats and Highlights the text of a block. /// </summary> private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock) { currentBlock.FormattedText = GetFormattedText(currentBlock.RawText); Dispatcher.Invoke(() => { CodeEditorContent.Instance.Highlight(currentBlock.FormattedText, openBracketPos, closeBracketPos); currentBlock.Code = -1; }); }
/// <summary> /// Formats and Highlights the text of a block. /// </summary> private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock) { currentBlock.FormattedText = GetFormattedText(currentBlock.RawText); if (CurrentHighlighter != null) { var previousCode = previousBlock?.Code ?? -1; currentBlock.Code = CurrentHighlighter.Highlight(currentBlock.FormattedText, previousCode); } }
/// <summary> /// Formats and Highlights the text of a block. /// </summary> private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock) { currentBlock.FormattedText = this.GetFormattedText(currentBlock.RawText); ThreadPool.QueueUserWorkItem(p => { int previousCode = previousBlock != null ? previousBlock.Code : -1; currentBlock.Code = this.CurrentHighlighter.Highlight(currentBlock.FormattedText, previousCode); }); }
/// <summary> /// Formats and Highlights the text of a block. /// </summary> private void FormatBlock(InnerTextBlock currentBlock) { currentBlock.FormattedText = GetFormattedText(currentBlock.RawText); Dispatcher.Invoke(() => { HiglightContent.Highlight(currentBlock.FormattedText, openBracketPos, closeBracketPos, BracketBrush); HiglightContent.HighlightErrors(currentBlock.FormattedText, Errors, blocks); currentBlock.Code = -1; }); }
/// <summary> /// Formats and Highlights the text of a block. /// </summary> private void FormatBlock(InnerTextBlock currentBlock, DpiScale dpi) { currentBlock.FormattedText = GetFormattedText(currentBlock.RawText, dpi); if (CurrentHighlighter != null) { ThreadPool.QueueUserWorkItem(p => { CurrentHighlighter.Highlight(currentBlock.FormattedText); currentBlock.Code = -1; }); } }
// Formats and Highlights the text of a block. private void FormatTextBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock) { currentBlock.FormattedText = GetFormattedText(currentBlock.RawText); if (Highlighter != null) { ThreadPool.QueueUserWorkItem(p => { blocksRunningCount++; Highlighter.Highlight(currentBlock.FormattedText); blocksRunningCount--; }); } }
private void DrawBlocks() { if (!IsLoaded || renderCanvas == null || lineNumbersCanvas == null) { return; } var dc = renderCanvas.GetContext(); var dc2 = lineNumbersCanvas.GetContext(); for (int i = 0; i < blocks.Count; i++) { InnerTextBlock block = blocks[i]; Point blockPos = block.Position; double top = blockPos.Y - VerticalOffset; double bottom = top + blockHeight; if (top < ActualHeight && bottom > 0) { try { if (TextToHighlight != null) { foreach (Match m in TextToHighlight.Matches(block.FormattedText.Text)) { Geometry highlight = block.FormattedText.BuildHighlightGeometry( new Point(2 - HorizontalOffset, block.Position.Y - this.VerticalOffset), m.Index, m.Length); if (highlight != null) { Brush brush = new SolidColorBrush(Brushes.LightCyan.Color); brush.Opacity = 0.5; dc.DrawGeometry(brush, null, highlight); } } } dc.DrawText(block.FormattedText, new Point(2 - HorizontalOffset, block.Position.Y - VerticalOffset)); lineNumbersCanvas.Width = GetFormattedTextWidth(string.Format("{0:0000}", totalLineCount)) + 5; dc2.DrawText(block.LineNumbers, new Point(lineNumbersCanvas.ActualWidth, 1 + block.Position.Y - VerticalOffset)); } catch { //Strange exception with large Copy } } } dc.Close(); dc2.Close(); }
// ----------------------------------------------------------- // Rendering // ----------------------------------------------------------- private void DrawBlocks() { if (!this.IsLoaded || this.renderCanvas == null || this.lineNumbersCanvas == null) { return; } this.CurrentHighlighter = HighlighterManager.Instance.Highlighters[this.SyntaxLanguage]; var dc = this.renderCanvas.GetContext(); var dc2 = this.lineNumbersCanvas.GetContext(); for (int i = 0; i < this.blocks.Count; i++) { InnerTextBlock block = this.blocks[i]; Point blockPos = block.Position; double top = blockPos.Y - this.VerticalOffset; double bottom = top + this.blockHeight; if (top < this.ActualHeight && bottom > 0) { try { dc.DrawText(block.FormattedText, new Point(2 - this.HorizontalOffset, block.Position.Y - this.VerticalOffset)); if (this.IsLineNumbersMarginVisible) { this.lineNumbersCanvas.Width = this.GetFormattedTextWidth(string.Format("{0:0000}", this.totalLineCount)) + 5; dc2.DrawText(block.LineNumbers, new Point(this.lineNumbersCanvas.ActualWidth, 1 + block.Position.Y - this.VerticalOffset)); } } catch { // Don't know why this exception is raised sometimes. // Reproduce steps: // - Sets a valid syntax highlighter on the box. // - Copy a large chunk of code in the clipboard. // - Paste it using ctrl+v and keep these buttons pressed. } } } dc.Close(); dc2.Close(); }
// ----------------------------------------------------------- // Rendering // ----------------------------------------------------------- private void DrawBlocks() { Debug.WriteLine("DrawBlocks: IsLoaded={0}, renderCanvas={1}, lineNumbersCanvas={2}", new Object[] { IsLoaded, renderCanvas == null, lineNumbersCanvas == null }); if (renderCanvas == null || lineNumbersCanvas == null) { return; } var dc = renderCanvas.GetContext(); var dc2 = lineNumbersCanvas.GetContext(); for (int i = 0; i < blocks.Count; i++) { InnerTextBlock block = blocks[i]; Point blockPos = block.Position; double top = blockPos.Y - VerticalOffset; double bottom = top + blockHeight; if (top < ActualHeight && bottom > 0) { try { dc.DrawText(block.FormattedText, new Point(2 - HorizontalOffset, block.Position.Y - VerticalOffset)); if (IsLineNumbersMarginVisible) { lineNumbersCanvas.Width = GetFormattedTextWidth(string.Format("{0:0000}", totalLineCount)) + 5; dc2.DrawText(block.LineNumbers, new Point(lineNumbersCanvas.ActualWidth, 1 + block.Position.Y - VerticalOffset)); } } catch { // Don't know why this exception is raised sometimes. // Reproduce steps: // - Sets a valid syntax highlighter on the box. // - Copy a large chunk of code in the clipboard. // - Paste it using ctrl+v and keep these buttons pressed. } } } dc.Close(); dc2.Close(); }
// ----------------------------------------------------------- // Updating & Block managing // ----------------------------------------------------------- private void UpdateBlocks() { if (blocks.Count == 0) return; // While something is visible after last block... while (!blocks.Last().IsLast && blocks.Last().Position.Y + blockHeight - VerticalOffset < ActualHeight) { int firstLineIndex = blocks.Last().LineEndIndex + 1; int lastLineIndex = firstLineIndex + maxLineCountInBlock - 1; lastLineIndex = lastLineIndex <= totalLineCount - 1 ? lastLineIndex : totalLineCount - 1; int fisrCharIndex = blocks.Last().CharEndIndex + 1; int lastCharIndex = TextUtilities.GetLastCharIndexFromLineIndex(Text, lastLineIndex); // to be optimized (forward search) if (lastCharIndex <= fisrCharIndex) { blocks.Last().IsLast = true; return; } InnerTextBlock block = new InnerTextBlock( fisrCharIndex, lastCharIndex, blocks.Last().LineEndIndex + 1, lastLineIndex, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); blocks.Add(block); FormatBlock(block); } }
/// <summary> /// Formats and Highlights the text of a block. /// </summary> private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock) { currentBlock.FormattedText = GetFormattedText(currentBlock.RawText); if (CurrentHighlighter != null) { ThreadPool.QueueUserWorkItem(p => { int previousCode = previousBlock != null ? previousBlock.Code : -1; currentBlock.Code = CurrentHighlighter.Highlight(currentBlock.FormattedText, previousCode); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(InvalidateVisual)); }); } }
private void InvalidateBlocks(int changeOffset) { InnerTextBlock blockChanged = null; for (int i = 0; i < blocks.Count; i++) { if (blocks[i].CharStartIndex <= changeOffset && changeOffset <= blocks[i].CharEndIndex + 1) { blockChanged = blocks[i]; break; } } if (blockChanged == null && changeOffset > 0) { blockChanged = blocks.Last(); } int fvline = blockChanged != null ? blockChanged.LineStartIndex : 0; int lvline = GetIndexOfLastVisibleLine(); int fvchar = blockChanged != null ? blockChanged.CharStartIndex : 0; int lvchar = TextUtilities.GetLastCharIndexFromLineIndex(Text, lvline); if (blockChanged != null) { blocks.RemoveRange(blocks.IndexOf(blockChanged), blocks.Count - blocks.IndexOf(blockChanged)); } int localLineCount = 1; int charStart = fvchar; int lineStart = fvline; for (int i = fvchar; i < Text.Length; i++) { if (Text[i] == '\n') { localLineCount += 1; } if (i == Text.Length - 1) { string blockText = Text.Substring(charStart); InnerTextBlock block = new InnerTextBlock( charStart, i, lineStart, lineStart + TextUtilities.GetLineCount(blockText) - 1, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); block.IsLast = true; foreach (InnerTextBlock b in blocks) { if (b.LineStartIndex == block.LineStartIndex) { throw new Exception(); } } blocks.Add(block); FormatBlock(block, blocks.Count > 1 ? blocks[blocks.Count - 2] : null); break; } if (localLineCount > maxLineCountInBlock) { InnerTextBlock block = new InnerTextBlock( charStart, i, lineStart, lineStart + maxLineCountInBlock - 1, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); foreach (InnerTextBlock b in blocks) { if (b.LineStartIndex == block.LineStartIndex) { throw new Exception(); } } blocks.Add(block); FormatBlock(block, blocks.Count > 1 ? blocks[blocks.Count - 2] : null); charStart = i + 1; lineStart += maxLineCountInBlock; localLineCount = 1; if (i > lvchar) { break; } } } }
public CodeEditor() { InitializeComponent(); HiglightContent = new CodeEditorContent(); Errors = new List <SyntaxError>(); MaxLineCountInBlock = 100; LineHeight = FontSize * 1.3; TabSize = 4; totalLineCount = 1; blocks = new List <InnerTextBlock>(); ToolTip = new ToolTip { IsOpen = false }; Loaded += (s, e) => { ApplyTemplate(); Text = Text.Replace("\t", new string(' ', TabSize)); renderCanvas = (DrawingControl)Template.FindName("PART_RenderCanvas", this); lineNumbersCanvas = (DrawingControl)Template.FindName("PART_LineNumbersCanvas", this); scrollViewer = (ScrollViewer)Template.FindName("PART_ContentHost", this); lineNumbersCanvas.Width = GetFormattedTextWidth($"{totalLineCount:0000}") + 5; scrollViewer.ScrollChanged += OnScrollChanged; InvalidateBlocks(0); InvalidateVisual(); }; SizeChanged += (s, e) => { if (e.HeightChanged == false) { return; } UpdateBlocks(); InvalidateVisual(); }; TextChanged += (s, e) => { UpdateTotalLineCount(); InvalidateBlocks(e.Changes.First().Offset); InvalidateVisual(); //If navigator exists, update its visuals if (navigator == null) { return; } navigator.LinkedScrollViewerHeight = scrollViewer.ViewportHeight; navigator.UpdateText(GetFormattedText(Text), new Point(2 - HorizontalOffset, VerticalOffset), scrollViewer.VerticalOffset); }; PreviewTextInput += (s, e) => { if (e.Text.Contains("{")) { WaitingForClosingBracket = true; } if (e.Text.Contains("}")) { WaitingForClosingBracket = false; } }; PreviewKeyDown += CodeEditor_OnPreviewKeyDown; SelectionChanged += CodeEditor_SelectionChanged; PreviewMouseDoubleClick += CodeEditor_MouseDoubleClick; MouseMove += (s, e) => { ToolTip localtool = ToolTip as ToolTip; if (localtool == null) { return; } Point mousePos = Mouse.GetPosition(renderCanvas); InnerTextBlock block = blocks.FirstOrDefault(b => new Rect(b.Position, new Size(b.FormattedText.Width, b.FormattedText.Height)).Contains(mousePos)); if (block == null) { localtool.IsOpen = false; return; } SyntaxError error = Errors.FirstOrDefault(ev => { int Line = ev.Line ?? -1; int Column = ev.Column ?? -1; int TagPos = CodeHelper.getStartCharOfPos(Text, Line, Column); return(TagPos >= block.CharStartIndex && TagPos <= block.CharEndIndex); }); if (error == null) { localtool.IsOpen = false; } else { localtool.HorizontalOffset = e.GetPosition(this).X; localtool.VerticalOffset = e.GetPosition(this).Y; localtool.IsOpen = true; localtool.Content = error.InnerMessage; } }; }
/// <summary> /// Formats and Highlights the text of a block. /// </summary> private void FormatBlock(InnerTextBlock currentBlock, InnerTextBlock previousBlock) { currentBlock.FormattedText = GetFormattedText(currentBlock.RawText); if (CurrentHighlighter != null) { ThreadPool.QueueUserWorkItem(p => { int previousCode = previousBlock != null ? previousBlock.Code : -1; currentBlock.Code = CurrentHighlighter.Highlight(currentBlock.FormattedText, previousCode); }); } }
private void InvalidateBlocks(int changeOffset) { InnerTextBlock blockChanged = blocks.FirstOrDefault(t => t.CharStartIndex <= changeOffset && changeOffset <= t.CharEndIndex + 1); if (blockChanged == null && changeOffset > 0) { blockChanged = blocks.Last(); } int fvline = blockChanged?.LineStartIndex ?? 0; int lvline = GetIndexOfLastVisibleLine(); int fvchar = blockChanged?.CharStartIndex ?? 0; int lvchar = CodeHelper.GetLastCharIndexFromLineIndex(Text, lvline); if (blockChanged != null) { blocks.RemoveRange(blocks.IndexOf(blockChanged), blocks.Count - blocks.IndexOf(blockChanged)); } int localLineCount = 1; int charStart = fvchar; int lineStart = fvline; for (int i = fvchar; i < Text.Length; i++) { if (Text[i] == '\n') { localLineCount += 1; } if (i == Text.Length - 1) { string blockText = Text.Substring(charStart); InnerTextBlock block = new InnerTextBlock( charStart, i, lineStart, lineStart + CodeHelper.GetLineCount(blockText) - 1, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); block.IsLast = true; if (blocks.Any(b => b.LineStartIndex == block.LineStartIndex)) { throw new Exception(); } blocks.Add(block); FormatBlock(block); break; } if (localLineCount <= maxLineCountInBlock) { continue; } { InnerTextBlock block = new InnerTextBlock( charStart, i, lineStart, lineStart + maxLineCountInBlock - 1, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); if (blocks.Any(b => b.LineStartIndex == block.LineStartIndex)) { throw new Exception(); } blocks.Add(block); FormatBlock(block); charStart = i + 1; lineStart += maxLineCountInBlock; localLineCount = 1; if (i > lvchar) { break; } } } }
private void InvalidateBlocks(int changeOffset) { InnerTextBlock blockChanged = blocks.FirstOrDefault(b=>b.CharStartIndex <= changeOffset && changeOffset <= b.CharEndIndex + 1); if (blockChanged == null && changeOffset > 0) blockChanged = blocks.Last(); int fvline = blockChanged != null ? blockChanged.LineStartIndex : 0; int lvline = GetIndexOfLastVisibleLine(); int fvchar = blockChanged != null ? blockChanged.CharStartIndex : 0; int lvchar = TextUtilities.GetLastCharIndexFromLineIndex(Text, lvline); if (blockChanged != null) blocks.RemoveRange(blocks.IndexOf(blockChanged), blocks.Count - blocks.IndexOf(blockChanged)); int localLineCount = 1; int charStart = fvchar; int lineStart = fvline; for (int i = fvchar; i < Text.Length; i++) { if (Text[i] == '\n') { localLineCount += 1; } if (i == Text.Length - 1) { string blockText = Text.Substring(charStart); InnerTextBlock block = new InnerTextBlock( charStart, i, lineStart, lineStart + TextUtilities.GetLineCount(blockText) - 1, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); block.IsLast = true; foreach (InnerTextBlock b in blocks) if (b.LineStartIndex == block.LineStartIndex) throw new Exception(); blocks.Add(block); FormatBlock(block); break; } if (localLineCount > maxLineCountInBlock) { InnerTextBlock block = new InnerTextBlock( charStart, i, lineStart, lineStart + maxLineCountInBlock - 1, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); foreach (InnerTextBlock b in blocks) if (b.LineStartIndex == block.LineStartIndex) throw new Exception(); blocks.Add(block); FormatBlock(block); charStart = i + 1; lineStart += maxLineCountInBlock; localLineCount = 1; if (i > lvchar) break; } } }
/// <summary> /// Formats and Highlights the text of a block. /// </summary> private void FormatBlock(InnerTextBlock currentBlock) { currentBlock.FormattedText = GetFormattedText(currentBlock.RawText); if (CurrentHighlighter != null) { ThreadPool.QueueUserWorkItem(p => { CurrentHighlighter.Highlight(currentBlock.FormattedText); currentBlock.Code = -1; }); } }
private void InvalidateBlocks(int changeOffset) { InnerTextBlock blockChanged = null; for (var i = 0; i < _blocks.Count; i++) { if (_blocks[i].CharStartIndex <= changeOffset && changeOffset <= _blocks[i].CharEndIndex + 1) { blockChanged = _blocks[i]; break; } } if (blockChanged == null && changeOffset > 0) { blockChanged = _blocks.Last(); } var fvline = blockChanged?.LineStartIndex ?? 0; var lvline = GetIndexOfLastVisibleLine(); var fvchar = blockChanged?.CharStartIndex ?? 0; var lvchar = Text.GetLastCharIndexFromLineIndex(lvline); if (blockChanged != null) { _blocks.RemoveRange(_blocks.IndexOf(blockChanged), _blocks.Count - _blocks.IndexOf(blockChanged)); } var localLineCount = 1; var charStart = fvchar; var lineStart = fvline; for (var i = fvchar; i < Text.Length; i++) { if (Text[i] == '\n') { localLineCount += 1; } if (i == Text.Length - 1) { var blockText = Text.Substring(charStart); var block = new InnerTextBlock( charStart, i, lineStart, lineStart + blockText.GetLineCount() - 1, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); block.IsLast = true; if (_blocks.Any(b => b.LineStartIndex == block.LineStartIndex)) { throw new Exception(); } _blocks.Add(block); FormatBlock(block, _blocks.Count > 1 ? _blocks[_blocks.Count - 2] : null); break; } if (localLineCount > _maxLineCountInBlock) { var block = new InnerTextBlock( charStart, i, lineStart, lineStart + _maxLineCountInBlock - 1, LineHeight); block.RawText = block.GetSubString(Text); block.LineNumbers = GetFormattedLineNumbers(block.LineStartIndex, block.LineEndIndex); if (_blocks.Any(b => b.LineStartIndex == block.LineStartIndex)) { throw new Exception(); } _blocks.Add(block); FormatBlock(block, _blocks.Count > 1 ? _blocks[_blocks.Count - 2] : null); charStart = i + 1; lineStart += _maxLineCountInBlock; localLineCount = 1; if (i > lvchar) { break; } } } }