#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

446 lines
9.9 KiB

// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using ICSharpCode.TextEditor.Undo;
namespace ICSharpCode.TextEditor.Document
{
/// <summary>
/// Describes the caret marker
/// </summary>
public enum LineViewerStyle {
/// <summary>
/// No line viewer will be displayed
/// </summary>
None,
/// <summary>
/// The row in which the caret is will be marked
/// </summary>
FullRow
}
/// <summary>
/// Describes the indent style
/// </summary>
public enum IndentStyle {
/// <summary>
/// No indentation occurs
/// </summary>
None,
/// <summary>
/// The indentation from the line above will be
/// taken to indent the curent line
/// </summary>
Auto,
/// <summary>
/// Inteligent, context sensitive indentation will occur
/// </summary>
Smart
}
/// <summary>
/// Describes the bracket highlighting style
/// </summary>
public enum BracketHighlightingStyle {
/// <summary>
/// Brackets won't be highlighted
/// </summary>
None,
/// <summary>
/// Brackets will be highlighted if the caret is on the bracket
/// </summary>
OnBracket,
/// <summary>
/// Brackets will be highlighted if the caret is after the bracket
/// </summary>
AfterBracket
}
/// <summary>
/// Describes the selection mode of the text area
/// </summary>
public enum DocumentSelectionMode {
/// <summary>
/// The 'normal' selection mode.
/// </summary>
Normal,
/// <summary>
/// Selections will be added to the current selection or new
/// ones will be created (multi-select mode)
/// </summary>
Additive
}
/// <summary>
/// The default <see cref="IDocument"/> implementation.
/// </summary>
internal class DefaultDocument : IDocument
{
bool readOnly = false;
ILineManager lineTrackingStrategy = null;
ICustomLineManager customLineManager = null;
BookmarkManager bookmarkManager = null;
ITextBufferStrategy textBufferStrategy = null;
IFormattingStrategy formattingStrategy = null;
FoldingManager foldingManager = null;
UndoStack undoStack = new UndoStack();
ITextEditorProperties textEditorProperties = new DefaultTextEditorProperties();
MarkerStrategy markerStrategy = null;
public MarkerStrategy MarkerStrategy {
get {
return markerStrategy;
}
set {
markerStrategy = value;
}
}
public ITextEditorProperties TextEditorProperties {
get {
return textEditorProperties;
}
set {
textEditorProperties = value;
}
}
public UndoStack UndoStack {
get {
return undoStack;
}
}
public List<LineSegment> LineSegmentCollection {
get {
return lineTrackingStrategy.LineSegmentCollection;
}
}
public bool ReadOnly {
get {
return readOnly;
}
set {
readOnly = value;
}
}
public ILineManager LineManager {
get {
return lineTrackingStrategy;
}
set {
lineTrackingStrategy = value;
}
}
public ITextBufferStrategy TextBufferStrategy {
get {
return textBufferStrategy;
}
set {
textBufferStrategy = value;
}
}
public IFormattingStrategy FormattingStrategy {
get {
return formattingStrategy;
}
set {
formattingStrategy = value;
}
}
public FoldingManager FoldingManager {
get {
return foldingManager;
}
set {
foldingManager = value;
}
}
public IHighlightingStrategy HighlightingStrategy {
get {
return lineTrackingStrategy.HighlightingStrategy;
}
set {
lineTrackingStrategy.HighlightingStrategy = value;
}
}
public int TextLength {
get {
return textBufferStrategy.Length;
}
}
public BookmarkManager BookmarkManager {
get {
return bookmarkManager;
}
set {
bookmarkManager = value;
}
}
public ICustomLineManager CustomLineManager {
get {
return customLineManager;
}
set {
customLineManager = value;
}
}
public string TextContent {
get {
return GetText(0, textBufferStrategy.Length);
}
set {
Debug.Assert(textBufferStrategy != null);
Debug.Assert(lineTrackingStrategy != null);
OnDocumentAboutToBeChanged(new DocumentEventArgs(this, 0, 0, value));
textBufferStrategy.SetContent(value);
lineTrackingStrategy.SetContent(value);
undoStack.ClearAll();
OnDocumentChanged(new DocumentEventArgs(this, 0, 0, value));
OnTextContentChanged(EventArgs.Empty);
}
}
public void Insert(int offset, string text)
{
if (readOnly) {
return;
}
OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, -1, text));
DateTime time = DateTime.Now;
textBufferStrategy.Insert(offset, text);
time = DateTime.Now;
lineTrackingStrategy.Insert(offset, text);
time = DateTime.Now;
undoStack.Push(new UndoableInsert(this, offset, text));
time = DateTime.Now;
OnDocumentChanged(new DocumentEventArgs(this, offset, -1, text));
}
public void Remove(int offset, int length)
{
if (readOnly) {
return;
}
OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, length));
undoStack.Push(new UndoableDelete(this, offset, GetText(offset, length)));
textBufferStrategy.Remove(offset, length);
lineTrackingStrategy.Remove(offset, length);
OnDocumentChanged(new DocumentEventArgs(this, offset, length));
}
public void Replace(int offset, int length, string text)
{
if (readOnly) {
return;
}
OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, length, text));
undoStack.Push(new UndoableReplace(this, offset, GetText(offset, length), text));
textBufferStrategy.Replace(offset, length, text);
lineTrackingStrategy.Replace(offset, length, text);
OnDocumentChanged(new DocumentEventArgs(this, offset, length, text));
}
public char GetCharAt(int offset)
{
return textBufferStrategy.GetCharAt(offset);
}
public string GetText(int offset, int length)
{
#if DEBUG
if (length < 0) throw new ArgumentOutOfRangeException("length", length, "length < 0");
#endif
return textBufferStrategy.GetText(offset, length);
}
public string GetText(ISegment segment)
{
return GetText(segment.Offset, segment.Length);
}
public int TotalNumberOfLines {
get {
return lineTrackingStrategy.TotalNumberOfLines;
}
}
public int GetLineNumberForOffset(int offset)
{
return lineTrackingStrategy.GetLineNumberForOffset(offset);
}
public LineSegment GetLineSegmentForOffset(int offset)
{
return lineTrackingStrategy.GetLineSegmentForOffset(offset);
}
public LineSegment GetLineSegment(int line)
{
return lineTrackingStrategy.GetLineSegment(line);
}
public int GetFirstLogicalLine(int lineNumber)
{
return lineTrackingStrategy.GetFirstLogicalLine(lineNumber);
}
public int GetLastLogicalLine(int lineNumber)
{
return lineTrackingStrategy.GetLastLogicalLine(lineNumber);
}
public int GetVisibleLine(int lineNumber)
{
return lineTrackingStrategy.GetVisibleLine(lineNumber);
}
// public int GetVisibleColumn(int logicalLine, int logicalColumn)
// {
// return lineTrackingStrategy.GetVisibleColumn(logicalLine, logicalColumn);
// }
//
public int GetNextVisibleLineAbove(int lineNumber, int lineCount)
{
return lineTrackingStrategy.GetNextVisibleLineAbove(lineNumber, lineCount);
}
public int GetNextVisibleLineBelow(int lineNumber, int lineCount)
{
return lineTrackingStrategy.GetNextVisibleLineBelow(lineNumber, lineCount);
}
public Point OffsetToPosition(int offset)
{
int lineNr = GetLineNumberForOffset(offset);
LineSegment line = GetLineSegment(lineNr);
return new Point(offset - line.Offset, lineNr);
}
public int PositionToOffset(Point p)
{
if (p.Y >= this.TotalNumberOfLines) {
return 0;
}
LineSegment line = GetLineSegment(p.Y);
return Math.Min(this.TextLength, line.Offset + Math.Min(line.Length, p.X));
}
public void UpdateSegmentListOnDocumentChange<T>(List<T> list, DocumentEventArgs e) where T : ISegment
{
for (int i = 0; i < list.Count; ++i) {
ISegment fm = list[i];
if (e.Offset <= fm.Offset && fm.Offset <= e.Offset + e.Length ||
e.Offset <= fm.Offset + fm.Length && fm.Offset + fm.Length <= e.Offset + e.Length) {
list.RemoveAt(i);
--i;
continue;
}
if (fm.Offset <= e.Offset && e.Offset <= fm.Offset + fm.Length) {
if (e.Text != null) {
fm.Length += e.Text.Length;
}
if (e.Length > 0) {
fm.Length -= e.Length;
}
continue;
}
if (fm.Offset >= e.Offset) {
if (e.Text != null) {
fm.Offset += e.Text.Length;
}
if (e.Length > 0) {
fm.Offset -= e.Length;
}
}
}
}
protected void OnDocumentAboutToBeChanged(DocumentEventArgs e)
{
if (DocumentAboutToBeChanged != null) {
DocumentAboutToBeChanged(this, e);
}
}
protected void OnDocumentChanged(DocumentEventArgs e)
{
if (DocumentChanged != null) {
DocumentChanged(this, e);
}
}
public event DocumentEventHandler DocumentAboutToBeChanged;
public event DocumentEventHandler DocumentChanged;
// UPDATE STUFF
List<TextAreaUpdate> updateQueue = new List<TextAreaUpdate>();
public List<TextAreaUpdate> UpdateQueue {
get {
return updateQueue;
}
}
public void RequestUpdate(TextAreaUpdate update)
{
updateQueue.Add(update);
}
public void CommitUpdate()
{
if (UpdateCommited != null) {
UpdateCommited(this, EventArgs.Empty);
}
}
protected virtual void OnTextContentChanged(EventArgs e)
{
if (TextContentChanged != null) {
TextContentChanged(this, e);
}
}
public event EventHandler UpdateCommited;
public event EventHandler TextContentChanged;
}
}