Browse Source

Merge 385231bac8 into ba372efbff

pull/564/merge
Abdelkarim Sellamna 8 years ago committed by GitHub
parent
commit
df8a4782b4
  1. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
  2. 114
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  3. 833
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/EditorSplitContainer.cs
  4. 52
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/EditorSplitContainerCommands.cs
  5. 58
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SpliterGrip.cs
  6. 28
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/themes/SpliterGrip.xaml
  7. 92
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/themes/generic.xaml

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj

@ -112,8 +112,11 @@
<Compile Include="Src\ContextActions\FindBaseClasses.cs" /> <Compile Include="Src\ContextActions\FindBaseClasses.cs" />
<Compile Include="Src\ContextActions\FindDerivedClassesOrOverrides.cs" /> <Compile Include="Src\ContextActions\FindDerivedClassesOrOverrides.cs" />
<Compile Include="Src\ContextActions\GoToEntityAction.cs" /> <Compile Include="Src\ContextActions\GoToEntityAction.cs" />
<Compile Include="Src\EditorSplitContainer.cs" />
<Compile Include="Src\EditorSplitContainerCommands.cs" />
<Compile Include="Src\EnhancedScrollBar.cs" /> <Compile Include="Src\EnhancedScrollBar.cs" />
<Compile Include="Src\HiddenDefinitionRenderer.cs" /> <Compile Include="Src\HiddenDefinitionRenderer.cs" />
<Compile Include="Src\SpliterGrip.cs" />
<Compile Include="Src\SyntaxHighlighting\CustomizingHighlighter.cs" /> <Compile Include="Src\SyntaxHighlighting\CustomizingHighlighter.cs" />
<Compile Include="Src\SyntaxHighlighting\FixedHighlighter.cs" /> <Compile Include="Src\SyntaxHighlighting\FixedHighlighter.cs" />
<Compile Include="Src\SyntaxHighlighting\MultiHighlighter.cs" /> <Compile Include="Src\SyntaxHighlighting\MultiHighlighter.cs" />
@ -217,6 +220,7 @@
<DependentUpon>SharpDevelopCompletionWindow.cs</DependentUpon> <DependentUpon>SharpDevelopCompletionWindow.cs</DependentUpon>
</Page> </Page>
<Page Include="themes\generic.xaml" /> <Page Include="themes\generic.xaml" />
<Page Include="themes\SpliterGrip.xaml" />
<ProjectReference Include="..\..\..\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj"> <ProjectReference Include="..\..\..\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj">
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project> <Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Name>ICSharpCode.AvalonEdit</Name> <Name>ICSharpCode.AvalonEdit</Name>

