Browse Source

WPF Designer.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2237 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
bef87e00dd
  1. 10
      src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml
  2. 33
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ContainerDragHandle.cs
  3. 45
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ResizeThumb.cs
  4. 20
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs
  5. 26
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SelectedElementRectangleExtension.cs
  6. 42
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs
  7. 34
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftGrabHandle.cs
  8. 247
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/UndoService.cs
  9. 9
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
  10. 1
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs
  11. 17
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs
  12. 36
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs
  13. 85
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs
  14. 41
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelPropertyCollection.cs
  15. 49
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/themes/generic.xaml
  16. 23
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs
  17. 4
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
  18. 72
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
  19. 18
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/AdornerProvider.cs
  20. 146
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/Placement.cs
  21. 47
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ChangeGroup.cs
  22. 16
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs
  23. 86
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItemProperty.cs
  24. 5
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/CustomInstanceFactory.cs
  25. 16
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/DefaultExtension.cs
  26. 5
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs
  27. 5
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionServer.cs
  28. 75
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/LogicalExtensionServers.cs
  29. 60
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs
  30. 6
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs
  31. 3
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj

10
src/AddIns/DisplayBindings/WpfDesign/StandaloneDesigner/Window1.xaml

@ -5,22 +5,20 @@ @@ -5,22 +5,20 @@
>
<TabControl TabStripPlacement="Bottom" Name="tabControl" SelectionChanged="tabControlSelectionChanged">
<TabItem Header="Code">
<TextBox Name="CodeTextBox" AcceptsReturn="True" xml:space="preserve">
<![CDATA[
<Border xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<TextBox Name="CodeTextBox" AcceptsReturn="True" xml:space="preserve"><![CDATA[
<Border xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" BorderThickness="10">
<StackPanel>
<Canvas Height="50" Background="White"></Canvas>
<Button>Button 1</Button>
<Button>Button 2</Button>
<TabControl Width="300" Height="300">
<TabItem Header="Page 1" />
<TabItem Header="Page 1"><StackPanel><Button>a</Button></StackPanel> </TabItem>
<TabItem Header="Page 2"><Button>button on page 2</Button></TabItem>
</TabControl>
</StackPanel>
</Border>
]]>
</TextBox>
]]></TextBox>
</TabItem>
<TabItem Header="Design" Name="designTab">
<designer:DesignSurface

33
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ContainerDragHandle.cs

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using ICSharpCode.WpfDesign.Adorners;
using ICSharpCode.WpfDesign.Extensions;
using ICSharpCode.WpfDesign.Designer.Controls;
namespace ICSharpCode.WpfDesign.Designer.Controls
{
/// <summary>
/// A thumb where the look can depend on the IsPrimarySelection property.
/// Used by UIElementSelectionRectangle.
/// </summary>
public class ContainerDragHandle : Control
{
static ContainerDragHandle()
{
//This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
//This style is defined in themes\generic.xaml
DefaultStyleKeyProperty.OverrideMetadata(typeof(ContainerDragHandle), new FrameworkPropertyMetadata(typeof(ContainerDragHandle)));
}
}
}

45
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Controls/ResizeThumb.cs

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using ICSharpCode.WpfDesign.Adorners;
using ICSharpCode.WpfDesign.Extensions;
namespace ICSharpCode.WpfDesign.Designer.Controls
{
/// <summary>
/// A thumb where the look can depend on the IsPrimarySelection property.
/// Used by UIElementSelectionRectangle.
/// </summary>
public class ResizeThumb : Thumb
{
/// <summary>
/// Dependency property for <see cref="IsPrimarySelection"/>.
/// </summary>
public static readonly DependencyProperty IsPrimarySelectionProperty
= DependencyProperty.Register("IsPrimarySelection", typeof(bool), typeof(ResizeThumb));
static ResizeThumb()
{
//This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
//This style is defined in themes\generic.xaml
DefaultStyleKeyProperty.OverrideMetadata(typeof(ResizeThumb), new FrameworkPropertyMetadata(typeof(ResizeThumb)));
}
/// <summary>
/// Gets/Sets if the resize thumb is attached to the primary selection.
/// </summary>
public bool IsPrimarySelection {
get { return (bool)GetValue(IsPrimarySelectionProperty); }
set { SetValue(IsPrimarySelectionProperty, value); }
}
}
}

20
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs

@ -140,7 +140,8 @@ namespace ICSharpCode.WpfDesign.Designer @@ -140,7 +140,8 @@ namespace ICSharpCode.WpfDesign.Designer
base.OnPreviewMouseDown(e);
if (!_isInInputAction) {
Debug.WriteLine("DesignPanel.PreviewMouseDown Source=" + e.Source.GetType().Name + " OriginalSource=" + e.OriginalSource.GetType().Name);
DesignItem site = FindDesignedElementForOriginalSource(e.OriginalSource);
object topMostHitSource = null;
DesignItem site = FindDesignedElementForOriginalSource(e.OriginalSource, ref topMostHitSource);
InputHandlingLayer itemLayer = InputHandlingLayer.None;
if (site != null) {
Debug.WriteLine(" Found designed element: " + site.Component.GetType().Name);
@ -148,6 +149,8 @@ namespace ICSharpCode.WpfDesign.Designer @@ -148,6 +149,8 @@ namespace ICSharpCode.WpfDesign.Designer
if (layerProvider != null) {
itemLayer = layerProvider.InputLayer;
}
} else if (topMostHitSource == _adornerLayer) {
itemLayer = InputHandlingLayer.Adorners;
}
if (ToolService.CurrentTool.InputLayer > itemLayer) {
ToolService.CurrentTool.OnMouseDown(this, e);
@ -155,7 +158,11 @@ namespace ICSharpCode.WpfDesign.Designer @@ -155,7 +158,11 @@ namespace ICSharpCode.WpfDesign.Designer
}
}
public DesignItem FindDesignedElementForOriginalSource(object originalSource)
// find a DesignItem for the clicked originalSource. This walks up the visual tree until it finds a designed item
// or the design surface itself.
// topMostSource is set to the element directly below the one that caused the tree walk to abort.
// For hits on the adorner layer, the method will return null and set topMostSource to _adornerLayer.
DesignItem FindDesignedElementForOriginalSource(object originalSource, ref object topMostSource)
{
if (originalSource == null)
return null;
@ -164,10 +171,17 @@ namespace ICSharpCode.WpfDesign.Designer @@ -164,10 +171,17 @@ namespace ICSharpCode.WpfDesign.Designer
return site;
if (originalSource == this)
return null;
topMostSource = originalSource;
DependencyObject dObj = originalSource as DependencyObject;
if (dObj == null)
return null;
return FindDesignedElementForOriginalSource(VisualTreeHelper.GetParent(dObj));
return FindDesignedElementForOriginalSource(VisualTreeHelper.GetParent(dObj), ref topMostSource);
}
public DesignItem FindDesignedElementForOriginalSource(object originalSource)
{
object topMostSource = null;
return FindDesignedElementForOriginalSource(originalSource, ref topMostSource);
}
/// <summary>

