#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
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.
 
 
 
 
 
 

259 lines
9.9 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.Diagnostics;
using System.Windows.Controls;
using System.Windows.Media;
using ICSharpCode.WpfDesign.Adorners;
using ICSharpCode.WpfDesign.Extensions;
using ICSharpCode.WpfDesign.Designer.Controls;
namespace ICSharpCode.WpfDesign.Designer.Extensions
{
/// <summary>
/// Provides <see cref="IPlacementBehavior"/> behavior for <see cref="Grid"/>.
/// </summary>
[ExtensionFor(typeof(Grid), OverrideExtension=typeof(DefaultPlacementBehavior))]
public sealed class GridPlacementSupport : SnaplinePlacementBehavior
{
Grid grid;
private bool enteredIntoNewContainer;
protected override void OnInitialized()
{
base.OnInitialized();
grid = (Grid)this.ExtendedItem.Component;
}
double GetColumnOffset(int index)
{
// when the grid has no columns, we still need to return 0 for index=0 and grid.Width for index=1
if (index == 0)
return 0;
else if (index < grid.ColumnDefinitions.Count)
return grid.ColumnDefinitions[index].Offset;
else
return grid.ActualWidth;
}
double GetRowOffset(int index)
{
if (index == 0)
return 0;
else 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)
{
bool isLeft = itemBounds.Left < availableSpaceRect.Left + availableSpaceRect.Width / 4;
bool isRight = itemBounds.Right > availableSpaceRect.Right - availableSpaceRect.Width / 4;
if (isLeft && isRight)
return HorizontalAlignment.Stretch;
else if (isRight)
return HorizontalAlignment.Right;
else
return HorizontalAlignment.Left;
}
static VerticalAlignment SuggestVerticalAlignment(Rect itemBounds, Rect availableSpaceRect)
{
bool isTop = itemBounds.Top < availableSpaceRect.Top + availableSpaceRect.Height / 4;
bool isBottom = itemBounds.Bottom > availableSpaceRect.Bottom - availableSpaceRect.Height / 4;
if (isTop && isBottom)
return VerticalAlignment.Stretch;
else if (isBottom)
return VerticalAlignment.Bottom;
else
return VerticalAlignment.Top;
}
public override void EnterContainer(PlacementOperation operation)
{
enteredIntoNewContainer=true;
grid.UpdateLayout();
base.EnterContainer(operation);
}
GrayOutDesignerExceptActiveArea grayOut;
public override void EndPlacement(PlacementOperation operation)
{
GrayOutDesignerExceptActiveArea.Stop(ref grayOut);
enteredIntoNewContainer=false;
base.EndPlacement(operation);
}
public override void SetPosition(PlacementInformation info)
{
base.SetPosition(info);
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 (info.Item == Services.Selection.PrimarySelection) {
// only for primary selection:
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;
if(enteredIntoNewContainer){
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 override void LeaveContainer(PlacementOperation operation)
{
GrayOutDesignerExceptActiveArea.Stop(ref grayOut);
base.LeaveContainer(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
this.ExtendedItem.Properties["ColumnDefinitions"].CollectionElements.Remove(info.Item);
} else if (info.Item.ComponentType == typeof(RowDefinition)) {
this.ExtendedItem.Properties["RowDefinitions"].CollectionElements.Remove(info.Item);
} else {
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();
HorizontalAlignment ha = (HorizontalAlignment)info.Item.Properties[FrameworkElement.HorizontalAlignmentProperty].ValueOnInstance;
VerticalAlignment va = (VerticalAlignment)info.Item.Properties[FrameworkElement.VerticalAlignmentProperty].ValueOnInstance;
if (ha == HorizontalAlignment.Stretch)
info.Item.Properties[FrameworkElement.WidthProperty].SetValue(info.Bounds.Width);
if (va == VerticalAlignment.Stretch)
info.Item.Properties[FrameworkElement.HeightProperty].SetValue(info.Bounds.Height);
}
}
}
}
}