Browse Source

- Add tests for grid placement and tab/shift+tab navigation.

- Fix a bug in grid adorner where incorrect margins were calculated.
- clean-up in margin handle.
- change change group scheme for in-place editor to Enter for changes, Shift+Enter for newline and Esc for cancelling as suggested by Siegfried.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6398 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Kumar Devvrat 15 years ago
parent
commit
d2a1fe9e83
  1. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml
  2. 9
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GridAdorner.cs
  3. 77
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/InPlaceEditor.cs
  4. 585
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/MarginHandle.cs
  5. 438
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/MarginHandleExtension.cs
  6. 102
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/FocusNavigatorTests.cs
  7. 124
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/MockFocusNavigator.cs
  8. 22
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs
  9. 93
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/PlacementTests.cs
  10. 2
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/WpfDesign.Tests.csproj

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

@ -285,7 +285,7 @@ @@ -285,7 +285,7 @@
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:InPlaceEditor}">
<TextBox Name="editor" ToolTip="Edit the Text. Press ESC key to make changes." SnapsToDevicePixels="True" Padding="{Binding Path=Padding}" FontSize="{Binding Path=FontSize}" FontFamily="{Binding Path=FontFamily}" FontStyle="{Binding Path=FontStyle}" FontStretch="{Binding Path=FontStretch}" FontWeight="{Binding Path=FontWight}" Text="{Binding Path=Bind, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" AcceptsReturn="True" />
<TextBox Name="editor" SnapsToDevicePixels="True" Padding="{Binding Path=Padding}" FontSize="{Binding Path=FontSize}" FontFamily="{Binding Path=FontFamily}" FontStyle="{Binding Path=FontStyle}" FontStretch="{Binding Path=FontStretch}" FontWeight="{Binding Path=FontWight}" Text="{Binding Path=Bind, RelativeSource={RelativeSource Mode=TemplatedParent}, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" AcceptsReturn="True" />
</ControlTemplate>
</Setter.Value>
</Setter>

9
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/GridAdorner.cs

@ -28,8 +28,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -28,8 +28,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
bgBrush = new SolidColorBrush(Color.FromArgb(0x35, 0x1E, 0x90, 0xff));
bgBrush.Freeze();
//selBrush = new SolidColorBrush(Color.FromArgb(0xC0, 0xff, 0xb7, 0x4f));
//selBrush.Freeze();
}
readonly DesignItem gridItem;
@ -409,13 +407,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -409,13 +407,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
}
}
}
if (gridItem.Properties["Children"].CollectionElements.Count > 0) {
var operation = PlacementOperation.Start(gridItem.Properties["Children"].CollectionElements, PlacementType.Move);
foreach (var info in operation.PlacedItems) {
operation.CurrentContainerBehavior.SetPosition(info);
}
operation.Commit();
}
}
static void SplitLength(GridLength oldLength, double insertionPosition, double oldActualValue,

77
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/InPlaceEditor.cs

@ -60,6 +60,12 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -60,6 +60,12 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
editor = new TextBox();
editor = Template.FindName("editor", this) as TextBox; // Gets the TextBox-editor from the Template
Debug.Assert(editor != null);
editor.PreviewKeyDown+= delegate(object sender, KeyEventArgs e) {
if (e.Key == Key.Enter && (e.KeyboardDevice.Modifiers & ModifierKeys.Shift) != ModifierKeys.Shift)
{
e.Handled = true;
} };
ToolTip = "Edit the Text. Press"+Environment.NewLine+"Enter to make changes."+Environment.NewLine+"Shift+Enter to insert a newline."+Environment.NewLine+"Esc to cancel editing.";
}
/// <summary>
@ -102,9 +108,10 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -102,9 +108,10 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
if (changeGroup != null && _isChangeGroupOpen){
changeGroup.Abort();
_isChangeGroupOpen=false;
}
}
if (textBlock != null)
textBlock.Visibility = Visibility.Visible;
Reset();
base.OnLostKeyboardFocus(e);
}
@ -115,40 +122,64 @@ namespace ICSharpCode.WpfDesign.Designer.Controls @@ -115,40 +122,64 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
if (e.Key == Key.Escape) {
// Commit the changes to the DOM
if(property!=null)
designItem.Properties[property].SetValue(Bind);
if(designItem.Properties[Control.FontFamilyProperty].ValueOnInstance!=editor.FontFamily)
designItem.Properties[Control.FontFamilyProperty].SetValue(editor.FontFamily);
if((double)designItem.Properties[Control.FontSizeProperty].ValueOnInstance!=editor.FontSize)
designItem.Properties[Control.FontSizeProperty].SetValue(editor.FontSize);
if((FontStretch)designItem.Properties[Control.FontStretchProperty].ValueOnInstance!=editor.FontStretch)
designItem.Properties[Control.FontStretchProperty].SetValue(editor.FontStretch);
if((FontStyle)designItem.Properties[Control.FontStyleProperty].ValueOnInstance!=editor.FontStyle)
designItem.Properties[Control.FontStyleProperty].SetValue(editor.FontStyle);
if((FontWeight)designItem.Properties[Control.FontWeightProperty].ValueOnInstance!=editor.FontWeight)
designItem.Properties[Control.FontWeightProperty].SetValue(editor.FontWeight);
if (changeGroup != null && _isChangeGroupOpen){
changeGroup.Commit();
_isChangeGroupOpen=false;
if(e.KeyboardDevice.Modifiers != ModifierKeys.Shift) {
switch(e.Key) {
case Key.Enter:
// Commit the changes to DOM.
if(property!=null)
designItem.Properties[property].SetValue(Bind);
if(designItem.Properties[Control.FontFamilyProperty].ValueOnInstance!=editor.FontFamily)
designItem.Properties[Control.FontFamilyProperty].SetValue(editor.FontFamily);
if((double)designItem.Properties[Control.FontSizeProperty].ValueOnInstance!=editor.FontSize)
designItem.Properties[Control.FontSizeProperty].SetValue(editor.FontSize);
if((FontStretch)designItem.Properties[Control.FontStretchProperty].ValueOnInstance!=editor.FontStretch)
designItem.Properties[Control.FontStretchProperty].SetValue(editor.FontStretch);
if((FontStyle)designItem.Properties[Control.FontStyleProperty].ValueOnInstance!=editor.FontStyle)
designItem.Properties[Control.FontStyleProperty].SetValue(editor.FontStyle);
if((FontWeight)designItem.Properties[Control.FontWeightProperty].ValueOnInstance!=editor.FontWeight)
designItem.Properties[Control.FontWeightProperty].SetValue(editor.FontWeight);
if (changeGroup != null && _isChangeGroupOpen){
changeGroup.Commit();
_isChangeGroupOpen=false;
}
changeGroup = null;
this.Visibility = Visibility.Hidden;
textBlock.Visibility = Visibility.Visible;
break;
case Key.Escape:
AbortEditing();
break;
}
changeGroup = null;
this.Visibility = Visibility.Hidden;
textBlock.Visibility = Visibility.Visible;
}else if(e.Key == Key.Enter){
editor.Text.Insert(editor.CaretIndex, Environment.NewLine);
}
}
private void Reset()
{
if (textBlock != null) {
if (property != null)
textBlock.Text = (string) designItem.Properties[property].ValueOnInstance;
textBlock.FontFamily = (System.Windows.Media.FontFamily)designItem.Properties[Control.FontFamilyProperty].ValueOnInstance;
textBlock.FontSize = (double) designItem.Properties[Control.FontSizeProperty].ValueOnInstance;
textBlock.FontStretch = (FontStretch) designItem.Properties[Control.FontStretchProperty].ValueOnInstance;
textBlock.FontStretch = (FontStretch) designItem.Properties[Control.FontStretchProperty].ValueOnInstance;
textBlock.FontWeight = (FontWeight) designItem.Properties[Control.FontWeightProperty].ValueOnInstance;
}
}
public void AbortEditing()
{
if(changeGroup!=null && _isChangeGroupOpen){
Reset();
changeGroup.Abort();
_isChangeGroupOpen=false;
}
}
this.Visibility= Visibility.Hidden;
if(textBlock!=null)
textBlock.Visibility=Visibility.Visible;
Reset();
}
public void StartEditing()

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