26
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/SelectedElementRectangleExtension.cs

@ -26,23 +26,25 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions @@ -26,23 +26,25 @@ namespace ICSharpCode.WpfDesign.Designer.Extensions
/// </summary>
public SelectedElementRectangleExtension()
{
Rectangle r = new Rectangle();
r.SnapsToDevicePixels = true;
r.Stroke = Brushes.Black;
r.StrokeDashCap = PenLineCap.Square;
r.StrokeDashArray = new DoubleCollection(new double[] { 0, 2 });
r.IsHitTestVisible = false;
Rectangle selectionRect = new Rectangle();
selectionRect.SnapsToDevicePixels = true;
selectionRect.Stroke = Brushes.White;
selectionRect.IsHitTestVisible = false;
RelativePlacement placement = new RelativePlacement();
placement.WidthRelativeToContentWidth = 1;
placement.HeightRelativeToContentHeight = 1;
placement.WidthOffset = 2;
placement.HeightOffset = 2;
Rectangle dottedRect = new Rectangle();
dottedRect.SnapsToDevicePixels = true;
dottedRect.Stroke = Brushes.Black;
dottedRect.StrokeDashCap = PenLineCap.Square;
dottedRect.StrokeDashArray = new DoubleCollection(new double[] { 0, 2 });
dottedRect.IsHitTestVisible = false;
RelativePlacement placement = new RelativePlacement(HorizontalAlignment.Stretch, VerticalAlignment.Stretch);
placement.XOffset = -1;
placement.YOffset = -1;
placement.WidthOffset = 2;
placement.HeightOffset = 2;
this.AddAdorner(r, placement);
this.AddAdorners(placement, selectionRect, dottedRect);
}
}
}

42
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftContainerDragHandle.cs

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using ICSharpCode.WpfDesign.Adorners;
using ICSharpCode.WpfDesign.Extensions;
using ICSharpCode.WpfDesign.Designer.Controls;
namespace ICSharpCode.WpfDesign.Designer.Extensions
{
/// <summary>
/// The drag handle displayed for panels.
/// </summary>
[ExtensionServer(typeof(PrimarySelectionExtensionServer))]
[ExtensionFor(typeof(Panel), OverrideExtension = typeof(TopLeftResizeThumb))]
public class TopLeftContainerDragHandle : AdornerProvider
{
/// <summary/>
public TopLeftContainerDragHandle()
{
ContainerDragHandle rect = new ContainerDragHandle();
rect.PreviewMouseDown += delegate {
Services.Selection.SetSelectedComponents(new DesignItem[] { this.ExtendedItem }, SelectionTypes.Auto);
};
RelativePlacement p = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Top);
p.XOffset = -1;
p.YOffset = -1;
AddAdorner(p, AdornerOrder.Background, rect);
}
}
}

34
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TopLeftGrabHandle.cs

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using ICSharpCode.WpfDesign.Adorners;
using ICSharpCode.WpfDesign.Extensions;
using ICSharpCode.WpfDesign.Designer.Controls;
namespace ICSharpCode.WpfDesign.Designer.Extensions
{
/// <summary>
/// The resize thumb at the top left edge of a component.
/// </summary>
[ExtensionFor(typeof(FrameworkElement))]
public class TopLeftResizeThumb : PrimarySelectionAdornerProvider
{
/// <summary></summary>
public TopLeftResizeThumb()
{
ResizeThumb resizeThumb = new ResizeThumb();
RelativePlacement p = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Top);
AddAdorner(p, AdornerOrder.Foreground, resizeThumb);
}
}
}

247
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/UndoService.cs

@ -0,0 +1,247 @@ @@ -0,0 +1,247 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ICSharpCode.WpfDesign.Designer.Services
{
#region ITransactionItem
interface ITransactionItem
{
void Do();
void Undo();
string Title { get; set; }
}
#endregion
#region UndoTransaction
/// <summary>
/// Supports ChangeGroup transactions and undo behavior.
/// </summary>
sealed class UndoTransaction : ChangeGroup, ITransactionItem
{
public enum TransactionState
{
Open,
Completed,
Undone,
Failed
}
TransactionState _state;
public TransactionState State
{
get { return _state; }
}
List<ITransactionItem> items = new List<ITransactionItem>();
public void Execute(ITransactionItem item)
{
AssertState(TransactionState.Open);
item.Do();
items.Add(item);
}
private void AssertState(TransactionState expectedState)
{
if (_state != expectedState)
throw new InvalidOperationException("Expected state " + expectedState + ", but state is " + _state);
}
public event EventHandler Committed;
public event EventHandler RolledBack;
public override void Commit()
{
AssertState(TransactionState.Open);
_state = TransactionState.Completed;
if (Committed != null)
Committed(this, EventArgs.Empty);
}
public override void Abort()
{
AssertState(TransactionState.Open);
_state = TransactionState.Failed;
InternalRollback();
if (RolledBack != null)
RolledBack(this, EventArgs.Empty);
}
public void Undo()
{
AssertState(TransactionState.Completed);
_state = TransactionState.Undone;
InternalRollback();
}
void InternalRollback()
{
try {
for (int i = items.Count - 1; i >= 0; i--) {
items[i].Undo();
}
} catch {
_state = TransactionState.Failed;
throw;
}
}
public void Redo()
{
AssertState(TransactionState.Undone);
try {
for (int i = 0; i < items.Count; i--) {
items[i].Do();
}
} catch {
_state = TransactionState.Failed;
try {
InternalRollback();
} catch (Exception ex) {
Debug.WriteLine("Exception rolling back after Redo error:\n" + ex.ToString());
}
throw;
}
}
void ITransactionItem.Do()
{
if (_state != TransactionState.Completed) {
Redo();
}
}
protected override void Disposed()
{
if (_state == TransactionState.Open) {
try {
Abort();
} catch (Exception ex) {
Debug.WriteLine("Exception rolling back after failure:\n" + ex.ToString());
}
}
}
}
#endregion
#region UndoService
/// <summary>
/// Service supporting Undo/Redo actions on the design surface.
/// </summary>
public sealed class UndoService
{
Stack<UndoTransaction> _transactionStack = new Stack<UndoTransaction>();
Stack<ITransactionItem> _undoStack = new Stack<ITransactionItem>();
Stack<ITransactionItem> _redoStack = new Stack<ITransactionItem>();
UndoTransaction CurrentTransaction {
get {
if (_transactionStack.Count == 0)
return null;
else
return _transactionStack.Peek();
}
}
internal UndoTransaction StartTransaction()
{
UndoTransaction t = new UndoTransaction();
t.Committed += TransactionFinished;
t.RolledBack += TransactionFinished;
t.Committed += delegate(object sender, EventArgs e) {
Execute((UndoTransaction)sender);
};
return t;
}
void TransactionFinished(object sender, EventArgs e)
{
if (sender != _transactionStack.Pop()) {
throw new Exception("Invalid transaction finish, nested transactions must finish first");
}
}
internal void Execute(ITransactionItem item)
{
if (_transactionStack.Count == 0) {
item.Do();
_undoStack.Push(item);
_redoStack.Clear();
} else {
_transactionStack.Peek().Execute(item);
}
}
/// <summary>
/// Gets if undo actions are available.
/// </summary>
public bool CanUndo {
get { return _undoStack.Count > 0; }
}
/// <summary>
/// Undoes the last action.
/// </summary>
public void Undo()
{
if (!CanUndo)
throw new InvalidOperationException("Cannot Undo: undo stack is empty");
if (_transactionStack.Count != 0)
throw new InvalidOperationException("Cannot Undo while transaction is running");
ITransactionItem item = _undoStack.Pop();
try {
item.Undo();
_redoStack.Push(item);
} catch {
// state might be invalid now, clear stacks to prevent getting more inconsistencies
Clear();
throw;
}
}
/// <summary>
/// Gets if there are redo actions available.
/// </summary>
public bool CanRedo { get { return _redoStack.Count > 0; } }
/// <summary>
/// Redoes a previously undone action.
/// </summary>
public void Redo()
{
if (!CanRedo)
throw new InvalidOperationException("Cannot Redo: redo stack is empty");
if (_transactionStack.Count != 0)
throw new InvalidOperationException("Cannot Redo while transaction is running");
ITransactionItem item = _redoStack.Pop();
try {
item.Do();
_undoStack.Push(item);
} catch {
// state might be invalid now, clear stacks to prevent getting more inconsistencies
Clear();
throw;
}
}
/// <summary>
/// Clears saved actions (both undo and redo stack).
/// </summary>
public void Clear()
{
_undoStack.Clear();
_redoStack.Clear();
}
}
#endregion
}

