You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
384 lines
15 KiB
384 lines
15 KiB
// 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.Linq; |
|
using System.IO; |
|
using System.Windows.Controls; |
|
using System.Windows.Documents; |
|
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 |
|
{ |
|
/// <summary> |
|
/// Static helper methods for working with the designer DOM. |
|
/// </summary> |
|
public static class ModelTools |
|
{ |
|
/// <summary> |
|
/// Compares the positions of a and b in the model file. |
|
/// </summary> |
|
public static int ComparePositionInModelFile(DesignItem a, DesignItem b) |
|
{ |
|
// first remember all parent properties of a |
|
HashSet<DesignItemProperty> aProps = new HashSet<DesignItemProperty>(); |
|
DesignItem tmp = a; |
|
while (tmp != null) { |
|
aProps.Add(tmp.ParentProperty); |
|
tmp = tmp.Parent; |
|
} |
|
|
|
// now walk up b's parent tree until a matching property is found |
|
tmp = b; |
|
while (tmp != null) { |
|
DesignItemProperty prop = tmp.ParentProperty; |
|
if (aProps.Contains(prop)) { |
|
if (prop.IsCollection) { |
|
return prop.CollectionElements.IndexOf(a).CompareTo(prop.CollectionElements.IndexOf(b)); |
|
} else { |
|
return 0; |
|
} |
|
} |
|
tmp = tmp.Parent; |
|
} |
|
return 0; |
|
} |
|
|
|
/// <summary> |
|
/// Gets if the specified design item is in the document it belongs to. |
|
/// </summary> |
|
/// <returns>True for live objects, false for deleted objects.</returns> |
|
public static bool IsInDocument(DesignItem item) |
|
{ |
|
DesignItem rootItem = item.Context.RootItem; |
|
while (item != null) { |
|
if (item == rootItem) return true; |
|
item = item.Parent; |
|
} |
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Gets if the specified components can be deleted. |
|
/// </summary> |
|
public static bool CanDeleteComponents(ICollection<DesignItem> items) |
|
{ |
|
IPlacementBehavior b = PlacementOperation.GetPlacementBehavior(items); |
|
return b != null |
|
&& b.CanPlace(items, PlacementType.Delete, PlacementAlignment.Center); |
|
} |
|
|
|
public static bool CanSelectComponent(DesignItem item) |
|
{ |
|
return item.View != null; |
|
} |
|
|
|
/// <summary> |
|
/// Deletes the specified components from their parent containers. |
|
/// If the deleted components are currently selected, they are deselected before they are deleted. |
|
/// </summary> |
|
public static void DeleteComponents(ICollection<DesignItem> items) |
|
{ |
|
DesignItem parent = items.First().Parent; |
|
PlacementOperation operation = PlacementOperation.Start(items, PlacementType.Delete); |
|
try { |
|
ISelectionService selectionService = items.First().Services.Selection; |
|
selectionService.SetSelectedComponents(items, SelectionTypes.Remove); |
|
// if the selection is empty after deleting some components, select the parent of the deleted component |
|
if (selectionService.SelectionCount == 0 && !items.Contains(parent)) { |
|
selectionService.SetSelectedComponents(new DesignItem[] { parent }); |
|
} |
|
foreach (var designItem in items) { |
|
designItem.Name = null; |
|
} |
|
operation.DeleteItemsAndCommit(); |
|
} catch { |
|
operation.Abort(); |
|
throw; |
|
} |
|
} |
|
|
|
internal static void CreateVisualTree(this UIElement element) |
|
{ |
|
try { |
|
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); |
|
element.Arrange(new Rect(element.DesiredSize)); |
|
|
|
//var fixedDoc = new FixedDocument(); |
|
//var pageContent = new PageContent(); |
|
//var fixedPage = new FixedPage(); |
|
//fixedPage.Children.Add(element); |
|
//(pageContent as IAddChild).AddChild(fixedPage); |
|
//fixedDoc.Pages.Add(pageContent); |
|
|
|
//var f = new XpsSerializerFactory(); |
|
//var w = f.CreateSerializerWriter(new MemoryStream()); |
|
//w.Write(fixedDoc); |
|
|
|
//fixedPage.Children.Remove(element); |
|
} |
|
catch (Exception) |
|
{ } |
|
} |
|
|
|
internal static Size GetDefaultSize(DesignItem createdItem) |
|
{ |
|
CreateVisualTree(createdItem.View); |
|
|
|
if (createdItem.View.GetType() == typeof (TextBlock)) |
|
return new Size(double.NaN, double.NaN); |
|
|
|
var s = Metadata.GetDefaultSize(createdItem.ComponentType, false); |
|
|
|
if (double.IsNaN(s.Width) && createdItem.View.DesiredSize.Width > 0) |
|
{ |
|
s.Width = createdItem.View.DesiredSize.Width; |
|
} |
|
if (double.IsNaN(s.Height) && createdItem.View.DesiredSize.Height > 0) |
|
{ |
|
s.Height = createdItem.View.DesiredSize.Height; |
|
} |
|
|
|
var newS = Metadata.GetDefaultSize(createdItem.ComponentType, true); |
|
|
|
if (!(s.Width > 0)) |
|
s.Width = newS.Width; |
|
|
|
if (!(s.Height > 0)) |
|
s.Height = newS.Height; |
|
|
|
if (double.IsNaN(s.Width)) { |
|
s.Width = GetWidth(createdItem.View); |
|
} |
|
if (double.IsNaN(s.Height)) { |
|
s.Height = GetHeight(createdItem.View); |
|
} |
|
|
|
return s; |
|
} |
|
|
|
internal static double GetWidth(UIElement element) |
|
{ |
|
double v = (double)element.GetValue(FrameworkElement.WidthProperty); |
|
if (double.IsNaN(v)) |
|
return element.RenderSize.Width; |
|
else |
|
return v; |
|
} |
|
|
|
internal static double GetHeight(UIElement element) |
|
{ |
|
double v = (double)element.GetValue(FrameworkElement.HeightProperty); |
|
if (double.IsNaN(v)) |
|
return element.RenderSize.Height; |
|
else |
|
return v; |
|
} |
|
|
|
public static void Resize(DesignItem item, double newWidth, double newHeight) |
|
{ |
|
if (newWidth != GetWidth(item.View)) { |
|
if(double.IsNaN(newWidth)) |
|
item.Properties.GetProperty(FrameworkElement.WidthProperty).Reset(); |
|
else |
|
item.Properties.GetProperty(FrameworkElement.WidthProperty).SetValue(newWidth); |
|
} |
|
if (newHeight != GetHeight(item.View)) { |
|
if (double.IsNaN(newHeight)) |
|
item.Properties.GetProperty(FrameworkElement.HeightProperty).Reset(); |
|
else |
|
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<DesignItem> 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<ItemPos> itemList = new List<ItemPos>(); |
|
|
|
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 }); |
|
} |
|
} |
|
}
|
|
|