From 89ec55d12f7a56fa5b30fbfe3f61ab0cbf2783d0 Mon Sep 17 00:00:00 2001 From: Kumar Devvrat Date: Sat, 31 Jul 2010 22:48:28 +0000 Subject: [PATCH] - Fix in-place editor placement and resolve issue when resizing while editing text too;caused an exception due to nested transactions. - Highlight text that can be edited with a border. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6337 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Controls/ControlStyles.xaml | 540 ++++++------------ .../Project/Controls/InPlaceEditor.cs | 138 +++-- .../Extensions/InPlaceEditorExtension.cs | 91 ++- .../Extensions/ResizeThumbExtension.cs | 13 +- 4 files changed, 340 insertions(+), 442 deletions(-) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml index af29907239..27b96be1f0 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ControlStyles.xaml @@ -1,105 +1,60 @@ - + - - - - + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/InPlaceEditor.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/InPlaceEditor.cs index 9143a643df..e8a69719fe 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/InPlaceEditor.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/InPlaceEditor.cs @@ -17,7 +17,7 @@ using System.Windows.Input; namespace ICSharpCode.WpfDesign.Designer.Controls { /// - /// Supports editing Text in the Designer + /// Supports editing Text in the Designer /// public class InPlaceEditor : TextBox { @@ -27,21 +27,23 @@ namespace ICSharpCode.WpfDesign.Designer.Controls } /// - /// This property is binded to the Text Property of the editor. + /// This property is binded to the Text Property of the editor. /// public static readonly DependencyProperty BindProperty = - DependencyProperty.Register("Bind", typeof (string), typeof (InPlaceEditor), new FrameworkPropertyMetadata()); + DependencyProperty.Register("Bind", typeof (string), typeof (InPlaceEditor), new FrameworkPropertyMetadata()); public string Bind{ - get { return (string) GetValue(BindProperty); } - set { SetValue(BindProperty, value); } - } + get { return (string) GetValue(BindProperty); } + set { SetValue(BindProperty, value); } + } readonly DesignItem designItem; ChangeGroup changeGroup; TextBlock textBlock; TextBox editor; + bool _isChangeGroupOpen; + /// /// This is the name of the property that is being edited for example Window.Title, Button.Content . /// @@ -53,12 +55,12 @@ namespace ICSharpCode.WpfDesign.Designer.Controls } public override void OnApplyTemplate() - { - base.OnApplyTemplate(); - editor = new TextBox(); - editor = Template.FindName("editor", this) as TextBox; // Gets the TextBox-editor from the Template - Debug.Assert(editor != null); - } + { + base.OnApplyTemplate(); + editor = new TextBox(); + editor = Template.FindName("editor", this) as TextBox; // Gets the TextBox-editor from the Template + Debug.Assert(editor != null); + } /// /// Binds the Text Property of the element extended with . @@ -68,66 +70,94 @@ namespace ICSharpCode.WpfDesign.Designer.Controls { Debug.Assert(textBlock!=null); this.textBlock = textBlock; - Binding binding = new Binding("Text"); - binding.Source = this.textBlock; - binding.Mode = BindingMode.TwoWay; - SetBinding(BindProperty, binding); - property=PropertyUpdated(textBlock); + Binding binding = new Binding("Text"); + binding.Source = this.textBlock; + binding.Mode = BindingMode.TwoWay; + SetBinding(BindProperty, binding); + property=PropertyUpdated(textBlock); } /// - /// Returns the property that is being edited in the element for example editing Window Title returns "Title", + /// Returns the property that is being edited in the element for example editing Window Title returns "Title", /// Button text as "Content". /// private string PropertyUpdated(TextBlock text) { MarkupObject obj = MarkupWriter.GetMarkupObjectFor(designItem.Component); - foreach (MarkupProperty property in obj.Properties) { - if (property.DependencyProperty != null && property.StringValue == textBlock.Text) - return property.Name; - } - return null; + foreach (MarkupProperty property in obj.Properties) { + if (property.DependencyProperty != null && property.StringValue == textBlock.Text) + return property.Name; + } + return null; } protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) - { - base.OnGotKeyboardFocus(e); - changeGroup = designItem.OpenGroup("Change Text"); - editor.Focus(); - } + { + base.OnGotKeyboardFocus(e); + StartEditing(); + } protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) - { - if (changeGroup != null) - changeGroup.Abort(); - if (textBlock != null) - textBlock.Visibility = Visibility.Visible; - base.OnLostKeyboardFocus(e); - } + { + if (changeGroup != null && _isChangeGroupOpen){ + changeGroup.Abort(); + _isChangeGroupOpen=false; + } + if (textBlock != null) + textBlock.Visibility = Visibility.Visible; + base.OnLostKeyboardFocus(e); + } /// /// Change is committed if the user releases the Escape Key. /// /// 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); - designItem.Properties[Control.FontFamilyProperty].SetValue(editor.FontFamily); - designItem.Properties[Control.FontSizeProperty].SetValue(editor.FontSize); - designItem.Properties[Control.FontStretchProperty].SetValue(editor.FontStretch); - designItem.Properties[Control.FontStyleProperty].SetValue(editor.FontStyle); - designItem.Properties[Control.FontWeightProperty].SetValue(editor.FontWeight); - - if (changeGroup != null) - changeGroup.Commit(); - changeGroup = null; - this.Visibility = Visibility.Hidden; - textBlock.Visibility = Visibility.Visible; - } - } + { + 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; + } + changeGroup = null; + this.Visibility = Visibility.Hidden; + textBlock.Visibility = Visibility.Visible; + } + } + + public void AbortEditing() + { + if(changeGroup!=null && _isChangeGroupOpen){ + changeGroup.Abort(); + _isChangeGroupOpen=false; + } + this.Visibility= Visibility.Hidden; + textBlock.Visibility=Visibility.Visible; + } + + public void StartEditing() + { + if(changeGroup==null){ + changeGroup = designItem.OpenGroup("Change Text"); + _isChangeGroupOpen=true; + } + this.Visibility=Visibility.Visible; + textBlock.Visibility=Visibility.Hidden; + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/InPlaceEditorExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/InPlaceEditorExtension.cs index e9c2bf1cdb..290ffd957d 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/InPlaceEditorExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/InPlaceEditorExtension.cs @@ -10,6 +10,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Windows; using System.Windows.Media; +using System.Windows.Media.Effects; using System.Windows.Input; using System.Windows.Controls; @@ -36,8 +37,8 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions bool isGettingDragged; // Flag to get/set whether the extended element is dragged. bool isMouseDown; // Flag to get/set whether left-button is down on the element. int numClicks; // No of left-button clicks on the element. - - public InPlaceEditorExtension() + + public InPlaceEditorExtension() { adornerPanel=new AdornerPanel(); isGettingDragged=false; @@ -77,10 +78,14 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions void PropertyChanged(object sender,PropertyChangedEventArgs e) { if (textBlock != null) { - if (e.PropertyName == "Width") - placement.XOffset = Mouse.GetPosition((IInputElement) element).X - Mouse.GetPosition(textBlock).X; - if (e.PropertyName == "Height") - placement.YOffset = Mouse.GetPosition((IInputElement) element).Y - Mouse.GetPosition(textBlock).Y; + if (e.PropertyName == "Width"){ + placement.XOffset = Mouse.GetPosition((IInputElement) element).X - Mouse.GetPosition(textBlock).X-2.8; + editor.MaxWidth = Math.Max((ModelTools.GetWidth(element) - placement.XOffset), 0); + } + if (e.PropertyName == "Height"){ + placement.YOffset = Mouse.GetPosition((IInputElement) element).Y - Mouse.GetPosition(textBlock).Y-1; + editor.MaxHeight = Math.Max((ModelTools.GetHeight(element) - placement.YOffset), 0); + } AdornerPanel.SetPlacement(editor, placement); } } @@ -96,8 +101,8 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions Debug.Assert(textBlock!=null); /* Gets the offset between the top-left corners of the element and the editor*/ - placement.XOffset = e.GetPosition(element).X - e.GetPosition(textBlock).X; - placement.YOffset = e.GetPosition(element).Y - e.GetPosition(textBlock).Y; + placement.XOffset = e.GetPosition(element).X - e.GetPosition(textBlock).X -2.8; + placement.YOffset = e.GetPosition(element).Y - e.GetPosition(textBlock).Y -1; placement.XRelativeToAdornerWidth = 0; placement.XRelativeToContentWidth = 0; placement.YRelativeToAdornerHeight = 0; @@ -107,9 +112,33 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions /* Change data context of the editor to the TextBlock */ editor.DataContext=textBlock; + /* Set MaxHeight and MaxWidth so that editor doesn't cross the boundaries of the control */ + var height = ModelTools.GetHeight(element); + var width = ModelTools.GetWidth(element); + editor.MaxHeight = Math.Max((height - placement.YOffset), 0); + editor.MaxWidth = Math.Max((width - placement.XOffset), 0); + /* Hides the TextBlock in control because of some minor offset in placement, overlaping makes text look fuzzy */ textBlock.Visibility = Visibility.Hidden; // - AdornerPanel.SetPlacement(editor, placement); + AdornerPanel.SetPlacement(editor, placement); + + RemoveBorder(); // Remove the highlight border. + } + + /// + /// Aborts the editing. This aborts the underlying change group of the editor + /// + public void AbortEdit() + { + editor.AbortEditing(); + } + + /// + /// Starts editing once again. This aborts the underlying change group of the editor + /// + public void StartEdit() + { + editor.StartEditing(); } #region MouseEvents @@ -142,6 +171,9 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions editor.Focus(); } } + DrawBorder((FrameworkElement) result.VisualHit); + }else{ + RemoveBorder(); } } @@ -164,6 +196,47 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions #endregion + #region HighlightBorder + private Border _border; + private sealed class BorderPlacement : AdornerPlacement + { + private readonly FrameworkElement _element; + + public BorderPlacement(FrameworkElement element) + { + _element = element; + } + + public override void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize) + { + Point p = _element.TranslatePoint(new Point(), panel.AdornedElement); + var rect = new Rect(p, _element.RenderSize); + rect.Inflate(3, 1); + adorner.Arrange(rect); + } + } + + private void DrawBorder(FrameworkElement item) + { + if (editor != null && editor.Visibility != Visibility.Visible) { + if (adornerPanel.Children.Contains(_border)) + adornerPanel.Children.Remove(_border); + _border = new Border {BorderBrush = Brushes.Gray, BorderThickness = new Thickness(1.4), ToolTip = "Edit this Text", SnapsToDevicePixels = true}; + var shadow = new DropShadowEffect {Color = Colors.LightGray, ShadowDepth = 3}; + _border.Effect = shadow; + var bp = new BorderPlacement(item); + AdornerPanel.SetPlacement(_border, bp); + adornerPanel.Children.Add(_border); + } + } + + private void RemoveBorder() + { + if (adornerPanel.Children.Contains(_border)) + adornerPanel.Children.Remove(_border); + } + #endregion + protected override void OnRemove() { ExtendedItem.PropertyChanged -= PropertyChanged; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs index e5d8edb39e..5a2db9fe33 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs @@ -106,9 +106,17 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions } Size oldSize; - + + // TODO : Remove all hide/show extensions from here. void drag_Started(DragListener drag) { + /* Abort editing Text if it was editing, because it interferes with the undo stack. */ + foreach(var extension in this.ExtendedItem.Extensions){ + if(extension is InPlaceEditorExtension){ + ((InPlaceEditorExtension)extension).AbortEdit(); + } + } + oldSize = new Size(ModelTools.GetWidth(ExtendedItem.View), ModelTools.GetHeight(ExtendedItem.View)); if (resizeBehavior != null) operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); @@ -163,7 +171,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions if (drag.IsCanceled) changeGroup.Abort(); else changeGroup.Commit(); changeGroup = null; - } + } _isResizing=false; HideSizeAndShowHandles(); } @@ -207,6 +215,7 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions r.Visibility = isVisible ? Visibility.Visible : Visibility.Hidden; } } + void ShowSizeAndHideHandles() { SizeDisplayExtension sizeDisplay=null;