diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Redo.png b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Redo.png
new file mode 100644
index 0000000000..9ce8542694
Binary files /dev/null and b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Redo.png differ
diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Undo.png b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Undo.png
new file mode 100644
index 0000000000..dba9b3a735
Binary files /dev/null and b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Images/Undo.png differ
diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/StandaloneDesigner.csproj b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/StandaloneDesigner.csproj
index 520825522b..8fef61a195 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/StandaloneDesigner.csproj
+++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/StandaloneDesigner.csproj
@@ -61,5 +61,8 @@
{66A378A1-E9F4-4AD5-8946-D0EC06C2902F}
WpfDesign
+
+
+
\ No newline at end of file
diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml
index d0aa4321eb..b0d9485d57 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml
+++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml
@@ -4,17 +4,22 @@
xmlns:designer="clr-namespace:ICSharpCode.WpfDesign.Designer;assembly=ICSharpCode.WpfDesign.Designer"
Title="StandaloneDesigner" Height="500" Width="700"
>
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
]]>
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
diff --git a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs
index a92c9954fd..73c686b713 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
+using System.Windows.Input;
using System.Windows.Markup;
using System.Xml;
using ICSharpCode.WpfDesign;
@@ -21,6 +22,11 @@ namespace StandaloneDesigner
{
try {
InitializeComponent();
+ foreach (object o in toolBar.Items) {
+ if (o is Button) {
+ (o as Button).CommandTarget = designSurface;
+ }
+ }
} catch (Exception ex) {
MessageBox.Show(ex.ToString());
Close();
@@ -32,6 +38,7 @@ namespace StandaloneDesigner
TextBox CodeTextBox;
DesignSurface designSurface;
PropertyEditor propertyEditor;
+ ToolBar toolBar;
#endif
void tabControlSelectionChanged(object sender, RoutedEventArgs e)
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs
index 0df8ca341f..f961073478 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs
@@ -6,11 +6,14 @@
//
using System;
+using System.Diagnostics;
using System.Windows;
+using System.Windows.Input;
using System.Windows.Controls;
using System.Xml;
using ICSharpCode.WpfDesign.Designer.Controls;
+using ICSharpCode.WpfDesign.Designer.Services;
namespace ICSharpCode.WpfDesign.Designer
{
@@ -34,7 +37,53 @@ namespace ICSharpCode.WpfDesign.Designer
_scrollViewer.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
_scrollViewer.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible;
this.VisualChild = _scrollViewer;
+
+ this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, OnUndoExecuted, OnUndoCanExecute));
+ this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, OnRedoExecuted, OnRedoCanExecute));
+ }
+
+ #region Undo/Redo
+ UndoService _undoService;
+
+ private UndoService UndoService {
+ get { return _undoService; }
+ set {
+ if (_undoService != null) {
+ _undoService.UndoStackChanged -= OnUndoStackChanged;
+ }
+ _undoService = value;
+ if (_undoService != null) {
+ _undoService.UndoStackChanged += OnUndoStackChanged;
+ }
+ CommandManager.InvalidateRequerySuggested();
+ }
+ }
+
+ void OnUndoExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ _undoService.Undo();
+ }
+
+ void OnUndoCanExecute(object sender, CanExecuteRoutedEventArgs e)
+ {
+ e.CanExecute = _undoService != null && _undoService.CanUndo;
+ }
+
+ void OnRedoExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ _undoService.Redo();
+ }
+
+ void OnRedoCanExecute(object sender, CanExecuteRoutedEventArgs e)
+ {
+ e.CanExecute = _undoService != null && _undoService.CanRedo;
+ }
+
+ void OnUndoStackChanged(object sender, EventArgs e)
+ {
+ CommandManager.InvalidateRequerySuggested();
}
+ #endregion
///
/// Gets the active design context.
@@ -70,6 +119,7 @@ namespace ICSharpCode.WpfDesign.Designer
designPanelBorder.Padding = new Thickness(10);
_designPanel.Child = designPanelBorder;
designPanelBorder.Child = context.RootItem.View;
+ UndoService = context.Services.GetService();
}
///
@@ -82,6 +132,7 @@ namespace ICSharpCode.WpfDesign.Designer
_designPanel.Child = null;
_designPanel.Adorners.Clear();
_designPanel.MarkerCanvas.Children.Clear();
+ UndoService = null;
}
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultChildResizeSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultChildResizeSupport.cs
index e8a9bfdb72..5ccab5530d 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultChildResizeSupport.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/DefaultChildResizeSupport.cs
@@ -66,10 +66,10 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
public void Resize(DesignItem childItem, double horizontalChange, double verticalChange, HorizontalAlignment horizontal, VerticalAlignment vertical)
{
RelativePlacement p = (RelativePlacement)GetPlacement(childItem, horizontalChange, verticalChange, horizontal, vertical);
- Resize(childItem, p, horizontalChange, verticalChange, horizontal, vertical);
+ Resize(childItem, p, horizontal, vertical);
}
- static void Resize(DesignItem childItem, RelativePlacement p, double horizontalChange, double verticalChange, HorizontalAlignment horizontal, VerticalAlignment vertical)
+ static void Resize(DesignItem childItem, RelativePlacement p, HorizontalAlignment horizontal, VerticalAlignment vertical)
{
DesignItemProperty margin = childItem.Properties[FrameworkElement.MarginProperty];
if (margin.IsSet) {
@@ -81,6 +81,9 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
margin.SetValue(t);
}
+ double horizontalChange = p.WidthOffset;
+ double verticalChange = p.HeightOffset;
+
FrameworkElement child = (FrameworkElement)childItem.Component;
double width = child.Width;
double height = child.Height;
@@ -130,8 +133,8 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
rp.XOffset -= horizontalChange;
rp.WidthOffset += horizontalChange;
} else {
- rp.XOffset -= horizontalChange / 2;
- rp.WidthOffset += horizontalChange;
+ rp.XOffset -= horizontalChange;
+ rp.WidthOffset += horizontalChange * 2;
}
if (vertical == VerticalAlignment.Bottom) {
@@ -140,8 +143,8 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
rp.YOffset -= verticalChange;
rp.HeightOffset += verticalChange;
} else {
- rp.YOffset -= verticalChange / 2;
- rp.HeightOffset += verticalChange;
+ rp.YOffset -= verticalChange;
+ rp.HeightOffset += verticalChange * 2;
}
return rp;
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 1e85071f9f..b257301f63 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/ResizeThumbExtension.cs
@@ -85,10 +85,13 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
adornerPanel.ClearValue(AdornerPanel.CursorProperty);
if (resizeBehavior != null) {
- resizeBehavior.Resize(this.ExtendedItem,
- FixChange(e.HorizontalChange, horizontalAlignment),
- FixChange(e.VerticalChange, verticalAlignment),
- horizontalAlignment, verticalAlignment);
+ using (ChangeGroup group = this.ExtendedItem.OpenGroup("Resize")) {
+ resizeBehavior.Resize(this.ExtendedItem,
+ FixChange(e.HorizontalChange, horizontalAlignment),
+ FixChange(e.VerticalChange, verticalAlignment),
+ horizontalAlignment, verticalAlignment);
+ group.Commit();
+ }
}
};
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/UndoService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/UndoService.cs
index ea0474b0ef..65132ab885 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/UndoService.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/UndoService.cs
@@ -17,7 +17,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services
void Do();
void Undo();
- string Title { get; set; }
+ string Title { get; }
}
#endregion
@@ -100,9 +100,10 @@ namespace ICSharpCode.WpfDesign.Designer.Services
{
AssertState(TransactionState.Undone);
try {
- for (int i = 0; i < items.Count; i--) {
+ for (int i = 0; i < items.Count; i++) {
items[i].Do();
}
+ _state = TransactionState.Completed;
} catch {
_state = TransactionState.Failed;
try {
@@ -144,18 +145,10 @@ namespace ICSharpCode.WpfDesign.Designer.Services
Stack _undoStack = new Stack();
Stack _redoStack = new Stack();
- UndoTransaction CurrentTransaction {
- get {
- if (_transactionStack.Count == 0)
- return null;
- else
- return _transactionStack.Peek();
- }
- }
-
internal UndoTransaction StartTransaction()
{
UndoTransaction t = new UndoTransaction();
+ _transactionStack.Push(t);
t.Committed += TransactionFinished;
t.RolledBack += TransactionFinished;
t.Committed += delegate(object sender, EventArgs e) {
@@ -177,6 +170,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services
item.Do();
_undoStack.Push(item);
_redoStack.Clear();
+ OnUndoStackChanged(EventArgs.Empty);
} else {
_transactionStack.Peek().Execute(item);
}
@@ -189,6 +183,18 @@ namespace ICSharpCode.WpfDesign.Designer.Services
get { return _undoStack.Count > 0; }
}
+ ///
+ /// Is raised when the undo stack has changed.
+ ///
+ public event EventHandler UndoStackChanged;
+
+ void OnUndoStackChanged(EventArgs e)
+ {
+ if (UndoStackChanged != null) {
+ UndoStackChanged(this, e);
+ }
+ }
+
///
/// Undoes the last action.
///
@@ -202,6 +208,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services
try {
item.Undo();
_redoStack.Push(item);
+ OnUndoStackChanged(EventArgs.Empty);
} catch {
// state might be invalid now, clear stacks to prevent getting more inconsistencies
Clear();
@@ -209,6 +216,28 @@ namespace ICSharpCode.WpfDesign.Designer.Services
}
}
+ ///
+ /// Gets the list of names of the available actions on the undo stack.
+ ///
+ public IEnumerable UndoActions {
+ get {
+ foreach (ITransactionItem item in _undoStack) {
+ yield return item.Title;
+ }
+ }
+ }
+
+ ///
+ /// Gets the list of names of the available actions on the undo stack.
+ ///
+ public IEnumerable RedoActions {
+ get {
+ foreach (ITransactionItem item in _redoStack) {
+ yield return item.Title;
+ }
+ }
+ }
+
///
/// Gets if there are redo actions available.
///
@@ -227,6 +256,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services
try {
item.Do();
_undoStack.Push(item);
+ OnUndoStackChanged(EventArgs.Empty);
} catch {
// state might be invalid now, clear stacks to prevent getting more inconsistencies
Clear();
@@ -241,6 +271,7 @@ namespace ICSharpCode.WpfDesign.Designer.Services
{
_undoStack.Clear();
_redoStack.Clear();
+ OnUndoStackChanged(EventArgs.Empty);
}
}
#endregion
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
index 000bab5e3d..e4506eccd0 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
@@ -11,6 +11,7 @@
using System;
using System.Diagnostics;
using ICSharpCode.WpfDesign.XamlDom;
+using ICSharpCode.WpfDesign.Designer.Services;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
@@ -88,42 +89,28 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
}
}
- #if EventHandlerDebugging
- private event EventHandler _ValueChanged;
-
+ // There may be multipley XamlModelProperty instances for the same property,
+ // so this class may not have any mutable fields / events - instead,
+ // we forward all event handlers to the XamlProperty.
public override event EventHandler ValueChanged {
add {
+ #if EventHandlerDebugging
if (ValueChangedEventHandlers == 0) {
Debug.WriteLine("ValueChangedEventHandlers is now > 0");
}
ValueChangedEventHandlers++;
- _ValueChanged += value;
+ #endif
+ _property.ValueChanged += value;
}
remove {
+ #if EventHandlerDebugging
ValueChangedEventHandlers--;
if (ValueChangedEventHandlers == 0) {
Debug.WriteLine("ValueChangedEventHandlers reached 0");
}
- _ValueChanged -= value;
- }
- }
- #else
- public override event EventHandler ValueChanged;
- #endif
-
- void OnValueChanged(EventArgs e)
- {
- #if EventHandlerDebugging
- if (_ValueChanged != null) {
- _ValueChanged(this, EventArgs.Empty);
- }
- #else
- if (ValueChanged != null) {
- ValueChanged(this, EventArgs.Empty);
+ #endif
+ _property.ValueChanged -= value;
}
- #endif
-
- _designItem.NotifyPropertyChanged(this.Name);
}
public override object ValueOnInstance {
@@ -162,10 +149,9 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public override void SetValue(object value)
{
- _property.ValueOnInstance = value;
-
+ XamlPropertyValue newValue;
if (value == null) {
- _property.PropertyValue = _property.ParentObject.OwnerDocument.CreateNullValue();
+ newValue = _property.ParentObject.OwnerDocument.CreateNullValue();
} else {
XamlComponentService componentService = _designItem.ComponentService;
@@ -173,22 +159,94 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
if (designItem != null) {
if (designItem.Parent != null)
throw new DesignerException("Cannot set value to design item that already has a parent");
- _property.PropertyValue = designItem.XamlObject;
+ newValue = designItem.XamlObject;
} else {
XamlPropertyValue val = _property.ParentObject.OwnerDocument.CreatePropertyValue(value, _property);
designItem = componentService.RegisterXamlComponentRecursive(val as XamlObject);
- _property.PropertyValue = val;
+ newValue = val;
}
}
- OnValueChanged(EventArgs.Empty);
+ UndoService undoService = _designItem.Services.GetService();
+ if (undoService != null)
+ undoService.Execute(new PropertyChangeAction(this, true, newValue, value));
+ else
+ SetValueInternal(value, newValue);
+ }
+
+ void SetValueInternal(object value, XamlPropertyValue newValue)
+ {
+ _property.ValueOnInstance = value;
+ _property.PropertyValue = newValue;
+
+ _designItem.NotifyPropertyChanged(this.Name);
}
public override void Reset()
+ {
+ UndoService undoService = _designItem.Services.GetService();
+ if (undoService != null)
+ undoService.Execute(new PropertyChangeAction(this, false, null, null));
+ else
+ ResetInternal();
+ }
+
+ void ResetInternal()
{
if (_property.IsSet) {
_property.Reset();
- OnValueChanged(EventArgs.Empty);
+ _designItem.NotifyPropertyChanged(this.Name);
+ }
+ }
+
+ sealed class PropertyChangeAction : ITransactionItem
+ {
+ XamlModelProperty property;
+
+ bool newIsSet;
+ XamlPropertyValue newValue;
+ object newObject;
+
+ XamlPropertyValue oldValue;
+ object oldObject;
+ bool oldIsSet;
+
+ public PropertyChangeAction(XamlModelProperty property, bool newIsSet, XamlPropertyValue newValue, object newObject)
+ {
+ this.property = property;
+
+ this.newIsSet = newIsSet;
+ this.newValue = newValue;
+ this.newObject = newObject;
+
+ oldIsSet = property._property.IsSet;
+ oldValue = property._property.PropertyValue;
+ oldObject = property._property.ValueOnInstance;
+ }
+
+ public string Title {
+ get {
+ if (newIsSet)
+ return "Set " + property.Name;
+ else
+ return "Reset " + property.Name;
+ }
+ }
+
+ public void Do()
+ {
+ if (newIsSet)
+ property.SetValueInternal(newObject, newValue);
+ else
+ property.ResetInternal();
+ }
+
+ public void Undo()
+ {
+ if (oldIsSet)
+ property.SetValueInternal(oldObject, oldValue);
+ else
+ property.ResetInternal();
}
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/TextBoxEditor.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/TextBoxEditor.cs
index 29faa2aedf..9392c5883c 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/TextBoxEditor.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyEditor/TextBoxEditor.cs
@@ -35,7 +35,9 @@ namespace ICSharpCode.WpfDesign.PropertyEditor
{
this.property = property;
UpdateFromSource();
- PropertyEditorBindingHelper.AddValueChangedEventHandler(this, property, delegate { UpdateFromSource(); });
+ PropertyEditorBindingHelper.AddValueChangedEventHandler(
+ this, property, delegate { UpdateFromSource(); }
+ );
}
void UpdateFromSource()