diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/UserControlPointsObjectThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/UserControlPointsObjectThumb.cs
new file mode 100644
index 0000000000..18cb5735c0
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/UserControlPointsObjectThumb.cs
@@ -0,0 +1,30 @@
+// 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 ICSharpCode.WpfDesign.UIExtensions;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+
+namespace ICSharpCode.WpfDesign.Designer.Controls
+{
+ public class UserControlPointsObjectThumb : DesignerThumb
+ {
+ public DependencyProperty DependencyProperty { get; set; }
+ }
+}
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 623bf53f2b..5d2b3214ea 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineExtensionBase.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineExtensionBase.cs
@@ -107,7 +107,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
///
/// if using a polygon or multipoint adorner this is the index of the point in the Points array
///
- protected PointTrackerPlacementSupport Place(ref DesignerThumb designerThumb, PlacementAlignment alignment, int index = -1)
+ protected PointTrackerPlacementSupport Place(DesignerThumb designerThumb, PlacementAlignment alignment, int index = -1)
{
PointTrackerPlacementSupport placement = new PointTrackerPlacementSupport(ExtendedItem.View as Shape, alignment, index);
return placement;
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 161b9a3236..30fdd856fd 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineHandlerExtension.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineHandlerExtension.cs
@@ -56,7 +56,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
protected DesignerThumb CreateThumb(PlacementAlignment alignment, Cursor cursor)
{
DesignerThumb designerThumb = new DesignerThumb { Alignment = alignment, Cursor = cursor, IsPrimarySelection = true};
- AdornerPanel.SetPlacement(designerThumb, Place(ref designerThumb, alignment));
+ AdornerPanel.SetPlacement(designerThumb, Place(designerThumb, alignment));
adornerPanel.Children.Add(designerThumb);
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 0a8bd1ccdd..4817174750 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PolyLineHandlerExtension.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PolyLineHandlerExtension.cs
@@ -49,7 +49,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
protected DesignerThumb CreateThumb(PlacementAlignment alignment, Cursor cursor, int index)
{
DesignerThumb designerThumb = new MultiPointThumb { Index = index, Alignment = alignment, Cursor = cursor, IsPrimarySelection = true };
- AdornerPlacement ap = Place(ref designerThumb, alignment, index);
+ AdornerPlacement ap = Place(designerThumb, alignment, index);
(designerThumb as MultiPointThumb).AdornerPlacement = ap;
AdornerPanel.SetPlacement(designerThumb, ap);
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/UserControlPointsObjectExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/UserControlPointsObjectExtension.cs
new file mode 100644
index 0000000000..dbf2388dfb
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/UserControlPointsObjectExtension.cs
@@ -0,0 +1,245 @@
+// 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.Collections.Generic;
+using System.Windows;
+using ICSharpCode.WpfDesign.Extensions;
+using ICSharpCode.WpfDesign.Adorners;
+using ICSharpCode.WpfDesign.Designer.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Shapes;
+using System.Windows.Controls;
+using ICSharpCode.WpfDesign.UIExtensions;
+namespace ICSharpCode.WpfDesign.Designer.Extensions
+{
+ ///
+ /// Description of UserControlPointsObjectExtension.
+ ///
+ //[ExtensionFor(typeof(Line), OverrideExtensions = new Type[] { typeof(ResizeThumbExtension), typeof(SelectedElementRectangleExtension), typeof(CanvasPositionExtension), typeof(QuickOperationMenuExtension), typeof(RotateThumbExtension), typeof(RenderTransformOriginExtension), typeof(InPlaceEditorExtension), typeof(SkewThumbExtension) })]
+ public abstract class UserControlPointsObjectExtension : LineExtensionBase
+ {
+ ///
+ /// Used instead of Rect to allow negative values on "Width" and "Height" (here called X and Y).
+ ///
+ class Bounds
+ {
+ public double X, Y, Left, Top;
+ }
+
+ //
+ private double CurrentX2;
+ private double CurrentY2;
+ private double CurrentLeft;
+ private double CurrentTop;
+
+ private IEnumerable _thumbProperties;
+
+ //Size oldSize;
+ ZoomControl zoom;
+
+ public DragListener DragListener {get; private set;}
+
+ protected UserControlPointsObjectThumb CreateThumb(PlacementAlignment alignment, Cursor cursor, DependencyProperty property)
+ {
+ var designerThumb = new UserControlPointsObjectThumb { Alignment = alignment, Cursor = cursor, IsPrimarySelection = true, DependencyProperty = property};
+ AdornerPanel.SetPlacement(designerThumb, Place(designerThumb, alignment));
+
+ adornerPanel.Children.Add(designerThumb);
+
+ DragListener = new DragListener(designerThumb);
+ DragListener.Started += drag_Started;
+ DragListener.Changed += drag_Changed;
+ DragListener.Completed += drag_Completed;
+
+ return designerThumb;
+ }
+
+ 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, 3, 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
+
+ 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 UserControlPointsObjectThumb).IsPrimarySelection = false;
+ }
+
+ protected virtual void drag_Changed(DragListener drag)
+ {
+ Line al = ExtendedItem.View as Line;
+
+ var alignment = (drag.Target as UserControlPointsObjectThumb).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 UserControlPointsObjectThumb).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 UserControlPointsObjectThumb).IsPrimarySelection = true;
+ HideSizeAndShowHandles();
+ }
+
+ #endregion
+
+ ///
+ /// 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();
+
+ FillThumbProperties();
+
+ foreach (var prp in _thumbProperties) {
+ CreateThumb(PlacementAlignment.Center, Cursors.Cross, prp);
+ }
+
+ extendedItemArray[0] = this.ExtendedItem;
+
+ Invalidate();
+
+ this.ExtendedItem.PropertyChanged += OnPropertyChanged;
+ resizeBehavior = PlacementOperation.GetPlacementBehavior(extendedItemArray);
+ UpdateAdornerVisibility();
+ }
+
+ protected abstract IEnumerable FillThumbProperties();
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
index 73df4f6809..444bb3b156 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
@@ -88,6 +88,7 @@
+
@@ -131,6 +132,7 @@
ArrangeItemsContextMenu.xaml
+
WrapItemContextMenu.xaml