diff --git a/.gitignore b/.gitignore index 1d2ebb26f2..d65d9d2e06 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,10 @@ bin/ /src/AddIns/Misc/PackageManagement/Packages/AvalonEdit/lib /packages/ /src/Tools/ResGet/*.log + + +*.ide/ +*.sdsettings +*.DotSettings.user +*.suo +.DS_Store \ No newline at end of file diff --git a/samples/XamlDesigner/XamlDesigner.sln b/samples/XamlDesigner/XamlDesigner.sln index e4a9c002ca..08bd78a71d 100644 --- a/samples/XamlDesigner/XamlDesigner.sln +++ b/samples/XamlDesigner/XamlDesigner.sln @@ -1,7 +1,9 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -# SharpDevelop 5.0 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +# SharpDevelop 5.1 +VisualStudioVersion = 12.0.20827.3 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlDesigner", "XamlDesigner.csproj", "{27DA2B5C-2AAA-4478-AB00-3E184273C241}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign", "..\..\src\AddIns\DisplayBindings\WpfDesign\WpfDesign\Project\WpfDesign.csproj", "{66A378A1-E9F4-4AD5-8946-D0EC06C2902F}" diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/BasicMetadata.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/BasicMetadata.cs index 266bb736ae..91c20c5c96 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/BasicMetadata.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/BasicMetadata.cs @@ -260,6 +260,11 @@ namespace ICSharpCode.WpfDesign.Designer Metadata.AddPopularControl(typeof(Viewbox)); Metadata.AddPopularControl(typeof(Viewport3D)); Metadata.AddPopularControl(typeof(WrapPanel)); + Metadata.AddPopularControl(typeof(Line)); + Metadata.AddPopularControl(typeof(Polyline)); + Metadata.AddPopularControl(typeof(Ellipse)); + Metadata.AddPopularControl(typeof(Rectangle)); + Metadata.AddPopularControl(typeof(Path)); //Basic Metadata Size of double.NaN, means no Size should be set. Metadata.AddDefaultSize(typeof(TextBlock), new Size(double.NaN, double.NaN)); @@ -285,6 +290,38 @@ namespace ICSharpCode.WpfDesign.Designer Metadata.AddDefaultSize(typeof(Label), new Size(130, 120)); Metadata.AddDefaultSize(typeof(Expander), new Size(130, 120)); + + + Metadata.AddDefaultPropertyValue(typeof(Line), Line.X1Property, 0.0); + Metadata.AddDefaultPropertyValue(typeof(Line), Line.Y1Property, 0.0); + Metadata.AddDefaultPropertyValue(typeof(Line), Line.X2Property, 20.0); + Metadata.AddDefaultPropertyValue(typeof(Line), Line.Y2Property, 20.0); + Metadata.AddDefaultPropertyValue(typeof(Line), Line.StrokeProperty, Brushes.Black); + Metadata.AddDefaultPropertyValue(typeof(Line), Line.StrokeThicknessProperty, 2d); + Metadata.AddDefaultPropertyValue(typeof(Line), Line.StretchProperty, Stretch.None); + + Metadata.AddDefaultPropertyValue(typeof(Polyline), Polyline.PointsProperty, new PointCollection() { new Point(0, 0), new Point(20, 0), new Point(20, 20) }); + Metadata.AddDefaultPropertyValue(typeof(Polyline), Polyline.StrokeProperty, Brushes.Black); + Metadata.AddDefaultPropertyValue(typeof(Polyline), Polyline.StrokeThicknessProperty, 2d); + Metadata.AddDefaultPropertyValue(typeof(Polyline), Polyline.StretchProperty, Stretch.None); + + Metadata.AddDefaultPropertyValue(typeof(Polygon), Polygon.PointsProperty, new PointCollection() { new Point(0, 20), new Point(20, 20), new Point(10, 0) }); + Metadata.AddDefaultPropertyValue(typeof(Polygon), Polygon.StrokeProperty, Brushes.Black); + Metadata.AddDefaultPropertyValue(typeof(Polygon), Polygon.StrokeThicknessProperty, 2d); + Metadata.AddDefaultPropertyValue(typeof(Polygon), Polygon.StretchProperty, Stretch.None); + + Metadata.AddDefaultPropertyValue(typeof(Path), Path.StrokeProperty, Brushes.Black); + Metadata.AddDefaultPropertyValue(typeof(Path), Path.StrokeThicknessProperty, 2d); + Metadata.AddDefaultPropertyValue(typeof(Path), Path.StretchProperty, Stretch.None); + + Metadata.AddDefaultPropertyValue(typeof(Rectangle), Rectangle.FillProperty, Brushes.Transparent); + Metadata.AddDefaultPropertyValue(typeof(Rectangle), Rectangle.StrokeProperty, Brushes.Black); + Metadata.AddDefaultPropertyValue(typeof(Rectangle), Rectangle.StrokeThicknessProperty, 2d); + + Metadata.AddDefaultPropertyValue(typeof(Ellipse), Ellipse.FillProperty, Brushes.Transparent); + Metadata.AddDefaultPropertyValue(typeof(Ellipse), Ellipse.StrokeProperty, Brushes.Black); + Metadata.AddDefaultPropertyValue(typeof(Ellipse), Ellipse.StrokeThicknessProperty, 2d); + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ContainerDragHandle.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ContainerDragHandle.cs index 283596a2c5..c2ba30c35e 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ContainerDragHandle.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ContainerDragHandle.cs @@ -27,7 +27,7 @@ using ICSharpCode.WpfDesign.Extensions; using ICSharpCode.WpfDesign.Designer.Converters; using System.Globalization; using System.Windows.Data; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Controls { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml index c1c8fb22c1..237a66ce9f 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml @@ -1,4 +1,9 @@ - + @@ -46,11 +51,20 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/DragListener.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/DragListener.cs index 6d27a2c276..671c332785 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/DragListener.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/DragListener.cs @@ -23,6 +23,7 @@ using System.Text; using System.Windows; using System.Windows.Input; using System.Diagnostics; +using System.Windows.Media; namespace ICSharpCode.WpfDesign.Designer.Controls { @@ -35,6 +36,8 @@ namespace ICSharpCode.WpfDesign.Designer.Controls InputManager.Current.PostProcessInput += new ProcessInputEventHandler(PostProcessInput); } + public Transform Transform { get; set; } + public DragListener(IInputElement target) { Target = target; @@ -43,6 +46,21 @@ namespace ICSharpCode.WpfDesign.Designer.Controls Target.PreviewMouseMove += Target_MouseMove; Target.PreviewMouseLeftButtonUp += Target_MouseUp; } + + public void ExternalStart() + { + Target_MouseDown(null, null); + } + + public void ExternalMouseMove(MouseEventArgs e) + { + Target_MouseMove(null, e); + } + + public void ExternalStop() + { + Target_MouseUp(null, null); + } static DragListener CurrentListener; @@ -66,6 +84,8 @@ namespace ICSharpCode.WpfDesign.Designer.Controls DeltaDelta = new Vector(); IsDown = true; IsCanceled = false; + if (MouseDown != null) + MouseDown(this); } void Target_MouseMove(object sender, MouseEventArgs e) @@ -110,6 +130,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls } } + public event DragHandler MouseDown; public event DragHandler Started; public event DragHandler Changed; public event DragHandler Completed; @@ -123,7 +144,14 @@ namespace ICSharpCode.WpfDesign.Designer.Controls public bool IsCanceled { get; private set; } public Vector Delta { - get { return CurrentPoint - StartPoint; } + get { + if (Transform != null) { + var matrix = Transform.Value; + matrix.Invert(); + return matrix.Transform(CurrentPoint - StartPoint); + } + return CurrentPoint - StartPoint; + } } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PanelMoveAdorner.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PanelMoveAdorner.cs index 5b053c6366..37a186e5fa 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PanelMoveAdorner.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PanelMoveAdorner.cs @@ -28,7 +28,7 @@ using System.Windows.Media; using ICSharpCode.WpfDesign.Designer.Converters; using System.Globalization; using System.Windows.Data; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Controls { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/QuickOperationMenu.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/QuickOperationMenu.cs index 2e24bf0a42..c3a11bff06 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/QuickOperationMenu.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/QuickOperationMenu.cs @@ -20,12 +20,10 @@ using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; -using System.Windows.Input; using System.Windows.Media; using ICSharpCode.WpfDesign.Designer.Converters; -using System.Globalization; using System.Windows.Data; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Controls @@ -41,12 +39,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls } public QuickOperationMenu() - { - scaleTransform = new ScaleTransform(1.0, 1.0); - this.LayoutTransform = scaleTransform; - } - - private ScaleTransform scaleTransform; + { } private MenuItem _mainHeader; @@ -98,16 +91,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls if (mainHeader != null) { _mainHeader = mainHeader; } - - var surface = this.TryFindParent(); - if (surface != null && surface.ZoomControl != null) - { - var bnd = new Binding("CurrentZoom") { Source = surface.ZoomControl }; - bnd.Converter = InvertedZoomConverter.Instance; - - BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleXProperty, bnd); - BindingOperations.SetBinding(scaleTransform, ScaleTransform.ScaleYProperty, bnd); - } } /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ResizeThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/DesignerThumb.cs similarity index 58% rename from src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ResizeThumb.cs rename to src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/DesignerThumb.cs index ec82214b0c..d47c3d832e 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ResizeThumb.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/DesignerThumb.cs @@ -16,44 +16,52 @@ // 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.Diagnostics; +using ICSharpCode.WpfDesign.UIExtensions; using System.Windows; -using System.Windows.Input; using System.Windows.Controls; using System.Windows.Controls.Primitives; -using ICSharpCode.WpfDesign.Adorners; -using ICSharpCode.WpfDesign.Extensions; namespace ICSharpCode.WpfDesign.Designer.Controls { /// /// A thumb where the look can depend on the IsPrimarySelection property. /// - public class ResizeThumb : Thumb + public class DesignerThumb : Thumb { /// /// Dependency property for . /// public static readonly DependencyProperty IsPrimarySelectionProperty - = DependencyProperty.Register("IsPrimarySelection", typeof(bool), typeof(ResizeThumb)); + = DependencyProperty.Register("IsPrimarySelection", typeof(bool), typeof(DesignerThumb)); /// /// Dependency property for . /// - public static readonly DependencyProperty ResizeThumbVisibleProperty - = DependencyProperty.Register("ResizeThumbVisible", typeof(bool), typeof(ResizeThumb), new FrameworkPropertyMetadata(true)); - + public static readonly DependencyProperty ThumbVisibleProperty + = DependencyProperty.Register("ThumbVisible", typeof(bool), typeof(DesignerThumb), new FrameworkPropertyMetadata(true)); + + /// + /// Dependency property for . + /// + public static readonly DependencyProperty OperationMenuProperty = + DependencyProperty.Register("OperationMenu", typeof(Control[]), typeof(DesignerThumb), new PropertyMetadata(null)); + internal PlacementAlignment Alignment; - static ResizeThumb() + static DesignerThumb() { //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. //This style is defined in themes\generic.xaml - DefaultStyleKeyProperty.OverrideMetadata(typeof(ResizeThumb), new FrameworkPropertyMetadata(typeof(ResizeThumb))); + DefaultStyleKeyProperty.OverrideMetadata(typeof(DesignerThumb), new FrameworkPropertyMetadata(typeof(DesignerThumb))); } - + + public void ReDraw() + { + var parent = this.TryFindParent(); + if (parent != null) + parent.InvalidateArrange(); + } + /// /// Gets/Sets if the resize thumb is attached to the primary selection. /// @@ -65,36 +73,18 @@ namespace ICSharpCode.WpfDesign.Designer.Controls /// /// Gets/Sets if the resize thumb is visible. /// - public bool ResizeThumbVisible { - get { return (bool)GetValue(ResizeThumbVisibleProperty); } - set { SetValue(ResizeThumbVisibleProperty, value); } + public bool ThumbVisible { + get { return (bool)GetValue(ThumbVisibleProperty); } + set { SetValue(ThumbVisibleProperty, value); } } - } - - /// - /// Resize thumb that automatically disappears if the adornered element is too small. - /// - sealed class ResizeThumbImpl : ResizeThumb - { - bool checkWidth, checkHeight; - - internal ResizeThumbImpl(bool checkWidth, bool checkHeight) - { - Debug.Assert((checkWidth && checkHeight) == false); - this.checkWidth = checkWidth; - this.checkHeight = checkHeight; - } - - protected override Size ArrangeOverride(Size arrangeBounds) + + /// + /// Gets/Sets the OperationMenu. + /// + public Control[] OperationMenu { - AdornerPanel parent = this.Parent as AdornerPanel; - if (parent != null && parent.AdornedElement != null) { - if (checkWidth) - this.ResizeThumbVisible = PlacementOperation.GetRealElementSize(parent.AdornedElement).Width > 14; - else if (checkHeight) - this.ResizeThumbVisible = PlacementOperation.GetRealElementSize(parent.AdornedElement).Height > 14; - } - return base.ArrangeOverride(arrangeBounds); + get { return (Control[])GetValue(OperationMenuProperty); } + set { SetValue(OperationMenuProperty, value); } } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/MultiPointThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/MultiPointThumb.cs new file mode 100644 index 0000000000..8bc7b8ac91 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/MultiPointThumb.cs @@ -0,0 +1,52 @@ +// 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.Windows; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Designer.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// Description of MultiPointThumb. + /// + internal sealed class MultiPointThumb : DesignerThumb + { + private int _index; + + public int Index + { + get { return _index; } + set + { + _index = value; + var p = AdornerPlacement as PointTrackerPlacementSupport; + if (p != null) + p.Index = value; + } + } + + private AdornerPlacement _adornerPlacement; + + public AdornerPlacement AdornerPlacement + { + get { return _adornerPlacement; } + set { _adornerPlacement = value; } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/PointThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/PointThumb.cs new file mode 100644 index 0000000000..a803df02c7 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/PointThumb.cs @@ -0,0 +1,115 @@ +// 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.Windows; +using System.Windows.Media; +using ICSharpCode.WpfDesign.Adorners; +using System.Windows.Data; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// Description of MultiPointThumb. + /// + public class PointThumb : DesignerThumb + { + public Transform InnerRenderTransform + { + get { return (Transform)GetValue(InnerRenderTransformProperty); } + set { SetValue(InnerRenderTransformProperty, value); } + } + + // Using a DependencyProperty as the backing store for InnerRenderTransform. This enables animation, styling, binding, etc... + public static readonly DependencyProperty InnerRenderTransformProperty = + DependencyProperty.Register("InnerRenderTransform", typeof(Transform), typeof(PointThumb), new PropertyMetadata(null)); + + public bool IsEllipse + { + get { return (bool)GetValue(IsEllipseProperty); } + set { SetValue(IsEllipseProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsEllipse. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsEllipseProperty = + DependencyProperty.Register("IsEllipse", typeof(bool), typeof(PointThumb), new PropertyMetadata(false)); + + public Point Point + { + get { return (Point)GetValue(PointProperty); } + set { SetValue(PointProperty, value); } + } + + // Using a DependencyProperty as the backing store for Point. This enables animation, styling, binding, etc... + public static readonly DependencyProperty PointProperty = + DependencyProperty.Register("Point", typeof(Point), typeof(PointThumb), new PropertyMetadata(OnPointChanged)); + + private static void OnPointChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var pt = (PointThumb)d; + ((PointPlacementSupport)pt.AdornerPlacement).p = (Point)e.NewValue; + var bndExpr = pt.GetBindingExpression(PointThumb.RelativeToPointProperty); + if (bndExpr != null) + bndExpr.UpdateTarget(); + ((PointThumb)d).ReDraw(); + } + + public Point? RelativeToPoint + { + get { return (Point?)GetValue(RelativeToPointProperty); } + set { SetValue(RelativeToPointProperty, value); } + } + + // Using a DependencyProperty as the backing store for RelativeToPoint. This enables animation, styling, binding, etc... + public static readonly DependencyProperty RelativeToPointProperty = + DependencyProperty.Register("RelativeToPoint", typeof(Point?), typeof(PointThumb), new PropertyMetadata(null)); + + static PointThumb() + { + //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. + //This style is defined in themes\generic.xaml + DefaultStyleKeyProperty.OverrideMetadata(typeof(PointThumb), new FrameworkPropertyMetadata(typeof(PointThumb))); + } + + public PointThumb(Point point) + { + this.AdornerPlacement = new PointPlacementSupport(point); + Point = point; + } + + public PointThumb() + { + this.AdornerPlacement = new PointPlacementSupport(Point); + } + + public AdornerPlacement AdornerPlacement { get; private set; } + + private class PointPlacementSupport : AdornerPlacement + { + public Point p; + public PointPlacementSupport(Point point) + { + this.p = point; + } + + public override void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize) + { + adorner.Arrange(new Rect(p.X, p.Y, adornedElementSize.Width, adornedElementSize.Height)); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/ResizeThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/ResizeThumb.cs new file mode 100644 index 0000000000..06e9c40d62 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/ResizeThumb.cs @@ -0,0 +1,52 @@ +// 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.Diagnostics; +using System.Windows; +using ICSharpCode.WpfDesign.Adorners; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// Resize thumb that automatically disappears if the adornered element is too small. + /// + public sealed class ResizeThumb : DesignerThumb + { + bool checkWidth, checkHeight; + + internal ResizeThumb(bool checkWidth, bool checkHeight) + { + Debug.Assert((checkWidth && checkHeight) == false); + this.checkWidth = checkWidth; + this.checkHeight = checkHeight; + } + + protected override Size ArrangeOverride(Size arrangeBounds) + { + AdornerPanel parent = this.Parent as AdornerPanel; + if (parent != null && parent.AdornedElement != null) + { + if (checkWidth) + this.ThumbVisible = PlacementOperation.GetRealElementSize(parent.AdornedElement).Width > 14; + else if (checkHeight) + this.ThumbVisible = PlacementOperation.GetRealElementSize(parent.AdornedElement).Height > 14; + } + return base.ArrangeOverride(arrangeBounds); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/RotateThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/RotateThumb.cs similarity index 80% rename from src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/RotateThumb.cs rename to src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/RotateThumb.cs index 61a9257ee2..f1ebb83739 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/RotateThumb.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/Thumbs/RotateThumb.cs @@ -17,20 +17,12 @@ // DEALINGS IN THE SOFTWARE. using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Input; -using System.Windows.Media; -using ICSharpCode.WpfDesign.Adorners; -using ICSharpCode.WpfDesign.Designer.Extensions; namespace ICSharpCode.WpfDesign.Designer.Controls { - public class RotateThumb : ResizeThumb + public class RotateThumb : DesignerThumb { static RotateThumb() { @@ -39,7 +31,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls public RotateThumb() { - this.ResizeThumbVisible = true; + this.ThumbVisible = true; } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Converters.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Converters.cs index 101cf285bf..7167b23905 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Converters.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Converters.cs @@ -131,6 +131,26 @@ namespace ICSharpCode.WpfDesign.Designer.Converters } } + public class CollapsedWhenNull : IValueConverter + { + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "converter is immutable")] + public static readonly CollapsedWhenNull Instance = new CollapsedWhenNull(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value != null) + { + return Visibility.Visible; + } + return Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + public class FalseWhenNull : IValueConverter { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "converter is immutable")] @@ -224,7 +244,21 @@ namespace ICSharpCode.WpfDesign.Designer.Converters throw new NotImplementedException(); } } - + + public class DoubleOffsetConverter : IValueConverter + { + public double Offset { get; set; } + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (double)value + Offset; + } + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return (double)value - Offset; + } + } + public class BlackWhenTrue : IValueConverter { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "converter is immutable")] diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs index 9ddfc7eefb..907287e1be 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs @@ -32,7 +32,7 @@ using System.Windows.Threading; using ICSharpCode.WpfDesign.Adorners; using ICSharpCode.WpfDesign.Designer.Controls; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; using ICSharpCode.WpfDesign.Designer.Xaml; using ICSharpCode.WpfDesign.Extensions; using System.Linq; @@ -511,7 +511,7 @@ namespace ICSharpCode.WpfDesign.Designer PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } - + #region ContextMenu private Dictionary>> contextMenusAndEntries = new Dictionary>>(); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs index 26e7d9c46e..67f8743067 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultPlacementBehavior.cs @@ -87,8 +87,11 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions public virtual void SetPosition(PlacementInformation info) { - if (info.Operation.Type != PlacementType.Move) + if (info.Operation.Type != PlacementType.Move && info.Operation.Type != PlacementType.MovePoint) ModelTools.Resize(info.Item, info.Bounds.Width, info.Bounds.Height); + + //if (info.Operation.Type == PlacementType.MovePoint) + // ModelTools.Resize(info.Item, info.Bounds.Width, info.Bounds.Height); } public virtual bool CanLeaveContainer(PlacementOperation operation) @@ -172,5 +175,10 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } } } + + public virtual Point PlacePoint(Point point) + { + return new Point(Math.Round(point.X), Math.Round(point.Y)); + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawLineExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawLineExtension.cs new file mode 100644 index 0000000000..3fdaec59dd --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawLineExtension.cs @@ -0,0 +1,124 @@ +// 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.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign.Extensions; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + [ExtensionFor(typeof(Canvas))] + [ExtensionFor(typeof(Grid))] + public class DrawLineExtension : BehaviorExtension, IDrawItemExtension + { + private ChangeGroup changeGroup; + + DesignItem CreateItem(DesignContext context, Type componentType) + { + object newInstance = context.Services.ExtensionManager.CreateInstanceWithCustomInstanceFactory(componentType, null); + DesignItem item = context.Services.Component.RegisterComponentForDesigner(newInstance); + changeGroup = item.OpenGroup("Draw Line"); + context.Services.ExtensionManager.ApplyDefaultInitializers(item); + return item; + } + + #region IDrawItemBehavior implementation + + public bool CanItemBeDrawn(Type createItemType) + { + return createItemType == typeof(Line); + } + + public void StartDrawItem(DesignItem clickedOn, Type createItemType, IDesignPanel panel, System.Windows.Input.MouseEventArgs e) + { + var createdItem = CreateItem(panel.Context, createItemType); + + var startPoint = e.GetPosition(clickedOn.View); + var operation = PlacementOperation.TryStartInsertNewComponents(clickedOn, + new DesignItem[] { createdItem }, + new Rect[] { new Rect(startPoint.X, startPoint.Y, double.NaN, double.NaN) }, + PlacementType.AddItem); + if (operation != null) { + createdItem.Services.Selection.SetSelectedComponents(new DesignItem[] { createdItem }); + operation.Commit(); + } + + createdItem.Properties[Shape.StrokeProperty].SetValue(Brushes.Black); + createdItem.Properties[Shape.StrokeThicknessProperty].SetValue(2d); + createdItem.Properties[Shape.StretchProperty].SetValue(Stretch.None); + + var lineHandler = createdItem.Extensions.OfType().First(); + lineHandler.DragListener.ExternalStart(); + + new DrawLineMouseGesture(lineHandler, clickedOn.View, changeGroup).Start(panel, (MouseButtonEventArgs) e); + } + + #endregion + + sealed class DrawLineMouseGesture : ClickOrDragMouseGesture + { + private LineHandlerExtension l; + private ChangeGroup changeGroup; + + public DrawLineMouseGesture(LineHandlerExtension l, IInputElement relativeTo, ChangeGroup changeGroup) + { + this.l = l; + this.positionRelativeTo = relativeTo; + this.changeGroup = changeGroup; + } + + protected override void OnMouseMove(object sender, MouseEventArgs e) + { + base.OnMouseMove(sender, e); + l.DragListener.ExternalMouseMove(e); + } + + protected override void OnMouseUp(object sender, MouseButtonEventArgs e) + { + l.DragListener.ExternalStop(); + if (changeGroup != null) + { + changeGroup.Commit(); + changeGroup = null; + } + base.OnMouseUp(sender, e); + } + + protected override void OnStopped() + { + if (changeGroup != null) + { + changeGroup.Abort(); + changeGroup = null; + } + if (services.Tool.CurrentTool is CreateComponentTool) + { + services.Tool.CurrentTool = services.Tool.PointerTool; + } + base.OnStopped(); + } + + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawPathExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawPathExtension.cs new file mode 100644 index 0000000000..828af5c3e3 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawPathExtension.cs @@ -0,0 +1,173 @@ +// 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.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign.Extensions; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + [ExtensionFor(typeof(Canvas))] + [ExtensionFor(typeof(Grid))] + public class DrawPathExtension : BehaviorExtension, IDrawItemExtension + { + private ChangeGroup changeGroup; + + DesignItem CreateItem(DesignContext context, Type componentType) + { + object newInstance = context.Services.ExtensionManager.CreateInstanceWithCustomInstanceFactory(componentType, null); + DesignItem item = context.Services.Component.RegisterComponentForDesigner(newInstance); + changeGroup = item.OpenGroup("Draw Path"); + context.Services.ExtensionManager.ApplyDefaultInitializers(item); + return item; + } + + #region IDrawItemBehavior implementation + + public bool CanItemBeDrawn(Type createItemType) + { + return createItemType == typeof(Path); + } + + public void StartDrawItem(DesignItem clickedOn, Type createItemType, IDesignPanel panel, System.Windows.Input.MouseEventArgs e) + { + var createdItem = CreateItem(panel.Context, createItemType); + + var startPoint = e.GetPosition(clickedOn.View); + var operation = PlacementOperation.TryStartInsertNewComponents(clickedOn, + new DesignItem[] { createdItem }, + new Rect[] { new Rect(startPoint.X, startPoint.Y, double.NaN, double.NaN) }, + PlacementType.AddItem); + if (operation != null) { + createdItem.Services.Selection.SetSelectedComponents(new DesignItem[] { createdItem }); + operation.Commit(); + } + + createdItem.Properties[Shape.StrokeProperty].SetValue(Brushes.Black); + createdItem.Properties[Shape.StrokeThicknessProperty].SetValue(2d); + createdItem.Properties[Shape.StretchProperty].SetValue(Stretch.None); + + var figure = new PathFigure(); + var geometry = new PathGeometry(); + var geometryDesignItem = createdItem.Services.Component.RegisterComponentForDesigner(geometry); + var figureDesignItem = createdItem.Services.Component.RegisterComponentForDesigner(figure); + createdItem.Properties[Path.DataProperty].SetValue(geometry); + //geometryDesignItem.Properties[PathGeometry.FiguresProperty].CollectionElements.Add(figureDesignItem); + figureDesignItem.Properties[PathFigure.StartPointProperty].SetValue(new Point(0,0)); + + new DrawPathMouseGesture(figure, createdItem, clickedOn.View, changeGroup, this.ExtendedItem.GetCompleteAppliedTransformationToView()).Start(panel, (MouseButtonEventArgs) e); + } + + #endregion + + sealed class DrawPathMouseGesture : ClickOrDragMouseGesture + { + private ChangeGroup changeGroup; + private DesignItem newLine; + private Point sP; + private PathFigure figure; + private DesignItem geometry; + private Matrix matrix; + + public DrawPathMouseGesture(PathFigure figure, DesignItem newLine, IInputElement relativeTo, ChangeGroup changeGroup, Transform transform) + { + this.newLine = newLine; + this.positionRelativeTo = relativeTo; + this.changeGroup = changeGroup; + this.figure = figure; + this.matrix = transform.Value; + matrix.Invert(); + + sP = Mouse.GetPosition(null); + + geometry = newLine.Properties[Path.DataProperty].Value; + } + + protected override void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + e.Handled = true; + base.OnPreviewMouseLeftButtonDown(sender, e); + } + + protected override void OnMouseMove(object sender, MouseEventArgs e) + { + var delta = matrix.Transform(e.GetPosition(null) - sP); + var point = new Point(Math.Round(delta.X, 0), Math.Round(delta.Y, 0)); + + var segment = figure.Segments.LastOrDefault() as LineSegment; + if (Mouse.LeftButton == MouseButtonState.Pressed) + { + if (segment == null || segment.Point != point) + { + figure.Segments.Add(new LineSegment(point, false)); + segment = figure.Segments.Last() as LineSegment;} + } + + segment.Point = point; + + geometry.Properties[PathGeometry.FiguresProperty].SetValue(figure.ToString()); + } + + protected override void OnMouseUp(object sender, MouseButtonEventArgs e) + { + var delta = matrix.Transform(e.GetPosition(null) - sP); + var point = new Point(Math.Round(delta.X, 0), Math.Round(delta.Y,0)); + + figure.Segments.Add(new LineSegment(point, false)); + geometry.Properties[PathGeometry.FiguresProperty].SetValue(figure.ToString()); + } + + protected override void OnMouseDoubleClick(object sender, MouseButtonEventArgs e) + { + base.OnMouseDoubleClick(sender, e); + + figure.Segments.RemoveAt(figure.Segments.Count - 1); + geometry.Properties[PathGeometry.FiguresProperty].SetValue(figure.ToString()); + + if (changeGroup != null) { + changeGroup.Commit(); + changeGroup = null; + } + + Stop(); + } + + protected override void OnStopped() + { + if (changeGroup != null) { + changeGroup.Abort(); + changeGroup = null; + } + if (services.Tool.CurrentTool is CreateComponentTool) { + services.Tool.CurrentTool = services.Tool.PointerTool; + } + + newLine.ReapplyAllExtensions(); + + base.OnStopped(); + } + + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawPolyLineExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawPolyLineExtension.cs new file mode 100644 index 0000000000..7569ece5a4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DrawPolyLineExtension.cs @@ -0,0 +1,173 @@ +// 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.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign.Extensions; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + [ExtensionFor(typeof(Canvas))] + [ExtensionFor(typeof(Grid))] + public class DrawPolyLineExtension : BehaviorExtension, IDrawItemExtension + { + private ChangeGroup changeGroup; + + DesignItem CreateItem(DesignContext context, Type componentType) + { + object newInstance = context.Services.ExtensionManager.CreateInstanceWithCustomInstanceFactory(componentType, null); + DesignItem item = context.Services.Component.RegisterComponentForDesigner(newInstance); + changeGroup = item.OpenGroup("Draw Polyline"); + context.Services.ExtensionManager.ApplyDefaultInitializers(item); + return item; + } + + #region IDrawItemBehavior implementation + + public bool CanItemBeDrawn(Type createItemType) + { + return createItemType == typeof(Polyline) || createItemType == typeof(Polygon); + } + + public void StartDrawItem(DesignItem clickedOn, Type createItemType, IDesignPanel panel, System.Windows.Input.MouseEventArgs e) + { + var createdItem = CreateItem(panel.Context, createItemType); + + var startPoint = e.GetPosition(clickedOn.View); + var operation = PlacementOperation.TryStartInsertNewComponents(clickedOn, + new DesignItem[] { createdItem }, + new Rect[] { new Rect(startPoint.X, startPoint.Y, double.NaN, double.NaN) }, + PlacementType.AddItem); + if (operation != null) { + createdItem.Services.Selection.SetSelectedComponents(new DesignItem[] { createdItem }); + operation.Commit(); + } + + createdItem.Properties[Shape.StrokeProperty].SetValue(Brushes.Black); + createdItem.Properties[Shape.StrokeThicknessProperty].SetValue(2d); + createdItem.Properties[Shape.StretchProperty].SetValue(Stretch.None); + + if (createItemType == typeof(Polyline)) + createdItem.Properties[Polyline.PointsProperty].CollectionElements.Add(createdItem.Services.Component.RegisterComponentForDesigner(new Point(0,0))); + else + createdItem.Properties[Polygon.PointsProperty].CollectionElements.Add(createdItem.Services.Component.RegisterComponentForDesigner(new Point(0,0))); + + new DrawPolylineMouseGesture(createdItem, clickedOn.View, changeGroup).Start(panel, (MouseButtonEventArgs) e); + } + + #endregion + + sealed class DrawPolylineMouseGesture : ClickOrDragMouseGesture + { + private ChangeGroup changeGroup; + private DesignItem newLine; + private Point startPoint; + + public DrawPolylineMouseGesture(DesignItem newLine, IInputElement relativeTo, ChangeGroup changeGroup) + { + this.newLine = newLine; + this.positionRelativeTo = relativeTo; + this.changeGroup = changeGroup; + + startPoint = Mouse.GetPosition(null); + } + + protected override void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + e.Handled = true; + base.OnPreviewMouseLeftButtonDown(sender, e); + } + + protected override void OnMouseMove(object sender, MouseEventArgs e) + { + var delta = e.GetPosition(null) - startPoint; + var point = new Point(delta.X, delta.Y); + + if (newLine.View is Polyline) { + if (((Polyline)newLine.View).Points.Count <= 1) + ((Polyline)newLine.View).Points.Add(point); + if (Mouse.LeftButton != MouseButtonState.Pressed) + ((Polyline)newLine.View).Points.RemoveAt(((Polyline)newLine.View).Points.Count - 1); + if (((Polyline)newLine.View).Points.Last() != point) + ((Polyline)newLine.View).Points.Add(point); + } else { + if (((Polygon)newLine.View).Points.Count <= 1) + ((Polygon)newLine.View).Points.Add(point); + if (Mouse.LeftButton != MouseButtonState.Pressed) + ((Polygon)newLine.View).Points.RemoveAt(((Polygon)newLine.View).Points.Count - 1); + if (((Polygon)newLine.View).Points.Last() != point) + ((Polygon)newLine.View).Points.Add(point); + } + } + + protected override void OnMouseUp(object sender, MouseButtonEventArgs e) + { + var delta = e.GetPosition(null) - startPoint; + var point = new Point(delta.X, delta.Y); + + if (newLine.View is Polyline) + ((Polyline)newLine.View).Points.Add(point); + else + ((Polygon)newLine.View).Points.Add(point); + } + + protected override void OnMouseDoubleClick(object sender, MouseButtonEventArgs e) + { + base.OnMouseDoubleClick(sender, e); + + if (newLine.View is Polyline) { + ((Polyline)newLine.View).Points.RemoveAt(((Polyline)newLine.View).Points.Count - 1); + newLine.Properties[Polyline.PointsProperty].SetValue(string.Join(",", ((Polyline)newLine.View).Points)); + } else { + ((Polygon)newLine.View).Points.RemoveAt(((Polygon)newLine.View).Points.Count - 1); + newLine.Properties[Polygon.PointsProperty].SetValue(string.Join(",", ((Polygon)newLine.View).Points)); + } + + if (changeGroup != null) + { + changeGroup.Commit(); + changeGroup = null; + } + + Stop(); + } + + protected override void OnStopped() + { + if (changeGroup != null) { + changeGroup.Abort(); + changeGroup = null; + } + if (services.Tool.CurrentTool is CreateComponentTool) { + services.Tool.CurrentTool = services.Tool.PointerTool; + } + + newLine.ReapplyAllExtensions(); + + base.OnStopped(); + } + + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/Initializers.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/Initializers.cs index b6b4aa941b..100c1f27aa 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/Initializers.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/Initializers.cs @@ -97,16 +97,4 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions.Initializers } } } - - [ExtensionFor(typeof(Shape))] - public class ShapeInitializer : DefaultInitializer - { - public override void InitializeDefaults(DesignItem item) - { - DesignItemProperty fillProperty = item.Properties["Fill"]; - if (fillProperty.ValueOnInstance == null) { - fillProperty.SetValue(Brushes.YellowGreen); - } - } - } } 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 e4d29574c5..6a9c6242c4 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineExtensionBase.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineExtensionBase.cs @@ -87,33 +87,19 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions 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) + foreach (DesignerThumb r in resizeThumbs) { bool isVisible = resizeBehavior != null && resizeBehavior.CanPlace(extendedItemArray, PlacementType.Resize, r.Alignment); @@ -125,11 +111,11 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions /// 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) + protected PointTrackerPlacementSupport Place(ref DesignerThumb designerThumb, PlacementAlignment alignment, int index = -1) { PointTrackerPlacementSupport placement = new PointTrackerPlacementSupport(ExtendedItem.View as Shape, alignment, index); return placement; @@ -150,11 +136,11 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions protected void SetSurfaceInfo(int x, int y, string s) { - if (_text == null) - { - _text = new TextBlock(); + if (_text == null) { + _text = new TextBlock(){ FontSize = 8, FontStyle = FontStyles.Italic }; _surface.Children.Add(_text); } + AdornerPanel ap = _surface.Parent as AdornerPanel; _surface.Width = ap.Width; @@ -163,7 +149,6 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions _text.Text = s; Canvas.SetLeft(_text, x); Canvas.SetTop(_text, y); - } protected void HideSizeAndShowHandles() @@ -194,7 +179,5 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions 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 2d74352e00..374c838ccf 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineHandlerExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/LineHandlerExtension.cs @@ -17,21 +17,15 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Windows; using ICSharpCode.WpfDesign.Extensions; -using ICSharpCode.WpfDesign; using ICSharpCode.WpfDesign.Adorners; -using ICSharpCode.WpfDesign.Designer; using ICSharpCode.WpfDesign.Designer.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; -using System.Windows; using System.Windows.Controls; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Extensions { /// @@ -49,18 +43,21 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions //Size oldSize; ZoomControl zoom; - protected ResizeThumb CreateThumb(PlacementAlignment alignment, Cursor cursor) + public DragListener DragListener {get; private set;} + + protected DesignerThumb CreateThumb(PlacementAlignment alignment, Cursor cursor) { - ResizeThumb resizeThumb = new ResizeThumb { Alignment = alignment, Cursor = cursor, IsPrimarySelection = true}; - AdornerPanel.SetPlacement(resizeThumb, Place(ref resizeThumb, alignment)); + DesignerThumb designerThumb = new DesignerThumb { Alignment = alignment, Cursor = cursor, IsPrimarySelection = true}; + AdornerPanel.SetPlacement(designerThumb, Place(ref designerThumb, alignment)); - adornerPanel.Children.Add(resizeThumb); + adornerPanel.Children.Add(designerThumb); - DragListener drag = new DragListener(resizeThumb); - drag.Started += drag_Started; - drag.Changed += drag_Changed; - drag.Completed += drag_Completed; - return resizeThumb; + DragListener = new DragListener(designerThumb); + DragListener.Started += drag_Started; + DragListener.Changed += drag_Changed; + DragListener.Completed += drag_Completed; + + return designerThumb; } protected Bounds CalculateDrawing(double x, double y, double left, double top, double xleft, double xtop) @@ -95,7 +92,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } } - SetSurfaceInfo(0, 0, Math.Round((180 / Math.PI) * Math.Atan2(y, x), 0).ToString()); + 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) }; } @@ -122,28 +119,27 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } _isResizing = true; - (drag.Target as ResizeThumb).IsPrimarySelection = false; + (drag.Target as DesignerThumb).IsPrimarySelection = false; } protected virtual void drag_Changed(DragListener drag) { Line al = ExtendedItem.View as Line; - var alignment = (drag.Target as ResizeThumb).Alignment; + var alignment = (drag.Target as DesignerThumb).Alignment; var info = operation.PlacedItems[0]; double dx = 0; double dy = 0; - if (zoom != null) - { + 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) - { + if (alignment == PlacementAlignment.TopLeft) { + //normal values x = CurrentX2 - dx; y = CurrentY2 - dy; @@ -154,14 +150,13 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions xtop = CurrentTop + CurrentY2; xleft = CurrentLeft + CurrentX2; - } - else - { + } 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); @@ -169,8 +164,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions ExtendedItem.Properties.GetProperty(Line.X2Property).SetValue(position.X); ExtendedItem.Properties.GetProperty(Line.Y2Property).SetValue(position.Y); - if (operation != null) - { + if (operation != null) { var result = info.OriginalBounds; result.X = position.Left; result.Y = position.Top; @@ -180,8 +174,13 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions info.Bounds = result.Round(); operation.CurrentContainerBehavior.BeforeSetPosition(operation); operation.CurrentContainerBehavior.SetPosition(info); + +// var p = operation.CurrentContainerBehavior.PlacePoint(new Point(position.X, position.Y)); +// ExtendedItem.Properties.GetProperty(Line.X2Property).SetValue(p.X); +// ExtendedItem.Properties.GetProperty(Line.Y2Property).SetValue(p.Y); } - (drag.Target as ResizeThumb).InvalidateArrange(); + + (drag.Target as DesignerThumb).InvalidateArrange(); ResetWidthHeightProperties(); } @@ -200,13 +199,15 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } else { - if (drag.IsCanceled) changeGroup.Abort(); - else changeGroup.Commit(); + if (drag.IsCanceled) + changeGroup.Abort(); + else + changeGroup.Commit(); changeGroup = null; } _isResizing = false; - (drag.Target as ResizeThumb).IsPrimarySelection = true; + (drag.Target as DesignerThumb).IsPrimarySelection = true; HideSizeAndShowHandles(); } @@ -216,34 +217,20 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions 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[] + + resizeThumbs = new DesignerThumb[] { - CreateThumb(PlacementAlignment.TopLeft, Cursors.SizeNWSE), - CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE) + CreateThumb(PlacementAlignment.TopLeft, Cursors.Cross), + CreateThumb(PlacementAlignment.BottomRight, Cursors.Cross) }; 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/MultiPointResizeThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/MultiPointResizeThumb.cs deleted file mode 100644 index b24a1bd773..0000000000 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/MultiPointResizeThumb.cs +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Created by SharpDevelop. - * User: trubra - * Date: 2014-12-22 - * Time: 11:06 - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ -using System; -using System.Windows; -using ICSharpCode.WpfDesign.Adorners; -using ICSharpCode.WpfDesign.Designer.Controls; - -namespace ICSharpCode.WpfDesign.Designer.Extensions -{ - /// - /// Description of MultiPointResizeThumb. - /// - sealed class MultiPointResizeThumb: ResizeThumb - { - private int _index; - public int Index - { - get { return _index; } - set - { - _index = value; - PointTrackerPlacementSupport p = AdornerPlacement as PointTrackerPlacementSupport; - if (p != null) - p.Index = value; - } - } - - public void Invalidate() - { - PointTrackerPlacementSupport p = AdornerPlacement as PointTrackerPlacementSupport; - - } - - private AdornerPlacement _adornerPlacement; - - public AdornerPlacement AdornerPlacement - { - get { return _adornerPlacement; } - set { _adornerPlacement = value; } - } - - } -} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenu.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenu.xaml new file mode 100644 index 0000000000..0eea94089e --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenu.xaml @@ -0,0 +1,8 @@ + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenu.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenu.xaml.cs new file mode 100644 index 0000000000..c6b7c94417 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenu.xaml.cs @@ -0,0 +1,135 @@ +// 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.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign.Designer.themes; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + public partial class PathContextMenu + { + private DesignItem designItem; + + public PathContextMenu(DesignItem designItem) + { + this.designItem = designItem; + + SpecialInitializeComponent(); + } + + /// + /// Fixes InitializeComponent with multiple Versions of same Assembly loaded + /// + public void SpecialInitializeComponent() + { + if (!this._contentLoaded) { + this._contentLoaded = true; + Uri resourceLocator = new Uri(VersionedAssemblyResourceDictionary.GetXamlNameForType(this.GetType()), UriKind.Relative); + Application.LoadComponent(this, resourceLocator); + } + + this.InitializeComponent(); + } + + void Click_ConvertToFigures(object sender, System.Windows.RoutedEventArgs e) + { + var path = this.designItem.Component as Path; + + if (path.Data is StreamGeometry) { + var sg = path.Data as StreamGeometry; + + var pg = sg.GetFlattenedPathGeometry(); + +// foreach (var g in parts) { +// +// } + + var pgDes = designItem.Services.Component.RegisterComponentForDesigner(pg); + designItem.Properties[Path.DataProperty].SetValue(pgDes); + } + else if (path.Data is PathGeometry) { + var pg = path.Data as PathGeometry; + + var figs = pg.Figures; + + var newPg = new PathGeometry(); + var newPgDes = designItem.Services.Component.RegisterComponentForDesigner(newPg); + + foreach (var fig in figs) { + newPgDes.Properties[PathGeometry.FiguresProperty].CollectionElements.Add(FigureToDesignItem(fig)); + } + + designItem.Properties[Path.DataProperty].SetValue(newPg); + } + + } + + private DesignItem FigureToDesignItem(PathFigure pf) + { + var pfDes = designItem.Services.Component.RegisterComponentForDesigner(new PathFigure()); + + pfDes.Properties[PathFigure.StartPointProperty].SetValue(pf.StartPoint); + pfDes.Properties[PathFigure.IsClosedProperty].SetValue(pf.IsClosed); + + foreach (var s in pf.Segments) { + pfDes.Properties[PathFigure.SegmentsProperty].CollectionElements.Add(SegmentToDesignItem(s)); + } + return pfDes; + } + + private DesignItem SegmentToDesignItem(PathSegment s) + { + var sDes = designItem.Services.Component.RegisterComponentForDesigner(s.Clone()); + + if (!((PathSegment)s).IsStroked) + sDes.Properties[PathSegment.IsStrokedProperty].SetValue(((PathSegment)s).IsStroked); + if (((PathSegment)s).IsSmoothJoin) + sDes.Properties[PathSegment.IsSmoothJoinProperty].SetValue(((PathSegment)s).IsSmoothJoin); + + if (s is LineSegment) { + sDes.Properties[LineSegment.PointProperty].SetValue(((LineSegment)s).Point); + } else if (s is QuadraticBezierSegment) { + sDes.Properties[QuadraticBezierSegment.Point1Property].SetValue(((QuadraticBezierSegment)s).Point1); + sDes.Properties[QuadraticBezierSegment.Point2Property].SetValue(((QuadraticBezierSegment)s).Point2); + } else if (s is BezierSegment) { + sDes.Properties[BezierSegment.Point1Property].SetValue(((BezierSegment)s).Point1); + sDes.Properties[BezierSegment.Point2Property].SetValue(((BezierSegment)s).Point2); + sDes.Properties[BezierSegment.Point3Property].SetValue(((BezierSegment)s).Point3); + } else if (s is ArcSegment) { + sDes.Properties[ArcSegment.PointProperty].SetValue(((ArcSegment)s).Point); + sDes.Properties[ArcSegment.IsLargeArcProperty].SetValue(((ArcSegment)s).IsLargeArc); + sDes.Properties[ArcSegment.RotationAngleProperty].SetValue(((ArcSegment)s).RotationAngle); + sDes.Properties[ArcSegment.SizeProperty].SetValue(((ArcSegment)s).Size); + sDes.Properties[ArcSegment.SweepDirectionProperty].SetValue(((ArcSegment)s).SweepDirection); + } else if (s is PolyLineSegment) { + sDes.Properties[PolyLineSegment.PointsProperty].SetValue(((PolyLineSegment)s).Points); + } else if (s is PolyQuadraticBezierSegment) { + sDes.Properties[PolyQuadraticBezierSegment.PointsProperty].SetValue(((PolyQuadraticBezierSegment)s).Points); + } else if (s is PolyBezierSegment) { + sDes.Properties[PolyBezierSegment.PointsProperty].SetValue(((PolyBezierSegment)s).Points); + } + return sDes; + } + } +} + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenuExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenuExtension.cs new file mode 100644 index 0000000000..7febe8bce9 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathContextMenuExtension.cs @@ -0,0 +1,58 @@ +// 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.Windows; +using System.Windows.Controls; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; +using ICSharpCode.WpfDesign.Designer; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// + /// + [ExtensionServer(typeof(PrimarySelectionExtensionServer))] + [ExtensionFor(typeof(Path))] + [Extension(Order = 70)] + public class PathContextMenuExtension: SelectionAdornerProvider + { + DesignPanel panel; + ContextMenu contextMenu; + + protected override void OnInitialized() + { + base.OnInitialized(); + + contextMenu = new PathContextMenu(ExtendedItem); + panel = ExtendedItem.Context.Services.DesignPanel as DesignPanel; + if (panel != null) + panel.AddContextMenu(contextMenu); + } + + protected override void OnRemove() + { + if (panel != null) + panel.RemoveContextMenu(contextMenu); + + base.OnRemove(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathHandlerExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathHandlerExtension.cs new file mode 100644 index 0000000000..042d329b86 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PathHandlerExtension.cs @@ -0,0 +1,792 @@ +// 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.Windows.Markup; +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; +using System.Windows.Controls; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using ICSharpCode.WpfDesign.UIExtensions; +using DragListener = ICSharpCode.WpfDesign.Designer.Controls.DragListener; +using System.Windows.Data; +using System.ComponentModel; +using System.Globalization; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Description of PathHandlerExtension. + /// + [ExtensionFor(typeof(Path))] + internal class PathHandlerExtension : LineExtensionBase, IKeyDown, IKeyUp + { + enum PathPartConvertType + { + insertPoint, + ToLineSegment, + ToBezierSegment, + ToQuadricBezierSegment, + ToArcSegment, + } + + //A modifieable Point on the Path + protected class PathPoint : INotifyPropertyChanged + { + public PathPoint(Point point, Object @object, Object parentObject, Action setLambda, Action save, Shape shape) + { + this._point = point; + this._setLambda = setLambda; + this.Object = @object; + this.ParentObject = parentObject; + this._shape = shape; + this._save = save; + } + + private Point _point; + Action _setLambda; + Action _save; + Shape _shape; + + public void Commit() { + _save(); + } + + + public Point Point + { + get { return _point; } + set { + if (_setLambda != null) + { + _point = value; + _setLambda(value); + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs("Point")); + PropertyChanged(this, new PropertyChangedEventArgs("TranslatedPoint")); + } + } + } + } + + public Point TranslatedPoint + { + get { + if (_shape.RenderedGeometry.Transform == null) + return Point; + return _shape.RenderedGeometry.Transform.Transform(Point); + } + set { + if (_shape.RenderedGeometry.Transform == null) + Point = value; + else + Point = _shape.RenderedGeometry.Transform.Inverse.Transform(value); + } + } + + public PathPoint ParentPathPoint {get; set;} + + public Point ReferencePoint { get; private set; } + + public object Object { get; private set; } + + public object ParentObject { get; private set; } + + public int PolyLineIndex { get; set; } + + public PathPoint TargetPathPoint { get; set; } + + public event PropertyChangedEventHandler PropertyChanged; + } + + //A Thumb wich displays the Point + protected class PathThumb : PointThumb + { + public PathThumb(int index, PathPoint pathpoint) : base() + { + this.Index = index; + this.PathPoint = pathpoint; + var bnd = new Binding("TranslatedPoint") { Source = this.PathPoint, Mode=BindingMode.OneWay }; + this.SetBinding(PointProperty, bnd); + } + + public int Index { get; set; } + + public PathPoint PathPoint { get; set; } + } + + //A Converter for the RealtiveTo Point (on PolyLineSegment, ...) + protected class RelativeToPointConverter : IValueConverter + { + PathPoint pathPoint; + + public RelativeToPointConverter(PathPoint pathPoint) + { + this.pathPoint = pathPoint; + } + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var pt = (Point)value; + return pt - new Vector(pathPoint.TranslatedPoint.X, pathPoint.TranslatedPoint.Y); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + private readonly Dictionary _selectedThumbs = new Dictionary(); + private bool _isDragging; + ZoomControl _zoom; + + private List pathPoints = null; + + protected virtual Control[] BuildMenu(PathPoint pathpoint) + { + var menuList = new List(); + MenuItem menuItem = null; + + if (pathpoint.TargetPathPoint == null && (pathpoint.Object is LineSegment || pathpoint.Object is PolyLineSegment || pathpoint.Object is BezierSegment || pathpoint.Object is QuadraticBezierSegment || pathpoint.Object is ArcSegment)) { + menuItem = new MenuItem() { Header = "insert Point", HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuItem.Click += (s, e) => ConvertPart(((DependencyObject)s).TryFindParent(), PathPartConvertType.insertPoint); + menuList.Add(menuItem); + menuItem = new MenuItem() { Header = "to Line Segment", HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuItem.Click += (s, e) => ConvertPart(((DependencyObject)s).TryFindParent(), PathPartConvertType.ToLineSegment); + menuList.Add(menuItem); + menuItem = new MenuItem() {Header = "to Bezier Segment", HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuItem.Click += (s, e) => ConvertPart(((DependencyObject)s).TryFindParent(), PathPartConvertType.ToBezierSegment); + menuList.Add(menuItem); + menuItem = new MenuItem() {Header = "to Quadric Bezier Segment", HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuItem.Click += (s, e) => ConvertPart(((DependencyObject)s).TryFindParent(), PathPartConvertType.ToQuadricBezierSegment); + menuList.Add(menuItem); + menuItem = new MenuItem() { Header = "to Arc Segment", HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuItem.Click += (s, e) => ConvertPart(((DependencyObject)s).TryFindParent(), PathPartConvertType.ToArcSegment); + menuList.Add(menuItem); + menuList.Add(new Separator()); + menuItem = new MenuItem() { Header = "is Stroked", IsChecked = ((PathSegment)pathpoint.Object).IsStroked, HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuItem.Click += (s, e) => ChangeIsStroked(((DependencyObject)s).TryFindParent(), (MenuItem)s); + menuList.Add(menuItem); + menuItem = new MenuItem() { Header = "is Smooth Join", IsChecked = ((PathSegment)pathpoint.Object).IsSmoothJoin, HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuList.Add(menuItem); + } + if (pathpoint.Object is ArcSegment) { + menuItem = new MenuItem() { Header = "is large Arc", IsChecked = ((ArcSegment)pathpoint.Object).IsLargeArc, HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuList.Add(menuItem); + menuItem = new MenuItem() { Header = "Rotation Angle", IsChecked = true, HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuList.Add(menuItem); + menuItem = new MenuItem() { Header = "Clockwise SweepDirection", IsChecked = ((ArcSegment)pathpoint.Object).SweepDirection == SweepDirection.Clockwise, HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuList.Add(menuItem); + } + + if (pathpoint.Object is PathFigure) { + menuItem = new MenuItem() { Header = "is Closed", IsChecked = ((PathFigure)pathpoint.Object).IsClosed, HorizontalContentAlignment = HorizontalAlignment.Left, VerticalContentAlignment = VerticalAlignment.Center }; + menuItem.Click += (s, e) => ChangeIsClosed(((DependencyObject)s).TryFindParent(), (MenuItem)s); + menuList.Add(menuItem); + } + + if (!menuList.Any()) + return null; + + return menuList.ToArray(); + } + + #region thumb methods + protected virtual PathThumb CreateThumb(PlacementAlignment alignment, Cursor cursor, int index, PathPoint pathpoint, Transform transform) + { + var designerThumb = new PathThumb(index, pathpoint) {Cursor = cursor}; + designerThumb.OperationMenu = BuildMenu(pathpoint); + + designerThumb.InnerRenderTransform = ((Transform)transform.Inverse); + + if (pathpoint.TargetPathPoint != null) { + designerThumb.IsEllipse = true; + designerThumb.Foreground = Brushes.Blue; + + var bnd = new Binding("TranslatedPoint") { Source = pathpoint.TargetPathPoint, Mode = BindingMode.OneWay, Converter = new RelativeToPointConverter(pathpoint) }; + designerThumb.SetBinding(PathThumb.RelativeToPointProperty, bnd); + } + + AdornerPanel.SetPlacement(designerThumb, designerThumb.AdornerPlacement); + adornerPanel.Children.Add(designerThumb); + + DragListener drag = new DragListener(designerThumb); + drag.Transform = transform; + + WeakEventManager.AddHandler(designerThumb, "PreviewMouseLeftButtonDown", ResizeThumbOnMouseLeftButtonUp); + + drag.MouseDown += drag_MouseDown; + drag.Started += drag_Started; + drag.Changed += drag_Changed; + drag.Completed += drag_Completed; + return designerThumb; + } + + private void ConvertPart(PathThumb senderThumb, PathPartConvertType convertType) + { + if (senderThumb.PathPoint.ParentObject is PathFigure) + { + var pathFigure = senderThumb.PathPoint.ParentObject as PathFigure; + var pathSegment = senderThumb.PathPoint.Object as PathSegment; + + var idx = pathFigure.Segments.IndexOf(pathSegment); + + var point = senderThumb.PathPoint.Point; + + if (pathSegment is PolyLineSegment) { + var poly = pathSegment as PolyLineSegment; + var lst = poly.Points.Take(senderThumb.PathPoint.PolyLineIndex); + var lst2 = poly.Points.Skip(senderThumb.PathPoint.PolyLineIndex + 1); + var p = poly.Points[senderThumb.PathPoint.PolyLineIndex]; + pathFigure.Segments.RemoveAt(idx); + var p1 = new PolyLineSegment(); + p1.Points.AddRange(lst); + pathFigure.Segments.Insert(idx, p1); + pathSegment = new LineSegment() {Point = p}; + pathFigure.Segments.Insert(idx+1, pathSegment); + var p2 = new PolyLineSegment(); + p2.Points.AddRange(lst2); + pathFigure.Segments.Insert(idx+2, p2); + idx++; + } else if (pathSegment is PolyBezierSegment) { + //TODO + } else if (pathSegment is PolyQuadraticBezierSegment) { + //TODO + } + + pathFigure.Segments.RemoveAt(idx); + + var midp = senderThumb.PathPoint.ParentPathPoint.Point - ((senderThumb.PathPoint.ParentPathPoint.Point - point) / 2); + + PathSegment newSegment = null; + switch (convertType) + { + case PathPartConvertType.ToBezierSegment: + newSegment = new BezierSegment() { Point1 = midp - new Vector(40, 40), Point2 = midp + new Vector(-40, 40), Point3 = point }; + break; + case PathPartConvertType.ToQuadricBezierSegment: + newSegment = new QuadraticBezierSegment() { Point1 = point - new Vector(40, 40), Point2 = point }; + break; + case PathPartConvertType.ToArcSegment: + newSegment = new ArcSegment() { Point = point, Size = new Size(20, 20) }; + break; + case PathPartConvertType.insertPoint: + pathFigure.Segments.Insert(idx, pathSegment); + newSegment = new LineSegment() { Point = midp, }; + break; + default: + newSegment = new LineSegment() { Point = point }; + break; + } + + pathFigure.Segments.Insert(idx, newSegment); + } + + this.ExtendedItem.ReapplyAllExtensions(); + } + + private void ChangeIsClosed(PathThumb senderThumb, MenuItem menuItem) + { + var figure = senderThumb.PathPoint.Object as PathFigure; + figure.IsClosed = !figure.IsClosed; + menuItem.IsChecked = figure.IsClosed; + } + + private void ChangeIsStroked(PathThumb senderThumb, MenuItem menuItem) + { + var segment = senderThumb.PathPoint.Object as PathSegment; + segment.IsStroked = !segment.IsStroked; + menuItem.IsChecked = segment.IsStroked; + } + + private void ResetThumbs() + { + foreach (FrameworkElement rt in adornerPanel.Children) + { + if (rt is DesignerThumb) + (rt as DesignerThumb).IsPrimarySelection = true; + } + _selectedThumbs.Clear(); + } + + private void SelectThumb(PathThumb mprt) + { + CommitOrAbortKeyboardOperation(); + + var points = GetPoints(); + Point p = points[mprt.Index].TranslatedPoint; + _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 + var mprt = sender as PathThumb; + if (mprt != null) + { + //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; + + } + } + + protected void drag_MouseDown(DragListener drag) + { + + } + + // TODO : Remove all hide/show extensions from here. + protected void drag_Started(DragListener drag) + { + //get current thumb + var mprt = (drag.Target as PathThumb); + if (mprt != null) + { + SetOperation(); + } + } + + bool _isKeyboardMoveing; + + void SetOperation() + { + var designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; + _zoom = designPanel.TryFindParent(); + + CommitOrAbortKeyboardOperation(); + + //Move a Virtual Design Item arround... (for Snaplines, raster, ...) + //And Resfresh the Points after Positioning that Item! + //if (resizeBehavior != null) + operation = PlacementOperation.Start(extendedItemArray, PlacementType.MovePoint); +// else +// { +// changeGroup = ExtendedItem.Context.OpenGroup("Resize", extendedItemArray); +// } + _isResizing = true; + } + + void CommitOrAbortKeyboardOperation() + { + if (operation != null) { + if (!_isKeyboardMoveing) { + var op = operation; + operation = null; + op.Abort(); + } + else + CommitOperation(); + } + + _isKeyboardMoveing = false; + } + void CommitOperation() + { + if (operation != null) + { + foreach (int i in _selectedThumbs.Keys) + { + pathPoints[i].Commit(); + } + + var op = operation; + operation = null; + op.Commit(); + + _isKeyboardMoveing = false; + } +// else +// { +// if (changeGroup != null) +// changeGroup.Commit(); +// changeGroup = null; +// } + _isResizing = false; + + //Invalidate(); + } + + protected void drag_Changed(DragListener drag) + { + var mprt = drag.Target as PathThumb; + if (mprt != null) { + _isDragging = true; + MovePoints(drag.Delta.X, drag.Delta.Y); + } + } + + protected void drag_Completed(DragListener drag) + { + var mprt = drag.Target as PathThumb; + if (mprt != null) { + if (operation != null && drag.IsCanceled) { + operation.Abort(); + } else if (drag.IsCanceled) { + changeGroup.Abort(); + } + CommitOperation(); + } + } + + + + protected override void OnInitialized() + { + base.OnInitialized(); + + pathPoints = GetPoints(); + + resizeThumbs = new List(); + + var transform = this.ExtendedItem.GetCompleteAppliedTransformationToView(); + + for (int i = 0; i < pathPoints.Count; i++) { + CreateThumb(PlacementAlignment.BottomRight, Cursors.Cross, i, pathPoints[i], transform); + } + + Invalidate(); + + ResetThumbs(); + _isDragging = false; + + extendedItemArray[0] = ExtendedItem; + ExtendedItem.PropertyChanged += OnPropertyChanged; + resizeBehavior = PlacementOperation.GetPlacementBehavior(extendedItemArray); + UpdateAdornerVisibility(); + + this.ExtendedItem.Services.Selection.PrimarySelectionChanged += ExtendedItem_Services_Selection_PrimarySelectionChanged; + } + + protected override void OnRemove() + { + this.ExtendedItem.Services.Selection.PrimarySelectionChanged -= ExtendedItem_Services_Selection_PrimarySelectionChanged; + base.OnRemove(); + } + + void ExtendedItem_Services_Selection_PrimarySelectionChanged(object sender, EventArgs e) + { + if (operation != null && _isKeyboardMoveing) { + var newSelection = this.ExtendedItem.Services.Selection.SelectedItems.ToList(); + CommitOrAbortKeyboardOperation(); + this.ExtendedItem.Services.Selection.SetSelectedComponents(newSelection); + } + } + + #endregion + + List GetPoints() + { + return GetPoints(this.ExtendedItem); + } + + protected List GetPoints(DesignItem designItem) + { + var retVal = new List(); + AddGeometryPoints(retVal, ((Path)designItem.View).Data, ((Path)designItem.View), () => designItem.Properties["Data"].SetValue(((Path)designItem.View).Data.ToString())); + + return retVal; + } + + protected void AddGeometryPoints(List list, Geometry geometry, Shape shape, Action saveDesignItem) + { + if (geometry is CombinedGeometry) { + var g = geometry as CombinedGeometry; + var d = ExtendedItem.Services.Component.GetDesignItem(g); + if (d != null) + saveDesignItem = () => + { + d.Properties["Geometry1"].SetValue(((CombinedGeometry)d.Component).Geometry1); + d.Properties["Geometry2"].SetValue(((CombinedGeometry)d.Component).Geometry2); + }; + AddGeometryPoints(list, g.Geometry1, shape, saveDesignItem); + AddGeometryPoints(list, g.Geometry2, shape, saveDesignItem); + } else if (geometry is GeometryGroup) { + var gg = geometry as GeometryGroup; + foreach (var g in gg.Children.ToList()) { + AddGeometryPoints(list, g, shape, saveDesignItem); + } + } else if (geometry is StreamGeometry) { + var sg = geometry as StreamGeometry; + var pg = sg.GetFlattenedPathGeometry().Clone(); + var d = ExtendedItem.Services.Component.GetDesignItem(sg); + if (d != null) + saveDesignItem = () => + { + d.ParentProperty.SetValue(Geometry.Parse(pg.ToString())); + }; + + if (d != null) { + if (!d.ParentProperty.IsCollection) + ((DependencyObject)d.ParentProperty.DesignItem.Component).SetValue(d.ParentProperty.DependencyProperty, pg); + else { + var collection = ((DependencyObject)d.ParentProperty.DesignItem.Component) as GeometryGroup; + var i = collection.Children.IndexOf(geometry); + collection.Children.RemoveAt(i); + collection.Children.Insert(i, pg); + } + } + else + ((Path)shape).Data = pg; + AddGeometryPoints(list, pg, shape, saveDesignItem); + } else if (geometry is PathGeometry) { + var g = geometry as PathGeometry; + var d = ExtendedItem.Services.Component.GetDesignItem(g); + if (d != null) + saveDesignItem = () => + { + d.Properties["Figures"].SetValue(((PathGeometry)d.Component).Figures); + }; + if (geometry!=null) { + foreach(var figure in g.Figures) { + var dd = ExtendedItem.Services.Component.GetDesignItem(figure); + if (dd != null) + saveDesignItem = () => + { + dd.Properties["StartPoint"].SetValue(((PathFigure)dd.Component).StartPoint); + dd.Properties["Segments"].SetValue(((PathFigure)dd.Component).Segments); + }; + list.Add(new PathPoint(figure.StartPoint, figure, null, (p) => figure.StartPoint = p, saveDesignItem, shape)); + foreach (var s in figure.Segments) { + var parentp = list.Last(); + if (s is LineSegment) + { + var ds = ExtendedItem.Services.Component.GetDesignItem(s); + if (ds != null) + saveDesignItem = () => + { + ds.Properties["Point"].SetValue(((LineSegment)ds.Component).Point); + }; + list.Add(new PathPoint(((LineSegment)s).Point, s, figure, (p) => ((LineSegment)s).Point = p, saveDesignItem, shape) { ParentPathPoint = parentp }); + } + else if (s is PolyLineSegment) + { + var ds = ExtendedItem.Services.Component.GetDesignItem(s); + if (ds != null) + saveDesignItem = () => + { + ds.Properties["Points"].SetValue(((PolyLineSegment)ds.Component).Points); + }; + var poly = s as PolyLineSegment; + for (int n = 0; n < poly.Points.Count; n++) + { + var closure_n = n; + list.Add(new PathPoint(poly.Points[closure_n], s, figure, (p) => poly.Points[closure_n] = p, saveDesignItem, shape) { PolyLineIndex = closure_n, ParentPathPoint = parentp }); + parentp = list.Last(); + } + } + else if (s is BezierSegment) + { + var ds = ExtendedItem.Services.Component.GetDesignItem(s); + if (ds != null) + saveDesignItem = () => + { + ds.Properties["Point1"].SetValue(((BezierSegment)ds.Component).Point1); + ds.Properties["Point2"].SetValue(((BezierSegment)ds.Component).Point2); + ds.Properties["Point3"].SetValue(((BezierSegment)ds.Component).Point3); + }; + var pathp = new PathPoint(((BezierSegment)s).Point3, s, figure, (p) => ((BezierSegment)s).Point3 = p, saveDesignItem, shape) { ParentPathPoint = parentp }; + var previous = list.Last(); + list.Add(new PathPoint(((BezierSegment)s).Point1, s, figure, (p) => ((BezierSegment)s).Point1 = p, saveDesignItem, shape) { TargetPathPoint = previous }); + list.Add(new PathPoint(((BezierSegment)s).Point2, s, figure, (p) => ((BezierSegment)s).Point2 = p, saveDesignItem, shape) { TargetPathPoint = pathp }); + list.Add(pathp); + } + else if (s is PolyBezierSegment) + { + var ds = ExtendedItem.Services.Component.GetDesignItem(s); + if (ds != null) + saveDesignItem = () => + { + ds.Properties["Points"].SetValue(((PolyBezierSegment)ds.Component).Points); + }; + var poly = s as PolyBezierSegment; + for (int n = 0; n < poly.Points.Count; n+=3) + { + var closure_n = n; + var previous = list.Last(); + var pathp = new PathPoint(poly.Points[closure_n+2], s, figure, (p) => poly.Points[closure_n+2] = p, saveDesignItem, shape) { PolyLineIndex = closure_n+2, ParentPathPoint = parentp }; + list.Add(new PathPoint(poly.Points[closure_n], s, figure, (p) => poly.Points[closure_n] = p, saveDesignItem, shape) { PolyLineIndex = closure_n, TargetPathPoint = previous }); + list.Add(new PathPoint(poly.Points[closure_n+1], s, figure, (p) => poly.Points[closure_n+1] = p, saveDesignItem, shape) { PolyLineIndex = closure_n+1, TargetPathPoint = pathp }); + list.Add(pathp); + parentp = pathp; + } + } + else if (s is QuadraticBezierSegment) + { + var ds = ExtendedItem.Services.Component.GetDesignItem(s); + if (ds != null) + saveDesignItem = () => + { + ds.Properties["Point1"].SetValue(((QuadraticBezierSegment)ds.Component).Point1); + ds.Properties["Point2"].SetValue(((QuadraticBezierSegment)ds.Component).Point2); + }; + var pathp = new PathPoint(((QuadraticBezierSegment)s).Point2, s, figure, (p) => ((QuadraticBezierSegment)s).Point2 = p, saveDesignItem, shape) { ParentPathPoint = parentp }; + list.Add(new PathPoint(((QuadraticBezierSegment)s).Point1, s, figure, (p) => ((QuadraticBezierSegment)s).Point1 = p, saveDesignItem, shape) { TargetPathPoint = pathp }); + list.Add(pathp); + } + else if (s is PolyQuadraticBezierSegment) + { + var ds = ExtendedItem.Services.Component.GetDesignItem(s); + if (ds != null) + saveDesignItem = () => + { + ds.Properties["Points"].SetValue(((PolyQuadraticBezierSegment)ds.Component).Points); + }; + var poly = s as PolyQuadraticBezierSegment; + for (int n = 0; n < poly.Points.Count; n+=2) + { + var closure_n = n; + var previous = list.Last(); + var pathp = new PathPoint(poly.Points[closure_n+1], s, figure, (p) => poly.Points[closure_n+1] = p, saveDesignItem, shape) { PolyLineIndex = closure_n+1, ParentPathPoint = parentp }; + list.Add(new PathPoint(poly.Points[closure_n], s, figure, (p) => poly.Points[closure_n] = p, saveDesignItem, shape) { PolyLineIndex = closure_n, TargetPathPoint = pathp }); + list.Add(pathp); + parentp = pathp; + } + } + else if (s is ArcSegment) + { + var ds = ExtendedItem.Services.Component.GetDesignItem(s); + if (ds != null) + saveDesignItem = () => + { + ds.Properties["Size"].SetValue(((ArcSegment)ds.Component).Size); + }; + var arc = ((ArcSegment)s); + var pathp = new PathPoint(arc.Point, s, figure, (p) => arc.Point = p, saveDesignItem, shape) { ParentPathPoint = parentp }; + list.Add(new PathPoint(arc.Point - new Vector(arc.Size.Width, arc.Size.Height), s, figure, (p) => arc.Size = new Size(Math.Abs(arc.Point.X - p.X), Math.Abs(arc.Point.Y - p.Y)), saveDesignItem, shape) { TargetPathPoint = pathp }); + list.Add(pathp); + } + } + } + } + } else if (geometry is RectangleGeometry) { + var g = geometry as RectangleGeometry; + list.Add(new PathPoint(g.Rect.TopLeft, geometry, null, null, saveDesignItem, shape)); //(p) => g.Rect.Left = p.X)); + list.Add(new PathPoint(g.Rect.TopRight, geometry, null, null, saveDesignItem, shape)); //(p) => g.Rect.Width = p.X)); + list.Add(new PathPoint(g.Rect.BottomLeft, geometry, null, null, saveDesignItem, shape)); //(p) => g.Rect.Top = p.Y)); + list.Add(new PathPoint(g.Rect.BottomRight, geometry, null, null, saveDesignItem, shape)); //(p) => g.Rect.Height = p.Y)); + } else if (geometry is EllipseGeometry) { + var g = geometry as EllipseGeometry; + var d = ExtendedItem.Services.Component.GetDesignItem(g); + if (d != null) + saveDesignItem = () => d.Properties["Center"].SetValue(((EllipseGeometry)d.Component).Center); + list.Add(new PathPoint(g.Center, geometry, null, (p) => g.Center = p, saveDesignItem, shape)); + } else if (geometry is LineGeometry) { + var g = geometry as LineGeometry; + var d = ExtendedItem.Services.Component.GetDesignItem(g); + if (d != null) + saveDesignItem = () => + { + d.Properties["StartPoint"].SetValue(((LineGeometry)d.Component).StartPoint); + d.Properties["EndPoint"].SetValue(((LineGeometry)d.Component).EndPoint); + }; + list.Add(new PathPoint(g.StartPoint, geometry, null, (p) => g.StartPoint = p, saveDesignItem, shape)); + list.Add(new PathPoint(g.EndPoint, geometry, null, (p) => g.EndPoint = p, saveDesignItem, shape)); + } + } + + void MovePoints(double displacementX, double displacementY, bool useContainerBehavior = true) + { + var relativeTo = new Vector(operation.PlacedItems[0].Bounds.TopLeft.X, operation.PlacedItems[0].Bounds.TopLeft.Y); + + //iterate all selected points + foreach (int i in _selectedThumbs.Keys) { + Point p = pathPoints[i].TranslatedPoint; + + //x and y is calculated from the currentl point + double x = _selectedThumbs[i].X + displacementX; + double y = _selectedThumbs[i].Y + displacementY; + + p.X = x; + p.Y = y; + + if (useContainerBehavior) + p = operation.CurrentContainerBehavior.PlacePoint(p + relativeTo) - relativeTo; + + pathPoints[i].TranslatedPoint = p; + } + } + + #region IKeyDown + + public bool InvokeDefaultAction + { + get { return _selectedThumbs.Count == 0 || _selectedThumbs.Count == pathPoints.Count - 1; } + } + + int _movingDistanceX; + int _movingDistanceY; + public void KeyDownAction(object sender, KeyEventArgs e) + { + if (_selectedThumbs.Count > 0) { + if (IsArrowKey(e.Key)) { + if (operation == null) { + SetOperation(); + _isKeyboardMoveing = true; + _movingDistanceX = 0; + _movingDistanceY = 0; + } + } + + var dx1 = (e.Key == Key.Left) ? Keyboard.IsKeyDown(Key.LeftShift) ? - 10 : - 1 : 0; + var dy1 = (e.Key == Key.Up) ? Keyboard.IsKeyDown(Key.LeftShift) ? - 10 : - 1 : 0; + var dx2 = (e.Key == Key.Right) ? Keyboard.IsKeyDown(Key.LeftShift) ? + 10 : + 1 : 0; + var dy2 = (e.Key == Key.Down) ? Keyboard.IsKeyDown(Key.LeftShift) ? + 10 : + 1 : 0; + + _movingDistanceX += (dx1 + dx2); + _movingDistanceY += (dy1 + dy2); + + if (operation != null) + MovePoints(_movingDistanceX, _movingDistanceY, false); + } + } + + public void KeyUpAction(object sender, KeyEventArgs e) + { +// 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/PointTrackerPlacementSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PointTrackerPlacementSupport.cs index ec0531a386..6065dc2479 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PointTrackerPlacementSupport.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PointTrackerPlacementSupport.cs @@ -1,11 +1,21 @@ -/* - * Created by SharpDevelop. - * User: trubra - * Date: 2014-12-22 - * Time: 11:05 - * - * 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 System.Windows; using System.Windows.Shapes; @@ -15,79 +25,57 @@ using ICSharpCode.WpfDesign.Adorners; namespace ICSharpCode.WpfDesign.Designer.Extensions { public class PointTrackerPlacementSupport : AdornerPlacement - { - private Shape shape; - private PlacementAlignment alignment; - - public int Index - { - get; set; - } - public PointTrackerPlacementSupport(Shape s, PlacementAlignment align, int index) - { - shape = s; - alignment = align; - Index = index; - } - - - - public PointTrackerPlacementSupport(Shape s, PlacementAlignment align) - { - shape = s; - alignment = align; - Index = -1; - } - - /// - /// Arranges the adorner element on the specified adorner panel. - /// - public override void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize) - { - Point p = new Point(0, 0); - double thumbsize = 7; - double distance = thumbsize / 2; - if (shape as Line != null) - { - Line s = shape as Line; - double x, y; - //will give you the angle of the line if more than 180 degrees it becomes negative from - Double theta = (180 / Math.PI) * Math.Atan2(s.Y2 - s.Y1, s.X2 - s.X1); - - //this will give you the x offset from the line x point in parts of half the size of the thumb - double dx = Math.Cos(theta * (Math.PI / 180)) * distance; - - //this will give you the y offset from the line y point in parts of half the size of the thumb - double dy = Math.Sin(theta * (Math.PI / 180)) * distance; - - if (alignment == PlacementAlignment.BottomRight) - { - //x offset is linear - x = s.X2 - Math.Abs(theta) / (180 / thumbsize) + dx; - //y offset is angular - y = s.Y2 - ((.5 - Math.Sin(theta * (Math.PI / 180)) * .5) * thumbsize) + dy; - } - else - { - x = s.X1 - ((180 - Math.Abs(theta)) / (180 / thumbsize)) - dx; - y = s.Y1 - ((.5 - Math.Sin(theta * (Math.PI / 180) + Math.PI) * .5) * thumbsize) - dy; - } - p = new Point(x, y); - - } - Polygon pg = shape as Polygon; - Polyline pl = shape as Polyline; - if (pg != null || pl != null) - { - if (Index > 0) - { - p = pl != null ? pl.Points[Index] : pg.Points[Index]; + { + private Shape shape; + private PlacementAlignment alignment; - } - } - adorner.Arrange(new Rect(p, new Size(thumbsize, thumbsize))); - } + public int Index + { + get; set; + } + + public PointTrackerPlacementSupport(Shape s, PlacementAlignment align, int index) + { + shape = s; + alignment = align; + Index = index; + } + /// + /// Arranges the adorner element on the specified adorner panel. + /// + public override void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize) + { + Point p = new Point(0, 0); + double distance = 0; + if (shape is Line) + { + var s = shape as Line; + double x, y; + + if (alignment == PlacementAlignment.BottomRight) + { + x = s.X2; + y = s.Y2; + } + else + { + x = s.X1; + y = s.Y1; + } + p = new Point(x, y); + } else if (shape is Polygon) { + var pg = shape as Polygon; + p = pg.Points[Index]; + } else if (shape is Polyline) { + var pg = shape as Polyline; + p = pg.Points[Index]; + } - } + var transform = shape.RenderedGeometry.Transform; + p = transform.Transform(p); + + adorner.Arrange(new Rect(p.X - 3.5, p.Y - 3.5, 7, 7)); + } + } } 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 c9a88c0423..e4e4323273 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PolyLineHandlerExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/PolyLineHandlerExtension.cs @@ -31,14 +31,15 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.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), typeof(SkewThumbExtension) })] + [ExtensionFor(typeof(Polyline))] + [ExtensionFor(typeof(Polygon))] internal class PolyLineHandlerExtension : LineExtensionBase, IKeyDown, IKeyUp { private readonly Dictionary _selectedThumbs = new Dictionary(); @@ -46,36 +47,36 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions ZoomControl _zoom; #region thumb methods - protected ResizeThumb CreateThumb(PlacementAlignment alignment, Cursor cursor, int index) + protected DesignerThumb 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; + DesignerThumb designerThumb = new MultiPointThumb { Index = index, Alignment = alignment, Cursor = cursor, IsPrimarySelection = true }; + AdornerPlacement ap = Place(ref designerThumb, alignment, index); + (designerThumb as MultiPointThumb).AdornerPlacement = ap; - AdornerPanel.SetPlacement(resizeThumb, ap); - adornerPanel.Children.Add(resizeThumb); + AdornerPanel.SetPlacement(designerThumb, ap); + adornerPanel.Children.Add(designerThumb); - DragListener drag = new DragListener(resizeThumb); + DragListener drag = new DragListener(designerThumb); - WeakEventManager.AddHandler(resizeThumb, "PreviewMouseLeftButtonDown", ResizeThumbOnMouseLeftButtonUp); + WeakEventManager.AddHandler(designerThumb, "PreviewMouseLeftButtonDown", ResizeThumbOnMouseLeftButtonUp); drag.Started += drag_Started; drag.Changed += drag_Changed; drag.Completed += drag_Completed; - return resizeThumb; + return designerThumb; } private void ResetThumbs() { foreach (FrameworkElement rt in adornerPanel.Children) { - if (rt is ResizeThumb) - (rt as ResizeThumb).IsPrimarySelection = true; + if (rt is DesignerThumb) + (rt as DesignerThumb).IsPrimarySelection = true; } _selectedThumbs.Clear(); } - private void SelectThumb(MultiPointResizeThumb mprt) + private void SelectThumb(MultiPointThumb mprt) { PointCollection points = GetPointCollection(); Point p = points[mprt.Index]; @@ -91,7 +92,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions private void ResizeThumbOnMouseLeftButtonUp(object sender, MouseButtonEventArgs mouseButtonEventArgs) { //get current thumb - MultiPointResizeThumb mprt = sender as MultiPointResizeThumb; + MultiPointThumb mprt = sender as MultiPointThumb; if (mprt != null) { //shift+ctrl will remove selected point @@ -103,7 +104,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions PointCollection points = GetPointCollection(); //iterate thumbs to lower index of remaining thumbs - foreach (MultiPointResizeThumb m in adornerPanel.Children) + foreach (MultiPointThumb m in adornerPanel.Children) { if (m.Index > mprt.Index) m.Index--; @@ -135,7 +136,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions protected void drag_Started(DragListener drag) { //get current thumb - MultiPointResizeThumb mprt = (drag.Target as MultiPointResizeThumb); + MultiPointThumb mprt = (drag.Target as MultiPointThumb); if (mprt != null) { SetOperation(); @@ -156,30 +157,6 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions _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) @@ -203,19 +180,18 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions _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(); + if (changeGroup != null) + changeGroup.Commit(); changeGroup = null; } _isResizing = false; - ResetWidthHeightProperties(); Invalidate(); } @@ -223,7 +199,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions { PointCollection points = GetPointCollection(); - MultiPointResizeThumb mprt = drag.Target as MultiPointResizeThumb; + MultiPointThumb mprt = drag.Target as MultiPointThumb; if (mprt != null) { double dx = 0; @@ -237,12 +213,9 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions Double theta; //if one point selected snapping angle is calculated in relation to previous point - if (_selectedThumbs.Count == 1) - { + if (_selectedThumbs.Count == 1 && mprt.Index > 0) { 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 - { + } else { //if multiple points snapping angle is calculated in relation to mouse dragging angle theta = (180 / Math.PI) * Math.Atan2(dy, dx); } @@ -265,14 +238,14 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions points.Insert(mprt.Index, p); //create adorner marker - CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE, mprt.Index); + CreateThumb(PlacementAlignment.BottomRight, Cursors.Cross, 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) + if (rt is MultiPointThumb) { - MultiPointResizeThumb t = rt as MultiPointResizeThumb; + MultiPointThumb t = rt as MultiPointThumb; if (t.Index > mprt.Index) t.Index++; } @@ -301,15 +274,13 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions points = MovePoints(points, dx, dy, theta, snapAngle); } - ChangeOperation(points); - (drag.Target as ResizeThumb).InvalidateArrange(); - + (drag.Target as DesignerThumb).InvalidateArrange(); } protected void drag_Completed(DragListener drag) { - MultiPointResizeThumb mprt = drag.Target as MultiPointResizeThumb; + MultiPointThumb mprt = drag.Target as MultiPointThumb; if (mprt != null) { if (operation != null && drag.IsCanceled) @@ -332,34 +303,21 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions PointCollection points = GetPointCollection(); - if (ExtendedItem.Properties[Shape.StrokeProperty].ValueOnInstance == null) + resizeThumbs = new List(); + for (int i = 0; i < points.Count; i++) { - 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); + CreateThumb(PlacementAlignment.BottomRight, Cursors.Cross, 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 @@ -433,7 +391,6 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions 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); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/QuickOperationMenuExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/QuickOperationMenuExtension.cs index 2ca8308f66..8b291fa37c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/QuickOperationMenuExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/QuickOperationMenuExtension.cs @@ -20,6 +20,7 @@ using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; +using System.Windows.Media; using ICSharpCode.SharpDevelop.Widgets; using ICSharpCode.WpfDesign.Designer.Controls; using ICSharpCode.WpfDesign.Extensions; @@ -43,6 +44,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions base.OnInitialized(); _menu = new QuickOperationMenu(); _menu.Loaded += OnMenuLoaded; + _menu.RenderTransform = ((Transform)this.ExtendedItem.GetCompleteAppliedTransformationToView().Inverse); var placement = new RelativePlacement(HorizontalAlignment.Right, VerticalAlignment.Top) {XOffset = 7, YOffset = 3.5}; this.AddAdorners(placement, _menu); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RasterPlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RasterPlacementBehavior.cs index c5aa6e56ce..cbbfebcb76 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RasterPlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RasterPlacementBehavior.cs @@ -23,6 +23,7 @@ using System.Windows.Media; using System.Windows.Shapes; using ICSharpCode.WpfDesign.Adorners; using ICSharpCode.WpfDesign.Designer.Controls; +using System.Windows; namespace ICSharpCode.WpfDesign.Designer.Extensions { @@ -112,6 +113,30 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions operation.PlacedItems[0].Bounds = bounds; } + public override Point PlacePoint(Point point) + { + if (surface == null) + return base.PlacePoint(point); + + DesignPanel designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; + if (designPanel == null || !designPanel.UseRasterPlacement) + return base.PlacePoint(point); + + if (Keyboard.IsKeyDown(Key.LeftCtrl)) + { + surface.Children.Clear(); + rasterDrawn = false; + return base.PlacePoint(point); + } + + drawRaster(); + + point.Y = ((int)point.Y / raster) * raster; + point.X = ((int)point.X / raster) * raster; + + return point; + } + private void drawRaster() { if (!rasterDrawn) 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 26d0de1c1c..ab15835f1a 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs @@ -26,7 +26,7 @@ using ICSharpCode.WpfDesign.Adorners; using ICSharpCode.WpfDesign.Designer.Controls; using ICSharpCode.WpfDesign.Extensions; using System.Collections.Generic; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Extensions { @@ -38,7 +38,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions public sealed class ResizeThumbExtension : SelectionAdornerProvider { readonly AdornerPanel adornerPanel; - readonly ResizeThumb[] resizeThumbs; + readonly DesignerThumb[] _designerThumbs; /// An array containing this.ExtendedItem as only element readonly DesignItem[] extendedItemArray = new DesignItem[1]; IPlacementBehavior resizeBehavior; @@ -60,7 +60,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions adornerPanel.Order = AdornerOrder.Foreground; this.Adorners.Add(adornerPanel); - resizeThumbs = new ResizeThumb[] { + _designerThumbs = new DesignerThumb[] { CreateThumb(PlacementAlignment.TopLeft, Cursors.SizeNWSE), CreateThumb(PlacementAlignment.Top, Cursors.SizeNS), CreateThumb(PlacementAlignment.TopRight, Cursors.SizeNESW), @@ -72,29 +72,29 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions }; } - ResizeThumb CreateThumb(PlacementAlignment alignment, Cursor cursor) + DesignerThumb CreateThumb(PlacementAlignment alignment, Cursor cursor) { - ResizeThumb resizeThumb = new ResizeThumbImpl( cursor == Cursors.SizeNS, cursor == Cursors.SizeWE ); - resizeThumb.Cursor = cursor; - resizeThumb.Alignment = alignment; - AdornerPanel.SetPlacement(resizeThumb, Place(ref resizeThumb, alignment)); - adornerPanel.Children.Add(resizeThumb); + DesignerThumb designerThumb = new ResizeThumb( cursor == Cursors.SizeNS, cursor == Cursors.SizeWE ); + designerThumb.Cursor = cursor; + designerThumb.Alignment = alignment; + AdornerPanel.SetPlacement(designerThumb, Place(ref designerThumb, alignment)); + adornerPanel.Children.Add(designerThumb); - DragListener drag = new DragListener(resizeThumb); + DragListener drag = new DragListener(designerThumb); drag.Started += new DragHandler(drag_Started); drag.Changed += new DragHandler(drag_Changed); drag.Completed += new DragHandler(drag_Completed); - return resizeThumb; + return designerThumb; } /// /// 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 /// - /// + /// /// /// - private RelativePlacement Place(ref ResizeThumb resizeThumb,PlacementAlignment alignment) + private RelativePlacement Place(ref DesignerThumb designerThumb,PlacementAlignment alignment) { RelativePlacement placement = new RelativePlacement(alignment.Horizontal,alignment.Vertical); @@ -102,14 +102,14 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions { placement.WidthRelativeToContentWidth = 1; placement.HeightOffset = 6; - resizeThumb.Opacity = 0; + designerThumb.Opacity = 0; return placement; } if (alignment.Vertical == VerticalAlignment.Center) { placement.HeightRelativeToContentHeight = 1; placement.WidthOffset = 6; - resizeThumb.Opacity = 0; + designerThumb.Opacity = 0; return placement; } @@ -119,14 +119,10 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } Size oldSize; - ZoomControl zoom; // TODO : Remove all hide/show extensions from here. void drag_Started(DragListener drag) { - var designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; - zoom = designPanel.TryFindParent(); - /* Abort editing Text if it was editing, because it interferes with the undo stack. */ foreach(var extension in this.ExtendedItem.Extensions){ if(extension is InPlaceEditorExtension){ @@ -134,6 +130,8 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } } + drag.Transform = this.ExtendedItem.GetCompleteAppliedTransformationToView(); + oldSize = new Size(ModelTools.GetWidth(ExtendedItem.View), ModelTools.GetHeight(ExtendedItem.View)); if (resizeBehavior != null) operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); @@ -148,12 +146,14 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions { double dx = 0; double dy = 0; - var alignment = (drag.Target as ResizeThumb).Alignment; + var alignment = (drag.Target as DesignerThumb).Alignment; + + var delta = drag.Delta; - if (alignment.Horizontal == HorizontalAlignment.Left) dx = -drag.Delta.X; - if (alignment.Horizontal == HorizontalAlignment.Right) dx = drag.Delta.X; - if (alignment.Vertical == VerticalAlignment.Top) dy = -drag.Delta.Y; - if (alignment.Vertical == VerticalAlignment.Bottom) dy = drag.Delta.Y; + if (alignment.Horizontal == HorizontalAlignment.Left) dx = -delta.X; + if (alignment.Horizontal == HorizontalAlignment.Right) dx = delta.X; + if (alignment.Vertical == VerticalAlignment.Top) dy = -delta.Y; + if (alignment.Vertical == VerticalAlignment.Bottom) dy = delta.Y; var designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; @@ -164,12 +164,6 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions else dy = dx; } - - if (zoom != null) - { - dx = dx * (1 / zoom.CurrentZoom); - dy = dy * (1 / zoom.CurrentZoom); - } var newWidth = Math.Max(0, oldSize.Width + dx); var newHeight = Math.Max(0, oldSize.Height + dy); @@ -253,7 +247,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions void OnPrimarySelectionChanged(object sender, EventArgs e) { bool isPrimarySelection = this.Services.Selection.PrimarySelection == this.ExtendedItem; - foreach (ResizeThumb g in adornerPanel.Children) { + foreach (DesignerThumb g in adornerPanel.Children) { g.IsPrimarySelection = isPrimarySelection; } } @@ -261,7 +255,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions void UpdateAdornerVisibility() { FrameworkElement fe = this.ExtendedItem.View as FrameworkElement; - foreach (ResizeThumb r in resizeThumbs) { + foreach (DesignerThumb r in _designerThumbs) { bool isVisible = resizeBehavior != null && resizeBehavior.CanPlace(extendedItemArray, PlacementType.Resize, r.Alignment); r.Visibility = isVisible ? Visibility.Visible : Visibility.Hidden; } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RotateThumbExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RotateThumbExtension.cs index 3165c03781..89b39c9aaa 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RotateThumbExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RotateThumbExtension.cs @@ -52,9 +52,9 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions thumb = CreateRotateThumb(); } - ResizeThumb CreateRotateThumb() + DesignerThumb CreateRotateThumb() { - ResizeThumb rotateThumb = new RotateThumb(); + DesignerThumb rotateThumb = new RotateThumb(); rotateThumb.Cursor = Cursors.Hand; rotateThumb.Cursor = ZoomControl.GetCursor("Images/rotate.cur"); rotateThumb.Alignment = PlacementAlignment.Top; @@ -137,7 +137,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } rtTransform.Properties["Angle"].SetValue(destAngle); - ((DesignPanel) this.ExtendedItem.Services.DesignPanel).AdornerLayer.UpdateAdornersForElement(this.ExtendedItem.View, true); + ((DesignPanel) this.ExtendedItem.Services.DesignPanel).AdornerLayer.UpdateAdornersForElement(this.ExtendedItem.View, true); } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SkewThumbExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SkewThumbExtension.cs index 47c48c1434..65e9da02ce 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SkewThumbExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SkewThumbExtension.cs @@ -27,7 +27,7 @@ using ICSharpCode.WpfDesign.Adorners; using ICSharpCode.WpfDesign.Designer.Controls; using ICSharpCode.WpfDesign.Extensions; using System.Collections.Generic; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.Extensions { 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 11c142a186..9b89754c0a 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs @@ -77,7 +77,64 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions base.LeaveContainer(operation); DeleteSurface(); } - + + public override Point PlacePoint(Point point) + { + if (surface == null) + return base.PlacePoint(point); + + DesignPanel designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; + if (designPanel == null || !designPanel.UseSnaplinePlacement) + return base.PlacePoint(point); ; + + surface.Children.Clear(); + if (Keyboard.IsKeyDown(Key.LeftCtrl)) + return base.PlacePoint(point); ; + + Rect bounds = new Rect(point.X, point.Y, 0, 0); + + var horizontalInput = new List(); + var verticalInput = new List(); + + AddLines(bounds, 0, false, horizontalInput, verticalInput, null); + if (baseline.HasValue) + { + var textOffset = bounds.Top + baseline.Value; + horizontalInput.Add(new Snapline() { Group = 1, Offset = textOffset, Start = bounds.Left, End = bounds.Right }); + } + + List drawLines; + double delta; + + var newPoint = base.PlacePoint(point); + if (Snap(horizontalInput, horizontalMap, Accuracy, out drawLines, out delta)) + { + foreach (var d in drawLines) + { + DrawLine(d.Start, d.Offset + d.DrawOffset, d.End, d.Offset + d.DrawOffset); + } + + point.Y += delta; + } + else + point.Y = newPoint.Y; + + if (Snap(verticalInput, verticalMap, Accuracy, out drawLines, out delta)) + { + foreach (var d in drawLines) + { + DrawLine(d.Offset + d.DrawOffset, d.Start, d.Offset + d.DrawOffset, d.End); + } + + point.X += delta; + } + else + point.X = newPoint.X; + + + return point; + } + public override void BeforeSetPosition(PlacementOperation operation) { base.BeforeSetPosition(operation); @@ -94,21 +151,25 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions foreach (var item in operation.PlacedItems) { bounds.Union(item.Bounds); } - + var horizontalInput = new List(); var verticalInput = new List(); var info = operation.PlacedItems[0]; - - if (operation.Type == PlacementType.Resize) { + + if (operation.Type == PlacementType.Resize) + { AddLines(bounds, 0, false, horizontalInput, verticalInput, info.ResizeThumbAlignment); - } else { + } + else + { AddLines(bounds, 0, false, horizontalInput, verticalInput, null); - if (baseline.HasValue) { + if (baseline.HasValue) + { var textOffset = bounds.Top + baseline.Value; horizontalInput.Add(new Snapline() { Group = 1, Offset = textOffset, Start = bounds.Left, End = bounds.Right }); } } - + // debug //foreach (var t in horizontalMap.Concat(horizontalInput)) { // surface.Children.Add(new Line() { X1 = t.Start, X2 = t.End, Y1 = t.Offset, Y2 = t.Offset, Stroke = Brushes.Black }); @@ -117,57 +178,75 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions // surface.Children.Add(new Line() { X1 = t.Offset, X2 = t.Offset, Y1 = t.Start , Y2 = t.End, Stroke = Brushes.Black }); //} //return; - + List drawLines; double delta; - - if (Snap(horizontalInput, horizontalMap, Accuracy, out drawLines, out delta)) { - - if (operation.Type == PlacementType.Resize) { - if (info.ResizeThumbAlignment != null && info.ResizeThumbAlignment.Value.Vertical == VerticalAlignment.Top) { + + if (Snap(horizontalInput, horizontalMap, Accuracy, out drawLines, out delta)) + { + + if (operation.Type == PlacementType.Resize) + { + if (info.ResizeThumbAlignment != null && info.ResizeThumbAlignment.Value.Vertical == VerticalAlignment.Top) + { bounds.Y += delta; bounds.Height = Math.Max(0, bounds.Height - delta); - } else { + } + else + { bounds.Height = Math.Max(0, bounds.Height + delta); } info.Bounds = bounds; - } else { - foreach (var item in operation.PlacedItems) { + } + else + { + foreach (var item in operation.PlacedItems) + { var r = item.Bounds; r.Y += delta; item.Bounds = r; } } - - foreach (var d in drawLines) { + + foreach (var d in drawLines) + { DrawLine(d.Start, d.Offset + d.DrawOffset, d.End, d.Offset + d.DrawOffset); } } - - if (Snap(verticalInput, verticalMap, Accuracy, out drawLines, out delta)) { - - if (operation.Type == PlacementType.Resize) { - if (info.ResizeThumbAlignment != null && info.ResizeThumbAlignment.Value.Horizontal == HorizontalAlignment.Left) { + + if (Snap(verticalInput, verticalMap, Accuracy, out drawLines, out delta)) + { + + if (operation.Type == PlacementType.Resize) + { + if (info.ResizeThumbAlignment != null && info.ResizeThumbAlignment.Value.Horizontal == HorizontalAlignment.Left) + { bounds.X += delta; bounds.Width = Math.Max(0, bounds.Width - delta); - } else { + } + else + { bounds.Width = Math.Max(0, bounds.Width + delta); } info.Bounds = bounds; - } else { - foreach (var item in operation.PlacedItems) { + } + else + { + foreach (var item in operation.PlacedItems) + { var r = item.Bounds; r.X += delta; item.Bounds = r; } } - - foreach (var d in drawLines) { + + foreach (var d in drawLines) + { DrawLine(d.Offset + d.DrawOffset, d.Start, d.Offset + d.DrawOffset, d.End); } } } - + void CreateSurface(PlacementOperation operation) { if (ExtendedItem.Services.GetService() != null) { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TextBlockRightClickContextMenu.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TextBlockRightClickContextMenu.xaml.cs index 1b8a1f5d48..ac3ff33c9a 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TextBlockRightClickContextMenu.xaml.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TextBlockRightClickContextMenu.xaml.cs @@ -20,7 +20,7 @@ using System; using System.Linq; using System.Windows; using ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.FormatedTextEditor; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; using ICSharpCode.WpfDesign.Designer.themes; namespace ICSharpCode.WpfDesign.Designer.Extensions diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs index c5a0aba8e7..88bfe0a00b 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs @@ -26,6 +26,7 @@ using System.Windows.Documents; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Imaging; +using System.Windows.Shapes; using System.Windows.Xps.Serialization; using ICSharpCode.WpfDesign.Designer.Xaml; @@ -589,5 +590,24 @@ namespace ICSharpCode.WpfDesign.Designer operation.Commit(); } + +// public static class Path { +// +// public static PathGeometry ConvertToPathGeometry(this TextBlock textBlock) +// { +// //var ft = new FormatedText(); +// return null; +// } +// +// public static PathGeometry ConvertToPathGeometry(this Rectangle rectangle) +// { +// return null; +// } +// +// public static PathGeometry ConvertToPathGeometry(this Ellipse ellipse) +// { +// return null; +// } +// } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/OutlineView/OutlineTreeView.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/OutlineView/OutlineTreeView.cs index b15cb23b81..bd86610444 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/OutlineView/OutlineTreeView.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/OutlineView/OutlineTreeView.cs @@ -20,7 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.OutlineView { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditor.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditor.cs index 635b45a4a3..2881979631 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditor.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditor.cs @@ -51,10 +51,16 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.BrushEditor .GetProperties(BindingFlags.Static | BindingFlags.Public) .Where(p => p.PropertyType == typeof(Color)) .Select(p => new BrushItem() - { - Name = p.Name, - Brush = new SolidColorBrush((Color)p.GetValue(null, null)) - }) + { + Name = p.Name, + Brush = new SolidColorBrush((Color)p.GetValue(null, null)) + }) + .ToArray(); + + public static BrushItem[] WpfBrushes = typeof(Brushes) + .GetProperties(BindingFlags.Static | BindingFlags.Public) + .Where(p => p.PropertyType == typeof(SolidColorBrush)) + .Select(p => new BrushItem() { Name = p.Name, Brush = (Brush)p.GetValue(null, null) }) .ToArray(); SolidColorBrush solidColorBrush = new SolidColorBrush(Colors.White); @@ -176,6 +182,10 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.BrushEditor public IEnumerable AvailableBrushes { get { return SystemBrushes; } } + + public IEnumerable AvailableWpfBrushes { + get { return WpfBrushes; } + } public void MakeGradientHorizontal() { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml index 2d89ae00a2..173b84cd9a 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml @@ -7,7 +7,7 @@ xmlns:Converters="clr-namespace:ICSharpCode.WpfDesign.Designer.Converters" xmlns:PropertyGrid="clr-namespace:ICSharpCode.WpfDesign.Designer.PropertyGrid" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" - Width="395"> + Width="395" MinHeight="320"> @@ -73,7 +73,12 @@ - + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml.cs index c1cf4480be..8117ceb0ca 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml.cs @@ -43,10 +43,6 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.BrushEditor DataContext = BrushEditor; SpecialInitializeComponent(); - - SetBinding(HeightProperty, new Binding("Brush") { - Converter = HeightConverter.Instance - }); } /// @@ -64,21 +60,5 @@ namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.BrushEditor } public BrushEditor BrushEditor { get; private set; } - - class HeightConverter : IValueConverter - { - public static HeightConverter Instance = new HeightConverter(); - - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - if (value is GradientBrush) return double.NaN; - return 315; - } - - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/SolidBrushEditor.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/SolidBrushEditor.xaml index 3a5fffea09..fd74a99ec2 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/SolidBrushEditor.xaml +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/BrushEditor/SolidBrushEditor.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" x:Name="this" - Height="284"> + Height="320"> @@ -13,5 +13,10 @@ SelectedValue="{Binding Color, ElementName=this}" SelectedValuePath="Brush.Color" /> + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/FormatedTextEditor/FormatedTextEditor.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/FormatedTextEditor/FormatedTextEditor.xaml.cs index e198361c5c..4a8ddbeb0c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/FormatedTextEditor/FormatedTextEditor.xaml.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/Editors/FormatedTextEditor/FormatedTextEditor.xaml.cs @@ -24,7 +24,7 @@ using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using ICSharpCode.WpfDesign.Designer.Xaml; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; using ICSharpCode.WpfDesign.Designer.themes; namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.FormatedTextEditor diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/RootItemBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/RootItemBehavior.cs index 4b436dba98..6e429e51f0 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/RootItemBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/RootItemBehavior.cs @@ -94,5 +94,10 @@ namespace ICSharpCode.WpfDesign.Designer { throw new NotImplementedException(); } + + public Point PlacePoint(Point point) + { + return point; + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs index 3071f29e06..88469fd72f 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/CreateComponentTool.cs @@ -16,6 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Linq; using System.Windows; using System; using System.Diagnostics; @@ -155,6 +156,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services object newInstance = context.Services.ExtensionManager.CreateInstanceWithCustomInstanceFactory(componentType, null); DesignItem item = context.Services.Component.RegisterComponentForDesigner(newInstance); changeGroup = item.OpenGroup("Drop Control"); + context.Services.Component.SetDefaultPropertyValues(item); context.Services.ExtensionManager.ApplyDefaultInitializers(item); return item; } @@ -163,7 +165,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services { CreateComponentTool cct = new CreateComponentTool(createdItem); return AddItemWithCustomSize(container, cct.CreateItem(container.Context), position, size); - } + } public static bool AddItemWithDefaultSize(DesignItem container, Type createdItem, Size size) { @@ -201,13 +203,20 @@ namespace ICSharpCode.WpfDesign.Designer.Services IDesignPanel designPanel = (IDesignPanel)sender; DesignPanelHitTestResult result = designPanel.HitTest(e.GetPosition(designPanel), false, true, HitTestType.Default); if (result.ModelHit != null) { - IPlacementBehavior behavior = result.ModelHit.GetBehavior(); - if (behavior != null) { - DesignItem createdItem = CreateItem(designPanel.Context); - - new CreateComponentMouseGesture(result.ModelHit, createdItem, changeGroup).Start(designPanel, e); - // CreateComponentMouseGesture now is responsible for the changeGroup created by CreateItem() - changeGroup = null; + var darwItemBehaviors = result.ModelHit.Extensions.OfType(); + var drawItembehavior = darwItemBehaviors.FirstOrDefault(x => x.CanItemBeDrawn(componentType)); + if (drawItembehavior != null && drawItembehavior.CanItemBeDrawn(componentType)) { + drawItembehavior.StartDrawItem(result.ModelHit, componentType, designPanel, e); + } + else { + var placementBehavior = result.ModelHit.GetBehavior(); + if (placementBehavior != null) { + var createdItem = CreateItem(designPanel.Context); + + new CreateComponentMouseGesture(result.ModelHit, createdItem, changeGroup).Start(designPanel, e); + // CreateComponentMouseGesture now is responsible for the changeGroup created by CreateItem() + changeGroup = null; + } } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MouseGestureBase.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MouseGestureBase.cs index ae5cc76262..c92b1c527c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MouseGestureBase.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/MouseGestureBase.cs @@ -18,6 +18,9 @@ using System; using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Controls; using System.Windows.Input; namespace ICSharpCode.WpfDesign.Designer.Services @@ -71,6 +74,10 @@ namespace ICSharpCode.WpfDesign.Designer.Services designPanel.MouseMove += OnMouseMove; designPanel.MouseUp += OnMouseUp; designPanel.KeyDown += OnKeyDown; + designPanel.PreviewMouseLeftButtonDown += OnPreviewMouseLeftButtonDown; + designPanel.PreviewMouseLeftButtonUp += OnPreviewMouseLeftButtonUp; + designPanel.PreviewMouseRightButtonDown += OnPreviewMouseRightButtonDown; + designPanel.PreviewMouseRightButtonUp += OnPreviewMouseRightButtonUp; } void UnRegisterEvents() @@ -80,6 +87,10 @@ namespace ICSharpCode.WpfDesign.Designer.Services designPanel.MouseMove -= OnMouseMove; designPanel.MouseUp -= OnMouseUp; designPanel.KeyDown -= OnKeyDown; + designPanel.PreviewMouseLeftButtonDown -= OnPreviewMouseLeftButtonDown; + designPanel.PreviewMouseLeftButtonUp -= OnPreviewMouseLeftButtonUp; + designPanel.PreviewMouseRightButtonDown -= OnPreviewMouseRightButtonDown; + designPanel.PreviewMouseRightButtonUp -= OnPreviewMouseRightButtonUp; } void OnKeyDown(object sender, KeyEventArgs e) @@ -95,10 +106,27 @@ namespace ICSharpCode.WpfDesign.Designer.Services Stop(); } - protected virtual void OnMouseDown(object sender, MouseButtonEventArgs e) + protected virtual void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { + if (MouseButtonHelper.IsDoubleClick(sender, e)) + OnMouseDoubleClick(sender, e); } + protected virtual void OnPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { } + + protected virtual void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) + { } + + protected virtual void OnPreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e) + { } + + protected virtual void OnMouseDoubleClick(object sender, MouseButtonEventArgs e) + { } + + protected virtual void OnMouseDown(object sender, MouseButtonEventArgs e) + { } + protected virtual void OnMouseMove(object sender, MouseEventArgs e) { } @@ -119,5 +147,56 @@ namespace ICSharpCode.WpfDesign.Designer.Services protected virtual void OnStarted(MouseButtonEventArgs e) {} protected virtual void OnStopped() {} + + static class MouseButtonHelper + { + [DllImport("user32.dll")] + static extern uint GetDoubleClickTime(); + + static MouseButtonHelper() + { + k_DoubleClickSpeed = GetDoubleClickTime(); + } + + private static readonly uint k_DoubleClickSpeed; + + private const double k_MaxMoveDistance = 10; + + private static long _LastClickTicks = 0; + private static Point _LastPosition; + private static WeakReference _LastSender; + + internal static bool IsDoubleClick(object sender, MouseButtonEventArgs e) + { + Point position = e.GetPosition(null); + long clickTicks = DateTime.Now.Ticks; + long elapsedTicks = clickTicks - _LastClickTicks; + long elapsedTime = elapsedTicks / TimeSpan.TicksPerMillisecond; + bool quickClick = (elapsedTime <= k_DoubleClickSpeed ); + bool senderMatch = (_LastSender != null && sender.Equals(_LastSender.Target)); + + if (senderMatch && quickClick && Distance(position, _LastPosition) <= k_MaxMoveDistance) + { + // Double click! + _LastClickTicks = 0; + _LastSender = null; + return true; + } + + // Not a double click + _LastClickTicks = clickTicks; + _LastPosition = position; + if (!quickClick) + _LastSender = new WeakReference(sender); + return false; + } + + private static double Distance(Point pointA, Point pointB) + { + double x = pointA.X - pointB.X; + double y = pointA.Y - pointB.Y; + return Math.Sqrt(x * x + y * y); + } + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ThumbnailView/ThumbnailView.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ThumbnailView/ThumbnailView.cs index 606ae58684..876d843ce7 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ThumbnailView/ThumbnailView.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ThumbnailView/ThumbnailView.cs @@ -27,7 +27,7 @@ using System.Windows.Controls.Primitives; using System.Windows.Media; using System.Diagnostics; using ICSharpCode.WpfDesign.Designer.Controls; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Designer.ThumbnailView { 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 a02de6758b..a9daa804f8 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj @@ -85,7 +85,12 @@ + + + + + DefaultCommandsContextMenu.xaml Code @@ -93,11 +98,17 @@ - + EditStyleContextMenu.xaml + + PathContextMenu.xaml + Code + + + @@ -175,10 +186,10 @@ - + - + @@ -294,7 +305,6 @@ - @@ -310,6 +320,7 @@ Designer + Designer diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs index 17aa91f9bf..9998929502 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml sealed class XamlComponentService : IComponentService { public event EventHandler PropertyChanged; - + #region IdentityEqualityComparer sealed class IdentityEqualityComparer : IEqualityComparer { @@ -69,7 +69,17 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml _sites.TryGetValue(component, out site); return site; } - + + public void SetDefaultPropertyValues(DesignItem designItem) + { + var values = Metadata.GetDefaultPropertyValues(designItem.ComponentType); + if (values != null) { + foreach (var value in values) { + designItem.Properties[value.Key].SetValue(value.Value); + } + } + } + public DesignItem RegisterComponentForDesigner(object component) { if (component == null) { @@ -79,7 +89,8 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml } XamlDesignItem item = new XamlDesignItem(_context.Document.CreateObject(component), _context); - _sites.Add(component, item); + if (!(component is string)) + _sites.Add(component, item); if (ComponentRegistered != null) { ComponentRegistered(this, new DesignItemEventArgs(item)); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/NamescopeTest.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/NamescopeTest.cs index 09d1357a93..26d5360960 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/NamescopeTest.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/XamlDom/NamescopeTest.cs @@ -11,7 +11,7 @@ using System.Xml; using ICSharpCode.WpfDesign.XamlDom; using NUnit.Framework; using ICSharpCode.WpfDesign.Designer; -using ICSharpCode.WpfDesign.Designer.UIExtensions; +using ICSharpCode.WpfDesign.UIExtensions; namespace ICSharpCode.WpfDesign.Tests.XamlDom { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs index 01b71be2f6..42f73d18d8 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/CollectionSupport.cs @@ -21,6 +21,7 @@ using System.Diagnostics; using System.Collections; using System.ComponentModel; using System.Globalization; +using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Documents; @@ -39,11 +40,11 @@ namespace ICSharpCode.WpfDesign.XamlDom public static bool IsCollectionType(Type type) { return type != typeof(LineBreak) && ( - typeof(IList).IsAssignableFrom(type) + typeof(IList).IsAssignableFrom(type) || type.IsArray || typeof(IAddChild).IsAssignableFrom(type) || typeof(IDictionary).IsAssignableFrom(type)); - } + } /// /// Gets if the collection type can accepts items of type @@ -85,12 +86,12 @@ namespace ICSharpCode.WpfDesign.XamlDom } else if (collectionInstance is IDictionary) { object val = newElement.GetValueFor(null); object key = newElement is XamlObject ? ((XamlObject)newElement).GetXamlAttribute("Key") : null; - if (key == null || key == "") - { - if (val is Style) - key = ((Style)val).TargetType; - } - if (key == null || (key as string) == "") + if (key == null || key == "") + { + if (val is Style) + key = ((Style)val).TargetType; + } + if (key == null || (key as string) == "") key = val; ((IDictionary)collectionInstance).Add(key, val); } else { @@ -102,16 +103,24 @@ namespace ICSharpCode.WpfDesign.XamlDom } } - /// + /// /// Adds a value at the specified index in the collection. /// - public static void Insert(Type collectionType, object collectionInstance, XamlPropertyValue newElement, int index) + public static bool Insert(Type collectionType, object collectionInstance, XamlPropertyValue newElement, int index) { - collectionType.InvokeMember( - "Insert", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, - null, collectionInstance, - new object[] { index, newElement.GetValueFor(null) }, - CultureInfo.InvariantCulture); + var hasInsert = collectionType.GetMethods().Any(x => x.Name == "Insert"); + + if (hasInsert) { + collectionType.InvokeMember( + "Insert", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, + null, collectionInstance, + new object[] { index, newElement.GetValueFor(null) }, + CultureInfo.InvariantCulture); + + return true; + } + + return false; } /// @@ -121,7 +130,7 @@ namespace ICSharpCode.WpfDesign.XamlDom internal static bool TryInsert(Type collectionType, object collectionInstance, XamlPropertyValue newElement, int index) { try { - Insert(collectionType, collectionInstance, newElement, index); + return Insert(collectionType, collectionInstance, newElement, index); } catch (MissingMethodException) { return false; } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs index d408c95746..b4be953816 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs @@ -203,8 +203,10 @@ namespace ICSharpCode.WpfDesign.XamlDom ResetInternal(); propertyValue = value; - propertyValue.ParentProperty = this; - propertyValue.AddNodeTo(this); + if (propertyValue != null) { + propertyValue.ParentProperty = this; + propertyValue.AddNodeTo(this); + } UpdateValueOnInstance(); ParentObject.OnPropertyChanged(this); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs index 287f8833da..b47a73daf6 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs @@ -22,7 +22,11 @@ using System.ComponentModel; using System.Diagnostics; using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using ICSharpCode.WpfDesign.UIExtensions; using ICSharpCode.WpfDesign.Extensions; +using System.Linq; namespace ICSharpCode.WpfDesign { @@ -131,9 +135,7 @@ namespace ICSharpCode.WpfDesign /// public IEnumerable Extensions { get { - foreach (ExtensionEntry entry in _extensions) { - yield return entry.Extension; - } + return _extensions.Select(x => x.Extension).ToList(); } } @@ -196,6 +198,17 @@ namespace ICSharpCode.WpfDesign }); } } + + public void ReapplyAllExtensions() + { + var manager = this.Services.GetService(); + + foreach (var e in this._extensions.ToList()) { + ApplyUnapplyExtensionServer(manager, false, e.Server); + ApplyUnapplyExtensionServer(manager, true, e.Server); + } + } + #endregion #region Manage behavior @@ -279,5 +292,24 @@ namespace ICSharpCode.WpfDesign /// Creates a copy of this design item. /// public abstract DesignItem Clone(); + + public Transform GetCompleteAppliedTransformationToView() + { + var retVal = new TransformGroup(); + var v = this.View as Visual; + while (v != null) { + var fe = v as FrameworkElement; + if (fe != null && fe.LayoutTransform != null) + retVal.Children.Add(fe.LayoutTransform); + if (fe != null && fe.RenderTransform != null) + retVal.Children.Add(fe.RenderTransform); + if (v is ContainerVisual && ((ContainerVisual)v).Transform != null) { + retVal.Children.Add(((ContainerVisual)v).Transform); + } + v = v.TryFindParent(true); + } + + return retVal; + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DrawItemExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DrawItemExtension.cs new file mode 100644 index 0000000000..a97dffafaa --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DrawItemExtension.cs @@ -0,0 +1,35 @@ +// 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 System.Windows.Input; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Behavior interface implemented by container elements to support resizing + /// drawing new Elements + /// + public interface IDrawItemExtension + { + bool CanItemBeDrawn(Type createItemType); + void StartDrawItem(DesignItem clickedOn, Type createItemType, IDesignPanel panel, MouseEventArgs e); + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs index 359a4823a0..ca4509c64f 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs @@ -45,6 +45,8 @@ namespace ICSharpCode.WpfDesign // Why not per-design context (as a service?) static Dictionary> standardValues = new Dictionary>(); + static Dictionary> standardPropertyValues = new Dictionary>(); + /// /// Registers a set of standard values for a by using the /// public static properties of the type . @@ -321,11 +323,39 @@ namespace ICSharpCode.WpfDesign if (defaultSizes.TryGetValue(t, out s)) { return s; } - t = checkBasetype ? t.BaseType : null; + t = checkBasetype ? t.BaseType : null; } } return null; } + + /// + /// Registers a default Property Value wich should be used + /// + public static void AddDefaultPropertyValue(Type t, DependencyProperty p, object value) + { + lock (standardPropertyValues) + { + if (!standardPropertyValues.ContainsKey(t)) + standardPropertyValues.Add(t, new Dictionary()); + + standardPropertyValues[t][p] = value; + } + } + + /// + /// Gets Default Propertie Values for a type + /// + public static Dictionary GetDefaultPropertyValues(Type t) + { + lock (standardPropertyValues) + { + if (standardPropertyValues.ContainsKey(t)) + return standardPropertyValues[t]; + + return null; + } + } } /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs index f34341e7bb..f75446dc5b 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs @@ -78,6 +78,11 @@ namespace ICSharpCode.WpfDesign /// Let the placed children enter this container. /// void EnterContainer(PlacementOperation operation); + + /// + /// Place Point. + /// + Point PlacePoint(Point point); } /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs index e47d8b855c..2f292195bb 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs @@ -25,6 +25,12 @@ namespace ICSharpCode.WpfDesign /// public sealed class PlacementType { + /// + /// Placement is done by Moving a inner Point (for Example on Path, Line, ...) + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly PlacementType MovePoint = Register("MovePoint"); + /// /// Placement is done by resizing an element in a drag'n'drop operation. /// @@ -51,10 +57,10 @@ namespace ICSharpCode.WpfDesign public static readonly PlacementType Delete = Register("Delete"); /// - /// Inserting from Cliboard - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] - public static readonly PlacementType PasteItem = Register("PasteItem"); + /// Inserting from Cliboard + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly PlacementType PasteItem = Register("PasteItem"); readonly string name; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs index 2a3a41cebf..93f1e9d561 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs @@ -129,6 +129,9 @@ namespace ICSharpCode.WpfDesign /// Property Changed event EventHandler PropertyChanged; + + /// Set's default Property Values as defined in Metadata + void SetDefaultPropertyValues(DesignItem designItem); } #endregion diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/UIExtensions/UIHelpers.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/UIExtensions/UIHelpers.cs similarity index 77% rename from src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/UIExtensions/UIHelpers.cs rename to src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/UIExtensions/UIHelpers.cs index 23f8b8f152..eaffed93ae 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/UIExtensions/UIHelpers.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/UIExtensions/UIHelpers.cs @@ -23,37 +23,39 @@ using System.Text; using System.Windows; using System.Windows.Media; -namespace ICSharpCode.WpfDesign.Designer.UIExtensions +namespace ICSharpCode.WpfDesign.UIExtensions { public static class UIHelpers { - public static DependencyObject GetParentObject(this DependencyObject child) + public static DependencyObject GetParentObject(this DependencyObject child, bool searchCompleteVisualTree) { if (child == null) return null; - var contentElement = child as ContentElement; - if (contentElement != null) - { - DependencyObject parent = ContentOperations.GetParent(contentElement); - if (parent != null) return parent; - - var fce = contentElement as FrameworkContentElement; - return fce != null ? fce.Parent : null; - } - - var frameworkElement = child as FrameworkElement; - if (frameworkElement != null) - { - DependencyObject parent = frameworkElement.Parent; - if (parent != null) return parent; + if (!searchCompleteVisualTree) { + var contentElement = child as ContentElement; + if (contentElement != null) + { + DependencyObject parent = ContentOperations.GetParent(contentElement); + if (parent != null) return parent; + + var fce = contentElement as FrameworkContentElement; + return fce != null ? fce.Parent : null; + } + + var frameworkElement = child as FrameworkElement; + if (frameworkElement != null) + { + DependencyObject parent = frameworkElement.Parent; + if (parent != null) return parent; + } } return VisualTreeHelper.GetParent(child); } - public static T TryFindParent(this DependencyObject child) where T : DependencyObject + public static T TryFindParent(this DependencyObject child, bool searchCompleteVisualTree = false) where T : DependencyObject { - DependencyObject parentObject = GetParentObject(child); + DependencyObject parentObject = GetParentObject(child, searchCompleteVisualTree); if (parentObject == null) return null; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj index ebc325f1c0..980bbeff25 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj @@ -73,6 +73,7 @@ + @@ -115,8 +116,12 @@ + + + + \ No newline at end of file