diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs index 18c7d26a06..61f186020a 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignPanel.cs @@ -77,10 +77,17 @@ namespace ICSharpCode.WpfDesign.Designer if (!_isInInputAction) { Debug.WriteLine("DesignPanel.PreviewMouseDown Source=" + e.Source.GetType().Name + " OriginalSource=" + e.OriginalSource.GetType().Name); DesignItem site = FindDesignedElementForOriginalSource(e.OriginalSource); + InputHandlingLayer itemLayer = InputHandlingLayer.None; if (site != null) { Debug.WriteLine(" Found designed element: " + site.Component.GetType().Name); + IProvideComponentInputHandlingLayer layerProvider = site.GetBehavior(); + if (layerProvider != null) { + itemLayer = layerProvider.InputLayer; + } + } + if (ToolService.CurrentTool.InputLayer > itemLayer) { + ToolService.CurrentTool.OnMouseDown(this, e); } - ToolService.CurrentTool.OnMouseDown(this, e); } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs index 93f9526470..45a8c1cf2d 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.cs @@ -58,7 +58,7 @@ namespace ICSharpCode.WpfDesign.Designer public void LoadDesigner(XmlReader xamlReader) { UnloadDesigner(); - InitializeDesigner(new Xaml.XamlDesignContext(XamlDom.XamlParser.Parse(xamlReader))); + InitializeDesigner(new Xaml.XamlDesignContext(xamlReader)); } /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TabItemClickableExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TabItemClickableExtension.cs index c8bfc7dbe3..4f60ef930d 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TabItemClickableExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Extensions/TabItemClickableExtension.cs @@ -13,11 +13,21 @@ using ICSharpCode.WpfDesign.Extensions; namespace ICSharpCode.WpfDesign.Designer.Extensions { /// - /// Makes the TabItem clickable. + /// Makes TabItems clickable. /// [ExtensionFor(typeof(TabItem))] - public sealed class TabItemClickableExtension : BehaviorExtension + public sealed class TabItemClickableExtension : BehaviorExtension, IProvideComponentInputHandlingLayer { + /// + protected override void OnInitialized() + { + this.ExtendedItem.AddBehavior(typeof(IProvideComponentInputHandlingLayer), this); + } + InputHandlingLayer IProvideComponentInputHandlingLayer.InputLayer { + get { + return InputHandlingLayer.ComponentHigh; + } + } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs index 596ceb23cf..0de3e52ed4 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs @@ -6,8 +6,10 @@ // using System; +using System.Xml; using ICSharpCode.WpfDesign.XamlDom; using ICSharpCode.WpfDesign.Designer.Services; +using ICSharpCode.WpfDesign.Extensions; namespace ICSharpCode.WpfDesign.Designer.Xaml { @@ -17,11 +19,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml readonly XamlDesignItem _rootItem; readonly XamlComponentService _componentService; - public XamlDesignContext(XamlDocument doc) + public XamlDesignContext(XmlReader xamlReader) { - if (doc == null) - throw new ArgumentNullException("doc"); - this._doc = doc; + if (xamlReader == null) + throw new ArgumentNullException("xamlReader"); this.Services.AddService(typeof(IVisualDesignService), new DefaultVisualDesignService()); this.Services.AddService(typeof(ISelectionService), new DefaultSelectionService()); @@ -33,7 +34,21 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml // register extensions from this assembly: this.Services.ExtensionManager.RegisterAssembly(typeof(XamlDesignContext).Assembly); - _rootItem = _componentService.RegisterXamlComponentRecursive(doc.RootElement); + XamlParserSettings xamlParseSettings = new XamlParserSettings(); + xamlParseSettings.CreateInstanceCallback = OnXamlParserCreateInstance; + _doc = XamlParser.Parse(xamlReader, xamlParseSettings); + _rootItem = _componentService.RegisterXamlComponentRecursive(_doc.RootElement); + } + + object OnXamlParserCreateInstance(Type instanceType, object[] arguments) + { + foreach (Type extensionType in this.Services.ExtensionManager.GetExtensionTypes(instanceType)) { + if (typeof(CustomInstanceFactory).IsAssignableFrom(extensionType)) { + CustomInstanceFactory factory = (CustomInstanceFactory)Activator.CreateInstance(extensionType); + return factory.CreateInstance(instanceType, arguments); + } + } + return CustomInstanceFactory.DefaultInstanceFactory.CreateInstance(instanceType, arguments); } public override void Save(System.Xml.XmlWriter writer) diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj index 8311b741e6..25777c00e3 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj @@ -63,6 +63,7 @@ + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs index ba0116f782..d2ad8089a6 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs @@ -25,63 +25,87 @@ namespace ICSharpCode.WpfDesign.XamlDom /// Parses a XAML document using a stream. /// public static XamlDocument Parse(Stream stream) + { + return Parse(stream, new XamlParserSettings()); + } + + /// + /// Parses a XAML document using a TextReader. + /// + public static XamlDocument Parse(TextReader reader) + { + return Parse(reader, new XamlParserSettings()); + } + + /// + /// Parses a XAML document using an XmlReader. + /// + public static XamlDocument Parse(XmlReader reader) + { + return Parse(reader, new XamlParserSettings()); + } + + /// + /// Parses a XAML document using a stream. + /// + public static XamlDocument Parse(Stream stream, XamlParserSettings settings) { if (stream == null) throw new ArgumentNullException("stream"); XmlDocument doc = new XmlDocument(); doc.Load(stream); - return Parse(doc); + return Parse(doc, settings); } /// /// Parses a XAML document using a TextReader. /// - public static XamlDocument Parse(TextReader reader) + public static XamlDocument Parse(TextReader reader, XamlParserSettings settings) { if (reader == null) throw new ArgumentNullException("reader"); XmlDocument doc = new XmlDocument(); doc.Load(reader); - return Parse(doc); + return Parse(doc, settings); } /// /// Parses a XAML document using an XmlReader. /// - public static XamlDocument Parse(XmlReader reader) + public static XamlDocument Parse(XmlReader reader, XamlParserSettings settings) { if (reader == null) throw new ArgumentNullException("reader"); XmlDocument doc = new XmlDocument(); doc.Load(reader); - return Parse(doc); + return Parse(doc, settings); } /// /// Creates a XAML document from an existing XmlDocument. /// - internal static XamlDocument Parse(XmlDocument document) + internal static XamlDocument Parse(XmlDocument document, XamlParserSettings settings) { + if (settings == null) + throw new ArgumentNullException("settings"); if (document == null) throw new ArgumentNullException("document"); XamlParser p = new XamlParser(); + p.settings = settings; p.document = new XamlDocument(document); p.document.ParseComplete(p.ParseObject(document.DocumentElement)); return p.document; } #endregion - XamlDocument document; - XamlTypeFinder typeFinder; + private XamlParser() { } - private XamlParser() - { - typeFinder = XamlTypeFinder.CreateWpfTypeFinder(); - } + XamlDocument document; + XamlParserSettings settings; Type FindType(string namespaceUri, string localName) { - Type elementType = typeFinder.GetType(namespaceUri, localName); + Type elementType = settings.TypeFinder.GetType(namespaceUri, localName); if (elementType == null) throw new XamlLoadException("Cannot find type " + localName + " in " + namespaceUri); return elementType; @@ -95,12 +119,15 @@ namespace ICSharpCode.WpfDesign.XamlDom return attribute.OwnerElement.NamespaceURI; } + readonly static object[] emptyObjectArray = new object[0]; XmlSpace currentXmlSpace = XmlSpace.None; XamlObject ParseObject(XmlElement element) { Type elementType = FindType(element.NamespaceURI, element.LocalName); - object instance = Activator.CreateInstance(elementType); + //object instance = Activator.CreateInstance(elementType); + object instance = settings.CreateInstanceCallback(elementType, emptyObjectArray); + XamlObject obj = new XamlObject(document, element, elementType, instance); ISupportInitialize iSupportInitializeInstance = instance as ISupportInitialize; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParserSettings.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParserSettings.cs new file mode 100644 index 0000000000..f1a938b32c --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParserSettings.cs @@ -0,0 +1,49 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.WpfDesign.XamlDom +{ + /// + /// Delegate used for XamlParserSettings.CreateInstanceCallback. + /// + public delegate object CreateInstanceCallback(Type type, object[] arguments); + + /// + /// Settings used for the XamlParser. + /// + public sealed class XamlParserSettings + { + CreateInstanceCallback _createInstanceCallback = Activator.CreateInstance; + XamlTypeFinder _typeFinder = XamlTypeFinder.CreateWpfTypeFinder(); + + /// + /// Gets/Sets the method used to create object instances. + /// + public CreateInstanceCallback CreateInstanceCallback { + get { return _createInstanceCallback; } + set { + if (value == null) + throw new ArgumentNullException("value"); + _createInstanceCallback = value; + } + } + + /// + /// Gets/Sets the type finder to do type lookup. + /// + public XamlTypeFinder TypeFinder { + get { return _typeFinder; } + set { + if (value == null) + throw new ArgumentNullException("value"); + _typeFinder = value; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs index a4ff757af5..9e194be822 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Tests/TestHelper.cs @@ -28,7 +28,7 @@ namespace ICSharpCode.WpfDesign.XamlDom.Tests Debug.WriteLine("Load using own XamlParser:"); ExampleClass.nextUniqueIndex = 0; TestHelperLog.logBuilder = new StringBuilder(); - XamlDocument doc = XamlParser.Parse(new XmlTextReader(new StringReader(xaml))); + XamlDocument doc = XamlParser.Parse(new StringReader(xaml)); Assert.IsNotNull(doc, "doc is null"); object ownResult = doc.RootInstance; string ownLog = TestHelperLog.logBuilder.ToString(); diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs index 2c4b74edac..ff9e19a9fd 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/DesignItem.cs @@ -108,5 +108,35 @@ namespace ICSharpCode.WpfDesign } } #endregion + + #region Manage behavior + Dictionary _behaviorObjects = new Dictionary(); + + /// + /// Adds a bevahior extension object to this design item. + /// + public void AddBehavior(Type bevahiorInterface, object behaviorImplementation) + { + if (bevahiorInterface == null) + throw new ArgumentNullException("bevahiorInterface"); + if (behaviorImplementation == null) + throw new ArgumentNullException("behaviorImplementation"); + + _behaviorObjects.Add(bevahiorInterface, behaviorImplementation); + } + + /// + /// Gets a bevahior extension object from the design item. + /// + /// The behavior object, or null if it was not found. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] + public T GetBehavior() where T : class + { + object obj; + _behaviorObjects.TryGetValue(typeof(T), out obj); + return (T)obj; + } + #endregion } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/BehaviorExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/BehaviorExtension.cs index c447c36d6a..06633b7497 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/BehaviorExtension.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/BehaviorExtension.cs @@ -51,6 +51,7 @@ namespace ICSharpCode.WpfDesign.Extensions /// /// Is called after the ExtendedItem was set. + /// Override this method to register your behavior with the item. /// protected virtual void OnInitialized() { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/CustomInstanceFactory.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/CustomInstanceFactory.cs new file mode 100644 index 0000000000..b4465d87ee --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/CustomInstanceFactory.cs @@ -0,0 +1,63 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// A special kind of extension that is used to create instances of objects when loading XAML inside + /// the designer. + /// + /// + /// CustomInstanceFactory in Cider: http://blogs.msdn.com/jnak/archive/2006/04/10/572241.aspx + /// + [ExtensionServer(typeof(NeverApplyExtensionsExtensionServer))] + public class CustomInstanceFactory : Extension + { + /// + /// Gets a default instance factory that uses Activator.CreateInstance to create instances. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly CustomInstanceFactory DefaultInstanceFactory = new CustomInstanceFactory(); + + /// + /// Creates a new CustomInstanceFactory instance. + /// + protected CustomInstanceFactory() + { + } + + /// + /// Creates an instance of the specified type, passing the specified arguments to its constructor. + /// + public virtual object CreateInstance(Type type, params object[] arguments) + { + return Activator.CreateInstance(type, arguments); + } + } + + // An extension server that never applies its extensions - used for special extensions + // like CustomInstanceFactory + sealed class NeverApplyExtensionsExtensionServer : ExtensionServer + { + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return false; + } + + public override Extension CreateExtension(Type extensionType, DesignItem extendedItem) + { + throw new NotImplementedException(); + } + + public override void RemoveExtension(Extension extension) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs index 877aec2c2d..0bb2576001 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Extensions/ExtensionManager.cs @@ -83,6 +83,16 @@ namespace ICSharpCode.WpfDesign.Extensions } return result; } + + /// + /// Gets all the types of all extensions that are applied to the specified item type. + /// + public IEnumerable GetExtensionTypes(Type extendedItemType) + { + foreach (ExtensionEntry entry in GetExtensionEntries(extendedItemType)) { + yield return entry.ExtensionType; + } + } #endregion #region Create Extensions diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs index f0f6da193f..424d66fca1 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Tools.cs @@ -41,6 +41,17 @@ namespace ICSharpCode.WpfDesign Highest } + /// + /// Interface for behavior extensions that specifies the input layer of the extended component. + /// + public interface IProvideComponentInputHandlingLayer + { + /// + /// Gets the input handling layer of the component. + /// + InputHandlingLayer InputLayer { get; } + } + /// /// Describes a tool that can handle input on the design surface. /// Modelled after the description on http://urbanpotato.net/Default.aspx/document/2300 diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj index 478d9a8cf3..649df1182b 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/WpfDesign.csproj @@ -62,6 +62,7 @@ +