Browse Source

Canvas Position Handle

-> When Positioning in a Canvas, show a Handle like the one Showed when Positioning in a Grid
pull/52/head
jkuehner 12 years ago
parent
commit
1aae5a1e38
  1. 218
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/CanvasPositionHandle.cs
  2. 41
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml
  3. 7
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/MarginHandle.cs
  4. 77
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPositionExtension.cs
  5. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj

218
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/CanvasPositionHandle.cs

@ -0,0 +1,218 @@ @@ -0,0 +1,218 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Windows.Input;
using System.Globalization;
using System.ComponentModel;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
using ICSharpCode.WpfDesign.Adorners;
namespace ICSharpCode.WpfDesign.Designer.Controls
{
/// <summary>
/// Adorner that displays the margin of a control in a Grid.
/// </summary>
public class CanvasPositionHandle : MarginHandle
{
static CanvasPositionHandle()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CanvasPositionHandle), new FrameworkPropertyMetadata(typeof(CanvasPositionHandle)));
HandleLengthOffset=2;
}
private Path line1;
private Path line2;
public override void OnApplyTemplate()
{
line1 = GetTemplateChild("line1") as Path;
line2 = GetTemplateChild("line2") as Path;
base.OnApplyTemplate();
}
readonly Canvas canvas;
readonly DesignItem adornedControlItem;
readonly AdornerPanel adornerPanel;
readonly HandleOrientation orientation;
readonly FrameworkElement adornedControl;
/// <summary> This grid contains the handle line and the endarrow.</summary>
Grid lineArrow;
private DependencyPropertyDescriptor leftDescriptor;
private DependencyPropertyDescriptor rightDescriptor;
private DependencyPropertyDescriptor topDescriptor;
private DependencyPropertyDescriptor bottomDescriptor;
private DependencyPropertyDescriptor widthDescriptor;
private DependencyPropertyDescriptor heightDescriptor;
public CanvasPositionHandle(DesignItem adornedControlItem, AdornerPanel adornerPanel, HandleOrientation orientation)
{
Debug.Assert(adornedControlItem != null);
this.adornedControlItem = adornedControlItem;
this.adornerPanel = adornerPanel;
this.orientation = orientation;
Angle = (double) orientation;
canvas = (Canvas) adornedControlItem.Parent.Component;
adornedControl = (FrameworkElement) adornedControlItem.Component;
Stub = new MarginStub(this);
ShouldBeVisible = true;
leftDescriptor = DependencyPropertyDescriptor.FromProperty(Canvas.LeftProperty,
adornedControlItem.Component.GetType());
leftDescriptor.AddValueChanged(adornedControl, OnPropertyChanged);
rightDescriptor = DependencyPropertyDescriptor.FromProperty(Canvas.RightProperty,
adornedControlItem.Component.GetType());
rightDescriptor.AddValueChanged(adornedControl, OnPropertyChanged);
topDescriptor = DependencyPropertyDescriptor.FromProperty(Canvas.TopProperty,
adornedControlItem.Component.GetType());
topDescriptor.AddValueChanged(adornedControl, OnPropertyChanged);
bottomDescriptor = DependencyPropertyDescriptor.FromProperty(Canvas.BottomProperty,
adornedControlItem.Component.GetType());
bottomDescriptor.AddValueChanged(adornedControl, OnPropertyChanged);
widthDescriptor = DependencyPropertyDescriptor.FromProperty(Control.WidthProperty,
adornedControlItem.Component.GetType());
widthDescriptor.AddValueChanged(adornedControl, OnPropertyChanged);
heightDescriptor = DependencyPropertyDescriptor.FromProperty(Control.WidthProperty,
adornedControlItem.Component.GetType());
heightDescriptor.AddValueChanged(adornedControl, OnPropertyChanged);
BindAndPlaceHandle();
}
void OnPropertyChanged(object sender, EventArgs e)
{
BindAndPlaceHandle();
}
/// <summary>
/// Gets/Sets the angle by which the Canvas display has to be rotated
/// </summary>
public override double TextTransform
{
get
{
if ((double)orientation == 90 || (double)orientation == 180)
return 180;
if ((double)orientation == 270)
return 0;
return (double)orientation;
}
set { }
}
/// <summary>
/// Binds the <see cref="HandleLength"/> to the margin and place the handles.
/// </summary>
void BindAndPlaceHandle()
{
if (!adornerPanel.Children.Contains(this))
adornerPanel.Children.Add(this);
if (!adornerPanel.Children.Contains(Stub))
adornerPanel.Children.Add(Stub);
RelativePlacement placement=new RelativePlacement();
switch (orientation)
{
case HandleOrientation.Left:
{
var wr = (double) leftDescriptor.GetValue(adornedControl);
if (double.IsNaN(wr))
{
wr = (double) rightDescriptor.GetValue(adornedControl);
wr = canvas.ActualWidth - (adornedControl.ActualWidth + wr);
}
else
{
if (line1 != null)
{
line1.StrokeDashArray.Clear();
line2.StrokeDashArray.Clear();
}
}
this.HandleLength = wr;
placement = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Center);
placement.XOffset = -HandleLengthOffset;
break;
}
case HandleOrientation.Top:
{
var wr = (double)topDescriptor.GetValue(adornedControl);
if (double.IsNaN(wr))
{
wr = (double)bottomDescriptor.GetValue(adornedControl);
wr = canvas.ActualHeight - (adornedControl.ActualHeight + wr);
}
else
{
if (line1 != null)
{
line1.StrokeDashArray.Clear();
line2.StrokeDashArray.Clear();
}
}
this.HandleLength = wr;
placement = new RelativePlacement(HorizontalAlignment.Center, VerticalAlignment.Top);
placement.YOffset = -HandleLengthOffset;
break;
}
case HandleOrientation.Right:
{
var wr = (double) rightDescriptor.GetValue(adornedControl);
if (double.IsNaN(wr))
{
wr = (double) leftDescriptor.GetValue(adornedControl);
wr = canvas.ActualWidth - (adornedControl.ActualWidth + wr);
}
else
{
if (line1 != null)
{
line1.StrokeDashArray.Clear();
line2.StrokeDashArray.Clear();
}
}
this.HandleLength = wr;
placement = new RelativePlacement(HorizontalAlignment.Right, VerticalAlignment.Center);
placement.XOffset = HandleLengthOffset;
break;
}
case HandleOrientation.Bottom:
{
var wr = (double)bottomDescriptor.GetValue(adornedControl);
if (double.IsNaN(wr))
{
wr = (double)topDescriptor.GetValue(adornedControl);
wr = canvas.ActualHeight - (adornedControl.ActualHeight + wr);
}
else
{
if (line1 != null)
{
line1.StrokeDashArray.Clear();
line2.StrokeDashArray.Clear();
}
}
this.HandleLength = wr;
placement = new RelativePlacement(HorizontalAlignment.Center, VerticalAlignment.Bottom);
placement.YOffset = HandleLengthOffset;
break;
}
}
AdornerPanel.SetPlacement(this, placement);
this.Visibility = Visibility.Visible;
}
}
}

