diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/AdornerLayer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/AdornerLayer.cs index f3ad95c10b..caef54e20c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/AdornerLayer.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/AdornerLayer.cs @@ -221,11 +221,11 @@ namespace ICSharpCode.WpfDesign.Designer.Controls protected override Size ArrangeOverride(Size finalSize) { - foreach (AdornerPanel adorner in this.Children) { - adorner.Arrange(new Rect(new Point(0, 0), adorner.DesiredSize)); + foreach (AdornerPanel adorner in this.Children) { if (adorner.AdornedElement.IsDescendantOf(_designPanel)) { adorner.RenderTransform = (Transform)adorner.AdornedElement.TransformToAncestor(_designPanel); } + adorner.Arrange(new Rect(new Point(0, 0), adorner.DesiredSize)); } return finalSize; } 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 3869f3c036..3958c4e123 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PanelMoveAdorner.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/PanelMoveAdorner.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { e.Handled = true; - item.Services.Selection.SetSelectedComponents(new DesignItem [] { item }, SelectionTypes.Auto); + //item.Services.Selection.SetSelectedComponents(new DesignItem [] { item }, SelectionTypes.Auto); new DragMoveMouseGesture(item, false).Start(item.Services.DesignPanel, e); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPositionExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPositionExtension.cs index b61374636b..2d919353a3 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPositionExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPositionExtension.cs @@ -28,7 +28,7 @@ using ICSharpCode.WpfDesign.Extensions; namespace ICSharpCode.WpfDesign.Designer.Extensions { [ExtensionFor(typeof(FrameworkElement))] - [ExtensionServer(typeof(PrimarySelectionExtensionServer))] + [ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))] public class CanvasPositionExtension : AdornerProvider { private MarginHandle[] _handles; 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 574112516b..2ca8308f66 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/QuickOperationMenuExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/QuickOperationMenuExtension.cs @@ -31,6 +31,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions /// /// Extends the Quick operation menu for the designer. /// + [ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))] [ExtensionFor(typeof (FrameworkElement))] class QuickOperationMenuExtension : PrimarySelectionAdornerProvider { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RenderTransformOriginExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RenderTransformOriginExtension.cs index 53ba6a4c56..86f105f55d 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RenderTransformOriginExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RenderTransformOriginExtension.cs @@ -32,6 +32,7 @@ using System.Windows.Media; namespace ICSharpCode.WpfDesign.Designer.Extensions { + [ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))] [ExtensionFor(typeof(FrameworkElement))] public class RenderTransformOriginExtension : SelectionAdornerProvider { 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 c068428963..c25bad2de3 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs @@ -32,6 +32,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions /// /// The resize thumb around a component. /// + [ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))] [ExtensionFor(typeof(FrameworkElement))] public sealed class ResizeThumbExtension : SelectionAdornerProvider { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickContextMenuExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickContextMenuExtension.cs index 2de65cf3aa..20dd2adacd 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickContextMenuExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickContextMenuExtension.cs @@ -30,6 +30,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions /// /// /// + [ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))] [ExtensionFor(typeof(UIElement))] public sealed class RightClickContextMenuExtension : PrimarySelectionAdornerProvider { 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 9b3d297dd0..63e7e70d68 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RotateThumbExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RotateThumbExtension.cs @@ -32,6 +32,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions /// /// The resize thumb around a component. /// + [ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))] [ExtensionFor(typeof(FrameworkElement))] public sealed class RotateThumbExtension : SelectionAdornerProvider { @@ -41,6 +42,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions readonly DesignItem[] extendedItemArray = new DesignItem[1]; IPlacementBehavior resizeBehavior; PlacementOperation operation; + private AdornerLayer _adornerLayer; public RotateThumbExtension() { @@ -64,6 +66,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions DragListener drag = new DragListener(rotateThumb); drag.Started += drag_Rotate_Started; drag.Changed += drag_Rotate_Changed; + drag.Completed += drag_Rotate_Completed; return rotateThumb; } @@ -75,10 +78,11 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions private RotateTransform rotateTransform; private double initialAngle; private DesignItem rtTransform; - private double angle; - + private void drag_Rotate_Started(DragListener drag) { + _adornerLayer = this.adornerPanel.TryFindParent(); + var designerItem = this.ExtendedItem.Component as FrameworkElement; this.parent = VisualTreeHelper.GetParent(designerItem) as UIElement; this.centerPoint = designerItem.TranslatePoint( @@ -135,10 +139,16 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value; } rtTransform.Properties["Angle"].SetValue(destAngle); - this.angle = destAngle * Math.PI / 180.0; + + _adornerLayer.UpdateAdornersForElement(this.ExtendedItem.View, true); } } + void drag_Rotate_Completed(ICSharpCode.WpfDesign.Designer.Controls.DragListener drag) + { + operation.Commit(); + } + #endregion protected override void OnInitialized() @@ -154,9 +164,6 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions var designerItem = this.ExtendedItem.Component as FrameworkElement; this.rotateTransform = designerItem.RenderTransform as RotateTransform; - - if (rotateTransform != null) - angle = rotateTransform.Angle; } void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SkewThumbExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SkewThumbExtension.cs new file mode 100644 index 0000000000..ad6839044e --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SkewThumbExtension.cs @@ -0,0 +1,248 @@ +// 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.Diagnostics; +using System.Windows; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Designer.Controls; +using ICSharpCode.WpfDesign.Extensions; +using System.Collections.Generic; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + [ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))] + [ExtensionFor(typeof(FrameworkElement))] + public sealed class SkewThumbExtension : SelectionAdornerProvider + { + readonly AdornerPanel adornerPanel; + readonly DesignItem[] extendedItemArray = new DesignItem[1]; + + private AdornerLayer _adornerLayer; + + public SkewThumbExtension() + { + adornerPanel = new AdornerPanel(); + adornerPanel.Order = AdornerOrder.BeforeForeground; + this.Adorners.Add(adornerPanel); + } + + #region Skew + + private Point startPoint; + private UIElement parent; + private SkewTransform skewTransform; + private double skewX; + private double skewY; + private DesignItem rtTransform; + private Thumb thumb1; + private Thumb thumb2; + PlacementOperation operation; + + private void dragX_Started(DragListener drag) + { + _adornerLayer = this.adornerPanel.TryFindParent(); + + var designerItem = this.ExtendedItem.Component as FrameworkElement; + this.parent = VisualTreeHelper.GetParent(designerItem) as UIElement; + + startPoint = Mouse.GetPosition(this.parent); + + if (this.skewTransform == null) + { + this.skewX = 0; + this.skewY = 0; + } + else + { + this.skewX = this.skewTransform.AngleX; + this.skewY = this.skewTransform.AngleY; + } + + rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value; + + operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); + } + + private void dragX_Changed(DragListener drag) + { + Point currentPoint = Mouse.GetPosition(this.parent); + Vector deltaVector = Point.Subtract(currentPoint, this.startPoint); + + var destAngle = (-0.5*deltaVector.X) + skewX; + + if (destAngle == 0 && skewY == 0) + { + this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformProperty).Reset(); + rtTransform = null; + skewTransform = null; + } + else + { + if (rtTransform == null) + { + if (!this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformOriginProperty).IsSet) { + this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformOriginProperty).SetValue(new Point(0.5,0.5)); + } + + if (this.skewTransform == null) + this.skewTransform = new SkewTransform(0, 0); + this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformProperty).SetValue(skewTransform); + rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value; + } + rtTransform.Properties["AngleX"].SetValue(destAngle); + } + + _adornerLayer.UpdateAdornersForElement(this.ExtendedItem.View, true); + } + + void dragX_Completed(ICSharpCode.WpfDesign.Designer.Controls.DragListener drag) + { + operation.Commit(); + } + + private void dragY_Started(DragListener drag) + { + _adornerLayer = this.adornerPanel.TryFindParent(); + + var designerItem = this.ExtendedItem.Component as FrameworkElement; + this.parent = VisualTreeHelper.GetParent(designerItem) as UIElement; + + startPoint = Mouse.GetPosition(this.parent); + + if (this.skewTransform == null) + { + this.skewX = 0; + this.skewY = 0; + } + else + { + this.skewX = this.skewTransform.AngleX; + this.skewY = this.skewTransform.AngleY; + } + + rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value; + + operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); + } + + private void dragY_Changed(DragListener drag) + { + Point currentPoint = Mouse.GetPosition(this.parent); + Vector deltaVector = Point.Subtract(currentPoint, this.startPoint); + + var destAngle = (-0.5*deltaVector.Y) + skewY; + + if (destAngle == 0 && skewX == 0) + { + this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformProperty).Reset(); + rtTransform = null; + skewTransform = null; + } + else + { + if (rtTransform == null) + { + if (!this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformOriginProperty).IsSet) + { + this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformOriginProperty).SetValue(new Point(0.5, 0.5)); + } + + if (this.skewTransform == null) + this.skewTransform = new SkewTransform(0, 0); + this.ExtendedItem.Properties.GetProperty(FrameworkElement.RenderTransformProperty).SetValue(skewTransform); + rtTransform = this.ExtendedItem.Properties[FrameworkElement.RenderTransformProperty].Value; + } + rtTransform.Properties["AngleY"].SetValue(destAngle); + } + + _adornerLayer.UpdateAdornersForElement(this.ExtendedItem.View, true); + } + + void dragY_Completed(ICSharpCode.WpfDesign.Designer.Controls.DragListener drag) + { + operation.Commit(); + } + + #endregion + + protected override void OnInitialized() + { + + if (this.ExtendedItem.Component is WindowClone) + return; + base.OnInitialized(); + + extendedItemArray[0] = this.ExtendedItem; + this.ExtendedItem.PropertyChanged += OnPropertyChanged; + + var designerItem = this.ExtendedItem.Component as FrameworkElement; + this.skewTransform = designerItem.RenderTransform as SkewTransform; + + if (skewTransform != null) + { + skewX = skewTransform.AngleX; + skewY = skewTransform.AngleY; + } + + thumb1 = new Thumb() { Cursor = Cursors.ScrollWE, Height = 14, Width = 4, Opacity = 1 }; + thumb2 = new Thumb() { Cursor = Cursors.ScrollNS, Width = 14, Height = 4, Opacity = 1 }; + + OnPropertyChanged(null, null); + + adornerPanel.Children.Add(thumb1); + adornerPanel.Children.Add(thumb2); + + DragListener drag1 = new DragListener(thumb1); + drag1.Started += dragX_Started; + drag1.Changed += dragX_Changed; + drag1.Completed += dragX_Completed; + DragListener drag2 = new DragListener(thumb2); + drag2.Started += dragY_Started; + drag2.Changed += dragY_Changed; + drag2.Completed += dragY_Completed; + } + + void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + if (sender == null || e.PropertyName == "Width" || e.PropertyName == "Height") { + AdornerPanel.SetPlacement(thumb1, + new RelativePlacement(HorizontalAlignment.Center, VerticalAlignment.Top) { + YOffset = 0, + XOffset = -1 * ((FrameworkElement)ExtendedItem.View).ActualWidth / 4 + }); + + AdornerPanel.SetPlacement(thumb2, + new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Center) { + YOffset = -1 * ((FrameworkElement)ExtendedItem.View).ActualHeight / 4, + XOffset = 0 + }); + } + } + + protected override void OnRemove() + { + this.ExtendedItem.PropertyChanged -= OnPropertyChanged; + base.OnRemove(); + } + } +} 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 80a3c0f2fe..9a30964556 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SnaplinePlacementBehavior.cs @@ -41,51 +41,51 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions List horizontalMap; List verticalMap; double? baseline; - + public const double Accuracy = 5; public const double Margin = 8; - + public override void BeginPlacement(PlacementOperation operation) { base.BeginPlacement(operation); CreateSurface(operation); } - + public override void EndPlacement(PlacementOperation operation) { base.EndPlacement(operation); DeleteSurface(); } - + public override void EnterContainer(PlacementOperation operation) { base.EnterContainer(operation); CreateSurface(operation); } - + public override void LeaveContainer(PlacementOperation operation) { base.LeaveContainer(operation); DeleteSurface(); } - + public override void BeforeSetPosition(PlacementOperation operation) { base.BeforeSetPosition(operation); if (surface == null) return; - + DesignPanel designPanel = ExtendedItem.Services.DesignPanel as DesignPanel; if (designPanel == null || !designPanel.UseSnaplinePlacement) return; surface.Children.Clear(); if (Keyboard.IsKeyDown(Key.LeftCtrl)) return; - + Rect bounds = Rect.Empty; foreach (var item in operation.PlacedItems) { bounds.Union(item.Bounds); } - + var horizontalInput = new List(); var verticalInput = new List(); var info = operation.PlacedItems[0]; @@ -99,7 +99,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions 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 }); @@ -108,12 +108,12 @@ 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.Vertical == VerticalAlignment.Top) { bounds.Y += delta; @@ -129,14 +129,14 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions item.Bounds = r; } } - + foreach (var d in drawLines) { DrawLine(d.Start, d.Offset, d.End, d.Offset); } } - + if (Snap(verticalInput, verticalMap, Accuracy, out drawLines, out delta)) { - + if (operation.Type == PlacementType.Resize) { if (info.ResizeThumbAlignment.Horizontal == HorizontalAlignment.Left) { bounds.X += delta; @@ -158,52 +158,77 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } } } - + void CreateSurface(PlacementOperation operation) { if (ExtendedItem.Services.GetService() != null) { - + surface = new Canvas(); adornerPanel = new AdornerPanel(); adornerPanel.SetAdornedElement(ExtendedItem.View, ExtendedItem); AdornerPanel.SetPlacement(surface, AdornerPlacement.FillContent); adornerPanel.Children.Add(surface); ExtendedItem.Services.DesignPanel.Adorners.Add(adornerPanel); - + BuildMaps(operation); - + if (operation.Type != PlacementType.Resize && operation.PlacedItems.Count == 1) { baseline = GetBaseline(operation.PlacedItems[0].Item.View); } } } - + + private IEnumerable AllDesignItems(DesignItem designItem = null) + { + if (designItem == null) + { + designItem = this.ExtendedItem.Services.DesignPanel.Context.RootItem; + yield return designItem; + if (designItem.ContentProperty.Value != null) { + yield return designItem.ContentProperty.Value; + designItem = designItem.ContentProperty.Value; + } + } + + if (designItem.ContentProperty != null && designItem.ContentProperty.IsCollection) + foreach (var collectionElement in designItem.ContentProperty.CollectionElements) + { + yield return collectionElement; + + foreach (var el in AllDesignItems(collectionElement)) + { + yield return el; + } + } + } + void BuildMaps(PlacementOperation operation) { horizontalMap = new List(); verticalMap = new List(); - + var containerRect = new Rect(0, 0, ModelTools.GetWidth(ExtendedItem.View), ModelTools.GetHeight(ExtendedItem.View)); AddLines(containerRect, -Margin, false); - + AddLines(containerRect, 0, false); - foreach (var item in ExtendedItem.ContentProperty.CollectionElements - .Except(operation.PlacedItems.Select(f => f.Item))) - { - var bounds = GetPosition(operation, item); - - AddLines(bounds, 0, false); - AddLines(bounds, Margin, true); - AddBaseline(item, bounds, horizontalMap); + foreach (var item in AllDesignItems() /* ExtendedItem.ContentProperty.CollectionElements */ + .Except(operation.PlacedItems.Select(f => f.Item))) { + if (item != null) { + var bounds = GetPosition(operation, item); + + AddLines(bounds, 0, false); + AddLines(bounds, Margin, true); + AddBaseline(item, bounds, horizontalMap); + } } } - + void AddLines(Rect r, double inflate, bool requireOverlap) { AddLines(r, inflate, requireOverlap, horizontalMap, verticalMap, null); } - + void AddLines(Rect r, double inflate, bool requireOverlap, List h, List v, PlacementAlignment? filter) { Rect r2 = r; @@ -217,8 +242,14 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left - 1, Start = r.Top, End = r.Bottom }); if (filter == null || filter.Value.Horizontal == HorizontalAlignment.Right) v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Right - 1, Start = r.Top, End = r.Bottom }); + + if (filter == null) + { + h.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Top + Math.Abs((r2.Top - r2.Bottom) / 2), Start = r.Left, End = r.Right }); + v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left + Math.Abs((r2.Left - r2.Right) / 2), Start = r.Top, End = r.Bottom }); + } } - + void AddBaseline(DesignItem item, Rect bounds, List list) { var baseline = GetBaseline(item.View); @@ -227,7 +258,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions list.Add(new Snapline() { Group = 1, Offset = textOffset, Start = bounds.Left, End = bounds.Right }); } } - + void DeleteSurface() { if (surface != null) { @@ -238,7 +269,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions verticalMap = null; } } - + void DrawLine(double x1, double y1, double x2, double y2) { var line1 = new Line() { @@ -250,7 +281,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions Stroke = Brushes.White }; surface.Children.Add(line1); - + var line2 = new Line() { X1 = x1, Y1 = y1, @@ -263,7 +294,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions }; surface.Children.Add(line2); } - + //TODO: GlyphRun must be used static double? GetBaseline(UIElement element) { var textBox = element as TextBox; @@ -274,21 +305,21 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions var textBlock = element as TextBlock; if (textBlock != null) return textBlock.TranslatePoint(new Point(0, textBlock.ActualHeight), element).Y; - + return null; } - + static bool Snap(List input, List map, double accuracy, - out List drawLines, out double delta) + out List drawLines, out double delta) { delta = double.MaxValue; drawLines = null; - + foreach (var inputLine in input) { foreach (var mapLine in map) { if (Math.Abs(mapLine.Offset - inputLine.Offset) <= accuracy) { if (!inputLine.RequireOverlap && !mapLine.RequireOverlap || - Math.Max(inputLine.Start, mapLine.Start) < Math.Min(inputLine.End, mapLine.End)) + Math.Max(inputLine.Start, mapLine.Start) < Math.Min(inputLine.End, mapLine.End)) { if (mapLine.Group == inputLine.Group) delta = mapLine.Offset - inputLine.Offset; @@ -296,10 +327,10 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } } } - + if (delta == double.MaxValue) return false; var offsetDict = new Dictionary(); - + foreach (var inputLine in input) { inputLine.Offset += delta; foreach (var mapLine in map) { @@ -318,11 +349,11 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } } } - + drawLines = offsetDict.Values.ToList(); return true; } - + [DebuggerDisplay("Snapline: {Offset}")] class Snapline { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs index e19a19ac27..c8220c2e32 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs @@ -32,16 +32,10 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions { /// - /// The drag handle displayed for panels. + /// The drag handle displayed for Framework Elements /// - [ExtensionServer(typeof(PrimarySelectionExtensionServer))] - [ExtensionFor(typeof(Panel))] - [ExtensionFor(typeof(Image))] - [ExtensionFor(typeof(MediaElement))] - [ExtensionFor(typeof(ItemsControl))] - [ExtensionFor(typeof(Border))] - [ExtensionFor(typeof(Viewbox))] - [ExtensionFor(typeof(ContentControl))] + [ExtensionServer(typeof(OnlyOneItemSelectedExtensionServer))] + [ExtensionFor(typeof(FrameworkElement))] public class TopLeftContainerDragHandle : AdornerProvider { /// @@ -50,9 +44,9 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions ContainerDragHandle rect = new ContainerDragHandle(); rect.PreviewMouseDown += delegate(object sender, MouseButtonEventArgs e) { - Services.Selection.SetSelectedComponents(new DesignItem[] { this.ExtendedItem }, SelectionTypes.Auto); + //Services.Selection.SetSelectedComponents(new DesignItem[] { this.ExtendedItem }, SelectionTypes.Auto); new DragMoveMouseGesture(this.ExtendedItem, false).Start(this.ExtendedItem.Services.DesignPanel,e); - e.Handled=true; + e.Handled=true; }; RelativePlacement p = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Top); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandleMultipleItems.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandleMultipleItems.cs new file mode 100644 index 0000000000..12a2505b3d --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandleMultipleItems.cs @@ -0,0 +1,93 @@ +// 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.Controls; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; + +using ICSharpCode.WpfDesign.Designer.Services; +using ICSharpCode.WpfDesign.Designer.Controls; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + + /// + /// The drag handle displayed for Framework Elements + /// + [ExtensionServer(typeof(PrimarySelectionButOnlyWhenMultipleSelectedExtensionServer))] + [ExtensionFor(typeof(FrameworkElement))] + public class TopLeftContainerDragHandleMultipleItems : AdornerProvider + { + /// + public TopLeftContainerDragHandleMultipleItems() + { } + + protected override void OnInitialized() + { + base.OnInitialized(); + + ContainerDragHandle rect = new ContainerDragHandle(); + + rect.PreviewMouseDown += delegate(object sender, MouseButtonEventArgs e) { + //Services.Selection.SetSelectedComponents(new DesignItem[] { this.ExtendedItem }, SelectionTypes.Auto); + new DragMoveMouseGesture(this.ExtendedItem, false).Start(this.ExtendedItem.Services.DesignPanel,e); + e.Handled=true; + }; + + var items = this.ExtendedItem.Services.Selection.SelectedItems; + + double minX = 0; + double minY = 0; + double maxX = 0; + double maxY = 0; + + foreach (DesignItem di in items) { + Point relativeLocation = di.View.TranslatePoint(new Point(0, 0), this.ExtendedItem.View); + + minX = minX < relativeLocation.X ? minX : relativeLocation.X; + minY = minY < relativeLocation.Y ? minY : relativeLocation.Y; + maxX = maxX > relativeLocation.X + ((FrameworkElement)this.ExtendedItem.View).ActualWidth ? maxX : relativeLocation.X + ((FrameworkElement)this.ExtendedItem.View).ActualWidth; + maxY = maxY > relativeLocation.Y + ((FrameworkElement)this.ExtendedItem.View).ActualHeight ? maxY : relativeLocation.Y + ((FrameworkElement)this.ExtendedItem.View).ActualHeight; + } + + Rectangle rect2 = new Rectangle() { + Width = (maxX - minX) + 4, + Height = (maxY - minY) + 4, + Stroke = Brushes.Black, + StrokeThickness = 2, + StrokeDashArray = new DoubleCollection(){ 2, 2 }, + }; + + RelativePlacement p = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Top); + p.XOffset = minX - 3; + p.YOffset = minY - 3; + + RelativePlacement p2 = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Top); + p2.XOffset = (minX + rect2.Width) - 2; + p2.YOffset = (minY + rect2.Height) - 2; + + AddAdorner(p, AdornerOrder.Background, rect); + AddAdorner(p2, AdornerOrder.Background, rect2); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/OutlineView/DragTreeViewItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/OutlineView/DragTreeViewItem.cs index c5bd677aa0..e4ec1d0ce5 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/OutlineView/DragTreeViewItem.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/OutlineView/DragTreeViewItem.cs @@ -94,8 +94,8 @@ namespace ICSharpCode.WpfDesign.Designer.OutlineView public static void OnIsSelectedChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) { - var el = s as FrameworkElement; - if (el != null) + var el = s as DragTreeViewItem; + if (el != null && el.IsSelected) el.BringIntoView(); } 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 a335f5f1f6..09acd365fa 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj @@ -87,6 +87,8 @@ + + FlatCollectionEditor.xaml Code diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/AdornerPanel.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/AdornerPanel.cs index 6670b2bb65..f9bd39d38d 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/AdornerPanel.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/AdornerPanel.cs @@ -179,6 +179,11 @@ namespace ICSharpCode.WpfDesign.Adorners /// public static readonly AdornerOrder Foreground = new AdornerOrder(300); + /// + /// The adorner is in the before foreground layer. + /// + public static readonly AdornerOrder BeforeForeground = new AdornerOrder(400); + int i; internal AdornerOrder(int i) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs index 9fd90eeefb..75db9cd2c4 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs @@ -102,6 +102,63 @@ namespace ICSharpCode.WpfDesign.Extensions } } + /// + /// Applies an extension to the primary selection, but only when multiple Items are selected! + /// + public class PrimarySelectionButOnlyWhenMultipleSelectedExtensionServer : PrimarySelectionExtensionServer + { + /// + /// Is called after the extension server is initialized and the Context property has been set. + /// + protected override void OnInitialized() + { + base.OnInitialized(); + this.Services.Selection.SelectionChanged += OnSelectionChanged; + } + + void OnSelectionChanged(object sender, EventArgs e) + { + ReapplyExtensions(this.Services.Selection.SelectedItems); + } + + /// + /// Gets if the item is in the secondary selection. + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return Services.Selection.PrimarySelection == extendedItem && Services.Selection.SelectionCount > 1; + } + } + + /// + /// Applies an extension to the primary selection if Only One Item is Selected. + /// + public class OnlyOneItemSelectedExtensionServer : PrimarySelectionExtensionServer + { + /// + /// Is called after the extension server is initialized and the Context property has been set. + /// + protected override void OnInitialized() + { + base.OnInitialized(); + this.Services.Selection.SelectionChanged += OnSelectionChanged; + } + + void OnSelectionChanged(object sender, EventArgs e) + { + if (this.Services.Selection.SelectedItems.Count > 1) + ReapplyExtensions(this.Services.Selection.SelectedItems); + } + + /// + /// Gets if the item is the primary selection. + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return Services.Selection.PrimarySelection == extendedItem && Services.Selection.SelectionCount < 2; + } + } + /// /// Applies an extension to the parent of the primary selection. ///