114
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -59,19 +59,32 @@ namespace ICSharpCode.AvalonEdit.AddIn
const string contextMenuPath = "/SharpDevelop/ViewContent/AvalonEdit/ContextMenu"; const string contextMenuPath = "/SharpDevelop/ViewContent/AvalonEdit/ContextMenu";
QuickClassBrowser quickClassBrowser; QuickClassBrowser quickClassBrowser;
readonly CodeEditorView primaryTextEditor; private CodeEditorView primaryTextEditor;
readonly CodeEditorAdapter primaryTextEditorAdapter; private CodeEditorView secondaryTextEditor;
private CodeEditorAdapter primaryTextEditorAdapter;
readonly IconBarManager iconBarManager; readonly IconBarManager iconBarManager;
readonly TextMarkerService textMarkerService; readonly TextMarkerService textMarkerService;
readonly IChangeWatcher changeWatcher; readonly IChangeWatcher changeWatcher;
ErrorPainter errorPainter; ErrorPainter errorPainter;
private EditorSplitContainer _splitContainer;
public CodeEditorView PrimaryTextEditor { public CodeEditorView PrimaryTextEditor {
get { return primaryTextEditor; } get { return primaryTextEditor; }
} }
public CodeEditorView SecondaryTextEditor{
get{ return secondaryTextEditor; }
}
public CodeEditorView ActiveTextEditor { public CodeEditorView ActiveTextEditor {
get { return primaryTextEditor; } get
{
// we return the editor that has keyboard focus in it.
if (secondaryTextEditor != null && secondaryTextEditor.IsKeyboardFocusWithin)
return secondaryTextEditor;
return primaryTextEditor;
}
} }
TextDocument document; TextDocument document;
@ -129,23 +142,26 @@ namespace ICSharpCode.AvalonEdit.AddIn
if (changeWatcher != null) { if (changeWatcher != null) {
changeWatcher.Initialize(this.Document, value); changeWatcher.Initialize(this.Document, value);
} }
UpdateSyntaxHighlighting(value);
UpdateSyntaxHighlighting(PrimaryTextEditor, value);
FetchParseInformation(); FetchParseInformation();
} }
} }
} }
void UpdateSyntaxHighlighting(FileName fileName) void UpdateSyntaxHighlighting(CodeEditorView editorView, FileName fileName)
{ {
var oldHighlighter = primaryTextEditor.GetService<IHighlighter>(); var oldHighlighter = editorView.GetService<IHighlighter>();
var highlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(fileName)); var highlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(fileName));
var highlighter = SD.EditorControlService.CreateHighlighter(document); var highlighter = SD.EditorControlService.CreateHighlighter(document);
primaryTextEditor.SyntaxHighlighting = highlighting; editorView.SyntaxHighlighting = highlighting;
primaryTextEditor.TextArea.TextView.LineTransformers.RemoveAll(t => t is HighlightingColorizer); editorView.TextArea.TextView.LineTransformers.RemoveAll(t => t is HighlightingColorizer);
primaryTextEditor.TextArea.TextView.LineTransformers.Insert(0, new HighlightingColorizer(highlighter)); editorView.TextArea.TextView.LineTransformers.Insert(0, new HighlightingColorizer(highlighter));
primaryTextEditor.UpdateCustomizedHighlighting(); editorView.UpdateCustomizedHighlighting();
// Dispose the old highlighter; necessary to avoid memory leaks as // Dispose the old highlighter; necessary to avoid memory leaks as
// semantic highlighters might attach to global parser events. // semantic highlighters might attach to global parser events.
@ -161,6 +177,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
const double minRowHeight = 40; const double minRowHeight = 40;
static CodeEditor()
{
InitEventHandlers();
}
public CodeEditor() public CodeEditor()
{ {
CodeEditorOptions.Instance.PropertyChanged += CodeEditorOptions_Instance_PropertyChanged; CodeEditorOptions.Instance.PropertyChanged += CodeEditorOptions_Instance_PropertyChanged;
@ -187,9 +208,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.ColumnDefinitions.Add(new ColumnDefinition()); this.ColumnDefinitions.Add(new ColumnDefinition());
this.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); this.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
this.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star), MinHeight = minRowHeight }); this.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star), MinHeight = minRowHeight });
SetRow(primaryTextEditor, 1);
this.Children.Add(primaryTextEditor); _splitContainer = new EditorSplitContainer
{
PrimaryView = primaryTextEditor
};
SetRow(_splitContainer, 1);
this.Children.Add(_splitContainer);
} }
void CodeEditorOptions_Instance_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) void CodeEditorOptions_Instance_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
@ -252,6 +278,65 @@ namespace ICSharpCode.AvalonEdit.AddIn
return codeEditorView; return codeEditorView;
} }
#region "EditorSplitContainer integration"
private static void InitEventHandlers()
{
EventManager.RegisterClassHandler(
typeof (CodeEditor),
EditorSplitContainer.RequestSecondaryViewEvent,
new RequestSecondaryViewEventHandler(
(sender, args) =>
{
var codeEditor = sender as CodeEditor;
if (codeEditor == null)
return;
codeEditor.OnRequestSecondaryView(args);
}));
EventManager.RegisterClassHandler(
typeof (CodeEditor),
EditorSplitContainer.DisposeSecondaryViewEvent,
new DisposeSecondaryViewEventHandler(
(sender, args) =>
{
var codeEditor = sender as CodeEditor;
if (codeEditor == null)
return;
codeEditor.OnDisposeOfSecondaryView(args);
}));
}
private void OnRequestSecondaryView(RequestSecondaryViewEventArgs e)
{
secondaryTextEditor = CreateTextEditor();
UpdateSyntaxHighlighting(secondaryTextEditor, FileName);
e.Container = secondaryTextEditor;
e.Handled = true;
}
private void OnDisposeOfSecondaryView(DisposeSecondaryViewEventArgs e)
{
var container = e.Container;
if (container == null)
return;
// if the primary editor is being disposed of, the user chose to keep the secondary,
// swap the editors.
if (container == PrimaryTextEditor && SecondaryTextEditor != null) {
primaryTextEditor = secondaryTextEditor;
primaryTextEditorAdapter = (CodeEditorAdapter)primaryTextEditor.TextArea.GetService(typeof(ITextEditor));
Debug.Assert(primaryTextEditorAdapter != null);
}
secondaryTextEditor = null;
e.Handled = true;
}
#endregion
void textEditor_TextArea_TextCopied(object sender, TextEventArgs e) void textEditor_TextArea_TextCopied(object sender, TextEventArgs e)
{ {
ICSharpCode.SharpDevelop.Gui.TextEditorSideBar.Instance.PutInClipboardRing(e.Text); ICSharpCode.SharpDevelop.Gui.TextEditorSideBar.Instance.PutInClipboardRing(e.Text);
@ -711,6 +796,11 @@ namespace ICSharpCode.AvalonEdit.AddIn
changeWatcher.Dispose(); changeWatcher.Dispose();
this.Document = null; this.Document = null;
DisposeTextEditor(primaryTextEditor); DisposeTextEditor(primaryTextEditor);
//TODO: dispose of secondary editor is necessary
if (secondaryTextEditor != null) {
DisposeTextEditor(secondaryTextEditor);
}
} }
} }
} }