41
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml

@ -188,6 +188,47 @@ @@ -188,6 +188,47 @@
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Controls:CanvasPositionHandle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:MarginHandle}">
<Grid Height="10" Width="{Binding Path=HandleLength, Converter={x:Static ControlConvertors:HandleLengthWithOffset.Instance}, RelativeSource={RelativeSource Mode=TemplatedParent}}" SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Name="startArrow" Fill="{StaticResource HandleBrush}" Stretch="Fill" Stroke="{TemplateBinding Panel.Background}" StrokeThickness="0.5" Margin="0,1,0,1" Data="M0,0 L0,1 1,0.5 z" Grid.Column="0" />
<!-- Wrap the handle-line and endArrow in this grid. It's visiblity is subjected to HandleLength -->
<Grid Height="10" Grid.Column="1" Name="lineArrow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition MaxWidth="20" MinWidth="10" />
<ColumnDefinition Width="*" />
<!--<ColumnDefinition Width="8" />
<ColumnDefinition Width="1.5"/>-->
</Grid.ColumnDefinitions>
<Rectangle Fill="Transparent" Height="10" Grid.Column="0" Grid.ColumnSpan="4" />
<Path Name="line1" StrokeDashArray="2,2" Stretch="Fill" Stroke="{StaticResource HandleBrush}" StrokeThickness="1.5" Margin="0 0 0 0" Data="M0,-0.75 L1,-0.75" Grid.Column="0" />
<TextBlock Grid.Column="1" Text="{Binding Path=HandleLength, Mode=OneWay, Converter={x:Static Converters:FormatDoubleConverter.Instance }, RelativeSource={RelativeSource Mode=TemplatedParent}}" FontSize="9" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="1,1,1,1">
<TextBlock.LayoutTransform>
<RotateTransform Angle="{Binding Path=TextTransform, RelativeSource={RelativeSource Mode=TemplatedParent}}" CenterX="0.5" CenterY="0.5">
</RotateTransform>
</TextBlock.LayoutTransform>
</TextBlock>
<Path Name="line2" StrokeDashArray="2,2" Stretch="Fill" Stroke="{StaticResource HandleBrush}" StrokeThickness="1.5" Margin="0 0 0 0" Data="M0,-0.75 L1,-0.75" Grid.Column="2" />
<!--<Path Name="arrow2" Margin="0,1,0,1" Fill="{StaticResource HandleBrush}" Stretch="Fill" Stroke="{TemplateBinding Panel.Background}" StrokeThickness="0.5" Data="M0,0 L0,1 1,0.5 z" Grid.Column="3" />-->
<!--<Rectangle Width="1.5" Fill="{StaticResource HandleBrush}" Grid.Column="4"/>-->
</Grid>
<!-- Rotate the handle and angle of rotation being set by the Margin type. See enum HandleOrientation -->
<Grid.LayoutTransform>
<RotateTransform Angle="{Binding Path=Angle, RelativeSource={RelativeSource Mode=TemplatedParent}}">
</RotateTransform>
</Grid.LayoutTransform>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Controls:MarginHandle}">
<Setter Property="Template">
<Setter.Value>