@ -22,303 +22,302 @@ using ICSharpCode.WpfDesign.Adorners; @@ -22,303 +22,302 @@ using ICSharpCode.WpfDesign.Adorners;
namespace ICSharpCode.WpfDesign.Designer.Controls
{
/// <summary>
/// Adorner that displays the margin of a control in a Grid.
/// </summary>
public class MarginHandle : Control
{
/// <summary>
/// Places the Handle with a certain offset so the Handle does not interfere with selection outline.
/// </summary>
public static double HandleLengthOffset;
/// <summary>
/// Adorner that displays the margin of a control in a Grid.
/// </summary>
public class MarginHandle : Control
{
/// <summary>
/// Places the Handle with a certain offset so the Handle does not interfere with selection outline.
/// </summary>
public static double HandleLengthOffset;
static MarginHandle()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MarginHandle), new FrameworkPropertyMetadata(typeof(MarginHandle)));
HandleLengthOffset=2;
}
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MarginHandle), new FrameworkPropertyMetadata(typeof(MarginHandle)));
HandleLengthOffset=2;
}
/// <summary>
/// Dependency property for <see cref="HandleLength"/>.
/// </summary>
public static readonly DependencyProperty HandleLengthProperty
= DependencyProperty.Register("HandleLength", typeof(double), typeof(MarginHandle), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnHandleLengthChanged)));
/// <summary>
/// Dependency property for <see cref="HandleLength"/>.
/// </summary>
public static readonly DependencyProperty HandleLengthProperty
= DependencyProperty.Register("HandleLength", typeof(double), typeof(MarginHandle), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender, new PropertyChangedCallback(OnHandleLengthChanged)));
/// <summary>
/// Gets/Sets the length of Margin Handle.
/// </summary>
public double HandleLength{
get { return (double)GetValue(HandleLengthProperty); }
set { SetValue(HandleLengthProperty, value); }
}
readonly Grid grid;
readonly DesignItem adornedControlItem;
readonly AdornerPanel adornerPanel;
readonly HandleOrientation orientation;
readonly FrameworkElement adornedControl;
/// <summary>
/// Gets/Sets the length of Margin Handle.
/// </summary>
public double HandleLength{
get { return (double)GetValue(HandleLengthProperty); }
set { SetValue(HandleLengthProperty, value); }
}
readonly Grid grid;
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;
/// <summary>
/// Gets the Stub for this handle
/// </summary>
public MarginStub Stub {get; private set;}
/// <summary>
/// Gets/Sets the angle by which handle rotates.
/// </summary>
public double Angle { get; set; }
/// <summary>
/// Gets/Sets the angle by which the Margin display has to be rotated
/// </summary>
public double TextTransform{
get{
if((double)orientation==90 || (double)orientation == 180)
return 180;
if ((double)orientation == 270)
return 0;
return (double)orientation;
}
set{ }
}
/// <summary>
/// Decides the visiblity of handle/stub when <see cref="HandleLength"/> changes
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
public static void OnHandleLengthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MarginHandle mar=(MarginHandle)d;
mar.DecideVisiblity((double)e.NewValue);
}
/// <summary>
/// Decides whether to permanently display the handle or not.
/// </summary>
public bool ShouldBeVisible { get; set; }
/// <summary>
/// Decides whether stub has to be only displayed.
/// </summary>
public bool DisplayOnlyStub { get; set; }
/// <summary>
/// Gets the orientation of the handle.
/// </summary>
public HandleOrientation Orientation {
get { return orientation; }
}
/// <summary> This grid contains the handle line and the endarrow.</summary>
Grid lineArrow;
/// <summary>
/// Gets the Stub for this handle
/// </summary>
public MarginStub Stub {get; private set;}
/// <summary>
/// Gets/Sets the angle by which handle rotates.
/// </summary>
public double Angle { get; set; }
/// <summary>
/// Gets/Sets the angle by which the Margin display has to be rotated
/// </summary>
public double TextTransform{
get{
if((double)orientation==90 || (double)orientation == 180)
return 180;
if ((double)orientation == 270)
return 0;
return (double)orientation;
}
set{ }
}
/// <summary>
/// Decides the visiblity of handle/stub when <see cref="HandleLength"/> changes
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
public static void OnHandleLengthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MarginHandle mar=(MarginHandle)d;
mar.DecideVisiblity((double)e.NewValue);
}
/// <summary>
/// Decides whether to permanently display the handle or not.
/// </summary>
public bool ShouldBeVisible { get; set; }
/// <summary>
/// Decides whether stub has to be only displayed.
/// </summary>
public bool DisplayOnlyStub { get; set; }
/// <summary>
/// Gets the orientation of the handle.
/// </summary>
public HandleOrientation Orientation {
get { return orientation; }
}
public MarginHandle(DesignItem adornedControlItem, AdornerPanel adornerPanel, HandleOrientation orientation)
{
Debug.Assert(adornedControlItem!=null);
this.adornedControlItem = adornedControlItem;
this.adornerPanel = adornerPanel;
this.orientation = orientation;
Angle = (double)orientation;
grid=(Grid)adornedControlItem.Parent.Component;
adornedControl=(FrameworkElement)adornedControlItem.Component;
Stub = new MarginStub(this);
ShouldBeVisible=true;
BindAndPlaceHandle();
adornedControlItem.PropertyChanged += OnPropertyChanged;
OnPropertyChanged(this.adornedControlItem, new PropertyChangedEventArgs("HorizontalAlignment"));
OnPropertyChanged(this.adornedControlItem, new PropertyChangedEventArgs("VerticalAlignment"));
}
public MarginHandle(DesignItem adornedControlItem, AdornerPanel adornerPanel, HandleOrientation orientation)
{
Debug.Assert(adornedControlItem!=null);
this.adornedControlItem = adornedControlItem;
this.adornerPanel = adornerPanel;
this.orientation = orientation;
Angle = (double)orientation;
grid=(Grid)adornedControlItem.Parent.Component;
adornedControl=(FrameworkElement)adornedControlItem.Component;
Stub = new MarginStub(this);
ShouldBeVisible=true;
BindAndPlaceHandle();
adornedControlItem.PropertyChanged += OnPropertyChanged;
OnPropertyChanged(this.adornedControlItem, new PropertyChangedEventArgs("HorizontalAlignment"));
OnPropertyChanged(this.adornedControlItem, new PropertyChangedEventArgs("VerticalAlignment"));
}
/// <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();
Binding binding = new Binding();
binding.Source = adornedControl;
switch (orientation)
{
case HandleOrientation.Left:
binding.Path = new PropertyPath("Margin.Left");
placement = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Center);
placement.XOffset=-HandleLengthOffset;
break;
case HandleOrientation.Top:
binding.Path = new PropertyPath("Margin.Top");
placement = new RelativePlacement(HorizontalAlignment.Center, VerticalAlignment.Top);
placement.YOffset=-HandleLengthOffset;
break;
case HandleOrientation.Right:
binding.Path = new PropertyPath("Margin.Right");
placement = new RelativePlacement(HorizontalAlignment.Right, VerticalAlignment.Center);
placement.XOffset=HandleLengthOffset;
break;
case HandleOrientation.Bottom:
binding.Path = new PropertyPath("Margin.Bottom");
placement = new RelativePlacement(HorizontalAlignment.Center, VerticalAlignment.Bottom);
placement.YOffset=HandleLengthOffset;
break;
}
/// <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();
Binding binding = new Binding();
binding.Source = adornedControl;
switch (orientation)
{
case HandleOrientation.Left:
binding.Path = new PropertyPath("Margin.Left");
placement = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Center);
placement.XOffset=-HandleLengthOffset;
break;
case HandleOrientation.Top:
binding.Path = new PropertyPath("Margin.Top");
placement = new RelativePlacement(HorizontalAlignment.Center, VerticalAlignment.Top);
placement.YOffset=-HandleLengthOffset;
break;
case HandleOrientation.Right:
binding.Path = new PropertyPath("Margin.Right");
placement = new RelativePlacement(HorizontalAlignment.Right, VerticalAlignment.Center);
placement.XOffset=HandleLengthOffset;
break;
case HandleOrientation.Bottom:
binding.Path = new PropertyPath("Margin.Bottom");
placement = new RelativePlacement(HorizontalAlignment.Center, VerticalAlignment.Bottom);
placement.YOffset=HandleLengthOffset;
break;
}
binding.Mode = BindingMode.TwoWay;
SetBinding(HandleLengthProperty, binding);
binding.Mode = BindingMode.TwoWay;
SetBinding(HandleLengthProperty, binding);
AdornerPanel.SetPlacement(this, placement);
AdornerPanel.SetPlacement(Stub, placement);
DecideVisiblity(this.HandleLength);
}
AdornerPanel.SetPlacement(this, placement);
AdornerPanel.SetPlacement(Stub, placement);
DecideVisiblity(this.HandleLength);
}
/// <summary>
/// Decides the visibllity of Handle or stub,whichever is set and hides the line-endarrow if the control is near the Grid or goes out of it.
/// </summary>
/// <param name="handleLength"></param>
public void DecideVisiblity(double handleLength)
{
if (ShouldBeVisible)
{
if (!DisplayOnlyStub)
{
this.Visibility = handleLength != 0.0 ? Visibility.Visible : Visibility.Hidden;
if (this.lineArrow != null)
{
lineArrow.Visibility = handleLength < 25 ? Visibility.Hidden : Visibility.Visible;
}
Stub.Visibility = this.Visibility == Visibility.Visible ? Visibility.Hidden : Visibility.Visible;
}
else
{
this.Visibility = Visibility.Hidden;
Stub.Visibility = Visibility.Visible;
}
}
else {
this.Visibility = Visibility.Hidden;
Stub.Visibility = Visibility.Hidden;
}
}
void OnPropertyChanged(object sender,PropertyChangedEventArgs e)
{
if(e.PropertyName=="HorizontalAlignment" && (orientation==HandleOrientation.Left || orientation==HandleOrientation.Right)) {
var ha = (HorizontalAlignment) adornedControlItem.Properties[FrameworkElement.HorizontalAlignmentProperty].ValueOnInstance;
if(ha==HorizontalAlignment.Stretch) {
DisplayOnlyStub = false;
}else if(ha==HorizontalAlignment.Center) {
DisplayOnlyStub = true;
} else
DisplayOnlyStub = ha.ToString() != orientation.ToString();
}
/// <summary>
/// Decides the visibllity of Handle or stub,whichever is set and hides the line-endarrow if the control is near the Grid or goes out of it.
/// </summary>
public void DecideVisiblity(double handleLength)
{
if (ShouldBeVisible)
{
if (!DisplayOnlyStub)
{
this.Visibility = handleLength != 0.0 ? Visibility.Visible : Visibility.Hidden;
if (this.lineArrow != null)
{
lineArrow.Visibility = handleLength < 25 ? Visibility.Hidden : Visibility.Visible;
}
Stub.Visibility = this.Visibility == Visibility.Visible ? Visibility.Hidden : Visibility.Visible;
}
else
{
this.Visibility = Visibility.Hidden;
Stub.Visibility = Visibility.Visible;
}
}
else {
this.Visibility = Visibility.Hidden;
Stub.Visibility = Visibility.Hidden;
}
}
void OnPropertyChanged(object sender,PropertyChangedEventArgs e)
{
if(e.PropertyName=="HorizontalAlignment" && (orientation==HandleOrientation.Left || orientation==HandleOrientation.Right)) {
var ha = (HorizontalAlignment) adornedControlItem.Properties[FrameworkElement.HorizontalAlignmentProperty].ValueOnInstance;
if(ha==HorizontalAlignment.Stretch) {
DisplayOnlyStub = false;
}else if(ha==HorizontalAlignment.Center) {
DisplayOnlyStub = true;
} else
DisplayOnlyStub = ha.ToString() != orientation.ToString();
}
if(e.PropertyName=="VerticalAlignment" && (orientation==HandleOrientation.Top || orientation==HandleOrientation.Bottom)) {
var va = (VerticalAlignment)adornedControlItem.Properties[FrameworkElement.VerticalAlignmentProperty].ValueOnInstance;
if(e.PropertyName=="VerticalAlignment" && (orientation==HandleOrientation.Top || orientation==HandleOrientation.Bottom)) {
var va = (VerticalAlignment)adornedControlItem.Properties[FrameworkElement.VerticalAlignmentProperty].ValueOnInstance;
if(va==VerticalAlignment.Stretch) {
DisplayOnlyStub = false;
} else if(va==VerticalAlignment.Center) {
DisplayOnlyStub = true;
} else
DisplayOnlyStub = va.ToString() != orientation.ToString();
}
DecideVisiblity(this.HandleLength);
}
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
base.OnMouseEnter(e);
this.Cursor = Cursors.Hand;
}
if(va==VerticalAlignment.Stretch) {
DisplayOnlyStub = false;
} else if(va==VerticalAlignment.Center) {
DisplayOnlyStub = true;
} else
DisplayOnlyStub = va.ToString() != orientation.ToString();
}
DecideVisiblity(this.HandleLength);
}
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
base.OnMouseEnter(e);
this.Cursor = Cursors.Hand;
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
this.Cursor = Cursors.Arrow;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
lineArrow = new Grid();
lineArrow = (Grid)Template.FindName("lineArrow", this) as Grid;
Debug.Assert(lineArrow != null);
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
this.Cursor = Cursors.Arrow;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
lineArrow = new Grid();
lineArrow = (Grid)Template.FindName("lineArrow", this) as Grid;
Debug.Assert(lineArrow != null);
}
}
}
/// <summary>
/// Display a stub indicating that the margin is not set.
/// </summary>
public class MarginStub : Control
{
MarginHandle marginHandle;
/// <summary>
/// Gets the margin handle using this stub.
/// </summary>
public MarginHandle Handle{
get { return marginHandle; }
}
static MarginStub()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MarginStub), new FrameworkPropertyMetadata(typeof(MarginStub)));
}
/// <summary>
/// Display a stub indicating that the margin is not set.
/// </summary>
public class MarginStub : Control
{
MarginHandle marginHandle;
/// <summary>
/// Gets the margin handle using this stub.
/// </summary>
public MarginHandle Handle{
get { return marginHandle; }
}
static MarginStub()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MarginStub), new FrameworkPropertyMetadata(typeof(MarginStub)));
}
public MarginStub(MarginHandle marginHandle)
{
this.marginHandle = marginHandle;
}
public MarginStub(MarginHandle marginHandle)
{
this.marginHandle = marginHandle;
}
protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
marginHandle.DecideVisiblity(marginHandle.HandleLength);
}
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
base.OnMouseEnter(e);
this.Cursor = Cursors.Hand;
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
this.Cursor = Cursors.Arrow;
}
}
protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
marginHandle.DecideVisiblity(marginHandle.HandleLength);
}
protected override void OnMouseEnter(System.Windows.Input.MouseEventArgs e)
{
base.OnMouseEnter(e);
this.Cursor = Cursors.Hand;
}
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
this.Cursor = Cursors.Arrow;
}
}
/// <summary>
/// Specifies the Handle orientation
/// </summary>
public enum HandleOrientation
{
/* Rotation of the handle is done with respect to right orientation and in clockwise direction*/
/// <summary>
/// Specifies the Handle orientation
/// </summary>
public enum HandleOrientation
{
/* Rotation of the handle is done with respect to right orientation and in clockwise direction*/
/// <summary>
/// Indicates that the margin handle is left-oriented and rotated 180 degrees with respect to <see cref="Right"/>.
/// </summary>
Left = 180,
/// <summary>
/// Indicates that the margin handle is top-oriented and rotated 270 degrees with respect to <see cref="Right"/>.
/// </summary>
Top = 270,
/// <summary>
/// Indicates that the margin handle is right.
/// </summary>
Right = 0,
/// <summary>
/// Indicates that the margin handle is left-oriented and rotated 180 degrees with respect to <see cref="Right"/>.
/// </summary>
Bottom = 90
}
/// <summary>
/// Indicates that the margin handle is left-oriented and rotated 180 degrees with respect to <see cref="Right"/>.
/// </summary>
Left = 180,
/// <summary>
/// Indicates that the margin handle is top-oriented and rotated 270 degrees with respect to <see cref="Right"/>.
/// </summary>
Top = 270,
/// <summary>
/// Indicates that the margin handle is right.
/// </summary>
Right = 0,
/// <summary>
/// Indicates that the margin handle is left-oriented and rotated 180 degrees with respect to <see cref="Right"/>.
/// </summary>
Bottom = 90
}
}
namespace ICSharpCode.WpfDesign.Designer.Controls.Converters
@ -327,21 +326,21 @@ namespace ICSharpCode.WpfDesign.Designer.Controls.Converters @@ -327,21 +326,21 @@ namespace ICSharpCode.WpfDesign.Designer.Controls.Converters
/// Offset the Handle Length with MarginHandle.HandleLengthOffset
/// </summary>
public class HandleLengthWithOffset : IValueConverter
{
public static HandleLengthWithOffset Instance = new HandleLengthWithOffset();
{
public static HandleLengthWithOffset Instance = new HandleLengthWithOffset();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is double) {
return Math.Max((double)value - MarginHandle.HandleLengthOffset,0);
}
return null;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is double) {
return Math.Max((double)value - MarginHandle.HandleLengthOffset,0);
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}