9
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj

@ -57,24 +57,32 @@ @@ -57,24 +57,32 @@
</Compile>
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Controls\AdornerLayer.cs" />
<Compile Include="Controls\ContainerDragHandle.cs" />
<Compile Include="Controls\ResizeThumb.cs" />
<Compile Include="Controls\SingleVisualChildElement.cs" />
<Compile Include="DesignPanel.cs" />
<Compile Include="Extensions\SelectedElementRectangleExtension.cs" />
<Compile Include="Extensions\TabItemClickableExtension.cs" />
<Compile Include="Extensions\TopLeftContainerDragHandle.cs" />
<Compile Include="Extensions\TopLeftGrabHandle.cs" />
<Compile Include="Linq.cs" />
<Compile Include="ServiceRequiredException.cs" />
<Compile Include="Services\SelectionService.cs" />
<Compile Include="Services\ToolService.cs" />
<Compile Include="Services\UndoService.cs" />
<Compile Include="Services\VisualDesignService.cs" />
<Compile Include="DesignSurface.cs" />
<Compile Include="Xaml\XamlComponentService.cs" />
<Compile Include="Xaml\XamlDesignContext.cs" />
<Compile Include="Xaml\XamlDesignItem.cs" />
<Compile Include="Xaml\XamlModelProperty.cs" />
<Compile Include="Xaml\XamlModelPropertyCollection.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Configuration" />
<Folder Include="Controls" />
<Folder Include="Extensions" />
<Folder Include="themes" />
<Folder Include="Xaml" />
<Folder Include="Services" />
<ProjectReference Include="..\..\WpfDesign.XamlDom\Project\WpfDesign.XamlDom.csproj">
@ -86,5 +94,6 @@ @@ -86,5 +94,6 @@
<Name>WpfDesign</Name>
<SpecificVersion>False</SpecificVersion>
</ProjectReference>
<Page Include="themes\generic.xaml" />
</ItemGroup>
</Project>

1
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlComponentService.cs

@ -38,6 +38,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -38,6 +38,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
{
if (component == null)
throw new ArgumentNullException("component");
throw new NotImplementedException();
}

17
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs

@ -13,12 +13,18 @@ using ICSharpCode.WpfDesign.Extensions; @@ -13,12 +13,18 @@ using ICSharpCode.WpfDesign.Extensions;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
sealed class XamlDesignContext : DesignContext
/// <summary>
/// The design context implementation used when editing XAML.
/// </summary>
public sealed class XamlDesignContext : DesignContext
{
readonly XamlDocument _doc;
readonly XamlDesignItem _rootItem;
readonly XamlComponentService _componentService;
internal readonly XamlComponentService _componentService;
/// <summary>
/// Creates a new XamlDesignContext instance.
/// </summary>
public XamlDesignContext(XmlReader xamlReader)
{
if (xamlReader == null)
@ -27,6 +33,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -27,6 +33,7 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
this.Services.AddService(typeof(IVisualDesignService), new DefaultVisualDesignService());
this.Services.AddService(typeof(ISelectionService), new DefaultSelectionService());
this.Services.AddService(typeof(IToolService), new DefaultToolService());
this.Services.AddService(typeof(UndoService), new UndoService());
_componentService = new XamlComponentService(this);
this.Services.AddService(typeof(IComponentService), _componentService);
@ -51,11 +58,17 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -51,11 +58,17 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
return CustomInstanceFactory.DefaultInstanceFactory.CreateInstance(instanceType, arguments);
}
/// <summary>
/// Saves the XAML DOM into the XML writer.
/// </summary>
public override void Save(System.Xml.XmlWriter writer)
{
_doc.Save(writer);
}
/// <summary>
/// Gets the root item being designed.
/// </summary>
public override DesignItem RootItem {
get { return _rootItem; }
}

36
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignItem.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
using System;
using System.Windows;
using ICSharpCode.WpfDesign.XamlDom;
using ICSharpCode.WpfDesign.Designer.Services;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
@ -15,12 +16,24 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -15,12 +16,24 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
{
readonly XamlObject _xamlObject;
readonly XamlDesignContext _designContext;
readonly XamlModelPropertyCollection _properties;
UIElement _view;
public XamlDesignItem(XamlObject xamlObject, XamlDesignContext designContext)
{
this._xamlObject = xamlObject;
this._designContext = designContext;
this._properties = new XamlModelPropertyCollection(this);
}
internal XamlComponentService ComponentService {
get {
return _designContext._componentService;
}
}
internal XamlObject XamlObject {
get { return _xamlObject; }
}
public override object Component {
@ -29,6 +42,15 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -29,6 +42,15 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
}
}
public override DesignItem Parent {
get {
if (_xamlObject.ParentProperty == null)
return null;
else
return ComponentService.GetDesignItem(_xamlObject.ParentProperty.ParentObject.Instance);
}
}
public override UIElement View {
get {
if (_view != null)
@ -38,6 +60,16 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -38,6 +60,16 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
}
}
public override ChangeGroup OpenGroup(string changeGroupTitle)
{
UndoService undoService = this.Services.GetService<UndoService>();
if (undoService == null)
throw new ServiceRequiredException(typeof(UndoService));
UndoTransaction g = undoService.StartTransaction();
g.Title = changeGroupTitle;
return g;
}
internal void SetView(UIElement newView)
{
_view = newView;
@ -46,5 +78,9 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -46,5 +78,9 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public override DesignContext Context {
get { return _designContext; }
}
public override DesignItemPropertyCollection Properties {
get { return _properties; }
}
}
}