7
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/MarginHandle.cs

@ -60,7 +60,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -60,7 +60,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
/// <summary>
/// Gets the Stub for this handle
/// </summary>
public MarginStub Stub {get; private set;}
public MarginStub Stub {get; protected set;}
/// <summary>
/// Gets/Sets the angle by which handle rotates.
@ -70,7 +70,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -70,7 +70,7 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
/// <summary>
/// Gets/Sets the angle by which the Margin display has to be rotated
/// </summary>
public double TextTransform{
public virtual double TextTransform{
get{
if((double)orientation==90 || (double)orientation == 180)
return 180;
@ -109,6 +109,9 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -109,6 +109,9 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
get { return orientation; }
}
protected MarginHandle()
{ }
public MarginHandle(DesignItem adornedControlItem, AdornerPanel adornerPanel, HandleOrientation orientation)
{
Debug.Assert(adornedControlItem!=null);

77
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/CanvasPositionExtension.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Windows.Input;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ICSharpCode.WpfDesign.Adorners;
using ICSharpCode.WpfDesign.Designer.Controls;
using ICSharpCode.WpfDesign.Extensions;
namespace ICSharpCode.WpfDesign.Designer.Extensions
{
[ExtensionFor(typeof(FrameworkElement))]
[ExtensionServer(typeof(PrimarySelectionExtensionServer))]
public class CanvasPositionExtension : AdornerProvider
{
private MarginHandle[] _handles;
private MarginHandle _leftHandle, _topHandle, _rightHandle, _bottomHandle;
private Canvas _canvas;
protected override void OnInitialized()
{
base.OnInitialized();
if (this.ExtendedItem.Parent != null)
{
if (this.ExtendedItem.Parent.ComponentType == typeof(Canvas))
{
FrameworkElement extendedControl = (FrameworkElement)this.ExtendedItem.Component;
AdornerPanel adornerPanel = new AdornerPanel();
// If the Element is rotated/skewed in the grid, then margin handles do not appear
if (extendedControl.LayoutTransform.Value == Matrix.Identity && extendedControl.RenderTransform.Value == Matrix.Identity)
{
_canvas = this.ExtendedItem.Parent.View as Canvas;
_handles = new[]
{
_leftHandle = new CanvasPositionHandle(ExtendedItem, adornerPanel, HandleOrientation.Left),
_topHandle = new CanvasPositionHandle(ExtendedItem, adornerPanel, HandleOrientation.Top),
_rightHandle = new CanvasPositionHandle(ExtendedItem, adornerPanel, HandleOrientation.Right),
_bottomHandle = new CanvasPositionHandle(ExtendedItem, adornerPanel, HandleOrientation.Bottom),
};
}
if (adornerPanel != null)
this.Adorners.Add(adornerPanel);
}
}
}
public void HideHandles()
{
if (_handles != null)
{
foreach (var handle in _handles)
{
handle.ShouldBeVisible = false;
handle.Visibility = Visibility.Hidden;
}
}
}
public void ShowHandles()
{
if (_handles != null)
{
foreach (var handle in _handles)
{
handle.ShouldBeVisible = true;
handle.Visibility = Visibility.Visible;
handle.DecideVisiblity(handle.HandleLength);
}
}
}
}
}

2
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj

@ -78,6 +78,7 @@ @@ -78,6 +78,7 @@
</Compile>
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Controls\AdornerLayer.cs" />
<Compile Include="Controls\CanvasPositionHandle.cs" />
<Compile Include="Controls\ContainerDragHandle.cs" />
<Compile Include="Controls\DropDownButton.cs" />
<Compile Include="Controls\EnterTextBox.cs" />
@ -118,6 +119,7 @@ @@ -118,6 +119,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Extensions\BorderForInvisibleControl.cs" />
<Compile Include="Extensions\CanvasPositionExtension.cs" />
<Compile Include="Extensions\Initializers.cs" />
<Compile Include="Extensions\DefaultPlacementBehavior.cs">
<SubType>Code</SubType>

Loading…
Cancel
Save