833
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/EditorSplitContainer.cs

@ -0,0 +1,833 @@
/*
* Created by SharpDevelop.
* User: Abdelkarim
* Date: 9/22/2014
* Time: 8:07 AM
*
*/
using System;
using System.Collections;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
namespace ICSharpCode.AvalonEdit.AddIn
{
[ContentProperty("PrimaryView")]
public class EditorSplitContainer : FrameworkElement
{
#region "Fields"
private readonly Rect _emptyRect = new Rect();
private UIElement _secondaryViewContainer;
private UIElement _primaryViewContainer;
private SpliterGrip _grip;
private readonly UIElementCollection _visualChildren;
private double _gripOffset;
// in percent
private bool _isSecondaryViewCollapsing;
private bool _isPrimaryViewCollapsing;
private bool _hideSpliterGrip;
private bool _isGripDragging;
#endregion
#region "Constructors"
/// <summary>
/// Initializes static members of the <see cref="EditorSplitContainer"/> class.
/// </summary>
static EditorSplitContainer()
{
ClipToBoundsProperty.OverrideMetadata(typeof(EditorSplitContainer), new FrameworkPropertyMetadata(BooleanBoxes.True));
InitCommands();
InitEventHandlers();
}
/// <summary>
/// Initializes instance members of the <see cref="EditorSplitContainer"/> class.
/// </summary>
public EditorSplitContainer()
{
InitSplitterHandle();
_visualChildren = new UIElementCollection(this, this) { _grip };
LoadInInitialLayout();
}
#endregion
#region "Events"
#region RequestSecondaryView
/// <summary>
/// RequestSecondaryView Routed Event
/// </summary>
public static readonly RoutedEvent RequestSecondaryViewEvent = EventManager.RegisterRoutedEvent("RequestSecondaryView",
RoutingStrategy.Bubble, typeof(RequestSecondaryViewEventHandler), typeof(EditorSplitContainer));
/// <summary>
/// Occurs when ...
/// </summary>
public event RequestSecondaryViewEventHandler RequestSecondaryView {
add { AddHandler(RequestSecondaryViewEvent, value); }
remove { RemoveHandler(RequestSecondaryViewEvent, value); }
}
/// <summary>
///
/// </summary>
/// <returns></returns>
protected RequestSecondaryViewEventArgs RaiseRequestSecondaryViewEvent()
{
var args = new RequestSecondaryViewEventArgs { RoutedEvent = RequestSecondaryViewEvent };
this.RaiseEvent(args);
return args;
}
#endregion
#region DisposeSecondaryView
/// <summary>
/// DisposeSecondaryView Routed Event
/// </summary>
public static readonly RoutedEvent DisposeSecondaryViewEvent = EventManager.RegisterRoutedEvent(
"DisposeSecondaryView",
RoutingStrategy.Bubble,
typeof(DisposeSecondaryViewEventHandler),
typeof(EditorSplitContainer));
/// <summary>
/// Occurs when ...
/// </summary>
public event DisposeSecondaryViewEventHandler DisposeSecondaryView {
add { AddHandler(DisposeSecondaryViewEvent, value); }
remove { RemoveHandler(DisposeSecondaryViewEvent, value); }
}
/// <summary>
/// A helper method to raise the <see cref="DisposeSecondaryView"/> event.
/// </summary>
protected void RaiseDisposeSecondaryViewEvent(object container)
{
// It is not immediately raised, but when idle.
// In case the dispose operation is expensive.
this.Dispatcher.BeginInvoke(
DispatcherPriority.ApplicationIdle,
new Action<object>(c => {
var args = new DisposeSecondaryViewEventArgs {
RoutedEvent = DisposeSecondaryViewEvent,
Container = c
};
this.RaiseEvent(args);
}),
container);
}
#endregion
#endregion
#region "Static Methods"
private static void InitCommands()
{
CommandManager.RegisterClassCommandBinding(typeof(EditorSplitContainer), new CommandBinding(
EditorSplitContainerCommands.SplitEditorCommand,
(sender, e) => {
var container = sender as EditorSplitContainer;
if (container == null)
return;
container.OnSplitEditor();
},
(sender, e) => {
var container = sender as EditorSplitContainer;
if (container == null)
return;
e.CanExecute = container.IsSplit;
}));
CommandManager.RegisterClassCommandBinding(typeof(EditorSplitContainer), new CommandBinding(
EditorSplitContainerCommands.RemoveSplitCommand,
(sender, e) => {
var container = sender as EditorSplitContainer;
if (container == null)
return;
container.OnRemoveSplit();
},
(sender, e) => {
var container = sender as EditorSplitContainer;
if (container == null)
return;
e.CanExecute = !container.IsSplit;
}));
}
private static void InitEventHandlers()
{
EventManager.RegisterClassHandler(typeof(EditorSplitContainer), Thumb.DragStartedEvent, new DragStartedEventHandler(OnEditorGripDragStarted));
EventManager.RegisterClassHandler(typeof(EditorSplitContainer), Thumb.DragDeltaEvent, new DragDeltaEventHandler(OnEditorGripDragDelta));
EventManager.RegisterClassHandler(typeof(EditorSplitContainer), Thumb.DragCompletedEvent, new DragCompletedEventHandler(OnEditorGripDragCompleted));
}
private static void OnEditorGripDragCompleted(object sender, DragCompletedEventArgs e)
{
var splitContainer = sender as EditorSplitContainer;
if (splitContainer == null)
return;
var thumb = e.OriginalSource as Thumb;
if (thumb == null || thumb == splitContainer._grip || thumb.Name != "PART_EditorGrip")
return;
splitContainer.OnDragCompleted();
}
private static void OnEditorGripDragDelta(object sender, DragDeltaEventArgs e)
{
var splitContainer = sender as EditorSplitContainer;
if (splitContainer == null)
return;
var thumb = e.OriginalSource as Thumb;
if (thumb == null || thumb == splitContainer._grip || thumb.Name != "PART_EditorGrip")
return;
splitContainer.OnEditorGripDragDelta(splitContainer.Orientation == Orientation.Horizontal
? e.VerticalChange
: e.HorizontalChange);
e.Handled = true;
}
private static void OnEditorGripDragStarted(object sender, DragStartedEventArgs e)
{
var splitContainer = sender as EditorSplitContainer;
if (splitContainer == null)
return;
var thumb = e.OriginalSource as Thumb;
if (thumb == null || thumb == splitContainer._grip || thumb.Name != "PART_EditorGrip")
return;
// when this occur the editor grip is visible, and the split container has only
// one view in it, the 2nd view.
splitContainer.OnDragStarted();
}
#endregion
#region "Properties"
#region Orientation
/// <summary>
/// Identifies the <see cref="Orientation"/> dependency property.
/// </summary>
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation",
typeof(Orientation),
typeof(EditorSplitContainer),
new FrameworkPropertyMetadata(Orientation.Horizontal,
FrameworkPropertyMetadataOptions.AffectsArrange,
(o, e) => {
var splitContainer = o as EditorSplitContainer;
if (splitContainer == null || splitContainer._grip == null)
return;
splitContainer._grip.Orientation = (Orientation)e.NewValue;
}),
IsValidOrientation);
private static bool IsValidOrientation(object value)
{
var orientation = (Orientation)value;
return orientation == Orientation.Horizontal || orientation == Orientation.Vertical;
}
/// <summary>
/// Gets or sets the Orientation property. This is a dependency property.
/// </summary>
/// <value>
///
/// </value>
[Bindable(true)]
public Orientation Orientation {
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
#endregion
#region IsSplit
private static readonly DependencyPropertyKey IsSplitPropertyKey = DependencyProperty.RegisterReadOnly(
"IsSplit",
typeof(bool),
typeof(EditorSplitContainer),
new FrameworkPropertyMetadata(
BooleanBoxes.False,
(o, args) => {
var container = (EditorSplitContainer)o;
container.OnIsSplitChanged((bool)args.NewValue);
}));
public static readonly DependencyProperty IsSplitProperty = IsSplitPropertyKey.DependencyProperty;
/// <summary>
/// Gets a value that indicates whether the editor is split into two.
/// </summary>
public bool IsSplit {
get { return (bool)GetValue(IsSplitProperty); }
internal set { SetValue(IsSplitPropertyKey, value); }
}
#endregion
#endregion
#region "Plain Properties"
/// <summary>
/// Gets the number of visual child elements within this element.
/// </summary>
/// <returns>
/// The number of visual child elements for this element.
/// </returns>
protected override int VisualChildrenCount {
get {
if (_visualChildren == null)
return 0;
return _visualChildren.Count;
}
}
/// <summary>
/// Gets an enumerator for logical child elements of this element.
/// </summary>
/// <returns>
/// An enumerator for logical child elements of this element.
/// </returns>
protected override IEnumerator LogicalChildren {
get {
var arrayList = new ArrayList(3);
foreach (var child in _visualChildren)
arrayList.Add(child);
return arrayList.GetEnumerator();
}
}
/// <summary>
/// The element that hosts the secondary view.
/// </summary>
public UIElement SecondaryView {
get { return _secondaryViewContainer == null ? null : _secondaryViewContainer; }
private set {
UpdateView(_secondaryViewContainer, value);
_secondaryViewContainer = value;
}
}
/// <summary>
/// The element that hosts the primary view.
/// </summary>
public UIElement PrimaryView {
get { return _primaryViewContainer; }
set {
if (_primaryViewContainer == value)
throw new NotSupportedException("");
UpdateView(_primaryViewContainer, value);
_primaryViewContainer = value;
}
}
/// <summary>
/// Gets a value that indicates whether we can snap the spliter grip to the top edge.
/// </summary>
private bool CanCollapseSecondaryView {
get {
if (Density > 0) {
var offset = 20 * Density;
return _gripOffset <= offset;
}
return false;
}
}
/// <summary>
/// Gets a value that indicates whether we can snap the spliter grip to the bottom edge
/// </summary>
private bool CanCollapsePrimaryView {
get {
if (Density > 0) {
var offset = 20 * Density;
return _gripOffset >= (100 - offset);
}
return false;
}
}
private double Density { get; set; }
private bool InternalIsSplit { get; set; }
#endregion
#region "Public Methods"
/// <summary>
/// Will split the editor into half.
/// </summary>
public void OnSplitEditor()
{
if (!IsSplit)
return;
_gripOffset = 50;
ComputeOffset(0);
InternalIsSplit = false;
IsSplit = false;
InvalidateVisual();
}
/// <summary>
/// Will remove the split from the editor if it is present
/// </summary>
public void OnRemoveSplit()
{
if (IsSplit)
return;
_gripOffset = 0;
ComputeOffset(0);
InternalIsSplit = true;
IsSplit = true;
InvalidateVisual();
}
#endregion
#region "Protected Overrides"
protected override Visual GetVisualChild(int index)
{
if (_visualChildren == null || (index < 0 || index >= _visualChildren.Count))
throw new ArgumentOutOfRangeException("index");
return _visualChildren[index];
}
protected override Size MeasureOverride(Size availableSize)
{
bool isHorizontal = Orientation == Orientation.Horizontal;
if (isHorizontal && (double.IsPositiveInfinity(availableSize.Height) || double.IsInfinity(availableSize.Height)))
return base.MeasureOverride(availableSize);
if (!isHorizontal && (double.IsPositiveInfinity(availableSize.Width) || double.IsInfinity(availableSize.Width)))
return base.MeasureOverride(availableSize);
double startPos, handleSize, secondaryViewSize, primaryViewSize;
this.ComputePartsSizes(availableSize, isHorizontal, out secondaryViewSize, out primaryViewSize, out handleSize, out startPos);
var secondaryView = SecondaryView;
if (secondaryView != null)
secondaryView.Measure(isHorizontal
? new Size(availableSize.Width, secondaryViewSize)
: new Size(secondaryViewSize, availableSize.Height));
var view2 = PrimaryView;
if (view2 != null)
view2.Measure(isHorizontal
? new Size(availableSize.Width, primaryViewSize)
: new Size(primaryViewSize, availableSize.Height));
_grip.Measure(availableSize);
return _grip.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
// initialization
var isHorizontal = Orientation == Orientation.Horizontal;
var secondaryView = SecondaryView;
var primaryView = PrimaryView;
double secondaryViewSize, primaryViewSize, gripSize, startPos;
ComputePartsSizes(finalSize, isHorizontal, out secondaryViewSize, out primaryViewSize, out gripSize, out startPos);
Rect finalRect = isHorizontal
? new Rect {
Location = new Point(0, startPos),
Width = finalSize.Width
}
: new Rect {
Location = new Point(startPos, 0),
Height = finalSize.Height
};
if (InternalIsSplit) {
if (_isSecondaryViewCollapsing) {
// SecondaryView
if (secondaryView != null)
secondaryView.Arrange(_emptyRect);
// Grip
if (isHorizontal) {
finalRect.Y = startPos;
finalRect.Height = gripSize;
} else {
finalRect.X = startPos;
finalRect.Width = gripSize;
}
_grip.Arrange(!_hideSpliterGrip ? finalRect : _emptyRect);
// view2
if (isHorizontal) {
finalRect.Y += gripSize;
finalRect.Height = primaryViewSize;
} else {
finalRect.X += gripSize;
finalRect.Width = primaryViewSize;
}
if (primaryView != null)
primaryView.Arrange(finalRect);
}
if (_isPrimaryViewCollapsing) {
// SecondaryView
if (isHorizontal)
finalRect.Height = secondaryViewSize;
else
finalRect.Width = secondaryViewSize;
if (secondaryView != null)
secondaryView.Arrange(finalRect);
// Grip
if (isHorizontal) {
finalRect.Y += secondaryViewSize;
finalRect.Height = gripSize;
} else {
finalRect.X += secondaryViewSize;
finalRect.Width = gripSize;
}
_grip.Arrange(!_hideSpliterGrip ? finalRect : _emptyRect);
// PrimaryView
if (primaryView != null)
primaryView.Arrange(_emptyRect);
}
} else {
// SecondaryView
if (isHorizontal)
finalRect.Height = secondaryViewSize;
else
finalRect.Width = secondaryViewSize;
if (secondaryView != null)
secondaryView.Arrange(finalRect);
// grip
if (isHorizontal) {
finalRect.Y += secondaryViewSize;
finalRect.Height = gripSize;
} else {
finalRect.X += secondaryViewSize;
finalRect.Width = gripSize;
}
_grip.Arrange(finalRect);
// PrimaryView
if (isHorizontal) {
finalRect.Y += gripSize;
finalRect.Height = primaryViewSize;
} else {
finalRect.X += gripSize;
finalRect.Width = primaryViewSize;
}
if (primaryView != null)
primaryView.Arrange(finalRect);
}
return finalSize;
}
#endregion
#region "Methods"
private void InitSplitterHandle()
{
_grip = new SpliterGrip {
Orientation = this.Orientation
};
_grip.DragStarted += OnDragStarted;
_grip.DragDelta += OnGripDragDelta;
_grip.DragCompleted += OnDragCompleted;
}
private void OnIsSplitChanged(bool newValue)
{
if (!newValue) {
var args = RaiseRequestSecondaryViewEvent();
var container = args.Container as UIElement;
if (container == null)
return;
SecondaryView = container;
} else {
var secondaryView = this.SecondaryView;
if (secondaryView == null)
return;
SecondaryView = null; // will cause it to be removed from the logical/visual trees.
RaiseDisposeSecondaryViewEvent(secondaryView);
}
}
private void OnDragStarted(object sender, DragStartedEventArgs e)
{
OnDragStarted();
}
private void OnDragStarted()
{
_hideSpliterGrip = false;
_isGripDragging = true;
IsSplit = false;
}
private void LoadInInitialLayout()
{
ComputeOffset(0);
IsSplit = InternalIsSplit;
}
private void OnDragCompleted(object sender, DragCompletedEventArgs e)
{
OnDragCompleted();
}
/// <summary>
/// Common method between split container grip, and editor grip
/// </summary>
private void OnDragCompleted()
{
_isGripDragging = false;
if (!_isSecondaryViewCollapsing && !_isPrimaryViewCollapsing) {
// we need to check if we are close to be collapsed, we snap one of them.
if (CanCollapseSecondaryView) {
_isSecondaryViewCollapsing = true;
InternalIsSplit = true;
} else if (CanCollapsePrimaryView) {
_isPrimaryViewCollapsing = true;
InternalIsSplit = true;
} else {
IsSplit = false;
return;
}
}
_hideSpliterGrip = InternalIsSplit;
// a final layout pass is to be made, in order to ensure
// that the active view has been measure/arrange against the available
// space.
if (InternalIsSplit) {
if (_isPrimaryViewCollapsing)
SwapViews();
// reset the offset
_gripOffset = -(6 * Density);
_isSecondaryViewCollapsing = true;
_isPrimaryViewCollapsing = false;
InvalidateMeasure();
InvalidateArrange();
}
IsSplit = InternalIsSplit;
}
private void OnGripDragDelta(object sender, DragDeltaEventArgs e) {
bool isHorizontal = Orientation == Orientation.Horizontal;
double change = isHorizontal ? e.VerticalChange : e.HorizontalChange;
ComputeOffset(change);
e.Handled = true;
}
protected void OnEditorGripDragDelta(double change) {
ComputeOffset(change);
}
private void ComputeOffset(double change) {
//double offset = double.IsNaN(_gripOffset) ? 50 : _gripOffset;
double offset = _gripOffset;
offset += Density * change;
CoerceOffset(ref offset);
_gripOffset = offset;
InvalidateMeasure();
InvalidateArrange();
}
private void CoerceOffset(ref double offset)
{
_isPrimaryViewCollapsing = _isSecondaryViewCollapsing = false;
bool isCollapsed = false;
double min = 0;
double max = 100;
var gripOffset = Density * 6;
min -= gripOffset;
max += gripOffset;
if (offset < min) {
offset = min;
} else if (offset > max) {
offset = max;
}
if (offset <= 0) {
isCollapsed = true;
_isSecondaryViewCollapsing = true;
_isPrimaryViewCollapsing = false;
} else if (offset >= 100) {
isCollapsed = true;
_isSecondaryViewCollapsing = false;
_isPrimaryViewCollapsing = true;
}
InternalIsSplit = isCollapsed;
}
private void UpdateView(UIElement oldView, UIElement newView)
{
if (oldView == newView)
return;
if (oldView != null)
_visualChildren.Remove(oldView);
if (newView != null)
_visualChildren.Add(newView);
InvalidateMeasure();
InvalidateArrange();
}
private void ComputePartsSizes(Size arrangeSize,
bool isHorizontal,
out double secondaryViewSize,
out double primaryViewSize,
out double handleSize,
out double startPos)
{
double offset = double.IsNaN(_gripOffset) ? 50 : _gripOffset;
startPos = 0;
// ensure proper sizes are selected.
double length;
if (isHorizontal) {
length = arrangeSize.Height;
handleSize = _grip.DesiredSize.Height;
} else {
length = arrangeSize.Width;
handleSize = _grip.DesiredSize.Width;
}
// compute density;
double remainingLength;
if (InternalIsSplit && !_isGripDragging) {
// only a single view is rendered, PrimaryView
remainingLength = length;
secondaryViewSize = 0;
primaryViewSize = remainingLength;
startPos = -handleSize;
// ensure that grip offset is correctly set.
var density = 100 / remainingLength;
_gripOffset = -(density * handleSize);
} else {
remainingLength = length - handleSize;
if (offset >= 0 && offset <= 100) {
secondaryViewSize = remainingLength * (offset / 100);
primaryViewSize = remainingLength - secondaryViewSize;
} else if (offset < 0) {
double handleVisiblePart = Math.Max(0.0, handleSize - (Math.Abs(offset) / 100) * remainingLength);
startPos = (handleSize - handleVisiblePart) * -1;
secondaryViewSize = primaryViewSize = length - handleVisiblePart;
} else { //offset > 100
double handleVisiblePart = Math.Max(0.0, handleSize - ((offset - 100) / 100) * remainingLength);
primaryViewSize = secondaryViewSize = length - handleVisiblePart;
}
}
Density = 100 / remainingLength;
}
private void SwapViews()
{
var temp = _secondaryViewContainer;
_secondaryViewContainer = _primaryViewContainer;
_primaryViewContainer = temp;
}
#endregion
}
public class RequestSecondaryViewEventArgs : RoutedEventArgs
{
public object Container { get; set; }
}
public delegate void RequestSecondaryViewEventHandler(object sender, RequestSecondaryViewEventArgs e);
public class DisposeSecondaryViewEventArgs : RoutedEventArgs
{
public object Container { get; set; }
}
public delegate void DisposeSecondaryViewEventHandler(object sender, DisposeSecondaryViewEventArgs e);
internal static class BooleanBoxes
{
public static object True = true;
public static object False = false;
public static object Box(bool value)
{
return value ? True : False;
}
}
}