85
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelProperty.cs

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using ICSharpCode.WpfDesign.XamlDom;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
sealed class XamlModelProperty : DesignItemProperty
{
readonly XamlDesignItem _designItem;
readonly XamlProperty _property;
public XamlModelProperty(XamlDesignItem designItem, XamlProperty property)
{
this._designItem = designItem;
this._property = property;
}
public override bool IsCollection {
get {
return _property.IsCollection;
}
}
public override System.Collections.Generic.IList<DesignItem> CollectionElements {
get {
throw new NotImplementedException();
}
}
public override DesignItem Value {
get {
if (IsCollection)
throw new DesignerException("Cannot access Value for collection properties.");
XamlComponentService componentService = _designItem.ComponentService;
object valueOnInstance = this.ValueOnInstance;
DesignItem designItem = componentService.GetDesignItem(valueOnInstance);
if (designItem != null)
return designItem;
return componentService.RegisterComponentForDesigner(valueOnInstance);
}
}
public override object ValueOnInstance {
get {
return _property.ValueOnInstance;
}
set {
_property.ValueOnInstance = value;
}
}
public override bool IsSet {
get {
return _property.IsSet;
}
}
public override void SetValue(object value)
{
XamlComponentService componentService = _designItem.ComponentService;
DesignItem designItem = componentService.GetDesignItem(value);
if (designItem != null) {
if (designItem.Parent != null)
throw new DesignerException("Cannot set value to design item that already has a parent");
} else {
designItem = componentService.RegisterComponentForDesigner(value);
}
}
public override void Reset()
{
_property.Reset();
}
}
}

41
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlModelPropertyCollection.cs

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Windows;
using ICSharpCode.WpfDesign.XamlDom;
namespace ICSharpCode.WpfDesign.Designer.Xaml
{
sealed class XamlModelPropertyCollection : DesignItemPropertyCollection
{
XamlDesignItem _item;
public XamlModelPropertyCollection(XamlDesignItem item)
{
this._item = item;
}
public override DesignItemProperty this[DependencyProperty dependencyProperty] {
get {
//return new XamlModelProperty(_item, dependencyProperty);
return this[dependencyProperty.Name];
}
}
public override DesignItemProperty this[string name] {
get {
return new XamlModelProperty(_item, _item.XamlObject.FindOrCreateProperty(name));
}
}
public override System.Collections.Generic.IEnumerator<DesignItemProperty> GetEnumerator()
{
throw new NotImplementedException();
}
}
}

49
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/themes/generic.xaml

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:ICSharpCode.WpfDesign.Designer"
>
<Style TargetType="{x:Type src:Controls.ResizeThumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type src:Controls.ResizeThumb}">
<Rectangle Name="thumbRectangle"
Width="7" Height="7" SnapsToDevicePixels="True"
Stroke="Black" Fill="White" RadiusX="1.4142" RadiusY="1.4142"/>
<ControlTemplate.Triggers>
<Trigger Property="IsPrimarySelection" Value="False">
<Setter TargetName="thumbRectangle" Property="Stroke" Value="White"/>
<Setter TargetName="thumbRectangle" Property="Fill" Value="Black"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="thumbRectangle" Property="Fill" Value="Gray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type src:Controls.ContainerDragHandle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type src:Controls.ContainerDragHandle}">
<Canvas Height="13" Width="13" Name="Canvas" Background="#00FFFFFF" SnapsToDevicePixels="True">
<Rectangle Height="13" Width="13" RadiusX="2" RadiusY="2"
Fill="#669ABFE5" Name="BorderRectangle" Stroke="#FF9ABFE5" StrokeThickness="1" />
<Path Fill="#FF748EAA" Canvas.Left="1" Canvas.Top="1">
<Path.Data>
<GeometryGroup>
<PathGeometry Figures="M5.5,0L3,3L8,3 M11,5.5L8,3L8,8 M5.5,11L3,8L8,8 M0,5.5L3,3L3,8" />
<RectangleGeometry Rect="3,5,5,1" />
<RectangleGeometry Rect="5,3,1,5" />
<RectangleGeometry Rect="5,5,1,1" />
</GeometryGroup>
</Path.Data>
</Path>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

23
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlObject.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml;
namespace ICSharpCode.WpfDesign.XamlDom
@ -74,5 +75,27 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -74,5 +75,27 @@ namespace ICSharpCode.WpfDesign.XamlDom
return properties.AsReadOnly();
}
}
/// <summary>
/// Finds the specified property, or creates it if it doesn't exist.
/// </summary>
public XamlProperty FindOrCreateProperty(string propertyName)
{
if (propertyName == null)
throw new ArgumentNullException("propertyName");
foreach (XamlProperty p in properties) {
if (p.PropertyName == propertyName)
return p;
}
PropertyDescriptorCollection propertyDescriptors = TypeDescriptor.GetProperties(elementType);
PropertyDescriptor propertyInfo = propertyDescriptors[propertyName];
if (propertyInfo == null) {
throw new ArgumentException("The property '" + propertyName + "' doesn't exist on " + elementType.FullName, "propertyName");
}
XamlProperty newProperty = new XamlProperty(this, new XamlNormalPropertyInfo(propertyInfo));
properties.Add(newProperty);
return newProperty;
}
}
}

4
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs

