// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
using System.Windows;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
namespace ICSharpCode.AvalonEdit.Editing
{
///
/// Base class for margins.
/// Margins don't have to derive from this class, it just helps maintaining a reference to the TextView
/// and the TextDocument.
/// AbstractMargin derives from FrameworkElement, so if you don't want to handle visual children and rendering
/// on your own, choose another base class for your margin!
///
public abstract class AbstractMargin : FrameworkElement, ITextViewConnect
{
///
/// TextView property.
///
public static readonly DependencyProperty TextViewProperty =
DependencyProperty.Register("TextView", typeof(TextView), typeof(AbstractMargin),
new FrameworkPropertyMetadata(OnTextViewChanged));
///
/// Gets/sets the text view for which line numbers are displayed.
///
/// Adding a margin to will automatically set this property to the text area's TextView.
public TextView TextView {
get { return (TextView)GetValue(TextViewProperty); }
set { SetValue(TextViewProperty, value); }
}
static void OnTextViewChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
AbstractMargin margin = (AbstractMargin)dp;
margin.wasAutoAddedToTextView = false;
margin.OnTextViewChanged((TextView)e.OldValue, (TextView)e.NewValue);
}
// automatically set/unset TextView property using ITextViewConnect
bool wasAutoAddedToTextView;
void ITextViewConnect.AddToTextView(TextView textView)
{
if (this.TextView == null) {
this.TextView = textView;
wasAutoAddedToTextView = true;
} else if (this.TextView != textView) {
throw new InvalidOperationException("This margin belongs to a different TextView.");
}
}
void ITextViewConnect.RemoveFromTextView(TextView textView)
{
if (wasAutoAddedToTextView && this.TextView == textView) {
this.TextView = null;
Debug.Assert(!wasAutoAddedToTextView); // setting this.TextView should have unset this flag
}
}
TextDocument document;
///
/// Gets the document associated with the margin.
///
public TextDocument Document {
get { return document; }
}
///
/// Called when the is changing.
///
protected virtual void OnTextViewChanged(TextView oldTextView, TextView newTextView)
{
if (oldTextView != null) {
oldTextView.DocumentChanged -= TextViewDocumentChanged;
}
if (newTextView != null) {
newTextView.DocumentChanged += TextViewDocumentChanged;
}
TextViewDocumentChanged(null, null);
}
void TextViewDocumentChanged(object sender, EventArgs e)
{
OnDocumentChanged(document, TextView != null ? TextView.Document : null);
}
///
/// Called when the is changing.
///
protected virtual void OnDocumentChanged(TextDocument oldDocument, TextDocument newDocument)
{
document = newDocument;
}
}
}