438
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/MarginHandleExtension.cs

@ -16,237 +16,225 @@ using ICSharpCode.WpfDesign.Extensions; @@ -16,237 +16,225 @@ using ICSharpCode.WpfDesign.Extensions;
namespace ICSharpCode.WpfDesign.Designer.Extensions
{
[ExtensionFor(typeof(FrameworkElement))]
[ExtensionServer(typeof(PrimarySelectionExtensionServer))]
public class MarginHandleExtension : AdornerProvider
{
//TODO : Use array to store all the handles.
private MarginHandle _leftHandle, _topHandle, _rightHandle, _bottomHandle;
private Grid _grid;
protected override void OnInitialized()
{
base.OnInitialized();
if (this.ExtendedItem.Parent != null)
{
if (this.ExtendedItem.Parent.ComponentType == typeof(Grid)){
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)
{
_grid = this.ExtendedItem.Parent.View as Grid;
_leftHandle = new MarginHandle(this.ExtendedItem, adornerPanel, HandleOrientation.Left);
_topHandle = new MarginHandle(this.ExtendedItem, adornerPanel, HandleOrientation.Top);
_rightHandle = new MarginHandle(this.ExtendedItem, adornerPanel, HandleOrientation.Right);
_bottomHandle = new MarginHandle(this.ExtendedItem, adornerPanel, HandleOrientation.Bottom);
_leftHandle.MouseLeftButtonDown += OnMouseDown;
_leftHandle.Stub.MouseLeftButtonDown += OnMouseDown;
[ExtensionFor(typeof(FrameworkElement))]
[ExtensionServer(typeof(PrimarySelectionExtensionServer))]
public class MarginHandleExtension : AdornerProvider
{
private MarginHandle []_handles;
private MarginHandle _leftHandle, _topHandle, _rightHandle, _bottomHandle;
private Grid _grid;
protected override void OnInitialized()
{
base.OnInitialized();
if (this.ExtendedItem.Parent != null)
{
if (this.ExtendedItem.Parent.ComponentType == typeof(Grid)){
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)
{
_grid = this.ExtendedItem.Parent.View as Grid;
_handles = new[]
{
_leftHandle = new MarginHandle(ExtendedItem, adornerPanel, HandleOrientation.Left),
_topHandle = new MarginHandle(ExtendedItem, adornerPanel, HandleOrientation.Top),
_rightHandle = new MarginHandle(ExtendedItem, adornerPanel, HandleOrientation.Right),
_bottomHandle = new MarginHandle(ExtendedItem, adornerPanel, HandleOrientation.Bottom),
};
foreach(var handle in _handles) {
handle.MouseLeftButtonDown += OnMouseDown;
handle.Stub.PreviewMouseLeftButtonDown += OnMouseDown;
}
}
if (adornerPanel != null)
this.Adorners.Add(adornerPanel);
}
}
}
#region Change margin through handle/stub
private void OnMouseDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
var row = (int) this.ExtendedItem.Properties.GetAttachedProperty(Grid.RowProperty).ValueOnInstance;
var rowSpan = (int) this.ExtendedItem.Properties.GetAttachedProperty(Grid.RowSpanProperty).ValueOnInstance;
_topHandle.MouseLeftButtonDown += OnMouseDown;
_topHandle.Stub.MouseLeftButtonDown += OnMouseDown;
var column = (int) this.ExtendedItem.Properties.GetAttachedProperty(Grid.ColumnProperty).ValueOnInstance;
var columnSpan = (int) this.ExtendedItem.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).ValueOnInstance;
_rightHandle.MouseLeftButtonDown += OnMouseDown;
_rightHandle.Stub.MouseLeftButtonDown += OnMouseDown;
var margin = (Thickness) this.ExtendedItem.Properties[FrameworkElement.MarginProperty].ValueOnInstance;
_bottomHandle.MouseLeftButtonDown += OnMouseDown;
_bottomHandle.Stub.MouseLeftButtonDown += OnMouseDown;
}
if (adornerPanel != null)
this.Adorners.Add(adornerPanel);
}
}
}
private void OnMouseDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
var row = (int) this.ExtendedItem.Properties.GetAttachedProperty(Grid.RowProperty).ValueOnInstance;
var rowSpan = (int) this.ExtendedItem.Properties.GetAttachedProperty(Grid.RowSpanProperty).ValueOnInstance;
var point = this.ExtendedItem.View.TranslatePoint(new Point(), _grid);
var position = new Rect(point, this.ExtendedItem.View.RenderSize);
MarginHandle handle = null;
if (sender is MarginHandle)
handle = sender as MarginHandle;
if (sender is MarginStub)
handle = ((MarginStub) sender).Handle;
if (handle != null) {
switch (handle.Orientation) {
case HandleOrientation.Left:
if (_rightHandle.Visibility == Visibility.Visible) {
if (_leftHandle.Visibility == Visibility.Visible) {
margin.Left = 0;
this.ExtendedItem.Properties[FrameworkElement.WidthProperty].SetValue(position.Width);
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Right);
} else {
var leftMargin = position.Left - GetColumnOffset(column);
margin.Left = leftMargin;
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].Reset();
}
} else {
if (_leftHandle.Visibility == Visibility.Visible) {
margin.Left = 0;
var rightMargin = GetColumnOffset(column + columnSpan) - position.Right;
margin.Right = rightMargin;
var column = (int) this.ExtendedItem.Properties.GetAttachedProperty(Grid.ColumnProperty).ValueOnInstance;
var columnSpan = (int) this.ExtendedItem.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).ValueOnInstance;
this.ExtendedItem.Properties[FrameworkElement.WidthProperty].SetValue(position.Width);
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Right);
} else {
var leftMargin = position.Left - GetColumnOffset(column);
margin.Left = leftMargin;
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Left);
}
}
break;
case HandleOrientation.Top:
if (_bottomHandle.Visibility == Visibility.Visible) {
if (_topHandle.Visibility == Visibility.Visible) {
margin.Top = 0;
this.ExtendedItem.Properties[FrameworkElement.HeightProperty].SetValue(position.Height);
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Bottom);
} else {
var topMargin = position.Top - GetRowOffset(row);
margin.Top = topMargin;
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].Reset();
}
} else {
if (_topHandle.Visibility == Visibility.Visible) {
margin.Top = 0;
var bottomMargin = GetRowOffset(row + rowSpan) - position.Bottom;
margin.Bottom = bottomMargin;
var margin = (Thickness) this.ExtendedItem.Properties[FrameworkElement.MarginProperty].ValueOnInstance;
this.ExtendedItem.Properties[FrameworkElement.HeightProperty].SetValue(position.Height);
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Bottom);
} else {
var topMargin = position.Top - GetRowOffset(row);
margin.Top = topMargin;
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Top);
}
}
break;
case HandleOrientation.Right:
if (_leftHandle.Visibility == Visibility.Visible) {
if (_rightHandle.Visibility == Visibility.Visible) {
margin.Right = 0;
this.ExtendedItem.Properties[FrameworkElement.WidthProperty].SetValue(position.Width);
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Left);
} else {
var rightMargin = GetColumnOffset(column + columnSpan) - position.Right;
margin.Right = rightMargin;
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].Reset();
}
} else {
if (_rightHandle.Visibility == Visibility.Visible) {
margin.Right = 0;
var leftMargin = position.Left - GetColumnOffset(column);
margin.Left = leftMargin;
var point = this.ExtendedItem.View.TranslatePoint(new Point(), _grid);
var position = new Rect(point, this.ExtendedItem.View.RenderSize);
MarginHandle handle = null;
if (sender is MarginHandle)
handle = sender as MarginHandle;
if (sender is MarginStub)
handle = ((MarginStub) sender).Handle;
if (handle != null) {
switch (handle.Orientation) {
case HandleOrientation.Left:
if (_rightHandle.Visibility == Visibility.Visible) {
if (_leftHandle.Visibility == Visibility.Visible) {
margin.Left = 0;
this.ExtendedItem.Properties[FrameworkElement.WidthProperty].SetValue(position.Width);
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Right);
} else {
var leftMargin = position.Left - GetColumnOffset(column);
margin.Left = leftMargin;
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].Reset();
}
} else {
if (_leftHandle.Visibility == Visibility.Visible) {
margin.Left = 0;
var rightMargin = GetColumnOffset(column + columnSpan) - position.Right;
margin.Right = rightMargin;
this.ExtendedItem.Properties[FrameworkElement.WidthProperty].SetValue(position.Width);
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Left);
} else {
var rightMargin = GetColumnOffset(column + columnSpan) - position.Right;
margin.Right = rightMargin;
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Right);
}
}
break;
case HandleOrientation.Bottom:
if (_topHandle.Visibility == Visibility.Visible) {
if (_bottomHandle.Visibility == Visibility.Visible) {
margin.Bottom = 0;
this.ExtendedItem.Properties[FrameworkElement.HeightProperty].SetValue(position.Height);
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Top);
} else {
var bottomMargin = GetRowOffset(row + rowSpan) - position.Bottom;
margin.Bottom = bottomMargin;
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].Reset();
}
} else {
if (_bottomHandle.Visibility == Visibility.Visible) {
margin.Bottom = 0;
var topMargin = position.Top - GetRowOffset(row);
margin.Top = topMargin;
this.ExtendedItem.Properties[FrameworkElement.WidthProperty].SetValue(position.Width);
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Right);
} else {
var leftMargin = position.Left - GetColumnOffset(column);
margin.Left = leftMargin;
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Left);
}
}
break;
case HandleOrientation.Top:
if (_bottomHandle.Visibility == Visibility.Visible) {
if (_topHandle.Visibility == Visibility.Visible) {
margin.Top = 0;
this.ExtendedItem.Properties[FrameworkElement.HeightProperty].SetValue(position.Height);
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Bottom);
} else {
var topMargin = position.Top - GetRowOffset(row);
margin.Top = topMargin;
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].Reset();
}
} else {
if (_topHandle.Visibility == Visibility.Visible) {
margin.Top = 0;
var bottomMargin = GetRowOffset(row + rowSpan) - position.Bottom;
margin.Bottom = bottomMargin;
this.ExtendedItem.Properties[FrameworkElement.HeightProperty].SetValue(position.Height);
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Top);
} else {
var bottomMargin = GetRowOffset(row + rowSpan) - position.Bottom;
margin.Bottom = bottomMargin;
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Bottom);
}
}
break;
}
}
this.ExtendedItem.Properties[FrameworkElement.MarginProperty].SetValue(margin);
}
private double GetColumnOffset(int index)
{
if (_grid != null) {
// 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;
if (index < _grid.ColumnDefinitions.Count)
return _grid.ColumnDefinitions[index].Offset;
return _grid.ActualWidth;
}
return 0;
}
this.ExtendedItem.Properties[FrameworkElement.HeightProperty].SetValue(position.Height);
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Bottom);
} else {
var topMargin = position.Top - GetRowOffset(row);
margin.Top = topMargin;
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Top);
}
}
break;
case HandleOrientation.Right:
if (_leftHandle.Visibility == Visibility.Visible) {
if (_rightHandle.Visibility == Visibility.Visible) {
margin.Right = 0;
this.ExtendedItem.Properties[FrameworkElement.WidthProperty].SetValue(position.Width);
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Left);
} else {
var rightMargin = GetColumnOffset(column + columnSpan) - position.Right;
margin.Right = rightMargin;
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].Reset();
}
} else {
if (_rightHandle.Visibility == Visibility.Visible) {
margin.Right = 0;
var leftMargin = position.Left - GetColumnOffset(column);
margin.Left = leftMargin;
this.ExtendedItem.Properties[FrameworkElement.WidthProperty].SetValue(position.Width);
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Left);
} else {
var rightMargin = GetColumnOffset(column + columnSpan) - position.Right;
margin.Right = rightMargin;
this.ExtendedItem.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(HorizontalAlignment.Right);
}
}
break;
case HandleOrientation.Bottom:
if (_topHandle.Visibility == Visibility.Visible) {
if (_bottomHandle.Visibility == Visibility.Visible) {
margin.Bottom = 0;
this.ExtendedItem.Properties[FrameworkElement.HeightProperty].SetValue(position.Height);
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Top);
} else {
var bottomMargin = GetRowOffset(row + rowSpan) - position.Bottom;
margin.Bottom = bottomMargin;
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].Reset();
}
} else {
if (_bottomHandle.Visibility == Visibility.Visible) {
margin.Bottom = 0;
var topMargin = position.Top - GetRowOffset(row);
margin.Top = topMargin;
this.ExtendedItem.Properties[FrameworkElement.HeightProperty].SetValue(position.Height);
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Top);
} else {
var bottomMargin = GetRowOffset(row + rowSpan) - position.Bottom;
margin.Bottom = bottomMargin;
this.ExtendedItem.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(VerticalAlignment.Bottom);
}
}
break;
}
}
this.ExtendedItem.Properties[FrameworkElement.MarginProperty].SetValue(margin);
}
private double GetColumnOffset(int index)
{
if (_grid != null) {
// 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;
if (index < _grid.ColumnDefinitions.Count)
return _grid.ColumnDefinitions[index].Offset;
return _grid.ActualWidth;
}
return 0;
}
private double GetRowOffset(int index)
{
if (_grid != null) {
if (index == 0)
return 0;
if (index < _grid.RowDefinitions.Count)
return _grid.RowDefinitions[index].Offset;
return _grid.ActualHeight;
}
return 0;
}
public void HideHandles()
{
if (_leftHandle != null && _topHandle != null && _rightHandle != null && _bottomHandle != null) {
_leftHandle.Visibility=Visibility.Hidden;
_leftHandle.ShouldBeVisible=false;
_topHandle.Visibility=Visibility.Hidden;
_topHandle.ShouldBeVisible=false;
_rightHandle.Visibility=Visibility.Hidden;
_rightHandle.ShouldBeVisible=false;
_bottomHandle.Visibility=Visibility.Hidden;
_bottomHandle.ShouldBeVisible=false;
}
}
public void ShowHandles()
{
if (_leftHandle != null && _topHandle != null && _rightHandle != null && _bottomHandle != null){
_leftHandle.Visibility=Visibility.Visible;
_leftHandle.ShouldBeVisible=true;
_leftHandle.DecideVisiblity(_leftHandle.HandleLength);
_topHandle.Visibility=Visibility.Visible;
_topHandle.ShouldBeVisible=true;
_rightHandle.DecideVisiblity(_rightHandle.HandleLength);
_rightHandle.Visibility=Visibility.Visible;
_rightHandle.ShouldBeVisible=true;
_rightHandle.DecideVisiblity(_rightHandle.HandleLength);
_bottomHandle.Visibility=Visibility.Visible;
_bottomHandle.ShouldBeVisible=true;
_bottomHandle.DecideVisiblity(_bottomHandle.HandleLength);
}
}
}
private double GetRowOffset(int index)
{
if (_grid != null) {
if (index == 0)
return 0;
if (index < _grid.RowDefinitions.Count)
return _grid.RowDefinitions[index].Offset;
return _grid.ActualHeight;
}
return 0;
}
#endregion
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);
}
}
}
}
}

