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 16 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 @@
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type Controls:InPlaceEditor}"> <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> </ControlTemplate>
</Setter.Value> </Setter.Value>
</Setter> </Setter>

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

@ -28,8 +28,6 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
bgBrush = new SolidColorBrush(Color.FromArgb(0x35, 0x1E, 0x90, 0xff)); bgBrush = new SolidColorBrush(Color.FromArgb(0x35, 0x1E, 0x90, 0xff));
bgBrush.Freeze(); bgBrush.Freeze();
//selBrush = new SolidColorBrush(Color.FromArgb(0xC0, 0xff, 0xb7, 0x4f));
//selBrush.Freeze();
} }
readonly DesignItem gridItem; readonly DesignItem gridItem;
@ -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, 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
editor = new TextBox(); editor = new TextBox();
editor = Template.FindName("editor", this) as TextBox; // Gets the TextBox-editor from the Template editor = Template.FindName("editor", this) as TextBox; // Gets the TextBox-editor from the Template
Debug.Assert(editor != null); 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> /// <summary>
@ -102,9 +108,10 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
if (changeGroup != null && _isChangeGroupOpen){ if (changeGroup != null && _isChangeGroupOpen){
changeGroup.Abort(); changeGroup.Abort();
_isChangeGroupOpen=false; _isChangeGroupOpen=false;
} }
if (textBlock != null) if (textBlock != null)
textBlock.Visibility = Visibility.Visible; textBlock.Visibility = Visibility.Visible;
Reset();
base.OnLostKeyboardFocus(e); base.OnLostKeyboardFocus(e);
} }
@ -115,40 +122,64 @@ namespace ICSharpCode.WpfDesign.Designer.Controls
protected override void OnKeyUp(KeyEventArgs e) protected override void OnKeyUp(KeyEventArgs e)
{ {
base.OnKeyUp(e); base.OnKeyUp(e);
if (e.Key == Key.Escape) { if(e.KeyboardDevice.Modifiers != ModifierKeys.Shift) {
// Commit the changes to the DOM switch(e.Key) {
if(property!=null) case Key.Enter:
designItem.Properties[property].SetValue(Bind); // Commit the changes to DOM.
if(designItem.Properties[Control.FontFamilyProperty].ValueOnInstance!=editor.FontFamily) if(property!=null)
designItem.Properties[Control.FontFamilyProperty].SetValue(editor.FontFamily); designItem.Properties[property].SetValue(Bind);
if((double)designItem.Properties[Control.FontSizeProperty].ValueOnInstance!=editor.FontSize) if(designItem.Properties[Control.FontFamilyProperty].ValueOnInstance!=editor.FontFamily)
designItem.Properties[Control.FontSizeProperty].SetValue(editor.FontSize); designItem.Properties[Control.FontFamilyProperty].SetValue(editor.FontFamily);
if((FontStretch)designItem.Properties[Control.FontStretchProperty].ValueOnInstance!=editor.FontStretch) if((double)designItem.Properties[Control.FontSizeProperty].ValueOnInstance!=editor.FontSize)
designItem.Properties[Control.FontStretchProperty].SetValue(editor.FontStretch); designItem.Properties[Control.FontSizeProperty].SetValue(editor.FontSize);
if((FontStyle)designItem.Properties[Control.FontStyleProperty].ValueOnInstance!=editor.FontStyle) if((FontStretch)designItem.Properties[Control.FontStretchProperty].ValueOnInstance!=editor.FontStretch)
designItem.Properties[Control.FontStyleProperty].SetValue(editor.FontStyle); designItem.Properties[Control.FontStretchProperty].SetValue(editor.FontStretch);
if((FontWeight)designItem.Properties[Control.FontWeightProperty].ValueOnInstance!=editor.FontWeight) if((FontStyle)designItem.Properties[Control.FontStyleProperty].ValueOnInstance!=editor.FontStyle)
designItem.Properties[Control.FontWeightProperty].SetValue(editor.FontWeight); designItem.Properties[Control.FontStyleProperty].SetValue(editor.FontStyle);
if((FontWeight)designItem.Properties[Control.FontWeightProperty].ValueOnInstance!=editor.FontWeight)
if (changeGroup != null && _isChangeGroupOpen){ designItem.Properties[Control.FontWeightProperty].SetValue(editor.FontWeight);
changeGroup.Commit();
_isChangeGroupOpen=false; 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; }else if(e.Key == Key.Enter){
this.Visibility = Visibility.Hidden; editor.Text.Insert(editor.CaretIndex, Environment.NewLine);
textBlock.Visibility = Visibility.Visible; }
}
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() public void AbortEditing()
{ {
if(changeGroup!=null && _isChangeGroupOpen){ if(changeGroup!=null && _isChangeGroupOpen){
Reset();
changeGroup.Abort(); changeGroup.Abort();
_isChangeGroupOpen=false; _isChangeGroupOpen=false;
} }
this.Visibility= Visibility.Hidden; this.Visibility= Visibility.Hidden;
if(textBlock!=null) if(textBlock!=null)
textBlock.Visibility=Visibility.Visible; textBlock.Visibility=Visibility.Visible;
Reset();
} }
public void StartEditing() public void StartEditing()

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

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

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

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

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

@ -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 @@
// <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
} }
protected DesignItem CreateGridContext(string xaml) 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>"); " + xaml + "</Grid>");
var grid = (Grid)context.RootItem.Component; var grid = (Grid)context.RootItem.Component;
var gridChild = context.Services.Component.GetDesignItem(grid.Children[0]); var gridChild = context.Services.Component.GetDesignItem(grid.Children[0]);
return gridChild; 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) static string ItemIdentity(DesignItem item)
{ {

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

@ -7,6 +7,7 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Controls;
using NUnit.Framework; using NUnit.Framework;
using ICSharpCode.WpfDesign; using ICSharpCode.WpfDesign;
using ICSharpCode.WpfDesign.Designer; using ICSharpCode.WpfDesign.Designer;
@ -31,17 +32,17 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
} }
internal static void Resize(Rect rect,params DesignItem[] items) internal static void Resize(Rect rect,params DesignItem[] items)
{ {
PlacementOperation operation = PlacementOperation.Start(items, PlacementType.Resize); PlacementOperation operation = PlacementOperation.Start(items, PlacementType.Resize);
foreach(var info in operation.PlacedItems) { foreach(var info in operation.PlacedItems) {
info.Bounds = rect; info.Bounds = rect;
operation.CurrentContainerBehavior.SetPosition(info); operation.CurrentContainerBehavior.SetPosition(info);
} }
operation.Commit(); operation.Commit();
} }
[Test] [Test]
[Ignore] //Currently bounds calculated using visuals [Ignore("Currently bounds calculated using visuals")]
public void MoveFixedWidthButton() public void MoveFixedWidthButton()
{ {
DesignItem button = CreateCanvasContext("<Button Width='100' Height='200'/>"); DesignItem button = CreateCanvasContext("<Button Width='100' Height='200'/>");
@ -56,5 +57,79 @@ namespace ICSharpCode.WpfDesign.Tests.Designer
Move(new Vector(50, 25), button); Move(new Vector(50, 25), button);
AssertCanvasDesignerOutput(@"<Button Canvas.Left=""50"" Canvas.Top=""25"" />", button.Context); 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 @@
<Link>GlobalAssemblyInfo.cs</Link> <Link>GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="AssemblyInfo.cs" /> <Compile Include="AssemblyInfo.cs" />
<Compile Include="Designer\FocusNavigatorTests.cs" />
<Compile Include="Designer\MarginHandleTests.cs" /> <Compile Include="Designer\MarginHandleTests.cs" />
<Compile Include="Designer\MockFocusNavigator.cs" />
<Compile Include="Designer\ModelTestHelper.cs" /> <Compile Include="Designer\ModelTestHelper.cs" />
<Compile Include="Designer\ModelTests.cs" /> <Compile Include="Designer\ModelTests.cs" />
<Compile Include="Designer\PlacementTests.cs" /> <Compile Include="Designer\PlacementTests.cs" />

Loading…
Cancel
Save