52
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/EditorSplitContainerCommands.cs

@ -0,0 +1,52 @@
/*
* Created by SharpDevelop.
* User: Abdelkarim
* Date: 9/22/2014
* Time: 8:07 AM
*
*/
using System;
using System.Collections;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
namespace ICSharpCode.AvalonEdit.AddIn
{
public static class EditorSplitContainerCommands
{
private static RoutedUICommand _splitEditorCommand;
private static RoutedUICommand _removeSplitCommand;
/// <summary>
///
/// </summary>
public static RoutedUICommand SplitEditorCommand {
get {
if (_splitEditorCommand == null)
_splitEditorCommand = new RoutedUICommand("Split", "SplitEditor", typeof(EditorSplitContainerCommands));
return _splitEditorCommand;
}
}
/// <summary>
///
/// </summary>
public static RoutedUICommand RemoveSplitCommand {
get {
if (_removeSplitCommand == null) {
_removeSplitCommand = new RoutedUICommand("Remove Split", "RemoveSplitEditor", typeof(EditorSplitContainerCommands));
}
return _removeSplitCommand;
}
}
}
}

58
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SpliterGrip.cs

@ -0,0 +1,58 @@
/*
* Created by SharpDevelop.
* User: Abdelkarim
* Date: 9/22/2014
* Time: 8:07 AM
*
*/
using System;
using System.Collections;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
namespace ICSharpCode.AvalonEdit.AddIn
{
public class SpliterGrip : Thumb
{
#region "Constructors"
/// <summary>
/// initializes static members of the <see cref="SpliterGrip"/> class.
/// </summary>
static SpliterGrip()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(SpliterGrip), new FrameworkPropertyMetadata(typeof(SpliterGrip)));
}
#endregion
#region "Properties"
#region Orientation
/// <summary>
/// Orientation Read-Only Dependency Property
/// </summary>
private static readonly DependencyPropertyKey OrientationPropertyKey = DependencyProperty.RegisterReadOnly("Orientation", typeof(Orientation), typeof(SpliterGrip), new FrameworkPropertyMetadata(Orientation.Horizontal));
public static readonly DependencyProperty OrientationProperty = OrientationPropertyKey.DependencyProperty;
/// <summary>
/// Gets the Orientation property. This dependency property
/// indicates ....
/// </summary>
public Orientation Orientation {
get {
return (Orientation)GetValue(OrientationProperty);
}
internal set {
SetValue(OrientationPropertyKey, value);
}
}
#endregion
#endregion
}
}