102
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/FocusNavigatorTests.cs

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Kumar Devvrat"/>
// <version>$Revision: $</version>
// </file>
using System;
using NUnit.Framework;
namespace ICSharpCode.WpfDesign.Tests.Designer
{
[TestFixture]
public class FocusNavigationTests : ModelTestHelper
{
[Test]
public void SingleChildHierarchyFocusForward()
{
var grid = CreateGridContextWithDesignSurface("<Button><Button/></Button>");
var firstButton = grid.ContentProperty.CollectionElements[0];
var secondButton = firstButton.ContentProperty.Value;
var selection = grid.Services.Selection;
selection.SetSelectedComponents(new[] {grid});
var focusNavigator = new MockFocusNavigator(grid.Context);
/* Move focus forward Tab */
focusNavigator.MoveFocusForward();
Assert.AreEqual(firstButton, selection.PrimarySelection);
focusNavigator.MoveFocusForward();
Assert.AreEqual(secondButton, selection.PrimarySelection);
focusNavigator.MoveFocusForward();
Assert.AreEqual(grid, selection.PrimarySelection);
}
[Test]
public void SingleChildHierarchyFocusBack()
{
var grid = CreateGridContextWithDesignSurface("<Button><Button/></Button>");
var firstButton = grid.ContentProperty.CollectionElements[0];
var secondButton = firstButton.ContentProperty.Value;
var selection = grid.Services.Selection;
selection.SetSelectedComponents(new[] {grid});
var focusNavigator = new MockFocusNavigator(grid.Context);
/* Move focus back Shift + Tab */
focusNavigator.MoveFocusBack();
Assert.AreEqual(secondButton, selection.PrimarySelection);
focusNavigator.MoveFocusBack();
Assert.AreEqual(firstButton, selection.PrimarySelection);
}
[Test]
public void MultipleChildHierarchyFocusForward()
{
var grid = CreateGridContextWithDesignSurface("<Button/><Grid><Button/></Grid>");
var firstButton = grid.ContentProperty.CollectionElements[0];
var innerGrid = grid.ContentProperty.CollectionElements[1];
var innerGridButton = innerGrid.ContentProperty.CollectionElements[0];
var selection = grid.Services.Selection;
selection.SetSelectedComponents(new[] { grid });
var focusNavigator = new MockFocusNavigator(grid.Context);
/* Move focus forward Tab */
focusNavigator.MoveFocusForward();
Assert.AreEqual(firstButton, selection.PrimarySelection);
focusNavigator.MoveFocusForward();
Assert.AreEqual(innerGrid, selection.PrimarySelection);
focusNavigator.MoveFocusForward();
Assert.AreEqual(innerGridButton, selection.PrimarySelection);
focusNavigator.MoveFocusForward();
Assert.AreEqual(grid, selection.PrimarySelection);
}
[Test]
public void MultipleChildHierarchyFocusBack()
{
var grid = CreateGridContextWithDesignSurface("<Button/><Grid><Button/></Grid>");
var firstButton = grid.ContentProperty.CollectionElements[0];
var innerGrid = grid.ContentProperty.CollectionElements[1];
var innerGridButton = innerGrid.ContentProperty.CollectionElements[0];
var selection = grid.Services.Selection;
selection.SetSelectedComponents(new[] { grid });
var focusNavigator = new MockFocusNavigator(grid.Context);
/* Move focus back Shift + Tab */
focusNavigator.MoveFocusBack();
Assert.AreEqual(innerGridButton, selection.PrimarySelection);
focusNavigator.MoveFocusBack();
Assert.AreEqual(innerGrid, selection.PrimarySelection);
focusNavigator.MoveFocusBack();
Assert.AreEqual(firstButton, selection.PrimarySelection);
focusNavigator.MoveFocusBack();
Assert.AreEqual(grid, selection.PrimarySelection);
focusNavigator.MoveFocusBack();
Assert.AreEqual(innerGridButton, selection.PrimarySelection);
}
}
}

