first commit
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
// <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.Drawing;
|
||||
using SWF = System.Windows.Forms;
|
||||
|
||||
namespace ICSharpCode.TextEditor.Document
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of Bookmark.
|
||||
/// </summary>
|
||||
public class Bookmark
|
||||
{
|
||||
IDocument document;
|
||||
TextAnchor anchor;
|
||||
TextLocation location;
|
||||
bool isEnabled = true;
|
||||
|
||||
public IDocument Document {
|
||||
get {
|
||||
return document;
|
||||
}
|
||||
set {
|
||||
if (document != value) {
|
||||
if (anchor != null) {
|
||||
location = anchor.Location;
|
||||
anchor = null;
|
||||
}
|
||||
document = value;
|
||||
CreateAnchor();
|
||||
OnDocumentChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateAnchor()
|
||||
{
|
||||
if (document != null) {
|
||||
LineSegment line = document.GetLineSegment(Math.Max(0, Math.Min(location.Line, document.TotalNumberOfLines-1)));
|
||||
anchor = line.CreateAnchor(Math.Max(0, Math.Min(location.Column, line.Length)));
|
||||
// after insertion: keep bookmarks after the initial whitespace (see DefaultFormattingStrategy.SmartReplaceLine)
|
||||
anchor.MovementType = AnchorMovementType.AfterInsertion;
|
||||
anchor.Deleted += AnchorDeleted;
|
||||
}
|
||||
}
|
||||
|
||||
void AnchorDeleted(object sender, EventArgs e)
|
||||
{
|
||||
document.BookmarkManager.RemoveMark(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the TextAnchor used for this bookmark.
|
||||
/// Is null if the bookmark is not connected to a document.
|
||||
/// </summary>
|
||||
public TextAnchor Anchor {
|
||||
get { return anchor; }
|
||||
}
|
||||
|
||||
public TextLocation Location {
|
||||
get {
|
||||
if (anchor != null)
|
||||
return anchor.Location;
|
||||
else
|
||||
return location;
|
||||
}
|
||||
set {
|
||||
location = value;
|
||||
CreateAnchor();
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler DocumentChanged;
|
||||
|
||||
protected virtual void OnDocumentChanged(EventArgs e)
|
||||
{
|
||||
if (DocumentChanged != null) {
|
||||
DocumentChanged(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabled {
|
||||
get {
|
||||
return isEnabled;
|
||||
}
|
||||
set {
|
||||
if (isEnabled != value) {
|
||||
isEnabled = value;
|
||||
if (document != null) {
|
||||
document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, LineNumber));
|
||||
document.CommitUpdate();
|
||||
}
|
||||
OnIsEnabledChanged(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler IsEnabledChanged;
|
||||
|
||||
protected virtual void OnIsEnabledChanged(EventArgs e)
|
||||
{
|
||||
if (IsEnabledChanged != null) {
|
||||
IsEnabledChanged(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
public int LineNumber {
|
||||
get {
|
||||
if (anchor != null)
|
||||
return anchor.LineNumber;
|
||||
else
|
||||
return location.Line;
|
||||
}
|
||||
}
|
||||
|
||||
public int ColumnNumber {
|
||||
get {
|
||||
if (anchor != null)
|
||||
return anchor.ColumnNumber;
|
||||
else
|
||||
return location.Column;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets if the bookmark can be toggled off using the 'set/unset bookmark' command.
|
||||
/// </summary>
|
||||
public virtual bool CanToggle {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public Bookmark(IDocument document, TextLocation location) : this(document, location, true)
|
||||
{
|
||||
}
|
||||
|
||||
public Bookmark(IDocument document, TextLocation location, bool isEnabled)
|
||||
{
|
||||
this.document = document;
|
||||
this.isEnabled = isEnabled;
|
||||
this.Location = location;
|
||||
}
|
||||
|
||||
public virtual bool Click(SWF.Control parent, SWF.MouseEventArgs e)
|
||||
{
|
||||
if (e.Button == SWF.MouseButtons.Left && CanToggle) {
|
||||
document.BookmarkManager.RemoveMark(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual void Draw(IconBarMargin margin, Graphics g, Point p)
|
||||
{
|
||||
margin.DrawBookmark(g, p.Y, isEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// <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;
|
||||
|
||||
namespace ICSharpCode.TextEditor.Document
|
||||
{
|
||||
public delegate void BookmarkEventHandler(object sender, BookmarkEventArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Description of BookmarkEventHandler.
|
||||
/// </summary>
|
||||
public class BookmarkEventArgs : EventArgs
|
||||
{
|
||||
Bookmark bookmark;
|
||||
|
||||
public Bookmark Bookmark {
|
||||
get {
|
||||
return bookmark;
|
||||
}
|
||||
}
|
||||
|
||||
public BookmarkEventArgs(Bookmark bookmark)
|
||||
{
|
||||
this.bookmark = bookmark;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
// <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.Collections.ObjectModel;
|
||||
using ICSharpCode.TextEditor.Util;
|
||||
|
||||
namespace ICSharpCode.TextEditor.Document
|
||||
{
|
||||
public interface IBookmarkFactory
|
||||
{
|
||||
Bookmark CreateBookmark(IDocument document, TextLocation location);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This class handles the bookmarks for a buffer
|
||||
/// </summary>
|
||||
public class BookmarkManager
|
||||
{
|
||||
IDocument document;
|
||||
#if DEBUG
|
||||
IList<Bookmark> bookmark = new CheckedList<Bookmark>();
|
||||
#else
|
||||
List<Bookmark> bookmark = new List<Bookmark>();
|
||||
#endif
|
||||
|
||||
/// <value>
|
||||
/// Contains all bookmarks
|
||||
/// </value>
|
||||
public ReadOnlyCollection<Bookmark> Marks {
|
||||
get {
|
||||
return new ReadOnlyCollection<Bookmark>(bookmark);
|
||||
}
|
||||
}
|
||||
|
||||
public IDocument Document {
|
||||
get {
|
||||
return document;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="BookmarkManager"/>
|
||||
/// </summary>
|
||||
internal BookmarkManager(IDocument document, LineManager lineTracker)
|
||||
{
|
||||
this.document = document;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the bookmark factory used to create bookmarks for "ToggleMarkAt".
|
||||
/// </summary>
|
||||
public IBookmarkFactory Factory { get; set;}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the mark at the line <code>location.Line</code> if it is not set, if the
|
||||
/// line is already marked the mark is cleared.
|
||||
/// </summary>
|
||||
public void ToggleMarkAt(TextLocation location)
|
||||
{
|
||||
Bookmark newMark;
|
||||
if (Factory != null) {
|
||||
newMark = Factory.CreateBookmark(document, location);
|
||||
} else {
|
||||
newMark = new Bookmark(document, location);
|
||||
}
|
||||
|
||||
Type newMarkType = newMark.GetType();
|
||||
|
||||
for (int i = 0; i < bookmark.Count; ++i) {
|
||||
Bookmark mark = bookmark[i];
|
||||
|
||||
if (mark.LineNumber == location.Line && mark.CanToggle && mark.GetType() == newMarkType) {
|
||||
bookmark.RemoveAt(i);
|
||||
OnRemoved(new BookmarkEventArgs(mark));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bookmark.Add(newMark);
|
||||
OnAdded(new BookmarkEventArgs(newMark));
|
||||
}
|
||||
|
||||
public void AddMark(Bookmark mark)
|
||||
{
|
||||
bookmark.Add(mark);
|
||||
OnAdded(new BookmarkEventArgs(mark));
|
||||
}
|
||||
|
||||
public void RemoveMark(Bookmark mark)
|
||||
{
|
||||
bookmark.Remove(mark);
|
||||
OnRemoved(new BookmarkEventArgs(mark));
|
||||
}
|
||||
|
||||
public void RemoveMarks(Predicate<Bookmark> predicate)
|
||||
{
|
||||
for (int i = 0; i < bookmark.Count; ++i) {
|
||||
Bookmark bm = bookmark[i];
|
||||
if (predicate(bm)) {
|
||||
bookmark.RemoveAt(i--);
|
||||
OnRemoved(new BookmarkEventArgs(bm));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <returns>
|
||||
/// true, if a mark at mark exists, otherwise false
|
||||
/// </returns>
|
||||
public bool IsMarked(int lineNr)
|
||||
{
|
||||
for (int i = 0; i < bookmark.Count; ++i) {
|
||||
if (bookmark[i].LineNumber == lineNr) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Clears all bookmark
|
||||
/// </remarks>
|
||||
public void Clear()
|
||||
{
|
||||
foreach (Bookmark mark in bookmark) {
|
||||
OnRemoved(new BookmarkEventArgs(mark));
|
||||
}
|
||||
bookmark.Clear();
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// The lowest mark, if no marks exists it returns -1
|
||||
/// </value>
|
||||
public Bookmark GetFirstMark(Predicate<Bookmark> predicate)
|
||||
{
|
||||
if (bookmark.Count < 1) {
|
||||
return null;
|
||||
}
|
||||
Bookmark first = null;
|
||||
for (int i = 0; i < bookmark.Count; ++i) {
|
||||
if (predicate(bookmark[i]) && bookmark[i].IsEnabled && (first == null || bookmark[i].LineNumber < first.LineNumber)) {
|
||||
first = bookmark[i];
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// The highest mark, if no marks exists it returns -1
|
||||
/// </value>
|
||||
public Bookmark GetLastMark(Predicate<Bookmark> predicate)
|
||||
{
|
||||
if (bookmark.Count < 1) {
|
||||
return null;
|
||||
}
|
||||
Bookmark last = null;
|
||||
for (int i = 0; i < bookmark.Count; ++i) {
|
||||
if (predicate(bookmark[i]) && bookmark[i].IsEnabled && (last == null || bookmark[i].LineNumber > last.LineNumber)) {
|
||||
last = bookmark[i];
|
||||
}
|
||||
}
|
||||
return last;
|
||||
}
|
||||
bool AcceptAnyMarkPredicate(Bookmark mark)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public Bookmark GetNextMark(int curLineNr)
|
||||
{
|
||||
return GetNextMark(curLineNr, AcceptAnyMarkPredicate);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// returns first mark higher than <code>lineNr</code>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// returns the next mark > cur, if it not exists it returns FirstMark()
|
||||
/// </returns>
|
||||
public Bookmark GetNextMark(int curLineNr, Predicate<Bookmark> predicate)
|
||||
{
|
||||
if (bookmark.Count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bookmark next = GetFirstMark(predicate);
|
||||
foreach (Bookmark mark in bookmark) {
|
||||
if (predicate(mark) && mark.IsEnabled && mark.LineNumber > curLineNr) {
|
||||
if (mark.LineNumber < next.LineNumber || next.LineNumber <= curLineNr) {
|
||||
next = mark;
|
||||
}
|
||||
}
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
public Bookmark GetPrevMark(int curLineNr)
|
||||
{
|
||||
return GetPrevMark(curLineNr, AcceptAnyMarkPredicate);
|
||||
}
|
||||
/// <remarks>
|
||||
/// returns first mark lower than <code>lineNr</code>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// returns the next mark lower than cur, if it not exists it returns LastMark()
|
||||
/// </returns>
|
||||
public Bookmark GetPrevMark(int curLineNr, Predicate<Bookmark> predicate)
|
||||
{
|
||||
if (bookmark.Count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Bookmark prev = GetLastMark(predicate);
|
||||
|
||||
foreach (Bookmark mark in bookmark) {
|
||||
if (predicate(mark) && mark.IsEnabled && mark.LineNumber < curLineNr) {
|
||||
if (mark.LineNumber > prev.LineNumber || prev.LineNumber >= curLineNr) {
|
||||
prev = mark;
|
||||
}
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
protected virtual void OnRemoved(BookmarkEventArgs e)
|
||||
{
|
||||
if (Removed != null) {
|
||||
Removed(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnAdded(BookmarkEventArgs e)
|
||||
{
|
||||
if (Added != null) {
|
||||
Added(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
public event BookmarkEventHandler Removed;
|
||||
public event BookmarkEventHandler Added;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
// <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.Xml;
|
||||
|
||||
namespace ICSharpCode.TextEditor.Document
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is used for storing the state of a bookmark manager
|
||||
/// </summary>
|
||||
public class BookmarkManagerMemento
|
||||
{
|
||||
List<int> bookmarks = new List<int>();
|
||||
|
||||
/// <value>
|
||||
/// Contains all bookmarks as int values
|
||||
/// </value>
|
||||
public List<int> Bookmarks {
|
||||
get {
|
||||
return bookmarks;
|
||||
}
|
||||
set {
|
||||
bookmarks = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates all bookmarks if they're in range of the document.
|
||||
/// (removing all bookmarks < 0 and bookmarks > max. line number
|
||||
/// </summary>
|
||||
public void CheckMemento(IDocument document)
|
||||
{
|
||||
for (int i = 0; i < bookmarks.Count; ++i) {
|
||||
int mark = (int)bookmarks[i];
|
||||
if (mark < 0 || mark >= document.TotalNumberOfLines) {
|
||||
bookmarks.RemoveAt(i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="BookmarkManagerMemento"/>
|
||||
/// </summary>
|
||||
public BookmarkManagerMemento()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="BookmarkManagerMemento"/>
|
||||
/// </summary>
|
||||
public BookmarkManagerMemento(XmlElement element)
|
||||
{
|
||||
foreach (XmlElement el in element.ChildNodes) {
|
||||
bookmarks.Add(int.Parse(el.Attributes["line"].InnerText));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="BookmarkManagerMemento"/>
|
||||
/// </summary>
|
||||
public BookmarkManagerMemento(List<int> bookmarks)
|
||||
{
|
||||
this.bookmarks = bookmarks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a xml element to a <see cref="BookmarkManagerMemento"/> object
|
||||
/// </summary>
|
||||
public object FromXmlElement(XmlElement element)
|
||||
{
|
||||
return new BookmarkManagerMemento(element);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this <see cref="BookmarkManagerMemento"/> to a xml element
|
||||
/// </summary>
|
||||
public XmlElement ToXmlElement(XmlDocument doc)
|
||||
{
|
||||
XmlElement bookmarknode = doc.CreateElement("Bookmarks");
|
||||
|
||||
foreach (int line in bookmarks) {
|
||||
XmlElement markNode = doc.CreateElement("Mark");
|
||||
|
||||
XmlAttribute lineAttr = doc.CreateAttribute("line");
|
||||
lineAttr.InnerText = line.ToString();
|
||||
markNode.Attributes.Append(lineAttr);
|
||||
|
||||
bookmarknode.AppendChild(markNode);
|
||||
}
|
||||
|
||||
return bookmarknode;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user