28
src/AddIns/DisplayBindings/AvalonEdit.AddIn/themes/SpliterGrip.xaml

@ -0,0 +1,28 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:sd="clr-namespace:ICSharpCode.AvalonEdit.AddIn"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="{x:Type sd:SpliterGrip}" TargetType="{x:Type sd:SpliterGrip}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="sd:SpliterGrip">
<Border x:Name="bg"
SnapsToDevicePixels="True"
Background="#CCCEDB" />
<ControlTemplate.Triggers>
<Trigger Property="Orientation" Value="Vertical">
<Setter TargetName="bg" Property="Width" Value="6" />
<Setter Property="Cursor" Value="SizeWE" />
</Trigger>
<Trigger Property="Orientation" Value="Horizontal">
<Setter TargetName="bg" Property="Height" Value="6" />
<Setter Property="Cursor" Value="SizeNS" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

92
src/AddIns/DisplayBindings/AvalonEdit.AddIn/themes/generic.xaml

@ -3,8 +3,95 @@
xmlns:ae="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns:ae="http://icsharpcode.net/sharpdevelop/avalonedit"
xmlns:local="clr-namespace:ICSharpCode.AvalonEdit.AddIn" xmlns:local="clr-namespace:ICSharpCode.AvalonEdit.AddIn"
xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets"
xmlns:core="http://icsharpcode.net/sharpdevelop/core" xmlns:core="http://icsharpcode.net/sharpdevelop/core">
>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/ICSharpCode.AvalonEdit.AddIn;component/themes/SpliterGrip.xaml" />
</ResourceDictionary.MergedDictionaries>
<Geometry x:Key="EditorSplitterGripShape">
M 0,5 L0,6 L11,6 L11,5 L6,5 L6,3 L8,3 L8,2 L7,2 L7,1 L6,1 L6,0 L5,0 L5,1 L4,1 L4,2 L3,2 L3,3 L5,3 L5,5 Z
M 0,8 L0,7 L11,7 L11,8 L6,8 L6,10 L8,10 L8,11 L7,11 L7,12 L6,12 L6,13 L5,13 L5,12 L4,12 L4,11 L3,11 L3,10 L5,10 L5,8 Z
</Geometry>
<Style x:Key="DragThumb" TargetType="Thumb">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Thumb">
<Border x:Name="bg" Padding="3" Background="Transparent">
<Path Fill="{TemplateBinding Foreground}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
SnapsToDevicePixels="True"
Data="{StaticResource EditorSplitterGripShape}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bg" Property="Background" Value="#C9DEF5" />
</Trigger>
<Trigger Property="IsDragging" Value="True">
<Setter Property="Foreground" Value="White" />
<Setter TargetName="bg" Property="Background" Value="#007ACC" />
</Trigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:EditorSplitContainer}, Path=IsSplit}" Value="False" />
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsDragging}" Value="False" />
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Collapsed" />
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ZoomScrollViewer" TargetType="{x:Type widgets:ZoomScrollViewer}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type widgets:ZoomScrollViewer}">
<Grid Background="{TemplateBinding Panel.Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<widgets:SelfCollapsingPanel Grid.Column="0" Grid.Row="1" CollapseOrientation="Horizontal" CanCollapse="{Binding Path=ComputedZoomButtonCollapsed, Mode=OneWay, RelativeSource={RelativeSource Mode=TemplatedParent}}">
<widgets:ZoomButtons x:Name="zoomButtons" Value="{Binding Path=CurrentZoom, RelativeSource={RelativeSource Mode=TemplatedParent}}" Minimum="{TemplateBinding MinimumZoom}" Maximum="{TemplateBinding MaximumZoom}" />
</widgets:SelfCollapsingPanel>
<Rectangle Grid.Column="2" Grid.Row="1" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
<ScrollContentPresenter Name="PART_Presenter" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Margin="{TemplateBinding Control.Padding}" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" CanContentScroll="{TemplateBinding ScrollViewer.CanContentScroll}">
<ScrollContentPresenter.LayoutTransform>
<ScaleTransform ScaleX="{Binding Path=CurrentZoom, RelativeSource={RelativeSource Mode=TemplatedParent}}" ScaleY="{Binding Path=CurrentZoom, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
</ScrollContentPresenter.LayoutTransform>
</ScrollContentPresenter>
<Grid Grid.Column="2" Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Thumb Grid.Row="0"
x:Name="PART_EditorGrip"
Style="{StaticResource DragThumb}"/>
<ScrollBar Name="PART_VerticalScrollBar"
Grid.Row="1"
Minimum="0" Maximum="{TemplateBinding ScrollableHeight}" ViewportSize="{TemplateBinding ViewportHeight}" Value="{TemplateBinding VerticalOffset}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
</Grid>
<ScrollBar Name="PART_HorizontalScrollBar" Orientation="Horizontal" Grid.Column="1" Grid.Row="1" Minimum="0" Maximum="{TemplateBinding ScrollableWidth}" ViewportSize="{TemplateBinding ViewportWidth}" Value="{TemplateBinding HorizontalOffset}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:SharpDevelopTextEditor}"> <Style TargetType="{x:Type local:SharpDevelopTextEditor}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" /> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" /> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
@ -14,6 +101,7 @@
<widgets:ZoomScrollViewer <widgets:ZoomScrollViewer
Focusable="False" Focusable="False"
Name="PART_ScrollViewer" Name="PART_ScrollViewer"
Style="{StaticResource ZoomScrollViewer}"
MouseWheelZoom="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Options.MouseWheelZoom}" MouseWheelZoom="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Options.MouseWheelZoom}"
CanContentScroll="True" CanContentScroll="True"
VerticalScrollBarVisibility="{TemplateBinding VerticalScrollBarVisibility}" VerticalScrollBarVisibility="{TemplateBinding VerticalScrollBarVisibility}"

Loading…
Cancel
Save