124
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/MockFocusNavigator.cs

@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <author name="Kumar Devvrat"/>
// <version>$Revision: $</version>
// </file>
using System;
using System.Linq;
using ICSharpCode.WpfDesign.Designer;
namespace ICSharpCode.WpfDesign.Tests.Designer
{
internal class MockFocusNavigator
{
private readonly DesignContext _context;
internal MockFocusNavigator(DesignContext context)
{
_context = context;
}
/// <summary>
/// Moves the Focus down the tree.
/// </summary>
internal void MoveFocusForward()
{
ISelectionService selection = _context.Services.Selection;
DesignItem item = selection.PrimarySelection;
selection.SetSelectedComponents(selection.SelectedItems, SelectionTypes.Remove);
if (item != GetLastElement()) {
if (item.ContentProperty != null) {
if (item.ContentProperty.IsCollection) {
if (item.ContentProperty.CollectionElements.Count != 0) {
if (ModelTools.CanSelectComponent(item.ContentProperty.CollectionElements.First()))
selection.SetSelectedComponents(new DesignItem[] {item.ContentProperty.CollectionElements.First()}, SelectionTypes.Primary);
else
SelectNextInPeers(item);
} else
SelectNextInPeers(item);
} else if (item.ContentProperty.Value != null) {
if (ModelTools.CanSelectComponent(item.ContentProperty.Value))
selection.SetSelectedComponents(new DesignItem[] {item.ContentProperty.Value}, SelectionTypes.Primary);
else
SelectNextInPeers(item);
} else {
SelectNextInPeers(item);
}
} else {
SelectNextInPeers(item);
}
} else {
//if the element was last element move focus to the root element to keep a focus cycle.
selection.SetSelectedComponents(new DesignItem[] {_context.RootItem}, SelectionTypes.Primary);
}
}
/// <summary>
/// Moves focus up-the-tree.
/// </summary>
internal void MoveFocusBack()
{
ISelectionService selection = _context.Services.Selection;
DesignItem item = selection.PrimarySelection;
if (item != _context.RootItem) {
if (item.Parent != null && item.Parent.ContentProperty.IsCollection) {
int index = item.Parent.ContentProperty.CollectionElements.IndexOf(item);
if (index != 0) {
if (ModelTools.CanSelectComponent(item.Parent.ContentProperty.CollectionElements.ElementAt(index - 1)))
selection.SetSelectedComponents(new DesignItem[] {item.Parent.ContentProperty.CollectionElements.ElementAt(index - 1)}, SelectionTypes.Primary);
} else {
if (ModelTools.CanSelectComponent(item.Parent))
selection.SetSelectedComponents(new DesignItem[] {item.Parent}, SelectionTypes.Primary);
}
} else {
if (ModelTools.CanSelectComponent(item.Parent))
selection.SetSelectedComponents(new DesignItem[] {item.Parent}, SelectionTypes.Primary);
}
} else {
// if the element was root item move focus again to the last element.
selection.SetSelectedComponents(new DesignItem[] {GetLastElement()}, SelectionTypes.Primary);
}
}
/// <summary>
/// Gets the last element in the element hierarchy.
/// </summary>
private DesignItem GetLastElement()
{
DesignItem item = _context.RootItem;
while (item != null && item.ContentProperty != null) {
if (item.ContentProperty.IsCollection) {
if (item.ContentProperty.CollectionElements.Count != 0) {
if (ModelTools.CanSelectComponent(item.ContentProperty.CollectionElements.Last()))
item = item.ContentProperty.CollectionElements.Last();
else
break;
} else
break;
} else {
if (item.ContentProperty.Value != null)
item = item.ContentProperty.Value;
else
break;
}
}
return item;
}
/// <summary>
/// Select the next element in the element collection if <paramref name="item"/> parent's had it's content property as collection.
/// </summary>
private void SelectNextInPeers(DesignItem item)
{
ISelectionService selection = _context.Services.Selection;
if (item.Parent != null && item.Parent.ContentProperty != null) {
if (item.Parent.ContentProperty.IsCollection) {
int index = item.Parent.ContentProperty.CollectionElements.IndexOf(item);
if (index != item.Parent.ContentProperty.CollectionElements.Count)
selection.SetSelectedComponents(new DesignItem[] {item.Parent.ContentProperty.CollectionElements.ElementAt(index + 1)}, SelectionTypes.Primary);
}
}
}
}
}

