using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using Storm.TextEditor.Core;
using Storm.TextEditor.Core.Splitting;
using Storm.TextEditor.Drawing;
using Storm.TextEditor.Editor.CodeCompletion;
using Storm.TextEditor.Editor.Forms;
using Storm.TextEditor.Editor.Interacting;
using Storm.TextEditor.Editor.Text;
using Storm.TextEditor.Editor.Undo;
using Storm.TextEditor.Interacting;
using Storm.TextEditor.Interacting.Keyboard;
using Storm.TextEditor.Interacting.Scrolling;
using Storm.TextEditor.Parser.Objects;
using Storm.TextEditor.Parser.Objects.Collections;
using Storm.TextEditor.Parser.XML;
using Storm.TextEditor.Win32;
using Storm.TextEditor.Win32.Enums;
using ScrollEventArgs = Storm.TextEditor.Interacting.Scrolling.ScrollEventArgs;
using ScrollEventHandler = Storm.TextEditor.Interacting.Scrolling.ScrollEventHandler;
namespace Storm.TextEditor.Editor
{
/// <summary>
/// Represents the TextEditor's child control that takes care of all the actual input from the user.
/// </summary>
[ToolboxItem(false)]
public sealed class TextEditorBase
: SplitViewChildControl
{
#region Fields
private int mouseX = 0;
private int mouseY = 0;
private int maxCharWidth = 8;
private int tabSpaces = 4;
private double scrollHandlerCurrentPosition = 0;
private string currentFileName = null;
private bool keepTabs = false;
private bool overWrite = false;
private bool keyDownHandled = false;
private Selection selection = null;
private Caret caret = null;
private MouseButtons mouseButton = MouseButtons.None;
private TextDrawType textDrawType = TextDrawType.StarBorder;
private CodeCompletionWindow codeCompletionWindow = null;
private WeakTimer caretTimer = null;
private FindReplace findReplaceDialog = null;
private ScrollHandler scrollHandler = null;
private PictureBox filler = null;
private ToolTip tooltip = null;
private IMEWindow imeWindow = null;
private IContainer components;
private IPainter painter = null;
private ViewPoint viewPoint = new ViewPoint();
#region Events
/// <summary>
/// Occurs when the clipboard is updated.
/// </summary>
public event CopyHandler ClipboardUpdated = null;
/// <summary>
/// Occurs when the caret has changed.
/// </summary>
public event EventHandler CaretChange = null;
/// <summary>
/// Occurs when the selection has changed.
/// </summary>
public event EventHandler SelectionChange = null;
/// <summary>
/// Occurs when the mouse pointer is over a row and a mouse button is pressed.
/// </summary>
public event RowMouseHandler RowMouseDown = null;
/// <summary>
/// Occurs when the mouse pointer is moved over a row.
/// </summary>
public event RowMouseHandler RowMouseMove = null;
/// <summary>
/// Occurs when a mouse button has been released.
/// </summary>
public event RowMouseHandler RowMouseUp = null;
/// <summary>
/// Occurs when a row has been clicked.
/// </summary>
public event RowMouseHandler RowClick = null;
/// <summary>
/// Occurs when when a row has been double clicked.
/// </summary>
public event RowMouseHandler RowDoubleClick = null;
/// <summary>
/// Occurs when a key is pressed while the control has focus.
/// </summary>
public new event KeyEventHandler KeyDown = null;
#endregion
#endregion
#region Properties
/// <summary>
/// Gets or sets the painter of the TextEditorBase.
/// </summary>
public IPainter Painter
{
get { return painter; }
set { painter = value; }
}
/// <summary>
/// Gets or sets the view point of the TextEditorBase.
/// </summary>
public ViewPoint ViewPoint
{
get { return viewPoint; }
set { viewPoint = value; }
}
/// <summary>
/// Gets or sets whether to keep tabs when indenting or replace them with spaces.
/// </summary>
public bool KeepTabs
{
get { return keepTabs; }
set { keepTabs = value; }
}
/// <summary>
/// Gets or sets the number of spaces a tab contains.
/// </summary>
public int TabSpaces
{
get { return TextEditor.TabSpaces; }
set { TextEditor.TabSpaces = value; }
}
/// <summary>
/// Gets or sets the FindReplace dialog of the TextEditorBase.
/// </summary>
public FindReplace FindReplaceDialog
{
get
{
this.CreateFindForm();
return findReplaceDialog;
}
set { findReplaceDialog = value; }
}
/// <summary>
/// Gets or sets the IMEWindow of the TextEditorBase.
/// </summary>
public IMEWindow IMEWindow
{
get { return imeWindow; }
set { imeWindow = value; }
}
/// <summary>
/// Gets or sets the current filename.
/// </summary>
[Browsable(false)]
[ReadOnly(true)]
public string FileName
{
get { return currentFileName; }
set
{
if (currentFileName != value)
currentFileName = value;
}
}
/// <summary>
/// Gets or sets the size of tabs in pixels.
/// </summary>
public int PixelTabSize
{
get { return this.TextEditor.TabSpaces * this.ViewPoint.CharWidth; }
}
/// <summary>
/// Gets whether the TextEditorBase is in Overwrite mode.
/// </summary>
[Browsable(false)]
public bool OverWrite
{
get { return overWrite; }
}
/// <summary>
/// Gets whether the user would be able to do a copy action.
/// </summary>
[Browsable(false)]
public bool CanCopy
{
get { return this.Selection.IsValid; }
}
/// <summary>
/// Gets whether the user would be able to do a paste action.
/// </summary>
[Browsable(false)]
public bool CanPaste
{
get
{
string clipboardData = "";
try
{
IDataObject dataObject = Clipboard.GetDataObject();
if (dataObject.GetDataPresent(DataFormats.Text))
clipboardData = dataObject.GetData(DataFormats.Text) as string;
if (clipboardData != null)
return true;
}
catch
{
}
return false;
}
}
/// <summary>
/// Gets whether the user would be able to do an undo action.
/// </summary>
[Browsable(false)]
public bool CanUndo
{
get { return this.Document.UndoStep > 0; }
}
/// <summary>
/// Gets whether the user would be able to do a redo action.
/// </summary>
[Browsable(false)]
public bool CanRedo
{
get
{
if (this.Document.UndoStep >= this.Document.UndoBuffer.Count)
return false;
else
return true;
}
}
/// <summary>
/// Gets the size (in pixels) of the font to use when rendering the content.
/// </summary>
public float FontSize
{
get { return this.TextEditor.FontSize; }
}
/// <summary>
/// Gets the indention style to use when inserting new lines.
/// </summary>
public IndentStyle Indent
{
get { return this.TextEditor.Indent; }
}
/// <summary>
/// Gets the SyntaxDocument the TextEditorBase is currently attatched to.
/// </summary>
public SyntaxDocument Document
{
get { return this.TextEditor.Document; }
}
/// <summary>
/// Gets the delay in milliseconds before the tooltip is displayed when hovering a collapsed section.
/// </summary>
public int TooltipDelay
{
get { return this.TextEditor.TooltipDelay; }
}
/// <summary>
/// Gets whether the TextEditorBase is readonly.
/// </summary>
public bool ReadOnly
{
get { return this.TextEditor.ReadOnly; }
}
/// <summary>
/// Gets or sets the name of the font to use when rendering the TextEditorBase.
/// </summary>
public string FontName
{
get { return this.TextEditor.FontName; }
}
/// <summary>
/// Gets the style to use when painting with Alt + (Arrow) keys.
/// </summary>
public TextDrawType TextDrawStyle
{
get { return textDrawType; }
set { textDrawType = value; }
}
/// <summary>
/// Gets whether the TextEditorBase should render bracket matching.
/// </summary>
public bool BracketMatching
{
get { return this.TextEditor.BracketMatching; }
}
/// <summary>
/// Gets whether the matching bracket should become bold when matched.
/// </summary>
public bool BracketBold
{
get { return this.TextEditor.BracketBold; }
}
/// <summary>
/// Gets whether the matching bracket should become italic when matched.
/// </summary>
public bool BracketItalic
{
get { return this.TextEditor.BracketItalic; }
}
/// <summary>
/// Gets whether the matching bracket should become underlined when matched.
/// </summary>
public bool BracketUnderline
{
get { return this.TextEditor.BracketUnderline; }
}
/// <summary>
/// Gets whether the matching bracket should become strikethroughed when matched.
/// </summary>
public bool BracketStrikethrough
{
get { return this.TextEditor.BracketStrikethrough; }
}
/// <summary>
/// Gets whether the TextEditorBase should render whitespace chars.
/// </summary>
public bool VirtualWhitespace
{
get { return this.TextEditor.VirtualWhitespace; }
}
/// <summary>
/// Gets the Color of the horizontal separators (a'la Visual Basic 6).
/// </summary>
public Color SeparatorColor
{
get { return this.TextEditor.SeparatorColor; }
}
/// <summary>
/// Gets the text color to use when rendering bracket matching.
/// </summary>
public Color BracketForeColor
{
get { return this.TextEditor.BracketForeColor; }
}
/// <summary>
/// Gets or sets the border color of active selection areas.
/// </summary>
public Color SelectionBorderColor
{
get { return this.TextEditor.SelectionBorderColor; }
}
/// <summary>
/// Gets or sets the border color of inactive selection areas.
/// </summary>
public Color InactiveSelectionBorderColor
{
get { return this.TextEditor.InactiveSelectionBorderColor; }
}
/// <summary>
/// Gets the background color to use when rendering bracket matches.
/// </summary>
public Color BracketBackColor
{
get { return this.TextEditor.BracketBackColor; }
}
/// <summary>
/// Gets the background color to use when rendering selected text.
/// </summary>
public Color SelectionBackColor
{
get { return this.TextEditor.SelectionBackColor; }
}
/// <summary>
/// Gets the background color to use when rendering inactive selected text.
/// </summary>
public Color InactiveSelectionBackColor
{
get { return this.TextEditor.InactiveSelectionBackColor; }
}
/// <summary>
/// Gets the color of the border between the line number area and the folding area.
/// </summary>
public Color LineNumberBorderColor
{
get { return this.TextEditor.LineNumberBorderColor; }
}
/// <summary>
/// Gets the text color to use when rendering breakpoints.
/// </summary>
public Color BreakpointForeColor
{
get { return this.TextEditor.BreakpointForeColor; }
}
/// <summary>
/// Gets the back color to use when rendering breakpoints.
/// </summary>
public Color BreakpointBackColor
{
get { return this.TextEditor.BreakpointBackColor; }
}
/// <summary>
/// Gets the text color to use when rendering line numbers.
/// </summary>
public Color LineNumberForeColor
{
get { return this.TextEditor.LineNumberForeColor; }
}
/// <summary>
/// Gets the back color to use when rendering the line number area.
/// </summary>
public Color LineNumberBackColor
{
get { return this.TextEditor.LineNumberBackColor; }
}
/// <summary>
/// Gets the color of the gutter margin.
/// </summary>
public Color GutterMarginColor
{
get { return this.TextEditor.GutterMarginColor; }
}
/// <summary>
/// <summary>
/// Gets or sets the color to use when rendering an expansion's background color.
/// </summary>
public Color ExpansionBackgroundColor
{
get { return this.TextEditor.ExpansionBackgroundColor; }
}
/// <summary>
/// Gets or sets the background color of the client area.
/// </summary>
public override Color BackColor
{
get { return this.TextEditor.BackColor; }
set { this.TextEditor.BackColor = value; }
}
/// <summary>
/// Gets the background color to use when rendering the active line.
/// </summary>
public Color HighlightedLineColor
{
get { return this.TextEditor.HighlightedLineColor; }
}
/// <summary>
/// Gets whether the TextEditorBase should highlight the active line.
/// </summary>
public bool HighlightActiveLine
{
get { return this.TextEditor.HighlightActiveLine; }
}
/// <summary>
/// Gets whether the TextEditorBase should render whitespace chars.
/// </summary>
public bool ShowWhitespace
{
get { return this.TextEditor.ShowWhitespace; }
}
/// <summary>
/// Gets whether the line number margin should be visible or not.
/// </summary>
public bool ShowLineNumbers
{
get { return this.TextEditor.ShowLineNumbers; }
}
/// <summary>
/// Gets whether the gutter margin should be visible or not.
/// </summary>
public bool ShowGutterMargin
{
get { return this.TextEditor.ShowGutterMargin; }
}
/// <summary>
/// Gets the width of the gutter margin. (In pixels)
/// </summary>
public int GutterMarginWidth
{
get { return this.TextEditor.GutterMarginWidth; }
}
/// <summary>
/// Gets whether the TextEditorBase should render Tab Guides.
/// </summary>
public bool ShowTabGuides
{
get { return this.TextEditor.ShowTabGuides; }
}
/// <summary>
/// Gets the color to use when rendering whitespace chars.
/// </summary>
public Color WhitespaceColor
{
get { return this.TextEditor.WhitespaceColor; }
}
/// <summary>
/// Gets the color to use when rendering tab guides.
/// </summary>
public Color TabGuideColor
{
get { return this.TextEditor.TabGuideColor; }
}
/// <summary>
/// Gets the color to use when rendering bracket matching borders.
/// </summary>
public Color BracketBorderColor
{
get { return this.TextEditor.BracketBorderColor; }
}
/// <summary>
/// Gets the color to use when rendering a hovered row.
/// </summary>
public Color RowHoverBackColor
{
get { return this.TextEditor.RowHoverBackColor; }
}
/// <summary>
/// Gets or sets the color to use when rendering a row's expansion's inner symbol. (-/+)
/// </summary>
public Color ExpansionSymbolColor
{
get { return this.TextEditor.ExpansionSymbolColor; }
}
/// <summary>
/// Gets the color to use when rendering Outline symbols.
/// </summary>
public Color OutlineColor
{
get { return this.TextEditor.OutlineColor; }
}
/// <summary>
/// Gets the color to use when rendering a collapsed expansion's background.
/// </summary>
public Color CollapsedBackgroundColor
{
get { return this.TextEditor.CollapsedBackgroundColor; }
}
/// <summary>
/// Gets or sets whether the TextEditorBase should use smooth scrolling.
/// </summary>
public bool SmoothScroll
{
get { return this.TextEditor.SmoothScroll; }
}
/// <summary>
/// Gets the number of pixels the screen should be scrolled per scroll when smooth scrolling is enabled.
/// </summary>
public int SmoothScrollSpeed
{
get { return this.TextEditor.SmoothScrollSpeed; }
}
/// <summary>
/// Gets whether the TextEditorBase should parse all of its contents when more content is drag dropped/pasted into it.
/// </summary>
public bool ParseOnPaste
{
get { return this.TextEditor.ParseOnPaste; }
}
/// <summary>
/// Gets a value indicating whether the TextEditorBase should use a dotted margin border.
/// </summary>
/// <value>
/// <c>true</c> if the TextEditorBase should use a dotted margin border; otherwise, <c>false</c>.
/// </value>
public bool UseDottedMarginBorder
{
get { return this.TextEditor.UseDottedMarginBorder; }
}
/// <summary>
/// Gets the Caret object.
/// </summary>
public Caret Caret
{
get { return caret; }
}
/// <summary>
/// Gets the Selection object.
/// </summary>
public Selection Selection
{
get { return selection; }
}
/// <summary>
/// Gets the code completion window.
/// </summary>
/// <value>The code completion window.</value>
public CodeCompletionWindow CodeCompletionWindow
{
get { return codeCompletionWindow; }
}
#endregion
#region Methods
#region Private
/// <summary>
/// Finds the matched word.
/// </summary>
/// <param name="list">The list.</param>
/// <param name="wordToSearch">The word to search.</param>
/// <returns>The found word.</returns>
private string FindMatchedWord(ArrayList list, string wordToSearch)
{
int binaryMatch = 0;
string nextMatch = "";
string lastMatch = "";
ArrayList nextList = null;
list.Sort();
binaryMatch = list.BinarySearch(wordToSearch);
if (binaryMatch < 0)
binaryMatch = ~binaryMatch;
if (binaryMatch > 0)
{
try
{
if (binaryMatch < list.Count)
nextList = list.GetRange(binaryMatch + 1, 1);
}
catch
{
nextList = list.GetRange(binaryMatch, 1);
lastMatch = nextList[0].ToString();
}
}
if (nextList != null)
nextMatch = nextList[0].ToString();
if (nextMatch.IndexOf(wordToSearch, StringComparison.OrdinalIgnoreCase) < 0)
{
if (binaryMatch < list.Count)
lastMatch = list.GetRange(binaryMatch, 1)[0].ToString();
}
return lastMatch;
}
/// <summary>
/// Creates the find form.
/// </summary>
private void CreateFindForm()
{
if (this.TextEditor.DisableFindForm == false && findReplaceDialog == null)
this.FindReplaceDialog = new FindReplace(this);
}
/// <summary>
/// Updates the sizes and visibility of the SplitViewChildControl's child Controls,
/// including the left and top SplitViewThumbControl and the ScrollBars. Also updates margins.
/// </summary>
private void UpdateContent()
{
this.SuspendLayout();
if (this.Visible == true && this.Width > 0 && this.Height > 0 && this.IsHandleCreated == true)
{
if (filler == null)
return;
this.TopThumb.Width = SystemInformation.VerticalScrollBarWidth;
this.LeftThumb.Height = SystemInformation.HorizontalScrollBarHeight;
vScroll.Width = SystemInformation.VerticalScrollBarWidth;
hScroll.Height = SystemInformation.HorizontalScrollBarHeight;
if (this.TopThumbVisible == true)
{
vScroll.Top = this.TopThumb.Height;
if (hScroll.Visible == true)
vScroll.Height = this.ClientHeight - hScroll.Height - this.TopThumb.Height;
else
vScroll.Height = this.ClientHeight - this.TopThumb.Height;
}
else
{
if (hScroll.Visible == true)
vScroll.Height = this.ClientHeight - hScroll.Height;
else
vScroll.Height = this.ClientHeight;
vScroll.Top = 0;
}
if (this.LeftThumbVisible == true)
{
hScroll.Left = this.LeftThumb.Width;
if (vScroll.Visible == true)
hScroll.Width = this.ClientWidth - vScroll.Width - this.LeftThumb.Width;
else
hScroll.Width = this.ClientWidth - this.LeftThumb.Width;
}
else
{
if (vScroll.Visible == true)
hScroll.Width = this.ClientWidth - vScroll.Width;
else
hScroll.Width = this.ClientWidth;
hScroll.Left = 0;
}
if (this.Painter != null)
this.Painter.Resize();
vScroll.Left = this.ClientWidth - vScroll.Width;
hScroll.Top = this.ClientHeight - hScroll.Height;
this.LeftThumb.Left = 0;
this.LeftThumb.Top = hScroll.Top;
this.TopThumb.Left = vScroll.Left;
this.TopThumb.Top = 0;
filler.Left = vScroll.Left;
filler.Top = hScroll.Top;
filler.Width = vScroll.Width;
filler.Height = hScroll.Height;
}
this.ResumeLayout(false);
}
/// <summary>
/// Inserts a new line.
/// </summary>
private void InsertEnter()
{
this.Caret.CropPosition();
if (this.Selection.IsValid == true)
{
this.Selection.DeleteSelection();
this.InsertEnter();
}
else
{
Row currentRow = this.Caret.CurrentRow;
string indentationLevel = "";
switch (this.Indent)
{
case IndentStyle.None:
this.Document.InsertText("\n", this.Caret.Position.X, this.Caret.Position.Y);
this.Caret.CurrentRow.Parse();
this.Caret.MoveDown(false);
this.Caret.CurrentRow.Parse(true);
this.Caret.Position.X = 0;
this.Caret.SetPosition(this.Caret.Position);
break;
case IndentStyle.LastRow:
indentationLevel = currentRow.GetLeadingWhitespace();
int maximumLength = Math.Min(indentationLevel.Length, this.Caret.Position.X);
string split = "\n" + indentationLevel.Substring(0, maximumLength);
this.Document.InsertText(split, this.Caret.Position.X, this.Caret.Position.Y);
this.Document.ResetVisibleRows();
this.Caret.CurrentRow.Parse(true);
this.Caret.MoveDown(false);
this.Caret.CurrentRow.Parse(true);
this.Caret.Position.X = indentationLevel.Length;
this.Caret.SetPosition(this.Caret.Position);
currentRow.Parse(true);
currentRow.NextRow.Parse(true);
break;
case IndentStyle.Scope:
currentRow.Parse(true);
if (currentRow.ShouldOutdent == true)
this.OutdentEndRow();
this.Document.InsertText("\n", this.Caret.Position.X, this.Caret.Position.Y);
this.Caret.CurrentRow.Parse();
this.Caret.MoveDown(false);
this.Caret.CurrentRow.Parse(false);
if (keepTabs == true)
indentationLevel = new string('\t', this.Caret.CurrentRow.Depth);
else
indentationLevel = new string(' ', tabSpaces * this.Caret.CurrentRow.Depth);
this.Document.InsertText(indentationLevel, 0, this.Caret.Position.Y);
this.Caret.CurrentRow.Parse(true);
this.Caret.Position.X = indentationLevel.Length;
this.Caret.SetPosition(this.Caret.Position);
this.Caret.CropPosition();
this.Selection.ClearSelection();
currentRow.Parse(true);
currentRow.NextRow.Parse(true);
break;
}
this.ScrollIntoView();
}
}
/// <summary>
/// Outdents the end row.
/// </summary>
private void OutdentEndRow()
{
if (this.Indent == IndentStyle.Scope)
{
Row currentRow = this.Caret.CurrentRow;
string indentation = currentRow.Text.Substring(0, currentRow.GetLeadingWhitespace().Length);
string newIndentation = "";
if (keepTabs == true)
newIndentation = new string('\t', this.Caret.CurrentRow.Depth);
else
newIndentation = new string(' ', tabSpaces * this.Caret.CurrentRow.Depth);
TextRange textRange = new TextRange();
textRange.FirstColumn = 0;
textRange.LastColumn = currentRow.GetLeadingWhitespace().Length;
textRange.FirstRow = currentRow.Index;
textRange.LastRow = currentRow.Index;
this.Document.DeleteRange(textRange);
this.Document.InsertText(newIndentation, 0, currentRow.Index, true);
this.Caret.Position.X += newIndentation.Length;
this.Caret.SetPosition(this.Caret.Position);
this.Caret.CropPosition();
this.Selection.ClearSelection();
this.Caret.CurrentRow.Parse(true);
}
}
/// <summary>
/// Performs a delete action one step forward from the current caret position.
/// </summary>
private void DeleteForward()
{
this.Caret.CropPosition();
if (this.Selection.IsValid == true)
this.Selection.DeleteSelection();
else
{
Row currentRow = this.Caret.CurrentRow;
if (this.Caret.Position.X == currentRow.Text.Length)
{
if (this.Caret.Position.Y <= Document.Count - 2)
{
TextRange textRange = new TextRange();
textRange.FirstColumn = this.Caret.Position.X;
textRange.FirstRow = this.Caret.Position.Y;
textRange.LastRow = textRange.FirstRow + 1;
textRange.LastColumn = 0;
this.Document.DeleteRange(textRange);
this.Document.ResetVisibleRows();
}
}
else
{
TextRange textRange = new TextRange();
textRange.FirstColumn = this.Caret.Position.X;
textRange.FirstRow = this.Caret.Position.Y;
textRange.LastRow = textRange.FirstRow;
textRange.LastColumn = textRange.FirstColumn + 1;
this.Document.DeleteRange(textRange);
this.Document.ResetVisibleRows();
this.Caret.CurrentRow.Parse(true);
}
}
}
/// <summary>
/// Performs a delete action one step backwards from the current caret position.
/// </summary>
private void DeleteBackwards()
{
this.Caret.CropPosition();
if (this.Selection.IsValid == true)
this.Selection.DeleteSelection();
else
{
Row currentRow = this.Caret.CurrentRow;
if (this.Caret.Position.X == 0)
{
if (this.Caret.Position.Y > 0)
{
this.Caret.Position.Y--;
this.Caret.MoveEnd(false);
this.DeleteForward();
this.Document.ResetVisibleRows();
}
}
else
{
if (this.Caret.Position.X >= currentRow.Text.Length)
{
TextRange textRange = new TextRange();
textRange.FirstColumn = this.Caret.Position.X - 1;
textRange.FirstRow = this.Caret.Position.Y;
textRange.LastRow = textRange.FirstRow;
textRange.LastColumn = textRange.FirstColumn + 1;
if (this.Caret.Position.X - tabSpaces > -1)
{
if (this.Caret.CurrentRow.Text.Substring(this.Caret.Position.X - tabSpaces, tabSpaces) == new string(' ', tabSpaces))
{
textRange.FirstColumn = this.Caret.Position.X - tabSpaces;
textRange.LastColumn = this.Caret.Position.X;
}
}
this.Document.DeleteRange(textRange);
this.Document.ResetVisibleRows();
this.Caret.MoveEnd(false);
this.Caret.CurrentRow.Parse();
}
else
{
bool tabDeleted = false;
TextRange textRange = new TextRange();
textRange.FirstColumn = this.Caret.Position.X - 1;
textRange.FirstRow = this.Caret.Position.Y;
textRange.LastRow = textRange.FirstRow;
textRange.LastColumn = textRange.FirstColumn + 1;
if (this.Caret.Position.X - tabSpaces > -1)
{
if (this.Caret.CurrentRow.Text.Substring(this.Caret.Position.X - tabSpaces, tabSpaces) == new string(' ', tabSpaces))
{
textRange.FirstColumn = this.Caret.Position.X - tabSpaces;
textRange.LastColumn = this.Caret.Position.X;
tabDeleted = true;
}
}
this.Document.DeleteRange(textRange);
this.Document.ResetVisibleRows();
if (tabDeleted == false)
this.Caret.MoveLeft(false);
else
{
this.Caret.MoveEnd(false);
this.Caret.MoveLeft(false);
}
this.Caret.CurrentRow.Parse();
}
}
}
}
/// <summary>
/// Scrolls the screen.
/// </summary>
/// <param name="scrollAmount">The scroll amount.</param>
private void ScrollScreen(int scrollAmount)
{
this.ScrollScreen(scrollAmount, 2);
}
/// <summary>
/// Scrolls the screen.
/// </summary>
/// <param name="scrollAmount">The scroll amount.</param>
/// <param name="speed">The speed.</param>
private void ScrollScreen(int scrollAmount, int speed)
{
tooltip.RemoveAll();
int newScrollValue = vScroll.Value + scrollAmount;
newScrollValue = Math.Max(newScrollValue, vScroll.Minimum);
newScrollValue = Math.Min(newScrollValue, vScroll.Maximum);
if (newScrollValue >= vScroll.Maximum - 2)
newScrollValue = vScroll.Maximum - 2;
vScroll.Value = newScrollValue;
this.Redraw();
}
/// <summary>
/// Pastes the text on the user's clipboard.
/// </summary>
private void PasteText()
{
IDataObject dataObject = Clipboard.GetDataObject();
string clipboardText = "";
if (dataObject.GetDataPresent(DataFormats.UnicodeText) == true)
clipboardText = dataObject.GetData(DataFormats.UnicodeText) as string;
else if (dataObject.GetDataPresent(DataFormats.Text) == true)
clipboardText = dataObject.GetData(DataFormats.Text) as string;
this.InsertText(clipboardText);
if (this.ParseOnPaste == true)
this.Document.ParseAll(true);
}
/// <summary>
/// Begins a drag drop operation.
/// </summary>
private void BeginDragDrop()
{
this.DoDragDrop(this.Selection.Text, DragDropEffects.All);
}
/// <summary>
/// Redraws this instance.
/// </summary>
private void Redraw()
{
this.Invalidate();
}
/// <summary>
/// Redraws the caret.
/// </summary>
private void RedrawCaret()
{
using (Graphics gfx = this.CreateGraphics())
this.Painter.RenderCaret(gfx);
}
/// <summary>
/// Sets the mouse cursor.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
private void SetMouseCursor(int x, int y)
{
if (this.TextEditor.LockCursorUpdate == true)
{
this.Cursor = this.TextEditor.Cursor;
return;
}
if (this.ViewPoint.Action == TextAction.DragText)
this.Cursor = Cursors.Hand;
else
{
if (x < this.ViewPoint.TotalMarginWidth)
{
if (x < this.ViewPoint.GutterMarginWidth)
this.Cursor = Cursors.Arrow;
else
{
Assembly assembly = this.GetType().Assembly;
Stream cursorStream = assembly.GetManifestResourceStream("Storm.TextEditor.Resources.FlippedCursor.cur");
this.Cursor = new Cursor(cursorStream);
}
}
else
{
if (x > this.ViewPoint.TextMargin - 8)
{
if (this.IsOverSelection(x, y) == true && this.ViewPoint.Action != TextAction.Select)
this.Cursor = Cursors.Arrow;
else
{
TextPoint textPoint = this.Painter.GetTextPointAtPixel(x, y);
Word textPointWord = this.Document.GetWordFromPos(textPoint);
if (textPointWord != null)
{
WordMouseEventArgs wordMouseEventArgs = new WordMouseEventArgs();
wordMouseEventArgs.Pattern = textPointWord.Pattern;
wordMouseEventArgs.Button = MouseButtons.None;
wordMouseEventArgs.Cursor = Cursors.IBeam;
wordMouseEventArgs.Word = textPointWord;
this.TextEditor.OnWordMouseHover(ref wordMouseEventArgs);
this.Cursor = wordMouseEventArgs.Cursor;
}
else
this.Cursor = Cursors.IBeam;
}
}
else
this.Cursor = Cursors.Arrow;
}
}
}
/// <summary>
/// Copies the selected text to the clipboard.
/// </summary>
private void CopyText()
{
if (this.Selection.IsValid == false)
return;
if (this.TextEditor.CopyAsRTF == true)
this.CopyAsRtf();
else
{
try
{
if (this.Selection != null)
{
Clipboard.SetDataObject(this.Selection.Text, true);
CopyEventArgs copyEventArgs = new CopyEventArgs();
copyEventArgs.Text = this.Selection.Text;
this.OnClipboardUpdated(copyEventArgs);
}
}
catch
{
}
}
}
/// <summary>
/// Gets the type of the char.
/// </summary>
/// <param name="characterString">The character string.</param>
/// <returns>The type of the char.</returns>
private int GetCharType(string characterString)
{
string firstType = " \t";
string secondType = ".,-+'?´=)(/&%¤#!\"\\<>[]$£@*:;{}";
if (firstType.IndexOf(characterString) >= 0)
return 1;
if (secondType.IndexOf(characterString) >= 0)
return 2;
return 3;
}
/// <summary>
/// Selects the pattern.
/// </summary>
/// <param name="rowIndex">Index of the row.</param>
/// <param name="column">The column.</param>
/// <param name="length">The length.</param>
private void SelectPattern(int rowIndex, int column, int length)
{
this.Selection.Bounds.FirstColumn = column;
this.Selection.Bounds.FirstRow = rowIndex;
this.Selection.Bounds.LastColumn = column + length;
this.Selection.Bounds.LastRow = rowIndex;
this.Caret.Position.X = column + length;
this.Caret.Position.Y = rowIndex;
this.Caret.CurrentRow.EnsureVisible();
this.ScrollIntoView();
this.Redraw();
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new Container();
ResourceManager resources = new ResourceManager(typeof(TextEditorBase));
filler = new PictureBox();
caretTimer = new WeakTimer(components);
tooltip = new ToolTip(components);
this.SuspendLayout();
scrollHandler = new ScrollHandler();
scrollHandler.Image = ((Bitmap)(resources.GetObject("ScrollHandler.Image")));
scrollHandler.Location = new Point(197, 157);
scrollHandler.Name = "scrollHandler";
scrollHandler.Size = new Size(28, 28);
scrollHandler.TabIndex = 4;
scrollHandler.TransparencyKey = Color.FromArgb(255, 0, 255);
scrollHandler.Visible = false;
scrollHandler.EndScroll += this.OnScrollHandlerEndScroll;
scrollHandler.BeginScroll += this.OnScrollHandlerBeginScroll;
scrollHandler.Scroll += this.OnScrollHandlerScroll;
hScroll.Cursor = Cursors.Default;
hScroll.Scroll += this.OnHoritonzalScrollBarScroll;
vScroll.Visible = false;
vScroll.Cursor = Cursors.Default;
vScroll.Scroll += this.OnVerticalScrollBarScroll;
vScroll.Visible = false;
caretTimer.Enabled = true;
caretTimer.Interval = 500;
caretTimer.Tick += this.OnCaretTimerTick;
tooltip.AutoPopDelay = 50000;
tooltip.InitialDelay = 0;
tooltip.ReshowDelay = 1000;
tooltip.ShowAlways = true;
codeCompletionWindow = new CodeCompletionWindow(this.TextEditor);
codeCompletionWindow.Visible = false;
this.Controls.Add(codeCompletionWindow);
this.TopThumb.BackColor = SystemColors.Control;
this.TopThumb.Cursor = Cursors.HSplit;
this.TopThumb.Location = new Point(101, 17);
this.TopThumb.Name = "TopThumb";
this.TopThumb.Size = new Size(16, 8);
this.TopThumb.TabIndex = 3;
this.TopThumb.Visible = false;
this.LeftThumb.BackColor = SystemColors.Control;
this.LeftThumb.Cursor = System.Windows.Forms.Cursors.VSplit;
this.LeftThumb.Location = new Point(423, 17);
this.LeftThumb.Name = "LeftThumb";
this.LeftThumb.Size = new Size(8, 16);
this.LeftThumb.TabIndex = 3;
this.LeftThumb.Visible = false;
this.AllowDrop = true;
this.Controls.Add(scrollHandler);
this.Size = new Size(240, 216);
this.LostFocus += this.OnLeave;
this.GotFocus += this.OnEnter;
this.ResumeLayout(false);
}
/// <summary>
/// Moves the caret to the next word.
/// </summary>
/// <param name="select">if set to <c>true</c> [select].</param>
private void MoveCaretToNextWord(bool select)
{
int x = this.Caret.Position.X;
int y = this.Caret.Position.Y;
string currentCharacter = "";
int currentCharacterType = 0;
bool found = false;
if (x == Caret.CurrentRow.Text.Length)
currentCharacterType = 1;
else
{
currentCharacter = this.Document[y].Text.Substring(this.Caret.Position.X, 1);
currentCharacterType = this.GetCharType(currentCharacter);
}
while (y < this.Document.Count)
{
while (x < this.Document[y].Text.Length)
{
string currentLocalCharacter = this.Document[y].Text.Substring(x, 1);
int currentLocalCharacterType = this.GetCharType(currentLocalCharacter);
if (currentLocalCharacterType != currentCharacterType)
{
if (currentLocalCharacterType == 1)
currentCharacterType = 1;
else
{
found = true;
break;
}
}
x++;
}
if (found == true)
break;
x = 0;
y++;
}
if (y >= this.Document.Count - 1)
{
y = this.Document.Count - 1;
if (x >= this.Document[y].Text.Length)
x = this.Document[y].Text.Length - 1;
if (x == -1)
x = 0;
}
this.Caret.SetPosition(new TextPoint(x, y));
if (select == false)
this.Selection.ClearSelection();
if (select == true)
this.Selection.MakeSelection();
this.ScrollIntoView();
}
/// <summary>
/// Moves the caret to the previous word.
/// </summary>
/// <param name="select">if set to <c>true</c> [select].</param>
private void MoveCaretToPreviousWord(bool select)
{
int x = this.Caret.Position.X;
int y = this.Caret.Position.Y;
string currentCharacter = "";
int currentCharacterType = 0;
bool found = false;
if (x == this.Caret.CurrentRow.Text.Length)
{
currentCharacterType = 1;
x = this.Caret.CurrentRow.Text.Length - 1;
}
else
{
currentCharacter = this.Document[y].Text.Substring(this.Caret.Position.X, 1);
currentCharacterType = this.GetCharType(currentCharacter);
}
while (y >= 0)
{
while (x >= 0 && x < this.Document[y].Text.Length)
{
string currentLocalCharacter = this.Document[y].Text.Substring(x, 1);
int currentLocalCharacterType = this.GetCharType(currentLocalCharacter);
if (currentLocalCharacterType != currentCharacterType)
{
found = true;
string currentLoopCharacter = this.Document[y].Text.Substring(x, 1);
int currentLoopCharacterType = currentLocalCharacterType;
while (x > 0)
{
currentLoopCharacter = this.Document[y].Text.Substring(x, 1);
currentLoopCharacterType = this.GetCharType(currentLoopCharacter);
if (currentLoopCharacterType != currentLocalCharacterType)
{
x++;
break;
}
x--;
}
break;
}
x--;
}
if (found == true)
break;
if (y == 0)
{
x = 0;
break;
}
y--;
x = this.Document[y].Text.Length - 1;
}
this.Caret.SetPosition(new TextPoint(x, y));
if (select == false)
this.Selection.ClearSelection();
if (select == true)
this.Selection.MakeSelection();
this.ScrollIntoView();
}
/// <summary>
/// Copies the current selection as Rtf format.
/// </summary>
private void CopyAsRtf()
{
TextStyle[] textStyles = this.Document.Parser.Language.Styles;
this.Document.ParseAll(true);
int firstRowIndex = Selection.LogicalBounds.FirstRow;
int lastRowIndex = Selection.LogicalBounds.LastRow;
int firstColumnIndex = Selection.LogicalBounds.FirstColumn;
int lastColumnIndex = Selection.LogicalBounds.LastColumn;
StringBuilder rtfBuilder = new StringBuilder();
rtfBuilder.Append(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1053{\fonttbl{\f0\fmodern\fprq1\fcharset0 " + this.FontName + @";}}");
rtfBuilder.Append(@"{\colortbl ;");
foreach (TextStyle textStyle in textStyles)
{
rtfBuilder.AppendFormat("\\red{0}\\green{1}\\blue{2};", textStyle.ForeColor.R, textStyle.ForeColor.G, textStyle.ForeColor.B);
rtfBuilder.AppendFormat("\\red{0}\\green{1}\\blue{2};", textStyle.BackColor.R, textStyle.BackColor.G, textStyle.BackColor.B);
}
rtfBuilder.Append(@";}");
rtfBuilder.Append(@"\viewkind4\uc1\pard\f0\fs20");
bool doneLooping = false;
for (int rowIndex = firstRowIndex; rowIndex <= lastRowIndex; rowIndex++)
{
Row currentRow = this.Document[rowIndex];
foreach (Word currentWord in currentRow)
{
if (rowIndex == firstRowIndex && currentWord.Column + currentWord.Text.Length < firstColumnIndex)
continue;
bool rowIsFirst = (rowIndex == firstRowIndex && currentWord.Column <= firstColumnIndex && currentWord.Column + currentWord.Text.Length > firstColumnIndex);
bool rowIsLast = (rowIndex == lastRowIndex && currentWord.Column < lastColumnIndex && currentWord.Column + currentWord.Text.Length > lastColumnIndex);
if (currentWord.Type == WordType.Word && currentWord.Style != null)
{
int currentTextStyleIndex = Array.IndexOf(textStyles, currentWord.Style);
currentTextStyleIndex *= 2;
currentTextStyleIndex++;
rtfBuilder.Append("{\\cf" + currentTextStyleIndex.ToString());
if (currentWord.Style.Transparent == false)
rtfBuilder.Append("\\highlight" + (currentTextStyleIndex + 1).ToString());
rtfBuilder.Append(" ");
}
if (currentWord.Style != null)
{
if (currentWord.Style.Bold == true)
rtfBuilder.Append(@"\b ");
if (currentWord.Style.Underline == true)
rtfBuilder.Append(@"\ul ");
if (currentWord.Style.Italic == true)
rtfBuilder.Append(@"\i ");
}
string currentWordText = currentWord.Text;
if (rowIsFirst == true)
currentWordText = currentWordText.Substring(firstColumnIndex - currentWord.Column);
if (rowIsLast == true)
currentWordText = currentWordText.Substring(0, lastColumnIndex - currentWord.Column);
currentWordText = currentWordText.Replace(@"\", @"\\").Replace(@"}", @"\}").Replace(@"{", @"\{");
rtfBuilder.Append(currentWordText);
if (currentWord.Style != null)
{
if (currentWord.Style.Bold == true)
rtfBuilder.Append(@"\b0 ");
if (currentWord.Style.Underline == true)
rtfBuilder.Append(@"\ul0 ");
if (currentWord.Style.Italic == true)
rtfBuilder.Append(@"\i0 ");
}
if (currentWord.Type == WordType.Word && currentWord.Style != null)
rtfBuilder.Append("}");
if (rowIsLast == true)
{
doneLooping = true;
break;
}
}
if (doneLooping == true)
break;
rtfBuilder.Append(@"\par");
}
DataObject dataObject = new DataObject();
dataObject.SetData(DataFormats.Rtf, rtfBuilder.ToString());
string selectionText = this.Selection.Text;
dataObject.SetData(DataFormats.Text, selectionText);
Clipboard.SetDataObject(dataObject);
CopyEventArgs copyEventArgs = new CopyEventArgs();
copyEventArgs.Text = selectionText;
this.OnClipboardUpdated(copyEventArgs);
}
/// <summary>
/// Selects the current word.
/// </summary>
private void SelectCurrentWord()
{
Row currentRow = this.Caret.CurrentRow;
if (currentRow.Text == "")
return;
if (this.Caret.Position.X >= currentRow.Text.Length)
return;
string currentCaretCharacter = currentRow.Text.Substring(this.Caret.Position.X, 1);
int characterType = this.GetCharType(currentCaretCharacter);
int leftPosition = this.Caret.Position.X;
int rightPosition = this.Caret.Position.X;
while (leftPosition >= 0 && this.GetCharType(currentRow.Text.Substring(leftPosition, 1)) == characterType)
leftPosition--;
while (rightPosition <= currentRow.Text.Length - 1 && this.GetCharType(currentRow.Text.Substring(rightPosition, 1)) == characterType)
rightPosition++;
this.Selection.Bounds.FirstRow = this.Selection.Bounds.LastRow = currentRow.Index;
this.Selection.Bounds.FirstColumn = leftPosition + 1;
this.Selection.Bounds.LastColumn = rightPosition;
this.Caret.Position.X = rightPosition;
this.Caret.SetPosition(Caret.Position);
this.Redraw();
}
#endregion
#region Public
/// <summary>
/// Removes the focus.
/// </summary>
public void RemoveFocus()
{
if (this.ContainsFocus == false)
{
caretTimer.Enabled = false;
this.Caret.Blink = false;
}
this.Redraw();
}
/// <summary>
/// Setups the view point members of the TextEditorBase.
/// </summary>
public void SetupViewPoint()
{
if (this.ViewPoint.RowHeight == 0)
this.ViewPoint.RowHeight = 48;
if (this.ViewPoint.CharWidth == 0)
this.ViewPoint.CharWidth = 16;
this.ViewPoint.FirstVisibleColumn = hScroll.Value;
this.ViewPoint.FirstVisibleRow = vScroll.Value;
this.ViewPoint.VisibleRowCount = 0;
if (hScroll.Visible == true)
this.ViewPoint.VisibleRowCount = (this.Height - hScroll.Height) / this.ViewPoint.RowHeight + 1;
else
this.ViewPoint.VisibleRowCount = (this.Height - hScroll.Height) / this.ViewPoint.RowHeight + 2;
if (this.ShowGutterMargin == true)
this.ViewPoint.GutterMarginWidth = this.GutterMarginWidth;
else
this.ViewPoint.GutterMarginWidth = 0;
if (this.ShowLineNumbers == true)
{
int rowCount = (this.Document.Count).ToString().Length;
string lineNumberString = new string('9', rowCount);
this.ViewPoint.LineNumberMarginWidth = 25 + this.Painter.MeasureString(lineNumberString).Width;
}
else
this.ViewPoint.LineNumberMarginWidth = 0;
this.ViewPoint.TotalMarginWidth = this.ViewPoint.GutterMarginWidth + this.ViewPoint.LineNumberMarginWidth;
if (this.Document.Folding == true)
this.ViewPoint.TextMargin = this.ViewPoint.TotalMarginWidth + 20;
else
this.ViewPoint.TextMargin = this.ViewPoint.TotalMarginWidth + 7;
this.ViewPoint.ClientAreaWidth = this.Width - vScroll.Width - this.ViewPoint.TextMargin;
this.ViewPoint.ClientAreaStart = this.ViewPoint.FirstVisibleColumn * this.ViewPoint.CharWidth;
}
/// <summary>
/// Gets the pixel at the text point.
/// </summary>
/// <param name="textPoint">The text point.</param>
/// <returns>The found point.</returns>
public Point GetPixelAtTextPoint(TextPoint textPoint)
{
return this.Painter.GetPixelAtTextPoint(textPoint);
}
/// <summary>
/// Calculates the maximum character width.
/// </summary>
public void CalculateMaxCharWidth()
{
maxCharWidth = this.Painter.GetMaxCharWidth();
}
/// <summary>
/// Sets the maximum amount of "scrolling space" available to the horizontal ScrollBar.
/// </summary>
public void SetMaxHorizontalScroll()
{
this.CalculateMaxCharWidth();
int charWidth = this.ViewPoint.CharWidth;
if (charWidth == 0)
charWidth = 1;
if (this.ViewPoint.ClientAreaWidth / charWidth < 0)
{
hScroll.Maximum = 1000;
return;
}
hScroll.LargeChange = this.ViewPoint.ClientAreaWidth / charWidth;
try
{
int maximumLength = 0;
for (int rowCount = this.ViewPoint.FirstVisibleRow; rowCount < this.Document.VisibleRows.Count; rowCount++)
{
if (rowCount >= this.ViewPoint.VisibleRowCount + this.ViewPoint.FirstVisibleRow)
break;
string rowText = "";
if (this.Document.VisibleRows[rowCount].IsCollapsed == true)
rowText = this.Document.VisibleRows[rowCount].VirtualCollapsedRow.Text;
else
rowText = this.Document.VisibleRows[rowCount].Text;
rowText = rowText.Replace("\t", new string(' ', this.TabSpaces));
if (rowText.Length > maximumLength)
maximumLength = rowText.Length;
}
int pixels = maximumLength * maxCharWidth;
int chars = pixels / charWidth;
if (hScroll.Value <= chars)
hScroll.Maximum = chars;
}
catch
{
hScroll.Maximum = 1000;
}
if (hScroll.Maximum > hScroll.LargeChange)
hScroll.Show();
else
hScroll.Hide();
}
/// <summary>
/// Sets up the ScrollBars.
/// </summary>
public void InitScrollbars()
{
if (this.Document.VisibleRows.Count > 0)
{
vScroll.Maximum = Document.VisibleRows.Count + 1;
vScroll.LargeChange = ViewPoint.VisibleRowCount;
this.SetMaxHorizontalScroll();
}
else
vScroll.Maximum = 1;
if (vScroll.Maximum > vScroll.LargeChange)
vScroll.Show();
else
vScroll.Hide();
}
/// <summary>
/// Initializes the TextEditorBase's Painter's graphics.
/// </summary>
public void InitGraphics()
{
this.Painter.InitGraphics();
}
/// <summary>
/// Inserts the specified text at the caret's current position.
/// </summary>
/// <param name="text">Text to insert.</param>
public void InsertText(string text)
{
this.Caret.CropPosition();
if (this.Selection.IsValid == true)
{
this.Selection.DeleteSelection();
this.InsertText(text);
}
else
{
if (overWrite == false || text.Length > 1)
{
TextPoint textPoint = this.Document.InsertText(text, this.Caret.Position.X, this.Caret.Position.Y);
this.Caret.CurrentRow.Parse(true);
if (text.Length == 1)
{
this.Caret.SetPosition(textPoint);
this.Caret.CaretMoved(false);
}
else
{
this.Document.ResetVisibleRows();
this.Caret.SetPosition(textPoint);
this.Caret.CaretMoved(false);
}
}
else
{
TextRange textRange = new TextRange();
textRange.FirstColumn = this.Caret.Position.X;
textRange.FirstRow = this.Caret.Position.Y;
textRange.LastColumn = this.Caret.Position.X + 1;
textRange.LastRow = this.Caret.Position.Y;
UndoBlockCollection undoBlockCollection = new UndoBlockCollection();
UndoBlock undoBlock = new UndoBlock();
undoBlock.Action = UndoAction.DeleteRange;
undoBlock.Text = this.Document.GetRange(textRange);
undoBlock.Position = this.Caret.Position;
undoBlockCollection.Add(undoBlock);
this.Document.DeleteRange(textRange, false);
undoBlock = new UndoBlock();
undoBlock.Action = UndoAction.InsertRange;
undoBlock.Text = text;
undoBlock.Position = this.Caret.Position;
undoBlockCollection.Add(undoBlock);
this.Document.AddToUndoList(undoBlockCollection);
this.Document.InsertText(text, this.Caret.Position.X, this.Caret.Position.Y, false);
this.Caret.CurrentRow.Parse(true);
this.Caret.MoveRight(false);
}
}
}
/// <summary>
/// Gets all keywords of the current language and returns them in a list.
/// </summary>
/// <returns>List containing all found keywords.</returns>
public ArrayList ExtractKeywords()
{
ArrayList keywordList = new ArrayList();
Language language = this.Document.Parser.Language;
for (int i = 0; i <= language.Blocks.Length - 1; i++)
{
Block block = language.Blocks[i];
if (block.KeywordsList.Count > 0)
{
for (int keywordIndex = 0; keywordIndex <= block.KeywordsList.Count - 1; keywordIndex++)
{
PatternList patternList = block.KeywordsList[keywordIndex];
foreach (string key in patternList.SimplePatterns.Keys)
{
if (keywordList.Contains(key) == false)
keywordList.Add(key);
}
}
}
}
return keywordList;
}
/// <summary>
/// Shows the Goto Line dialog.
/// </summary>
public void ShowGotoLine()
{
GotoLine gotoLineDialog = new GotoLine(this, this.Document.Count);
gotoLineDialog.ShowDialog(this.TopLevelControl);
}
/// <summary>
/// Selects the specified row and scrolls to it.
/// </summary>
/// <param name="rowIndex">Row to select and scroll to.</param>
public void GotoLine(int rowIndex)
{
if (rowIndex >= this.Document.Count)
rowIndex = this.Document.Count - 1;
if (rowIndex < 0)
rowIndex = 0;
this.Caret.Position.Y = rowIndex;
this.Caret.Position.X = 0;
this.Caret.CurrentRow.EnsureVisible();
this.ClearSelection();
this.ScrollIntoView();
this.Redraw();
}
/// <summary>
/// Clears the selection.
/// </summary>
public void ClearSelection()
{
this.Selection.ClearSelection();
this.Redraw();
}
/// <summary>
/// Returns whether the X and Y coordinates is over the current selection.
/// </summary>
/// <param name="x">The X coordinate.</param>
/// <param name="y">The Y coordinate.</param>
/// <returns>Whether the X and Y coordinates is the over the current selection.</returns>
public bool IsOverSelection(int x, int y)
{
TextPoint textPoint = this.Painter.GetTextPointAtPixel(x, y);
if (textPoint.Y >= this.Selection.LogicalBounds.FirstRow && textPoint.Y <= this.Selection.LogicalBounds.LastRow && this.Selection.IsValid == true)
{
if (textPoint.Y > this.Selection.LogicalBounds.FirstRow && textPoint.Y < this.Selection.LogicalBounds.LastRow && this.Selection.IsValid == true)
return true;
else
{
if (textPoint.Y == this.Selection.LogicalBounds.FirstRow && this.Selection.LogicalBounds.FirstRow == this.Selection.LogicalBounds.LastRow)
{
if (textPoint.X >= this.Selection.LogicalBounds.FirstColumn && textPoint.X <= this.Selection.LogicalBounds.LastColumn)
return true;
else
return false;
}
else if (textPoint.X >= this.Selection.LogicalBounds.FirstColumn && textPoint.Y == this.Selection.LogicalBounds.FirstRow)
return true;
else if (textPoint.X <= this.Selection.LogicalBounds.LastColumn && textPoint.Y == this.Selection.LogicalBounds.LastRow)
return true;
else
return false;
}
}
else
return false;
}
/// <summary>
/// If the specified TextPoint isn't visible, scrolls to it.
/// </summary>
/// <param name="textPoint">TextPoint to scroll to.</param>
public void ScrollIntoView(TextPoint textPoint)
{
TextPoint tempTextPoint = this.Caret.Position;
this.Caret.Position = textPoint;
if (this.Caret.CurrentRow != null)
this.Caret.CurrentRow.EnsureVisible();
this.ScrollIntoView();
this.Caret.Position = tempTextPoint;
this.Invalidate();
}
/// <summary>
/// If the specified Row isn't visible, scrolls to it.
/// </summary>
/// <param name="rowIndex">Row to scroll to.</param>
public void ScrollIntoView(int rowIndex)
{
Row row = this.Document[rowIndex];
row.EnsureVisible();
vScroll.Value = row.VisibleIndex;
this.Invalidate();
}
/// <summary>
/// If the current caret position is out of view, scrolls to it.
/// </summary>
public void ScrollIntoView()
{
this.InitScrollbars();
this.Caret.CropPosition();
try
{
Row currentRow = this.Caret.CurrentRow;
if (currentRow.VisibleIndex >= this.ViewPoint.FirstVisibleRow + this.ViewPoint.VisibleRowCount - 2)
{
int difference = this.Caret.CurrentRow.VisibleIndex - (this.ViewPoint.FirstVisibleRow + this.ViewPoint.VisibleRowCount - 2) +
this.ViewPoint.FirstVisibleRow;
if (difference > this.Document.VisibleRows.Count - 1)
difference = this.Document.VisibleRows.Count - 1;
Row visibleRow = this.Document.VisibleRows[difference];
int index = visibleRow.VisibleIndex;
if (index != -1)
vScroll.Value = index;
}
}
catch
{
}
if (this.Caret.CurrentRow.VisibleIndex < this.ViewPoint.FirstVisibleRow)
{
Row currentRow = this.Caret.CurrentRow;
int index = currentRow.VisibleIndex;
if (index != -1)
vScroll.Value = index;
}
int x = 0;
Row row = this.Caret.CurrentRow;
if (Caret.CurrentRow.IsCollapsedEndPart)
{
x = this.Painter.MeasureRow(row, this.Caret.Position.X).Width + this.Caret.CurrentRow.ExpansionPixelStart;
x -= this.Painter.MeasureRow(row, row.ExpansionStartChar).Width;
if (x >= this.ViewPoint.ClientAreaWidth + this.ViewPoint.ClientAreaStart)
hScroll.Value = Math.Min(hScroll.Maximum, ((x - this.ViewPoint.ClientAreaWidth) / this.ViewPoint.CharWidth) + 15);
if (x < this.ViewPoint.ClientAreaStart + 10)
hScroll.Value = Math.Max(hScroll.Minimum, ((x) / this.ViewPoint.CharWidth) - 15);
}
else
{
x = this.Painter.MeasureRow(row, this.Caret.Position.X).Width;
if (x >= this.ViewPoint.ClientAreaWidth + this.ViewPoint.ClientAreaStart)
hScroll.Value = Math.Min(hScroll.Maximum, ((x - this.ViewPoint.ClientAreaWidth) / this.ViewPoint.CharWidth) + 15);
if (x < this.ViewPoint.ClientAreaStart)
hScroll.Value = Math.Max(hScroll.Minimum, (x / this.ViewPoint.CharWidth) - 15);
}
}
/// <summary>
/// Scrolls to the next bookmark.
/// </summary>
public void GotoNextBookmark()
{
int index = 0;
index = this.Document.GetNextBookmark(this.Caret.Position.Y);
this.Caret.SetPosition(new TextPoint(0, index));
this.ScrollIntoView();
this.Redraw();
}
/// <summary>
/// Scrolls to the previous bookmark.
/// </summary>
public void GotoPreviousBookmark()
{
int index = 0;
index = this.Document.GetPreviousBookmark(this.Caret.Position.Y);
this.Caret.SetPosition(new TextPoint(0, index));
this.ScrollIntoView();
this.Redraw();
}
/// <summary>
/// Selects the next match depending on the specified conditions.
/// </summary>
/// <param name="Pattern">Pattern to search for.</param>
/// <param name="matchCase">Whether the pattern should match case.</param>
/// <param name="wholeWords">Whether the pattern should be a whole word.</param>
/// <param name="useRegularExpressions">Whether to use regular expressions when searching.</param>
/// <returns>Found match.</returns>
public bool SelectNext(string pattern, bool matchCase, bool wholeWords, bool useRegularExpressions)
{
string newPattern = pattern;
int startColumn = this.Caret.Position.X;
int startRow = this.Caret.Position.Y;
for (int rowIndex = this.Caret.Position.Y; rowIndex < this.Document.Count; rowIndex++)
{
Row row = this.Document[rowIndex];
if (useRegularExpressions == true)
{
Regex regex = new Regex(pattern);
int matchColumn = startColumn;
if (rowIndex == startRow)
{
if (startColumn < row.Text.Length)
continue;
}
else
matchColumn = 0;
Match match = regex.Match(row.Text, matchColumn);
if (match.Success == true)
{
this.SelectPattern(rowIndex, match.Index, match.Length);
return true;
}
}
else
{
int column = -1;
string spacedText = "";
string rowText = row.Text;
if (wholeWords == true)
{
spacedText = " " + row.Text + " ";
rowText = "";
newPattern = " " + pattern + " ";
foreach (char character in spacedText)
{
if (".,+-*^\\/()[]{}@:;'?£$#%& \t=<>".IndexOf(character) >= 0)
rowText += " ";
else
rowText += character;
}
}
if (matchCase == false)
{
rowText = rowText.ToLower();
newPattern = newPattern.ToLower();
}
column = rowText.IndexOf(newPattern);
if (column >= startColumn || (rowIndex > startRow && column >= 0))
{
this.SelectPattern(rowIndex, column, pattern.Length);
return true;
}
}
}
return false;
}
/// <summary>
/// Replaces the current selection with the specified text.
/// </summary>
/// <param name="text">Text to replace selection with.</param>
/// <returns>Whether the replacing was successful.</returns>
public bool ReplaceSelection(string text)
{
if (this.Selection.IsValid == false)
return false;
int x = this.Selection.LogicalBounds.FirstColumn;
int y = this.Selection.LogicalBounds.FirstRow;
TextRange textRange = new TextRange(this.Selection.Bounds.FirstColumn, this.Selection.Bounds.FirstRow,
this.Selection.Bounds.LastColumn, this.Selection.Bounds.LastRow);
TextRange newTextRange = this.Document.ReplaceRange(textRange, text, true);
this.Selection.Bounds = newTextRange;
this.Caret.Position.X = newTextRange.LastColumn;
this.Caret.Position.Y = newTextRange.LastRow;
return true;
}
/// <summary>
/// Toggles a bookmark at the line the user is currently on.
/// </summary>
public void ToggleBookmark()
{
this.Document[this.Caret.Position.Y].Bookmarked = this.Document[this.Caret.Position.Y].Bookmarked == false;
this.Redraw();
}
/// <summary>
/// Deletes the letter after the user's current selection.
/// </summary>
public void Delete()
{
this.DeleteForward();
this.Refresh();
}
/// <summary>
/// Selects all the content of the TextEditorBase.
/// </summary>
public void SelectAll()
{
this.Selection.SelectAll();
this.Redraw();
}
/// <summary>
/// Pastes the user's clipboard to the user's current selection. (If the clipboard content is valid)
/// </summary>
public void Paste()
{
this.PasteText();
this.Refresh();
}
/// <summary>
/// Copies the user's current selection to his/her clipboard.
/// </summary>
public void Copy()
{
this.CopyText();
}
/// <summary>
/// Copies the user's current selection to his/her clipboard and deletes the selection.
/// </summary>
public void Cut()
{
this.CopyText();
this.Selection.DeleteSelection();
}
/// <summary>
/// Removes the row the user is currently on.
/// </summary>
public void RemoveCurrentRow()
{
if (this.Caret.CurrentRow != null && this.Document.Count > 1)
{
this.Document.Remove(this.Caret.CurrentRow.Index, true);
this.Document.ResetVisibleRows();
this.Caret.CropPosition();
this.Caret.CurrentRow.Text = Caret.CurrentRow.Text;
this.Caret.CurrentRow.Parse(true);
this.Document.ResetVisibleRows();
this.ScrollIntoView();
}
}
/// <summary>
/// If the current selection is valid, does a Cut action, else, removes the current row.
/// </summary>
public void CutClear()
{
if (this.Selection.IsValid == true)
this.Cut();
else
this.RemoveCurrentRow();
}
/// <summary>
/// Redoes the last undone action by the user.
/// </summary>
public void Redo()
{
TextPoint textPoint = this.Document.Redo();
if (textPoint.X != -1 && textPoint.Y != -1)
{
this.Caret.Position = textPoint;
this.Selection.ClearSelection();
this.ScrollIntoView();
}
}
/// <summary>
/// Undoes the last action by the user.
/// </summary>
public void Undo()
{
TextPoint textPoint = this.Document.Undo();
if (textPoint.X != -1 && textPoint.Y != -1)
{
this.Caret.Position = textPoint;
this.Selection.ClearSelection();
this.ScrollIntoView();
}
}
/// <summary>
/// Gets the text point at the given coordinates.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <returns>The found text point.</returns>
public TextPoint GetTextPointAtPixel(int x, int y)
{
return this.Painter.GetTextPointAtPixel(x, y);
}
/// <summary>
/// Shows the Find form.
/// </summary>
public void ShowFind()
{
if (this.FindReplaceDialog != null)
{
this.FindReplaceDialog.TopLevel = true;
if (this.TopLevelControl is Form)
this.FindReplaceDialog.Owner = this.TopLevelControl as Form;
this.FindReplaceDialog.ShowFind();
}
}
/// <summary>
/// Shows the Replace form.
/// </summary>
public void ShowReplace()
{
if (this.FindReplaceDialog != null)
{
this.FindReplaceDialog.TopLevel = true;
if (this.TopLevelControl is Form)
this.FindReplaceDialog.Owner = this.TopLevelControl as Form;
this.FindReplaceDialog.ShowReplace();
}
}
/// <summary>
/// Finds the next match.
/// </summary>
public void FindNext()
{
this.FindReplaceDialog.FindNext();
}
/// <summary>
/// Scrolls to the specified row and centers it in the TextEditorBase.
/// </summary>
/// <param name="rowIndex">Row to scroll to and center.</param>
public void CenterInView(int rowIndex)
{
if (this.Document == null && rowIndex > this.Document.Count && rowIndex < 0)
return;
Row row = this.Document[rowIndex];
int topRow = 0;
int visibleLines = 0;
if (row != null)
{
this.InitScrollbars();
row.EnsureVisible();
visibleLines = this.ViewPoint.VisibleRowCount / 2;
if (row.VisibleIndex < visibleLines)
topRow = 0;
else
topRow = row.VisibleIndex - visibleLines;
vScroll.Value = topRow;
this.Invalidate();
}
}
#endregion
#region Protected
/// <summary>
/// Processes Windows messages from the OS.
/// </summary>
/// <param name="m">Windows message to process.</param>
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WindowMessage.WM_DESTROY)
{
try
{
if (this.FindReplaceDialog != null)
this.FindReplaceDialog.Close();
}
catch
{
}
}
base.WndProc(ref m);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
this.RemoveFocus();
if (disposing == true)
{
if (components != null)
components.Dispose();
if (this.Painter != null)
this.Painter.Dispose();
}
base.Dispose(disposing);
}
#endregion
#region EventHandlers
/// <summary>
/// Called when [scroll handler begin scroll].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnScrollHandlerBeginScroll(object sender, EventArgs e) {
scrollHandlerCurrentPosition = 0;
this.ViewPoint.YOffset = 0;
}
/// <summary>
/// Called when [scroll handler end scroll].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnScrollHandlerEndScroll(object sender, EventArgs e) {
this.ViewPoint.YOffset = 0;
this.Redraw();
}
/// <summary>
/// Called when [scroll handler scroll].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="Storm.TextEditor.Interacting.Scrolling.ScrollEventArgs"/> instance containing the event data.</param>
private void OnScrollHandlerScroll(object sender, ScrollEventArgs e) {
if (e.DeltaY < 0 && vScroll.Value == 0) {
this.ViewPoint.YOffset = 0;
this.Redraw();
return;
}
if (e.DeltaY > 0 && vScroll.Value >= vScroll.Maximum - this.ViewPoint.VisibleRowCount + 1) {
this.ViewPoint.YOffset = 0;
this.Redraw();
return;
}
scrollHandlerCurrentPosition += (double)e.DeltaY / (double)8;
int rowScrollCount = (int)scrollHandlerCurrentPosition / this.ViewPoint.RowHeight;
if (rowScrollCount != 0)
scrollHandlerCurrentPosition -= rowScrollCount * this.ViewPoint.RowHeight;
this.ViewPoint.YOffset = -(int)scrollHandlerCurrentPosition;
this.ScrollScreen(rowScrollCount);
}
/// <summary>
/// Raises the <see cref="E:ClipboardUpdated"/> event.
/// </summary>
/// <param name="e">The <see cref="Storm.TextEditor.Editor.CopyEventArgs"/> instance containing the event data.</param>
private void OnClipboardUpdated(CopyEventArgs e)
{
if (this.ClipboardUpdated != null)
this.ClipboardUpdated(this, e);
}
/// <summary>
/// Raises the <see cref="E:RowMouseDown"/> event.
/// </summary>
/// <param name="e">The <see cref="Storm.TextEditor.Editor.RowMouseEventArgs"/> instance containing the event data.</param>
private void OnRowMouseDown(RowMouseEventArgs e)
{
if (this.RowMouseDown != null)
this.RowMouseDown(this, e);
}
/// <summary>
/// Raises the <see cref="E:RowMouseMove"/> event.
/// </summary>
/// <param name="e">The <see cref="Storm.TextEditor.Editor.RowMouseEventArgs"/> instance containing the event data.</param>
private void OnRowMouseMove(RowMouseEventArgs e)
{
if (this.RowMouseMove != null)
this.RowMouseMove(this, e);
}
/// <summary>
/// Raises the <see cref="E:RowMouseUp"/> event.
/// </summary>
/// <param name="e">The <see cref="Storm.TextEditor.Editor.RowMouseEventArgs"/> instance containing the event data.</param>
private void OnRowMouseUp(RowMouseEventArgs e)
{
if (this.RowMouseUp != null)
this.RowMouseUp(this, e);
}
/// <summary>
/// Raises the <see cref="E:RowClick"/> event.
/// </summary>
/// <param name="e">The <see cref="Storm.TextEditor.Editor.RowMouseEventArgs"/> instance containing the event data.</param>
private void OnRowClick(RowMouseEventArgs e)
{
if (this.RowClick != null)
this.RowClick(this, e);
}
/// <summary>
/// Raises the <see cref="E:RowDoubleClick"/> event.
/// </summary>
/// <param name="e">The <see cref="Storm.TextEditor.Editor.RowMouseEventArgs"/> instance containing the event data.</param>
private void OnRowDoubleClick(RowMouseEventArgs e)
{
if (this.RowDoubleClick != null)
this.RowDoubleClick(this, e);
}
/// <summary>
/// Raises the Load event.
/// </summary>
/// <param name="e">EventArgs.</param>
protected override void OnLoad(EventArgs e)
{
this.UpdateContent();
this.Refresh();
}
/// <summary>
/// Called when [parse].
/// </summary>
internal void OnParse()
{
this.Redraw();
}
/// <summary>
/// Called when [change].
/// </summary>
internal void OnChange()
{
if (this.Caret.Position.Y > this.Document.Count - 1)
{
this.Caret.Position.Y = this.Document.Count - 1;
this.ScrollIntoView();
}
if (this.VirtualWhitespace == false && this.Caret.CurrentRow != null && this.Caret.Position.X > this.Caret.CurrentRow.Text.Length)
{
this.Caret.Position.X = this.Caret.CurrentRow.Text.Length;
this.Redraw();
}
if (this.ContainsFocus == false)
this.Selection.ClearSelection();
if (this.Selection.LogicalBounds.FirstRow > this.Document.Count)
{
this.Selection.Bounds.FirstColumn = Caret.Position.X;
this.Selection.Bounds.LastColumn = Caret.Position.X;
this.Selection.Bounds.FirstRow = Caret.Position.Y;
this.Selection.Bounds.LastRow = Caret.Position.Y;
}
if (this.Selection.LogicalBounds.LastRow > this.Document.Count)
{
this.Selection.Bounds.FirstColumn = this.Caret.Position.X;
this.Selection.Bounds.LastColumn = this.Caret.Position.X;
this.Selection.Bounds.FirstRow = this.Caret.Position.Y;
this.Selection.Bounds.LastRow = this.Caret.Position.Y;
}
this.Redraw();
}
/// <summary>
/// Determines whether the specified key is a regular input key or a special key that requires preprocessing.
/// </summary>
/// <param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys"/> values.</param>
/// <returns>
/// true if the specified key is a regular input key; otherwise, false.
/// </returns>
protected override bool IsInputKey(Keys keyData)
{
switch (keyData & Keys.KeyCode)
{
case Keys.Up:
return true;
case Keys.Down:
return true;
case Keys.Right:
return true;
case Keys.Left:
return true;
case Keys.Tab:
return true;
default:
return base.IsInputKey(keyData);
}
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.KeyDown"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.KeyEventArgs"/> that contains the event data.</param>
protected override void OnKeyDown(KeyEventArgs e)
{
keyDownHandled = e.Handled;
if (this.KeyDown != null)
this.KeyDown(this, e);
if (e.Handled == false)
{
foreach (KeyboardAction keyboardAction in this.TextEditor.KeyboardActions)
{
if (this.ReadOnly == false || keyboardAction.AllowReadOnly == true)
{
if (keyboardAction.Key == e.KeyCode && keyboardAction.Alt == e.Alt && keyboardAction.Shift == e.Shift
&& keyboardAction.Control == e.Control)
{
keyboardAction.Action();
}
}
}
switch (e.KeyCode)
{
case Keys.ShiftKey:
case Keys.ControlKey:
case Keys.Alt:
break;
case Keys.Down:
if (e.Control == true)
this.ScrollScreen(1);
else
{
if (codeCompletionWindow.Visible == true)
codeCompletionWindow.UpdateInput((char)Keys.Down, e.Control, e.Alt, e.Shift);
else
this.Caret.MoveDown(e.Shift);
}
this.Redraw();
break;
case Keys.Up:
if (e.Control == true)
this.ScrollScreen(-1);
else
{
if (codeCompletionWindow.Visible == true)
codeCompletionWindow.UpdateInput((char)Keys.Up, e.Control, e.Alt, e.Shift);
else
this.Caret.MoveUp(e.Shift);
}
this.Redraw();
break;
case Keys.Left:
if (e.Control == true)
this.MoveCaretToPreviousWord(e.Shift);
else
this.Caret.MoveLeft(e.Shift);
this.Redraw();
break;
case Keys.Right:
if (e.Control == true)
this.MoveCaretToNextWord(e.Shift);
else
this.Caret.MoveRight(e.Shift);
this.Redraw();
break;
case Keys.End:
if (e.Control == true)
this.Caret.MoveAbsoluteEnd(e.Shift);
else
this.Caret.MoveEnd(e.Shift);
this.Redraw();
break;
case Keys.Home:
if (e.Control == true)
this.Caret.MoveAbsoluteHome(e.Shift);
else
this.Caret.MoveHome(e.Shift);
this.Redraw();
break;
case Keys.PageDown:
this.Caret.MoveDown(this.ViewPoint.VisibleRowCount - 2, e.Shift);
this.Redraw();
break;
case Keys.PageUp:
this.Caret.MoveUp(this.ViewPoint.VisibleRowCount - 2, e.Shift);
this.Redraw();
break;
default:
break;
}
if (this.ReadOnly == false)
{
switch (e.KeyCode)
{
case Keys.Enter:
if (e.Control == true)
{
if (this.Caret.CurrentRow.CanFold == true)
{
this.Caret.MoveHome(false);
this.Document.ToggleRowExpansion(Caret.CurrentRow);
this.Redraw();
}
}
else
{
if (codeCompletionWindow.Visible == true)
codeCompletionWindow.UpdateInput((char)Keys.Enter, e.Control, e.Alt, e.Shift);
else
this.InsertEnter();
}
break;
case Keys.Back:
if (e.Control == false)
{
this.DeleteBackwards();
codeCompletionWindow.UpdateInput((char)Keys.Back, e.Control, e.Alt, e.Shift);
}
else
{
if (this.Selection.IsValid == true)
this.Selection.DeleteSelection();
else
{
this.Selection.ClearSelection();
this.MoveCaretToPreviousWord(true);
this.Selection.DeleteSelection();
}
this.Caret.CurrentRow.Parse(true);
}
break;
case Keys.Delete:
if (e.Control == false && e.Alt == false && e.Shift == false)
{
this.Delete();
codeCompletionWindow.UpdateInput((char)Keys.Delete, e.Control, e.Alt, e.Shift);
}
else if (e.Control == true && e.Alt == false && e.Shift == false)
{
if (this.Selection.IsValid == true)
this.Cut();
else
{
this.Selection.ClearSelection();
this.MoveCaretToNextWord(true);
this.Selection.DeleteSelection();
}
this.Caret.CurrentRow.Parse(true);
}
break;
case Keys.Insert:
if (e.Control == false && e.Alt == false && e.Shift == false)
overWrite = overWrite == false;
break;
case Keys.Tab:
if (this.Selection.IsValid == false)
{
if (keepTabs == false)
{
for (int i = 0; i < tabSpaces; i++)
this.InsertText(" ");
}
else
this.InsertText("\t");
codeCompletionWindow.UpdateInput((char)Keys.Tab, e.Control, e.Alt, e.Shift);
}
break;
default:
break;
}
}
this.Caret.Blink = true;
}
base.OnKeyDown(e);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.KeyPress"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.KeyPressEventArgs"/> that contains the event data.</param>
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
if (e.Handled == false && keyDownHandled == false && e.KeyChar != (char)127)
{
if (((int)e.KeyChar) < 32)
return;
if (this.ReadOnly == false)
{
this.InsertText(e.KeyChar.ToString());
bool shift = e.KeyChar == '(' || e.KeyChar == ')';
codeCompletionWindow.UpdateInput(e.KeyChar, false, false, shift);
if (this.Indent == IndentStyle.Scope)
{
if (this.Caret.CurrentRow.ShouldOutdent == true)
this.OutdentEndRow();
}
}
}
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseDown(MouseEventArgs e)
{
mouseX = e.X;
mouseY = e.Y;
mouseButton = e.Button;
this.Focus();
Row row = null;
TextPoint textPoint = this.Painter.GetTextPointAtPixel(e.X, e.Y);
if (textPoint.Y >= 0 && textPoint.Y < this.Document.Count)
row = this.Document[textPoint.Y];
RowMouseEventArgs rowMouseEventArgs = new RowMouseEventArgs();
rowMouseEventArgs.Row = row;
rowMouseEventArgs.Button = e.Button;
rowMouseEventArgs.MouseX = mouseX;
rowMouseEventArgs.MouseY = mouseY;
if (e.X >= this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.TextArea;
else if (e.X < this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.GutterArea;
else if (e.X < this.ViewPoint.LineNumberMarginWidth + this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.LineNumberArea;
else if (e.X < this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.FoldingArea;
else
rowMouseEventArgs.Area = RowArea.Other;
this.OnRowMouseDown(rowMouseEventArgs);
row = this.Document[textPoint.Y];
if (row != null)
{
if (e.X >= row.ExpansionPixelEnd && row.IsCollapsed == true)
{
if (row.ExpansionStartSegment != null)
{
if (row.ExpansionStartSegment.StartRow != null && row.ExpansionStartSegment.EndRow != null &&
row.ExpansionStartSegment.Expanded == false)
{
if (this.IsOverSelection(e.X, e.Y) == false)
{
this.Caret.Position.X = textPoint.X;
this.Caret.Position.Y = textPoint.Y;
this.Selection.ClearSelection();
Row expansionEndRow = row.ExpansionEndRow;
int expansionStartCharIndex = expansionEndRow.ExpansionStartChar;
this.Caret.Position.X = expansionStartCharIndex;
this.Caret.Position.Y = expansionEndRow.Index;
this.Selection.MakeSelection();
this.Redraw();
this.ViewPoint.Action = TextAction.Select;
return;
}
}
}
}
}
bool shift = NativeUser32Api.IsKeyPressed(Keys.ShiftKey);
if (e.X > this.ViewPoint.TotalMarginWidth)
{
if (e.X > this.ViewPoint.TextMargin - 8)
{
if (this.IsOverSelection(e.X, e.Y) == false)
{
if (e.Button == MouseButtons.Left)
{
if (shift == false)
{
Word textPointWord = this.Document.GetWordFromPos(textPoint);
if (textPointWord != null && textPointWord.Pattern != null && textPointWord.Pattern.Category != "")
{
WordMouseEventArgs wordMouseEventArgs = new WordMouseEventArgs();
wordMouseEventArgs.Pattern = textPointWord.Pattern;
wordMouseEventArgs.Button = e.Button;
wordMouseEventArgs.Word = textPointWord;
this.TextEditor.OnWordMouseDown(ref wordMouseEventArgs);
}
this.ViewPoint.Action = TextAction.Select;
this.Caret.SetPosition(textPoint);
this.Selection.ClearSelection();
this.Caret.Blink = true;
this.Redraw();
}
else
{
this.ViewPoint.Action = TextAction.Select;
this.Caret.SetPosition(textPoint);
this.Selection.MakeSelection();
this.Caret.Blink = true;
this.Redraw();
}
}
}
}
else
{
if (row.ExpansionStartSegment != null)
{
this.Caret.SetPosition(new TextPoint(0, textPoint.Y));
this.Selection.ClearSelection();
this.Document.ToggleRowExpansion(row);
this.Redraw();
}
}
}
else
{
if (e.X < this.ViewPoint.GutterMarginWidth)
{
if (this.TextEditor.AllowBreakPoints == true)
{
row = this.Document[this.Painter.GetTextPointAtPixel(e.X, e.Y).Y];
row.Breakpoint = row.Breakpoint == false;
this.Redraw();
}
else
{
row = this.Document[this.Painter.GetTextPointAtPixel(e.X, e.Y).Y];
row.Breakpoint = false;
this.Redraw();
}
}
else
{
this.ViewPoint.Action = TextAction.Select;
this.Caret.SetPosition(this.Painter.GetTextPointAtPixel(0, e.Y));
this.Selection.ClearSelection();
this.Caret.MoveDown(true);
this.Redraw();
}
}
this.SetMouseCursor(e.X, e.Y);
base.OnMouseDown(e);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseMove"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseMove(MouseEventArgs e)
{
mouseX = e.X;
mouseY = e.Y;
mouseButton = e.Button;
Row row = null;
TextPoint textPoint = this.Painter.GetTextPointAtPixel(e.X, e.Y);
if (textPoint.Y >= 0 && textPoint.Y < Document.Count)
row = Document[textPoint.Y];
RowMouseEventArgs rowMouseEventArgs = new RowMouseEventArgs();
rowMouseEventArgs.Row = row;
rowMouseEventArgs.Button = e.Button;
rowMouseEventArgs.MouseX = mouseX;
rowMouseEventArgs.MouseY = mouseY;
if (e.X >= this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.TextArea;
else if (e.X < this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.GutterArea;
else if (e.X < this.ViewPoint.LineNumberMarginWidth + this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.LineNumberArea;
else if (e.X < this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.FoldingArea;
else
rowMouseEventArgs.Area = RowArea.Other;
this.OnRowMouseMove(rowMouseEventArgs);
if (this.Document != null)
{
if (e.Button == MouseButtons.Left)
{
if (this.ViewPoint.Action == TextAction.Select)
{
this.Caret.Blink = true;
this.Caret.SetPosition(textPoint);
if (e.X <= ViewPoint.TotalMarginWidth)
this.Caret.MoveDown(true);
this.Caret.CropPosition();
this.Selection.MakeSelection();
this.ScrollIntoView();
this.Redraw();
}
else if (this.ViewPoint.Action == TextAction.None)
{
if (this.IsOverSelection(e.X, e.Y) == true)
this.BeginDragDrop();
}
}
else
{
row = this.Document[textPoint.Y];
bool showTooltip = false;
if (row != null)
{
if (e.X < this.ViewPoint.TextMargin - 8 && e.X > this.ViewPoint.TotalMarginWidth)
{
bool shouldContinue = true;
int startRowIndex = textPoint.Y;
Row endRow = row.ExpansionEndRow;
if (row.CanFold == false)
{
int index = row.StartSegment != null && row.StartSegment.StartRow != null ? this.Document.IndexOf(row.StartSegment.StartRow) : -1;
if (index < 0)
shouldContinue = false;
startRowIndex = index;
endRow = row.StartSegment != null ? row.StartSegment.EndRow : null;
}
if (shouldContinue == true)
{
if (this.Document[startRowIndex].Expanded == true)
{
for (int rowIndex = 0; rowIndex < this.Document.Count; rowIndex++)
{
this.Document[rowIndex].BackColor = Color.Transparent;
this.Document[rowIndex].Hovered = false;
}
for (int rowIndex = startRowIndex; rowIndex <= this.Document.IndexOf(endRow); rowIndex++)
{
this.Document[rowIndex].BackColor = this.RowHoverBackColor;
this.Document[rowIndex].Hovered = true;
}
}
this.Redraw();
}
}
else
{
for (int rowIndex = 0; rowIndex < this.Document.Count; rowIndex++)
{
this.Document[rowIndex].BackColor = Color.Transparent;
this.Document[rowIndex].Hovered = false;
}
this.Redraw();
}
if (e.X >= row.ExpansionPixelEnd && row.IsCollapsed)
{
if (row.ExpansionStartSegment != null)
{
if (row.ExpansionStartSegment.StartRow != null && row.ExpansionStartSegment.EndRow != null &&
row.ExpansionStartSegment.Expanded == false)
{
string tabbedText = "";
for (int rowIndex = this.Document.IndexOf(row.ExpansionStartSegment.StartRow); rowIndex <=
row.ExpansionStartSegment.EndRow.Index; rowIndex++)
{
if (rowIndex > 0)
tabbedText += "\n";
Row currentRow = this.Document[rowIndex];
string removedTabsText = currentRow.Text.Replace("\t", " ");
tabbedText += removedTabsText;
if (rowIndex > 20)
{
tabbedText += "...";
break;
}
rowIndex++;
}
tooltip.InitialDelay = TooltipDelay;
if (tooltip.GetToolTip(this) != tabbedText)
tooltip.SetToolTip(this, tabbedText);
tooltip.Active = true;
showTooltip = true;
}
}
}
}
if (tooltip != null)
{
if (showTooltip == false)
tooltip.SetToolTip(this, "");
}
}
this.SetMouseCursor(e.X, e.Y);
base.OnMouseMove(e);
}
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseUp(MouseEventArgs e)
{
mouseX = e.X;
mouseY = e.Y;
mouseButton = e.Button;
Row row = null;
TextPoint textPoint = this.Painter.GetTextPointAtPixel(e.X, e.Y);
if (textPoint.Y >= 0 && textPoint.Y < Document.Count)
row = this.Document[textPoint.Y];
RowMouseEventArgs rowMouseEventArgs = new RowMouseEventArgs();
rowMouseEventArgs.Row = row;
rowMouseEventArgs.Button = e.Button;
rowMouseEventArgs.MouseX = mouseX;
rowMouseEventArgs.MouseY = mouseY;
if (e.X >= this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.TextArea;
else if (e.X < this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.GutterArea;
else if (e.X < this.ViewPoint.LineNumberMarginWidth + this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.LineNumberArea;
else if (e.X < this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.FoldingArea;
else
rowMouseEventArgs.Area = RowArea.Other;
this.OnRowMouseUp(rowMouseEventArgs);
if (this.ViewPoint.Action == TextAction.None)
{
if (e.X > ViewPoint.TotalMarginWidth)
{
if (this.IsOverSelection(e.X, e.Y) == true && e.Button == MouseButtons.Left)
{
this.ViewPoint.Action = TextAction.Select;
this.Caret.SetPosition(this.Painter.GetTextPointAtPixel(e.X, e.Y));
this.Selection.ClearSelection();
this.Redraw();
}
}
}
this.ViewPoint.Action = TextAction.None;
base.OnMouseUp(e);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseWheel"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
protected override void OnMouseWheel(MouseEventArgs e)
{
int scrollLines = SystemInformation.MouseWheelScrollLines;
this.ScrollScreen(-(e.Delta / 120) * scrollLines, 2);
base.OnMouseWheel(e);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
protected override void OnPaint(PaintEventArgs e)
{
if (this.Document != null && Width > 0 && Height > 0)
this.Painter.RenderAll(e.Graphics);
}
/// <summary>
/// Raises the <see cref="E:Resize"/> event.
/// </summary>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
protected override void OnResize(EventArgs e)
{
this.UpdateContent();
base.OnResize(e);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.DragOver"/> event.
/// </summary>
/// <param name="drgevent">A <see cref="T:System.Windows.Forms.DragEventArgs"/> that contains the event data.</param>
protected override void OnDragOver(DragEventArgs drgevent)
{
if (this.ReadOnly == false)
{
if (this.Document != null)
{
this.ViewPoint.Action = TextAction.DragText;
Point point = this.PointToClient(new Point(drgevent.X, drgevent.Y));
int x = point.X;
int y = point.Y;
if ((drgevent.KeyState & 8) == 8)
drgevent.Effect = DragDropEffects.Copy;
else
drgevent.Effect = DragDropEffects.Move;
this.Caret.SetPosition(this.Painter.GetTextPointAtPixel(x, y));
this.Redraw();
}
}
else
drgevent.Effect = DragDropEffects.None;
base.OnDragOver(drgevent);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.DragDrop"/> event.
/// </summary>
/// <param name="drgevent">A <see cref="T:System.Windows.Forms.DragEventArgs"/> that contains the event data.</param>
protected override void OnDragDrop(DragEventArgs drgevent)
{
if (this.ReadOnly == false)
{
if (this.Document != null)
{
this.ViewPoint.Action = TextAction.None;
int selectionStart = this.Selection.LogicalSelStart;
int dropPosition = this.Document.PointToIntPos(this.Caret.Position);
string dropText = drgevent.Data.GetData(typeof(string)).ToString();
int dropTextLength = dropText.Length;
if (dropPosition >= selectionStart && dropPosition <= selectionStart + Math.Abs(this.Selection.SelLength))
dropPosition = selectionStart;
else if (dropPosition >= selectionStart + dropTextLength)
dropPosition -= dropTextLength;
this.Document.StartUndoCapture();
if ((drgevent.KeyState & 8) == 0)
{
this.TextEditor.Selection.DeleteSelection();
this.Caret.Position = this.Document.IntPosToPoint(dropPosition);
}
TextPoint textPoint = this.Document.InsertText(dropText, Caret.Position.X, Caret.Position.Y);
this.Document.EndUndoCapture();
this.Selection.SelStart = this.Document.PointToIntPos(this.Caret.Position);
this.Selection.SelLength = dropTextLength;
this.Document.ResetVisibleRows();
this.ScrollIntoView();
this.Redraw();
drgevent.Effect = DragDropEffects.All;
if (this.ParseOnPaste == true)
this.Document.ParseAll(true);
this.ViewPoint.Action = TextAction.None;
}
}
base.OnDragDrop(drgevent);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.DragLeave"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
protected override void OnDragLeave(EventArgs e)
{
this.ViewPoint.Action = TextAction.None;
base.OnDragLeave(e);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.DoubleClick"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
protected override void OnDoubleClick(EventArgs e)
{
Row row = null;
TextPoint textPoint = this.Painter.GetTextPointAtPixel(mouseX, mouseY);
if (textPoint.Y >= 0 && textPoint.Y < Document.Count)
row = this.Document[textPoint.Y];
RowMouseEventArgs rowMouseEventArgs = new RowMouseEventArgs();
rowMouseEventArgs.Row = row;
rowMouseEventArgs.Button = MouseButtons.None;
rowMouseEventArgs.MouseX = mouseX;
rowMouseEventArgs.MouseY = mouseY;
if (mouseX >= this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.TextArea;
else if (mouseX < this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.GutterArea;
else if (mouseX < this.ViewPoint.LineNumberMarginWidth + ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.LineNumberArea;
else if (mouseX < this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.FoldingArea;
else
rowMouseEventArgs.Area = RowArea.Other;
this.OnRowDoubleClick(rowMouseEventArgs);
row = this.Document[textPoint.Y];
if (row != null)
{
if (mouseX >= row.ExpansionPixelEnd && row.IsCollapsed == true)
{
if (row.ExpansionStartSegment != null)
{
if (row.ExpansionStartSegment.StartRow != null && row.ExpansionStartSegment.EndRow != null &&
row.ExpansionStartSegment.Expanded == false)
{
row.Expanded = true;
this.Document.ResetVisibleRows();
this.Redraw();
return;
}
}
}
}
if (mouseX > this.ViewPoint.TotalMarginWidth)
this.SelectCurrentWord();
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.Click"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
protected override void OnClick(EventArgs e)
{
Row row = null;
TextPoint textPoint = this.Painter.GetTextPointAtPixel(mouseX, mouseY);
if (textPoint.Y >= 0 && textPoint.Y < this.Document.Count)
row = this.Document[textPoint.Y];
RowMouseEventArgs rowMouseEventArgs = new RowMouseEventArgs();
rowMouseEventArgs.Row = row;
rowMouseEventArgs.Button = MouseButtons.None;
rowMouseEventArgs.MouseX = mouseX;
rowMouseEventArgs.MouseY = mouseY;
if (mouseX >= this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.TextArea;
else if (mouseX < this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.GutterArea;
else if (mouseX < this.ViewPoint.LineNumberMarginWidth + this.ViewPoint.GutterMarginWidth)
rowMouseEventArgs.Area = RowArea.LineNumberArea;
else if (mouseX < this.ViewPoint.TextMargin - 7)
rowMouseEventArgs.Area = RowArea.FoldingArea;
else
rowMouseEventArgs.Area = RowArea.Other;
this.OnRowClick(rowMouseEventArgs);
}
/// <summary>
/// Called when [vertical scroll bar scroll].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Forms.ScrollEventArgs"/> instance containing the event data.</param>
private void OnVerticalScrollBarScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
{
this.SetMaxHorizontalScroll();
this.Focus();
int difference = e.NewValue - vScroll.Value;
if ((difference == -1 || difference == 1) && (e.Type == ScrollEventType.SmallDecrement || e.Type == ScrollEventType.SmallIncrement))
this.ScrollScreen(difference);
else
this.Invalidate();
}
/// <summary>
/// Called when [horitonzal scroll bar scroll].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Forms.ScrollEventArgs"/> instance containing the event data.</param>
private void OnHoritonzalScrollBarScroll(object sender, System.Windows.Forms.ScrollEventArgs e)
{
this.Focus();
this.Invalidate();
}
/// <summary>
/// Called when [caret timer tick].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnCaretTimerTick(object sender, EventArgs e)
{
this.Caret.Blink = this.Caret.Blink == false;
this.RedrawCaret();
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.MouseLeave"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
protected override void OnMouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
if (tooltip != null)
tooltip.RemoveAll();
}
/// <summary>
/// Called when [caret changed].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnCaretChanged(object sender, EventArgs e)
{
this.OnCaretChange();
}
/// <summary>
/// Called when [leave].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnLeave(object sender, EventArgs e)
{
this.RemoveFocus();
}
/// <summary>
/// Called when [enter].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnEnter(object sender, EventArgs e)
{
caretTimer.Enabled = true;
}
/// <summary>
/// Called when [selection changed].
/// </summary>
/// <param name="s">The s.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void OnSelectionChanged(object s, EventArgs e)
{
this.OnSelectionChange();
}
/// <summary>
/// Called when [caret change].
/// </summary>
private void OnCaretChange()
{
if (this.CaretChange != null)
this.CaretChange(this, null);
}
/// <summary>
/// Called when [selection change].
/// </summary>
private void OnSelectionChange()
{
if (this.SelectionChange != null)
this.SelectionChange(this, null);
}
/// <summary>
/// Raises the <see cref="E:System.Windows.Forms.Control.VisibleChanged"/> event.
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
protected override void OnVisibleChanged(EventArgs e)
{
if (this.Visible == false)
this.RemoveFocus();
base.OnVisibleChanged(e);
this.UpdateContent();
}
#endregion
#endregion
/// <summary>
/// Initializes a new instance of TextEditorBase.
/// </summary>
public TextEditorBase(TextEditor parent)
: base(parent)
{
painter = new DefaultPainter(this);
selection = new Selection(this);
caret = new Caret(this);
caret.Change += this.OnCaretChanged;
selection.Change += this.OnSelectionChanged;
this.InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint, false);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.UserPaint, true);
}
}
}