From bb0efc503a9b91ea5acb0e297ebed61b58846f66 Mon Sep 17 00:00:00 2001 From: jkuehner Date: Fri, 26 Dec 2014 19:34:54 +0100 Subject: [PATCH 01/10] Fix Middle Snaplines were not correct! --- .../Project/Extensions/SnaplinePlacementBehavior.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs index d2d187561e..3c94a2577c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs @@ -264,8 +264,8 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions if (filter == null) { - h.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Top + Math.Abs((r2.Top - r2.Bottom) / 2), Start = r.Left, End = r.Right }); - v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left + Math.Abs((r2.Left - r2.Right) / 2), Start = r.Top, End = r.Bottom }); + h.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Top + Math.Abs((r2.Top - r2.Bottom) / 2)-1, Start = r.Left, End = r.Right }); + v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left + Math.Abs((r2.Left - r2.Right) / 2)-1, Start = r.Top, End = r.Bottom }); } } } From ebbe00a10c4416327aa3b401b0c340312ab80eb1 Mon Sep 17 00:00:00 2001 From: jkuehner Date: Sat, 27 Dec 2014 11:30:45 +0100 Subject: [PATCH 02/10] Fix in Snapline - Middle Position is now drawn 1px aside --- .../Project/Extensions/SnaplinePlacementBehavior.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs index 3c94a2577c..11c142a186 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs @@ -140,7 +140,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } foreach (var d in drawLines) { - DrawLine(d.Start, d.Offset, d.End, d.Offset); + DrawLine(d.Start, d.Offset + d.DrawOffset, d.End, d.Offset + d.DrawOffset); } } @@ -163,7 +163,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } foreach (var d in drawLines) { - DrawLine(d.Offset, d.Start, d.Offset, d.End); + DrawLine(d.Offset + d.DrawOffset, d.Start, d.Offset + d.DrawOffset, d.End); } } } @@ -264,8 +264,8 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions if (filter == null) { - h.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Top + Math.Abs((r2.Top - r2.Bottom) / 2)-1, Start = r.Left, End = r.Right }); - v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left + Math.Abs((r2.Left - r2.Right) / 2)-1, Start = r.Top, End = r.Bottom }); + h.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Top + Math.Abs((r2.Top - r2.Bottom) / 2) - 1, DrawOffset = 1, Start = r.Left, End = r.Right }); + v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left + Math.Abs((r2.Left - r2.Right) / 2) - 1, DrawOffset = 1, Start = r.Top, End = r.Bottom }); } } } @@ -365,6 +365,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions drawLine = new Snapline(); drawLine.Start = double.MaxValue; drawLine.End = double.MinValue; + drawLine.DrawOffset = mapLine.DrawOffset; offsetDict[offset] = drawLine; } drawLine.Offset = offset; @@ -386,6 +387,8 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions public double End; public bool RequireOverlap; public int Group; + + public double DrawOffset = 0; } } } From 6ca3555dc74a45424d7f8781e58c3b27e849a6bf Mon Sep 17 00:00:00 2001 From: jkuehner Date: Sat, 27 Dec 2014 11:32:01 +0100 Subject: [PATCH 03/10] Code fixes in Line/Polyline Extensions --- .../Project/Extensions/LineExtensionBase.cs | 350 +++---- .../Extensions/LineHandlerExtension.cs | 457 +++++----- .../Extensions/PolyLineHandlerExtension.cs | 859 +++++++++--------- .../Extensions/ResizeThumbExtension.cs | 11 +- 4 files changed, 843 insertions(+), 834 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineExtensionBase.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineExtensionBase.cs index 9cd0d22d6b..e4d29574c5 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineExtensionBase.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineExtensionBase.cs @@ -1,11 +1,21 @@ -/* - * Created by SharpDevelop. - * User: trubra - * Date: 2014-12-22 - * Time: 11:00 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ +// 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 ICSharpCode.WpfDesign.Designer.Controls; using ICSharpCode.WpfDesign.Designer.Extensions; @@ -25,166 +35,166 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions /// Description of LineExtensionBase. /// class Bounds - { - public double X, Y, Left, Top; - } - /// - /// base class for the Line, Polyline and Polygon extension classes - /// - public class LineExtensionBase : SelectionAdornerProvider - { - - - internal AdornerPanel adornerPanel; - internal IEnumerable resizeThumbs; - - /// An array containing this.ExtendedItem as only element - internal readonly DesignItem[] extendedItemArray = new DesignItem[1]; - - internal IPlacementBehavior resizeBehavior; - internal PlacementOperation operation; - internal ChangeGroup changeGroup; - private Canvas _surface; - internal bool _isResizing; - private TextBlock _text; - //private DesignPanel designPanel; - - /// - /// Gets whether this extension is resizing any element. - /// - public bool IsResizing - { - get { return _isResizing; } - } - - /// - /// on creation add adornerlayer - /// - public LineExtensionBase() - { - _surface = new Canvas(); - adornerPanel = new AdornerPanel(); - adornerPanel.Order = AdornerOrder.Foreground; - adornerPanel.Children.Add(_surface); - Adorners.Add(adornerPanel); - } - - #region eventhandlers - - - protected void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) - { - UpdateAdornerVisibility(); - } - - protected override void OnRemove() - { - this.ExtendedItem.PropertyChanged -= OnPropertyChanged; - this.Services.Selection.PrimarySelectionChanged -= OnPrimarySelectionChanged; - DependencyPropertyDescriptor.FromProperty(FrameworkElement.HeightProperty, typeof (Shape)) - .RemoveValueChanged(ExtendedItem.View, (s, ev) => ResetWidthHeightProperties()); - base.OnRemove(); - } - - protected void OnPrimarySelectionChanged(object sender, EventArgs e) - { - bool isPrimarySelection = this.Services.Selection.PrimarySelection == this.ExtendedItem; - if (isPrimarySelection) - DependencyPropertyDescriptor.FromProperty(FrameworkElement.HeightProperty, typeof (Shape)) - .AddValueChanged(ExtendedItem.View, (s, ev) => ResetWidthHeightProperties()); - //foreach (ResizeThumb g in adornerPanel.Children) - //{ - // g.IsPrimarySelection = isPrimarySelection; - //} - } - - #endregion - - protected void UpdateAdornerVisibility() - { - FrameworkElement fe = this.ExtendedItem.View as FrameworkElement; - foreach (ResizeThumb r in resizeThumbs) - { - bool isVisible = resizeBehavior != null && - resizeBehavior.CanPlace(extendedItemArray, PlacementType.Resize, r.Alignment); - r.Visibility = isVisible ? Visibility.Visible : Visibility.Hidden; - } - } - - /// - /// Places resize thumbs at their respective positions - /// and streches out thumbs which are at the center of outline to extend resizability across the whole outline - /// - /// - /// - /// if using a polygon or multipoint adorner this is the index of the point in the Points array - /// - protected PointTrackerPlacementSupport Place(ref ResizeThumb resizeThumb, PlacementAlignment alignment, int index = -1) - { - PointTrackerPlacementSupport placement = new PointTrackerPlacementSupport(ExtendedItem.View as Shape, alignment, index); - return placement; - } - - /// - /// forces redraw of shape - /// - protected void Invalidate() - { - Shape s = ExtendedItem.View as Shape; - if (s != null) - { - s.InvalidateVisual(); - s.BringIntoView(); - } - } - - protected void SetSurfaceInfo(int x, int y, string s) - { - if (_text == null) - { - _text = new TextBlock(); - _surface.Children.Add(_text); - } - AdornerPanel ap = _surface.Parent as AdornerPanel; - - _surface.Width = ap.Width; - _surface.Height = ap.Height; - - _text.Text = s; - Canvas.SetLeft(_text, x); - Canvas.SetTop(_text, y); - - } - - protected void HideSizeAndShowHandles() - { - SizeDisplayExtension sizeDisplay = null; - MarginHandleExtension marginDisplay = null; - foreach (var extension in ExtendedItem.Extensions) - { - if (extension is SizeDisplayExtension) - sizeDisplay = extension as SizeDisplayExtension; - if (extension is MarginHandleExtension) - marginDisplay = extension as MarginHandleExtension; - } - - if (sizeDisplay != null) - { - sizeDisplay.HeightDisplay.Visibility = Visibility.Hidden; - sizeDisplay.WidthDisplay.Visibility = Visibility.Hidden; - } - if (marginDisplay != null) - { - marginDisplay.ShowHandles(); - } - } - - protected void ResetWidthHeightProperties() - { - ExtendedItem.Properties.GetProperty(FrameworkElement.HeightProperty).Reset(); - ExtendedItem.Properties.GetProperty(FrameworkElement.WidthProperty).Reset(); - } - - - } + { + public double X, Y, Left, Top; + } + /// + /// base class for the Line, Polyline and Polygon extension classes + /// + public class LineExtensionBase : SelectionAdornerProvider + { + + + internal AdornerPanel adornerPanel; + internal IEnumerable resizeThumbs; + + /// An array containing this.ExtendedItem as only element + internal readonly DesignItem[] extendedItemArray = new DesignItem[1]; + + internal IPlacementBehavior resizeBehavior; + internal PlacementOperation operation; + internal ChangeGroup changeGroup; + private Canvas _surface; + internal bool _isResizing; + private TextBlock _text; + //private DesignPanel designPanel; + + /// + /// Gets whether this extension is resizing any element. + /// + public bool IsResizing + { + get { return _isResizing; } + } + + /// + /// on creation add adornerlayer + /// + public LineExtensionBase() + { + _surface = new Canvas(); + adornerPanel = new AdornerPanel(); + adornerPanel.Order = AdornerOrder.Foreground; + adornerPanel.Children.Add(_surface); + Adorners.Add(adornerPanel); + } + + #region eventhandlers + + + protected void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + UpdateAdornerVisibility(); + } + + protected override void OnRemove() + { + this.ExtendedItem.PropertyChanged -= OnPropertyChanged; + this.Services.Selection.PrimarySelectionChanged -= OnPrimarySelectionChanged; + DependencyPropertyDescriptor.FromProperty(FrameworkElement.HeightProperty, typeof (Shape)) + .RemoveValueChanged(ExtendedItem.View, (s, ev) => ResetWidthHeightProperties()); + base.OnRemove(); + } + + protected void OnPrimarySelectionChanged(object sender, EventArgs e) + { + bool isPrimarySelection = this.Services.Selection.PrimarySelection == this.ExtendedItem; + if (isPrimarySelection) + DependencyPropertyDescriptor.FromProperty(FrameworkElement.HeightProperty, typeof (Shape)) + .AddValueChanged(ExtendedItem.View, (s, ev) => ResetWidthHeightProperties()); + //foreach (ResizeThumb g in adornerPanel.Children) + //{ + // g.IsPrimarySelection = isPrimarySelection; + //} + } + + #endregion + + protected void UpdateAdornerVisibility() + { + FrameworkElement fe = this.ExtendedItem.View as FrameworkElement; + foreach (ResizeThumb r in resizeThumbs) + { + bool isVisible = resizeBehavior != null && + resizeBehavior.CanPlace(extendedItemArray, PlacementType.Resize, r.Alignment); + r.Visibility = isVisible ? Visibility.Visible : Visibility.Hidden; + } + } + + /// + /// Places resize thumbs at their respective positions + /// and streches out thumbs which are at the center of outline to extend resizability across the whole outline + /// + /// + /// + /// if using a polygon or multipoint adorner this is the index of the point in the Points array + /// + protected PointTrackerPlacementSupport Place(ref ResizeThumb resizeThumb, PlacementAlignment alignment, int index = -1) + { + PointTrackerPlacementSupport placement = new PointTrackerPlacementSupport(ExtendedItem.View as Shape, alignment, index); + return placement; + } + + /// + /// forces redraw of shape + /// + protected void Invalidate() + { + Shape s = ExtendedItem.View as Shape; + if (s != null) + { + s.InvalidateVisual(); + s.BringIntoView(); + } + } + + protected void SetSurfaceInfo(int x, int y, string s) + { + if (_text == null) + { + _text = new TextBlock(); + _surface.Children.Add(_text); + } + AdornerPanel ap = _surface.Parent as AdornerPanel; + + _surface.Width = ap.Width; + _surface.Height = ap.Height; + + _text.Text = s; + Canvas.SetLeft(_text, x); + Canvas.SetTop(_text, y); + + } + + protected void HideSizeAndShowHandles() + { + SizeDisplayExtension sizeDisplay = null; + MarginHandleExtension marginDisplay = null; + foreach (var extension in ExtendedItem.Extensions) + { + if (extension is SizeDisplayExtension) + sizeDisplay = extension as SizeDisplayExtension; + if (extension is MarginHandleExtension) + marginDisplay = extension as MarginHandleExtension; + } + + if (sizeDisplay != null) + { + sizeDisplay.HeightDisplay.Visibility = Visibility.Hidden; + sizeDisplay.WidthDisplay.Visibility = Visibility.Hidden; + } + if (marginDisplay != null) + { + marginDisplay.ShowHandles(); + } + } + + protected void ResetWidthHeightProperties() + { + ExtendedItem.Properties.GetProperty(FrameworkElement.HeightProperty).Reset(); + ExtendedItem.Properties.GetProperty(FrameworkElement.WidthProperty).Reset(); + } + + + } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineHandlerExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineHandlerExtension.cs index 6d011171f0..2d74352e00 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineHandlerExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineHandlerExtension.cs @@ -1,11 +1,21 @@ -/* - * Created by SharpDevelop. - * User: trubra - * Date: 2014-12-22 - * Time: 10:34 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ +// 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 ICSharpCode.WpfDesign.Extensions; using ICSharpCode.WpfDesign; @@ -21,228 +31,221 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using ICSharpCode.WpfDesign.Designer.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Extensions { /// /// Description of LineHandlerExtension. /// - [ExtensionFor(typeof(Line), OverrideExtensions = new Type[] { typeof(ResizeThumbExtension), typeof(SelectedElementRectangleExtension), typeof(CanvasPositionExtension), typeof(QuickOperationMenuExtension), typeof(RotateThumbExtension), typeof(RenderTransformOriginExtension), typeof(InPlaceEditorExtension) })] - internal class LineHandlerExtension : LineExtensionBase - { - // - private double CurrentX2; - private double CurrentY2; - private double CurrentLeft; - private double CurrentTop; - - //Size oldSize; - ZoomControl zoom; - - protected ResizeThumb CreateThumb(PlacementAlignment alignment, Cursor cursor) - { - ResizeThumb resizeThumb = new ResizeThumb { Alignment = alignment, Cursor = cursor, IsPrimarySelection = true}; - AdornerPanel.SetPlacement(resizeThumb, Place(ref resizeThumb, alignment)); - - adornerPanel.Children.Add(resizeThumb); - - DragListener drag = new DragListener(resizeThumb); - drag.Started += drag_Started; - drag.Changed += drag_Changed; - drag.Completed += drag_Completed; - return resizeThumb; - } - - protected Bounds CalculateDrawing(double x, double y, double left, double top, double xleft, double xtop) - { - - Double theta = (180 / Math.PI) * Math.Atan2(y, x); - double verticaloffset = Math.Abs(90 - Math.Abs(theta)); - if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) - { - if (Math.Abs(theta) < 45 || Math.Abs(theta) > 135) - { - y = 0; - top = xtop; - } - else if (verticaloffset < 45) - { - x = 0; - left = xleft; - } - } - else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) - { - if (verticaloffset < 10) - { - x = 0; - left = xleft; - } - else if (Math.Abs(theta) < 10 || Math.Abs(theta) > 170) - { - y = 0; - top = xtop; - } - } - - SetSurfaceInfo(0, 0, Math.Round((180 / Math.PI) * Math.Atan2(y, x), 0).ToString()); - return new Bounds { X = Math.Round(x, 1), Y = Math.Round(y, 1), Left = Math.Round(left, 1), Top = Math.Round(top, 1) }; - } - - #region eventhandlers - - - // TODO : Remove all hide/show extensions from here. - protected virtual void drag_Started(DragListener drag) - { - Line al = ExtendedItem.View as Line; - CurrentX2 = al.X2; - CurrentY2 = al.Y2; - CurrentLeft = (double)al.GetValue(Canvas.LeftProperty); - CurrentTop = (double)al.GetValue(Canvas.TopProperty); - - var designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; - if (designPanel != null) - { - var p = VisualTreeHelper.GetParent(designPanel); - while (p != null && !(p is ZoomControl)) - { - p = VisualTreeHelper.GetParent(p); - } - zoom = p as ZoomControl; - } - - if (resizeBehavior != null) - operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); - else - { - changeGroup = this.ExtendedItem.Context.OpenGroup("Resize", extendedItemArray); - } - _isResizing = true; - - (drag.Target as ResizeThumb).IsPrimarySelection = false; - } - - protected virtual void drag_Changed(DragListener drag) - { - Line al = ExtendedItem.View as Line; - - var alignment = (drag.Target as ResizeThumb).Alignment; - var info = operation.PlacedItems[0]; - double dx = 0; - double dy = 0; - - if (zoom != null) - { - dx = drag.Delta.X * (1 / zoom.CurrentZoom); - dy = drag.Delta.Y * (1 / zoom.CurrentZoom); - } - double top, left, x, y, xtop, xleft; - - - if (alignment == PlacementAlignment.TopLeft) - { - //normal values - x = CurrentX2 - dx; - y = CurrentY2 - dy; - top = CurrentTop + dy; - left = CurrentLeft + dx; - - //values to use when keys are pressed - xtop = CurrentTop + CurrentY2; - xleft = CurrentLeft + CurrentX2; - - } - else - { - x = CurrentX2 + dx; - y = CurrentY2 + dy; - top = xtop = CurrentTop; - left = xleft = CurrentLeft; - } - Bounds position = CalculateDrawing(x, y, left, top, xleft, xtop); - - ExtendedItem.Properties.GetProperty(Line.X1Property).SetValue(0); - ExtendedItem.Properties.GetProperty(Line.Y1Property).SetValue(0); - ExtendedItem.Properties.GetProperty(Line.X2Property).SetValue(position.X); - ExtendedItem.Properties.GetProperty(Line.Y2Property).SetValue(position.Y); - - if (operation != null) - { - var result = info.OriginalBounds; - result.X = position.Left; - result.Y = position.Top; - result.Width = Math.Abs(position.X); - result.Height = Math.Abs(position.Y); - - info.Bounds = result.Round(); - operation.CurrentContainerBehavior.BeforeSetPosition(operation); - operation.CurrentContainerBehavior.SetPosition(info); - } - (drag.Target as ResizeThumb).InvalidateArrange(); - ResetWidthHeightProperties(); - } - - protected virtual void drag_Completed(DragListener drag) - { - if (operation != null) - { - if (drag.IsCanceled) operation.Abort(); - else - { - ResetWidthHeightProperties(); - - operation.Commit(); - } - operation = null; - } - else - { - if (drag.IsCanceled) changeGroup.Abort(); - else changeGroup.Commit(); - changeGroup = null; - } - - _isResizing = false; - (drag.Target as ResizeThumb).IsPrimarySelection = true; - HideSizeAndShowHandles(); - } - - /// - /// is invoked whenever a line is selected on the canvas, remember that the adorners are created for each line object and never destroyed - /// - protected override void OnInitialized() - { - base.OnInitialized(); - if (ExtendedItem.Properties.GetProperty(Line.StrokeProperty).ValueOnInstance == null) - { - ExtendedItem.Properties[Shape.StrokeProperty].SetValue(Colors.Black); - ExtendedItem.Properties[Shape.StrokeThicknessProperty].SetValue(2d); - ExtendedItem.Properties[Shape.StretchProperty].SetValue(Stretch.None); - ExtendedItem.Properties.GetProperty(Line.X1Property).SetValue(0); - ExtendedItem.Properties.GetProperty(Line.Y1Property).SetValue(0); - ExtendedItem.Properties.GetProperty(Line.X2Property).SetValue(20); - ExtendedItem.Properties.GetProperty(Line.Y2Property).SetValue(20); - (ExtendedItem.View as Line).BringIntoView(); - } - - resizeThumbs = new ResizeThumb[] - { - CreateThumb(PlacementAlignment.TopLeft, Cursors.SizeNWSE), - CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE) - }; - - extendedItemArray[0] = this.ExtendedItem; - - Invalidate(); - //ResetWidthHeightProperties(); - - this.ExtendedItem.PropertyChanged += OnPropertyChanged; - this.Services.Selection.PrimarySelectionChanged += OnPrimarySelectionChanged; - resizeBehavior = PlacementOperation.GetPlacementBehavior(extendedItemArray); - UpdateAdornerVisibility(); - OnPrimarySelectionChanged(null, null); - } - - #endregion - } + [ExtensionFor(typeof(Line), OverrideExtensions = new Type[] { typeof(ResizeThumbExtension), typeof(SelectedElementRectangleExtension), typeof(CanvasPositionExtension), typeof(QuickOperationMenuExtension), typeof(RotateThumbExtension), typeof(RenderTransformOriginExtension), typeof(InPlaceEditorExtension), typeof(SkewThumbExtension) })] + internal class LineHandlerExtension : LineExtensionBase + { + // + private double CurrentX2; + private double CurrentY2; + private double CurrentLeft; + private double CurrentTop; + + //Size oldSize; + ZoomControl zoom; + + protected ResizeThumb CreateThumb(PlacementAlignment alignment, Cursor cursor) + { + ResizeThumb resizeThumb = new ResizeThumb { Alignment = alignment, Cursor = cursor, IsPrimarySelection = true}; + AdornerPanel.SetPlacement(resizeThumb, Place(ref resizeThumb, alignment)); + + adornerPanel.Children.Add(resizeThumb); + + DragListener drag = new DragListener(resizeThumb); + drag.Started += drag_Started; + drag.Changed += drag_Changed; + drag.Completed += drag_Completed; + return resizeThumb; + } + + protected Bounds CalculateDrawing(double x, double y, double left, double top, double xleft, double xtop) + { + + Double theta = (180 / Math.PI) * Math.Atan2(y, x); + double verticaloffset = Math.Abs(90 - Math.Abs(theta)); + if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) + { + if (Math.Abs(theta) < 45 || Math.Abs(theta) > 135) + { + y = 0; + top = xtop; + } + else if (verticaloffset < 45) + { + x = 0; + left = xleft; + } + } + else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) + { + if (verticaloffset < 10) + { + x = 0; + left = xleft; + } + else if (Math.Abs(theta) < 10 || Math.Abs(theta) > 170) + { + y = 0; + top = xtop; + } + } + + SetSurfaceInfo(0, 0, Math.Round((180 / Math.PI) * Math.Atan2(y, x), 0).ToString()); + return new Bounds { X = Math.Round(x, 1), Y = Math.Round(y, 1), Left = Math.Round(left, 1), Top = Math.Round(top, 1) }; + } + + #region eventhandlers + + + // TODO : Remove all hide/show extensions from here. + protected virtual void drag_Started(DragListener drag) + { + Line al = ExtendedItem.View as Line; + CurrentX2 = al.X2; + CurrentY2 = al.Y2; + CurrentLeft = (double)al.GetValue(Canvas.LeftProperty); + CurrentTop = (double)al.GetValue(Canvas.TopProperty); + + var designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; + zoom = designPanel.TryFindParent(); + + if (resizeBehavior != null) + operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); + else + { + changeGroup = this.ExtendedItem.Context.OpenGroup("Resize", extendedItemArray); + } + _isResizing = true; + + (drag.Target as ResizeThumb).IsPrimarySelection = false; + } + + protected virtual void drag_Changed(DragListener drag) + { + Line al = ExtendedItem.View as Line; + + var alignment = (drag.Target as ResizeThumb).Alignment; + var info = operation.PlacedItems[0]; + double dx = 0; + double dy = 0; + + if (zoom != null) + { + dx = drag.Delta.X * (1 / zoom.CurrentZoom); + dy = drag.Delta.Y * (1 / zoom.CurrentZoom); + } + double top, left, x, y, xtop, xleft; + + + if (alignment == PlacementAlignment.TopLeft) + { + //normal values + x = CurrentX2 - dx; + y = CurrentY2 - dy; + top = CurrentTop + dy; + left = CurrentLeft + dx; + + //values to use when keys are pressed + xtop = CurrentTop + CurrentY2; + xleft = CurrentLeft + CurrentX2; + + } + else + { + x = CurrentX2 + dx; + y = CurrentY2 + dy; + top = xtop = CurrentTop; + left = xleft = CurrentLeft; + } + Bounds position = CalculateDrawing(x, y, left, top, xleft, xtop); + + ExtendedItem.Properties.GetProperty(Line.X1Property).SetValue(0); + ExtendedItem.Properties.GetProperty(Line.Y1Property).SetValue(0); + ExtendedItem.Properties.GetProperty(Line.X2Property).SetValue(position.X); + ExtendedItem.Properties.GetProperty(Line.Y2Property).SetValue(position.Y); + + if (operation != null) + { + var result = info.OriginalBounds; + result.X = position.Left; + result.Y = position.Top; + result.Width = Math.Abs(position.X); + result.Height = Math.Abs(position.Y); + + info.Bounds = result.Round(); + operation.CurrentContainerBehavior.BeforeSetPosition(operation); + operation.CurrentContainerBehavior.SetPosition(info); + } + (drag.Target as ResizeThumb).InvalidateArrange(); + ResetWidthHeightProperties(); + } + + protected virtual void drag_Completed(DragListener drag) + { + if (operation != null) + { + if (drag.IsCanceled) operation.Abort(); + else + { + ResetWidthHeightProperties(); + + operation.Commit(); + } + operation = null; + } + else + { + if (drag.IsCanceled) changeGroup.Abort(); + else changeGroup.Commit(); + changeGroup = null; + } + + _isResizing = false; + (drag.Target as ResizeThumb).IsPrimarySelection = true; + HideSizeAndShowHandles(); + } + + /// + /// is invoked whenever a line is selected on the canvas, remember that the adorners are created for each line object and never destroyed + /// + protected override void OnInitialized() + { + base.OnInitialized(); + if (ExtendedItem.Properties.GetProperty(Line.StrokeProperty).ValueOnInstance == null) + { + ExtendedItem.Properties[Shape.StrokeProperty].SetValue(Colors.Black); + ExtendedItem.Properties[Shape.StrokeThicknessProperty].SetValue(2d); + ExtendedItem.Properties[Shape.StretchProperty].SetValue(Stretch.None); + ExtendedItem.Properties.GetProperty(Line.X1Property).SetValue(0); + ExtendedItem.Properties.GetProperty(Line.Y1Property).SetValue(0); + ExtendedItem.Properties.GetProperty(Line.X2Property).SetValue(20); + ExtendedItem.Properties.GetProperty(Line.Y2Property).SetValue(20); + (ExtendedItem.View as Line).BringIntoView(); + } + + resizeThumbs = new ResizeThumb[] + { + CreateThumb(PlacementAlignment.TopLeft, Cursors.SizeNWSE), + CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE) + }; + + extendedItemArray[0] = this.ExtendedItem; + + Invalidate(); + //ResetWidthHeightProperties(); + + this.ExtendedItem.PropertyChanged += OnPropertyChanged; + this.Services.Selection.PrimarySelectionChanged += OnPrimarySelectionChanged; + resizeBehavior = PlacementOperation.GetPlacementBehavior(extendedItemArray); + UpdateAdornerVisibility(); + OnPrimarySelectionChanged(null, null); + } + + #endregion + } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PolyLineHandlerExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PolyLineHandlerExtension.cs index 76ca6cac45..c9a88c0423 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PolyLineHandlerExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PolyLineHandlerExtension.cs @@ -1,11 +1,21 @@ -/* - * Created by SharpDevelop. - * User: trubra - * Date: 2014-12-22 - * Time: 10:34 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ +// 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 ICSharpCode.WpfDesign.Extensions; using ICSharpCode.WpfDesign; @@ -21,430 +31,423 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using ICSharpCode.WpfDesign.Designer.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Extensions { /// /// Description of PolyLineHandlerExtension. /// - [ExtensionFor(typeof(Polyline), OverrideExtensions = new Type[] { typeof(ResizeThumbExtension), typeof(SelectedElementRectangleExtension), typeof(CanvasPositionExtension), typeof(QuickOperationMenuExtension), typeof(RotateThumbExtension), typeof(RenderTransformOriginExtension), typeof(InPlaceEditorExtension), typeof(SizeDisplayExtension) })] - internal class PolyLineHandlerExtension : LineExtensionBase, IKeyDown, IKeyUp - { - private readonly Dictionary _selectedThumbs = new Dictionary(); - private bool _isDragging; - ZoomControl _zoom; - - #region thumb methods - protected ResizeThumb CreateThumb(PlacementAlignment alignment, Cursor cursor, int index) - { - ResizeThumb resizeThumb = new MultiPointResizeThumb { Index = index, Alignment = alignment, Cursor = cursor, IsPrimarySelection = true }; - AdornerPlacement ap = Place(ref resizeThumb, alignment, index); - (resizeThumb as MultiPointResizeThumb).AdornerPlacement = ap; - - AdornerPanel.SetPlacement(resizeThumb, ap); - adornerPanel.Children.Add(resizeThumb); - - DragListener drag = new DragListener(resizeThumb); - - WeakEventManager.AddHandler(resizeThumb, "PreviewMouseLeftButtonDown", ResizeThumbOnMouseLeftButtonUp); - - drag.Started += drag_Started; - drag.Changed += drag_Changed; - drag.Completed += drag_Completed; - return resizeThumb; - } - - private void ResetThumbs() - { - foreach (FrameworkElement rt in adornerPanel.Children) - { - if (rt is ResizeThumb) - (rt as ResizeThumb).IsPrimarySelection = true; - } - _selectedThumbs.Clear(); - } - - private void SelectThumb(MultiPointResizeThumb mprt) - { - PointCollection points = GetPointCollection(); - Point p = points[mprt.Index]; - _selectedThumbs.Add(mprt.Index, new Bounds { X = p.X, Y = p.Y }); - - mprt.IsPrimarySelection = false; - } - - #endregion - - #region eventhandlers - - private void ResizeThumbOnMouseLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs) - { - //get current thumb - MultiPointResizeThumb mprt = sender as MultiPointResizeThumb; - if (mprt != null) - { - //shift+ctrl will remove selected point - if ((Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) && - (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))) - { - //unselect all points - ResetThumbs(); - PointCollection points = GetPointCollection(); - - //iterate thumbs to lower index of remaining thumbs - foreach (MultiPointResizeThumb m in adornerPanel.Children) - { - if (m.Index > mprt.Index) - m.Index--; - } - - //remove point and thumb - points.RemoveAt(mprt.Index); - adornerPanel.Children.Remove(mprt); - - Invalidate(); - } - else - { - //if not keyboard ctrl is pressed and selected point is not previously selected, clear selection - if (!_selectedThumbs.ContainsKey(mprt.Index) & !Keyboard.IsKeyDown(Key.LeftCtrl) & - !Keyboard.IsKeyDown(Key.RightCtrl)) - { - ResetThumbs(); - } - //add selected thumb, if ctrl pressed this could be all points in poly - if (!_selectedThumbs.ContainsKey(mprt.Index)) - SelectThumb(mprt); - _isDragging = false; - } - } - } - - // TODO : Remove all hide/show extensions from here. - protected void drag_Started(DragListener drag) - { - //get current thumb - MultiPointResizeThumb mprt = (drag.Target as MultiPointResizeThumb); - if (mprt != null) - { - SetOperation(); - } - } - - void SetOperation() - { - var designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; - if (designPanel != null) - { - var p = VisualTreeHelper.GetParent(designPanel); - while (p != null && !(p is ZoomControl)) - { - p = VisualTreeHelper.GetParent(p); - } - _zoom = p as ZoomControl; - } - - if (resizeBehavior != null) - operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); - else - { - changeGroup = ExtendedItem.Context.OpenGroup("Resize", extendedItemArray); - } - _isResizing = true; - } - - void ChangeOperation(PointCollection points) - { - //this is for SharpDevelop built in undo functionality - if (operation != null) - { - var info = operation.PlacedItems[0]; - var result = info.OriginalBounds; - - IEnumerable xs = points.Select(x => x.X); - IEnumerable ys = points.Select(y => y.Y); - result.X = (double)(info.Item.Properties.GetAttachedProperty(Canvas.LeftProperty).ValueOnInstance); - result.Y = (double)(info.Item.Properties.GetAttachedProperty(Canvas.TopProperty).ValueOnInstance); - result.Width = xs.Max() - xs.Min(); - result.Height = ys.Max() - ys.Min(); - - info.Bounds = result.Round(); - operation.CurrentContainerBehavior.BeforeSetPosition(operation); - operation.CurrentContainerBehavior.SetPosition(info); - } - - ResetWidthHeightProperties(); - - } - - void CommitOperation() - { - if (operation != null) - { - PointCollection points; - Polygon pg = ExtendedItem.View as Polygon; - Polyline pl = ExtendedItem.View as Polyline; - if (pl == null) - { - points = pg.Points; - - } - else - { - points = pl.Points; - } - - foreach (int i in _selectedThumbs.Keys) - { - _selectedThumbs[i].X = points[i].X; - _selectedThumbs[i].Y = points[i].Y; - } - ExtendedItem.Properties.GetProperty(pl != null ? Polyline.PointsProperty : Polygon.PointsProperty).SetValue(points); - ResetWidthHeightProperties(); - operation.Commit(); - - operation = null; - } - else - { - changeGroup.Commit(); - changeGroup = null; - } - _isResizing = false; - - ResetWidthHeightProperties(); - Invalidate(); - } - - protected void drag_Changed(DragListener drag) - { - PointCollection points = GetPointCollection(); - - MultiPointResizeThumb mprt = drag.Target as MultiPointResizeThumb; - if (mprt != null) - { - double dx = 0; - double dy = 0; - //if has zoomed - if (_zoom != null) - { - dx = drag.Delta.X * (1 / _zoom.CurrentZoom); - dy = drag.Delta.Y * (1 / _zoom.CurrentZoom); - } - - Double theta; - //if one point selected snapping angle is calculated in relation to previous point - if (_selectedThumbs.Count == 1) - { - theta = (180 / Math.PI) * Math.Atan2(_selectedThumbs[mprt.Index].Y + dy - points[mprt.Index - 1].Y, _selectedThumbs[mprt.Index].X + dx - points[mprt.Index - 1].X); - } - else//if multiple points snapping angle is calculated in relation to mouse dragging angle - { - theta = (180 / Math.PI) * Math.Atan2(dy, dx); - } - - //snappingAngle is used for snapping function to horizontal or vertical plane in line drawing, and is activated by pressing ctrl or shift button - int? snapAngle = null; - - //shift+alt gives a new point - if ((Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) && (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt))) - { - //if dragging occurs on a point and that point is the only selected, a new node will be added. - //_isCtrlDragging is needed since this method is called for every x pixel that the mouse moves - //so it could be many thousands of times during a single dragging - if (!_isDragging && _selectedThumbs.Count == 1 && (Math.Abs(dx) > 0 || Math.Abs(dy) > 0)) - { - - //duplicate point that is selected - Point p = points[mprt.Index]; - - //insert duplicate - points.Insert(mprt.Index, p); - - //create adorner marker - CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE, mprt.Index); - - //set index of all points that had a higher index than selected to +1 - foreach (FrameworkElement rt in adornerPanel.Children) - { - if (rt is MultiPointResizeThumb) - { - MultiPointResizeThumb t = rt as MultiPointResizeThumb; - if (t.Index > mprt.Index) - t.Index++; - } - } - - //set index of new point to old point index + 1 - mprt.Index = mprt.Index + 1; - ResetThumbs(); - SelectThumb(mprt); - - } - snapAngle = 10; - } - - //snapping occurs when mouse is within 10 degrees from horizontal or vertical plane if shift is pressed - else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) - { - snapAngle = 10; - } - //snapping occurs within 45 degree intervals that is line will always be horizontal or vertical if alt is pressed - else if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) - { - snapAngle = 45; - } - _isDragging = true; - points = MovePoints(points, dx, dy, theta, snapAngle); - - } - ChangeOperation(points); - (drag.Target as ResizeThumb).InvalidateArrange(); - - - } - - protected void drag_Completed(DragListener drag) - { - MultiPointResizeThumb mprt = drag.Target as MultiPointResizeThumb; - if (mprt != null) - { - if (operation != null && drag.IsCanceled) - { - operation.Abort(); - } - else if (drag.IsCanceled) - { - changeGroup.Abort(); - } - CommitOperation(); - } - } - - - - protected override void OnInitialized() - { - base.OnInitialized(); - - PointCollection points = GetPointCollection(); - - if (ExtendedItem.Properties[Shape.StrokeProperty].ValueOnInstance == null) - { - ExtendedItem.Properties[Shape.StrokeProperty].SetValue(Colors.Black); - ExtendedItem.Properties[Shape.StrokeThicknessProperty].SetValue(2d); - ExtendedItem.Properties[Shape.StretchProperty].SetValue(Stretch.None); - points.AddRange(new List { new Point(0, 0), new Point(20, 20) }); - ExtendedItem.Properties.GetProperty(ExtendedItem.View as Polyline != null ? Polyline.PointsProperty : Polygon.PointsProperty).SetValue(points); - } - - resizeThumbs = new List(); - for (int i = 1; i < points.Count; i++) - { - CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE, i); - } - - Invalidate(); - - ResetWidthHeightProperties(); - - ResetThumbs(); - _isDragging = false; - - extendedItemArray[0] = ExtendedItem; - ExtendedItem.PropertyChanged += OnPropertyChanged; - Services.Selection.PrimarySelectionChanged += OnPrimarySelectionChanged; - resizeBehavior = PlacementOperation.GetPlacementBehavior(extendedItemArray); - UpdateAdornerVisibility(); - OnPrimarySelectionChanged(null, null); - } - - #endregion - - PointCollection GetPointCollection() - { - Polygon pg = ExtendedItem.View as Polygon; - Polyline pl = ExtendedItem.View as Polyline; - - return pl == null ? pg.Points : pl.Points; - } - - PointCollection MovePoints(PointCollection pc, double displacementX, double displacementY, double theta, int? snapangle) - { - //iterate all selected points - foreach (int i in _selectedThumbs.Keys) - { - Point p = pc[i]; - - //x and y is calculated from the currentl point - double x = _selectedThumbs[i].X + displacementX; - double y = _selectedThumbs[i].Y + displacementY; - - //if snap is applied - if (snapangle != null) - { - if (_selectedThumbs.Count > 0) - { - //horizontal snap - if (Math.Abs(theta) < snapangle || 180 - Math.Abs(theta) < snapangle) - { - //if one point selected use point before as snap point, else snap to movement - y = _selectedThumbs.Count == 1 ? pc[i - 1].Y : y - displacementY; - } - else if (Math.Abs(90 - Math.Abs(theta)) < snapangle)//vertical snap - { - //if one point selected use point before as snap point, else snap to movement - x = _selectedThumbs.Count == 1 ? pc[i - 1].X : x - displacementX; - } - } - } - - p.X = x; - p.Y = y; - pc[i] = p; - } - return pc; - } - - #region IKeyDown - - public bool InvokeDefaultAction - { - get { return _selectedThumbs.Count == 0 || _selectedThumbs.Count == GetPointCollection().Count - 1; } - } - - int _movingDistance; - public void KeyDownAction(object sender, KeyEventArgs e) - { - Debug.WriteLine("KeyDown"); - if (IsArrowKey(e.Key)) - if (operation == null) - { - SetOperation(); - _movingDistance = 0; - } - - - var dx1 = (e.Key == Key.Left) ? Keyboard.IsKeyDown(Key.LeftShift) ? _movingDistance - 10 : _movingDistance - 1 : 0; - var dy1 = (e.Key == Key.Up) ? Keyboard.IsKeyDown(Key.LeftShift) ? _movingDistance - 10 : _movingDistance - 1 : 0; - var dx2 = (e.Key == Key.Right) ? Keyboard.IsKeyDown(Key.LeftShift) ? _movingDistance + 10 : _movingDistance + 1 : 0; - var dy2 = (e.Key == Key.Down) ? Keyboard.IsKeyDown(Key.LeftShift) ? _movingDistance + 10 : _movingDistance + 1 : 0; - - ChangeOperation(MovePoints(GetPointCollection(), dx1 + dx2, dy1 + dy2, 0, null)); - _movingDistance = (dx1 + dx2 + dy1 + dy2); - } - - public void KeyUpAction(object sender, KeyEventArgs e) - { - Debug.WriteLine("Keyup"); - if (IsArrowKey(e.Key)) - CommitOperation(); - } - - bool IsArrowKey(Key key) - { - return (key == Key.Left || key == Key.Right || key == Key.Up || key == Key.Down); - } - #endregion - } + [ExtensionFor(typeof(Polyline), OverrideExtensions = new Type[] { typeof(ResizeThumbExtension), typeof(SelectedElementRectangleExtension), typeof(CanvasPositionExtension), typeof(QuickOperationMenuExtension), typeof(RotateThumbExtension), typeof(RenderTransformOriginExtension), typeof(InPlaceEditorExtension), typeof(SizeDisplayExtension), typeof(SkewThumbExtension) })] + internal class PolyLineHandlerExtension : LineExtensionBase, IKeyDown, IKeyUp + { + private readonly Dictionary _selectedThumbs = new Dictionary(); + private bool _isDragging; + ZoomControl _zoom; + + #region thumb methods + protected ResizeThumb CreateThumb(PlacementAlignment alignment, Cursor cursor, int index) + { + ResizeThumb resizeThumb = new MultiPointResizeThumb { Index = index, Alignment = alignment, Cursor = cursor, IsPrimarySelection = true }; + AdornerPlacement ap = Place(ref resizeThumb, alignment, index); + (resizeThumb as MultiPointResizeThumb).AdornerPlacement = ap; + + AdornerPanel.SetPlacement(resizeThumb, ap); + adornerPanel.Children.Add(resizeThumb); + + DragListener drag = new DragListener(resizeThumb); + + WeakEventManager.AddHandler(resizeThumb, "PreviewMouseLeftButtonDown", ResizeThumbOnMouseLeftButtonUp); + + drag.Started += drag_Started; + drag.Changed += drag_Changed; + drag.Completed += drag_Completed; + return resizeThumb; + } + + private void ResetThumbs() + { + foreach (FrameworkElement rt in adornerPanel.Children) + { + if (rt is ResizeThumb) + (rt as ResizeThumb).IsPrimarySelection = true; + } + _selectedThumbs.Clear(); + } + + private void SelectThumb(MultiPointResizeThumb mprt) + { + PointCollection points = GetPointCollection(); + Point p = points[mprt.Index]; + _selectedThumbs.Add(mprt.Index, new Bounds { X = p.X, Y = p.Y }); + + mprt.IsPrimarySelection = false; + } + + #endregion + + #region eventhandlers + + private void ResizeThumbOnMouseLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs) + { + //get current thumb + MultiPointResizeThumb mprt = sender as MultiPointResizeThumb; + if (mprt != null) + { + //shift+ctrl will remove selected point + if ((Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) && + (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))) + { + //unselect all points + ResetThumbs(); + PointCollection points = GetPointCollection(); + + //iterate thumbs to lower index of remaining thumbs + foreach (MultiPointResizeThumb m in adornerPanel.Children) + { + if (m.Index > mprt.Index) + m.Index--; + } + + //remove point and thumb + points.RemoveAt(mprt.Index); + adornerPanel.Children.Remove(mprt); + + Invalidate(); + } + else + { + //if not keyboard ctrl is pressed and selected point is not previously selected, clear selection + if (!_selectedThumbs.ContainsKey(mprt.Index) & !Keyboard.IsKeyDown(Key.LeftCtrl) & + !Keyboard.IsKeyDown(Key.RightCtrl)) + { + ResetThumbs(); + } + //add selected thumb, if ctrl pressed this could be all points in poly + if (!_selectedThumbs.ContainsKey(mprt.Index)) + SelectThumb(mprt); + _isDragging = false; + } + } + } + + // TODO : Remove all hide/show extensions from here. + protected void drag_Started(DragListener drag) + { + //get current thumb + MultiPointResizeThumb mprt = (drag.Target as MultiPointResizeThumb); + if (mprt != null) + { + SetOperation(); + } + } + + void SetOperation() + { + var designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; + _zoom = designPanel.TryFindParent(); + + if (resizeBehavior != null) + operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); + else + { + changeGroup = ExtendedItem.Context.OpenGroup("Resize", extendedItemArray); + } + _isResizing = true; + } + + void ChangeOperation(PointCollection points) + { + //this is for SharpDevelop built in undo functionality + if (operation != null) + { + var info = operation.PlacedItems[0]; + var result = info.OriginalBounds; + + IEnumerable xs = points.Select(x => x.X); + IEnumerable ys = points.Select(y => y.Y); + result.X = (double)(info.Item.Properties.GetAttachedProperty(Canvas.LeftProperty).ValueOnInstance); + result.Y = (double)(info.Item.Properties.GetAttachedProperty(Canvas.TopProperty).ValueOnInstance); + result.Width = xs.Max() - xs.Min(); + result.Height = ys.Max() - ys.Min(); + + info.Bounds = result.Round(); + operation.CurrentContainerBehavior.BeforeSetPosition(operation); + operation.CurrentContainerBehavior.SetPosition(info); + } + + ResetWidthHeightProperties(); + + } + + void CommitOperation() + { + if (operation != null) + { + PointCollection points; + Polygon pg = ExtendedItem.View as Polygon; + Polyline pl = ExtendedItem.View as Polyline; + if (pl == null) + { + points = pg.Points; + + } + else + { + points = pl.Points; + } + + foreach (int i in _selectedThumbs.Keys) + { + _selectedThumbs[i].X = points[i].X; + _selectedThumbs[i].Y = points[i].Y; + } + ExtendedItem.Properties.GetProperty(pl != null ? Polyline.PointsProperty : Polygon.PointsProperty).SetValue(points); + ResetWidthHeightProperties(); + operation.Commit(); + + operation = null; + } + else + { + changeGroup.Commit(); + changeGroup = null; + } + _isResizing = false; + + ResetWidthHeightProperties(); + Invalidate(); + } + + protected void drag_Changed(DragListener drag) + { + PointCollection points = GetPointCollection(); + + MultiPointResizeThumb mprt = drag.Target as MultiPointResizeThumb; + if (mprt != null) + { + double dx = 0; + double dy = 0; + //if has zoomed + if (_zoom != null) + { + dx = drag.Delta.X * (1 / _zoom.CurrentZoom); + dy = drag.Delta.Y * (1 / _zoom.CurrentZoom); + } + + Double theta; + //if one point selected snapping angle is calculated in relation to previous point + if (_selectedThumbs.Count == 1) + { + theta = (180 / Math.PI) * Math.Atan2(_selectedThumbs[mprt.Index].Y + dy - points[mprt.Index - 1].Y, _selectedThumbs[mprt.Index].X + dx - points[mprt.Index - 1].X); + } + else//if multiple points snapping angle is calculated in relation to mouse dragging angle + { + theta = (180 / Math.PI) * Math.Atan2(dy, dx); + } + + //snappingAngle is used for snapping function to horizontal or vertical plane in line drawing, and is activated by pressing ctrl or shift button + int? snapAngle = null; + + //shift+alt gives a new point + if ((Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) && (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt))) + { + //if dragging occurs on a point and that point is the only selected, a new node will be added. + //_isCtrlDragging is needed since this method is called for every x pixel that the mouse moves + //so it could be many thousands of times during a single dragging + if (!_isDragging && _selectedThumbs.Count == 1 && (Math.Abs(dx) > 0 || Math.Abs(dy) > 0)) + { + + //duplicate point that is selected + Point p = points[mprt.Index]; + + //insert duplicate + points.Insert(mprt.Index, p); + + //create adorner marker + CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE, mprt.Index); + + //set index of all points that had a higher index than selected to +1 + foreach (FrameworkElement rt in adornerPanel.Children) + { + if (rt is MultiPointResizeThumb) + { + MultiPointResizeThumb t = rt as MultiPointResizeThumb; + if (t.Index > mprt.Index) + t.Index++; + } + } + + //set index of new point to old point index + 1 + mprt.Index = mprt.Index + 1; + ResetThumbs(); + SelectThumb(mprt); + + } + snapAngle = 10; + } + + //snapping occurs when mouse is within 10 degrees from horizontal or vertical plane if shift is pressed + else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) + { + snapAngle = 10; + } + //snapping occurs within 45 degree intervals that is line will always be horizontal or vertical if alt is pressed + else if (Keyboard.IsKeyDown(Key.LeftAlt) || Keyboard.IsKeyDown(Key.RightAlt)) + { + snapAngle = 45; + } + _isDragging = true; + points = MovePoints(points, dx, dy, theta, snapAngle); + + } + ChangeOperation(points); + (drag.Target as ResizeThumb).InvalidateArrange(); + + + } + + protected void drag_Completed(DragListener drag) + { + MultiPointResizeThumb mprt = drag.Target as MultiPointResizeThumb; + if (mprt != null) + { + if (operation != null && drag.IsCanceled) + { + operation.Abort(); + } + else if (drag.IsCanceled) + { + changeGroup.Abort(); + } + CommitOperation(); + } + } + + + + protected override void OnInitialized() + { + base.OnInitialized(); + + PointCollection points = GetPointCollection(); + + if (ExtendedItem.Properties[Shape.StrokeProperty].ValueOnInstance == null) + { + ExtendedItem.Properties[Shape.StrokeProperty].SetValue(Colors.Black); + ExtendedItem.Properties[Shape.StrokeThicknessProperty].SetValue(2d); + ExtendedItem.Properties[Shape.StretchProperty].SetValue(Stretch.None); + points.AddRange(new List { new Point(0, 0), new Point(20, 20) }); + ExtendedItem.Properties.GetProperty(ExtendedItem.View as Polyline != null ? Polyline.PointsProperty : Polygon.PointsProperty).SetValue(points); + } + + resizeThumbs = new List(); + for (int i = 1; i < points.Count; i++) + { + CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE, i); + } + + Invalidate(); + + ResetWidthHeightProperties(); + + ResetThumbs(); + _isDragging = false; + + extendedItemArray[0] = ExtendedItem; + ExtendedItem.PropertyChanged += OnPropertyChanged; + Services.Selection.PrimarySelectionChanged += OnPrimarySelectionChanged; + resizeBehavior = PlacementOperation.GetPlacementBehavior(extendedItemArray); + UpdateAdornerVisibility(); + OnPrimarySelectionChanged(null, null); + } + + #endregion + + PointCollection GetPointCollection() + { + Polygon pg = ExtendedItem.View as Polygon; + Polyline pl = ExtendedItem.View as Polyline; + + return pl == null ? pg.Points : pl.Points; + } + + PointCollection MovePoints(PointCollection pc, double displacementX, double displacementY, double theta, int? snapangle) + { + //iterate all selected points + foreach (int i in _selectedThumbs.Keys) + { + Point p = pc[i]; + + //x and y is calculated from the currentl point + double x = _selectedThumbs[i].X + displacementX; + double y = _selectedThumbs[i].Y + displacementY; + + //if snap is applied + if (snapangle != null) + { + if (_selectedThumbs.Count > 0) + { + //horizontal snap + if (Math.Abs(theta) < snapangle || 180 - Math.Abs(theta) < snapangle) + { + //if one point selected use point before as snap point, else snap to movement + y = _selectedThumbs.Count == 1 ? pc[i - 1].Y : y - displacementY; + } + else if (Math.Abs(90 - Math.Abs(theta)) < snapangle)//vertical snap + { + //if one point selected use point before as snap point, else snap to movement + x = _selectedThumbs.Count == 1 ? pc[i - 1].X : x - displacementX; + } + } + } + + p.X = x; + p.Y = y; + pc[i] = p; + } + return pc; + } + + #region IKeyDown + + public bool InvokeDefaultAction + { + get { return _selectedThumbs.Count == 0 || _selectedThumbs.Count == GetPointCollection().Count - 1; } + } + + int _movingDistance; + public void KeyDownAction(object sender, KeyEventArgs e) + { + Debug.WriteLine("KeyDown"); + if (IsArrowKey(e.Key)) + if (operation == null) + { + SetOperation(); + _movingDistance = 0; + } + + + var dx1 = (e.Key == Key.Left) ? Keyboard.IsKeyDown(Key.LeftShift) ? _movingDistance - 10 : _movingDistance - 1 : 0; + var dy1 = (e.Key == Key.Up) ? Keyboard.IsKeyDown(Key.LeftShift) ? _movingDistance - 10 : _movingDistance - 1 : 0; + var dx2 = (e.Key == Key.Right) ? Keyboard.IsKeyDown(Key.LeftShift) ? _movingDistance + 10 : _movingDistance + 1 : 0; + var dy2 = (e.Key == Key.Down) ? Keyboard.IsKeyDown(Key.LeftShift) ? _movingDistance + 10 : _movingDistance + 1 : 0; + + ChangeOperation(MovePoints(GetPointCollection(), dx1 + dx2, dy1 + dy2, 0, null)); + _movingDistance = (dx1 + dx2 + dy1 + dy2); + } + + public void KeyUpAction(object sender, KeyEventArgs e) + { + Debug.WriteLine("Keyup"); + if (IsArrowKey(e.Key)) + CommitOperation(); + } + + bool IsArrowKey(Key key) + { + return (key == Key.Left || key == Key.Right || key == Key.Up || key == Key.Down); + } + #endregion + } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs index c25bad2de3..26d0de1c1c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs @@ -26,6 +26,7 @@ using ICSharpCode.WpfDesign.Adorners; using ICSharpCode.WpfDesign.Designer.Controls; using ICSharpCode.WpfDesign.Extensions; using System.Collections.Generic; +using ICSharpCode.WpfDesign.Designer.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Extensions { @@ -124,15 +125,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions void drag_Started(DragListener drag) { var designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; - if (designPanel != null) - { - var p = VisualTreeHelper.GetParent(designPanel); - while (p != null && !(p is ZoomControl)) - { - p = VisualTreeHelper.GetParent(p); - } - zoom = p as ZoomControl; - } + zoom = designPanel.TryFindParent(); /* Abort editing Text if it was editing, because it interferes with the undo stack. */ foreach(var extension in this.ExtendedItem.Extensions){ From 20c1bd6c22392a585297bc7a6b6a9010887346cf Mon Sep 17 00:00:00 2001 From: jkuehner Date: Sat, 27 Dec 2014 14:47:27 +0100 Subject: [PATCH 04/10] Items Control should have a Transp. Background so it can be used as a Drop Target --- .../Extensions/PanelInstanceFactory.cs | 141 ++++------------- ...lueInsteadOfNullTypeDescriptionProvider.cs | 142 ++++++++++++++++++ .../WpfDesign/Project/WpfDesign.csproj | 1 + 3 files changed, 169 insertions(+), 115 deletions(-) create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DummyValueInsteadOfNullTypeDescriptionProvider.cs diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelInstanceFactory.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelInstanceFactory.cs index 3da7397e10..6b12abe3d7 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelInstanceFactory.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PanelInstanceFactory.cs @@ -79,6 +79,32 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } } + [ExtensionFor(typeof(ItemsControl))] + public sealed class TransparentControlsInstanceFactory : CustomInstanceFactory + { + Brush _transparentBrush = new SolidColorBrush(Colors.Transparent); + + /// + /// Creates an instance of the specified type, passing the specified arguments to its constructor. + /// + public override object CreateInstance(Type type, params object[] arguments) + { + object instance = base.CreateInstance(type, arguments); + Control control = instance as Control; + if (control != null && ( + type == typeof(ItemsControl))) { + if (control.Background == null) { + control.Background = _transparentBrush; + } + + TypeDescriptionProvider provider = new DummyValueInsteadOfNullTypeDescriptionProvider( + TypeDescriptor.GetProvider(control), "Background", _transparentBrush); + TypeDescriptor.AddProvider(provider, control); + } + return instance; + } + } + [ExtensionFor(typeof(Border))] public sealed class BorderInstanceFactory : CustomInstanceFactory { @@ -104,119 +130,4 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions return instance; } } - - sealed class DummyValueInsteadOfNullTypeDescriptionProvider : TypeDescriptionProvider - { - // By using a TypeDescriptionProvider, we can intercept all access to the property that is - // using a PropertyDescriptor. WpfDesign.XamlDom uses a PropertyDescriptor for accessing - // properties (except for attached properties), so even DesignItemProperty/XamlProperty.ValueOnInstance - // will report null when the actual value is the dummy value. - - readonly string _propertyName; - readonly object _dummyValue; - - public DummyValueInsteadOfNullTypeDescriptionProvider(TypeDescriptionProvider existingProvider, - string propertyName, object dummyValue) - : base(existingProvider) - { - this._propertyName = propertyName; - this._dummyValue = dummyValue; - } - - public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) - { - return new ShadowTypeDescriptor(this, base.GetTypeDescriptor(objectType, instance)); - } - - sealed class ShadowTypeDescriptor : CustomTypeDescriptor - { - readonly DummyValueInsteadOfNullTypeDescriptionProvider _parent; - - public ShadowTypeDescriptor(DummyValueInsteadOfNullTypeDescriptionProvider parent, - ICustomTypeDescriptor existingDescriptor) - : base(existingDescriptor) - { - this._parent = parent; - } - - public override PropertyDescriptorCollection GetProperties() - { - return Filter(base.GetProperties()); - } - - public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) - { - return Filter(base.GetProperties(attributes)); - } - - PropertyDescriptorCollection Filter(PropertyDescriptorCollection properties) - { - PropertyDescriptor property = properties[_parent._propertyName]; - if (property != null) { - if ((properties as System.Collections.IDictionary).IsReadOnly) { - properties = new PropertyDescriptorCollection(properties.Cast().ToArray()); - } - properties.Remove(property); - properties.Add(new ShadowPropertyDescriptor(_parent, property)); - } - return properties; - } - } - - sealed class ShadowPropertyDescriptor : PropertyDescriptor - { - readonly DummyValueInsteadOfNullTypeDescriptionProvider _parent; - readonly PropertyDescriptor _baseDescriptor; - - public ShadowPropertyDescriptor(DummyValueInsteadOfNullTypeDescriptionProvider parent, - PropertyDescriptor existingDescriptor) - : base(existingDescriptor) - { - this._parent = parent; - this._baseDescriptor = existingDescriptor; - } - - public override Type ComponentType { - get { return _baseDescriptor.ComponentType; } - } - - public override bool IsReadOnly { - get { return _baseDescriptor.IsReadOnly; } - } - - public override Type PropertyType { - get { return _baseDescriptor.PropertyType; } - } - - public override bool CanResetValue(object component) - { - return _baseDescriptor.CanResetValue(component); - } - - public override object GetValue(object component) - { - object value = _baseDescriptor.GetValue(component); - if (value == _parent._dummyValue) - return null; - else - return value; - } - - public override void ResetValue(object component) - { - _baseDescriptor.SetValue(component, _parent._dummyValue); - } - - public override void SetValue(object component, object value) - { - _baseDescriptor.SetValue(component, value ?? _parent._dummyValue); - } - - public override bool ShouldSerializeValue(object component) - { - return _baseDescriptor.ShouldSerializeValue(component) - && _baseDescriptor.GetValue(component) != _parent._dummyValue; - } - } - } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DummyValueInsteadOfNullTypeDescriptionProvider.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DummyValueInsteadOfNullTypeDescriptionProvider.cs new file mode 100644 index 0000000000..2834cabe6b --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DummyValueInsteadOfNullTypeDescriptionProvider.cs @@ -0,0 +1,142 @@ +// 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.ComponentModel; +using System.Linq; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Description of DummyValueInsteadOfNullTypeDescriptionProvider. + /// + public sealed class DummyValueInsteadOfNullTypeDescriptionProvider : TypeDescriptionProvider + { + // By using a TypeDescriptionProvider, we can intercept all access to the property that is + // using a PropertyDescriptor. WpfDesign.XamlDom uses a PropertyDescriptor for accessing + // properties (except for attached properties), so even DesignItemProperty/XamlProperty.ValueOnInstance + // will report null when the actual value is the dummy value. + + readonly string _propertyName; + readonly object _dummyValue; + + public DummyValueInsteadOfNullTypeDescriptionProvider(TypeDescriptionProvider existingProvider, + string propertyName, object dummyValue) + : base(existingProvider) + { + this._propertyName = propertyName; + this._dummyValue = dummyValue; + } + + public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + { + return new ShadowTypeDescriptor(this, base.GetTypeDescriptor(objectType, instance)); + } + + sealed class ShadowTypeDescriptor : CustomTypeDescriptor + { + readonly DummyValueInsteadOfNullTypeDescriptionProvider _parent; + + public ShadowTypeDescriptor(DummyValueInsteadOfNullTypeDescriptionProvider parent, + ICustomTypeDescriptor existingDescriptor) + : base(existingDescriptor) + { + this._parent = parent; + } + + public override PropertyDescriptorCollection GetProperties() + { + return Filter(base.GetProperties()); + } + + public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) + { + return Filter(base.GetProperties(attributes)); + } + + PropertyDescriptorCollection Filter(PropertyDescriptorCollection properties) + { + PropertyDescriptor property = properties[_parent._propertyName]; + if (property != null) { + if ((properties as System.Collections.IDictionary).IsReadOnly) { + properties = new PropertyDescriptorCollection(properties.Cast().ToArray()); + } + properties.Remove(property); + properties.Add(new ShadowPropertyDescriptor(_parent, property)); + } + return properties; + } + } + + sealed class ShadowPropertyDescriptor : PropertyDescriptor + { + readonly DummyValueInsteadOfNullTypeDescriptionProvider _parent; + readonly PropertyDescriptor _baseDescriptor; + + public ShadowPropertyDescriptor(DummyValueInsteadOfNullTypeDescriptionProvider parent, + PropertyDescriptor existingDescriptor) + : base(existingDescriptor) + { + this._parent = parent; + this._baseDescriptor = existingDescriptor; + } + + public override Type ComponentType { + get { return _baseDescriptor.ComponentType; } + } + + public override bool IsReadOnly { + get { return _baseDescriptor.IsReadOnly; } + } + + public override Type PropertyType { + get { return _baseDescriptor.PropertyType; } + } + + public override bool CanResetValue(object component) + { + return _baseDescriptor.CanResetValue(component); + } + + public override object GetValue(object component) + { + object value = _baseDescriptor.GetValue(component); + if (value == _parent._dummyValue) + return null; + else + return value; + } + + public override void ResetValue(object component) + { + _baseDescriptor.SetValue(component, _parent._dummyValue); + } + + public override void SetValue(object component, object value) + { + _baseDescriptor.SetValue(component, value ?? _parent._dummyValue); + } + + public override bool ShouldSerializeValue(object component) + { + return _baseDescriptor.ShouldSerializeValue(component) + && _baseDescriptor.GetValue(component) != _parent._dummyValue; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj index 7bc841aa26..ebc325f1c0 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj @@ -73,6 +73,7 @@ + From 8951f3a2f90875cc81996a98c0226f301f5810b5 Mon Sep 17 00:00:00 2001 From: jkuehner Date: Sat, 27 Dec 2014 14:51:22 +0100 Subject: [PATCH 05/10] Use "EnableAppXamlParsing" Setting, but default should be "true" --- .../Src/Options/WpfEditorOptions.cs | 2 +- .../WpfDesign.AddIn/Src/WpfViewContent.cs | 36 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Options/WpfEditorOptions.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Options/WpfEditorOptions.cs index 9f16acdec8..488e026a22 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Options/WpfEditorOptions.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Options/WpfEditorOptions.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.WpfDesign.AddIn.Options public static bool EnableAppXamlParsing { get { - return SD.PropertyService.Get(EnableAppXamlParsingOptionName, false); + return SD.PropertyService.Get(EnableAppXamlParsingOptionName, true); } set { SD.PropertyService.Set(EnableAppXamlParsingOptionName, value); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs index 7a9765cf85..2dd405ed6d 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs @@ -49,6 +49,7 @@ using ICSharpCode.WpfDesign.Designer.PropertyGrid; using ICSharpCode.WpfDesign.Designer.Services; using ICSharpCode.WpfDesign.Designer.Xaml; using ICSharpCode.WpfDesign.XamlDom; +using ICSharpCode.WpfDesign.AddIn.Options; namespace ICSharpCode.WpfDesign.AddIn { @@ -155,26 +156,27 @@ namespace ICSharpCode.WpfDesign.AddIn } try{ - var appXaml = SD.ProjectService.CurrentProject.Items.FirstOrDefault(x=>x.FileName.GetFileName().ToLower() == ("app.xaml")); - if (appXaml!=null){ - var f=appXaml as FileProjectItem; - OpenedFile a = SD.FileService.GetOrCreateOpenedFile(f.FileName); + if (WpfEditorOptions.EnableAppXamlParsing) { + var appXaml = SD.ProjectService.CurrentProject.Items.FirstOrDefault(x=>x.FileName.GetFileName().ToLower() == ("app.xaml")); + if (appXaml!=null){ + var f=appXaml as FileProjectItem; + OpenedFile a = SD.FileService.GetOrCreateOpenedFile(f.FileName); - var xml = XmlReader.Create(a.OpenRead()); - var doc=new XmlDocument(); - doc.Load(xml); - var node = doc.FirstChild.ChildNodes.Cast().FirstOrDefault(x=>x.Name=="Application.Resources"); + var xml = XmlReader.Create(a.OpenRead()); + var doc=new XmlDocument(); + doc.Load(xml); + var node = doc.FirstChild.ChildNodes.Cast().FirstOrDefault(x=>x.Name=="Application.Resources"); - foreach (XmlAttribute att in doc.FirstChild.Attributes.Cast().ToList()) - { - if (att.Name.StartsWith("xmlns")) - node.Attributes.Append(att); - } + foreach (XmlAttribute att in doc.FirstChild.Attributes.Cast().ToList()) { + if (att.Name.StartsWith("xmlns")) + node.Attributes.Append(att); + } - var appXamlXml = XmlReader.Create(new StringReader(node.InnerXml)); - var parsed = XamlParser.Parse(appXamlXml, ((XamlDesignContext) designer.DesignContext).ParserSettings); - var dict = (ResourceDictionary)parsed.RootInstance; - designer.DesignPanel.Resources.MergedDictionaries.Add(dict); + var appXamlXml = XmlReader.Create(new StringReader(node.InnerXml)); + var parsed = XamlParser.Parse(appXamlXml, ((XamlDesignContext) designer.DesignContext).ParserSettings); + var dict = (ResourceDictionary)parsed.RootInstance; + designer.DesignPanel.Resources.MergedDictionaries.Add(dict); + } } } catch (Exception ex) { LoggingService.Error("Error in loading app.xaml", ex); From 76803ef109773cf9e56959cf3c06f4d51d88ada7 Mon Sep 17 00:00:00 2001 From: Simon Bridewell Date: Sat, 27 Dec 2014 20:36:37 +0000 Subject: [PATCH 06/10] Add -mergebyhash command line option when running PartCover, to avoid trying to add the same assembly to the code coverage results more than once. See http://community.sharpdevelop.net/forums/p/22003/56296.aspx --- .../Analysis/CodeCoverage/Project/Src/OpenCoverApplication.cs | 2 +- .../CodeCoverage/Test/Testing/OpenCoverApplicationTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AddIns/Analysis/CodeCoverage/Project/Src/OpenCoverApplication.cs b/src/AddIns/Analysis/CodeCoverage/Project/Src/OpenCoverApplication.cs index fdd2a97d49..805ac8e593 100644 --- a/src/AddIns/Analysis/CodeCoverage/Project/Src/OpenCoverApplication.cs +++ b/src/AddIns/Analysis/CodeCoverage/Project/Src/OpenCoverApplication.cs @@ -104,7 +104,7 @@ namespace ICSharpCode.CodeCoverage string GetArguments() { // IMPORTANT: https://github.com/sawilde/opencover/wiki/Usage - arguments = new StringBuilder("-register:user "); + arguments = new StringBuilder("-register:user -mergebyhash "); AppendTarget(); AppendTargetWorkingDirectory(); diff --git a/src/AddIns/Analysis/CodeCoverage/Test/Testing/OpenCoverApplicationTests.cs b/src/AddIns/Analysis/CodeCoverage/Test/Testing/OpenCoverApplicationTests.cs index 68fffe4340..001f04105e 100644 --- a/src/AddIns/Analysis/CodeCoverage/Test/Testing/OpenCoverApplicationTests.cs +++ b/src/AddIns/Analysis/CodeCoverage/Test/Testing/OpenCoverApplicationTests.cs @@ -163,7 +163,7 @@ namespace ICSharpCode.CodeCoverage.Tests.Testing ProcessStartInfo processStartInfo = openCoverApp.GetProcessStartInfo(); string expectedCommandLine = - "-register:user -target:\"d:\\sharpdevelop\\bin\\Tools\\NUnit\\nunit-console-x86.exe\" " + + "-register:user -mergebyhash -target:\"d:\\sharpdevelop\\bin\\Tools\\NUnit\\nunit-console-x86.exe\" " + "-targetdir:\"c:\\projects\\MyTests\\bin\\Debug\" " + "-targetargs:\"\\\"c:\\projects\\MyTests\\bin\\Debug\\MyTests.dll\\\" /noxml\" " + "-output:\"c:\\projects\\MyTests\\OpenCover\\coverage.xml\" " + @@ -187,7 +187,7 @@ namespace ICSharpCode.CodeCoverage.Tests.Testing ProcessStartInfo processStartInfo = openCoverApp.GetProcessStartInfo(); string expectedCommandLine = - "-register:user -target:\"d:\\sharpdevelop\\bin\\Tools\\NUnit\\nunit-console-x86.exe\" " + + "-register:user -mergebyhash -target:\"d:\\sharpdevelop\\bin\\Tools\\NUnit\\nunit-console-x86.exe\" " + "-targetdir:\"c:\\projects\\MyTests\\bin\\Debug\" " + "-targetargs:\"\\\"c:\\projects\\MyTests\\bin\\Debug\\MyTests.dll\\\" /noxml\" " + "-output:\"c:\\projects\\MyTests\\OpenCover\\coverage.xml\" " + From 177dbe5dde8c54a91bc495e60bff811d6776410a Mon Sep 17 00:00:00 2001 From: Abdelkarim Sellamna Date: Tue, 16 Sep 2014 22:25:47 +0100 Subject: [PATCH 07/10] Fixed DropShadow issue Fixed an issue with the DropShadowEffect in the NavigatorWindowStyle of AvalonDock. --- .../Resources/NavigatorWindowStyle.xaml | 144 +++++++++--------- 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/src/Libraries/AvalonDock/AvalonDock/Resources/NavigatorWindowStyle.xaml b/src/Libraries/AvalonDock/AvalonDock/Resources/NavigatorWindowStyle.xaml index d551c8378f..e4f7335a85 100644 --- a/src/Libraries/AvalonDock/AvalonDock/Resources/NavigatorWindowStyle.xaml +++ b/src/Libraries/AvalonDock/AvalonDock/Resources/NavigatorWindowStyle.xaml @@ -155,75 +155,83 @@ - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From af2cfa321c7e1879acb221d16757432042b98c77 Mon Sep 17 00:00:00 2001 From: Abdelkarim Sellamna Date: Mon, 22 Sep 2014 09:27:55 +0100 Subject: [PATCH 08/10] tweaked the right margin for membersComboBox of the QuickClassBrowser. --- .../DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml index 049069b662..d227a84442 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.xaml @@ -31,7 +31,7 @@ DropDownClosed="ComboBox_DropDownClosed"/> From 2278daa694491af37f484cf9a231843ba4d63ef1 Mon Sep 17 00:00:00 2001 From: lvv83 Date: Sun, 4 Jan 2015 20:51:47 +0300 Subject: [PATCH 09/10] Fix closing tag for exception (xml-docs) --- .../Completion/CSharpCompletionEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs index 5398d044ec..e2fe1690b9 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs @@ -3629,7 +3629,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion yield return factory.CreateXmlDocCompletionData( "exception", "Identifies the exceptions a method can throw", - "exception cref=\"|\">" ); yield return factory.CreateXmlDocCompletionData( "include", From 8d963abf1b5172c13b0f16521bd716882a11241c Mon Sep 17 00:00:00 2001 From: Andreas Weizel Date: Mon, 12 Jan 2015 02:25:27 +0100 Subject: [PATCH 10/10] Fixed AssemblyInfoProviderTests broken by pull request #641. --- .../Test/ProjectOptions/AssemblyInfoProviderTests.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Main/Base/Test/ProjectOptions/AssemblyInfoProviderTests.cs b/src/Main/Base/Test/ProjectOptions/AssemblyInfoProviderTests.cs index e479f26e2e..5a05a0bd80 100644 --- a/src/Main/Base/Test/ProjectOptions/AssemblyInfoProviderTests.cs +++ b/src/Main/Base/Test/ProjectOptions/AssemblyInfoProviderTests.cs @@ -103,7 +103,7 @@ using System.Runtime.InteropServices; Assert.AreEqual("Alias", assemblyInfo.DefaultAlias); Assert.AreEqual(new Version(1, 2, 3, 1), assemblyInfo.AssemblyVersion); Assert.AreEqual(new Version(1, 2, 3, 2), assemblyInfo.AssemblyFileVersion); - Assert.AreEqual(new Version(1, 2, 3, 3), assemblyInfo.InformationalVersion); + Assert.AreEqual(new Version(1, 2, 3, 3).ToString(), assemblyInfo.InformationalVersion); Assert.AreEqual(new Guid("0c8c889f-ced2-4167-b155-2d48a99d8c72"), assemblyInfo.Guid); Assert.AreEqual("ru-RU", assemblyInfo.NeutralLanguage); Assert.IsTrue(assemblyInfo.ComVisible); @@ -136,7 +136,7 @@ using System.Runtime.InteropServices; var assemblyInfo = ReadAssemblyInfo(assemblyInfoFile); Assert.IsNull(assemblyInfo.AssemblyVersion); Assert.IsNull(assemblyInfo.AssemblyFileVersion); - Assert.IsNull(assemblyInfo.InformationalVersion); + Assert.AreEqual("Incorrect version", assemblyInfo.InformationalVersion); } [TestCase] @@ -202,7 +202,7 @@ using System.Runtime.InteropServices; Assert.AreEqual("", assemblyInfo.DefaultAlias); Assert.IsNull(assemblyInfo.AssemblyVersion); Assert.IsNull(assemblyInfo.AssemblyFileVersion); - Assert.IsNull(assemblyInfo.InformationalVersion); + Assert.AreEqual("", assemblyInfo.InformationalVersion); Assert.IsNull(assemblyInfo.Guid); Assert.AreEqual("", assemblyInfo.NeutralLanguage); } @@ -291,7 +291,7 @@ using System.Runtime.InteropServices; Assert.AreEqual("Alias", assemblyInfo.DefaultAlias); Assert.AreEqual(new Version(1, 2, 3, 1), assemblyInfo.AssemblyVersion); Assert.AreEqual(new Version(1, 2, 3, 2), assemblyInfo.AssemblyFileVersion); - Assert.AreEqual(new Version(1, 2, 3, 3), assemblyInfo.InformationalVersion); + Assert.AreEqual(new Version(1, 2, 3, 3).ToString(), assemblyInfo.InformationalVersion); Assert.AreEqual(new Guid("0c8c889f-ced2-4167-b155-2d48a99d8c72"), assemblyInfo.Guid); Assert.AreEqual("ru-RU", assemblyInfo.NeutralLanguage); Assert.IsTrue(assemblyInfo.ComVisible); @@ -400,7 +400,7 @@ using System.Reflection; DefaultAlias = "Alias", AssemblyVersion = new Version(1, 2, 3, 4), AssemblyFileVersion = new Version(1, 2, 3, 4), - InformationalVersion = new Version(1, 2, 3, 4), + InformationalVersion = new Version(1, 2, 3, 4).ToString(), Guid = new Guid("0c8c889f-ced2-4167-b155-2d48a99d8c72"), NeutralLanguage = "ru-RU", ComVisible = true, @@ -451,7 +451,7 @@ using System.Runtime.InteropServices; DefaultAlias = "Alias-changed", AssemblyVersion = new Version(4, 3, 2, 1), AssemblyFileVersion = new Version(4, 3, 2, 1), - InformationalVersion = new Version(4, 3, 2, 1), + InformationalVersion = new Version(4, 3, 2, 1).ToString(), Guid = new Guid("dc8c889f-ced2-4167-b155-2d48a99d8c72"), NeutralLanguage = "en-US", ComVisible = false,