@ -175,7 +175,7 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -175,7 +175,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
if (childValue != null) {
if (defaultProperty != null && defaultProperty.IsCollection) {
defaultProperty.AddValue(defaultPropertyValue, childValue);
defaultCollectionProperty.AddCollectionElement(childValue);
defaultCollectionProperty.ParserAddCollectionElement(childValue);
} else {
if (setDefaultValueTo != null)
throw new XamlLoadException("default property may have only one value assigned");
@ -335,7 +335,7 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -335,7 +335,7 @@ namespace ICSharpCode.WpfDesign.XamlDom
if (childValue != null) {
if (propertyInfo.IsCollection) {
propertyInfo.AddValue(collectionInstance, childValue);
collectionProperty.AddCollectionElement(childValue);
collectionProperty.ParserAddCollectionElement(childValue);
} else {
if (valueWasSet)
throw new XamlLoadException("non-collection property may have only one child element");

72
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Xml;
@ -21,13 +22,33 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -21,13 +22,33 @@ namespace ICSharpCode.WpfDesign.XamlDom
XamlObject parentObject;
XamlPropertyInfo propertyInfo;
XamlPropertyValue propertyValue;
List<XamlPropertyValue> collectionElements = new List<XamlPropertyValue>();
List<XamlPropertyValue> collectionElements;
bool _isCollection;
static readonly IList<XamlPropertyValue> emptyCollectionElementsArray = new XamlPropertyValue[0];
// for use by parser only
internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo, XamlPropertyValue propertyValue)
{
this.parentObject = parentObject;
this.propertyInfo = propertyInfo;
this.propertyValue = propertyValue;
if (propertyValue != null) {
propertyValue.ParentProperty = this;
} else {
if (propertyInfo.IsCollection) {
_isCollection = true;
collectionElements = new List<XamlPropertyValue>();
}
}
}
internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo)
{
this.parentObject = parentObject;
this.propertyInfo = propertyInfo;
_isCollection = propertyInfo.IsCollection;
}
/// <summary>
@ -51,20 +72,55 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -51,20 +72,55 @@ namespace ICSharpCode.WpfDesign.XamlDom
get { return propertyValue; }
}
/// <summary>
/// Gets if the property is a collection property.
/// </summary>
public bool IsCollection {
get { return _isCollection; }
}
/// <summary>
/// Gets the collection elements of the property. Is empty if the property is not a collection.
/// </summary>
public IList<XamlPropertyValue> CollectionElements {
get { return collectionElements.AsReadOnly(); }
get { return collectionElements != null ? collectionElements.AsReadOnly() : emptyCollectionElementsArray; }
}
/// <summary>
/// Gets if the property is set.
/// </summary>
public bool IsSet {
get { return propertyValue != null || collectionElements != null; }
}
/// <summary>
/// Resets the properties value.
/// </summary>
public void Reset()
{
throw new NotImplementedException();
}
/// <summary>
/// used internally by the XamlParser.
/// Add a collection element that already is part of the XML DOM.
/// </summary>
internal void AddCollectionElement(XamlPropertyValue val)
internal void ParserAddCollectionElement(XamlPropertyValue val)
{
collectionElements.Add(val);
val.ParentProperty = this;
}
/// <summary>
/// Gets/Sets the value of the property on the instance without updating the XAML document.
/// </summary>
public object ValueOnInstance {
get{
return propertyInfo.GetValue(parentObject.Instance);
}
set {
propertyInfo.SetValue(parentObject.Instance, value);
}
}
/*public bool IsAttributeSyntax {
@ -96,6 +152,16 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -96,6 +152,16 @@ namespace ICSharpCode.WpfDesign.XamlDom
/// used internally by the XamlParser.
/// </summary>
internal abstract object GetValueFor(XamlPropertyInfo targetProperty);
XamlProperty _parentProperty;
/// <summary>
/// Gets the parent property that this value is assigned to.
/// </summary>
public XamlProperty ParentProperty {
get { return _parentProperty; }
internal set { _parentProperty = value; }
}
}
/// <summary>

18
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/AdornerProvider.cs

@ -116,14 +116,28 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -116,14 +116,28 @@ namespace ICSharpCode.WpfDesign.Adorners
/// <summary>
/// Adds an UIElement as adorner with the specified placement.
/// </summary>
protected void AddAdorner(UIElement adorner, Placement placement)
protected void AddAdorner(Placement placement, AdornerOrder order, UIElement adorner)
{
AdornerPanel.SetPlacement(adorner, placement);
AdornerPanel p = new AdornerPanel();
p.Order = order;
AdornerPanel.SetPlacement(adorner, placement);
p.Children.Add(adorner);
this.Adorners.Add(p);
}
/// <summary>
/// Adds several UIElements as adorners with the specified placement.
/// </summary>
protected void AddAdorners(Placement placement, params UIElement[] adorners)
{
AdornerPanel p = new AdornerPanel();
foreach (UIElement adorner in adorners) {
AdornerPanel.SetPlacement(adorner, placement);
p.Children.Add(adorner);
}
this.Adorners.Add(p);
}
internal void OnAdornerAdd(AdornerPanel item)
{
if (!isVisible) return;

146
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Adorners/Placement.cs

@ -45,10 +45,61 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -45,10 +45,61 @@ namespace ICSharpCode.WpfDesign.Adorners
/// </summary>
public sealed class RelativePlacement : Placement
{
/// <summary>
/// Creates a new RelativePlacement instance. The default instance is a adorner with zero size, you
/// have to set some properties to define the placement.
/// </summary>
public RelativePlacement()
{
}
/// <summary>
/// Creates a new RelativePlacement instance from the specified horizontal and vertical alignments.
/// </summary>
public RelativePlacement(HorizontalAlignment horizontal, VerticalAlignment vertical)
{
switch (horizontal) {
case HorizontalAlignment.Left:
widthRelativeToDesiredWidth = 1;
xRelativeToAdornerWidth = -1;
break;
case HorizontalAlignment.Right:
widthRelativeToDesiredWidth = 1;
xRelativeToContentWidth = 1;
break;
case HorizontalAlignment.Center:
widthRelativeToDesiredWidth = 1;
xRelativeToContentWidth = 0.5;
xRelativeToAdornerWidth = -0.5;
break;
case HorizontalAlignment.Stretch:
widthRelativeToContentWidth = 1;
break;
}
switch (vertical) {
case VerticalAlignment.Top:
heightRelativeToDesiredHeight = 1;
yRelativeToAdornerHeight = -1;
break;
case VerticalAlignment.Bottom:
heightRelativeToDesiredHeight = 1;
yRelativeToContentHeight = 1;
break;
case VerticalAlignment.Center:
heightRelativeToDesiredHeight = 1;
yRelativeToContentHeight = 0.5;
yRelativeToAdornerHeight = -0.5;
break;
case VerticalAlignment.Stretch:
heightRelativeToContentHeight = 1;
break;
}
}
double widthRelativeToDesiredWidth, heightRelativeToDesiredHeight;
/// <summary>
/// Gets/Sets the width of the adorner relative to the desired adorner width.
/// Gets/Sets the width of the adorner as factor relative to the desired adorner width.
/// </summary>
public double WidthRelativeToDesiredWidth {
get { return widthRelativeToDesiredWidth; }
@ -56,7 +107,7 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -56,7 +107,7 @@ namespace ICSharpCode.WpfDesign.Adorners
}
/// <summary>
/// Gets/Sets the height of the adorner relative to the desired adorner height.
/// Gets/Sets the height of the adorner as factor relative to the desired adorner height.
/// </summary>
public double HeightRelativeToDesiredHeight {
get { return heightRelativeToDesiredHeight; }
@ -66,7 +117,7 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -66,7 +117,7 @@ namespace ICSharpCode.WpfDesign.Adorners
double widthRelativeToContentWidth, heightRelativeToContentHeight;
/// <summary>
/// Gets/Sets the width of the adorner relative to the width of the adorned item.
/// Gets/Sets the width of the adorner as factor relative to the width of the adorned item.
/// </summary>
public double WidthRelativeToContentWidth {
get { return widthRelativeToContentWidth; }
@ -74,7 +125,7 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -74,7 +125,7 @@ namespace ICSharpCode.WpfDesign.Adorners
}
/// <summary>
/// Gets/Sets the height of the adorner relative to the height of the adorned item.
/// Gets/Sets the height of the adorner as factor relative to the height of the adorned item.
/// </summary>
public double HeightRelativeToContentHeight {
get { return heightRelativeToContentHeight; }
@ -101,14 +152,12 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -101,14 +152,12 @@ namespace ICSharpCode.WpfDesign.Adorners
Size CalculateSize(UIElement adorner, Size adornedElementSize)
{
Size size = new Size(widthOffset, heightOffset);
if (widthRelativeToDesiredWidth != 0 || heightRelativeToDesiredHeight != 0) {
size.Width += widthRelativeToDesiredWidth * adorner.DesiredSize.Width;
size.Height += heightRelativeToDesiredHeight * adorner.DesiredSize.Height;
}
size.Width += widthRelativeToContentWidth * adornedElementSize.Width;
size.Height += heightRelativeToContentHeight * adornedElementSize.Height;
return size;
return new Size(widthOffset
+ widthRelativeToDesiredWidth * adorner.DesiredSize.Width
+ widthRelativeToContentWidth * adornedElementSize.Width,
heightOffset
+ heightRelativeToDesiredHeight * adorner.DesiredSize.Height
+ heightRelativeToContentHeight * adornedElementSize.Height);
}
double xOffset, yOffset;
@ -129,9 +178,50 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -129,9 +178,50 @@ namespace ICSharpCode.WpfDesign.Adorners
set { yOffset = value; }
}
double xRelativeToAdornerWidth, yRelativeToAdornerHeight;
/// <summary>
/// Gets/Sets the left border of the adorner element as factor relative to the width of the adorner.
/// </summary>
public double XRelativeToAdornerWidth {
get { return xRelativeToAdornerWidth; }
set { xRelativeToAdornerWidth = value; }
}
/// <summary>
/// Gets/Sets the top border of the adorner element as factor relative to the height of the adorner.
/// </summary>
public double YRelativeToAdornerHeight {
get { return yRelativeToAdornerHeight; }
set { yRelativeToAdornerHeight = value; }
}
double xRelativeToContentWidth, yRelativeToContentHeight;
/// <summary>
/// Gets/Sets the left border of the adorner element as factor relative to the width of the adorned content.
/// </summary>
public double XRelativeToContentWidth {
get { return xRelativeToContentWidth; }
set { xRelativeToContentWidth = value; }
}
/// <summary>
/// Gets/Sets the top border of the adorner element as factor relative to the height of the adorned content.
/// </summary>
public double YRelativeToContentHeight {
get { return yRelativeToContentHeight; }
set { yRelativeToContentHeight = value; }
}
Point CalculatePosition(Size adornedElementSize, Size adornerSize)
{
return new Point(xOffset, yOffset);
return new Point(xOffset
+ xRelativeToAdornerWidth * adornerSize.Width
+ xRelativeToContentWidth * adornedElementSize.Width,
yOffset
+ yRelativeToAdornerHeight * adornerSize.Height
+ yRelativeToContentHeight * adornedElementSize.Height);
}
/// <summary>
@ -143,7 +233,7 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -143,7 +233,7 @@ namespace ICSharpCode.WpfDesign.Adorners
adorner.Arrange(new Rect(CalculatePosition(adornedElementSize, adornerSize), adornerSize));
}
}
/// <summary>
/// Describes the space in which an adorner is placed.
/// </summary>
@ -162,32 +252,4 @@ namespace ICSharpCode.WpfDesign.Adorners @@ -162,32 +252,4 @@ namespace ICSharpCode.WpfDesign.Adorners
/// </summary>
Designer
}
/// <summary>
/// The possible layers where adorners can be placed.
/// </summary>
public enum AdornerZLayer
{
/// <summary>
/// This layer is below the other adorner layers.
/// </summary>
Low,
/// <summary>
/// This layer is for normal background adorners.
/// </summary>
Normal,
/// <summary>
/// This layer is for selection adorners
/// </summary>
Selection,
/// <summary>
/// This layer is for primary selection adorners
/// </summary>
PrimarySelection,
/// <summary>
/// This layer is above the other layers.
/// It is used for temporary drawings, e.g. the selection frame while selecting multiple controls with the mouse.
/// </summary>
High
}
}

47
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ChangeGroup.cs

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.WpfDesign
{
/// <summary>
/// Base class for change groups.
/// </summary>
public abstract class ChangeGroup : IDisposable
{
string title;
/// <summary>
/// Gets/Sets the title of the change group.
/// </summary>
public string Title {
get { return title; }
set { title = value; }
}
/// <summary>
/// Commits the change group.
/// </summary>
public abstract void Commit();
/// <summary>
/// Aborts the change group.
/// </summary>
public abstract void Abort();
/// <summary>
/// Is called when the change group is disposed. Should Abort the change group if it is not already committed.
/// </summary>
protected abstract void Disposed();
void IDisposable.Dispose()
{
Disposed();
}
}
}

16
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs

@ -34,6 +34,16 @@ namespace ICSharpCode.WpfDesign @@ -34,6 +34,16 @@ namespace ICSharpCode.WpfDesign
/// </summary>
public abstract DesignContext Context { get; }
/// <summary>
/// Gets the parent design item.
/// </summary>
public abstract DesignItem Parent { get; }
/// <summary>
/// Gets properties set on the design item.
/// </summary>
public abstract DesignItemPropertyCollection Properties { get; }
/// <summary>
/// Gets an instance that provides convenience properties for the most-used designers.
/// </summary>
@ -42,6 +52,12 @@ namespace ICSharpCode.WpfDesign @@ -42,6 +52,12 @@ namespace ICSharpCode.WpfDesign
get { return this.Context.Services; }
}
/// <summary>
/// Opens a new change group used to batch several changes. ChangeGroups work as transactions and
/// are used to support the Undo/Redo system.
/// </summary>
public abstract ChangeGroup OpenGroup(string changeGroupTitle);
#region Extensions support
private struct ExtensionEntry
{

86
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItemProperty.cs

@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Windows;
namespace ICSharpCode.WpfDesign
{
/// <summary>
/// Represents a property of a DesignItem.
/// All changes done via the DesignItemProperty class are represented in the underlying model (e.g. XAML).
/// This also ensures that
/// Changes directly done to control instances might not be reflected in the model.
/// </summary>
public abstract class DesignItemProperty
{
/// <summary>
/// Gets if the property represents a collection.
/// </summary>
public abstract bool IsCollection { get; }
/// <summary>
/// Gets the elements represented by the collection.
/// </summary>
public abstract IList<DesignItem> CollectionElements { get; }
/// <summary>
/// Gets the value of the property. This property returns null if the value is not set.
/// </summary>
public abstract DesignItem Value { get; }
/// <summary>
/// Gets/Sets the value of the property on the designed instance.
/// If the property is not set, this returns the default value.
/// The setter does NOT update the underlying model, use SetValue() instead!
/// </summary>
public abstract object ValueOnInstance { get; set; }
/// <summary>
/// Sets the value of the property.
/// </summary>
public abstract void SetValue(object value);
/// <summary>
/// Gets if the property is set on the design item.
/// </summary>
public abstract bool IsSet { get; }
/// <summary>
/// Resets the property value to the default, possibly removing it from the list of properties.
/// </summary>
public abstract void Reset();
}
/// <summary>
/// Represents a collection of design item properties.
/// </summary>
public abstract class DesignItemPropertyCollection : IEnumerable<DesignItemProperty>
{
/// <summary>
/// Gets the design item property representing the specified dependency property.
/// </summary>
public abstract DesignItemProperty this[DependencyProperty dependencyProperty] { get; }
/// <summary>
/// Gets the property with the specified name.
/// </summary>
public abstract DesignItemProperty this[string name] { get; }
/// <summary>
/// Gets an enumerator to enumerate the properties that have a non-default value.
/// </summary>
public abstract IEnumerator<DesignItemProperty> GetEnumerator();
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}

5
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/CustomInstanceFactory.cs

@ -59,5 +59,10 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -59,5 +59,10 @@ namespace ICSharpCode.WpfDesign.Extensions
{
throw new NotImplementedException();
}
// since the event is never raised, we don't have to store the event handlers
public override event EventHandler<DesignItemCollectionEventArgs> ShouldApplyExtensionsInvalidated {
add {} remove {}
}
}
}

16
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/DefaultExtension.cs

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
namespace ICSharpCode.WpfDesign.Extensions
{
@ -103,6 +104,21 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -103,6 +104,21 @@ namespace ICSharpCode.WpfDesign.Extensions
((DefaultExtension)extension).CallOnRemove();
}
/// <summary>
/// This event is raised when ShouldApplyExtensions is invalidated for a set of items.
/// </summary>
public override event EventHandler<DesignItemCollectionEventArgs> ShouldApplyExtensionsInvalidated;
/// <summary>
/// Raise the ShouldApplyExtensionsInvalidated event for the specified set of design items.
/// </summary>
protected void ReapplyExtensions(ICollection<DesignItem> items)
{
if (ShouldApplyExtensionsInvalidated != null) {
ShouldApplyExtensionsInvalidated(this, new DesignItemCollectionEventArgs(items));
}
}
internal sealed class Permanent : DefaultExtensionServer
{
public override bool ShouldApplyExtensions(DesignItem extendedItem)

5
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -38,7 +38,7 @@ namespace ICSharpCode.WpfDesign.Extensions
/// <summary>
/// Re-applies extensions from the ExtensionServer to the specified design items.
/// </summary>
public void ReapplyExtensions(IEnumerable<DesignItem> items, ExtensionServer server)
void ReapplyExtensions(IEnumerable<DesignItem> items, ExtensionServer server)
{
foreach (DesignItem item in items) {
item.ReapplyExtensionServer(this, server);
@ -203,6 +203,9 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -203,6 +203,9 @@ namespace ICSharpCode.WpfDesign.Extensions
server = (ExtensionServer)Activator.CreateInstance(extensionServerType);
server.InitializeExtensionServer(_context);
_extensionServers[extensionServerType] = server;
server.ShouldApplyExtensionsInvalidated += delegate(object sender, DesignItemCollectionEventArgs e) {
ReapplyExtensions(e.Items, (ExtensionServer)sender);
};
return server;
}
#endregion

5
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionServer.cs

@ -74,5 +74,10 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -74,5 +74,10 @@ namespace ICSharpCode.WpfDesign.Extensions
/// Is called by the ExtensionManager.
/// </summary>
public abstract void RemoveExtension(Extension extension);
/// <summary>
/// This event is raised when ShouldApplyExtensions is invalidated for a set of items.
/// </summary>
public abstract event EventHandler<DesignItemCollectionEventArgs> ShouldApplyExtensionsInvalidated;
}
}

75
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/LogicalExtensionServers.cs

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using System;
namespace ICSharpCode.WpfDesign.Extensions
{
/// <summary>
/// Combines two extension servers using a logical OR.
/// </summary>
public sealed class LogicalOrExtensionServer<A, B> : DefaultExtensionServer
where A : ExtensionServer
where B : ExtensionServer
{
ExtensionServer _a;
ExtensionServer _b;
/// <summary/>
protected override void OnInitialized()
{
base.OnInitialized();
_a = Context.Services.ExtensionManager.GetExtensionServer(new ExtensionServerAttribute(typeof(A)));
_b = Context.Services.ExtensionManager.GetExtensionServer(new ExtensionServerAttribute(typeof(B)));
_a.ShouldApplyExtensionsInvalidated += OnShouldApplyExtensionsInvalidated;
_b.ShouldApplyExtensionsInvalidated += OnShouldApplyExtensionsInvalidated;
}
void OnShouldApplyExtensionsInvalidated(object sender, DesignItemCollectionEventArgs e)
{
ReapplyExtensions(e.Items);
}
/// <summary/>
public override bool ShouldApplyExtensions(DesignItem extendedItem)
{
return _a.ShouldApplyExtensions(extendedItem) || _b.ShouldApplyExtensions(extendedItem);
}
}
/// <summary>
/// Combines two extension servers using a logical AND.
/// </summary>
public sealed class LogicalAndExtensionServer<A, B> : DefaultExtensionServer
where A : ExtensionServer
where B : ExtensionServer
{
ExtensionServer _a;
ExtensionServer _b;
/// <summary/>
protected override void OnInitialized()
{
base.OnInitialized();
_a = Context.Services.ExtensionManager.GetExtensionServer(new ExtensionServerAttribute(typeof(A)));
_b = Context.Services.ExtensionManager.GetExtensionServer(new ExtensionServerAttribute(typeof(B)));
_a.ShouldApplyExtensionsInvalidated += OnShouldApplyExtensionsInvalidated;
_b.ShouldApplyExtensionsInvalidated += OnShouldApplyExtensionsInvalidated;
}
void OnShouldApplyExtensionsInvalidated(object sender, DesignItemCollectionEventArgs e)
{
ReapplyExtensions(e.Items);
}
/// <summary/>
public override bool ShouldApplyExtensions(DesignItem extendedItem)
{
return _a.ShouldApplyExtensions(extendedItem) && _b.ShouldApplyExtensions(extendedItem);
}
}
}

60
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/SelectionExtensionServer.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -25,7 +25,7 @@ namespace ICSharpCode.WpfDesign.Extensions
void OnSelectionChanged(object sender, DesignItemCollectionEventArgs e)
{
Services.ExtensionManager.ReapplyExtensions(e.Items, this);
ReapplyExtensions(e.Items);
}
/// <summary>
@ -72,11 +72,11 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -72,11 +72,11 @@ namespace ICSharpCode.WpfDesign.Extensions
DesignItem newPrimarySelection = this.Services.Selection.PrimarySelection;
if (oldPrimarySelection != newPrimarySelection) {
if (oldPrimarySelection == null) {
this.Services.ExtensionManager.ReapplyExtensions(new DesignItem[] { newPrimarySelection }, this);
ReapplyExtensions(new DesignItem[] { newPrimarySelection });
} else if (newPrimarySelection == null) {
this.Services.ExtensionManager.ReapplyExtensions(new DesignItem[] { oldPrimarySelection }, this);
ReapplyExtensions(new DesignItem[] { oldPrimarySelection });
} else {
this.Services.ExtensionManager.ReapplyExtensions(new DesignItem[] { oldPrimarySelection, newPrimarySelection }, this);
ReapplyExtensions(new DesignItem[] { oldPrimarySelection, newPrimarySelection });
}
oldPrimarySelection = newPrimarySelection;
}
@ -90,4 +90,56 @@ namespace ICSharpCode.WpfDesign.Extensions @@ -90,4 +90,56 @@ namespace ICSharpCode.WpfDesign.Extensions
return Services.Selection.PrimarySelection == extendedItem;
}
}
/// <summary>
/// Applies an extension to the parent of the primary selection.
/// </summary>
public class PrimarySelectionParentExtensionServer : DefaultExtensionServer
{
DesignItem oldPrimarySelectionParent;
/// <summary>
/// Is called after the extension server is initialized and the Context property has been set.
/// </summary>
protected override void OnInitialized()
{
base.OnInitialized();
this.Services.Selection.PrimarySelectionChanged += OnPrimarySelectionChanged;
}
DesignItem PrimarySelectionParent {
get {
DesignItem newPrimarySelection = this.Services.Selection.PrimarySelection;
if (newPrimarySelection != null) {
return newPrimarySelection.Parent;
} else {
return null;
}
}
}
void OnPrimarySelectionChanged(object sender, EventArgs e)
{
DesignItem newPrimarySelectionParent = PrimarySelectionParent;
if (oldPrimarySelectionParent != newPrimarySelectionParent) {
if (oldPrimarySelectionParent == null) {
ReapplyExtensions(new DesignItem[] { newPrimarySelectionParent });
} else if (newPrimarySelectionParent == null) {
ReapplyExtensions(new DesignItem[] { oldPrimarySelectionParent });
} else {
ReapplyExtensions(new DesignItem[] { oldPrimarySelectionParent, newPrimarySelectionParent });
}
oldPrimarySelectionParent = newPrimarySelectionParent;
}
}
/// <summary>
/// Gets if the item is the primary selection.
/// </summary>
public override bool ShouldApplyExtensions(DesignItem extendedItem)
{
return PrimarySelectionParent == extendedItem;
}
}
}

6
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs

@ -38,6 +38,10 @@ namespace ICSharpCode.WpfDesign @@ -38,6 +38,10 @@ namespace ICSharpCode.WpfDesign
/// </summary>
ComponentHigh,
/// <summary>
/// This value is used for mouse input on the adorner layer.
/// </summary>
Adorners,
/// <summary>
/// This layer is higher than all other layers.
/// </summary>
Highest
@ -131,7 +135,7 @@ namespace ICSharpCode.WpfDesign @@ -131,7 +135,7 @@ namespace ICSharpCode.WpfDesign
/// Used for temporary drawings that are not attached to any element, e.g. the selection frame.
/// </summary>
Canvas MarkerCanvas { get; }
*/
*/
// The following members were missing in <see cref="IInputElement"/>, but of course
// are supported on the DesignPanel:

3
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj

@ -61,7 +61,9 @@ @@ -61,7 +61,9 @@
<Compile Include="Adorners\AdornerProvider.cs" />
<Compile Include="Adorners\AdornerProviderClasses.cs" />
<Compile Include="Adorners\Placement.cs" />
<Compile Include="ChangeGroup.cs" />
<Compile Include="DesignContext.cs" />
<Compile Include="DesignItemProperty.cs" />
<Compile Include="EventArgs.cs" />
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="DesignerException.cs" />
@ -73,6 +75,7 @@ @@ -73,6 +75,7 @@
<Compile Include="Extensions\ExtensionManager.cs" />
<Compile Include="Extensions\ExtensionServer.cs" />
<Compile Include="Extensions\ExtensionServerAttribute.cs" />
<Compile Include="Extensions\LogicalExtensionServers.cs" />
<Compile Include="Extensions\SelectionExtensionServer.cs" />
<Compile Include="HashSet.cs" />
<Compile Include="Linq.cs" />

Loading…
Cancel
Save