22
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/ModelTestHelper.cs

@ -78,13 +78,23 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -78,13 +78,23 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
}
protected DesignItem CreateGridContext(string xaml)
{
XamlDesignContext context = CreateContext(@"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
{
XamlDesignContext context = CreateContext(@"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
" + xaml + "</Grid>");
var grid = (Grid)context.RootItem.Component;
var gridChild = context.Services.Component.GetDesignItem(grid.Children[0]);
return gridChild;
}
var grid = (Grid)context.RootItem.Component;
var gridChild = context.Services.Component.GetDesignItem(grid.Children[0]);
return gridChild;
}
protected DesignItem CreateGridContextWithDesignSurface(string xaml)
{
var surface = new DesignSurface();
var xamlWithGrid=@"<Grid xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" >
" + xaml + "</Grid>";
surface.LoadDesigner(new XmlTextReader(new StringReader(xamlWithGrid)), new XamlLoadSettings());
Assert.IsNotNull(surface.DesignContext.RootItem);
return surface.DesignContext.RootItem;
}
static string ItemIdentity(DesignItem item)
{

93
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Tests/Designer/PlacementTests.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Windows;
using System.Windows.Controls;
using NUnit.Framework;
using ICSharpCode.WpfDesign;
using ICSharpCode.WpfDesign.Designer;
@ -31,17 +32,17 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -31,17 +32,17 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
}
internal static void Resize(Rect rect,params DesignItem[] items)
{
PlacementOperation operation = PlacementOperation.Start(items, PlacementType.Resize);
foreach(var info in operation.PlacedItems) {
info.Bounds = rect;
operation.CurrentContainerBehavior.SetPosition(info);
}
operation.Commit();
}
{
PlacementOperation operation = PlacementOperation.Start(items, PlacementType.Resize);
foreach(var info in operation.PlacedItems) {
info.Bounds = rect;
operation.CurrentContainerBehavior.SetPosition(info);
}
operation.Commit();
}
[Test]
[Ignore] //Currently bounds calculated using visuals
[Ignore("Currently bounds calculated using visuals")]
public void MoveFixedWidthButton()
{
DesignItem button = CreateCanvasContext("<Button Width='100' Height='200'/>");
@ -56,5 +57,79 @@ namespace ICSharpCode.WpfDesign.Tests.Designer @@ -56,5 +57,79 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
Move(new Vector(50, 25), button);
AssertCanvasDesignerOutput(@"<Button Canvas.Left=""50"" Canvas.Top=""25"" />", button.Context);
}
#region Grid Placement Tests
private DesignItem _buttonInGridWithAutoSize;
private DesignItem _buttonIsGridWithFixedSize;
[TestFixtureSetUp]
public void Intialize()
{
_buttonInGridWithAutoSize=CreateGridContext("<Button/>");
Move(new Vector(50,25),_buttonInGridWithAutoSize);
_buttonIsGridWithFixedSize=CreateGridContext("<Button HorizontalAlignment=\"Left\" VerticalAlignment=\"Top\" Width=\"50\" Height=\"50\"/>");
Move(new Vector(50,25),_buttonIsGridWithFixedSize);
}
[Test]
public void AssertAlignmentsForAutoSize()
{
Assert.AreEqual(HorizontalAlignment.Stretch,_buttonInGridWithAutoSize.Properties[FrameworkElement.HorizontalAlignmentProperty].ValueOnInstance);
Assert.AreEqual(VerticalAlignment.Stretch,_buttonInGridWithAutoSize.Properties[FrameworkElement.VerticalAlignmentProperty].ValueOnInstance);
}
[Test]
public void AssertAlignmentForFixedSize()
{
Assert.AreEqual(HorizontalAlignment.Left,_buttonIsGridWithFixedSize.Properties[FrameworkElement.HorizontalAlignmentProperty].ValueOnInstance);
Assert.AreEqual(VerticalAlignment.Top,_buttonIsGridWithFixedSize.Properties[FrameworkElement.VerticalAlignmentProperty].ValueOnInstance);
}
[Test]
public void AssertMarginForAutoSize()
{
Assert.AreEqual(new Thickness(50,25,-50,-25),_buttonInGridWithAutoSize.Properties[FrameworkElement.MarginProperty].ValueOnInstance);
}
[Test]
public void AssertMarginForFixedSize()
{
Assert.AreEqual(new Thickness(50,25,0,0),_buttonIsGridWithFixedSize.Properties[FrameworkElement.MarginProperty].ValueOnInstance);
}
[Test]
public void AssertRowColumnForAutoSize()
{
Assert.AreEqual(0,_buttonInGridWithAutoSize.Properties.GetAttachedProperty(Grid.RowProperty).ValueOnInstance);
Assert.AreEqual(1,_buttonInGridWithAutoSize.Properties.GetAttachedProperty(Grid.RowSpanProperty).ValueOnInstance);
Assert.AreEqual(0,_buttonInGridWithAutoSize.Properties.GetAttachedProperty(Grid.ColumnProperty).ValueOnInstance);
Assert.AreEqual(1,_buttonInGridWithAutoSize.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).ValueOnInstance);
}
[Test]
public void AssetRowColumnForFixedSize()
{
Assert.AreEqual(0, _buttonIsGridWithFixedSize.Properties.GetAttachedProperty(Grid.RowProperty).ValueOnInstance);
Assert.AreEqual(1, _buttonIsGridWithFixedSize.Properties.GetAttachedProperty(Grid.RowSpanProperty).ValueOnInstance);
Assert.AreEqual(0, _buttonIsGridWithFixedSize.Properties.GetAttachedProperty(Grid.ColumnProperty).ValueOnInstance);
Assert.AreEqual(1, _buttonIsGridWithFixedSize.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).ValueOnInstance);
}
[Test]
public void AssertSizeForAutoSize()
{
Assert.AreEqual(double.NaN,_buttonInGridWithAutoSize.Properties[FrameworkElement.HeightProperty].ValueOnInstance);
Assert.AreEqual(double.NaN,_buttonInGridWithAutoSize.Properties[FrameworkElement.WidthProperty].ValueOnInstance);
}
[Test]
[Ignore("Bounds calculated using Visuals")]
public void AssertSizeForFixedSize()
{
Assert.AreEqual(50,_buttonIsGridWithFixedSize.Properties[FrameworkElement.HeightProperty].ValueOnInstance);
Assert.AreEqual(50,_buttonIsGridWithFixedSize.Properties[FrameworkElement.WidthProperty].ValueOnInstance);
}
#endregion
}
}

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

@ -55,7 +55,9 @@ @@ -55,7 +55,9 @@
<Link>GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="Designer\FocusNavigatorTests.cs" />
<Compile Include="Designer\MarginHandleTests.cs" />
<Compile Include="Designer\MockFocusNavigator.cs" />
<Compile Include="Designer\ModelTestHelper.cs" />
<Compile Include="Designer\ModelTests.cs" />
<Compile Include="Designer\PlacementTests.cs" />

Loading…
Cancel
Save