From fc0ca926c54a0d6f91f4c811aa28b75e45ba1709 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 11 Mar 2007 11:35:27 +0000 Subject: [PATCH] Allow placing elements in a Grid. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2443 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../GrayOutDesignerExceptActiveArea.cs | 21 +- .../Project/Controls/GridAdorner.cs | 4 +- .../Extensions/CanvasPlacementSupport.cs | 3 + .../Extensions/GridPlacementSupport.cs | 237 +++++++++++++++++- .../WpfDesign/Project/PlacementType.cs | 2 +- 5 files changed, 257 insertions(+), 10 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs index 2a2b2ede70..56fc2f8737 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GrayOutDesignerExceptActiveArea.cs @@ -55,7 +55,26 @@ namespace ICSharpCode.WpfDesign.Designer.Controls drawingContext.DrawGeometry(grayOutBrush, null, combinedGeometry); } + Rect currentAnimateActiveAreaRectToTarget; + + internal void AnimateActiveAreaRectTo(Rect newRect) + { + if (newRect.Equals(currentAnimateActiveAreaRectToTarget)) + return; + activeAreaGeometry.BeginAnimation( + RectangleGeometry.RectProperty, + new RectAnimation(newRect, new Duration(new TimeSpan(0,0,0,0,100))), + HandoffBehavior.SnapshotAndReplace); + currentAnimateActiveAreaRectToTarget = newRect; + } + internal static void Start(ref GrayOutDesignerExceptActiveArea grayOut, ServiceContainer services, UIElement activeContainer) + { + Debug.Assert(activeContainer != null); + Start(ref grayOut, services, activeContainer, new Rect(activeContainer.RenderSize)); + } + + internal static void Start(ref GrayOutDesignerExceptActiveArea grayOut, ServiceContainer services, UIElement activeContainer, Rect activeRectInActiveContainer) { Debug.Assert(services != null); Debug.Assert(activeContainer != null); @@ -68,7 +87,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls grayOut.adornerPanel.Order = AdornerOrder.BehindForeground; grayOut.adornerPanel.SetAdornedElement(designPanel.Context.RootItem.View, null); grayOut.adornerPanel.Children.Add(grayOut); - grayOut.ActiveAreaGeometry = new RectangleGeometry(new Rect(activeContainer.RenderSize), 0, 0, (Transform)activeContainer.TransformToVisual(grayOut.adornerPanel.AdornedElement)); + grayOut.ActiveAreaGeometry = new RectangleGeometry(activeRectInActiveContainer, 0, 0, (Transform)activeContainer.TransformToVisual(grayOut.adornerPanel.AdornedElement)); Animate(grayOut.GrayOutBrush, Brush.OpacityProperty, 0, MaxOpacity); designPanel.Adorners.Add(grayOut.adornerPanel); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GridAdorner.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GridAdorner.cs index d8e86027d7..d5d563adec 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GridAdorner.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GridAdorner.cs @@ -244,12 +244,12 @@ namespace ICSharpCode.WpfDesign.Designer.Controls if (original1.IsStar && originalPixelSize1 > 0) new1 = new GridLength(original1.Value * (originalPixelSize1 + delta) / originalPixelSize1, GridUnitType.Star); else - new1 = new GridLength(original1.Value + delta); + new1 = new GridLength(originalPixelSize1 + delta); GridLength new2; if (original2.IsStar && originalPixelSize2 > 0) new2 = new GridLength(original2.Value * (originalPixelSize2 - delta) / originalPixelSize2, GridUnitType.Star); else - new2 = new GridLength(original2.Value - delta); + new2 = new GridLength(originalPixelSize2 - delta); firstRow.Properties[RowColumnSizeProperty].SetValue(new1); secondRow.Properties[RowColumnSizeProperty].SetValue(new2); ((UIElement)VisualTreeHelper.GetParent(this)).InvalidateArrange(); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPlacementSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPlacementSupport.cs index 0015c61a06..9df927b6f2 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPlacementSupport.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPlacementSupport.cs @@ -115,6 +115,9 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions foreach (PlacementInformation info in operation.PlacedItems) { this.ExtendedItem.Properties["Children"].CollectionElements.Add(info.Item); SetPosition(info); + info.Item.Properties[FrameworkElement.HorizontalAlignmentProperty].Reset(); + info.Item.Properties[FrameworkElement.VerticalAlignmentProperty].Reset(); + info.Item.Properties[FrameworkElement.MarginProperty].Reset(); } BeginPlacement(operation); } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/GridPlacementSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/GridPlacementSupport.cs index af1ea9091b..927f37ceeb 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/GridPlacementSupport.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/GridPlacementSupport.cs @@ -8,7 +8,9 @@ using System; using System.Collections.Generic; using System.Windows; +using System.Diagnostics; using System.Windows.Controls; +using System.Windows.Media; using ICSharpCode.WpfDesign.Adorners; using ICSharpCode.WpfDesign.Extensions; @@ -22,33 +24,247 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions [ExtensionFor(typeof(Grid))] public sealed class GridPlacementSupport : BehaviorExtension, IPlacementBehavior { + Grid grid; + protected override void OnInitialized() { base.OnInitialized(); + grid = (Grid)this.ExtendedItem.Component; this.ExtendedItem.AddBehavior(typeof(IPlacementBehavior), this); } public bool CanPlace(ICollection childItems, PlacementType type, PlacementAlignment position) { - return type == PlacementType.Delete; + return type == PlacementType.Resize || type == PlacementType.Move + || type == PlacementType.Delete + || type == PlacementType.AddItem; } + GrayOutDesignerExceptActiveArea grayOut; + public void BeginPlacement(PlacementOperation operation) { } public void EndPlacement(PlacementOperation operation) { + GrayOutDesignerExceptActiveArea.Stop(ref grayOut); } public Rect GetPosition(PlacementOperation operation, DesignItem child) { - return new Rect(); + FrameworkElement obj = child.Component as FrameworkElement; + if (obj == null) return new Rect(); + + Thickness margin = obj.Margin; + + double left, width, right; + switch (obj.HorizontalAlignment) { + case HorizontalAlignment.Stretch: + left = GetColumnOffset(Grid.GetColumn(obj)) + margin.Left; + right = GetColumnOffset(Grid.GetColumn(obj) + Grid.GetColumnSpan(obj)) - margin.Right; + width = right - left; + break; + case HorizontalAlignment.Left: + left = GetColumnOffset(Grid.GetColumn(obj)) + margin.Left; + width = ModelTools.GetWidth(obj); + right = left + width; + break; + case HorizontalAlignment.Right: + right = GetColumnOffset(Grid.GetColumn(obj) + Grid.GetColumnSpan(obj)) - margin.Right; + width = ModelTools.GetWidth(obj); + left = right - width; + break; + case HorizontalAlignment.Center: + throw new NotImplementedException(); + default: + throw new NotSupportedException(); + } + + double top, height, bottom; + switch (obj.VerticalAlignment) { + case VerticalAlignment.Stretch: + top = GetRowOffset(Grid.GetRow(obj)) + margin.Top; + bottom = GetRowOffset(Grid.GetRow(obj) + Grid.GetRowSpan(obj)) - margin.Bottom; + height = bottom - top; + break; + case VerticalAlignment.Top: + top = GetRowOffset(Grid.GetRow(obj)) + margin.Top; + height = ModelTools.GetHeight(obj); + bottom = top + height; + break; + case VerticalAlignment.Bottom: + bottom = GetRowOffset(Grid.GetRow(obj) + Grid.GetRowSpan(obj)) - margin.Bottom; + height = ModelTools.GetHeight(obj); + top = bottom - height; + break; + case VerticalAlignment.Center: + throw new NotImplementedException(); + default: + throw new NotSupportedException(); + } + return new Rect(left, top, width, height); + } + + double GetColumnOffset(int index) + { + if (index < grid.ColumnDefinitions.Count) + return grid.ColumnDefinitions[index].Offset; + else + return grid.ActualWidth; + } + + double GetRowOffset(int index) + { + if (index < grid.RowDefinitions.Count) + return grid.RowDefinitions[index].Offset; + else + return grid.ActualHeight; + } + + const double epsilon = 0.00000001; + + int GetColumnIndex(double x) + { + if (grid.ColumnDefinitions.Count == 0) + return 0; + for (int i = 1; i < grid.ColumnDefinitions.Count; i++) { + if (x < grid.ColumnDefinitions[i].Offset - epsilon) + return i - 1; + } + return grid.ColumnDefinitions.Count - 1; + } + + int GetRowIndex(double y) + { + if (grid.RowDefinitions.Count == 0) + return 0; + for (int i = 1; i < grid.RowDefinitions.Count; i++) { + if (y < grid.RowDefinitions[i].Offset - epsilon) + return i - 1; + } + return grid.RowDefinitions.Count - 1; + } + + int GetEndColumnIndex(double x) + { + if (grid.ColumnDefinitions.Count == 0) + return 0; + for (int i = 1; i < grid.ColumnDefinitions.Count; i++) { + if (x <= grid.ColumnDefinitions[i].Offset + epsilon) + return i - 1; + } + return grid.ColumnDefinitions.Count - 1; + } + + int GetEndRowIndex(double y) + { + if (grid.RowDefinitions.Count == 0) + return 0; + for (int i = 1; i < grid.RowDefinitions.Count; i++) { + if (y <= grid.RowDefinitions[i].Offset + epsilon) + return i - 1; + } + return grid.RowDefinitions.Count - 1; + } + + static void SetColumn(DesignItem item, int column, int columnSpan) + { + Debug.Assert(item != null && column >= 0 && columnSpan > 0); + item.Properties.GetAttachedProperty(Grid.ColumnProperty).SetValue(column); + if (columnSpan == 1) { + item.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).Reset(); + } else { + item.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).SetValue(columnSpan); + } + } + + static void SetRow(DesignItem item, int row, int rowSpan) + { + Debug.Assert(item != null && row >= 0 && rowSpan > 0); + item.Properties.GetAttachedProperty(Grid.RowProperty).SetValue(row); + if (rowSpan == 1) { + item.Properties.GetAttachedProperty(Grid.RowSpanProperty).Reset(); + } else { + item.Properties.GetAttachedProperty(Grid.RowSpanProperty).SetValue(rowSpan); + } + } + + static HorizontalAlignment SuggestHorizontalAlignment(Rect itemBounds, Rect availableSpaceRect) + { + if (itemBounds.Right < (availableSpaceRect.Left + availableSpaceRect.Right) / 2) { + return HorizontalAlignment.Left; + } else if (itemBounds.Left > (availableSpaceRect.Left + availableSpaceRect.Right) / 2) { + return HorizontalAlignment.Right; + } else { + return HorizontalAlignment.Stretch; + } + } + + static VerticalAlignment SuggestVerticalAlignment(Rect itemBounds, Rect availableSpaceRect) + { + if (itemBounds.Bottom < (availableSpaceRect.Top + availableSpaceRect.Bottom) / 2) { + return VerticalAlignment.Top; + } else if (itemBounds.Top > (availableSpaceRect.Top + availableSpaceRect.Bottom) / 2) { + return VerticalAlignment.Bottom; + } else { + return VerticalAlignment.Stretch; + } } public void SetPosition(PlacementInformation info) { - throw new NotImplementedException(); + if (info.Operation.Type == PlacementType.AddItem) { + SetColumn(info.Item, GetColumnIndex(info.Bounds.Left), 1); + SetRow(info.Item, GetRowIndex(info.Bounds.Top), 1); + } else { + int leftColumnIndex = GetColumnIndex(info.Bounds.Left); + int rightColumnIndex = GetEndColumnIndex(info.Bounds.Right); + if (rightColumnIndex < leftColumnIndex) rightColumnIndex = leftColumnIndex; + SetColumn(info.Item, leftColumnIndex, rightColumnIndex - leftColumnIndex + 1); + int topRowIndex = GetRowIndex(info.Bounds.Top); + int bottomRowIndex = GetEndRowIndex(info.Bounds.Bottom); + if (bottomRowIndex < topRowIndex) bottomRowIndex = topRowIndex; + SetRow(info.Item, topRowIndex, bottomRowIndex - topRowIndex + 1); + + Rect availableSpaceRect = new Rect( + new Point(GetColumnOffset(leftColumnIndex), GetRowOffset(topRowIndex)), + new Point(GetColumnOffset(rightColumnIndex + 1), GetRowOffset(bottomRowIndex + 1)) + ); + if (grayOut != null) { + grayOut.AnimateActiveAreaRectTo(availableSpaceRect); + } else { + GrayOutDesignerExceptActiveArea.Start(ref grayOut, this.Services, this.ExtendedItem.View, availableSpaceRect); + } + + HorizontalAlignment ha = (HorizontalAlignment)info.Item.Properties[FrameworkElement.HorizontalAlignmentProperty].ValueOnInstance; + VerticalAlignment va = (VerticalAlignment)info.Item.Properties[FrameworkElement.VerticalAlignmentProperty].ValueOnInstance; + ha = SuggestHorizontalAlignment(info.Bounds, availableSpaceRect); + va = SuggestVerticalAlignment(info.Bounds, availableSpaceRect); + + info.Item.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(ha); + info.Item.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(va); + + Thickness margin = new Thickness(0, 0, 0, 0); + if (ha == HorizontalAlignment.Left || ha == HorizontalAlignment.Stretch) + margin.Left = info.Bounds.Left - GetColumnOffset(leftColumnIndex); + if (va == VerticalAlignment.Top || va == VerticalAlignment.Stretch) + margin.Top = info.Bounds.Top - GetRowOffset(topRowIndex); + if (ha == HorizontalAlignment.Right || ha == HorizontalAlignment.Stretch) + margin.Right = GetColumnOffset(rightColumnIndex + 1) - info.Bounds.Right; + if (va == VerticalAlignment.Bottom || va == VerticalAlignment.Stretch) + margin.Bottom = GetRowOffset(bottomRowIndex + 1) - info.Bounds.Bottom; + info.Item.Properties[FrameworkElement.MarginProperty].SetValue(margin); + + if (ha == HorizontalAlignment.Stretch) + info.Item.Properties[FrameworkElement.WidthProperty].Reset(); + else + info.Item.Properties[FrameworkElement.WidthProperty].SetValue(info.Bounds.Width); + if (va == VerticalAlignment.Stretch) + info.Item.Properties[FrameworkElement.HeightProperty].Reset(); + else + info.Item.Properties[FrameworkElement.HeightProperty].SetValue(info.Bounds.Height); + } } public bool CanLeaveContainer(PlacementOperation operation) @@ -58,6 +274,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions public void LeaveContainer(PlacementOperation operation) { + EndPlacement(operation); foreach (PlacementInformation info in operation.PlacedItems) { if (info.Item.ComponentType == typeof(ColumnDefinition)) { // TODO: combine the width of the deleted column with the previous column @@ -65,19 +282,27 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } else if (info.Item.ComponentType == typeof(RowDefinition)) { this.ExtendedItem.Properties["RowDefinitions"].CollectionElements.Remove(info.Item); } else { - throw new NotImplementedException(); + this.ExtendedItem.Properties["Children"].CollectionElements.Remove(info.Item); + info.Item.Properties.GetAttachedProperty(Grid.RowProperty).Reset(); + info.Item.Properties.GetAttachedProperty(Grid.ColumnProperty).Reset(); + info.Item.Properties.GetAttachedProperty(Grid.RowSpanProperty).Reset(); + info.Item.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).Reset(); } } } public bool CanEnterContainer(PlacementOperation operation) { - return false; + return true; } public void EnterContainer(PlacementOperation operation) { - throw new NotImplementedException(); + foreach (PlacementInformation info in operation.PlacedItems) { + this.ExtendedItem.Properties["Children"].CollectionElements.Add(info.Item); + SetPosition(info); + } + BeginPlacement(operation); } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs index ce570d1d8e..4430d4abad 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementType.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.WpfDesign /// /// Adding an element to a specified position in the container. - /// T + /// AddItem is used when dragging a toolbox item to the design surface. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static readonly PlacementType AddItem = Register("AddItem");