Browse Source
Fixed bugs in text drag+drop. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3842 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
17 changed files with 473 additions and 153 deletions
@ -0,0 +1,48 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <author name="Daniel Grunwald"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Diagnostics; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Media; |
||||||
|
|
||||||
|
namespace ICSharpCode.AvalonEdit.Gui |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Base class for known layers.
|
||||||
|
/// </summary>
|
||||||
|
class Layer : UIElement |
||||||
|
{ |
||||||
|
protected readonly TextView textView; |
||||||
|
protected readonly KnownLayer knownLayer; |
||||||
|
|
||||||
|
public Layer(TextView textView, KnownLayer knownLayer) |
||||||
|
{ |
||||||
|
Debug.Assert(textView != null); |
||||||
|
this.textView = textView; |
||||||
|
this.knownLayer = knownLayer; |
||||||
|
|
||||||
|
this.IsHitTestVisible = false; |
||||||
|
} |
||||||
|
|
||||||
|
protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters) |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnRender(DrawingContext drawingContext) |
||||||
|
{ |
||||||
|
base.OnRender(drawingContext); |
||||||
|
textView.RenderBackground(drawingContext, knownLayer); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,95 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <author name="Daniel Grunwald"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Windows; |
||||||
|
|
||||||
|
namespace ICSharpCode.AvalonEdit.Gui |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// An enumeration of well-known layers.
|
||||||
|
/// </summary>
|
||||||
|
public enum KnownLayer |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// This layer is in the background.
|
||||||
|
/// There is no UIElement to represent this layer, it is directly drawn in the TextView.
|
||||||
|
/// It is invalid to replace the background layer or insert
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This layer is below the Selection layer.</remarks>
|
||||||
|
Background, |
||||||
|
/// <summary>
|
||||||
|
/// This layer contains the selection rectangle.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This layer is between the Background and the Text layers.</remarks>
|
||||||
|
Selection, |
||||||
|
/// <summary>
|
||||||
|
/// This layer contains the text and inline UI elements.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This layer is between the Selection and the Caret layers.</remarks>
|
||||||
|
Text, |
||||||
|
/// <summary>
|
||||||
|
/// This layer contains the blinking caret.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This layer is above the Text layer.</remarks>
|
||||||
|
Caret |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies where a new layer is inserted, in relation to an old layer.
|
||||||
|
/// </summary>
|
||||||
|
public enum LayerInsertionPosition |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// The new layer is inserted below the specified layer.
|
||||||
|
/// </summary>
|
||||||
|
Below, |
||||||
|
/// <summary>
|
||||||
|
/// The new layer replaces the specified layer. The old layer is removed
|
||||||
|
/// from the <see cref="TextView.Layers"/> collection.
|
||||||
|
/// </summary>
|
||||||
|
Replace, |
||||||
|
/// <summary>
|
||||||
|
/// The new layer is inserted above the specified layer.
|
||||||
|
/// </summary>
|
||||||
|
Above |
||||||
|
} |
||||||
|
|
||||||
|
sealed class LayerPosition : IComparable<LayerPosition> |
||||||
|
{ |
||||||
|
internal static readonly DependencyProperty LayerPositionProperty = |
||||||
|
DependencyProperty.RegisterAttached("LayerPosition", typeof(LayerPosition), typeof(LayerPosition)); |
||||||
|
|
||||||
|
public static void SetLayerPosition(UIElement layer, LayerPosition value) |
||||||
|
{ |
||||||
|
layer.SetValue(LayerPositionProperty, value); |
||||||
|
} |
||||||
|
|
||||||
|
public static LayerPosition GetLayerPosition(UIElement layer) |
||||||
|
{ |
||||||
|
return (LayerPosition)layer.GetValue(LayerPositionProperty); |
||||||
|
} |
||||||
|
|
||||||
|
internal readonly KnownLayer KnownLayer; |
||||||
|
internal readonly LayerInsertionPosition Position; |
||||||
|
|
||||||
|
public LayerPosition(KnownLayer knownLayer, LayerInsertionPosition position) |
||||||
|
{ |
||||||
|
this.KnownLayer = knownLayer; |
||||||
|
this.Position = position; |
||||||
|
} |
||||||
|
|
||||||
|
public int CompareTo(LayerPosition other) |
||||||
|
{ |
||||||
|
int r = this.KnownLayer.CompareTo(other.KnownLayer); |
||||||
|
if (r != 0) |
||||||
|
return r; |
||||||
|
else |
||||||
|
return this.Position.CompareTo(other.Position); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <author name="Daniel Grunwald"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Media; |
||||||
|
|
||||||
|
namespace ICSharpCode.AvalonEdit.Gui |
||||||
|
{ |
||||||
|
sealed class SelectionLayer : Layer, IWeakEventListener |
||||||
|
{ |
||||||
|
readonly TextArea textArea; |
||||||
|
|
||||||
|
public SelectionLayer(TextArea textArea) : base(textArea.TextView, KnownLayer.Selection) |
||||||
|
{ |
||||||
|
this.textArea = textArea; |
||||||
|
TextViewWeakEventManager.VisualLinesChanged.AddListener(textView, this); |
||||||
|
} |
||||||
|
|
||||||
|
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) |
||||||
|
{ |
||||||
|
if (managerType == typeof(TextViewWeakEventManager.VisualLinesChanged)) { |
||||||
|
InvalidateVisual(); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnRender(DrawingContext drawingContext) |
||||||
|
{ |
||||||
|
base.OnRender(drawingContext); |
||||||
|
|
||||||
|
BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder(); |
||||||
|
geoBuilder.AddSegments(textView, textArea.Selection.Segments); |
||||||
|
PathGeometry geometry = geoBuilder.CreateGeometry(); |
||||||
|
if (geometry != null) { |
||||||
|
SolidColorBrush lightHighlightBrush = new SolidColorBrush(SystemColors.HighlightColor); |
||||||
|
lightHighlightBrush.Opacity = 0.7; |
||||||
|
lightHighlightBrush.Freeze(); |
||||||
|
Pen pen = new Pen(SystemColors.HighlightBrush, 1); |
||||||
|
//pen.LineJoin = PenLineJoin.Round;
|
||||||
|
pen.Freeze(); |
||||||
|
drawingContext.DrawGeometry(lightHighlightBrush, pen, geometry); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,107 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <author name="Daniel Grunwald"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Media; |
||||||
|
|
||||||
|
namespace ICSharpCode.AvalonEdit.Gui |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// The control that contains the text.
|
||||||
|
///
|
||||||
|
/// This control is used to allow other UIElements to be placed inside the TextView but
|
||||||
|
/// behind the text.
|
||||||
|
/// The text rendering process (VisualLine creation) is controlled by the TextView, this
|
||||||
|
/// class simply displays the created Visual Lines.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This class does not contain any input handling and is invisible to hit testing. Input
|
||||||
|
/// is handled by the TextView.
|
||||||
|
/// This allows UIElements that are displayed behind the text, but still can react to mouse input.
|
||||||
|
/// </remarks>
|
||||||
|
sealed class TextLayer : Layer |
||||||
|
{ |
||||||
|
public TextLayer(TextView textView) : base(textView, KnownLayer.Text) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnRender(DrawingContext drawingContext) |
||||||
|
{ |
||||||
|
base.OnRender(drawingContext); |
||||||
|
textView.RenderTextLayer(drawingContext); |
||||||
|
} |
||||||
|
|
||||||
|
#region Inline object handling
|
||||||
|
internal List<InlineObjectRun> inlineObjects = new List<InlineObjectRun>(); |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a new inline object.
|
||||||
|
/// </summary>
|
||||||
|
internal void AddInlineObject(InlineObjectRun inlineObject) |
||||||
|
{ |
||||||
|
inlineObjects.Add(inlineObject); |
||||||
|
AddVisualChild(inlineObject.Element); |
||||||
|
inlineObject.Element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); |
||||||
|
} |
||||||
|
|
||||||
|
List<VisualLine> visualLinesWithOutstandingInlineObjects = new List<VisualLine>(); |
||||||
|
|
||||||
|
internal void RemoveInlineObjects(VisualLine visualLine) |
||||||
|
{ |
||||||
|
// Delay removing inline objects:
|
||||||
|
// A document change immediately invalidates affected visual lines, but it does not
|
||||||
|
// cause an immediate redraw.
|
||||||
|
// To prevent inline objects from flickering when they are recreated, we delay removing
|
||||||
|
// inline objects until the next redraw.
|
||||||
|
visualLinesWithOutstandingInlineObjects.Add(visualLine); |
||||||
|
} |
||||||
|
|
||||||
|
internal void RemoveInlineObjectsNow() |
||||||
|
{ |
||||||
|
inlineObjects.RemoveAll( |
||||||
|
ior => { |
||||||
|
if (visualLinesWithOutstandingInlineObjects.Contains(ior.VisualLine)) { |
||||||
|
ior.VisualLine = null; |
||||||
|
RemoveVisualChild(ior.Element); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
}); |
||||||
|
visualLinesWithOutstandingInlineObjects.Clear(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the inline object that displays the specified UIElement.
|
||||||
|
/// </summary>
|
||||||
|
internal void RemoveInlineObject(UIElement element) |
||||||
|
{ |
||||||
|
inlineObjects.RemoveAll( |
||||||
|
ior => { |
||||||
|
if (ior.Element == element) { |
||||||
|
ior.VisualLine = null; |
||||||
|
RemoveVisualChild(ior.Element); |
||||||
|
return true; |
||||||
|
} |
||||||
|
return false; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override int VisualChildrenCount { |
||||||
|
get { return inlineObjects.Count; } |
||||||
|
} |
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
protected override Visual GetVisualChild(int index) |
||||||
|
{ |
||||||
|
return inlineObjects[index].Element; |
||||||
|
} |
||||||
|
#endregion
|
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue