Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/wpfdesigner@5914 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61pull/1/head
4 changed files with 329 additions and 1 deletions
@ -0,0 +1,131 @@ |
|||||||
|
// <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.ComponentModel; |
||||||
|
using System.Diagnostics; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows.Markup.Primitives; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Input; |
||||||
|
|
||||||
|
namespace ICSharpCode.WpfDesign.Designer.Controls |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Supports editing Text in the Designer
|
||||||
|
/// </summary>
|
||||||
|
public class InPlaceEditor : TextBox |
||||||
|
{ |
||||||
|
static InPlaceEditor() |
||||||
|
{ |
||||||
|
DefaultStyleKeyProperty.OverrideMetadata(typeof (InPlaceEditor), new FrameworkPropertyMetadata(typeof (InPlaceEditor))); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This property is binded to the Text Property of the editor.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty BindProperty = |
||||||
|
DependencyProperty.Register("Bind", typeof (string), typeof (InPlaceEditor), new FrameworkPropertyMetadata()); |
||||||
|
|
||||||
|
public string Bind{ |
||||||
|
get { return (string) GetValue(BindProperty); } |
||||||
|
set { SetValue(BindProperty, value); } |
||||||
|
} |
||||||
|
|
||||||
|
readonly DesignItem designItem; |
||||||
|
ChangeGroup changeGroup; |
||||||
|
TextBlock textBlock; |
||||||
|
TextBox editor; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is the name of the property that is being edited for example Window.Title, Button.Content .
|
||||||
|
/// </summary>
|
||||||
|
string property; |
||||||
|
|
||||||
|
public InPlaceEditor(DesignItem designItem) |
||||||
|
{ |
||||||
|
this.designItem=designItem; |
||||||
|
} |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binds the Text Property of the element extended with <see cref="Bind"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textBlock"></param>
|
||||||
|
public void SetBinding(TextBlock textBlock) |
||||||
|
{ |
||||||
|
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); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the property that is being edited in the element for example editing Window Title returns "Title",
|
||||||
|
/// Button text as "Content".
|
||||||
|
/// </summary>
|
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e) |
||||||
|
{ |
||||||
|
base.OnGotKeyboardFocus(e); |
||||||
|
changeGroup = designItem.OpenGroup("Change Text"); |
||||||
|
editor.Focus(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnLostKeyboardFocus(KeyboardFocusChangedEventArgs e) |
||||||
|
{ |
||||||
|
if (changeGroup != null) |
||||||
|
changeGroup.Abort(); |
||||||
|
base.OnLostKeyboardFocus(e); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Change is committed if the user releases the Escape Key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,176 @@ |
|||||||
|
// <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.ComponentModel; |
||||||
|
using System.Diagnostics; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Media; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Controls; |
||||||
|
|
||||||
|
using ICSharpCode.WpfDesign.Adorners; |
||||||
|
using ICSharpCode.WpfDesign.Extensions; |
||||||
|
using ICSharpCode.WpfDesign.Designer.Controls; |
||||||
|
|
||||||
|
namespace ICSharpCode.WpfDesign.Designer.Extensions |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Extends In-Place editor to edit any text in the designer which is wrapped in the Visual tree under TexBlock
|
||||||
|
/// </summary>
|
||||||
|
[ExtensionFor(typeof(FrameworkElement))] |
||||||
|
public class InPlaceEditorExtension : PrimarySelectionAdornerProvider |
||||||
|
{ |
||||||
|
AdornerPanel adornerPanel; |
||||||
|
RelativePlacement placement; |
||||||
|
InPlaceEditor editor; |
||||||
|
/// <summary> Is the element in the Visual tree of the extended element which is being edited. </summary>
|
||||||
|
TextBlock textBlock; |
||||||
|
FrameworkElement element; |
||||||
|
DesignPanel designPanel; |
||||||
|
|
||||||
|
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() |
||||||
|
{ |
||||||
|
adornerPanel=new AdornerPanel(); |
||||||
|
isGettingDragged=false; |
||||||
|
isMouseDown=Mouse.LeftButton==MouseButtonState.Pressed ? true : false; |
||||||
|
numClicks=0; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnInitialized() |
||||||
|
{ |
||||||
|
base.OnInitialized(); |
||||||
|
element = ExtendedItem.Component as FrameworkElement; |
||||||
|
editor = new InPlaceEditor(ExtendedItem); |
||||||
|
editor.DataContext = element; |
||||||
|
editor.Visibility = Visibility.Hidden; // Hide the editor first, It's visibility is governed by mouse events.
|
||||||
|
|
||||||
|
placement = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Top); |
||||||
|
adornerPanel.Children.Add(editor); |
||||||
|
Adorners.Add(adornerPanel); |
||||||
|
|
||||||
|
designPanel = ExtendedItem.Services.GetService<IDesignPanel>() as DesignPanel; |
||||||
|
Debug.Assert(designPanel!=null); |
||||||
|
|
||||||
|
/* Add mouse event handlers */ |
||||||
|
designPanel.PreviewMouseLeftButtonDown += MouseDown; |
||||||
|
designPanel.PreviewMouseLeftButtonUp += MouseUp; |
||||||
|
designPanel.PreviewMouseMove += MouseMove; |
||||||
|
|
||||||
|
/* To update the position of Editor in case of resize operation */ |
||||||
|
ExtendedItem.PropertyChanged += PropertyChanged; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether heigth/width have changed and updates the position of editor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
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; |
||||||
|
AdornerPanel.SetPlacement(editor, placement); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Places the handle from a calculated offset using Mouse Positon
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
void PlaceEditor(Visual text,MouseEventArgs e) |
||||||
|
{ |
||||||
|
textBlock = text as TextBlock; |
||||||
|
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.XRelativeToAdornerWidth = 0; |
||||||
|
placement.XRelativeToContentWidth = 0; |
||||||
|
placement.YRelativeToAdornerHeight = 0; |
||||||
|
placement.YRelativeToContentHeight = 0; |
||||||
|
editor.SetBinding(textBlock); |
||||||
|
|
||||||
|
/* Change data context of the editor to the TextBlock */ |
||||||
|
editor.DataContext=textBlock; |
||||||
|
|
||||||
|
/* 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); |
||||||
|
} |
||||||
|
|
||||||
|
#region MouseEvents
|
||||||
|
DesignPanelHitTestResult result; |
||||||
|
Point Current; |
||||||
|
Point Start; |
||||||
|
|
||||||
|
void MouseDown(object sender,MouseEventArgs e) |
||||||
|
{ |
||||||
|
result = designPanel.HitTest(e.GetPosition(designPanel), false, true); |
||||||
|
if(result.ModelHit==ExtendedItem && result.VisualHit is TextBlock) { |
||||||
|
Start = Mouse.GetPosition(null); |
||||||
|
Current = Start; |
||||||
|
isMouseDown = true; |
||||||
|
} |
||||||
|
numClicks++; |
||||||
|
} |
||||||
|
|
||||||
|
void MouseMove(object sender, MouseEventArgs e) |
||||||
|
{ |
||||||
|
Current += e.GetPosition(null) - Start; |
||||||
|
result = designPanel.HitTest(e.GetPosition(designPanel), false, true); |
||||||
|
if (result.ModelHit == ExtendedItem && result.VisualHit is TextBlock) { |
||||||
|
if (numClicks > 0) { |
||||||
|
if (isMouseDown && |
||||||
|
((Current-Start).X > SystemParameters.MinimumHorizontalDragDistance |
||||||
|
|| (Current-Start).Y > SystemParameters.MinimumVerticalDragDistance)) { |
||||||
|
|
||||||
|
isGettingDragged = true; |
||||||
|
editor.Focus(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void MouseUp(object sender,MouseEventArgs e) |
||||||
|
{ |
||||||
|
result = designPanel.HitTest(e.GetPosition(designPanel), false, true); |
||||||
|
if (result.ModelHit == ExtendedItem && result.VisualHit is TextBlock && numClicks>0){ |
||||||
|
if (!isGettingDragged) { |
||||||
|
PlaceEditor(result.VisualHit, e); |
||||||
|
editor.Visibility = Visibility.Visible; |
||||||
|
} |
||||||
|
}else{ // Clicked outside the Text - > hide the editor and make the actualt text visible again
|
||||||
|
editor.Visibility = Visibility.Hidden; |
||||||
|
if (textBlock != null) textBlock.Visibility = Visibility.Visible; |
||||||
|
} |
||||||
|
|
||||||
|
isMouseDown = false; |
||||||
|
isGettingDragged = false; |
||||||
|
} |
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
protected override void OnRemove() |
||||||
|
{ |
||||||
|
ExtendedItem.PropertyChanged -= PropertyChanged; |
||||||
|
designPanel.PreviewMouseLeftButtonDown -= MouseDown; |
||||||
|
designPanel.PreviewMouseMove -= MouseMove; |
||||||
|
designPanel.PreviewMouseLeftButtonUp -= MouseUp; |
||||||
|
base.OnRemove(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue