diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml
new file mode 100644
index 0000000000..d6c69df71b
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml.cs
new file mode 100644
index 0000000000..e616350d12
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenu.xaml.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.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using ICSharpCode.WpfDesign.PropertyGrid;
+using ICSharpCode.WpfDesign.Designer.Xaml;
+
+namespace ICSharpCode.WpfDesign.Designer.Extensions
+{
+ public partial class RightClickMultipleItemsContextMenu
+ {
+ private DesignItem designItem;
+
+ public RightClickMultipleItemsContextMenu(DesignItem designItem)
+ {
+ this.designItem = designItem;
+
+ InitializeComponent();
+ }
+
+ void Click_WrapInCanvas(object sender, System.Windows.RoutedEventArgs e)
+ {
+ ModelTools.WrapItemsNewContainer(this.designItem.Services.Selection.SelectedItems, typeof(Canvas));
+ }
+
+ void Click_WrapInGrid(object sender, System.Windows.RoutedEventArgs e)
+ {
+ ModelTools.WrapItemsNewContainer(this.designItem.Services.Selection.SelectedItems, typeof(Grid));
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenuExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenuExtension.cs
new file mode 100644
index 0000000000..5f24f5caff
--- /dev/null
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/RightClickMultipleItemsContextMenuExtension.cs
@@ -0,0 +1,54 @@
+// 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.Media;
+using System.Windows.Shapes;
+
+using ICSharpCode.WpfDesign.Adorners;
+using ICSharpCode.WpfDesign.Extensions;
+using ICSharpCode.WpfDesign.Designer;
+
+namespace ICSharpCode.WpfDesign.Designer.Extensions
+{
+ ///
+ ///
+ ///
+ [ExtensionServer(typeof(MultipleSelectedExtensionServer))]
+ [ExtensionFor(typeof(UIElement))]
+ public class RightClickMultipleItemsContextMenuExtension : SelectionAdornerProvider
+ {
+ DesignPanel panel;
+
+ protected override void OnInitialized()
+ {
+ base.OnInitialized();
+
+ panel = ExtendedItem.Context.Services.DesignPanel as DesignPanel;
+ panel.ContextMenu = new RightClickMultipleItemsContextMenu(ExtendedItem);
+ }
+
+ protected override void OnRemove()
+ {
+ panel.ContextMenu = null;
+
+ base.OnRemove();
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs
index 73a1510495..f8c8d22406 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/ModelTools.cs
@@ -27,6 +27,7 @@ using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Xps.Serialization;
+using ICSharpCode.WpfDesign.Designer.Xaml;
namespace ICSharpCode.WpfDesign.Designer
{
@@ -137,7 +138,7 @@ namespace ICSharpCode.WpfDesign.Designer
catch (Exception)
{ }
}
-
+
internal static Size GetDefaultSize(DesignItem createdItem)
{
CreateVisualTree(createdItem.View);
@@ -198,5 +199,174 @@ namespace ICSharpCode.WpfDesign.Designer
item.Properties.GetProperty(FrameworkElement.HeightProperty).SetValue(newHeight);
}
}
+
+
+ private class ItemPos
+ {
+ public HorizontalAlignment HorizontalAlignment{ get; set; }
+
+ public VerticalAlignment VerticalAlignment{ get; set; }
+
+ public double Xmin { get; set; }
+
+ public double Xmax { get; set; }
+
+ public double Ymin { get; set; }
+
+ public double Ymax { get; set; }
+
+ public DesignItem DesignItem { get; set; }
+ }
+
+ public static void WrapItemsNewContainer(IEnumerable items, Type containerType)
+ {
+ var collection = items;
+
+ var _context = collection.First().Context as XamlDesignContext;
+
+ var oldContainer = collection.First().Parent;
+
+ if (collection.Any(x => x.Parent != oldContainer))
+ return;
+
+ var newInstance = Activator.CreateInstance(containerType);
+ DesignItem newPanel = _context.Services.Component.RegisterComponentForDesigner(newInstance);
+ var changeGroup = newPanel.OpenGroup("Wrap in Container");
+
+ List itemList = new List();
+
+ foreach (var item in collection) {
+
+ var itemPos = new ItemPos(){ DesignItem = item };
+ itemList.Add(itemPos);
+
+ if (oldContainer.Component is Canvas) {
+ var canvas = oldContainer.View as Canvas;
+
+ if (item.Properties.GetAttachedProperty(Canvas.RightProperty) != null && item.Properties.GetAttachedProperty(Canvas.RightProperty).IsSet) {
+ itemPos.HorizontalAlignment = HorizontalAlignment.Right;
+ itemPos.Xmax = canvas.ActualWidth - (double)item.Properties.GetAttachedProperty(Canvas.RightProperty).ValueOnInstance;
+ itemPos.Xmin = itemPos.Xmax - ((FrameworkElement)item.View).ActualWidth;
+ }
+ else if (item.Properties.GetAttachedProperty(Canvas.LeftProperty) != null && item.Properties.GetAttachedProperty(Canvas.LeftProperty).IsSet) {
+ itemPos.HorizontalAlignment = HorizontalAlignment.Left;
+ itemPos.Xmin = (double)item.Properties.GetAttachedProperty(Canvas.LeftProperty).ValueOnInstance;
+ itemPos.Xmax = itemPos.Xmin + ((FrameworkElement)item.View).ActualWidth;
+ } else {
+ itemPos.HorizontalAlignment = HorizontalAlignment.Left;
+ itemPos.Xmax = itemPos.Xmin + ((FrameworkElement)item.View).ActualWidth;
+ }
+
+ if (item.Properties.GetAttachedProperty(Canvas.BottomProperty) != null && item.Properties.GetAttachedProperty(Canvas.BottomProperty).IsSet) {
+ itemPos.VerticalAlignment = VerticalAlignment.Bottom;
+ itemPos.Ymax = canvas.ActualHeight - (double)item.Properties.GetAttachedProperty(Canvas.BottomProperty).ValueOnInstance;
+ itemPos.Ymin = itemPos.Ymax - ((FrameworkElement)item.View).ActualHeight;
+ }
+ else if (item.Properties.GetAttachedProperty(Canvas.TopProperty) != null && item.Properties.GetAttachedProperty(Canvas.TopProperty).IsSet) {
+ itemPos.VerticalAlignment = VerticalAlignment.Top;
+ itemPos.Ymin = (double)item.Properties.GetAttachedProperty(Canvas.TopProperty).ValueOnInstance;
+ itemPos.Ymax = itemPos.Ymin + ((FrameworkElement)item.View).ActualHeight;
+ } else {
+ itemPos.VerticalAlignment = VerticalAlignment.Top;
+ itemPos.Ymax = itemPos.Ymin + ((FrameworkElement)item.View).ActualHeight;
+ }
+
+ item.Properties.GetAttachedProperty(Canvas.RightProperty).Reset();
+ item.Properties.GetAttachedProperty(Canvas.LeftProperty).Reset();
+ item.Properties.GetAttachedProperty(Canvas.TopProperty).Reset();
+ item.Properties.GetAttachedProperty(Canvas.BottomProperty).Reset();
+ } else if (oldContainer.Component is Grid) {
+ var grid = oldContainer.View as Grid;
+
+ if ((HorizontalAlignment)item.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).ValueOnInstance == HorizontalAlignment.Right) {
+ itemPos.HorizontalAlignment = HorizontalAlignment.Right;
+ itemPos.Xmax = grid.ActualWidth - ((Thickness)item.Properties.GetProperty(FrameworkElement.MarginProperty).ValueOnInstance).Right;
+ itemPos.Xmin = itemPos.Xmax - ((FrameworkElement)item.View).ActualWidth;
+ } else {
+ itemPos.HorizontalAlignment = HorizontalAlignment.Left;
+ itemPos.Xmin = ((Thickness)item.Properties.GetProperty(FrameworkElement.MarginProperty).ValueOnInstance).Left;
+ itemPos.Xmax = itemPos.Xmin + ((FrameworkElement)item.View).ActualWidth;
+ }
+
+ if ((VerticalAlignment)item.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).ValueOnInstance == VerticalAlignment.Bottom) {
+ itemPos.VerticalAlignment = VerticalAlignment.Bottom;
+ itemPos.Ymax = grid.ActualHeight - ((Thickness)item.Properties.GetProperty(FrameworkElement.MarginProperty).ValueOnInstance).Bottom;
+ itemPos.Ymin = itemPos.Ymax - ((FrameworkElement)item.View).ActualHeight;
+ } else {
+ itemPos.VerticalAlignment = VerticalAlignment.Top;
+ itemPos.Ymin = ((Thickness)item.Properties.GetProperty(FrameworkElement.MarginProperty).ValueOnInstance).Top;
+ itemPos.Ymax = itemPos.Ymin + ((FrameworkElement)item.View).ActualHeight;
+ }
+
+ item.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).Reset();
+ item.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).Reset();
+ item.Properties.GetProperty(FrameworkElement.MarginProperty).Reset();
+ }
+
+ var parCol = item.ParentProperty.CollectionElements;
+ parCol.Remove(item);
+ }
+
+ var xmin = itemList.Min(x => x.Xmin);
+ var xmax = itemList.Max(x => x.Xmax);
+ var ymin = itemList.Min(x => x.Ymin);
+ var ymax = itemList.Max(x => x.Ymax);
+
+ if (oldContainer.Component is Canvas) {
+ newPanel.Properties.GetProperty(FrameworkElement.WidthProperty).SetValue(xmax - xmin);
+ newPanel.Properties.GetProperty(FrameworkElement.HeightProperty).SetValue(ymax - ymin);
+ newPanel.Properties.GetAttachedProperty(Canvas.LeftProperty).SetValue(xmin);
+ newPanel.Properties.GetAttachedProperty(Canvas.TopProperty).SetValue(ymin);
+ } else if (oldContainer.Component is Grid) {
+ newPanel.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).SetValue(HorizontalAlignment.Left);
+ newPanel.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).SetValue(VerticalAlignment.Top);
+ newPanel.Properties.GetProperty(FrameworkElement.MarginProperty).SetValue(new Thickness(xmin, ymin, 0, 0));
+ newPanel.Properties.GetProperty(FrameworkElement.WidthProperty).SetValue(xmax - xmin);
+ newPanel.Properties.GetProperty(FrameworkElement.HeightProperty).SetValue(ymax - ymin);
+ }
+
+ foreach (var item in itemList) {
+ newPanel.ContentProperty.CollectionElements.Add(item.DesignItem);
+
+ if (newPanel.Component is Canvas) {
+ if (item.HorizontalAlignment == HorizontalAlignment.Right) {
+ item.DesignItem.Properties.GetAttachedProperty(Canvas.RightProperty).SetValue(xmax - item.Xmax);
+ } else {
+ item.DesignItem.Properties.GetAttachedProperty(Canvas.LeftProperty).SetValue(item.Xmin - xmin);
+ }
+
+ if (item.VerticalAlignment == VerticalAlignment.Bottom) {
+ item.DesignItem.Properties.GetAttachedProperty(Canvas.BottomProperty).SetValue(ymax - item.Ymax);
+ } else {
+ item.DesignItem.Properties.GetAttachedProperty(Canvas.TopProperty).SetValue(item.Ymin - ymin);
+ }
+ } else if (newPanel.Component is Grid) {
+ Thickness thickness = new Thickness(0);
+ if (item.HorizontalAlignment == HorizontalAlignment.Right) {
+ item.DesignItem.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).SetValue(HorizontalAlignment.Right);
+ thickness.Right = xmax - item.Xmax;
+ } else {
+ item.DesignItem.Properties.GetProperty(FrameworkElement.HorizontalAlignmentProperty).SetValue(HorizontalAlignment.Left);
+ thickness.Left = item.Xmin - xmin;
+ }
+
+ if (item.VerticalAlignment == VerticalAlignment.Bottom) {
+ item.DesignItem.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).SetValue(VerticalAlignment.Bottom);
+ thickness.Bottom = ymax - item.Ymax;
+ } else {
+ item.DesignItem.Properties.GetProperty(FrameworkElement.VerticalAlignmentProperty).SetValue(VerticalAlignment.Top);
+ thickness.Top = item.Ymin - ymin;
+ }
+
+ item.DesignItem.Properties.GetProperty(FrameworkElement.MarginProperty).SetValue(thickness);
+ }
+ }
+
+ oldContainer.ContentProperty.CollectionElements.Add(newPanel);
+
+ changeGroup.Commit();
+
+ _context.Services.Selection.SetSelectedComponents(new []{ newPanel });
+ }
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Translations.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Translations.cs
index 15677480c9..ebb196ca26 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Translations.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Translations.cs
@@ -65,5 +65,23 @@ namespace ICSharpCode.WpfDesign.Designer
return "Press \"Alt\" to Enter Container";
}
}
+
+ public virtual string WrapInCanvas {
+ get {
+ return "Wrap in Canvas";
+ }
+ }
+
+ public virtual string WrapInGrid {
+ get {
+ return "Wrap in Grid";
+ }
+ }
+
+ public virtual string WrapInBorder {
+ get {
+ return "Wrap in Border";
+ }
+ }
}
}
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 0cb8629e13..ee6c301f7f 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
@@ -90,6 +90,10 @@
+
+
+ RightClickMultipleItemsContextMenu.xaml
+
@@ -263,6 +267,7 @@
+
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs
index 75db9cd2c4..fc88c441a9 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs
@@ -118,7 +118,7 @@ namespace ICSharpCode.WpfDesign.Extensions
void OnSelectionChanged(object sender, EventArgs e)
{
- ReapplyExtensions(this.Services.Selection.SelectedItems);
+ ReapplyExtensions(this.Services.Selection.SelectedItems);
}
///
@@ -130,6 +130,34 @@ namespace ICSharpCode.WpfDesign.Extensions
}
}
+ ///
+ /// Applies an extension only when multiple Items are selected!
+ ///
+ public class MultipleSelectedExtensionServer : DefaultExtensionServer
+ {
+ ///
+ /// 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.SelectionCount > 1;
+ }
+ }
+
///
/// Applies an extension to the primary selection if Only One Item is Selected.
///