From 1069fc57dc7976893cb8c8f483bd3d23df3a6436 Mon Sep 17 00:00:00 2001 From: Ivan Shumilin Date: Tue, 21 Oct 2008 11:56:25 +0000 Subject: [PATCH] xaml specification, xaml backend, reorganize code, etc etc git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3609 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- data/options/WpfToolbox.xaml | 61 ++ samples/XamlDesigner/App.xaml | 4 +- samples/XamlDesigner/App.xaml.cs | 2 +- samples/XamlDesigner/Converters.cs | 26 +- samples/XamlDesigner/Document.cs | 198 +++--- samples/XamlDesigner/DocumentView.xaml | 30 +- samples/XamlDesigner/DocumentView.xaml.cs | 102 ++- samples/XamlDesigner/ErrorListView.xaml | 10 +- samples/XamlDesigner/ErrorListView.xaml.cs | 3 +- samples/XamlDesigner/Images/Control.png | Bin 0 -> 470 bytes samples/XamlDesigner/Images/Folder.png | Bin 0 -> 537 bytes samples/XamlDesigner/MainWindow.xaml | 184 +++-- samples/XamlDesigner/MainWindow.xaml.cs | 26 +- samples/XamlDesigner/MainWindow_Commands.cs | 125 ++-- .../XamlDesigner/Properties/AssemblyInfo.cs | 3 + .../Properties/Settings.Designer.cs | 110 +++ .../XamlDesigner/Properties/Settings.settings | 46 ++ samples/XamlDesigner/Properties/app.manifest | 29 + samples/XamlDesigner/Shell.cs | 85 ++- samples/XamlDesigner/SimpleCommand.cs | 2 +- samples/XamlDesigner/TestFiles/grid.xaml | 10 + samples/XamlDesigner/Toolbox.cs | 5 +- samples/XamlDesigner/ToolboxTreeView.cs | 26 + samples/XamlDesigner/XamlDesigner.csproj | 53 +- samples/XamlDesigner/app.config | 51 ++ .../Xaml/Xaml.Tests/EditingTests.cs | 197 ++++++ .../Xaml/Xaml.Tests/Xaml.Tests.csproj | 85 +++ .../Xaml/Xaml.Tests/app.config | 13 + .../Xaml/Xaml/AllowedLocation.cs | 12 + .../Xaml/Xaml/CollectionSupport.cs | 60 ++ .../BackendBindings/Xaml/Xaml/Constructor.cs | 13 + .../Xaml/Xaml/DefaultXamlMember.cs | 70 ++ .../Xaml/Xaml/DefaultXamlType.cs | 140 ++++ .../BackendBindings/Xaml/Xaml/Directive.cs | 68 ++ .../Xaml/Xaml/ExtensionMethods.cs | 20 + .../Xaml/Xaml/IHasAnnotations.cs | 13 + .../Xaml/Xaml/InstanceTracker.cs | 238 +++++++ .../Xaml/Xaml/IntristicMember.cs | 83 +++ .../Xaml/Xaml/IntristicType.cs | 151 +++++ .../Xaml/Xaml/MarkupExtensionParser.cs | 209 ++++++ .../Xaml/Xaml/MarkupExtensionPrinter.cs | 45 ++ .../BackendBindings/Xaml/Xaml/MemberNode.cs | 71 ++ .../Xaml/Xaml/NodeCollection.cs | 68 ++ .../BackendBindings/Xaml/Xaml/ObjectNode.cs | 154 +++++ .../Xaml/Xaml/ReflectionAssembly.cs | 38 ++ .../Xaml/Xaml/ReflectionMapper.cs | 45 ++ .../Xaml/Xaml/ReflectionMember.cs | 87 +++ .../Xaml/Xaml/ReflectionMemberInfo.cs | 284 ++++++++ .../Xaml/Xaml/ReflectionType.cs | 265 ++++++++ .../BackendBindings/Xaml/Xaml/Runtime.cs | 236 +++++++ .../Xaml/Xaml/StandardValues.cs | 135 ++++ .../BackendBindings/Xaml/Xaml/TextNode.cs | 31 + .../BackendBindings/Xaml/Xaml/Tracker.cs | 66 ++ .../Xaml/Xaml/ValueCollection.cs | 11 + .../BackendBindings/Xaml/Xaml/WpfTracker.cs | 14 + .../BackendBindings/Xaml/Xaml/Xaml.csproj | 119 ++++ .../BackendBindings/Xaml/Xaml/XamlAssembly.cs | 18 + .../Xaml/Xaml/XamlConstants.cs | 30 + .../BackendBindings/Xaml/Xaml/XamlContext.cs | 130 ++++ .../BackendBindings/Xaml/Xaml/XamlDocument.cs | 152 +++++ .../Xaml/Xaml/XamlDocumentError.cs | 15 + .../Xaml/Xaml/XamlException.cs | 35 + .../Xaml/Xaml/XamlFormatter.cs | 210 ++++++ .../BackendBindings/Xaml/Xaml/XamlMember.cs | 38 ++ .../BackendBindings/Xaml/Xaml/XamlNode.cs | 77 +++ .../BackendBindings/Xaml/Xaml/XamlParser.cs | 637 ++++++++++++++++++ .../BackendBindings/Xaml/Xaml/XamlProject.cs | 91 +++ .../BackendBindings/Xaml/Xaml/XamlProperty.cs | 268 ++++++++ .../BackendBindings/Xaml/Xaml/XamlType.cs | 51 ++ .../Xaml/Xaml/XamlTypeFinder.cs | 188 ++++++ .../BackendBindings/Xaml/Xaml/XamlValue.cs | 23 + .../BackendBindings/Xaml/Xaml/XmlTracker.cs | 448 ++++++++++++ .../Xaml/Xaml/XmlnsDefinition.cs | 11 + .../XamlBinding.Tests.csproj | 75 +++ .../XamlExpressionFinderTests.cs | 48 ++ .../Xaml/XamlBinding/XamlBinding.addin | 43 ++ .../Xaml/XamlBinding/XamlBinding.csproj | 96 +++ .../Xaml/XamlBinding/XamlClassReturnType.cs | 45 ++ .../XamlBinding/XamlCodeCompletionBinding.cs | 102 +++ .../Xaml/XamlBinding/XamlCompilationUnit.cs | 128 ++++ .../Xaml/XamlBinding/XamlExpressionContext.cs | 63 ++ .../Xaml/XamlBinding/XamlExpressionFinder.cs | 75 +++ .../Xaml/XamlBinding/XamlParser.cs | 151 +++++ .../Xaml/XamlBinding/XamlResolver.cs | 349 ++++++++++ .../AbstractEventHandlerService.cs | 115 ++++ .../CSharpEventHandlerService.cs | 48 ++ .../WpfDesign.AddIn/FileUriContext.cs | 39 ++ .../WpfDesign.AddIn/GetBitmapExtension.cs | 44 ++ .../WpfDesign.AddIn/IdeChooseClassService.cs | 29 + .../WpfDesign/WpfDesign.AddIn/MyTypeFinder.cs | 62 ++ .../WpfDesign.AddIn/ObjectEditor.xaml | 8 + .../WpfDesign.AddIn/ObjectEditor.xaml.cs | 31 + .../WpfDesign.AddIn/OutlineViewPad.cs | 66 ++ .../Properties/AssemblyInfo.cs | 1 + .../PropertyDescriptionService.cs | 26 + .../SharpDevelopElementHost.cs | 123 ++++ .../WpfAndWinFormsTopLevelWindowService.cs | 77 +++ .../WpfDesign.AddIn/WpfDesign.AddIn.csproj | 50 +- .../WpfDesign/WpfDesign.AddIn/WpfDesign.addin | 11 +- .../WpfPrimaryDisplayBinding.cs | 22 + .../WpfDesign.AddIn/WpfPrimaryViewContent.cs | 105 +++ .../WpfSecondaryDisplayBinding.cs | 38 ++ .../WpfSecondaryViewContent.cs | 108 +++ .../WpfDesign.AddIn/WpfSideTabItem.cs | 37 + .../WpfDesign/WpfDesign.AddIn/WpfToolbox.cs | 128 ++++ .../WpfDesign/WpfDesign.AddIn/WpfTools.cs | 94 +++ .../WpfDesign/WpfDesign.AddIn/XamlMapper.cs | 201 ++++++ .../WpfDesign.Designer/BasicMetadata.cs | 256 +++++++ .../WpfDesign.Designer/CallExtension.cs | 111 +++ .../WpfDesign.Designer/Converters.cs | 156 +++++ .../WpfDesign.Designer/DesignPanel.cs | 283 ++++++++ .../WpfDesign.Designer/DesignSurface.xaml | 13 + .../WpfDesign.Designer/DesignSurface.xaml.cs | 125 ++++ .../WpfDesign.Designer/DesignSurface1.xaml | 15 + .../WpfDesign.Designer/DesignSurface1.xaml.cs | 258 +++++++ .../DragDropExceptionHandler.cs | 24 + .../WpfDesign.Designer/ExtensionMethods.cs | 86 +++ .../WpfDesign.Designer/ModelTools.cs | 306 +++++++++ .../Properties/AssemblyInfo.cs | 11 + .../ServiceRequiredException.cs | 58 ++ .../WpfDesign.Designer/SharedInstances.cs | 24 + .../WpfDesign/WpfDesign.Designer/Toolbox.xaml | 16 + .../WpfDesign.Designer/Toolbox.xaml.cs | 107 +++ .../WpfDesign.Designer.csproj | 314 +++++++++ .../XamlBackend/WpfProject.cs | 31 + .../XamlBackend/XamlComponentService.cs | 49 ++ .../XamlBackend/XamlDesignContext.cs | 61 ++ .../XamlBackend/XamlDesignItem.cs | 133 ++++ .../XamlBackend/XamlDesignItemCollection.cs | 140 ++++ .../XamlBackend/XamlDesignItemProperty.cs | 237 +++++++ .../XamlDesignItemPropertyCollection.cs | 32 + .../XamlBackend/XamlModelService.cs | 111 +++ .../Properties/AssemblyInfo.cs | 1 + .../WpfDesign.Tests/WpfDesign.Tests.csproj | 99 +++ .../WpfDesign/WpfDesign.Tests/app.config | 15 + .../DisplayBindings/WpfDesign/WpfDesign.sln | 62 +- .../WpfDesign/WpfDesign/ChangeGroup.cs | 47 ++ .../WpfDesign/WpfDesign/DesignContext.cs | 140 ++++ .../WpfDesign/WpfDesign/DesignItem.cs | 219 ++++++ .../WpfDesign/WpfDesign/DesignItemProperty.cs | 208 ++++++ .../WpfDesign/DesignPanelHitTestResult.cs | 113 ++++ .../WpfDesign/WpfDesign/DesignerException.cs | 50 ++ .../WpfDesign/WpfDesign/EventArgs.cs | 60 ++ .../WpfDesign/WpfDesign/HashSet.cs | 202 ++++++ .../WpfDesign/WpfDesign/Metadata.cs | 413 ++++++++++++ .../WpfDesign/WpfDesign/MouseInteraction.cs | 29 + .../WpfDesign/WpfDesign/PlacementAlignment.cs | 109 +++ .../WpfDesign/WpfDesign/PlacementBehavior.cs | 75 +++ .../WpfDesign/PlacementInformation.cs | 64 ++ .../WpfDesign/WpfDesign/PlacementOperation.cs | 302 +++++++++ .../WpfDesign/WpfDesign/PlacementType.cs | 67 ++ .../WpfDesign/Properties/AssemblyInfo.cs | 3 + .../WpfDesign/WpfDesign/ServiceContainer.cs | 114 ++++ .../WpfDesign/WpfDesign/Services.cs | 303 +++++++++ .../WpfDesign/WpfDesign/Tools.cs | 134 ++++ .../WpfDesign/WpfDesign/WpfDesign.csproj | 127 ++++ .../Project/ICSharpCode.TextEditor.csproj | 2 +- .../Project/Src/Undo/UndoStack.cs | 26 +- .../Gui/Editor/TextEditorDisplayBinding.cs | 7 +- src/SharpDevelop.sln | 303 +++++---- 160 files changed, 14978 insertions(+), 565 deletions(-) create mode 100644 data/options/WpfToolbox.xaml create mode 100644 samples/XamlDesigner/Images/Control.png create mode 100644 samples/XamlDesigner/Images/Folder.png create mode 100644 samples/XamlDesigner/Properties/AssemblyInfo.cs create mode 100644 samples/XamlDesigner/Properties/Settings.Designer.cs create mode 100644 samples/XamlDesigner/Properties/Settings.settings create mode 100644 samples/XamlDesigner/Properties/app.manifest create mode 100644 samples/XamlDesigner/TestFiles/grid.xaml create mode 100644 samples/XamlDesigner/ToolboxTreeView.cs create mode 100644 samples/XamlDesigner/app.config create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml.Tests/EditingTests.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml.Tests/Xaml.Tests.csproj create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml.Tests/app.config create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/AllowedLocation.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/CollectionSupport.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/Constructor.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/DefaultXamlMember.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/DefaultXamlType.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/Directive.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/ExtensionMethods.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/IHasAnnotations.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/InstanceTracker.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/IntristicMember.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/IntristicType.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/MarkupExtensionParser.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/MarkupExtensionPrinter.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/MemberNode.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/NodeCollection.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/ObjectNode.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/ReflectionAssembly.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMapper.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMember.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMemberInfo.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/ReflectionType.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/Runtime.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/StandardValues.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/TextNode.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/Tracker.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/ValueCollection.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/WpfTracker.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlAssembly.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlConstants.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlContext.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlDocumentError.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlException.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlFormatter.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlMember.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlNode.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlParser.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlProject.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlProperty.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlType.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlTypeFinder.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XamlValue.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XmlTracker.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/XmlnsDefinition.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/XamlBinding.Tests.csproj create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/XamlExpressionFinderTests.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlBinding.addin create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlBinding.csproj create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlClassReturnType.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlCodeCompletionBinding.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlCompilationUnit.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlExpressionContext.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlExpressionFinder.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlParser.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/XamlResolver.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/AbstractEventHandlerService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/CSharpEventHandlerService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/FileUriContext.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/GetBitmapExtension.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/IdeChooseClassService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/MyTypeFinder.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/ObjectEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/ObjectEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/OutlineViewPad.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Properties/AssemblyInfo.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/PropertyDescriptionService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/SharpDevelopElementHost.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfAndWinFormsTopLevelWindowService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfPrimaryDisplayBinding.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfPrimaryViewContent.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSecondaryDisplayBinding.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSecondaryViewContent.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSideTabItem.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfToolbox.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfTools.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/XamlMapper.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/BasicMetadata.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/CallExtension.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Converters.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignPanel.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface1.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface1.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DragDropExceptionHandler.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ExtensionMethods.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ModelTools.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Properties/AssemblyInfo.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ServiceRequiredException.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/SharedInstances.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Toolbox.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Toolbox.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/WpfProject.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlComponentService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignContext.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItem.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemCollection.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemProperty.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemPropertyCollection.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlModelService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Properties/AssemblyInfo.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/app.config create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/ChangeGroup.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignContext.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignItem.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignItemProperty.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignPanelHitTestResult.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignerException.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/EventArgs.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/HashSet.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Metadata.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/MouseInteraction.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementAlignment.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementBehavior.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementInformation.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementOperation.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementType.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Properties/AssemblyInfo.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/ServiceContainer.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Services.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Tools.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj diff --git a/data/options/WpfToolbox.xaml b/data/options/WpfToolbox.xaml new file mode 100644 index 0000000000..03c4d44106 --- /dev/null +++ b/data/options/WpfToolbox.xaml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/XamlDesigner/App.xaml b/samples/XamlDesigner/App.xaml index 3a19748fc3..c5322e635e 100644 --- a/samples/XamlDesigner/App.xaml +++ b/samples/XamlDesigner/App.xaml @@ -5,9 +5,9 @@ StartupUri="MainWindow.xaml" ShutdownMode="OnMainWindowClose"> - + - + diff --git a/samples/XamlDesigner/App.xaml.cs b/samples/XamlDesigner/App.xaml.cs index 12ea48806c..1b86d3654f 100644 --- a/samples/XamlDesigner/App.xaml.cs +++ b/samples/XamlDesigner/App.xaml.cs @@ -4,7 +4,7 @@ using System.Configuration; using System.Data; using System.Linq; using System.Windows; -using ICSharpCode.XamlDesigner.Configuration; +using ICSharpCode.XamlDesigner.Properties; using System.Windows.Threading; using System.Diagnostics; diff --git a/samples/XamlDesigner/Converters.cs b/samples/XamlDesigner/Converters.cs index feeb6d9d02..a9c2ac2bc7 100644 --- a/samples/XamlDesigner/Converters.cs +++ b/samples/XamlDesigner/Converters.cs @@ -9,21 +9,21 @@ using System.Collections; namespace ICSharpCode.XamlDesigner.Converters { - public class EnumToIntConverter : IValueConverter - { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) - { - return (int)value; - } + public class EnumToIntConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (int)value; + } - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) - { - return value; - } - } + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value; + } + } public class CollapsedWhenFalse : IValueConverter - { + { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (bool)value ? Visibility.Visible : Visibility.Collapsed; @@ -36,7 +36,7 @@ namespace ICSharpCode.XamlDesigner.Converters } public class FalseWhenZero : IValueConverter - { + { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || (int)value == 0) { diff --git a/samples/XamlDesigner/Document.cs b/samples/XamlDesigner/Document.cs index 4998e87618..1899c1a151 100644 --- a/samples/XamlDesigner/Document.cs +++ b/samples/XamlDesigner/Document.cs @@ -5,7 +5,7 @@ using System.Text; using System.ComponentModel; using System.IO; using ICSharpCode.WpfDesign.Designer; -using ICSharpCode.WpfDesign.Designer.Xaml; +using ICSharpCode.WpfDesign.Designer.XamlBackend; using ICSharpCode.WpfDesign.Designer.OutlineView; using System.Xml; using ICSharpCode.WpfDesign; @@ -17,28 +17,41 @@ namespace ICSharpCode.XamlDesigner public class Document : INotifyPropertyChanged { public Document(string tempName, string text) + : this() { this.tempName = tempName; Text = text; + Context.Parse(Text); IsDirty = false; } public Document(string filePath) + : this() { this.filePath = filePath; ReloadFile(); } - + + Document() + { + var doc = Shell.Instance.Project.CreateDocument(); + context = new XamlDesignContext(doc); + context.UndoService.UndoStackChanged += new EventHandler(UndoService_UndoStackChanged); + } + string tempName; - DesignSurface designSurface = new DesignSurface(); + XamlDesignContext context; string text; - public string Text { - get { + public string Text + { + get + { return text; } - set { + set + { if (text != value) { text = value; IsDirty = true; @@ -49,39 +62,47 @@ namespace ICSharpCode.XamlDesigner DocumentMode mode; - public DocumentMode Mode { - get { + public DocumentMode Mode + { + get + { return mode; } - set { + set + { mode = value; - if (InDesignMode) { - UpdateDesign(); - } - else { - UpdateXaml(); - } + //if (InDesignMode) { + // UpdateDesign(); + //} + //else { + // UpdateXaml(); + //} RaisePropertyChanged("Mode"); RaisePropertyChanged("InXamlMode"); RaisePropertyChanged("InDesignMode"); } } - public bool InXamlMode { + public bool InXamlMode + { get { return Mode == DocumentMode.Xaml; } } - public bool InDesignMode { + public bool InDesignMode + { get { return Mode == DocumentMode.Design; } } string filePath; - public string FilePath { - get { + public string FilePath + { + get + { return filePath; } - private set { + private set + { filePath = value; RaisePropertyChanged("FilePath"); RaisePropertyChanged("FileName"); @@ -92,11 +113,14 @@ namespace ICSharpCode.XamlDesigner bool isDirty; - public bool IsDirty { - get { + public bool IsDirty + { + get + { return isDirty; } - private set { + private set + { isDirty = value; RaisePropertyChanged("IsDirty"); RaisePropertyChanged("Name"); @@ -104,79 +128,59 @@ namespace ICSharpCode.XamlDesigner } } - public string FileName { - get { + public string FileName + { + get + { if (FilePath == null) return null; return Path.GetFileName(FilePath); } } - public string Name { - get { + public string Name + { + get + { return FileName ?? tempName; } } - public string Title { - get { + public string Title + { + get + { return IsDirty ? Name + "*" : Name; } } - public DesignSurface DesignSurface { - get { return designSurface; } - } - - public DesignContext DesignContext { - get { return designSurface.DesignContext; } - } - - public UndoService UndoService { - get { return DesignContext.Services.GetService(); } - } - - public ISelectionService SelectionService { - get { - if (InDesignMode) { - return DesignContext.Services.Selection; - } - return null; - } - } - - public XamlErrorService XamlErrorService { - get { - if (DesignContext != null) { - return DesignContext.Services.GetService(); - } - return null; - } + public DesignContext Context + { + get { return context; } } - OutlineNode outlineRoot; - - public OutlineNode OutlineRoot { - get { - return outlineRoot; - } - private set { - outlineRoot = value; - RaisePropertyChanged("OutlineRoot"); - } - } + //TODO + //public XamlErrorService XamlErrorService { + // get { + // if (DesignContext != null) { + // return DesignContext.GetService(); + // } + // return null; + // } + //} void ReloadFile() { Text = File.ReadAllText(FilePath); - UpdateDesign(); + //UpdateDesign(); + Context.Parse(Text); IsDirty = false; } public void Save() { - if (InDesignMode) { - UpdateXaml(); - } + //if (InDesignMode) { + // UpdateXaml(); + //} File.WriteAllText(FilePath, Text); IsDirty = false; } @@ -189,41 +193,33 @@ namespace ICSharpCode.XamlDesigner public void Refresh() { - UpdateXaml(); - UpdateDesign(); + //UpdateXaml(); + //UpdateDesign(); } - void UpdateXaml() - { - if (DesignContext.CanSave && UndoService.CanUndo) { - var sb = new StringBuilder(); - using (var xmlWriter = XmlWriter.Create(sb)) { - DesignSurface.SaveDesigner(xmlWriter); - Text = XamlFormatter.Format(sb.ToString()); - } - } - } + //void UpdateXaml() + //{ + // if (Context.CanSave) { + // Text = Context.Save(); + // } + //} - void UpdateDesign() - { - OutlineRoot = null; - using (var xmlReader = XmlReader.Create(new StringReader(Text))) { - DesignSurface.LoadDesigner(xmlReader, null); - } - if (DesignContext.RootItem != null) { - OutlineRoot = OutlineNode.Create(DesignContext.RootItem); - UndoService.UndoStackChanged += new EventHandler(UndoService_UndoStackChanged); - } - RaisePropertyChanged("SelectionService"); - RaisePropertyChanged("XamlErrorService"); - } + //void UpdateDesign() + //{ + // Context.Parse(Text); + //} void UndoService_UndoStackChanged(object sender, EventArgs e) { - IsDirty = true; - if (InXamlMode) { - UpdateXaml(); - } + IsDirty = Context.UndoService.CanUndo; + if (Context.ParseSuggested) { + Context.Parse(Text); + } + //if (Context.Is + //IsDirty = true; + //if (InXamlMode) { + // UpdateXaml(); + //} } #region INotifyPropertyChanged Members diff --git a/samples/XamlDesigner/DocumentView.xaml b/samples/XamlDesigner/DocumentView.xaml index 8306752798..9e1632feab 100644 --- a/samples/XamlDesigner/DocumentView.xaml +++ b/samples/XamlDesigner/DocumentView.xaml @@ -1,23 +1,23 @@ - - + + + DockPanel.Dock="Bottom" /> - + - + + - + \ No newline at end of file diff --git a/samples/XamlDesigner/DocumentView.xaml.cs b/samples/XamlDesigner/DocumentView.xaml.cs index b9bbcb53f4..a61ce04bd9 100644 --- a/samples/XamlDesigner/DocumentView.xaml.cs +++ b/samples/XamlDesigner/DocumentView.xaml.cs @@ -13,6 +13,13 @@ using System.Windows.Navigation; using System.Windows.Shapes; using ICSharpCode.WpfDesign.Designer.Services; using System.Windows.Threading; +using ICSharpCode.Xaml; +using ICSharpCode.WpfDesign.Designer; +using ICSharpCode.TextEditor; +using System.Windows.Forms; +using ICSharpCode.TextEditor.Document; +using ICSharpCode.WpfDesign; +using ICSharpCode.TextEditor.Undo; namespace ICSharpCode.XamlDesigner { @@ -22,21 +29,106 @@ namespace ICSharpCode.XamlDesigner { InitializeComponent(); - Document = doc; + ShellDocument = doc; Shell.Instance.Views[doc] = this; uxTextEditor.SetHighlighting("XML"); uxTextEditor.DataBindings.Add("Text", doc, "Text", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged); + ShellDocument.Context.AddService(typeof(ITextContainer), uxTextEditor); + + uxTextEditor.Document.UndoStack.OperationPushed += UndoStack_OperationPushed; + uxTextEditor.Document.DocumentChanged += Document_DocumentChanged; + uxTextEditor.Document.DocumentAboutToBeChanged += Document_DocumentAboutToBeChanged; + } + + public Document ShellDocument { get; private set; } + + IUndoableOperation lastOperation; + bool textValid; + + void Document_DocumentAboutToBeChanged(object sender, DocumentEventArgs e) + { + textValid = false; + } + + void Document_DocumentChanged(object sender, DocumentEventArgs e) + { + textValid = true; + TryUpdateDesignUndoStack(); + } + + void UndoStack_OperationPushed(object sender, OperationEventArgs e) + { + lastOperation = e.Operation; + TryUpdateDesignUndoStack(); + } + + void TryUpdateDesignUndoStack() + { + if (textValid && lastOperation != null) { + ShellDocument.Context.UndoService.Done(new TextAction(lastOperation)); + lastOperation = null; + } } - public Document Document { get; private set; } + public DesignSurface DesignSurface + { + get + { + return uxDesignSurface; + } + } - public void JumpToError(XamlError error) + public void JumpToError(XamlDocumentError error) { - Document.Mode = DocumentMode.Xaml; + ShellDocument.Mode = DocumentMode.Xaml; Dispatcher.BeginInvoke(new Action(delegate { - uxTextEditor.ActiveTextAreaControl.JumpTo(error.Line - 1, error.Column - 1); + uxTextEditor.ActiveTextAreaControl.JumpTo(error.LineNumber - 1, error.LinePosition - 1); }), DispatcherPriority.Background); } } + + class TextEditorWithoutUndo : TextEditorControl, ITextContainer + { + public TextEditorWithoutUndo() + { + editactions.Remove(Keys.Control | Keys.Z); + editactions.Remove(Keys.Control | Keys.Y); + } + + public override void EndUpdate() + { + base.EndUpdate(); + } + } + + class TextAction : ITextAction + { + public TextAction(IUndoableOperation op) + { + this.op = op; + } + + IUndoableOperation op; + + public IEnumerable AffectedItems + { + get { yield break; } + } + + public string Title + { + get { return "Text Editing"; } + } + + public void Do() + { + op.Redo(); + } + + public void Undo() + { + op.Undo(); + } + } } diff --git a/samples/XamlDesigner/ErrorListView.xaml b/samples/XamlDesigner/ErrorListView.xaml index fa661fa0e3..b5bc2625ec 100644 --- a/samples/XamlDesigner/ErrorListView.xaml +++ b/samples/XamlDesigner/ErrorListView.xaml @@ -1,15 +1,15 @@  + xmlns:Xaml="clr-namespace:ICSharpCode.Xaml;assembly=ICSharpCode.Xaml"> - + - + Margin="2" /> + diff --git a/samples/XamlDesigner/ErrorListView.xaml.cs b/samples/XamlDesigner/ErrorListView.xaml.cs index 9d866bd82a..4faf31f33f 100644 --- a/samples/XamlDesigner/ErrorListView.xaml.cs +++ b/samples/XamlDesigner/ErrorListView.xaml.cs @@ -12,6 +12,7 @@ using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using ICSharpCode.WpfDesign.Designer.Services; +using ICSharpCode.Xaml; namespace ICSharpCode.XamlDesigner { @@ -24,7 +25,7 @@ namespace ICSharpCode.XamlDesigner protected override void OnMouseDoubleClick(MouseButtonEventArgs e) { - var error = e.GetDataContext() as XamlError; + var error = e.GetDataContext() as XamlDocumentError; if (error != null) { Shell.Instance.JumpToError(error); } diff --git a/samples/XamlDesigner/Images/Control.png b/samples/XamlDesigner/Images/Control.png new file mode 100644 index 0000000000000000000000000000000000000000..386cb302f16b36e4ae67dc9f0aea1b4a051c22c6 GIT binary patch literal 470 zcmV;{0V)28P)``2`~zsHhc-<7$F60BN8G$;h9Qc)$m zPjaF(rLGTDO~!4K5|M!ls#FRA{~+9_mh$B%Z0UrmNw|v!8R{*)VvIsyE!@@WjQ0Lu zG45gF&|%`^8m{Z2fQS@JKovnbzF5W>!$F>t_qCIs%wUXRcKm?<7uRk6jy>0U{$XW$ zkEc3qYB0utYFr3Nl5}@-_vnko8F3szAXJEHK*aJ;t?e|ae*4Gt7rT9)_)n@C%m4rY M07*qoM6N<$f~O_aVE_OC literal 0 HcmV?d00001 diff --git a/samples/XamlDesigner/Images/Folder.png b/samples/XamlDesigner/Images/Folder.png new file mode 100644 index 0000000000000000000000000000000000000000..784e8fa48234f4f64b6922a6758f254ee0ca08ec GIT binary patch literal 537 zcmV+!0_OdRP)x(K@^6+>g^d@v4;gkbWsEoXE%32*i1tcpTNXd5CcIl)ECgqz|2rE6EW}s7R?kl za1q`0GCkMruC6-2LANtwVlsgzsp4?{@7$`KBv!G66>Vie3h?3OmEEkjwdLG0PgLVi z`!N((f$A@n17Ldj#`};0I3@iHJ5M{#IZz|UIYRm4(!uV7eYIYIwQf&}_2J~}>pQ^n z6o8--^T(=hkBNQ_k{-_GWE;FMW7!p}f{NG3nHZ{D5<3d8&tLh%a4AqqnjMkr3m&fkMdECD3N5}Unig5wy40;>lo4j~k+e}v)` zR6)J8Mk*u=SpB`p6o)7j?S0T@9?bz#m@l>gc*zk__|*!FMcHwP!gwLJvS~9c0px8E zW - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/XamlDesigner/MainWindow.xaml.cs b/samples/XamlDesigner/MainWindow.xaml.cs index 3874cc1a47..7c88be3fd9 100644 --- a/samples/XamlDesigner/MainWindow.xaml.cs +++ b/samples/XamlDesigner/MainWindow.xaml.cs @@ -10,13 +10,14 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; -using ICSharpCode.XamlDesigner.Configuration; +using ICSharpCode.XamlDesigner.Properties; using System.ComponentModel; using Microsoft.Win32; using AvalonDock; using System.IO; using System.Collections.Specialized; using ICSharpCode.WpfDesign.Designer; +using ICSharpCode.Xaml; namespace ICSharpCode.XamlDesigner { @@ -27,15 +28,12 @@ namespace ICSharpCode.XamlDesigner Instance = this; DataContext = Shell.Instance; RenameCommands(); - BasicMetadata.Register(); InitializeComponent(); Shell.Instance.PropertyGrid = uxPropertyGridView.PropertyGrid; AvalonDockWorkaround(); - RouteDesignSurfaceCommands(); - - this.AddCommandHandler(RefreshCommand, Shell.Instance.Refresh, Shell.Instance.CanRefresh); + RegisterCommandHandlers(); LoadSettings(); ProcessPaths(App.Args); @@ -89,7 +87,7 @@ namespace ICSharpCode.XamlDesigner e.Effects = DragDropEffects.Copy; break; } - else if (path.EndsWith(".xaml", StringComparison.InvariantCultureIgnoreCase)) { + else if (XamlConstants.HasXamlExtension(path)) { e.Effects = DragDropEffects.Copy; break; } @@ -99,11 +97,12 @@ namespace ICSharpCode.XamlDesigner void ProcessPaths(IEnumerable paths) { foreach (var path in paths) { - if (path.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) || - path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase)) { - Toolbox.Instance.AddAssembly(path); - } - else if (path.EndsWith(".xaml", StringComparison.InvariantCultureIgnoreCase)) { + //if (path.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) || + // path.EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase)) { + // Toolbox.Instance.AddAssembly(path); + //} + //else + if (XamlConstants.HasXamlExtension(path)) { Shell.Instance.Open(path); } } @@ -149,6 +148,11 @@ namespace ICSharpCode.XamlDesigner if (Settings.Default.AvalonDockLayout != null) { uxDockingManager.RestoreLayout(Settings.Default.AvalonDockLayout.ToStream()); } + + var toolboxContentPath = "WpfToolbox.xaml"; + if (File.Exists(toolboxContentPath)) { + uxToolbox.Load(File.ReadAllText(toolboxContentPath)); + } } void SaveSettings() diff --git a/samples/XamlDesigner/MainWindow_Commands.cs b/samples/XamlDesigner/MainWindow_Commands.cs index 040f15a27c..a1eaf2ece3 100644 --- a/samples/XamlDesigner/MainWindow_Commands.cs +++ b/samples/XamlDesigner/MainWindow_Commands.cs @@ -4,6 +4,8 @@ using System.Linq; using System.Text; using System.Windows.Input; using System.Windows; +using ICSharpCode.WpfDesign.Designer; +using ICSharpCode.WpfDesign; namespace ICSharpCode.XamlDesigner { @@ -20,81 +22,122 @@ namespace ICSharpCode.XamlDesigner ApplicationCommands.SaveAs.Text = "Save As..."; } - void NewCommand_Executed(object sender, ExecutedRoutedEventArgs e) + void RegisterCommandHandlers() { - Shell.Instance.New(); + this.AddCommandHandler(ApplicationCommands.New, Shell.Instance.New); + this.AddCommandHandler(ApplicationCommands.Open, Shell.Instance.Open); + this.AddCommandHandler(ApplicationCommands.Close, Shell.Instance.CloseCurrentDocument, HasCurrentDocument); + this.AddCommandHandler(ApplicationCommands.Save, Shell.Instance.SaveCurrentDocument, HasCurrentDocument); + this.AddCommandHandler(ApplicationCommands.SaveAs, Shell.Instance.SaveCurrentDocumentAs, HasCurrentDocument); + + this.AddCommandHandler(SaveAllCommand, SaveAll, HasCurrentDocument); + this.AddCommandHandler(CloseAllCommand, CloseAll, HasCurrentDocument); + this.AddCommandHandler(ExitCommand, Shell.Instance.Exit, HasCurrentDocument); + this.AddCommandHandler(RefreshCommand, Shell.Instance.Refresh, Shell.Instance.CanRefresh); + + this.AddCommandHandler(ApplicationCommands.Undo, Undo, CanUndo); + this.AddCommandHandler(ApplicationCommands.Redo, Redo, CanRedo); + this.AddCommandHandler(ApplicationCommands.Copy, Copy, CanCopy); + this.AddCommandHandler(ApplicationCommands.Cut, Cut, CanCut); + this.AddCommandHandler(ApplicationCommands.Delete, Delete, CanDelete); + this.AddCommandHandler(ApplicationCommands.Paste, Paste, CanPaste); + this.AddCommandHandler(ApplicationCommands.SelectAll, SelectAll, CanSelectAll); } - void OpenCommand_Executed(object sender, ExecutedRoutedEventArgs e) + bool HasCurrentDocument() { - Shell.Instance.Open(); + return Shell.Instance.CurrentDocument != null; } - void CloseCommand_Executed(object sender, ExecutedRoutedEventArgs e) + void SaveAll() { - Shell.Instance.CloseCurrentDocument(); + Shell.Instance.SaveAll(); } - void CloseCommand_PreviewExecuted(object sender, ExecutedRoutedEventArgs e) + void CloseAll() { - Shell.Instance.CloseCurrentDocument(); + Shell.Instance.CloseAll(); } - void CloseAllCommand_Executed(object sender, ExecutedRoutedEventArgs e) + ICommandService CurrentCommandService { - Shell.Instance.CloseAll(); + get + { + if (Shell.Instance.CurrentDocument != null) { + return Shell.Instance.CurrentDocument.Context.CommandService; + } + return null; + } } - void SaveCommand_Executed(object sender, ExecutedRoutedEventArgs e) + void Undo() { - Shell.Instance.SaveCurrentDocument(); + CurrentCommandService.Undo(); } - void SaveAsCommand_Executed(object sender, ExecutedRoutedEventArgs e) + void Redo() { - Shell.Instance.SaveCurrentDocumentAs(); + CurrentCommandService.Redo(); } - void SaveAllCommand_Executed(object sender, ExecutedRoutedEventArgs e) + void Copy() { - Shell.Instance.SaveAll(); + CurrentCommandService.Copy(); } - void ExitCommand_Executed(object sender, ExecutedRoutedEventArgs e) + void Paste() { - Shell.Instance.Exit(); + CurrentCommandService.Paste(); } - void CurrentDocument_CanExecute(object sender, CanExecuteRoutedEventArgs e) + void Cut() { - e.CanExecute = Shell.Instance.CurrentDocument != null; + CurrentCommandService.Cut(); } - void RouteDesignSurfaceCommands() + void SelectAll() { - RouteDesignSurfaceCommand(ApplicationCommands.Undo); - RouteDesignSurfaceCommand(ApplicationCommands.Redo); - RouteDesignSurfaceCommand(ApplicationCommands.Copy); - RouteDesignSurfaceCommand(ApplicationCommands.Cut); - RouteDesignSurfaceCommand(ApplicationCommands.Paste); - RouteDesignSurfaceCommand(ApplicationCommands.SelectAll); - RouteDesignSurfaceCommand(ApplicationCommands.Delete); + CurrentCommandService.SelectAll(); } - void RouteDesignSurfaceCommand(RoutedCommand command) + void Delete() { - var cb = new CommandBinding(command); - cb.CanExecute += delegate(object sender, CanExecuteRoutedEventArgs e) { - if (Shell.Instance.CurrentDocument != null) { - Shell.Instance.CurrentDocument.DesignSurface.RaiseEvent(e); - }else { - e.CanExecute = false; - } - }; - cb.Executed += delegate(object sender, ExecutedRoutedEventArgs e) { - Shell.Instance.CurrentDocument.DesignSurface.RaiseEvent(e); - }; - CommandBindings.Add(cb); + CurrentCommandService.Delete(); + } + + bool CanUndo() + { + return CurrentCommandService != null && CurrentCommandService.CanUndo(); + } + + bool CanRedo() + { + return CurrentCommandService != null && CurrentCommandService.CanRedo(); + } + + bool CanCopy() + { + return CurrentCommandService != null && CurrentCommandService.CanCopy(); + } + + bool CanPaste() + { + return CurrentCommandService != null && CurrentCommandService.CanPaste(); + } + + bool CanCut() + { + return CurrentCommandService != null && CurrentCommandService.CanCut(); + } + + bool CanSelectAll() + { + return CurrentCommandService != null && CurrentCommandService.CanSelectAll(); + } + + bool CanDelete() + { + return CurrentCommandService != null && CurrentCommandService.CanDelete(); } } } diff --git a/samples/XamlDesigner/Properties/AssemblyInfo.cs b/samples/XamlDesigner/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..c0ea722fa8 --- /dev/null +++ b/samples/XamlDesigner/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Windows; + +[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] \ No newline at end of file diff --git a/samples/XamlDesigner/Properties/Settings.Designer.cs b/samples/XamlDesigner/Properties/Settings.Designer.cs new file mode 100644 index 0000000000..213b5bbc32 --- /dev/null +++ b/samples/XamlDesigner/Properties/Settings.Designer.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.3053 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ICSharpCode.XamlDesigner.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0,0,0,0")] + public global::System.Windows.Rect MainWindowRect { + get { + return ((global::System.Windows.Rect)(this["MainWindowRect"])); + } + set { + this["MainWindowRect"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute(@" + + + + + + + + + + + + + + + + + + + + + +")] + public string AvalonDockLayout { + get { + return ((string)(this["AvalonDockLayout"])); + } + set { + this["AvalonDockLayout"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Collections.Specialized.StringCollection RecentFiles { + get { + return ((global::System.Collections.Specialized.StringCollection)(this["RecentFiles"])); + } + set { + this["RecentFiles"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute(@" + + %ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\PresentationFramework.dll +")] + public global::System.Collections.Specialized.StringCollection AssemblyList { + get { + return ((global::System.Collections.Specialized.StringCollection)(this["AssemblyList"])); + } + set { + this["AssemblyList"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("Maximized")] + public global::System.Windows.WindowState MainWindowState { + get { + return ((global::System.Windows.WindowState)(this["MainWindowState"])); + } + set { + this["MainWindowState"] = value; + } + } + } +} diff --git a/samples/XamlDesigner/Properties/Settings.settings b/samples/XamlDesigner/Properties/Settings.settings new file mode 100644 index 0000000000..06bf0de18a --- /dev/null +++ b/samples/XamlDesigner/Properties/Settings.settings @@ -0,0 +1,46 @@ + + + + + + 0,0,0,0 + + + <DockingManager> + <ResizingPanel Orientation="Horizontal"> + <ResizingPanel ResizeWidth="200" Orientation="Vertical"> + <DockablePane ResizeHeight="441.36166666666668" Anchor="Left"> + <DockableContent Name="content1" AutoHide="false" /> + </DockablePane> + <DockablePane ResizeWidth="200" Anchor="Left"> + <DockableContent Name="content2" AutoHide="false" /> + </DockablePane> + </ResizingPanel> + <ResizingPanel Orientation="Vertical"> + <DocumentPanePlaceHolder /> + <DockablePane ResizeHeight="138" Anchor="Bottom"> + <DockableContent Name="content3" AutoHide="false" /> + </DockablePane> + </ResizingPanel> + <DockablePane ResizeWidth="271" Anchor="Right"> + <DockableContent Name="content4" AutoHide="false" /> + </DockablePane> + </ResizingPanel> + <Hidden /> + <Windows /> +</DockingManager> + + + + + + <?xml version="1.0" encoding="utf-16"?> +<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <string>%ProgramFiles%\Reference Assemblies\Microsoft\Framework\v3.0\PresentationFramework.dll</string> +</ArrayOfString> + + + Maximized + + + \ No newline at end of file diff --git a/samples/XamlDesigner/Properties/app.manifest b/samples/XamlDesigner/Properties/app.manifest new file mode 100644 index 0000000000..e82a10f183 --- /dev/null +++ b/samples/XamlDesigner/Properties/app.manifest @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/XamlDesigner/Shell.cs b/samples/XamlDesigner/Shell.cs index 2f1a0abe41..222ba76781 100644 --- a/samples/XamlDesigner/Shell.cs +++ b/samples/XamlDesigner/Shell.cs @@ -5,12 +5,14 @@ using System.Text; using System.ComponentModel; using System.Collections.ObjectModel; using ICSharpCode.WpfDesign.Designer.PropertyGrid; -using ICSharpCode.XamlDesigner.Configuration; +using ICSharpCode.XamlDesigner.Properties; using System.Collections.Specialized; using System.IO; using System.Windows; using System.Diagnostics; using ICSharpCode.WpfDesign.Designer.Services; +using ICSharpCode.Xaml; +using ICSharpCode.WpfDesign.Designer.XamlBackend; namespace ICSharpCode.XamlDesigner { @@ -29,29 +31,52 @@ namespace ICSharpCode.XamlDesigner public const string ApplicationTitle = "Xaml Designer"; //public Toolbox Toolbox { get; set; } - //public SceneTree SceneTree { get; set; } - public PropertyGrid PropertyGrid { get; internal set; } - //public ErrorList ErrorList { get; set; } - + //public SceneTree SceneTree { get; set; } + public PropertyGrid PropertyGrid { get; internal set; } + //public ErrorList ErrorList { get; set; } + public ObservableCollection Documents { get; private set; } - public ObservableCollection RecentFiles { get; private set; } + public ObservableCollection RecentFiles { get; private set; } public Dictionary Views { get; private set; } + XamlProject project = new DefaultWpfProject(); + + public XamlProject Project + { + get { return project; } + } + Document currentDocument; - public Document CurrentDocument { - get { + public Document CurrentDocument + { + get + { return currentDocument; } - set { + set + { currentDocument = value; RaisePropertyChanged("CurrentDocument"); RaisePropertyChanged("Title"); } } - public string Title { - get { + public DocumentView CurrentDocumentView + { + get + { + if (CurrentDocument != null) { + return Views[CurrentDocument] as DocumentView; + } + return null; + } + } + + public string Title + { + get + { if (CurrentDocument != null) { return CurrentDocument.Title + " - " + ApplicationTitle; } @@ -84,7 +109,7 @@ namespace ICSharpCode.XamlDesigner MessageBox.Show(x.ToString()); } - public void JumpToError(XamlError error) + public void JumpToError(XamlDocumentError error) { if (CurrentDocument != null) { (Views[CurrentDocument] as DocumentView).JumpToError(error); @@ -103,8 +128,10 @@ namespace ICSharpCode.XamlDesigner #region Files - bool IsSomethingDirty { - get { + bool IsSomethingDirty + { + get + { foreach (var doc in Shell.Instance.Documents) { if (doc.IsDirty) return true; } @@ -115,22 +142,22 @@ namespace ICSharpCode.XamlDesigner static int nonameIndex = 1; public void New() - { - Document doc = new Document("New" + nonameIndex++, File.ReadAllText("NewFileTemplate.xaml")); - Documents.Add(doc); - CurrentDocument = doc; - } + { + Document doc = new Document("New" + nonameIndex++, File.ReadAllText("NewFileTemplate.xaml")); + Documents.Add(doc); + CurrentDocument = doc; + } public void Open() - { + { var path = MainWindow.Instance.AskOpenFileName(); if (path != null) { Open(path); } } - public void Open(string path) - { + public void Open(string path) + { path = Path.GetFullPath(path); if (RecentFiles.Contains(path)) { @@ -145,10 +172,10 @@ namespace ICSharpCode.XamlDesigner } } - var newDoc = new Document(path); - Documents.Add(newDoc); - CurrentDocument = newDoc; - } + var newDoc = new Document(path); + Documents.Add(newDoc); + CurrentDocument = newDoc; + } public bool Save(Document doc) { @@ -165,7 +192,7 @@ namespace ICSharpCode.XamlDesigner { var initName = doc.FileName ?? doc.Name + ".xaml"; var path = MainWindow.Instance.AskSaveFileName(initName); - if (path != null) { + if (path != null) { doc.SaveAs(path); return true; } @@ -183,7 +210,7 @@ namespace ICSharpCode.XamlDesigner public bool Close(Document doc) { if (doc.IsDirty) { - var result = MessageBox.Show("Save \"" + doc.Name + "\" ?", Shell.ApplicationTitle, + var result = MessageBox.Show("Save \"" + doc.Name + "\" ?", Shell.ApplicationTitle, MessageBoxButton.YesNoCancel, MessageBoxImage.Question); if (result == MessageBoxResult.Yes) { @@ -211,7 +238,7 @@ namespace ICSharpCode.XamlDesigner if (IsSomethingDirty) { var result = MessageBox.Show("Save All?", Shell.ApplicationTitle, MessageBoxButton.YesNoCancel, MessageBoxImage.Question); - + if (result == MessageBoxResult.Yes) { if (!SaveAll()) return false; } diff --git a/samples/XamlDesigner/SimpleCommand.cs b/samples/XamlDesigner/SimpleCommand.cs index 3daea1f5f0..eadd7217e6 100644 --- a/samples/XamlDesigner/SimpleCommand.cs +++ b/samples/XamlDesigner/SimpleCommand.cs @@ -19,7 +19,7 @@ namespace ICSharpCode.XamlDesigner Text = text; } - public SimpleCommand(string text, Key key) + public SimpleCommand(string text, Key key) : this(text, ModifierKeys.None, key) { } diff --git a/samples/XamlDesigner/TestFiles/grid.xaml b/samples/XamlDesigner/TestFiles/grid.xaml new file mode 100644 index 0000000000..e2d186be94 --- /dev/null +++ b/samples/XamlDesigner/TestFiles/grid.xaml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/samples/XamlDesigner/Toolbox.cs b/samples/XamlDesigner/Toolbox.cs index fcab34988b..b2276b3d17 100644 --- a/samples/XamlDesigner/Toolbox.cs +++ b/samples/XamlDesigner/Toolbox.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using System.Reflection; using System.Collections.ObjectModel; -using ICSharpCode.XamlDesigner.Configuration; +using ICSharpCode.XamlDesigner.Properties; using System.Windows; using System.Collections.Specialized; using ICSharpCode.WpfDesign; @@ -52,12 +52,15 @@ namespace ICSharpCode.XamlDesigner } Settings.Default.AssemblyList.Add(path); } + + Shell.Instance.Project.AddReference(assembly); } public void Remove(AssemblyNode node) { AssemblyNodes.Remove(node); Settings.Default.AssemblyList.Remove(node.Path); + Shell.Instance.Project.RemoveReference(node.Assembly); } public void LoadSettings() diff --git a/samples/XamlDesigner/ToolboxTreeView.cs b/samples/XamlDesigner/ToolboxTreeView.cs new file mode 100644 index 0000000000..9422515185 --- /dev/null +++ b/samples/XamlDesigner/ToolboxTreeView.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.WpfDesign.Designer.OutlineView; + +namespace ICSharpCode.XamlDesigner +{ + class ToolboxTreeView : DragTreeView + { + protected override bool CanInsert(DragTreeViewItem target, DragTreeViewItem[] items, DragTreeViewItem after, bool copy) + { + return base.CanInsert(target, items, after, copy); + } + + protected override void Insert(DragTreeViewItem target, DragTreeViewItem[] items, DragTreeViewItem after, bool copy) + { + base.Insert(target, items, after, copy); + } + + protected override void Remove(DragTreeViewItem target, DragTreeViewItem item) + { + base.Remove(target, item); + } + } +} diff --git a/samples/XamlDesigner/XamlDesigner.csproj b/samples/XamlDesigner/XamlDesigner.csproj index ed892c2e4f..61839e3fc6 100644 --- a/samples/XamlDesigner/XamlDesigner.csproj +++ b/samples/XamlDesigner/XamlDesigner.csproj @@ -13,7 +13,7 @@ 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 - Configuration\app.manifest + Properties\app.manifest true @@ -90,45 +90,44 @@ - Configuration\GlobalAssemblyInfo.cs + Properties\GlobalAssemblyInfo.cs BitmapButton.xaml - - Code - - - True - True - Settings.settings - DocumentView.xaml + UserControl ErrorListView.xaml + + + True + True + Settings.settings + MainWindow.xaml - - - ToolboxView.xaml - - Designer Always + + WpfToolbox.xaml + Designer + PreserveNewest + MSBuild:Compile Designer @@ -161,15 +160,11 @@ Designer MSBuild:Compile - - MSBuild:Compile - Designer - - - - + + + SettingsSingleFileGenerator Settings.Designer.cs @@ -179,13 +174,17 @@ - - {88DA149F-21B2-48AB-82C4-28FB6BDFD783} - WpfDesign.XamlDom - + - + + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD} + Xaml + + + {78CC29AC-CC79-4355-B1F2-97936DF198AC} + WpfDesign.Designer + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Xaml/Xaml.Tests/app.config b/src/AddIns/BackendBindings/Xaml/Xaml.Tests/app.config new file mode 100644 index 0000000000..09b260ec97 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml.Tests/app.config @@ -0,0 +1,13 @@ + + + + +
+ + + + + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/AllowedLocation.cs b/src/AddIns/BackendBindings/Xaml/Xaml/AllowedLocation.cs new file mode 100644 index 0000000000..9011ea5173 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/AllowedLocation.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + public enum AllowedLocation + { + Any, AttributeOnly, None + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/CollectionSupport.cs b/src/AddIns/BackendBindings/Xaml/Xaml/CollectionSupport.cs new file mode 100644 index 0000000000..2284fd8bd4 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/CollectionSupport.cs @@ -0,0 +1,60 @@ +// +// +// +// +// $Revision: 3509 $ +// + +using System; +using System.Diagnostics; +using System.Collections; +using System.ComponentModel; +using System.Globalization; +using System.Reflection; +using System.Windows; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + /// + /// Static class containing helper methods to work with collections (like the XamlParser does) + /// + public static class CollectionSupport + { + /// + /// Gets if the type is considered a collection in XAML. + /// + public static bool IsCollectionType(Type type) + { + return typeof(IList).IsAssignableFrom(type) + || type.IsArray + || typeof(IAddChild).IsAssignableFrom(type) + || typeof(ResourceDictionary).IsAssignableFrom(type); + } + + /// + /// Gets if the collection type can accepts items of type + /// . + /// + public static bool CanCollectionAdd(Type col, Type item) + { + var e = col.GetInterface("IEnumerable`1"); + if (e != null && e.IsGenericType) { + var a = e.GetGenericArguments()[0]; + return a.IsAssignableFrom(item); + } + return true; + } + + /// + /// Gets if the collection type can accept the specified items. + /// + public static bool CanCollectionAdd(Type col, IEnumerable items) + { + foreach (var item in items) { + if (!CanCollectionAdd(col, item.GetType())) return false; + } + return true; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/Constructor.cs b/src/AddIns/BackendBindings/Xaml/Xaml/Constructor.cs new file mode 100644 index 0000000000..e92cea455b --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/Constructor.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + public class Constructor + { + public XamlType[] Arguments; + public XamlMember[] CorrespondingMembers; + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/DefaultXamlMember.cs b/src/AddIns/BackendBindings/Xaml/Xaml/DefaultXamlMember.cs new file mode 100644 index 0000000000..1df997bcaa --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/DefaultXamlMember.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + public class DefaultXamlMember : XamlMember + { + public override string Name + { + get { throw new NotImplementedException(); } + } + + public override XamlType OwnerType + { + get { throw new NotImplementedException(); } + } + + public override XamlType ValueType + { + get { throw new NotImplementedException(); } + } + + public override bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public override bool IsStatic + { + get { throw new NotImplementedException(); } + } + + public override bool IsAttachable + { + get { throw new NotImplementedException(); } + } + + public override XamlType TargetType + { + get { throw new NotImplementedException(); } + } + + public override AllowedLocation AllowedLocation + { + get { throw new NotImplementedException(); } + } + + public override bool IsEvent + { + get { throw new NotImplementedException(); } + } + + public override bool IsDirective + { + get { throw new NotImplementedException(); } + } + + public override T GetAttribute() + { + throw new NotImplementedException(); + } + + public override bool HasTextSyntax + { + get { throw new NotImplementedException(); } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/DefaultXamlType.cs b/src/AddIns/BackendBindings/Xaml/Xaml/DefaultXamlType.cs new file mode 100644 index 0000000000..86dcdfc1bf --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/DefaultXamlType.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + public class DefaultXamlType : XamlType + { + public override string Name + { + get { throw new NotImplementedException(); } + } + + public override bool IsDefaultConstructible + { + get { throw new NotImplementedException(); } + } + + public override bool IsNullable + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable Members + { + get { throw new NotImplementedException(); } + } + + public override XamlMember ContentProperty + { + get { throw new NotImplementedException(); } + } + + public override XamlMember DictionaryKeyProperty + { + get { throw new NotImplementedException(); } + } + + public override XamlMember NameProperty + { + get { throw new NotImplementedException(); } + } + + public override XamlMember XmlLangProperty + { + get { throw new NotImplementedException(); } + } + + public override bool TrimSurroundingWhitespace + { + get { throw new NotImplementedException(); } + } + + public override bool IsWhitespaceSignificantCollection + { + get { throw new NotImplementedException(); } + } + + public override bool IsCollection + { + get { throw new NotImplementedException(); } + } + + public override bool IsDictionary + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable AllowedTypes + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable AllowedKeyTypes + { + get { throw new NotImplementedException(); } + } + + public override bool IsXData + { + get { throw new NotImplementedException(); } + } + + public override bool IsNameScope + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable Constructors + { + get { throw new NotImplementedException(); } + } + + public override XamlType ReturnValueType + { + get { throw new NotImplementedException(); } + } + + public override string Namespace + { + get { throw new NotImplementedException(); } + } + + public override XamlAssembly Assembly + { + get { throw new NotImplementedException(); } + } + + public override XamlMember Member(string name) + { + throw new NotImplementedException(); + } + + public override IEnumerable ContentWrappers + { + get { throw new NotImplementedException(); } + } + + public override bool HasTextSyntax + { + get { throw new NotImplementedException(); } + } + + public override Type SystemType + { + get { throw new NotImplementedException(); } + } + + public override bool IsAssignableFrom(XamlType type) + { + throw new NotImplementedException(); + } + + public override T GetAttribute() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/Directive.cs b/src/AddIns/BackendBindings/Xaml/Xaml/Directive.cs new file mode 100644 index 0000000000..1bb2585662 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/Directive.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace ICSharpCode.Xaml +{ + public class Directive + { + static Directive() + { + Name = CreateXamlDirective("Name"); + Key = CreateXamlDirective("Key"); + Uid = CreateXamlDirective("Uid"); + Class = CreateXamlDirective("Class"); + ClassModifier = CreateXamlDirective("ClassModifier"); + FieldModifier = CreateXamlDirective("FieldModifier"); + TypeArguments = CreateXamlDirective("TypeArguments"); + XmlLang = CreateDirective(XNamespace.Xml + "lang"); + XmlSpace = CreateDirective(XNamespace.Xml + "space"); + } + + public static XamlMember Name; + public static XamlMember Key; + public static XamlMember Uid; + public static XamlMember Class; + public static XamlMember ClassModifier; + public static XamlMember FieldModifier; + public static XamlMember TypeArguments; + public static XamlMember XmlLang; + public static XamlMember XmlSpace; + + static XamlMember CreateXamlDirective(string name) + { + return CreateDirective(XamlConstants.XamlNamespace + name); + } + + static XamlMember CreateDirective(XName name) + { + var result = new IntristicMember(name.LocalName); + directiveFromName[name] = result; + nameFromDirective[result] = name; + return result; + } + + static Dictionary directiveFromName = new Dictionary(); + static Dictionary nameFromDirective = new Dictionary(); + + public static XamlMember GetDirective(XName name) + { + XamlMember result; + if (directiveFromName.TryGetValue(name, out result)) { + return result; + } + return null; + } + + public static XName GetDirectiveName(XamlMember member) + { + XName result; + if (nameFromDirective.TryGetValue(member, out result)) { + return result; + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/ExtensionMethods.cs b/src/AddIns/BackendBindings/Xaml/Xaml/ExtensionMethods.cs new file mode 100644 index 0000000000..15d9d94912 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/ExtensionMethods.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + public static class ExtensionMethods + { + public static V FindOrCreate(this Dictionary dict, K key) where V : new() + { + V value; + if (!dict.TryGetValue(key, out value)) { + value = new V(); + dict[key] = value; + } + return value; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/IHasAnnotations.cs b/src/AddIns/BackendBindings/Xaml/Xaml/IHasAnnotations.cs new file mode 100644 index 0000000000..3c1b4dc7c0 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/IHasAnnotations.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + public interface IHasAnnotations + { + void AnnotateWith(T annotation) where T : class; + T GetAnnotation() where T : class; + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/InstanceTracker.cs b/src/AddIns/BackendBindings/Xaml/Xaml/InstanceTracker.cs new file mode 100644 index 0000000000..e962c1738d --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/InstanceTracker.cs @@ -0,0 +1,238 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel; +using System.Windows.Markup; +using System.Windows; + +namespace ICSharpCode.Xaml +{ + class InstanceTracker : Tracker + { + public override void Add(MemberNode memberNode) + { + foreach (var valueNode in memberNode.Values) { + Add(valueNode); + } + } + + public override void Add(ObjectNode objectNode) + { + if (objectNode.Instance == null) { + Instantiate(objectNode); + } + var parentMember = objectNode.ParentMember; + if (parentMember != null) { + if (parentMember.Member == IntristicMember.Items) { + var collectionObjectNode = parentMember.ParentObject; + if (collectionObjectNode.Type.IsDictionary) { + //var keyValue = objectNode.Key.Value; + //if (keyValue != null) { + // Runtime.Add(collectionObjectNode.Instance, + // keyValue.Instance, objectNode.Instance); + //} + } + else { + Runtime.Add(collectionObjectNode.Instance, objectNode.Instance); + } + } + else { + if (!objectNode.IsRetrieved) { + object valueInstance; + if (objectNode.Type.IsMarkupExtension) { + valueInstance = ProvideValue(objectNode); + } + else { + valueInstance = objectNode.Instance; + } + Runtime.SetValue(parentMember, valueInstance); + } + } + } + } + + public override void Add(TextNode textNode) + { + var parentMember = textNode.ParentMember; + if (parentMember != null) { + textNode.Instance = Runtime.ConvertFromText( + parentMember.Property.XamlContext, + textNode.Text); + + if (parentMember.Member == IntristicMember.Items) { + // IAddChild support. + // Instance could differ without it (e.g. TextBlock.Inlines vs TextBlock.Text) + var grandParentMember = parentMember.ParentObject.ParentMember; + if (grandParentMember != null) { + var addChild = grandParentMember.ParentObject.Instance as IAddChild; + if (addChild != null) { + addChild.AddText(textNode.Text); + return; + } + } + + Runtime.Add(parentMember.ParentObject.Instance, textNode.Instance); + } + else { + Runtime.SetValue(parentMember, textNode.Instance); + if (parentMember.Member == Directive.Key) { + Runtime.Add(parentMember.ParentObject.ParentObject.Instance, + textNode.Instance, parentMember.ParentObject.Instance); + } + } + } + } + + public override void Remove(MemberNode node, ObjectNode parent) + { + Runtime.ResetValue(parent.Instance, node.Member); + } + + public override void Remove(ObjectNode node, MemberNode parent) + { + if (parent != null && parent.Member == IntristicMember.Items) { + Runtime.Remove(parent.ParentObject.Instance, node.Instance); + } + } + + void Instantiate(ObjectNode objectNode) + { + var parentMember = objectNode.ParentMember; + ISupportInitialize supportInitialize = null; + + if (objectNode.IsRetrieved) { + objectNode.Instance = Runtime.GetValue(parentMember); + } + else { + if (objectNode.InitializationText.IsSet) { + objectNode.Instance = Runtime.ConvertFromText( + objectNode.InitializationText.XamlContext, + objectNode.InitializationText.ValueText); + } + else { + var ctorNode = objectNode.FindMemberNode(IntristicMember.ConsructorArgs); + if (ctorNode != null) { + objectNode.Instance = Construct(ctorNode); + } + else { + objectNode.Instance = Runtime.CreateInstance(objectNode.Type, null); + } + } + + supportInitialize = objectNode.Instance as ISupportInitialize; + if (supportInitialize != null) { + supportInitialize.BeginInit(); + } + } + + foreach (var memberNode in objectNode.MemberNodes) { + if (memberNode.Member == IntristicMember.ConsructorArgs) continue; + Add(memberNode); + } + + if (supportInitialize != null) { + supportInitialize.EndInit(); + } + } + + object Construct(MemberNode ctorNode) + { + var objectNode = ctorNode.ParentObject; + var args = new List(); + var ctor = objectNode.Type.Constructors.First( + c => c.Arguments.Count() == ctorNode.Values.Count); + + for (int i = 0; i < ctorNode.Values.Count; i++) { + var ctorArgValue = ctorNode.Values[i]; + Add(ctorArgValue); + + var value = ctorArgValue.Instance; + var targetType = ctor.Arguments[i]; + if (!targetType.SystemType.IsAssignableFrom(value.GetType())) { + var text = value as string; + if (text != null) { + value = Runtime.ConvertFromText(ctorNode.Property.XamlContext, targetType, text); + } + else { + throw new XamlException("Cannot convert"); + } + } + args.Add(value); + } + return Runtime.CreateInstance(objectNode.Type, args.ToArray()); + } + + object ProvideValue(ObjectNode node) + { + var me = node.Instance as MarkupExtension; + + Instantiate(node); + + if (me is StaticResourceExtension) { + return FindResource(node, (me as StaticResourceExtension).ResourceKey); + } + else if (me is DynamicResourceExtension) { + return FindResource(node, (me as DynamicResourceExtension).ResourceKey); + } + + return me.ProvideValue(node.ParentMember.Property.XamlContext); + } + + object FindResource(ObjectNode node, object key) + { + if (key == null) return null; + + var current = node; + while (current != null) { + var result = GetResource(current.Instance, key); + if (result != Runtime.UnsetValue) { + return result; + } + current = current.ParentObject; + } + + var appDefinition = node.Document.Project.ApplicationDefinition; + if (appDefinition != null) { + var app = appDefinition.Root.Instance as Application; + if (app != null) { + var result = GetResource(app, key); + if (result != Runtime.UnsetValue) { + return result; + } + } + } + //if (key is ComponentResourceKey) + //{ + // fore + //} + return null; + } + + public static object GetResource(object container, object key) + { + var resources = GetResources(container); + if (resources != null && resources.Contains(key)) { + return resources[key]; + } + return Runtime.UnsetValue; + } + + public static ResourceDictionary GetResources(object container) + { + if (container is FrameworkElement) { + return (container as FrameworkElement).Resources; + } + if (container is FrameworkTemplate) { + return (container as FrameworkTemplate).Resources; + } + if (container is Style) { + return (container as Style).Resources; + } + if (container is Application) { + return (container as Application).Resources; + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/IntristicMember.cs b/src/AddIns/BackendBindings/Xaml/Xaml/IntristicMember.cs new file mode 100644 index 0000000000..e9b202c2d0 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/IntristicMember.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace ICSharpCode.Xaml +{ + public class IntristicMember : XamlMember + { + public IntristicMember(string name) + { + this.name = name; + } + + public static XamlMember Items = new IntristicMember("Items"); + public static XamlMember ConsructorArgs = new IntristicMember("ConsructorArgs"); + public static XamlMember InitializationText = new IntristicMember("InitializationText"); + public static XamlMember DirectiveChildren = new IntristicMember("DirectiveChildren"); + + string name; + + public override string Name + { + get { return name; } + } + + public override XamlType OwnerType + { + get { return null; } + } + + public override XamlType ValueType + { + get { return ReflectionMapper.GetXamlType(typeof(object)); } + } + + public override XamlType TargetType + { + get { throw new NotImplementedException(); } + } + + public override AllowedLocation AllowedLocation + { + get { throw new NotImplementedException(); } + } + + public override bool IsEvent + { + get { throw new NotImplementedException(); } + } + + public override bool IsDirective + { + get { return true; } + } + + public override bool IsReadOnly + { + get { return false; } + } + + public override bool IsStatic + { + get { throw new NotImplementedException(); } + } + + public override bool IsAttachable + { + get { return false; } + } + + public override T GetAttribute() + { + throw new NotImplementedException(); + } + + public override bool HasTextSyntax + { + get { throw new NotImplementedException(); } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/IntristicType.cs b/src/AddIns/BackendBindings/Xaml/Xaml/IntristicType.cs new file mode 100644 index 0000000000..f1b280aa5f --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/IntristicType.cs @@ -0,0 +1,151 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + public class IntristicType : XamlType + { + public static XName CodeName = XamlConstants.XamlNamespace + "Code"; + public static XName XDataName = XamlConstants.XamlNamespace + "XData"; + + public static XamlType Code = new IntristicType(); + public static XamlType XData = new IntristicType(); + + public static XamlType String = ReflectionMapper.GetXamlType(typeof(string)); + public static XamlType MarkupExtension = ReflectionMapper.GetXamlType(typeof(MarkupExtension)); + + public override string Name + { + get { throw new NotImplementedException(); } + } + + public override bool IsDefaultConstructible + { + get { throw new NotImplementedException(); } + } + + public override bool IsNullable + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable Members + { + get { throw new NotImplementedException(); } + } + + public override XamlMember ContentProperty + { + get { throw new NotImplementedException(); } + } + + public override XamlMember DictionaryKeyProperty + { + get { throw new NotImplementedException(); } + } + + public override XamlMember NameProperty + { + get { throw new NotImplementedException(); } + } + + public override XamlMember XmlLangProperty + { + get { throw new NotImplementedException(); } + } + + public override bool TrimSurroundingWhitespace + { + get { throw new NotImplementedException(); } + } + + public override bool IsWhitespaceSignificantCollection + { + get { throw new NotImplementedException(); } + } + + public override bool IsCollection + { + get { throw new NotImplementedException(); } + } + + public override bool IsDictionary + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable AllowedTypes + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable AllowedKeyTypes + { + get { throw new NotImplementedException(); } + } + + public override bool IsXData + { + get { throw new NotImplementedException(); } + } + + public override bool IsNameScope + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable Constructors + { + get { throw new NotImplementedException(); } + } + + public override XamlType ReturnValueType + { + get { throw new NotImplementedException(); } + } + + public override string Namespace + { + get { throw new NotImplementedException(); } + } + + public override XamlAssembly Assembly + { + get { throw new NotImplementedException(); } + } + + public override XamlMember Member(string name) + { + throw new NotImplementedException(); + } + + public override bool IsAssignableFrom(XamlType type) + { + throw new NotImplementedException(); + } + + public override IEnumerable ContentWrappers + { + get { throw new NotImplementedException(); } + } + + public override bool HasTextSyntax + { + get { throw new NotImplementedException(); } + } + + public override Type SystemType + { + get { return null; } + } + + public override T GetAttribute() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/MarkupExtensionParser.cs b/src/AddIns/BackendBindings/Xaml/Xaml/MarkupExtensionParser.cs new file mode 100644 index 0000000000..340e380774 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/MarkupExtensionParser.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + class MarkupExtensionParser + { + public static MarkupExtensionAst Parse(string text) + { + var tokens = MarkupExtensionTokenizer.Tokenize(text); + + if (tokens.Count < 3 || + tokens[0].Kind != MarkupExtensionTokenKind.OpenBrace || + tokens[1].Kind != MarkupExtensionTokenKind.TypeName || + tokens[tokens.Count - 1].Kind != MarkupExtensionTokenKind.CloseBrace) { + throw new XamlException("Invalid markup extension"); + } + + var result = new MarkupExtensionAst(); + result.TypeName = tokens[1].Value; + + for (int i = 2; i < tokens.Count - 1; i++) { + if (tokens[i].Kind == MarkupExtensionTokenKind.String) { + result.PositionalArgs.Add(tokens[i].Value); + } + else if (tokens[i].Kind == MarkupExtensionTokenKind.Membername) { + if (tokens[i + 1].Kind != MarkupExtensionTokenKind.Equals || + tokens[i + 2].Kind != MarkupExtensionTokenKind.String) { + throw new XamlException("Invalid markup extension"); + } + var namedArg = new KeyValuePair(tokens[i].Value, tokens[i + 2].Value); + result.NamedArgs.Add(namedArg); + i += 2; + } + } + return result; + } + } + + class MarkupExtensionAst + { + public string TypeName; + public List PositionalArgs = new List(); + public List> NamedArgs = new List>(); + } + + class MarkupExtensionTokenizer + { + private MarkupExtensionTokenizer() { } + + string text; + int pos; + List tokens = new List(); + + public static List Tokenize(string text) + { + MarkupExtensionTokenizer t = new MarkupExtensionTokenizer(); + t.text = text; + t.Parse(); + return t.tokens; + } + + void AddToken(MarkupExtensionTokenKind kind, string val) + { + tokens.Add(new MarkupExtensionToken(kind, val)); + } + + void Parse() + { + AddToken(MarkupExtensionTokenKind.OpenBrace, "{"); + Expect('{'); + ConsumeWhitespace(); + CheckNotEOF(); + + StringBuilder b = new StringBuilder(); + while (pos < text.Length && !char.IsWhiteSpace(text, pos) && text[pos] != '}') + b.Append(text[pos++]); + AddToken(MarkupExtensionTokenKind.TypeName, b.ToString()); + + ConsumeWhitespace(); + while (pos < text.Length) { + switch (text[pos]) { + case '}': + AddToken(MarkupExtensionTokenKind.CloseBrace, "}"); + pos++; + break; + case '=': + AddToken(MarkupExtensionTokenKind.Equals, "="); + pos++; + break; + case ',': + AddToken(MarkupExtensionTokenKind.Comma, ","); + pos++; + break; + default: + MembernameOrString(); + break; + } + ConsumeWhitespace(); + } + } + + void MembernameOrString() + { + StringBuilder b = new StringBuilder(); + if (text[pos] == '"' || text[pos] == '\'') { + char quote = text[pos++]; + CheckNotEOF(); + while (!(text[pos] == quote && text[pos - 1] != '\\')) { + char c = text[pos++]; + if (c != '\\') + b.Append(c); + CheckNotEOF(); + } + pos++; // consume closing quote + ConsumeWhitespace(); + } + else { + int braceTotal = 0; + while (true) { + CheckNotEOF(); + switch (text[pos]) { + case '\\': + pos++; + CheckNotEOF(); + b.Append(text[pos++]); + break; + case '{': + b.Append(text[pos++]); + braceTotal++; + break; + case '}': + if (braceTotal == 0) goto stop; + b.Append(text[pos++]); + braceTotal--; + break; + case ',': + case '=': + if (braceTotal == 0) goto stop; + b.Append(text[pos++]); + break; + default: + b.Append(text[pos++]); + break; + } + } + stop: ; + } + CheckNotEOF(); + string valueText = b.ToString(); + if (text[pos] == '=') { + AddToken(MarkupExtensionTokenKind.Membername, valueText.Trim()); + } + else { + AddToken(MarkupExtensionTokenKind.String, valueText); + } + } + + void Expect(char c) + { + CheckNotEOF(); + if (text[pos] != c) + throw new XamlException("Expected '" + c + "'"); + pos++; + } + + void ConsumeWhitespace() + { + while (pos < text.Length && char.IsWhiteSpace(text, pos)) + pos++; + } + + void CheckNotEOF() + { + if (pos >= text.Length) + throw new XamlException("Unexpected end of markup extension"); + } + } + + class MarkupExtensionToken + { + public MarkupExtensionToken(MarkupExtensionTokenKind kind, string value) + { + this.Kind = kind; + this.Value = value; + } + + public readonly MarkupExtensionTokenKind Kind; + public readonly string Value; + + public override string ToString() + { + return "[" + Kind + " " + Value + "]"; + } + } + + enum MarkupExtensionTokenKind + { + OpenBrace, + CloseBrace, + Equals, + Comma, + TypeName, + Membername, + String + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/MarkupExtensionPrinter.cs b/src/AddIns/BackendBindings/Xaml/Xaml/MarkupExtensionPrinter.cs new file mode 100644 index 0000000000..b326216614 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/MarkupExtensionPrinter.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.WpfDesign.Xaml +{ + public static class MarkupExtensionPrinter + { + public static bool CanPrint(XamlObject obj) + { + return true; + } + + public static string Print(XamlObject obj) + { + StringBuilder sb = new StringBuilder(); + sb.Append("{"); + sb.Append(obj.GetNameForMarkupExtension()); + + bool first = true; + foreach (var property in obj.Properties) { + if (!property.IsSet) continue; + + if (first) + sb.Append(" "); + else + sb.Append(", "); + first = false; + + sb.Append(property.GetNameForMarkupExtension()); + sb.Append("="); + + var value = property.PropertyValue; + if (value is XamlTextValue) { + sb.Append((value as XamlTextValue).Text); + } else if (value is XamlObject) { + sb.Append(Print(value as XamlObject)); + } + } + sb.Append("}"); + return sb.ToString(); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/MemberNode.cs b/src/AddIns/BackendBindings/Xaml/Xaml/MemberNode.cs new file mode 100644 index 0000000000..7c8abb3c1e --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/MemberNode.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; + +namespace ICSharpCode.Xaml +{ + public class MemberNode : XamlNode + { + internal MemberNode() + { + Values = new NodeCollection(this); + } + + public XamlMember Member; + public NodeCollection Values; + + public ObjectNode ParentObject + { + get { return ParentNode as ObjectNode; } + } + + public XamlProperty Property + { + get + { + if (ParentObject != null) { + return ParentObject.Property(Member); + } + return null; + } + } + + public XamlValue SingleValue + { + get + { + if (Values.Count == 1) { + return Values[0]; + } + return null; + } + set + { + if (Values.Count == 1) { + Values[0] = value; + } + else { + Values.Clear(); + Values.Add(value); + } + } + } + + public override string ToString() + { + return GetType().Name + ": " + Member.Name; + } + + public override IEnumerable Nodes() + { + return Values.Cast(); + } + + protected override void RemoveChild(XamlNode node) + { + Values.Remove(node as XamlValue); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/NodeCollection.cs b/src/AddIns/BackendBindings/Xaml/Xaml/NodeCollection.cs new file mode 100644 index 0000000000..04fd9c7fe0 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/NodeCollection.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections.ObjectModel; + +namespace ICSharpCode.Xaml +{ + public class NodeCollection : Collection where T : XamlNode + { + public NodeCollection(XamlNode parent) + { + this.parent = parent; + } + + XamlNode parent; + + protected override void InsertItem(int index, T item) + { + base.InsertItem(index, item); + item.ParentNode = parent; + if (item.Document != null) { + var e = new DocumentChangedEventArgs() { NewNode = item }; + item.Document.RaiseDocumentChanged(e); + } + } + + protected override void RemoveItem(int index) + { + var item = this[index]; + base.RemoveItem(index); + if (item.Document != null) { + var e = new DocumentChangedEventArgs() { OldNode = item, OldParent = item.ParentNode }; + item.ParentNode = null; + item.Document.RaiseDocumentChanged(e); + } + else { + item.ParentNode = null; + } + } + + protected override void SetItem(int index, T item) + { + var oldItem = this[index]; + base.SetItem(index, item); + if (item.Document != null) { + var e = new DocumentChangedEventArgs() { + OldNode = oldItem, + OldParent = oldItem.ParentNode, + NewNode = item + }; + oldItem.ParentNode = null; + item.ParentNode = parent; + item.Document.RaiseDocumentChanged(e); + } + else { + oldItem.ParentNode = null; + } + } + + protected override void ClearItems() + { + while (Count > 0) { + RemoveItem(Count - 1); + } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/ObjectNode.cs b/src/AddIns/BackendBindings/Xaml/Xaml/ObjectNode.cs new file mode 100644 index 0000000000..aeb93bbf37 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/ObjectNode.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using System.Collections.ObjectModel; +using System.Windows; + +namespace ICSharpCode.Xaml +{ + public class ObjectNode : XamlValue + { + internal ObjectNode() + { + MemberNodes = new NodeCollection(this); + } + + internal ObjectNode(XamlDocument doc, object instance) + : this() + { + Document = doc; + Instance = instance; + Type = ReflectionMapper.GetXamlType(instance.GetType()); + } + + public XamlType Type; + public bool IsRetrieved; + public NodeCollection MemberNodes; + Dictionary properties = new Dictionary(); + + public bool IsDocumentRoot + { + get { return Document.Root == this; } + } + + public XamlProperty Content + { + get + { + if (Type.ContentProperty != null) { + return Property(Type.ContentProperty); + } + if (Type.IsCollection) { + return Property(IntristicMember.Items); + } + return null; + } + } + + public XamlProperty InitializationText + { + get { return Property(IntristicMember.InitializationText); } + } + + public string Name + { + get + { + var nameProperty = Property(Type.NameProperty); + if (nameProperty != null && nameProperty.IsSet) { + return nameProperty.ValueText; + } + var xNameProperty = Property(Directive.Name); + return xNameProperty.ValueText; + } + set + { + var nameProperty = Property(Type.NameProperty); + var xNameProperty = Property(Directive.Name); + + if (nameProperty != null) { + nameProperty.Reset(); + } + + xNameProperty.Set(value); + } + } + + public XamlProperty Key + { + get { return Property(Directive.Key); } + } + + public override string ToString() + { + return GetType().Name + ": " + Type.Name; + } + + public override IEnumerable Nodes() + { + return MemberNodes.Cast(); + } + + protected override void RemoveChild(XamlNode node) + { + MemberNodes.Remove(node as MemberNode); + } + + public MemberNode FindMemberNode(XamlMember member) + { + foreach (var memberNode in MemberNodes) { + if (memberNode.Member == member) { + return memberNode; + } + } + return null; + } + + public MemberNode EnsureMemberNode(XamlMember member) + { + var memberNode = FindMemberNode(member); + if (memberNode == null) { + memberNode = new MemberNode() { Document = Document, Member = member }; + MemberNodes.Add(memberNode); + + if (member.IsReadOnly) { + var collection = new ObjectNode() { + Document = Document, + Type = member.ValueType, + IsRetrieved = true + }; + memberNode.SingleValue = collection; + } + } + return memberNode; + } + + public XamlProperty Property(string name) + { + return Property(Type.Member(name)); + } + + public XamlProperty Property(DependencyProperty dp) + { + return Property(dp.Name) ?? Property(dp.OwnerType, dp.Name); + } + + public XamlProperty Property(Type type, string name) + { + return Property(ReflectionMapper.GetXamlType(type).Member(name)); + } + + public XamlProperty Property(XamlMember member) + { + if (member == null) return null; + XamlProperty property; + if (!properties.TryGetValue(member, out property)) { + property = new XamlProperty(this, member); + properties[member] = property; + } + return property; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionAssembly.cs b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionAssembly.cs new file mode 100644 index 0000000000..abac72ba01 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionAssembly.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + public class ReflectionAssembly : XamlAssembly + { + internal ReflectionAssembly(Assembly assembly) + { + Assembly = assembly; + } + + public Assembly Assembly; + + public override string Name + { + get { return Assembly.GetName().Name; } + } + + public override IEnumerable XmlnsDefinitions + { + get { return Assembly.GetCustomAttributes(typeof(XmlnsDefinitionAttribute), false) as XmlnsDefinitionAttribute[]; } + } + + public override XamlType GetType(string fullName) + { + var type = Assembly.GetType(fullName); + if (type != null) { + return ReflectionMapper.GetXamlType(type); + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMapper.cs b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMapper.cs new file mode 100644 index 0000000000..006fdd163f --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMapper.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; + +namespace ICSharpCode.Xaml +{ + public static class ReflectionMapper + { + static Dictionary assemblies = new Dictionary(); + static Dictionary types = new Dictionary(); + static Dictionary members = new Dictionary(); + + public static XamlAssembly GetXamlAssembly(Assembly key) + { + XamlAssembly result; + if (!assemblies.TryGetValue(key, out result)) { + result = new ReflectionAssembly(key); + assemblies[key] = result; + } + return result; + } + + public static XamlType GetXamlType(Type key) + { + XamlType result; + if (!types.TryGetValue(key, out result)) { + result = new ReflectionType(key); + types[key] = result; + } + return result; + } + + public static XamlMember GetXamlMember(ReflectionMemberInfo key) + { + XamlMember result; + if (!members.TryGetValue(key, out result)) { + result = new ReflectionMember(key); + members[key] = result; + } + return result; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMember.cs b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMember.cs new file mode 100644 index 0000000000..34267cc253 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMember.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System.Diagnostics; + +namespace ICSharpCode.Xaml +{ + public class ReflectionMember : XamlMember + { + internal ReflectionMember(ReflectionMemberInfo info) + { + this.info = info; + } + + ReflectionMemberInfo info; + + public ReflectionMemberInfo Info + { + get { return info; } + } + + public override string Name + { + get { return info.Name; } + } + + public override XamlType OwnerType + { + get { return ReflectionMapper.GetXamlType(info.OwnerType); } + } + + public override XamlType ValueType + { + get + { + return ReflectionMapper.GetXamlType(info.ValueType); + } + } + + public override XamlType TargetType + { + get { throw new NotImplementedException(); } + } + + public override AllowedLocation AllowedLocation + { + get { return AllowedLocation.Any; } + } + + public override bool IsEvent + { + get { return Info is ReflectionEventInfo; } + } + + public override bool IsDirective + { + get { return false; } + } + + public override bool IsReadOnly + { + get { return Info.IsReadOnly; } + } + + public override bool IsStatic + { + get { throw new NotImplementedException(); } + } + + public override bool IsAttachable + { + get { return Info is ReflectionAttachedPropertyInfo || Info is DependencyPropertyInfo; } + } + + public override T GetAttribute() + { + return null; + } + + public override bool HasTextSyntax + { + get { return Runtime.GetValueSerializer(this) != null; } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMemberInfo.cs b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMemberInfo.cs new file mode 100644 index 0000000000..532dbd0462 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionMemberInfo.cs @@ -0,0 +1,284 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System.ComponentModel; +using System.Windows; + +namespace ICSharpCode.Xaml +{ + public abstract class ReflectionMemberInfo + { + public abstract string Name { get; } + public abstract Type ValueType { get; } + public abstract Type OwnerType { get; } + public abstract object GetValue(object instance); + public abstract void SetValue(object instance, object value); + public abstract void ResetValue(object instance); + public abstract bool IsReadOnly { get; } + public abstract PropertyDescriptor PropertyDescriptor { get; } + protected abstract object EqualiltyCore { get; } + + public DependencyProperty DependencyProperty + { + get + { + var dpd = DependencyPropertyDescriptor.FromProperty(PropertyDescriptor); + if (dpd != null) { + return dpd.DependencyProperty; + } + return null; + } + } + + public override bool Equals(object obj) + { + var other = obj as ReflectionMemberInfo; + if (other != null) { + return EqualiltyCore == other.EqualiltyCore; + } + return false; + } + + public override int GetHashCode() + { + return EqualiltyCore.GetHashCode(); + } + } + + class ReflectionPropertyInfo : ReflectionMemberInfo + { + public ReflectionPropertyInfo(PropertyDescriptor pd) + { + this.pd = pd; + } + + PropertyDescriptor pd; + + public override string Name + { + get { return pd.Name; } + } + + public override Type ValueType + { + get { return pd.PropertyType; } + } + + public override Type OwnerType + { + get { return pd.ComponentType; } + } + + public override object GetValue(object instance) + { + return pd.GetValue(instance); + } + + public override void SetValue(object instance, object value) + { + pd.SetValue(instance, value); + } + + public override void ResetValue(object instance) + { + if (pd.CanResetValue(instance)) { + pd.ResetValue(instance); + } + else { + pd.SetValue(instance, null); + } + } + + protected override object EqualiltyCore + { + get { return pd; } + } + + public override bool IsReadOnly + { + get { return pd.IsReadOnly; } + } + + public override PropertyDescriptor PropertyDescriptor + { + get { return pd; } + } + } + + class ReflectionAttachedPropertyInfo : ReflectionMemberInfo + { + public ReflectionAttachedPropertyInfo(MethodInfo getter, MethodInfo setter) + { + this.getter = getter; + this.setter = setter; + } + + MethodInfo getter; + MethodInfo setter; + + public override string Name + { + get { return setter.Name.Substring(3); } + } + + public override Type ValueType + { + get { return setter.GetParameters()[1].ParameterType; } + } + + public override Type OwnerType + { + get { return setter.DeclaringType; } + } + + public override object GetValue(object instance) + { + if (getter != null) { + return getter.Invoke(instance, null); + } + throw new NotImplementedException(); + } + + public override void SetValue(object instance, object value) + { + setter.Invoke(instance, new[] { instance, value }); + } + + public override void ResetValue(object instance) + { + throw new NotImplementedException(); + } + + protected override object EqualiltyCore + { + get { return setter; } + } + + public override bool IsReadOnly + { + get { return false; } + } + + public override PropertyDescriptor PropertyDescriptor + { + get { return null; } + } + } + + class DependencyPropertyInfo : ReflectionMemberInfo + { + public DependencyPropertyInfo(DependencyProperty dp) + { + this.dp = dp; + if (typeof(DependencyObject).IsAssignableFrom(dp.OwnerType)) { + this.dpd = DependencyPropertyDescriptor.FromProperty(dp, dp.OwnerType); + } + } + + DependencyProperty dp; + DependencyPropertyDescriptor dpd; + + public override string Name + { + get { return dp.Name; } + } + + public override Type ValueType + { + get { return dp.PropertyType; } + } + + public override Type OwnerType + { + get { return dp.OwnerType; } + } + + public override object GetValue(object instance) + { + var d = instance as DependencyObject; + return d.GetValue(dp); + } + + public override void SetValue(object instance, object value) + { + var d = instance as DependencyObject; + d.SetValue(dp, value); + } + + public override void ResetValue(object instance) + { + var d = instance as DependencyObject; + d.ClearValue(dp); + } + + protected override object EqualiltyCore + { + get { return dp; } + } + + public override bool IsReadOnly + { + get { return dp.ReadOnly; } + } + + public override PropertyDescriptor PropertyDescriptor + { + get { return dpd; } + } + } + + class ReflectionEventInfo : ReflectionMemberInfo + { + public ReflectionEventInfo(EventInfo eventInfo) + { + this.eventInfo = eventInfo; + } + + EventInfo eventInfo; + + public override string Name + { + get { return eventInfo.Name; } + } + + public override Type ValueType + { + get { return eventInfo.EventHandlerType; } + } + + public override Type OwnerType + { + get { return eventInfo.DeclaringType; } + } + + public override object GetValue(object instance) + { + return null; + } + + public override void SetValue(object instance, object value) + { + } + + public override void ResetValue(object instance) + { + } + + protected override object EqualiltyCore + { + get { return eventInfo; } + } + + public override bool IsReadOnly + { + get { return false; } + } + + public override PropertyDescriptor PropertyDescriptor + { + get { return null; } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionType.cs b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionType.cs new file mode 100644 index 0000000000..3e76c7bdf4 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/ReflectionType.cs @@ -0,0 +1,265 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Markup; +using System.Reflection; +using System.Collections; +using System.ComponentModel; +using System.Windows; + +namespace ICSharpCode.Xaml +{ + public class ReflectionType : XamlType + { + internal ReflectionType(Type type) + { + this.type = type; + this.propertyDescriptors = TypeDescriptor.GetProperties(type); + } + + Type type; + PropertyDescriptorCollection propertyDescriptors; + + public Type Type + { + get { return type; } + } + + public override string Name + { + get { return type.Name; } + } + + public override bool IsDefaultConstructible + { + get { return type.GetConstructor(Type.EmptyTypes) != null; } + } + + public override bool IsNullable + { + get { return !type.IsValueType; } + } + + public override IEnumerable Members + { + get { throw new NotImplementedException(); } + } + + public override XamlMember ContentProperty + { + get + { + foreach (ContentPropertyAttribute a in type.GetCustomAttributes(typeof(ContentPropertyAttribute), true)) { + return Member(a.Name); + } + return null; + } + } + + public override XamlMember DictionaryKeyProperty + { + get { throw new NotImplementedException(); } + } + + public override XamlMember NameProperty + { + get + { + foreach (RuntimeNamePropertyAttribute a in type.GetCustomAttributes(typeof(RuntimeNamePropertyAttribute), true)) { + return Member(a.Name); + } + return null; + } + } + + public override XamlMember XmlLangProperty + { + get { throw new NotImplementedException(); } + } + + public override bool TrimSurroundingWhitespace + { + get + { + foreach (var a in type.GetCustomAttributes(typeof(TrimSurroundingWhitespaceAttribute), true)) { + return true; + } + return false; + } + } + + public override bool IsWhitespaceSignificantCollection + { + get + { + foreach (var a in type.GetCustomAttributes(typeof(WhitespaceSignificantCollectionAttribute), true)) { + return true; + } + return false; + } + } + + public override bool IsCollection + { + get { return typeof(ICollection).IsAssignableFrom(type); } + } + + public override bool IsDictionary + { + get { return typeof(IDictionary).IsAssignableFrom(type); } + } + + public override IEnumerable AllowedTypes + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable AllowedKeyTypes + { + get { throw new NotImplementedException(); } + } + + public override bool IsXData + { + get { throw new NotImplementedException(); } + } + + public override bool IsNameScope + { + get { throw new NotImplementedException(); } + } + + public override IEnumerable Constructors + { + get + { + Dictionary ctors = new Dictionary(); + foreach (var ctorInfo in type.GetConstructors()) { + var parameters = ctorInfo.GetParameters(); + if (parameters.Length > 0 && !ctors.ContainsKey(parameters.Length)) { + var ctor = new Constructor(); + ctor.Arguments = parameters + .Select(p => ReflectionMapper.GetXamlType(p.ParameterType)).ToArray(); + + List members = new List(); + foreach (var p in parameters) { + var member = MemberCaseInsensetive(p.Name); + if (member == null) { + members = null; + break; + } + members.Add(member); + } + if (members != null) { + ctor.CorrespondingMembers = members.ToArray(); + } + + ctors[parameters.Length] = ctor; + } + } + return ctors.Values; + } + } + + public override XamlType ReturnValueType + { + get { throw new NotImplementedException(); } + } + + public override string Namespace + { + get { return type.Namespace; } + } + + public override XamlAssembly Assembly + { + get { return ReflectionMapper.GetXamlAssembly(type.Assembly); } + } + + public override XamlMember Member(string name) + { + ReflectionMemberInfo info = null; + + var pd = propertyDescriptors[name]; + if (pd != null) { + info = new ReflectionPropertyInfo(pd); + } + else { + var eventInfo = type.GetEvent(name, BindingFlags.Public | BindingFlags.Instance); + if (eventInfo != null) { + info = new ReflectionEventInfo(eventInfo); + } + else { + // attached dp better than getter/setter cause we have DependencyObject.ClearValue(dp) + var field = type.GetField(name + "Property", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + if (field != null) { + var dp = (DependencyProperty)field.GetValue(null); + if (dp != null) { + info = new DependencyPropertyInfo(dp); + } + } + if (info == null) { + var getter = type.GetMethod("Get" + name, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + var setter = type.GetMethod("Set" + name, BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy); + if (setter != null) { + info = new ReflectionAttachedPropertyInfo(getter, setter); + } + } + } + } + if (info != null) { + return ReflectionMapper.GetXamlMember(info); + } + return null; + } + + XamlMember MemberCaseInsensetive(string name) + { + foreach (PropertyDescriptor pd in propertyDescriptors) { + if (pd.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)) { + return ReflectionMapper.GetXamlMember(new ReflectionPropertyInfo(pd)); + } + } + return null; + } + + public override IEnumerable ContentWrappers + { + get + { + foreach (ContentWrapperAttribute a in type.GetCustomAttributes(typeof(ContentWrapperAttribute), true)) { + yield return ReflectionMapper.GetXamlType(a.ContentWrapper); + } + } + } + + public override bool IsAssignableFrom(XamlType other) + { + var r = other as ReflectionType; + if (r != null) { + return type.IsAssignableFrom(r.Type); + } + return false; + } + + public override bool HasTextSyntax + { + get { return Runtime.GetValueSerializer(this) != null; } + } + + public override Type SystemType + { + get { return type; } + } + + public override T GetAttribute() + { + var usageAttribute = (AttributeUsageAttribute)typeof(T).GetCustomAttributes(typeof(AttributeUsageAttribute), true)[0]; + foreach (T attr in type.GetCustomAttributes(typeof(T), usageAttribute.Inherited)) { + return attr; + } + return null; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/Runtime.cs b/src/AddIns/BackendBindings/Xaml/Xaml/Runtime.cs new file mode 100644 index 0000000000..62e6e55854 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/Runtime.cs @@ -0,0 +1,236 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; +using System.ComponentModel; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + public static class Runtime + { + public static object UnsetValue = new object(); + + static Dictionary typeReplacers = new Dictionary(); + + public static void AddTypeReplacer(Type type, Type replacer) + { + lock (typeReplacers) { + typeReplacers[type] = replacer; + } + } + + public static Type GetTypeReplacer(Type type) + { + Type replacer; + lock (typeReplacers) { + typeReplacers.TryGetValue(type, out replacer); + return replacer; + } + } + + public static object CreateInstance(XamlType type, object[] args) + { + if (type.SystemType != null) { + var finalType = GetTypeReplacer(type.SystemType) ?? type.SystemType; + return Activator.CreateInstance(finalType, args); + } + return null; + } + + public static object GetValue(MemberNode memberNode) + { + return GetValue(memberNode.ParentObject.Instance, memberNode.Member); + } + + public static void SetValue(MemberNode memberNode, object value) + { + SetValue(memberNode.ParentObject.Instance, memberNode.Member, value); + } + + public static void ResetValue(MemberNode memberNode) + { + ResetValue(memberNode.ParentObject.Instance, memberNode.Member); + } + + public static object GetValue(object instance, XamlMember member) + { + var info = GetFinalMemberInfo(instance, member); + if (info != null) { + return info.GetValue(instance); + } + return Runtime.UnsetValue; + } + + public static void SetValue(object instance, XamlMember member, object value) + { + var info = GetFinalMemberInfo(instance, member); + if (info != null) { + info.SetValue(instance, value); + } + } + + public static void ResetValue(object instance, XamlMember member) + { + var info = GetFinalMemberInfo(instance, member); + if (info != null) { + info.ResetValue(instance); + } + } + + static ReflectionMemberInfo GetFinalMemberInfo(object instance, XamlMember member) + { + var result = member as ReflectionMember; + if (result != null) { + if (!result.IsAttachable) { + var designTimeType = instance.GetType(); + var ownerType = member.OwnerType.SystemType; + + if (!ownerType.IsAssignableFrom(designTimeType)) { + result = ReflectionMapper.GetXamlType(designTimeType) + .Member(member.Name) as ReflectionMember; + } + } + return result.Info; + } + return null; + } + + public static void Add(object collection, object item) + { + IList list = collection as IList; + list.Add(item); + } + + public static void Add(object collection, object key, object item) + { + IDictionary dict = collection as IDictionary; + dict.Add(key, item); + } + + public static void Insert(object collection, int index, object item) + { + IList list = collection as IList; + list.Insert(index, item); + } + + public static void Remove(object collection, object item) + { + IList list = collection as IList; + if (list != null) { + list.Remove(item); + } + else { + IDictionary dict = collection as IDictionary; + object key = null; + foreach (DictionaryEntry pair in dict) { + if (pair.Value == item) { + key = pair.Key; + break; + } + } + dict.Remove(key); + } + } + + public static bool TryConvertToText(XamlContext context, object value, out string text) + { + text = null; + if (value != null) { + text = ConvertToText(context, value); + } + return text != null; + } + + public static string ConvertToText(XamlContext context, object value) + { + var text = StandardValues.GetStandardValueText(value); + if (text != null) { + return text; + } + var targetType = context.XamlProperty.ValueType.SystemType; + if (targetType != null) { + TryConvert(ref value, targetType); + } + var valueSerializer = GetValueSerializer(context); + if (valueSerializer != null && valueSerializer.CanConvertToString(value, context)) { + return valueSerializer.ConvertToString(value, context); + } + return null; + } + + static void TryConvert(ref object value, Type targetType) + { + if (!targetType.IsAssignableFrom(value.GetType())) { + if (value is IConvertible && typeof(IConvertible).IsAssignableFrom(targetType)) { + value = Convert.ChangeType(value, targetType); + } + } + } + + public static object ConvertFromText(XamlContext context, string text) + { + var valueSerializer = GetValueSerializer(context); + if (valueSerializer != null && valueSerializer.CanConvertFromString(text, context)) { + return valueSerializer.ConvertFromString(text, context); + } + return text; + } + + public static object ConvertFromText(XamlContext context, XamlType targetType, string text) + { + var valueSerializer = GetValueSerializer(targetType); + if (valueSerializer != null && valueSerializer.CanConvertFromString(text, context)) { + return valueSerializer.ConvertFromString(text, context); + } + return text; + } + + public static ValueSerializer GetValueSerializer(XamlContext context) + { + var valueSerializer = GetValueSerializer(context.XamlProperty.Member); + if (valueSerializer == null) { + valueSerializer = GetValueSerializer(context.XamlProperty.ValueType); + } + return valueSerializer; + } + + public static ValueSerializer GetValueSerializer(XamlType type) + { + if (type.SystemType != null) { + return ValueSerializer.GetSerializerFor(type.SystemType); + } + return null; + } + + public static ValueSerializer GetValueSerializer(XamlMember member) + { + var reflectionMember = member as ReflectionMember; + if (reflectionMember != null && reflectionMember.Info.PropertyDescriptor != null) { + return ValueSerializer.GetSerializerFor(reflectionMember.Info.PropertyDescriptor); + } + return null; + } + + public static XamlType GetWrapperTypeForInitializationText(object value) + { + var type = value.GetType(); + Type prev = null; + + while (true) { + if (type == null || ValueSerializer.GetSerializerFor(type) == null) { + break; + } + prev = type; + type = type.BaseType; + } + + if (prev != null) { + return ReflectionMapper.GetXamlType(prev); + } + + throw new XamlException("ValueSerializer not found"); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/StandardValues.cs b/src/AddIns/BackendBindings/Xaml/Xaml/StandardValues.cs new file mode 100644 index 0000000000..b2591dd478 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/StandardValues.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; +using System.Reflection; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows; +using System.Windows.Documents; +using System.ComponentModel; + +namespace ICSharpCode.Xaml +{ + public static class StandardValues + { + static Dictionary> standardValues = new Dictionary>(); + static Dictionary standardValueFromInstance = new Dictionary(); + + public static void AddStandardValues(Type type, Type valuesContainer) + { + AddStandardValues(type, valuesContainer + .GetProperties(BindingFlags.Public | BindingFlags.Static) + .Select(p => new StandardValue() { + Instance = p.GetValue(null, null), + Text = p.Name + })); + } + + public static void AddStandardValue(Type type, string text, object value) + { + AddStandardValues(type, new[] { new StandardValue() { Text = text, Instance = value } }); + } + + public static void AddStandardValues(Type type, IEnumerable values) + { + List list; + lock (standardValues) { + lock (standardValueFromInstance) { + if (!standardValues.TryGetValue(type, out list)) { + list = new List(); + standardValues[type] = list; + } + foreach (var v in values) { + list.Add(v); + standardValueFromInstance[v.Instance] = v; + } + } + } + } + + public static IEnumerable GetStandardValues(Type type) + { + if (type.IsEnum) { + var enumValues = Enum.GetValues(type); + var enumNames = Enum.GetNames(type); + + for (int i = 0; i < enumValues.Length; i++) { + yield return new StandardValue() { + Instance = enumValues.GetValue(i), + Text = enumNames[i], + }; + } + } + List values; + lock (standardValues) { + if (standardValues.TryGetValue(type, out values)) { + foreach (var value in values) { + if (value.Text == null) { + if (Runtime.TryConvertToText(null, value.Instance, out value.Text)) { + yield return value; + } + } + else { + yield return value; + } + } + } + } + var converter = TypeDescriptor.GetConverter(type); + if (converter.GetStandardValuesSupported()) { + foreach (var value in converter.GetStandardValues()) { + string text; + if (Runtime.TryConvertToText(null, value, out text)) { + yield return new StandardValue() { + Instance = value, + Text = text + }; + } + } + } + yield break; + } + + public static string GetStandardValueText(object value) + { + lock (standardValueFromInstance) { + StandardValue standardValue; + if (standardValueFromInstance.TryGetValue(value, out standardValue)) { + return standardValue.Text; + } + } + return null; + } + + //static Dictionary designTimeTypes = new Dictionary(); + + //public static void AddDesignTimeType(Type type, Type designTimeType) + //{ + // lock (designTimeTypes) + // { + // designTimeTypes[type] = designTimeType; + // } + //} + + //public static Type GetDesignTimeType(Type type) + //{ + // lock (designTimeTypes) + // { + // Type result; + // if (designTimeTypes.TryGetValue(type, out result)) + // { + // return result; + // } + // } + // return type; + //} + } + + public class StandardValue + { + public object Instance; + public string Text; + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/TextNode.cs b/src/AddIns/BackendBindings/Xaml/Xaml/TextNode.cs new file mode 100644 index 0000000000..4e159de081 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/TextNode.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; + +namespace ICSharpCode.Xaml +{ + public class TextNode : XamlValue + { + internal TextNode() + { + } + + public string Text; + + public override string ToString() + { + return GetType().Name + ": " + Text; + } + + public override IEnumerable Nodes() + { + yield break; + } + + protected override void RemoveChild(XamlNode node) + { + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/Tracker.cs b/src/AddIns/BackendBindings/Xaml/Xaml/Tracker.cs new file mode 100644 index 0000000000..e73de78a65 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/Tracker.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + public class Tracker + { + public virtual void Process(DocumentChangedEventArgs e) + { + Remove(e.OldNode, e.OldParent); + Add(e.NewNode); + } + + public virtual void Add(XamlNode node) + { + if (node is MemberNode) { + Add(node as MemberNode); + } + else if (node is ObjectNode) { + Add(node as ObjectNode); + } + else if (node is TextNode) { + Add(node as TextNode); + } + } + + public virtual void Add(MemberNode node) + { + } + + public virtual void Add(ObjectNode node) + { + } + + public virtual void Add(TextNode node) + { + } + + public virtual void Remove(XamlNode node, XamlNode parent) + { + if (node is MemberNode) { + Remove(node as MemberNode, parent as ObjectNode); + } + else if (node is ObjectNode) { + Remove(node as ObjectNode, parent as MemberNode); + } + else if (node is TextNode) { + Remove(node as TextNode, parent as MemberNode); + } + } + + public virtual void Remove(MemberNode node, ObjectNode parent) + { + } + + public virtual void Remove(ObjectNode node, MemberNode parent) + { + } + + public virtual void Remove(TextNode node, MemberNode parent) + { + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/ValueCollection.cs b/src/AddIns/BackendBindings/Xaml/Xaml/ValueCollection.cs new file mode 100644 index 0000000000..3cce4a32f7 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/ValueCollection.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.WpfDesign.Xaml +{ + class XamlValueCollection + { + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/WpfTracker.cs b/src/AddIns/BackendBindings/Xaml/Xaml/WpfTracker.cs new file mode 100644 index 0000000000..555327a7f9 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/WpfTracker.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.Xaml; +using System.Windows; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + public class WpfTracker : Tracker + { + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj b/src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj new file mode 100644 index 0000000000..792291d5d2 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj @@ -0,0 +1,119 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD} + Library + Properties + ICSharpCode.Xaml + ICSharpCode.Xaml + v3.5 + 512 + + + true + full + false + ..\..\..\..\..\AddIns\AddIns\BackendBindings\XamlBinding\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + 3.0 + + + 3.0 + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + 3.0 + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + Code + + + Code + + + Code + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Code + + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlAssembly.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlAssembly.cs new file mode 100644 index 0000000000..f0c737a661 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlAssembly.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Markup; +using System.Diagnostics; + +namespace ICSharpCode.Xaml +{ + [DebuggerDisplay("{Name}")] + public abstract class XamlAssembly + { + //public abstract XamlType[] Types; + public abstract IEnumerable XmlnsDefinitions { get; } + public abstract string Name { get; } + public abstract XamlType GetType(string fullName); + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlConstants.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlConstants.cs new file mode 100644 index 0000000000..11370012b5 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlConstants.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using System.Reflection; +using System.Windows; +using System.IO; + +namespace ICSharpCode.Xaml +{ + public class XamlConstants + { + public static XNamespace XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; + public static XNamespace Presentation2006Namespace = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; + public static XNamespace Presentation2007Namespace = "http://schemas.microsoft.com/netfx/2007/xaml/presentation"; + + public static Assembly MscorlibAssembly = typeof(object).Assembly; + public static Assembly WindowsBaseAssembly = typeof(DependencyObject).Assembly; + public static Assembly PresentationCoreAssembly = typeof(UIElement).Assembly; + public static Assembly PresentationFrameworkAssembly = typeof(FrameworkElement).Assembly; + + public static XName XmlSpaceName = XNamespace.Xml.GetName("space"); + + public static bool HasXamlExtension(string filePath) + { + return Path.GetExtension(filePath).Equals(".xaml", StringComparison.InvariantCultureIgnoreCase); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlContext.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlContext.cs new file mode 100644 index 0000000000..3f8ceba1f3 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlContext.cs @@ -0,0 +1,130 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + public class XamlContext : IServiceProvider, ITypeDescriptorContext, IXamlTypeResolver, IUriContext, IProvideValueTarget, IValueSerializerContext + { + internal XamlContext(XamlProperty property) + { + this.property = property; + } + + XamlProperty property; + + public XamlProperty XamlProperty + { + get { return property; } + } + + #region IServiceProvider Members + + public object GetService(Type serviceType) + { + if (serviceType == typeof(ITypeDescriptorContext)) return this; + if (serviceType == typeof(IXamlTypeResolver)) return this; + if (serviceType == typeof(IUriContext)) return this; + if (serviceType == typeof(IProvideValueTarget)) return this; + if (serviceType == typeof(IValueSerializerContext)) return this; + return null; + } + + #endregion + + #region ITypeDescriptorContext Members + + public IContainer Container + { + get { throw new NotImplementedException(); } + } + + public object Instance + { + get { throw new NotImplementedException(); } + } + + public void OnComponentChanged() + { + throw new NotImplementedException(); + } + + public bool OnComponentChanging() + { + throw new NotImplementedException(); + } + + public PropertyDescriptor PropertyDescriptor + { + get { throw new NotImplementedException(); } + } + + #endregion + + #region IXamlTypeResolver Members + + public Type Resolve(string qualifiedTypeName) + { + var namespaceProvider = XmlTracker.GetNamespaceProvider(property.Object); + var typeName = XamlParser.GetTypeName(qualifiedTypeName, namespaceProvider); + var type = property.Object.Document.Project.TypeFinder.FindType(typeName); + return type.SystemType; + } + + #endregion + + #region IUriContext Members + + public Uri BaseUri + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + #endregion + + #region IProvideValueTarget Members + + public object TargetObject + { + get { return property.Object.Instance; } + } + + public object TargetProperty + { + get + { + var reflectionMember = property.Member as ReflectionMember; + if (reflectionMember != null) { + return reflectionMember.Info.DependencyProperty; + } + return null; + } + } + + #endregion + + #region IValueSerializerContext Members + + public ValueSerializer GetValueSerializerFor(PropertyDescriptor descriptor) + { + return null; + } + + public ValueSerializer GetValueSerializerFor(Type type) + { + return null; + } + + #endregion + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs new file mode 100644 index 0000000000..5bcbefa4c3 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using System.Diagnostics; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + public class XamlDocument : IUriContext + { + internal XamlDocument(XamlProject project) + { + Project = project; + Parser = new XamlParser(this); + Trackers.Add(new InstanceTracker()); + Trackers.Add(new XmlTracker()); + } + + public XamlParser Parser { get; private set; } + public XamlProject Project { get; private set; } + public List Dependencies = new List(); + public List Errors = new List(); + public List Trackers = new List(); + public XDocument XmlDocument; + + public event EventHandler RootChanged; + public event DocumentChangedEventHandler DocumentChanged; + + bool parsing; + + ObjectNode root; + + public ObjectNode Root + { + get + { + return root; + } + set + { + var e = new DocumentChangedEventArgs() { OldNode = root, NewNode = value }; + root = value; + RaiseDocumentChanged(e); + + if (RootChanged != null) { + RootChanged(this, EventArgs.Empty); + } + } + } + + public ObjectNode ParseObject(string text) + { + throw new NotImplementedException(); + } + + public ObjectNode CreateObject(object instance) + { + return new ObjectNode(this, instance); + } + + public void Parse(string text) + { + ObjectNode result = null; + Errors.Clear(); + parsing = true; + + try { + XmlDocument = XDocument.Parse(text); + result = Parser.CreateObjectNodeFromXmlElement(XmlDocument.Root, false); + foreach (var node in result.DescendantsAndSelf()) { + node.Document = this; + } + } + catch (Exception x) { + } + + parsing = false; + Root = result; + } + + public bool CanSave + { + get { return XmlDocument != null; } + } + + public string Save() + { + //return XamlFormatter.Format(XmlDocument.ToString()); + + var settings = new XmlWriterSettings() { + Indent = true, + IndentChars = " ", + NewLineOnAttributes = true, + OmitXmlDeclaration = true + }; + var sb = new StringBuilder(); + using (var writer = XmlWriter.Create(sb, settings)) { + XmlDocument.WriteTo(writer); + } + + return sb.ToString(); + } + + internal void RaiseDocumentChanged(DocumentChangedEventArgs e) + { + if (!parsing) { + foreach (var t in Trackers) { + t.Process(e); + } + if (DocumentChanged != null) { + DocumentChanged(this, e); + } + } + } + + #region IUriContext Members + + Uri baseUri; + + public Uri BaseUri + { + get + { + return baseUri; + } + set + { + if (baseUri != null) { + Project.Documents.Remove(baseUri); + } + baseUri = value; + if (baseUri != null) { + Project.Documents[baseUri] = this; + } + } + } + + #endregion + } + + public delegate void DocumentChangedEventHandler(object sender, DocumentChangedEventArgs e); + + public class DocumentChangedEventArgs : EventArgs + { + public XamlNode OldNode; + public XamlNode OldParent; + public XamlNode NewNode; + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocumentError.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocumentError.cs new file mode 100644 index 0000000000..ba576bfe90 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocumentError.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + public class XamlDocumentError + { + public string Message { get; set; } + public int LineNumber { get; set; } + public int LinePosition { get; set; } + public XamlDocument Document { get; set; } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlException.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlException.cs new file mode 100644 index 0000000000..ba7ce644ea --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlException.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; + +namespace ICSharpCode.Xaml +{ + [Serializable] + public class XamlException : Exception + { + public XamlException() + { + } + + public XamlException(string message) + : base(message) + { + } + + public XamlException(string message, Exception innerException) + : base(message, innerException) + { + } + + protected XamlException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + + public int LineNumber { get; set; } + public int LinePosition { get; set; } + public Uri BaseUri { get; set; } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlFormatter.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlFormatter.cs new file mode 100644 index 0000000000..edd844b3cb --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlFormatter.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace ICSharpCode.Xaml +{ + //TODO: formatter should be based on XamlDocument + public static class XamlFormatter + { + public static char IndentChar = ' '; + public static int Indenation = 2; + public static int LengthBeforeNewLine = 60; + + static StringBuilder sb; + static int currentColumn; + static int nextColumn; + + public static string Format(string xaml) + { + sb = new StringBuilder(); + currentColumn = 0; + nextColumn = 0; + + try { + var doc = XDocument.Parse(xaml); + WalkContainer(doc); + return sb.ToString(); + } + catch { + return xaml; + } + } + + static void WalkContainer(XContainer node) + { + foreach (var c in node.Nodes()) { + if (c is XElement) { + WalkElement(c as XElement); + } + else { + NewLine(); + Append(c.ToString().Trim()); + } + } + } + + static void WalkElement(XElement e) + { + NewLine(); + string prefix1 = e.GetPrefixOfNamespace(e.Name.Namespace); + string name1 = prefix1 == null ? e.Name.LocalName : prefix1 + ":" + e.Name.LocalName; + Append("<" + name1); + + List list = new List(); + int length = name1.Length; + + foreach (var a in e.Attributes()) { + string prefix2 = e.GetPrefixOfNamespace(a.Name.Namespace); + var g = new AttributeString() { Name = a.Name, Prefix = prefix2, Value = a.Value }; + list.Add(g); + length += g.FinalString.Length; + } + + list.Sort(AttributeComparrer.Instance); + + if (length > LengthBeforeNewLine) { + nextColumn = currentColumn + 1; + for (int i = 0; i < list.Count; i++) { + if (i > 0) { + NewLine(); + } + else { + Append(" "); + } + Append(list[i].FinalString); + } + nextColumn -= name1.Length + 2; + } + else { + foreach (var a in list) { + Append(" " + a.FinalString); + } + } + + if (e.Nodes().Count() > 0) { + Append(">"); + nextColumn += Indenation; + + WalkContainer(e); + + nextColumn -= Indenation; + NewLine(); + Append(""); + } + else { + Append(" />"); + } + } + + static void NewLine() + { + if (sb.Length > 0) { + sb.AppendLine(); + sb.Append(new string(' ', nextColumn)); + currentColumn = nextColumn; + } + } + + static void Append(string s) + { + sb.Append(s); + currentColumn += s.Length; + } + + enum AttributeLayout + { + X, + XmlnsMicrosoft, + Xmlns, + XmlnsWithClr, + SpecialOrder, + ByName, + Attached, + WithPrefix + } + + class AttributeString + { + public XName Name; + public string Prefix; + public string Value; + + public string LocalName + { + get { return Name.LocalName; } + } + + public string FinalName + { + get + { + return Prefix == null ? Name.LocalName : Prefix + ":" + Name.LocalName; + } + } + + public string FinalString + { + get + { + return FinalName + "=\"" + Value + "\""; + } + } + + public AttributeLayout GetAttributeLayout() + { + if (Prefix == "xmlns" || LocalName == "xmlns") { + if (Value.StartsWith("http://schemas.microsoft.com")) return AttributeLayout.XmlnsMicrosoft; + if (Value.StartsWith("clr")) return AttributeLayout.XmlnsWithClr; + return AttributeLayout.Xmlns; + } + if (Prefix == "x") return AttributeLayout.X; + if (Prefix != null) return AttributeLayout.WithPrefix; + if (LocalName.Contains(".")) return AttributeLayout.Attached; + if (AttributeComparrer.SpecialOrder.Contains(LocalName)) return AttributeLayout.SpecialOrder; + return AttributeLayout.ByName; + } + } + + class AttributeComparrer : IComparer + { + public static AttributeComparrer Instance = new AttributeComparrer(); + + public int Compare(AttributeString a1, AttributeString a2) + { + var y1 = a1.GetAttributeLayout(); + var y2 = a2.GetAttributeLayout(); + if (y1 == y2) { + if (y1 == AttributeLayout.SpecialOrder) { + return + Array.IndexOf(SpecialOrder, a1.LocalName).CompareTo( + Array.IndexOf(SpecialOrder, a2.LocalName)); + } + return a1.FinalName.CompareTo(a2.FinalName); + } + return y1.CompareTo(y2); + } + + public static string[] SpecialOrder = new string[] { + "Name", + "Content", + "Command", + "Executed", + "CanExecute", + "Width", + "Height", + "Margin", + "HorizontalAlignment", + "VerticalAlignment", + "HorizontalContentAlignment", + "VerticalContentAlignment", + "StartPoint", + "EndPoint", + "Offset", + "Color" + }; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlMember.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlMember.cs new file mode 100644 index 0000000000..1db676e69b --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlMember.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; + +namespace ICSharpCode.Xaml +{ + public abstract class XamlMember + { + public abstract string Name { get; } + public abstract XamlType OwnerType { get; } + public abstract XamlType ValueType { get; } + public abstract bool IsReadOnly { get; } + public abstract bool IsStatic { get; } + public abstract bool IsAttachable { get; } + public abstract XamlType TargetType { get; } + public abstract AllowedLocation AllowedLocation { get; } + public abstract bool IsEvent { get; } + public abstract bool IsDirective { get; } + public abstract bool HasTextSyntax { get; } + + public bool IsNameProperty + { + get + { + return this == Directive.Name || this == OwnerType.NameProperty; + } + } + + public abstract T GetAttribute() where T : Attribute; + + public override string ToString() + { + return GetType().Name + ": " + Name; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlNode.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlNode.cs new file mode 100644 index 0000000000..3b1bbbf6c6 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlNode.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace ICSharpCode.Xaml +{ + public abstract class XamlNode : IHasAnnotations + { + public XamlNode ParentNode; + public XamlDocument Document; + public XObject XmlObject; + + public abstract IEnumerable Nodes(); + protected abstract void RemoveChild(XamlNode node); + + public bool InDocument + { + get { return FindAncestor(n => Document.Root == n) != null; } + } + + public IEnumerable Descendants() + { + foreach (var node in Nodes()) { + foreach (var node2 in node.DescendantsAndSelf()) { + yield return node2; + } + } + } + + public IEnumerable DescendantsAndSelf() + { + foreach (var node in Descendants()) { + yield return node; + } + yield return this; + } + + public XamlNode FindAncestor(Predicate predicate) + { + var node = this; + while (node != null) { + if (predicate(node)) { + return node; + } + node = node.ParentNode; + } + return null; + } + + public void Remove() + { + ParentNode.RemoveChild(this); + } + + #region IHasAnnotations Members + + Dictionary annotations = new Dictionary(); + + public void AnnotateWith(T annotation) where T : class + { + annotations[typeof(T)] = annotation; + } + + public T GetAnnotation() where T : class + { + object result; + if (annotations.TryGetValue(typeof(T), out result)) { + return (T)result; + } + return default(T); + } + + #endregion + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlParser.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlParser.cs new file mode 100644 index 0000000000..8c2ee53241 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlParser.cs @@ -0,0 +1,637 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using System.Text.RegularExpressions; +using System.Windows.Data; +using System.Collections; + +namespace ICSharpCode.Xaml +{ + public class XamlParser + { + public XamlParser(XamlDocument doc) + { + Document = doc; + } + + public XamlDocument Document { get; private set; } + + public XamlTypeFinder TypeFinder + { + get { return Document.Project.TypeFinder; } + } + + public ObjectNode CreateObjectNodeFromXmlElement(XElement xmlObjectElement, + bool parentPreservesXmlSpace) + { + //type + XamlType objectType = TypeFinder.FindType(xmlObjectElement.Name); + if (objectType == null) { + objectType = TypeFinder.FindExtensionType(xmlObjectElement.Name); + } + if (objectType == null) { + throw new XamlException("Unknown element type"); + } + + //xml:space + bool preserveChildXmlSpace = parentPreservesXmlSpace; + var spaceAttribute = xmlObjectElement.Attribute(XamlConstants.XmlSpaceName); + if (spaceAttribute != null) { + preserveChildXmlSpace = spaceAttribute.Value == "preserve"; + } + + //x:Code, x:XData + if (objectType == IntristicType.Code || objectType == IntristicType.XData) { + ObjectNode literalResult = new ObjectNode(); + literalResult.Type = objectType; + var textNode = new TextNode() { Text = xmlObjectElement.Value }; + var memberNode = new MemberNode(); + memberNode.Values.Add(textNode); + literalResult.MemberNodes.Add(memberNode); + literalResult.XmlObject = xmlObjectElement; + return literalResult; + } + + List convertedChildNodes = new List(); + List codeItems = new List(); + + //conversion + + foreach (var node in xmlObjectElement.Nodes()) { + var childElement = node as XElement; + if (childElement != null) { + if (IsXamlName(childElement.Name)) { + var convertedObject = CreateObjectNodeFromXmlElement(childElement, preserveChildXmlSpace); + if (convertedObject.Type == IntristicType.Code) { + codeItems.Add(convertedObject); + } + else { + convertedChildNodes.Add(convertedObject); + } + } + else if (GetDottedXamlName(childElement.Name) != null) { + var convertedMember = CreateMemberNodeFromXmlElement(childElement, objectType, preserveChildXmlSpace); + foreach (var objectNode in convertedMember.Values.OfType().ToArray()) { + if (objectNode.Type == IntristicType.Code) { + codeItems.Add(objectNode); + convertedMember.Values.Remove(objectNode); + } + } + convertedChildNodes.Add(convertedMember); + } + else { + throw new XamlException("Invalid element name syntax"); + } + } + else { + AddText(convertedChildNodes, node); + } + } + + if (codeItems.Count > 0) { + MemberNode directiveChildren = new MemberNode(); + directiveChildren.Member = IntristicMember.DirectiveChildren; + foreach (var item in codeItems) { + directiveChildren.Values.Add(item); + //item.ParentMember = directiveChildren; + } + + } + + //whitespace removal + + List strippedChildNodes = new List(); + int n = convertedChildNodes.Count; + bool hasTextNodes = false; + bool hasContent = false; + + for (int i = 0; i < n; i++) { + var node = convertedChildNodes[i]; + var textNode = node as TextNode; + if (textNode != null && IsCollapsibleString(textNode.Text)) { + bool prevMember = i - 1 > 0 && convertedChildNodes[i - 1] is MemberNode; + bool nextMember = i + 1 < n && convertedChildNodes[i + 1] is MemberNode; + if (i == 0 && nextMember) continue; + if (prevMember && nextMember) continue; + if (i == n - 1 && prevMember && (hasTextNodes || hasContent)) continue; + } + + strippedChildNodes.Add(convertedChildNodes[i]); + + if (textNode != null) { + hasTextNodes = true; + } + var memberNode = node as MemberNode; + if (memberNode != null && memberNode.Member == objectType.ContentProperty) { + hasContent = true; + } + } + + //content wrapping + + XamlMember contentMember = null; + XamlType contentMemberType = null; + if (objectType.ContentProperty != null) { + contentMember = objectType.ContentProperty; + contentMemberType = contentMember.ValueType; + } + else { + contentMember = IntristicMember.Items; + contentMemberType = objectType; + } + + List attributeMembers = new List(); + foreach (var xmlAttribute in xmlObjectElement.Attributes()) { + if (xmlAttribute.IsNamespaceDeclaration) continue; + var memberNode = CreateMemberNodeFromXmlAttribute(xmlAttribute, objectType, xmlObjectElement); + attributeMembers.Add(memberNode); + } + + List members = new List(); + + bool initFromText = + strippedChildNodes.Count(node => node is TextNode) == 1 && + strippedChildNodes.All(node => node is TextNode || + node is MemberNode && (node as MemberNode).Member == IntristicMember.DirectiveChildren) && + attributeMembers.All(node => node.Member == Directive.Key || + node.Member == Directive.Uid) && + + // differ from spec (spec bug?) + //(contentMember.HasTextSyntax || objectType.HasTextSyntax); + objectType.HasTextSyntax; + + if (initFromText) { + var initTextMember = new MemberNode(); + initTextMember.Member = IntristicMember.InitializationText; + initTextMember.Values.Add(strippedChildNodes.OfType().First()); + members.Add(initTextMember); + } + else { + members.AddRange(attributeMembers); + List npChildren = new List(); + + foreach (var node in strippedChildNodes) { + if (node is MemberNode) { + if (npChildren.Count > 0) { + var memberNode = CreateMemberNodeFromContent(contentMember, contentMemberType, npChildren, preserveChildXmlSpace); + members.Add(memberNode); + npChildren.Clear(); + } + members.Add(node as MemberNode); + } + else { + npChildren.Add(node as XamlValue); + } + } + + if (npChildren.Count > 0) { + var memberNode = CreateMemberNodeFromContent(contentMember, contentMemberType, npChildren, preserveChildXmlSpace); + members.Add(memberNode); + } + } + + ObjectNode result = new ObjectNode(); + result.Type = objectType; + foreach (var memberNode in members) { + result.MemberNodes.Add(memberNode); + //memberNode.ParentObject = result; + } + result.XmlObject = xmlObjectElement; + return result; + } + + public MemberNode CreateMemberNodeFromXmlAttribute(XAttribute xmlAttribute, + XamlType objectType, XElement namespaceProvider) + { + XamlMember member; + if (IsXamlName(xmlAttribute.Name)) { + member = objectType.Member(xmlAttribute.Name.LocalName); + if (member == null) { + member = Directive.GetDirective(xmlAttribute.Name); + } + if (member == null) { + throw new XamlException("Unknown member"); + } + } + else { + var dottedName = GetDottedXamlName(xmlAttribute.Name); + if (dottedName != null) { + var attributeNamespace = + xmlAttribute.Name.Namespace != XNamespace.None ? + xmlAttribute.Name.Namespace : + namespaceProvider.Name.Namespace; + + var definingType = TypeFinder.FindType(attributeNamespace + dottedName.TypeName); + if (definingType == null) { + throw new XamlException("Unknown type"); + } + member = definingType.Member(dottedName.MemberName); + if (member == null) { + throw new XamlException("Unknown member"); + } + } + else { + throw new XamlException("Invalid attribute syntax"); + } + } + + XamlValue attributeValue = CreateValueFromAttributeText(xmlAttribute.Value, namespaceProvider); + + MemberNode result = new MemberNode(); + result.Member = member; + result.Values.Add(attributeValue); + //attributeValue.ParentMember = result; + result.XmlObject = xmlAttribute; + return result; + } + + public XamlValue CreateValueFromAttributeText(string valueText, XElement namespaceProvider) + { + if (valueText.StartsWith("{}")) { + return new TextNode() { Text = valueText.Substring(2) }; + } + else if (valueText.StartsWith("{")) { + return CreateObjectNodeFromMarkupExtensionInAttribute(valueText, namespaceProvider); + } + return new TextNode() { Text = valueText }; + } + + public MemberNode CreateMemberNodeFromXmlElement(XElement xmlMemberElement, + XamlType containingType, bool parentPreservesXmlSpace) + { + if (xmlMemberElement.HasAttributes) { + if (xmlMemberElement.Attributes().Count() > 1 || + Directive.GetDirective(xmlMemberElement.FirstAttribute.Name) != + Directive.Uid) { + throw new XamlException("Member elements cannot contain attributes"); + } + } + + var dottedName = GetDottedXamlName(xmlMemberElement.Name); + XamlType ownerType = TypeFinder.FindType(xmlMemberElement.Name.Namespace + dottedName.TypeName); + if (ownerType == null) { + throw new XamlException("Unknown element type"); + } + + XamlMember resolvedMember = ownerType.Member(dottedName.MemberName); + if (resolvedMember == null || resolvedMember.AllowedLocation != AllowedLocation.Any) { + throw new XamlException("Member not found"); + } + + List convertedChildNodes = new List(); + + foreach (var node in xmlMemberElement.Nodes()) { + var childElement = node as XElement; + if (childElement != null) { + if (IsXamlName(childElement.Name)) { + var convertedObject = CreateObjectNodeFromXmlElement(childElement, parentPreservesXmlSpace); + convertedChildNodes.Add(convertedObject); + } + else if (GetDottedXamlName(childElement.Name) != null) { + throw new XamlException("Member elements may not be nested directly inside of another member element"); + } + else { + throw new XamlException("Invalid element name syntax"); + } + } + else { + AddText(convertedChildNodes, node); + } + } + + var result = CreateMemberNodeFromContent(resolvedMember, resolvedMember.ValueType, convertedChildNodes, parentPreservesXmlSpace); + result.XmlObject = xmlMemberElement; + return result; + } + + public MemberNode CreateMemberNodeFromContent(XamlMember containingMember, + XamlType memberType, List childNodes, bool preserveXmlSpace) + { + if (!preserveXmlSpace) { + if (memberType.IsWhitespaceSignificantCollection) { + TextNode prevTextNode = null; + for (int i = 0; i < childNodes.Count; i++) { + var node = childNodes[i]; + var textNode = node as TextNode; + if (textNode != null) { + textNode.Text = CollapseWhitespace(textNode.Text); + if (prevTextNode == null) { + textNode.Text = textNode.Text.TrimStart(); + prevTextNode = textNode; + } + } + else { + var objectNode = node as ObjectNode; + if (objectNode != null && objectNode.Type.TrimSurroundingWhitespace) { + var afterTextNode = i + 1 < childNodes.Count ? childNodes[i + 1] as TextNode : null; + if (prevTextNode != null) { + prevTextNode.Text = prevTextNode.Text.TrimEnd(); + } + if (afterTextNode != null) { + afterTextNode.Text = afterTextNode.Text.TrimStart(); + } + } + } + } + if (prevTextNode != null) { + prevTextNode.Text = prevTextNode.Text.TrimEnd(); + } + } + // differ from spec (spec bug?) + else { + foreach (var textNode in childNodes.OfType()) { + textNode.Text = CollapseWhitespace(textNode.Text).Trim(); + } + } + } + + childNodes = childNodes.Where(node => node is ObjectNode || (node as TextNode).Text.Length > 0).ToList(); + + List outputValues = new List(); + var singleObjectNode = childNodes.FirstOrDefault() as ObjectNode; + var useSingleObjectNode = singleObjectNode != null && memberType.IsAssignableFrom(singleObjectNode.Type); + + if (memberType.IsCollection && !useSingleObjectNode) { + var retrievedContentMember = new MemberNode(); + retrievedContentMember.Member = IntristicMember.Items; + foreach (var value in childNodes) { + retrievedContentMember.Values.Add(value); + } + + var retrievedValue = new ObjectNode(); + retrievedValue.Type = memberType; + retrievedValue.MemberNodes.Add(retrievedContentMember); + retrievedValue.IsRetrieved = true; + + outputValues.Add(retrievedValue); + } + else { + outputValues.AddRange(childNodes); + } + + MemberNode result = new MemberNode(); + result.Member = containingMember; + foreach (var value in outputValues) { + result.Values.Add(value); + //value.ParentMember = result; + } + return result; + } + + public static XName GetTypeName(string typeNameWithPrefix, XElement namespaceProvider) + { + var prefixedName = GetPrefixedName(typeNameWithPrefix); + if (prefixedName == null) { + throw new XamlException("Bad type extension name"); + } + + XNamespace typeNamespace = null; + if (prefixedName.Prefix == null) { + typeNamespace = namespaceProvider.Name.Namespace; + } + else { + typeNamespace = namespaceProvider.GetNamespaceOfPrefix(prefixedName.Prefix); + if (typeNamespace == null) { + throw new XamlException("Unrecognized namespace prefix"); + } + } + + return typeNamespace + prefixedName.LocalName; + } + + public ObjectNode CreateObjectNodeFromMarkupExtensionInAttribute(string attributeText, + XElement namespaceProvider) + { + var ast = MarkupExtensionParser.Parse(attributeText); + + var prefixedName = GetPrefixedName(ast.TypeName); + if (prefixedName == null) { + throw new XamlException("Bad type extension name"); + } + + XNamespace typeNamespace = null; + if (prefixedName.Prefix == null) { + typeNamespace = namespaceProvider.Name.Namespace; + } + else { + typeNamespace = namespaceProvider.GetNamespaceOfPrefix(prefixedName.Prefix); + if (typeNamespace == null) { + throw new XamlException("Unrecognized namespace prefix"); + } + } + + XName typeName = typeNamespace + prefixedName.LocalName; + XamlType extensionType = TypeFinder.FindExtensionType(typeName); + if (extensionType == null || !IntristicType.MarkupExtension.IsAssignableFrom(extensionType)) { + extensionType = TypeFinder.FindType(typeName); + } + if (extensionType == null || !IntristicType.MarkupExtension.IsAssignableFrom(extensionType)) { + throw new XamlException("Unknown markup extension"); + } + + List namedMembers = new List(); + foreach (var namedArg in ast.NamedArgs) { + var memberName = GetPrefixedName(namedArg.Key); + if (memberName == null) { + throw new XamlException("Bad member name"); + } + + XNamespace memberNamespace; + if (prefixedName.Prefix == null) { + memberNamespace = namespaceProvider.Name.Namespace; + } + else { + memberNamespace = namespaceProvider.GetNamespaceOfPrefix(prefixedName.Prefix); + if (typeNamespace == null) { + throw new XamlException("Unrecognized namespace prefix"); + } + } + + XamlMember member = null; + if (IsXamlName(memberName.LocalName)) { + if (memberNamespace != typeNamespace) { + throw new XamlException("Unknown member"); + } + member = extensionType.Member(memberName.LocalName); + } + else { + var dottedName = GetDottedXamlName(memberNamespace + memberName.LocalName); + if (dottedName != null) { + var ownerType = TypeFinder.FindType(memberNamespace + dottedName.TypeName); + if (ownerType == null) { + throw new XamlException("Unknown type"); + } + member = ownerType.Member(dottedName.MemberName); + } + } + + if (member == null) { + throw new XamlException("Unknown member"); + } + + var memberValue = CreateValueFromAttributeText(namedArg.Value, namespaceProvider); + + var namedMember = new MemberNode(); + namedMember.Member = member; + namedMember.Values.Add(memberValue); + namedMembers.Add(namedMember); + } + + List positionalArgs = ast.PositionalArgs; + MemberNode positionalArgsMember = null; + + if (positionalArgs.Count > 0) { + Constructor constructorInfo = null; + foreach (var extensionConstructor in extensionType.Constructors) { + if (extensionConstructor.Arguments.Length == positionalArgs.Count) { + constructorInfo = extensionConstructor; + break; + } + } + + if (constructorInfo == null) { + throw new XamlException( + string.Format("No constructor for type '{0}' has {1} parameters", extensionType.Name, positionalArgs.Count)); + } + + List positionalArgValues = new List(); + + for (int i = 0; i < positionalArgs.Count; i++) { + var positionalArg = positionalArgs[i]; + var argumentType = constructorInfo.Arguments.ElementAt(i); + var argValue = CreateValueFromAttributeText(positionalArg, namespaceProvider); + positionalArgValues.Add(argValue); + } + + if (!MapPositionalArgsToNamedMembers(constructorInfo, positionalArgValues, namedMembers)) { + positionalArgsMember = new MemberNode(); + positionalArgsMember.Member = IntristicMember.ConsructorArgs; + foreach (var value in positionalArgValues) { + positionalArgsMember.Values.Add(value); + //value.ParentMember = positionalArgsMember; + } + } + } + + List allArgs = new List(); + allArgs.AddRange(namedMembers); + if (positionalArgsMember != null) { + allArgs.Add(positionalArgsMember); + } + + ObjectNode result = new ObjectNode(); + result.Type = extensionType; + foreach (var arg in allArgs) { + result.MemberNodes.Add(arg); + //arg.ParentObject = result; + } + return result; + } + + static bool MapPositionalArgsToNamedMembers(Constructor ctor, List positionalArgValues, List namedMembers) + { + if (ctor.CorrespondingMembers != null) { + for (int i = 0; i < positionalArgValues.Count; i++) { + var memberNode = new MemberNode(); + memberNode.Member = ctor.CorrespondingMembers[i]; + memberNode.Values.Add(positionalArgValues[i]); + namedMembers.Add(memberNode); + } + return true; + } + return false; + } + + static Regex XamlNameRegex = new Regex(@"^[\w]*$"); + static Regex DottedXamlNameRegex = new Regex(@"^([\w]*)\.([\w]*)$"); + + static bool IsXamlName(XName name) + { + return XamlNameRegex.IsMatch(name.LocalName); + } + + static DottedXamlName GetDottedXamlName(XName name) + { + var m = DottedXamlNameRegex.Match(name.LocalName); + if (m.Success) { + return new DottedXamlName() { + TypeName = m.Groups[1].Value, + MemberName = m.Groups[2].Value + }; + } + return null; + } + + static PrefixedName GetPrefixedName(string s) + { + var result = new PrefixedName(); + var parts = s.Split(':'); + if (parts.Length == 1) { + result.LocalName = parts[0]; + } + else { + result.Prefix = parts[0]; + result.LocalName = parts[1]; + } + return result; + } + + public static bool IsCollapsibleChar(char c) + { + return char.IsWhiteSpace(c); + } + + public static bool IsCollapsibleString(string s) + { + return s == null || s.Trim().Length == 0; + } + + public static string CollapseWhitespace(string s) + { + StringBuilder b = new StringBuilder(s.Length); + bool firstSpace = true; + foreach (var c in s) { + if (char.IsWhiteSpace(c)) { + if (firstSpace) b.Append(" "); + firstSpace = false; + continue; + } + b.Append(c); + firstSpace = true; + } + return b.ToString(); + } + + static void AddText(IList convertedChildNodes, XNode node) + { + var xmlTextNode = node as XText; + if (xmlTextNode != null) { + TextNode textNode = null; + if (convertedChildNodes.Count > 0) { + textNode = convertedChildNodes[convertedChildNodes.Count - 1] as TextNode; + } + if (textNode != null) { + textNode.Text += xmlTextNode.Value; + } + else { + textNode = new TextNode() { Text = xmlTextNode.Value }; + convertedChildNodes.Add(textNode); + } + } + } + + class DottedXamlName + { + public string TypeName; + public string MemberName; + } + + class PrefixedName + { + public string Prefix; + public string LocalName; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlProject.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlProject.cs new file mode 100644 index 0000000000..9cb7d7fe53 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlProject.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System.Xml.Linq; +using System.Xml; +using System.IO; + +namespace ICSharpCode.Xaml +{ + public abstract class XamlProject + { + public XamlProject() + { + TypeFinder = new XamlTypeFinder(this); + } + + public XamlTypeFinder TypeFinder; + public XamlAssembly ProjectAssembly; + public XamlDocument ApplicationDefinition; + public List References = new List(); + public List Themes = new List(); + public Dictionary Documents = new Dictionary(); + + XmlResolver xmlResolver = new XmlUrlResolver(); + + public IEnumerable AllAssemblies + { + get + { + if (ProjectAssembly != null) { + yield return ProjectAssembly; + } + foreach (var a in References) { + yield return a; + } + } + } + + public XamlDocument LoadDocument(string uri) + { + var absoluteUri = xmlResolver.ResolveUri(null, uri); + XamlDocument doc; + if (!Documents.TryGetValue(absoluteUri, out doc)) { + doc = new XamlDocument(this); + var stream = (Stream)xmlResolver.GetEntity(absoluteUri, null, typeof(Stream)); + var text = new StreamReader(stream).ReadToEnd(); + doc.Parse(text); + doc.BaseUri = absoluteUri; + } + return doc; + } + + public XamlDocument ParseDocument(string text) + { + var doc = new XamlDocument(this); + doc.Parse(text); + return doc; + } + + public XamlDocument CreateDocument() + { + return new XamlDocument(this); + } + + public XamlDocument CreateDocument(object root) + { + var doc = new XamlDocument(this); + doc.Root = doc.CreateObject(root); + return doc; + } + + public void AddReference(Assembly assembly) + { + AddReference(ReflectionMapper.GetXamlAssembly(assembly)); + } + + public void AddReference(XamlAssembly xamlAssembly) + { + References.Add(xamlAssembly); + TypeFinder.RegisterAssembly(xamlAssembly); + } + + public void RemoveReference(Assembly assembly) + { + var xamlAssembly = ReflectionMapper.GetXamlAssembly(assembly); + References.Remove(xamlAssembly); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlProperty.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlProperty.cs new file mode 100644 index 0000000000..bf9bd1e506 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlProperty.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + public class XamlProperty : IHasAnnotations + { + internal XamlProperty(ObjectNode objectNode, XamlMember member) + { + this.objectNode = objectNode; + this.member = member; + this.context = new XamlContext(this); + } + + ObjectNode objectNode; + XamlMember member; + XamlContext context; + + public event EventHandler IsSetChanged; + public event EventHandler ValueChanged; + + public ObjectNode Object + { + get { return objectNode; } + } + + public XamlMember Member + { + get { return member; } + } + + public XamlContext XamlContext + { + get { return context; } + } + + public bool IsSet + { + get { return FindMemberNode() != null; } + } + + public XamlValue Value + { + get + { + var memberNode = FindMemberNode(); + if (memberNode != null) { + return memberNode.SingleValue; + } + return null; + } + } + + public XamlType ValueType + { + get + { + if (member == IntristicMember.InitializationText) { + return Object.Type; + } + return member.ValueType; + } + } + + public string ValueText + { + get + { + var textValue = Value as TextNode; + if (textValue != null) { + return textValue.Text; + } + return null; + } + } + + public object ValueOnInstance + { + get + { + // TODO: return real value + if (Member.IsEvent) { + return ValueText; + } + return Runtime.GetValue(Object.Instance, Member); + } + set + { + throw new NotImplementedException(); + } + } + + public NodeCollection Collection + { + get + { + var items = EnsureItems(); + if (items != null) { + return items.Values; + } + return null; + } + } + + public ObjectNode Add(object key, object value) + { + var newObject = AddObject(value); + newObject.Property(Directive.Key).Set(key); + return newObject; + } + + public ObjectNode AddObject(object value) + { + return Add(value) as ObjectNode; + } + + public XamlValue Add(object value) + { + var newValue = PrepareValueForCollection(value); + EnsureItems().Values.Add(newValue); + return newValue; + } + + public XamlValue Insert(int index, object value) + { + var newValue = PrepareValueForCollection(value); + EnsureItems().Values.Insert(index, newValue); + return newValue; + } + + public override string ToString() + { + return GetType().Name + ": " + Member.Name; + } + + public ObjectNode SetObject(object value) + { + return Set(value) as ObjectNode; + } + + public TextNode SetText(object value) + { + return Set(value) as TextNode; + } + + public XamlValue Set(object value) + { + if (member.ValueType.IsCollection && !member.ValueType.HasTextSyntax) { + return AddObject(value); + } + else { + var newValue = PrepareValue(value); + EnsureMemberNode().SingleValue = newValue; + return newValue; + } + } + + public void Reset() + { + var memberNode = FindMemberNode(); + if (memberNode != null) { + memberNode.Remove(); + } + } + + public XamlValue PrepareValue(object value) + { + if (value is XamlValue) { + return value as XamlValue; + } + if (value == null) { + return new ObjectNode(objectNode.Document, new NullExtension()); + } + + string text = value as string; + if (text == null) { + Runtime.TryConvertToText(context, value, out text); + } + if (text != null) { + var namespaceProvider = XmlTracker.GetNamespaceProvider(objectNode); + var valueNode = objectNode.Document.Parser.CreateValueFromAttributeText(text, namespaceProvider); + valueNode.Document = objectNode.Document; + return valueNode; + } + + return new ObjectNode(objectNode.Document, value); + } + + public XamlValue PrepareValueForCollection(object value) + { + var valueNode = PrepareValue(value); + var textNode = valueNode as TextNode; + if (textNode != null) { + var itemsNode = EnsureItems(); + if (itemsNode.ParentObject != null && + itemsNode.ParentObject.Type.ContentWrappers.Where( + t => t.ContentProperty != null && + t.ContentProperty.ValueType == IntristicType.String).Any()) { + return textNode; + } + + var wrapperType = Runtime.GetWrapperTypeForInitializationText(value); + var wrapperNode = new ObjectNode() { + Document = objectNode.Document, + Type = wrapperType, + Instance = value + }; + wrapperNode.InitializationText.Set(textNode); + return wrapperNode; + } + return valueNode; + } + + public MemberNode FindMemberNode() + { + return objectNode.FindMemberNode(member); + } + + public MemberNode EnsureMemberNode() + { + return objectNode.EnsureMemberNode(member); + } + + MemberNode EnsureItems() + { + if (member == IntristicMember.Items || + member == IntristicMember.ConsructorArgs || + member == IntristicMember.DirectiveChildren) { + return EnsureMemberNode(); + } + + var memberNode = EnsureMemberNode(); + if (memberNode.SingleValue == null) { + var collection = new ObjectNode() { + Document = objectNode.Document, + Type = member.ValueType, + IsRetrieved = true + }; + memberNode.SingleValue = collection; + } + return (memberNode.SingleValue as ObjectNode).EnsureMemberNode(IntristicMember.Items); + } + + #region IHasAnnotations Members + + Dictionary annotations = new Dictionary(); + + public void AnnotateWith(T annotation) where T : class + { + annotations[typeof(T)] = annotation; + } + + public T GetAnnotation() where T : class + { + object result; + if (annotations.TryGetValue(typeof(T), out result)) { + return (T)result; + } + return default(T); + } + + #endregion + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlType.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlType.cs new file mode 100644 index 0000000000..63c68eb76b --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlType.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using System.Windows.Markup; + +namespace ICSharpCode.Xaml +{ + public abstract class XamlType + { + public abstract string Name { get; } + public abstract bool IsDefaultConstructible { get; } + public abstract bool IsNullable { get; } + public abstract IEnumerable Members { get; } + public abstract XamlMember ContentProperty { get; } + public abstract XamlMember DictionaryKeyProperty { get; } + public abstract XamlMember NameProperty { get; } + public abstract XamlMember XmlLangProperty { get; } + public abstract bool TrimSurroundingWhitespace { get; } + public abstract bool IsWhitespaceSignificantCollection { get; } + public abstract bool IsCollection { get; } + public abstract bool IsDictionary { get; } + public abstract IEnumerable AllowedTypes { get; } + public abstract IEnumerable AllowedKeyTypes { get; } + public abstract bool IsXData { get; } + public abstract bool IsNameScope { get; } + public abstract IEnumerable Constructors { get; } + public abstract XamlType ReturnValueType { get; } + public abstract bool HasTextSyntax { get; } + + public abstract string Namespace { get; } + public abstract XamlAssembly Assembly { get; } + public abstract XamlMember Member(string name); + public abstract IEnumerable ContentWrappers { get; } + public abstract Type SystemType { get; } + + public abstract bool IsAssignableFrom(XamlType type); + public abstract T GetAttribute() where T : Attribute; + + public bool IsMarkupExtension + { + get { return IntristicType.MarkupExtension.IsAssignableFrom(this); } + } + + public override string ToString() + { + return GetType().Name + ": " + Name; + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlTypeFinder.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlTypeFinder.cs new file mode 100644 index 0000000000..353ee5e338 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlTypeFinder.cs @@ -0,0 +1,188 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Windows.Markup; +using System.Xml.Linq; + +namespace ICSharpCode.Xaml +{ + public class XamlTypeFinder + { + public XamlTypeFinder(XamlProject project) + { + Project = project; + } + + public XamlProject Project { get; private set; } + + Dictionary xamlNamespaces = new Dictionary(); + Dictionary xmlNamespaces = new Dictionary(); + + public XamlType FindType(XName name) + { + if (name == IntristicType.CodeName) return IntristicType.Code; + if (name == IntristicType.XDataName) return IntristicType.XData; + + return FindType(name, null); + } + + public XamlType FindExtensionType(XName name) + { + return FindType(name, "Extension"); + } + + XamlType FindType(XName name, string suffix) + { + XamlNamespace ns; + if (!xamlNamespaces.TryGetValue(name.Namespace, out ns)) { + var mapping = ParseMappingString(name.Namespace); + if (mapping != null) { + ns = new XamlNamespace() { XmlNamespace = name.Namespace }; + AddMapping(ns, mapping); + xamlNamespaces[name.Namespace] = ns; + } + else { + return null; + } + } + foreach (var mapping in ns.Mappings) { + var type = mapping.Assembly.GetType(mapping.ClrNamespace + "." + name.LocalName + suffix); + if (type != null) return type; + } + return null; + } + + public XNamespace GetXmlNamespaceForType(XamlType type) + { + Mapping mapping = new Mapping() { Assembly = type.Assembly, ClrNamespace = type.Namespace }; + XNamespace ns; + if (xmlNamespaces.TryGetValue(mapping, out ns)) { + return ns; + } + if (mapping.Assembly == null || mapping.Assembly == Project.ProjectAssembly) { + return "clr-namespace:" + mapping.ClrNamespace; + } + return "clr-namespace:" + mapping.ClrNamespace + ";assembly=" + mapping.Assembly.Name; + } + + public void RegisterAssembly(XamlAssembly assembly) + { + foreach (var def in assembly.XmlnsDefinitions) { + XamlNamespace ns; + if (!xamlNamespaces.TryGetValue(def.XmlNamespace, out ns)) { + ns = new XamlNamespace() { XmlNamespace = def.XmlNamespace }; + xamlNamespaces[ns.XmlNamespace] = ns; + } + //TODO def.AssemblyName + AddMapping(ns, new Mapping() { Assembly = assembly, ClrNamespace = def.ClrNamespace }); + } + } + + public void UnregisterAssembly(XamlAssembly assembly) + { + foreach (var ns in xamlNamespaces.Values) { + foreach (var mapping in ns.Mappings.ToArray()) { + if (mapping.Assembly == assembly) { + RemoveMapping(ns, mapping); + } + } + if (ns.Mappings.Count == 0) { + xamlNamespaces.Remove(ns.XmlNamespace); + } + } + } + + void AddMapping(XamlNamespace ns, Mapping mapping) + { + ns.Mappings.Add(mapping); + + // XamlWriter compares prefixes lengths (av < wpf, av < xps) + // but we want Presentation2007Namespace as default + XNamespace xmlns; + xmlNamespaces.TryGetValue(mapping, out xmlns); + if (xmlns != XamlConstants.Presentation2007Namespace) { + xmlNamespaces[mapping] = ns.XmlNamespace; + } + } + + void RemoveMapping(XamlNamespace ns, Mapping mapping) + { + ns.Mappings.Remove(mapping); + xmlNamespaces.Remove(mapping); + } + + Mapping ParseMappingString(XNamespace ns) + { + var text = ns.NamespaceName; + if (text.StartsWith("clr-namespace:")) { + var mapping = new Mapping(); + text = text.Substring("clr-namespace:".Length); + + int pos = text.IndexOf(';'); + if (pos < 0) { + mapping.ClrNamespace = text; + mapping.Assembly = FindAssembly(null); + } + else { + mapping.ClrNamespace = text.Substring(0, pos); + text = text.Substring(pos + 1).Trim(); + if (!text.StartsWith("assembly=")) { + throw new XamlException("Expected: 'assembly='"); + } + var assemblyName = text.Substring("assembly=".Length); + mapping.Assembly = FindAssembly(assemblyName); + } + return mapping; + } + return null; + } + + XamlAssembly FindAssembly(string name) + { + XamlAssembly result = null; + if (string.IsNullOrEmpty(name)) { + result = Project.ProjectAssembly; + } + else { + foreach (var a in Project.References) { + if (a.Name == name) { + result = a; + } + } + } + if (result != null) { + return result; + } + throw new XamlException(string.Format("Assembly '{0}' not found in project.", name)); + } + + class XamlNamespace + { + public XNamespace XmlNamespace; + public List Mappings = new List(); + } + + class Mapping : IEquatable + { + public XamlAssembly Assembly; + public string ClrNamespace; + + public override int GetHashCode() + { + return Assembly.GetHashCode() ^ ClrNamespace.GetHashCode(); + } + + public override bool Equals(object obj) + { + return Equals(obj as Mapping); + } + + public bool Equals(Mapping other) + { + return other != null && other.Assembly == this.Assembly && other.ClrNamespace == this.ClrNamespace; + } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlValue.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlValue.cs new file mode 100644 index 0000000000..6f9ce223b1 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlValue.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace ICSharpCode.Xaml +{ + public abstract class XamlValue : XamlNode + { + public object Instance; + + public MemberNode ParentMember + { + get { return ParentNode as MemberNode; } + } + + public ObjectNode ParentObject + { + get { return ParentMember != null ? ParentMember.ParentObject : null; } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XmlTracker.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XmlTracker.cs new file mode 100644 index 0000000000..eb7c8a9e01 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XmlTracker.cs @@ -0,0 +1,448 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using System.Xml.Linq; + +namespace ICSharpCode.Xaml +{ + class XmlTracker : Tracker + { + public override void Process(DocumentChangedEventArgs e) + { + if (e.OldNode != null) { + if (!TryUpdateMarkupExtension(e.OldParent)) { + Detach(e.OldNode, e.OldParent); + } + RemoveEmptyBranch(e.OldParent); + } + if (e.NewNode != null) { + if (!TryUpdateMarkupExtension(e.OldParent)) { + Attach(e.NewNode); + } + } + } + + static void Attach(XamlNode node) + { + var value = node as XamlValue; + if (value == null) return; + if (!node.InDocument) return; + + var objectNode = node as ObjectNode; + if (objectNode != null && objectNode.IsDocumentRoot) { + var doc = objectNode.Document; + if (doc.XmlDocument == null) { + doc.XmlDocument = new XDocument(); + } + PrintObject(objectNode, doc.XmlDocument, null, null); + return; + } + + if (!TryAttachUsingSiblings(value)) { + AttachUsingPrint(value); + } + } + + static void Detach(XamlNode node, XamlNode nodeParent) + { + if (node.XmlObject != null) { + RemoveXmlObject(node); + } + else { + if (nodeParent.InDocument) { + var currentXmlElement = nodeParent.FindAncestor(n => n.XmlObject != null).XmlObject as XElement; + if (currentXmlElement != null) { + currentXmlElement.RemoveNodes(); + } + } + } + } + + static bool TryAttachUsingSiblings(XamlValue value) + { + var values = value.ParentMember.Values; + if (values.Count > 1) { + var index = values.IndexOf(value); + if (index + 1 < values.Count) { + var before = values[index + 1].XmlObject as XNode; + PrintValue(value, null, null, before); + } + else { + var after = values[index - 1].XmlObject as XNode; + PrintValue(value, null, after, null); + } + return true; + } + return false; + } + + static void AttachUsingPrint(XamlValue value) + { + var memberNode = value.FindAncestor(n => n is MemberNode && + (n as MemberNode).ParentObject.XmlObject != null) as MemberNode; + // TODO: XamlNode.IsAttached + if (memberNode != null) { + PrintMember(memberNode, memberNode.ParentObject.XmlObject as XElement, null, null); + } + } + + static void RemoveEmptyBranch(XamlNode part) + { + XamlNode prev = null; + while (IsEmpty(part)) { + prev = part; + part = part.ParentNode; + } + if (prev != null) { + prev.Remove(); + } + } + + static bool IsEmpty(XamlNode node) + { + var objectNode = node as ObjectNode; + if (objectNode != null) { + if (objectNode.MemberNodes.Count == 0 && objectNode.IsRetrieved) { + return true; + } + } + else { + var memberNode = node as MemberNode; + if (memberNode != null) { + if (memberNode.Values.Count == 0) { + return true; + } + } + } + return false; + } + + static XName CreateMemberName(MemberNode node, bool forAttribute) + { + if (node.Member.IsDirective) { + return Directive.GetDirectiveName(node.Member); + } + var type = node.Member.OwnerType; + if (type.IsAssignableFrom(node.ParentObject.Type)) { + if (forAttribute) { + return node.Member.Name; + } + type = node.ParentObject.Type; + } + var dottedName = type.Name + "." + node.Member.Name; + var typeNamespace = node.Document.Project.TypeFinder.GetXmlNamespaceForType(type); + if (forAttribute) { + var xmlElement = node.FindAncestor(n => n.XmlObject is XElement).XmlObject as XElement; + if (typeNamespace == xmlElement.Name.Namespace) { + return dottedName; + } + } + return typeNamespace + dottedName; + } + + static XName CreateTypeName(ObjectNode node) + { + var typeNamespace = node.Document.Project.TypeFinder.GetXmlNamespaceForType(node.Type); + var typeName = node.Type.Name; + if (node.Type.IsMarkupExtension && typeName.EndsWith("Extension")) { + typeName = typeName.Substring(0, typeName.Length - "Extension".Length); + } + return typeNamespace + typeName; + } + + static bool TryPrintMarkupExtension(ObjectNode node, out string text) + { + text = null; + if (!node.Type.IsMarkupExtension) { + return false; + } + + StringBuilder sb = new StringBuilder(); + sb.Append("{"); + + var typeName = CreateTypeName(node); + //TODO + //var typePrefix = GetPrefixOfNamespace(node, typeName.Namespace); + //sb.Append(typePrefix + ":" + typeName.LocalName); + sb.Append(typeName.LocalName); + + List positionalValues = new List(); + var ctorArgs = node.FindMemberNode(IntristicMember.ConsructorArgs); + + if (ctorArgs != null) { + positionalValues.AddRange(ctorArgs.Values); + } + else { + var ctor = node.Type.Constructors.FirstOrDefault(); + if (ctor != null && ctor.CorrespondingMembers != null) { + foreach (var ctorMember in ctor.CorrespondingMembers) { + var ctorMemberNode = node.FindMemberNode(ctorMember); + if (ctorMemberNode == null || ctorMemberNode.SingleValue == null) { + positionalValues.Clear(); + break; + } + positionalValues.Add(ctorMemberNode.SingleValue); + } + } + } + + bool first = true; + HashSet printed = new HashSet(); + + if (positionalValues.Count > 0) { + foreach (var value in positionalValues) { + if (first) { + sb.Append(" "); + first = false; + } + else { + sb.Append(", "); + } + + string valueText; + if (!TryPrintMarkupExtensionValue(value, out valueText)) { + return false; + } + sb.Append(valueText); + + printed.Add(value.ParentMember); + } + } + + foreach (var memberNode in node.MemberNodes) { + if (printed.Contains(memberNode)) { + continue; + } + + if (first) { + sb.Append(" "); + first = false; + } + else { + sb.Append(", "); + } + + var memberName = CreateMemberName(memberNode, true); + sb.Append(memberName.LocalName); + + sb.Append("="); + + string valueText; + if (!TryPrintMarkupExtensionValue(memberNode.SingleValue, out valueText)) { + return false; + } + sb.Append(valueText); + } + + sb.Append("}"); + text = sb.ToString(); + return true; + } + + static bool TryPrintMarkupExtensionValue(XamlValue value, out string text) + { + text = null; + if (value is TextNode) { + text = (value as TextNode).Text; + } + else if (value is ObjectNode) { + if (!TryPrintMarkupExtension(value as ObjectNode, out text)) { + return false; + } + } + return true; + } + + static XNamespace GetPrefixOfNamespace(XamlNode node, XNamespace ns) + { + var xmlElement = node.FindAncestor(n => n.XmlObject is XElement).XmlObject as XElement; + return xmlElement.GetPrefixOfNamespace(ns); + } + + static bool TryUpdateMarkupExtension(XamlNode node) + { + MemberNode root = null; + while (node != null) { + MemberNode memberNode = node as MemberNode; + if (memberNode != null) { + var markupExtensionNode = memberNode.SingleValue as ObjectNode; + if (markupExtensionNode != null && markupExtensionNode.Type.IsMarkupExtension) { + root = memberNode; + } + } + node = node.ParentNode; + } + + if (root != null) { + string text; + if (TryPrintMarkupExtension(root.SingleValue as ObjectNode, out text)) { + EnsureXmlAttribute(root, root.ParentObject.XmlObject as XElement).Value = text; + foreach (var descendant in root.Descendants()) { + descendant.XmlObject = null; + } + return true; + } + } + + return false; + } + + static void PrintObject(ObjectNode node, XContainer currentXmlContainer, XNode after, XNode before) + { + if (node.IsRetrieved) { + foreach (var memberNode in node.MemberNodes) { + PrintMember(memberNode, currentXmlContainer as XElement, after, before); + } + } + else { + if (node.XmlObject == null) { + var typeFinder = node.Document.Project.TypeFinder; + var xmlElement = new XElement(typeFinder.GetXmlNamespaceForType(node.Type) + node.Type.Name); + node.XmlObject = xmlElement; + + // preserve usual namespaces + if (node.IsDocumentRoot) { + xmlElement.Add(new XAttribute("xmlns", xmlElement.Name.Namespace)); + xmlElement.Add(new XAttribute(XNamespace.Xmlns + "x", XamlConstants.XamlNamespace)); + } + + AddXmlObject(node, currentXmlContainer, after, before); + + foreach (var memberNode in node.MemberNodes) { + PrintMember(memberNode, xmlElement, after, before); + } + } + else { + AddXmlObject(node, currentXmlContainer, after, before); + } + } + } + + static void PrintMember(MemberNode node, XElement currentXmlElement, XNode after, XNode before) + { + if (node.SingleValue is TextNode && node.Member != IntristicMember.Items) { + if (node.Member == IntristicMember.InitializationText) { + PrintValue(node.SingleValue, currentXmlElement, after, before); + } + else { + EnsureXmlAttribute(node, currentXmlElement).Value = (node.SingleValue as TextNode).Text; + } + } + else { + var me = node.SingleValue as ObjectNode; + if (me != null && me.Type.IsMarkupExtension) { + string text; + if (TryPrintMarkupExtension(me, out text)) { + EnsureXmlAttribute(node, currentXmlElement).Value = text; + return; + } + } + var xmlElement = EnsureXmlElement(node, currentXmlElement); + foreach (var value in node.Values) { + PrintValue(value, xmlElement, after, before); + } + } + } + + static void PrintValue(XamlValue value, XElement currentXmlElement, XNode after, XNode before) + { + var textNode = value as TextNode; + if (textNode != null) { + var text = textNode.Text; + textNode.XmlObject = new XText(text); + AddXmlObject(textNode, currentXmlElement, after, before); + + if (text.StartsWith(" ") || text.EndsWith(" ")) { + var xmlElement = currentXmlElement ?? (after != null ? after.Parent : null) ?? before.Parent; + xmlElement.SetAttributeValue(XamlConstants.XmlSpaceName, "preserve"); + } + } + else { + PrintObject(value as ObjectNode, currentXmlElement, after, before); + } + } + + static void AddXmlObject(XamlNode node, XContainer currentXmlContainer, XNode after, XNode before) + { + if (after != null) { + after.AddAfterSelf(node.XmlObject); + } + else if (before != null) { + before.AddBeforeSelf(node.XmlObject); + } + else if (node.XmlObject.Document == null) { + currentXmlContainer.Add(node.XmlObject); + } + } + + static void RemoveXmlObject(XamlNode node) + { + if (node.XmlObject is XAttribute) { + (node.XmlObject as XAttribute).Remove(); + node.XmlObject = null; + } + else if (node.XmlObject is XNode) { + (node.XmlObject as XNode).Remove(); + } + //node.XmlObject = null; + } + + static XAttribute EnsureXmlAttribute(MemberNode node, XElement currentXmlElement) + { + var xmlAttribute = node.XmlObject as XAttribute; + if (xmlAttribute == null) { + if (node.XmlObject != null) { + RemoveXmlObject(node); + } + else if (IsContent(node)) { + currentXmlElement.RemoveNodes(); + } + + xmlAttribute = new XAttribute(CreateMemberName(node, true), ""); + currentXmlElement.Add(xmlAttribute); + node.XmlObject = xmlAttribute; + } + return xmlAttribute; + } + + static XElement EnsureXmlElement(MemberNode node, XElement currentXmlElement) + { + var xmlElement = node.XmlObject as XElement; + if (xmlElement == null) { + if (node.XmlObject != null) { + RemoveXmlObject(node); + } + if (IsContent(node)) { + return currentXmlElement; + } + + xmlElement = new XElement(CreateMemberName(node, false)); + currentXmlElement.AddFirst(xmlElement); + node.XmlObject = xmlElement; + } + return xmlElement; + } + + static bool IsContent(MemberNode node) + { + return + node.Member == node.ParentObject.Type.ContentProperty || + node.Member == IntristicMember.Items || + node.Member == IntristicMember.InitializationText; + } + + public static XElement GetNamespaceProvider(ObjectNode node) + { + var nodeWithXmlElement = node.FindAncestor(n => n.XmlObject is XElement); + if (nodeWithXmlElement != null) { + return (nodeWithXmlElement.XmlObject as XElement); + } + if (node.Document.XmlDocument != null && node.Document.XmlDocument.Root != null) { + return node.Document.XmlDocument.Root; + } + return new XElement("Empty"); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XmlnsDefinition.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XmlnsDefinition.cs new file mode 100644 index 0000000000..a68d237af6 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XmlnsDefinition.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.Xaml +{ + class XmlnsDefinition + { + } +} diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/XamlBinding.Tests.csproj b/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/XamlBinding.Tests.csproj new file mode 100644 index 0000000000..22bfabc1eb --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/XamlBinding.Tests.csproj @@ -0,0 +1,75 @@ + + + {F390DA70-1FE1-4715-81A0-389AB010C130} + Debug + AnyCPU + Library + ICSharpCode.XamlBinding.Tests + ICSharpCode.XamlBinding.Tests + v3.5 + Properties + C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis + ..\..\..\..\..\bin\UnitTests\ + False + False + 4 + false + + + true + Full + False + True + DEBUG;TRACE + + + False + None + True + False + TRACE + + + False + Auto + 4194304 + AnyCPU + 4096 + + + + + ..\..\..\..\Tools\NUnit\nunit.framework.dll + False + + + + 3.5 + + + + 3.5 + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3} + ICSharpCode.SharpDevelop.Dom + + + {6B717BD1-CD5E-498C-A42E-9E6A4584DC48} + XmlEditor + + + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8} + XamlBinding + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/XamlExpressionFinderTests.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/XamlExpressionFinderTests.cs new file mode 100644 index 0000000000..46572b69ec --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/XamlExpressionFinderTests.cs @@ -0,0 +1,48 @@ +// +// +// +// +// $Revision: 3494 $ +// + + +using ICSharpCode.SharpDevelop.Dom; +using System; +using NUnit.Framework; +using NUnit.Framework.SyntaxHelpers; + +namespace ICSharpCode.XamlBinding.Tests +{ + [TestFixture] + public class XamlExpressionFinderTests + { + XamlExpressionContext GetXamlContext(string text) + { + return (XamlExpressionContext)GetContext(text); + } + + ExpressionContext GetContext(string text) + { + return XamlExpressionFinder.Instance.FindExpression(text, text.Length).Context; + } + + [Test] + public void FindContextAfterElementName() + { + XamlExpressionContext c = GetXamlContext(" Grid", c.ElementPath.ToString()); + Assert.IsNull(c.AttributeName); + Assert.IsFalse(c.InAttributeValue); + } + + [Test] + public void FindContextAtElementStart() + { + XamlExpressionContext c = GetXamlContext("<"); + Assert.AreEqual(0, c.ElementPath.Elements.Count); + Assert.IsNull(c.AttributeName); + Assert.IsFalse(c.InAttributeValue); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlBinding.addin b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlBinding.addin new file mode 100644 index 0000000000..f287e47386 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlBinding.addin @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlBinding.csproj b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlBinding.csproj new file mode 100644 index 0000000000..1785e60230 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlBinding.csproj @@ -0,0 +1,96 @@ + + + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8} + Debug + AnyCPU + Library + ICSharpCode.XamlBinding + ICSharpCode.XamlBinding + ..\..\..\..\..\AddIns\AddIns\BackendBindings\XamlBinding + False + False + 4 + false + C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis + v3.5 + + + true + Full + True + DEBUG;TRACE + False + + + False + None + False + TRACE + + + False + Auto + 4194304 + AnyCPU + 4096 + + + + + + 3.5 + + + + + + + + Always + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} + ICSharpCode.TextEditor + False + + + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} + NRefactory + False + + + {2748AD25-9C63-4E12-877B-4DCE96FBED54} + ICSharpCode.SharpDevelop + False + + + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} + ICSharpCode.Core + False + + + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3} + ICSharpCode.SharpDevelop.Dom + False + + + {6B717BD1-CD5E-498C-A42E-9E6A4584DC48} + XmlEditor + False + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlClassReturnType.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlClassReturnType.cs new file mode 100644 index 0000000000..a714e4aa53 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlClassReturnType.cs @@ -0,0 +1,45 @@ +// +// +// +// +// $Revision: 2569 $ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.XamlBinding +{ + /// + /// Description of XamlClassReturnType. + /// + public class XamlClassReturnType : ProxyReturnType + { + XamlCompilationUnit compilationUnit; + string xmlNamespace; + string className; + + public XamlClassReturnType(XamlCompilationUnit compilationUnit, string xmlNamespace, string className) + { + if (compilationUnit == null) + throw new ArgumentNullException("compilationUnit"); + + this.compilationUnit = compilationUnit; + this.xmlNamespace = xmlNamespace; + this.className = className ?? ""; + } + + public override IReturnType BaseType + { + get + { + return compilationUnit.FindType(xmlNamespace, className); + } + } + + public override string Name + { + get { return className; } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlCodeCompletionBinding.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlCodeCompletionBinding.cs new file mode 100644 index 0000000000..56f319f910 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlCodeCompletionBinding.cs @@ -0,0 +1,102 @@ +// +// +// +// +// $Revision: 3494 $ +// + +using ICSharpCode.SharpDevelop.Gui; +using System; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.TextEditor.Gui.CompletionWindow; +using ICSharpCode.XmlEditor; + +namespace ICSharpCode.XamlBinding +{ + public class XamlCodeCompletionBinding : ICodeCompletionBinding + { + public bool HandleKeyPress(SharpDevelopTextAreaControl editor, char ch) + { + if (ch == '<') { + editor.ShowCompletionWindow(new XamlCompletionDataProvider(XamlExpressionContext.Empty), ch); + return true; + } + else if (char.IsLetter(ch)) { + int offset = editor.ActiveTextAreaControl.TextArea.Caret.Offset; + if (offset > 0) { + char c = editor.Document.GetCharAt(offset - 1); + if (c == ' ' || c == '\t') { + XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(editor.Text, offset); + if (path != null && path.Elements.Count > 0) { + editor.ShowCompletionWindow( + new XamlCompletionDataProvider( + new XamlExpressionContext(path, "", false) + ) { IsAttributeCompletion = true } + , '\0'); + return false; + } + } + } + } + return false; + } + + public bool CtrlSpace(SharpDevelopTextAreaControl editor) + { + XamlCompletionDataProvider provider = new XamlCompletionDataProvider(); + provider.AllowCompleteExistingExpression = true; + editor.ShowCompletionWindow(provider, '\0'); + return true; + } + } + + sealed class XamlCompletionDataProvider : CtrlSpaceCompletionDataProvider + { + public XamlCompletionDataProvider() + { + } + + public XamlCompletionDataProvider(ExpressionContext overrideContext) + : base(overrideContext) + { + } + + public override CompletionDataProviderKeyResult ProcessKey(char key) + { + if (key == ':' || key == '.') { + return CompletionDataProviderKeyResult.NormalKey; + } + else { + return base.ProcessKey(key); + } + } + + public bool IsAttributeCompletion; + + public override bool InsertAction(ICompletionData data, ICSharpCode.TextEditor.TextArea textArea, int insertionOffset, char key) + { + CodeCompletionData ccData = data as CodeCompletionData; + if (IsAttributeCompletion && ccData != null) { + textArea.Caret.Position = textArea.Document.OffsetToPosition(insertionOffset); + textArea.InsertString(ccData.Text + "=\"\""); + textArea.Caret.Column -= 1; + + SharpDevelopTextAreaControl editor = textArea.MotherTextEditorControl as SharpDevelopTextAreaControl; + if (editor != null) { + WorkbenchSingleton.SafeThreadAsyncCall( + delegate { + XamlCompletionDataProvider provider = new XamlCompletionDataProvider(); + provider.AllowCompleteExistingExpression = true; + editor.ShowCompletionWindow(provider, '\0'); + } + ); + } + return false; + } + else { + return base.InsertAction(data, textArea, insertionOffset, key); + } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlCompilationUnit.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlCompilationUnit.cs new file mode 100644 index 0000000000..2e2e62de89 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlCompilationUnit.cs @@ -0,0 +1,128 @@ +// +// +// +// +// $Revision: 3494 $ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using System.Collections; +using System.Collections.Generic; + +namespace ICSharpCode.XamlBinding +{ + /// + /// Description of XamlCompilationUnit. + /// + public class XamlCompilationUnit : DefaultCompilationUnit + { + public XamlCompilationUnit(IProjectContent projectContent) + : base(projectContent) + { + } + + public IReturnType CreateType(string xmlNamespace, string className) + { + if (xmlNamespace.StartsWith("clr-namespace:")) { + return CreateClrNamespaceType(this.ProjectContent, xmlNamespace, className); + } + else { + return new XamlClassReturnType(this, xmlNamespace, className); + } + } + + static IReturnType CreateClrNamespaceType(IProjectContent pc, string xmlNamespace, string className) + { + string namespaceName = GetNamespaceNameFromClrNamespace(xmlNamespace); + return new GetClassReturnType(pc, namespaceName + "." + className, 0); + } + + static string GetNamespaceNameFromClrNamespace(string xmlNamespace) + { + string namespaceName = xmlNamespace.Substring("clr-namespace:".Length); + int pos = namespaceName.IndexOf(';'); + if (pos >= 0) { + // we expect that the target type is also a reference of the project, so we + // can ignore the assembly part after the ; + namespaceName = namespaceName.Substring(0, pos); + } + return namespaceName; + } + + public IReturnType FindType(string xmlNamespace, string className) + { + return FindType(this.ProjectContent, xmlNamespace, className); + } + + public static IReturnType FindType(IProjectContent pc, string xmlNamespace, string className) + { + if (pc == null) + throw new ArgumentNullException("pc"); + if (xmlNamespace == null || className == null) + return null; + if (xmlNamespace.StartsWith("clr-namespace:")) { + return CreateClrNamespaceType(pc, xmlNamespace, className); + } + else { + IReturnType type = FindTypeInAssembly(pc, xmlNamespace, className); + if (type != null) + return type; + foreach (IProjectContent p in pc.ReferencedContents) { + type = FindTypeInAssembly(p, xmlNamespace, className); + if (type != null) + return type; + } + return null; + } + } + + static IReturnType FindTypeInAssembly(IProjectContent projectContent, string xmlNamespace, string className) + { + foreach (IAttribute att in projectContent.GetAssemblyAttributes()) { + if (att.PositionalArguments.Count == 2 + && att.AttributeType.FullyQualifiedName == "System.Windows.Markup.XmlnsDefinitionAttribute") { + string namespaceName = att.PositionalArguments[1] as string; + if (xmlNamespace.Equals(att.PositionalArguments[0]) && namespaceName != null) { + IClass c = projectContent.GetClass(namespaceName + "." + className, 0); + if (c != null) + return c.DefaultReturnType; + } + } + } + return null; + } + + public static ArrayList GetNamespaceMembers(IProjectContent pc, string xmlNamespace) + { + if (pc == null) + throw new ArgumentNullException("pc"); + if (xmlNamespace == null) + return null; + if (xmlNamespace.StartsWith("clr-namespace:")) { + return pc.GetNamespaceContents(GetNamespaceNameFromClrNamespace(xmlNamespace)); + } + else { + ArrayList list = new ArrayList(); + AddNamespaceMembersInAssembly(pc, xmlNamespace, list); + foreach (IProjectContent p in pc.ReferencedContents) { + AddNamespaceMembersInAssembly(p, xmlNamespace, list); + } + return list; + } + } + + static void AddNamespaceMembersInAssembly(IProjectContent projectContent, string xmlNamespace, ArrayList list) + { + foreach (IAttribute att in projectContent.GetAssemblyAttributes()) { + if (att.PositionalArguments.Count == 2 + && att.AttributeType.FullyQualifiedName == "System.Windows.Markup.XmlnsDefinitionAttribute") { + string namespaceName = att.PositionalArguments[1] as string; + if (xmlNamespace.Equals(att.PositionalArguments[0]) && namespaceName != null) { + projectContent.AddNamespaceContents(list, namespaceName, projectContent.Language, false); + } + } + } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlExpressionContext.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlExpressionContext.cs new file mode 100644 index 0000000000..bb27bf1e29 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlExpressionContext.cs @@ -0,0 +1,63 @@ +// +// +// +// +// $Revision: 3494 $ +// + +using System; +using System.Text; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.XmlEditor; + +namespace ICSharpCode.XamlBinding +{ + /// + /// Represents the context of a location in a XAML document. + /// + public sealed class XamlExpressionContext : ExpressionContext + { + public static readonly XamlExpressionContext Empty = new XamlExpressionContext(new XmlElementPath(), null, false); + + public readonly XmlElementPath ElementPath; + public readonly string AttributeName; + public readonly bool InAttributeValue; + + public XamlExpressionContext(XmlElementPath elementPath, string attributeName, bool inAttributeValue) + { + if (elementPath == null) + throw new ArgumentNullException("elementPath"); + this.ElementPath = elementPath; + this.AttributeName = attributeName; + this.InAttributeValue = inAttributeValue; + } + + public override bool ShowEntry(object o) + { + return true; + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append("[XamlExpressionContext "); + for (int i = 0; i < ElementPath.Elements.Count; i++) { + if (i > 0) b.Append(">"); + if (!string.IsNullOrEmpty(ElementPath.Elements[i].Prefix)) { + b.Append(ElementPath.Elements[i].Prefix); + b.Append(':'); + } + b.Append(ElementPath.Elements[i].Name); + } + if (AttributeName != null) { + b.Append(" AttributeName="); + b.Append(AttributeName); + if (InAttributeValue) { + b.Append(" InAttributeValue"); + } + } + b.Append("]"); + return b.ToString(); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlExpressionFinder.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlExpressionFinder.cs new file mode 100644 index 0000000000..6b7cd8c52c --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlExpressionFinder.cs @@ -0,0 +1,75 @@ +// +// +// +// +// $Revision: 3494 $ +// + +using System; +using System.Text; +using System.Xml; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.XmlEditor; + +namespace ICSharpCode.XamlBinding +{ + /// + /// Description of XamlExpressionFinder. + /// + public class XamlExpressionFinder : IExpressionFinder + { + public static readonly XamlExpressionFinder Instance = new XamlExpressionFinder(); + + bool IsValidChar(char c) + { + return char.IsLetterOrDigit(c) || c == '_' || c == ':' || c == '.'; + } + + public ExpressionResult FindExpression(string text, int offset) + { + int pos = offset - 1; + while (pos > 0 && IsValidChar(text[pos])) { + pos--; + } + pos++; + return new ExpressionResult(text.Substring(pos, offset - pos), GetContext(text, offset)); + } + + public ExpressionResult FindFullExpression(string text, int offset) + { + int start = offset - 1; + while (start > 0 && IsValidChar(text[start])) { + start--; + } + start++; + while (offset < text.Length && IsValidChar(text[offset])) { + offset++; + } + return new ExpressionResult(text.Substring(start, offset - start), GetContext(text, offset)); + } + + public string RemoveLastPart(string expression) + { + return ""; + } + + ExpressionContext GetContext(string text, int offset) + { + XmlElementPath path = XmlParser.GetActiveElementStartPathAtIndex(text, offset); + if (path == null || path.Elements.Count == 0) { + if (offset > 0 && text[offset - 1] == '<') + return XamlExpressionContext.Empty; + else + return ExpressionContext.Default; + } + string attributeName = XmlParser.GetAttributeNameAtIndex(text, offset); + if (!string.IsNullOrEmpty(attributeName)) { + return new XamlExpressionContext(path, attributeName, XmlParser.IsInsideAttributeValue(text, offset)); + } + else { + return new XamlExpressionContext(path, null, false); + } + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlParser.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlParser.cs new file mode 100644 index 0000000000..9db1a5aff3 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlParser.cs @@ -0,0 +1,151 @@ +// +// +// +// +// $Revision: 2568 $ +// + +using System; +using System.Diagnostics; +using System.IO; +using System.Xml; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.XamlBinding +{ + /// + /// Parses xaml files to partial classes for the Dom. + /// + public class XamlParser : IParser + { + string[] lexerTags; + + public string[] LexerTags + { + get + { + return lexerTags; + } + set + { + lexerTags = value; + } + } + + public LanguageProperties Language + { + get + { + return LanguageProperties.CSharp; + } + } + + public bool CanParse(string fileName) + { + return Path.GetExtension(fileName).Equals(".xaml", StringComparison.InvariantCultureIgnoreCase); + } + + public bool CanParse(ICSharpCode.SharpDevelop.Project.IProject project) + { + return false; + } + + const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; + + public ICompilationUnit Parse(IProjectContent projectContent, string fileName, string fileContent) + { + XamlCompilationUnit cu = new XamlCompilationUnit(projectContent); + cu.FileName = fileName; + try { + using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) { + r.WhitespaceHandling = WhitespaceHandling.Significant; + r.Read(); + r.MoveToContent(); + DomRegion classStart = new DomRegion(r.LineNumber, r.LinePosition - 1); + string className = r.GetAttribute("Class", XamlNamespace); + if (string.IsNullOrEmpty(className)) { + LoggingService.Debug("XamlParser: returning empty cu because root element has no Class attribute"); + } + else { + DefaultClass c = new DefaultClass(cu, className); + c.Modifiers = ModifierEnum.Partial; + c.Region = classStart; + c.BaseTypes.Add(TypeFromXmlNode(cu, r)); + cu.Classes.Add(c); + + DefaultMethod initializeComponent = new DefaultMethod( + "InitializeComponent", + projectContent.SystemTypes.Void, + ModifierEnum.Public | ModifierEnum.Synthetic, + classStart, DomRegion.Empty, + c); + c.Methods.Add(initializeComponent); + + ParseXamlElement(cu, c, r); + if (r.NodeType == XmlNodeType.EndElement) { + c.Region = new DomRegion(classStart.BeginLine, classStart.BeginColumn, r.LineNumber, r.LinePosition + r.Name.Length); + } + } + } + } + catch (XmlException ex) { + LoggingService.Debug("XamlParser exception: " + ex.ToString()); + cu.ErrorsDuringCompile = true; + } + return cu; + } + + IReturnType TypeFromXmlNode(XamlCompilationUnit cu, XmlReader r) + { + return cu.CreateType(r.NamespaceURI, r.LocalName); + } + + void ParseXamlElement(XamlCompilationUnit cu, DefaultClass c, XmlTextReader r) + { + Debug.Assert(r.NodeType == XmlNodeType.Element); + string name = r.GetAttribute("Name", XamlNamespace) ?? r.GetAttribute("Name"); + bool isEmptyElement = r.IsEmptyElement; + + if (!string.IsNullOrEmpty(name)) { + IReturnType type = TypeFromXmlNode(cu, r); + + // Use position of Name attribute for field region + //if (!r.MoveToAttribute("Name", XamlNamespace)) { + // r.MoveToAttribute("Name"); + //} + DomRegion position = new DomRegion(r.LineNumber, r.LinePosition, r.LineNumber, r.LinePosition + name.Length); + c.Fields.Add(new DefaultField(type, name, ModifierEnum.Internal, position, c)); + } + + if (isEmptyElement) + return; + while (r.Read()) { + if (r.NodeType == XmlNodeType.Element) { + ParseXamlElement(cu, c, r); + } + else if (r.NodeType == XmlNodeType.Comment) { + foreach (string tag in lexerTags) { + if (r.Value.Contains(tag)) { + cu.TagComments.Add(new TagComment(r.Value, new DomRegion(r.LineNumber, r.LinePosition, r.LineNumber, r.LinePosition + r.Value.Length))); + break; + } + } + } + else if (r.NodeType == XmlNodeType.EndElement) { + break; + } + } + } + + public IExpressionFinder CreateExpressionFinder(string fileName) + { + return XamlExpressionFinder.Instance; + } + + public IResolver CreateResolver() + { + return new XamlResolver(); + } + } +} diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlResolver.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlResolver.cs new file mode 100644 index 0000000000..7aadbbb35a --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/XamlResolver.cs @@ -0,0 +1,349 @@ +// +// +// +// +// $Revision: 3539 $ +// + +using ICSharpCode.XmlEditor; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.XamlBinding +{ + /// + /// Description of XamlResolver. + /// + public class XamlResolver : IResolver + { + IClass callingClass; + string resolveExpression; + XamlExpressionContext context; + ParseInformation parseInfo; + int caretLineNumber, caretColumn; + + bool IsReaderAtTarget(XmlTextReader r) + { + if (r.LineNumber > caretLineNumber) + return true; + else if (r.LineNumber == caretLineNumber) + return r.LinePosition >= caretColumn; + else + return false; + } + + public ResolveResult Resolve(ExpressionResult expressionResult, ParseInformation parseInfo, string fileContent) + { + this.resolveExpression = expressionResult.Expression; + this.parseInfo = parseInfo; + this.caretLineNumber = expressionResult.Region.BeginLine; + this.caretColumn = expressionResult.Region.BeginColumn; + this.callingClass = parseInfo.BestCompilationUnit.GetInnermostClass(caretLineNumber, caretColumn); + this.context = expressionResult.Context as XamlExpressionContext; + if (context == null) + return null; + try { + using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) { + r.WhitespaceHandling = WhitespaceHandling.Significant; + // move reader to correct position + while (r.Read() && !IsReaderAtTarget(r)) { } + + if (string.IsNullOrEmpty(context.AttributeName)) { + return ResolveElementName(r); + } + else if (context.InAttributeValue) { + MemberResolveResult mrr = ResolveAttribute(r, context.AttributeName); + if (mrr != null) { + return ResolveAttributeValue(mrr.ResolvedMember, resolveExpression); + } + } + else { + // in attribute name + return ResolveAttribute(r, resolveExpression); + } + } + return null; + } + catch (XmlException) { + return null; + } + } + + ResolveResult ResolveElementName(XmlReader r) + { + string xmlNamespace; + string name; + if (resolveExpression.Contains(":")) { + string prefix = resolveExpression.Substring(0, resolveExpression.IndexOf(':')); + name = resolveExpression.Substring(resolveExpression.IndexOf(':') + 1); + xmlNamespace = r.LookupNamespace(prefix); + } + else { + xmlNamespace = r.LookupNamespace(""); + name = resolveExpression; + } + if (name.Contains(".")) { + string propertyName = name.Substring(name.IndexOf('.') + 1); + name = name.Substring(0, name.IndexOf('.')); + return ResolveProperty(xmlNamespace, name, propertyName, true); + } + else { + IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent; + IReturnType resolvedType = XamlCompilationUnit.FindType(pc, xmlNamespace, name); + IClass resolvedClass = resolvedType != null ? resolvedType.GetUnderlyingClass() : null; + if (resolvedClass != null) { + return new TypeResolveResult(callingClass, null, resolvedClass); + } + else { + return null; + } + } + } + + MemberResolveResult ResolveProperty(string xmlNamespace, string className, string propertyName, bool allowAttached) + { + IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent; + IReturnType resolvedType = XamlCompilationUnit.FindType(pc, xmlNamespace, className); + if (resolvedType != null && resolvedType.GetUnderlyingClass() != null) { + IMember member = resolvedType.GetProperties().Find(delegate(IProperty p) { return p.Name == propertyName; }); + if (member == null) { + member = resolvedType.GetEvents().Find(delegate(IEvent p) { return p.Name == propertyName; }); + } + if (member == null && allowAttached) { + member = resolvedType.GetMethods().Find( + delegate(IMethod p) { + return p.IsStatic && p.Parameters.Count == 1 && p.Name == "Get" + propertyName; + }); + } + if (member != null) + return new MemberResolveResult(callingClass, null, member); + } + return null; + } + + MemberResolveResult ResolveAttribute(XmlReader r, string attributeName) + { + if (context.ElementPath.Elements.Count == 0) { + return null; + } + string attributeXmlNamespace; + if (attributeName.Contains(":")) { + attributeXmlNamespace = r.LookupNamespace(attributeName.Substring(0, attributeName.IndexOf(':'))); + attributeName = attributeName.Substring(attributeName.IndexOf(':') + 1); + } + else { + attributeXmlNamespace = r.LookupNamespace(""); + } + if (attributeName.Contains(".")) { + string className = attributeName.Substring(0, attributeName.IndexOf('.')); + attributeName = attributeName.Substring(attributeName.IndexOf('.') + 1); + return ResolveProperty(attributeXmlNamespace, className, attributeName, true); + } + else { + ICSharpCode.XmlEditor.QualifiedName lastElement = context.ElementPath.Elements[context.ElementPath.Elements.Count - 1]; + return ResolveProperty(lastElement.Namespace, lastElement.Name, attributeName, false); + } + } + + ResolveResult ResolveAttributeValue(IMember propertyOrEvent, string expression) + { + if (propertyOrEvent == null) + return null; + if (propertyOrEvent is IEvent) { + return new MethodGroupResolveResult(callingClass, null, callingClass.DefaultReturnType, expression); + } + + if (propertyOrEvent.Name == "Name" && callingClass != null) { + foreach (IField f in callingClass.Fields) { + if (f.Name == expression) + return new MemberResolveResult(callingClass, null, f); + } + } + + IReturnType type = propertyOrEvent.ReturnType; + if (type == null) return null; + IClass c = type.GetUnderlyingClass(); + if (c == null) return null; + + if (c.ClassType == ClassType.Enum) { + foreach (IField f in c.Fields) { + if (f.Name == expression) + return new MemberResolveResult(callingClass, null, f); + } + } + return null; + } + + public ArrayList CtrlSpace(int caretLineNumber, int caretColumn, ParseInformation parseInfo, string fileContent, ExpressionContext expressionContext) + { + this.parseInfo = parseInfo; + this.caretLineNumber = caretLineNumber; + this.caretColumn = caretColumn; + this.callingClass = parseInfo.BestCompilationUnit.GetInnermostClass(caretLineNumber, caretColumn); + this.context = expressionContext as XamlExpressionContext; + if (context == null) { + return null; + } + + if (context.AttributeName == null) { + return CtrlSpaceForElement(fileContent); + } + else if (context.InAttributeValue) { + return CtrlSpaceForAttributeValue(fileContent, context); + } + else { + return CtrlSpaceForAttributeName(fileContent, context); + } + } + + ArrayList CtrlSpaceForAttributeName(string fileContent, XamlExpressionContext context) + { + if (context.ElementPath.Elements.Count == 0) + return null; + QualifiedName lastElement = context.ElementPath.Elements[context.ElementPath.Elements.Count - 1]; + XamlCompilationUnit cu = parseInfo.BestCompilationUnit as XamlCompilationUnit; + if (cu == null) + return null; + IReturnType rt = cu.CreateType(lastElement.Namespace, lastElement.Name); + if (rt == null) + return null; + ArrayList list = new ArrayList(); + foreach (IProperty p in rt.GetProperties()) { + if (p.IsPublic && p.CanSet) { + list.Add(p); + } + } + return list; + } + + ArrayList CtrlSpaceForAttributeValue(string fileContent, XamlExpressionContext context) + { + ArrayList attributes = CtrlSpaceForAttributeName(fileContent, context); + if (attributes != null) { + foreach (IProperty p in attributes.OfType()) { + if (p.Name == context.AttributeName && p.ReturnType != null) { + IClass c = p.ReturnType.GetUnderlyingClass(); + if (c != null && c.ClassType == ClassType.Enum) { + return EnumCompletion(c); + } + } + } + } + return null; + } + + ArrayList EnumCompletion(IClass enumClass) + { + ArrayList arr = new ArrayList(); + foreach (IField f in enumClass.Fields) { + arr.Add(f); + } + return arr; + } + + ArrayList CtrlSpaceForElement(string fileContent) + { + using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) { + try { + r.WhitespaceHandling = WhitespaceHandling.Significant; + // move reader to correct position + while (r.Read() && !IsReaderAtTarget(r)) { } + } + catch (XmlException) { + } + ArrayList result = new ArrayList(); + IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent; + + resolveExpression = r.Name; + TypeResolveResult rr = ResolveElementName(r) as TypeResolveResult; + if (rr != null) { + AddPropertiesForType(result, r, rr); + } + + foreach (var ns in r.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml)) { + ArrayList list = XamlCompilationUnit.GetNamespaceMembers(pc, ns.Value); + if (list != null) { + foreach (IClass c in list.OfType()) { + if (c.ClassType != ClassType.Class) + continue; + if (c.IsAbstract && c.IsStatic) + continue; + if (c.ClassInheritanceTree.Any(b => b.FullyQualifiedName == "System.Attribute")) + continue; + if (!c.Methods.Any(m => m.IsConstructor && m.IsPublic)) + continue; + if (string.IsNullOrEmpty(ns.Key)) + result.Add(c); + else + result.Add(new XamlCompletionClass(c, ns.Key)); + } + } + } + return result; + } + } + + void AddPropertiesForType(ArrayList result, XmlTextReader r, TypeResolveResult rr) + { + if (rr.ResolvedType != null) { + foreach (IProperty p in rr.ResolvedType.GetProperties()) { + if (!p.IsPublic) + continue; + if (!p.CanSet && !IsCollectionType(p.ReturnType)) + continue; + string propPrefix = p.DeclaringType.Name; + if (!string.IsNullOrEmpty(r.Prefix)) + propPrefix = r.Prefix + ":" + propPrefix; + result.Add(new XamlCompletionProperty(p, propPrefix)); + } + } + } + + bool IsCollectionType(IReturnType rt) + { + if (rt == null) + return false; + return rt.GetMethods().Any(m => m.Name == "Add" && m.IsPublic); + } + + class XamlCompletionClass : DefaultClass, IEntity + { + string newName; + + public XamlCompletionClass(IClass baseClass, string prefix) + : base(baseClass.CompilationUnit, baseClass.FullyQualifiedName) + { + this.Modifiers = baseClass.Modifiers; + newName = prefix + ":" + baseClass.Name; + } + + string IEntity.Name + { + get { return newName; } + } + } + + class XamlCompletionProperty : DefaultProperty, IEntity + { + string newName; + + public XamlCompletionProperty(IProperty baseProperty, string prefix) + : base(baseProperty.DeclaringType, baseProperty.Name) + { + this.Modifiers = baseProperty.Modifiers; + newName = prefix + "." + baseProperty.Name; + } + + string IEntity.Name + { + get { return newName; } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/AbstractEventHandlerService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/AbstractEventHandlerService.cs new file mode 100644 index 0000000000..1d1afb20da --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/AbstractEventHandlerService.cs @@ -0,0 +1,115 @@ +// +// +// +// +// $Revision: 2667$ +// + +using System; +using System.ComponentModel; +using System.IO; +using System.Windows.Controls; + +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.WpfDesign.Designer.XamlBackend; +using ICSharpCode.Xaml; + +namespace ICSharpCode.WpfDesign.AddIn +{ + abstract class AbstractEventHandlerService : IEventHandlerService + { + WpfPrimaryViewContent viewContent; + + protected AbstractEventHandlerService(WpfPrimaryViewContent viewContent) + { + if (viewContent == null) + throw new ArgumentNullException("viewContent"); + this.viewContent = viewContent; + } + + protected IProjectContent GetProjectContent() + { + IProject p = ProjectService.OpenSolution.FindProjectContainingFile(viewContent.PrimaryFileName); + if (p != null) + return ParserService.GetProjectContent(p) ?? ParserService.DefaultProjectContent; + else + return ParserService.DefaultProjectContent; + } + + protected IClass GetDesignedClass() + { + var model = viewContent.Context.ModelService as XamlModelService; + if (model != null) { + string className = model.ClassName; + if (!string.IsNullOrEmpty(className)) { + return GetProjectContent().GetClass(className, 0); + } + } + return null; + } + + protected IClass GetDesignedClassCodeBehindPart(IClass c) + { + CompoundClass compound = c as CompoundClass; + if (compound != null) { + c = null; + foreach (IClass part in compound.Parts) { + if (string.IsNullOrEmpty(part.CompilationUnit.FileName)) + continue; + if (XamlConstants.HasXamlExtension(part.CompilationUnit.FileName)) + continue; + if (c == null || c.CompilationUnit.FileName.Length > part.CompilationUnit.FileName.Length) + c = part; + } + } + return c; + } + + protected abstract void CreateEventHandlerInternal(Type eventHandlerType, string handlerName); + + public void CreateEventHandler(DesignItemProperty eventProperty) + { + var item = eventProperty.DesignItem; + string handlerName = (string)eventProperty.ValueOnInstance; + + if (string.IsNullOrEmpty(handlerName)) { + if (string.IsNullOrEmpty(item.Name)) { + GenerateName(eventProperty.DesignItem); + } + handlerName = item.Name + "_" + eventProperty.Name; + eventProperty.SetValue(handlerName); + } + CreateEventHandlerInternal(eventProperty.ReturnType, handlerName); + } + + public DesignItemProperty GetDefaultEvent(DesignItem item) + { + object[] attributes = item.ComponentType.GetCustomAttributes(typeof(DefaultEventAttribute), true); + if (attributes.Length == 1) { + DefaultEventAttribute dae = (DefaultEventAttribute)attributes[0]; + DesignItemProperty property = item.Properties.GetProperty(dae.Name); + if (property != null && property.IsEvent) { + return property; + } + } + return null; + } + + void GenerateName(DesignItem item) + { + for (int i = 1; ; i++) { + try { + string name = item.ComponentType.Name + i; + name = char.ToLower(name[0]) + name.Substring(1); + item.Name = name; + break; + } + catch { + } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/CSharpEventHandlerService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/CSharpEventHandlerService.cs new file mode 100644 index 0000000000..8f1019147e --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/CSharpEventHandlerService.cs @@ -0,0 +1,48 @@ +// +// +// +// +// $Revision: 2667$ +// + +using System; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; + +namespace ICSharpCode.WpfDesign.AddIn +{ + sealed class CSharpEventHandlerService : AbstractEventHandlerService + { + public CSharpEventHandlerService(WpfPrimaryViewContent viewContent) + : base(viewContent) + { + } + + protected override void CreateEventHandlerInternal(Type eventHandlerType, string handlerName) + { + IClass c = GetDesignedClass(); + if (c != null) { + foreach (IMethod m in c.Methods) { + if (m.Name == handlerName) { + FileService.JumpToFilePosition(m.DeclaringType.CompilationUnit.FileName, + m.Region.BeginLine - 1, m.Region.BeginColumn - 1); + return; + } + } + } + c = GetDesignedClassCodeBehindPart(c); + if (c != null) { + ITextEditorControlProvider tecp = FileService.OpenFile(c.CompilationUnit.FileName) as ITextEditorControlProvider; + if (tecp != null) { + int lineNumber; + FormsDesigner.CSharpDesignerGenerator.CreateComponentEvent( + c, tecp.TextEditorControl.Document, eventHandlerType, handlerName, null, + out lineNumber); + tecp.TextEditorControl.ActiveTextAreaControl.JumpTo(lineNumber - 1); + } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/FileUriContext.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/FileUriContext.cs new file mode 100644 index 0000000000..7a22990fb6 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/FileUriContext.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision: 2577 $ +// + +using System; +using System.IO; +using System.Windows.Markup; + +using ICSharpCode.SharpDevelop; + +namespace ICSharpCode.WpfDesign.AddIn +{ + /// + /// Used to support loading Image.ImageSource. + /// + public class FileUriContext : IUriContext + { + OpenedFile file; + + public FileUriContext(OpenedFile file) + { + if (file == null) + throw new ArgumentNullException("file"); + this.file = file; + } + + public Uri BaseUri { + get { + return new Uri(file.FileName); + } + set { + throw new NotSupportedException(); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/GetBitmapExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/GetBitmapExtension.cs new file mode 100644 index 0000000000..b8a978a140 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/GetBitmapExtension.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows; +using System.Windows.Interop; +using System.Windows.Markup; +using System.Windows.Media.Imaging; + +using ICSharpCode.Core.WinForms; + +namespace ICSharpCode.WpfDesign.AddIn +{ + class GetBitmapExtension : MarkupExtension + { + public GetBitmapExtension(string key) + { + this.key = key; + } + + static Dictionary cache = new Dictionary(); + + protected string key; + + public override object ProvideValue(IServiceProvider sp) + { + lock (cache) { + BitmapSource result; + if (!cache.TryGetValue(key, out result)) { + result = GetBitmapSource(); + result.Freeze(); + cache[key] = result; + } + return result; + } + } + + BitmapSource GetBitmapSource() + { + Bitmap bitmap = WinFormsResourceService.GetBitmap(key); + return Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, + Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/IdeChooseClassService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/IdeChooseClassService.cs new file mode 100644 index 0000000000..42a8401152 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/IdeChooseClassService.cs @@ -0,0 +1,29 @@ +using System; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using System.Reflection; +using System.Collections.Generic; +using System.IO; +using ICSharpCode.Core; +using ICSharpCode.WpfDesign.Designer.Services; +using ICSharpCode.FormsDesigner.Services; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public class IdeChooseClassService : ChooseClassServiceBase + { + public override IEnumerable GetAssemblies() + { + var pc = ParserService.CurrentProjectContent; + if (pc != null) { + var a = XamlMapper.TypeResolutionServiceInstance.LoadAssembly(pc); + if (a != null) yield return a; + foreach (var r in pc.ReferencedContents) { + a = XamlMapper.TypeResolutionServiceInstance.LoadAssembly(r); + if (a != null) yield return a; + } + } + } + } +} \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/MyTypeFinder.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/MyTypeFinder.cs new file mode 100644 index 0000000000..d4a08faed7 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/MyTypeFinder.cs @@ -0,0 +1,62 @@ +// +// +// +// +// $Revision: 2577 $ +// + +using System; +using System.Reflection; +using ICSharpCode.WpfDesign.XamlDom; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using TypeResolutionService = ICSharpCode.FormsDesigner.Services.TypeResolutionService; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public class MyTypeFinder : XamlTypeFinder + { + OpenedFile file; + + public static MyTypeFinder Create(OpenedFile file) + { + MyTypeFinder f = new MyTypeFinder(); + f.file = file; + f.ImportFrom(CreateWpfTypeFinder()); + return f; + } + + public override Assembly LoadAssembly(string name) + { + if (string.IsNullOrEmpty(name)) { + IProjectContent pc = GetProjectContent(file); + if (pc != null) { + return TypeResolutionService.LoadAssembly(pc); + } + return null; + } else { + return base.LoadAssembly(name); + } + } + + public override XamlTypeFinder Clone() + { + MyTypeFinder copy = new MyTypeFinder(); + copy.file = this.file; + copy.ImportFrom(this); + return copy; + } + + internal static IProjectContent GetProjectContent(OpenedFile file) + { + if (ProjectService.OpenSolution != null && file != null) { + IProject p = ProjectService.OpenSolution.FindProjectContainingFile(file.FileName); + if (p != null) { + return ParserService.GetProjectContent(p); + } + } + return ParserService.DefaultProjectContent; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/ObjectEditor.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/ObjectEditor.xaml new file mode 100644 index 0000000000..6456e70d4e --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/ObjectEditor.xaml @@ -0,0 +1,8 @@ + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/ObjectEditor.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/ObjectEditor.xaml.cs new file mode 100644 index 0000000000..e51e8ba2b4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/ObjectEditor.xaml.cs @@ -0,0 +1,31 @@ +using System; +using System.Windows; +using ICSharpCode.WpfDesign.PropertyGrid; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace ICSharpCode.WpfDesign.AddIn +{ + [PropertyEditor(typeof(FrameworkElement), "DataContext")] + public partial class ObjectEditor + { + public ObjectEditor() + { + InitializeComponent(); + } + + public PropertyNode PropertyNode { + get { return DataContext as PropertyNode; } + } + + protected override void OnClick() + { + var s = PropertyNode.Services.GetService(); + if (s != null) { + var c = s.ChooseClass(); + if (c != null) { + PropertyNode.Value = Activator.CreateInstance(c); + } + } + } + } +} \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/OutlineViewPad.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/OutlineViewPad.cs new file mode 100644 index 0000000000..5641717ddc --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/OutlineViewPad.cs @@ -0,0 +1,66 @@ +// +// +// +// +// $Revision: 3519 $ +// + +using System; +using System.Windows; +using System.Windows.Controls; + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public class OutlineViewPad : AbstractPadContent + { + public override System.Windows.Forms.Control Control + { + get { return WpfTools.OutlineHost; } + } + + //SharpDevelopElementHost host = new SharpDevelopElementHost(); + + //TextBlock notAvailableTextBlock = new TextBlock { + // Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.OutlinePad.NotAvailable}"), + // TextWrapping = TextWrapping.Wrap + //}; + + //public OutlineViewPad() + //{ + // WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchActiveViewContentChanged; + // WorkbenchActiveViewContentChanged(null, null); + //} + + //void WorkbenchActiveViewContentChanged(object sender, EventArgs e) + //{ + // WpfSecondaryViewContent wpfView = WorkbenchSingleton.Workbench.ActiveViewContent as WpfSecondaryViewContent; + // host.ViewContent = wpfView; + // if (wpfView != null) { + // host.Child = wpfView.Outline; + // } else { + // host.Child = notAvailableTextBlock; + // } + //} + + ///// + ///// The representing the pad + ///// + //public override System.Windows.Forms.Control Control { + // get { + // return host; + // } + //} + + ///// + ///// Cleans up all used resources + ///// + //public override void Dispose() + //{ + // host.Dispose(); + // base.Dispose(); + //} + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Properties/AssemblyInfo.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..5f282702bb --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/PropertyDescriptionService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/PropertyDescriptionService.cs new file mode 100644 index 0000000000..cd0843addb --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/PropertyDescriptionService.cs @@ -0,0 +1,26 @@ +// +// +// +// +// $Revision: 3506 $ +// + +using System; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.WpfDesign.Designer.XamlBackend; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public class PropertyDescriptionService : IPropertyDescriptionService + { + public object GetDescription(DesignItemProperty property) + { + var p = property as XamlDesignItemProperty; + var m = XamlMapper.GetDomMember(p.XamlProperty.Member); + return CodeCompletionData.GetDocumentation(m.Documentation); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/SharpDevelopElementHost.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/SharpDevelopElementHost.cs new file mode 100644 index 0000000000..3d11c4bf0b --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/SharpDevelopElementHost.cs @@ -0,0 +1,123 @@ +// +// +// +// +// $Revision: 3519 $ +// + +using System; +using System.Windows; +using System.Windows.Forms.Integration; +using System.Windows.Input; +using System.Windows.Threading; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.WpfDesign.Designer; + +namespace ICSharpCode.WpfDesign.AddIn +{ + /// + /// Hosts a WPF element inside a Windows.Forms application. + /// + public class SharpDevelopElementHost : ElementHost, IUndoHandler, IClipboardHandler + { + public SharpDevelopElementHost(UIElement child) + { + Child = child; + + if (!registeredErrorHandler) { + registeredErrorHandler = true; + Dispatcher.CurrentDispatcher.UnhandledException += CurrentDispatcher_UnhandledException; + } + } + + [ThreadStatic] + static bool registeredErrorHandler; + + static void CurrentDispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) + { + ICSharpCode.Core.MessageService.ShowError(e.Exception, "Unhandled WPF exception"); + e.Handled = true; + } + + ICommandService CurrentCommandService + { + get + { + if (WpfTools.ActiveContext != null) { + return WpfTools.ActiveContext.CommandService; + } + return null; + } + } + + public bool EnableUndo + { + get { return CurrentCommandService != null && CurrentCommandService.CanUndo(); } + } + + public bool EnableRedo + { + get { return CurrentCommandService != null && CurrentCommandService.CanRedo(); } + } + + public bool EnableCopy + { + get { return CurrentCommandService != null && CurrentCommandService.CanCopy(); } + } + + public bool EnablePaste + { + get { return CurrentCommandService != null && CurrentCommandService.CanPaste(); } + } + + public bool EnableCut + { + get { return CurrentCommandService != null && CurrentCommandService.CanCut(); } + } + + public bool EnableSelectAll + { + get { return CurrentCommandService != null && CurrentCommandService.CanSelectAll(); } + } + + public bool EnableDelete + { + get { return CurrentCommandService != null && CurrentCommandService.CanDelete(); } + } + + public void Undo() + { + CurrentCommandService.Undo(); + } + + public void Redo() + { + CurrentCommandService.Redo(); + } + + public void Copy() + { + CurrentCommandService.Copy(); + } + + public void Paste() + { + CurrentCommandService.Paste(); + } + + public void Cut() + { + CurrentCommandService.Cut(); + } + + public void SelectAll() + { + CurrentCommandService.SelectAll(); + } + + public void Delete() + { + CurrentCommandService.Delete(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfAndWinFormsTopLevelWindowService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfAndWinFormsTopLevelWindowService.cs new file mode 100644 index 0000000000..70e7306a37 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfAndWinFormsTopLevelWindowService.cs @@ -0,0 +1,77 @@ +// +// +// +// +// $Revision: 2667$ +// + +using System; +using System.Windows; +using System.Windows.Forms; +using System.Windows.Interop; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.AddIn +{ + sealed class WpfAndWinFormsTopLevelWindowService : ITopLevelWindowService + { + public ITopLevelWindow GetTopLevelWindow(UIElement element) + { + Window window = Window.GetWindow(element); + if (window != null) { + return new WpfTopLevelWindow(window); + } + HwndSource hwndSource = PresentationSource.FromVisual(element) as HwndSource; + if (hwndSource != null) { + Control ctl = Control.FromChildHandle(hwndSource.Handle); + if (ctl != null) { + Form form = ctl.FindForm(); + if (form != null) { + return new WindowsFormsTopLevelWindow(form); + } + } + } + return null; + } + + sealed class WpfTopLevelWindow : ITopLevelWindow + { + Window window; + + public WpfTopLevelWindow(Window window) + { + this.window = window; + } + + public void SetOwner(Window child) + { + child.Owner = window; + } + + public bool Activate() + { + return window.Activate(); + } + } + + sealed class WindowsFormsTopLevelWindow : ITopLevelWindow + { + Form form; + + public WindowsFormsTopLevelWindow(Form form) + { + this.form = form; + } + + public void SetOwner(Window child) + { + (new WindowInteropHelper(child)).Owner = form.Handle; + } + + public bool Activate() + { + return form.Focus(); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj index b0a4d54f83..d388ec2503 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj @@ -53,26 +53,24 @@ Always - Configuration\GlobalAssemblyInfo.cs + Properties\GlobalAssemblyInfo.cs - - - - - - - - - ObjectEditor.xaml + + + + + + + + + + + + Code - - - - - - - - + + + @@ -105,26 +103,22 @@ ICSharpCode.SharpDevelop.Widgets False + + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD} + Xaml + {7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57} FormsDesigner False - + {78CC29AC-CC79-4355-B1F2-97936DF198AC} WpfDesign.Designer - False - - {88DA149F-21B2-48AB-82C4-28FB6BDFD783} - WpfDesign.XamlDom - False - - + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F} WpfDesign - False - \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.addin b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.addin index 0df15edf4b..aa81cf9701 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.addin +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.addin @@ -13,11 +13,14 @@ - + fileNamePattern = "\.xaml$"/> + + + +// +// +// +// $Revision: 3497 $ +// + +using System; +using System.IO; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public class WpfPrimaryDisplayBinding : TextEditorDisplayBinding + { + protected override TextEditorDisplayBindingWrapper CreateWrapper(OpenedFile file) + { + return new WpfPrimaryViewContent(file); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfPrimaryViewContent.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfPrimaryViewContent.cs new file mode 100644 index 0000000000..dc1b19d8c2 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfPrimaryViewContent.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.WpfDesign.Designer.XamlBackend; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.WpfDesign.Designer.Services; +using System.Windows.Threading; +using System.IO; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public class WpfPrimaryViewContent : TextEditorDisplayBindingWrapper, IWpfViewContent, IHasPropertyContainer, IUndoHandler, IToolsHost, IParseInformationListener + { + public WpfPrimaryViewContent(OpenedFile file) + : base(file) + { + } + + List tasks = new List(); + + public override void Load(OpenedFile file, Stream stream) + { + base.Load(file, stream); + var doc = XamlMapper.GetXamlDocument(file.FileName); + Context = new XamlDesignContext(doc); + Context.AddService(typeof(IPropertyDescriptionService), new PropertyDescriptionService()); + Context.AddService(typeof(IEventHandlerService), new CSharpEventHandlerService(this)); + Context.AddService(typeof(ITopLevelWindowService), new WpfAndWinFormsTopLevelWindowService()); + Context.AddService(typeof(ChooseClassServiceBase), new IdeChooseClassService()); + Context.UndoService.UndoStackChanged += new EventHandler(Undo_UndoStackChanged); + Context.Parse(Text); + } + + void Undo_UndoStackChanged(object sender, EventArgs e) + { + this.PrimaryFile.MakeDirty(); + } + + //public new void ParseInformationUpdated(ParseInformation parseInfo) + //{ + // base.ParseInformationUpdated(parseInfo); + + // Dispatcher.CurrentDispatcher.Invoke(new Action(delegate { + // Context.Load(Text); + // })); + + // UpdateTasks(); + //} + + void UpdateTasks() + { + foreach (var task in tasks) { + TaskService.Remove(task); + } + + tasks.Clear(); + + foreach (var error in Context.Document.Errors) { + var task = new Task(PrimaryFile.FileName, error.Message, error.LinePosition - 1, error.LineNumber - 1, TaskType.Error); + tasks.Add(task); + TaskService.Add(task); + } + } + + #region WpfViewContent Implementation + + public XamlDesignContext Context { get; private set; } + + public PropertyContainer PropertyContainer + { + get { return WpfTools.PropertyContainer; } + } + + public System.Windows.Forms.Control ToolsControl + { + get { return WpfTools.ToolboxHost; } + } + + public bool EnableRedo + { + get { return Context.UndoService.CanRedo; } + } + + public bool EnableUndo + { + get { return Context.UndoService.CanUndo; } + } + + public void Redo() + { + Context.UndoService.Redo(); + } + + public void Undo() + { + Context.UndoService.Undo(); + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSecondaryDisplayBinding.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSecondaryDisplayBinding.cs new file mode 100644 index 0000000000..6ab752ab39 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSecondaryDisplayBinding.cs @@ -0,0 +1,38 @@ +// +// +// +// +// $Revision: 3497 $ +// + +using System; +using System.IO; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Gui; +using System.Xml; +using ICSharpCode.Xaml; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public class WpfSecondaryDisplayBinding : ISecondaryDisplayBinding + { + public bool ReattachWhenParserServiceIsReady + { + get + { + return false; + } + } + + public bool CanAttachTo(IViewContent content) + { + return XamlConstants.HasXamlExtension(content.PrimaryFileName); + } + + public IViewContent[] CreateSecondaryViewContent(IViewContent viewContent) + { + return new IViewContent[] { new WpfSecondaryViewContent(viewContent as WpfPrimaryViewContent) }; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSecondaryViewContent.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSecondaryViewContent.cs new file mode 100644 index 0000000000..c8b103de7f --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSecondaryViewContent.cs @@ -0,0 +1,108 @@ +// +// +// +// +// $Revision: 3528 $ +// + +using ICSharpCode.WpfDesign.Designer.OutlineView; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Windows.Forms; +using System.Windows.Forms.Integration; +using System.Windows.Markup; +using System.Xml; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.WpfDesign.Designer; +using ICSharpCode.WpfDesign.Designer.PropertyGrid; +using ICSharpCode.WpfDesign.Designer.Services; +using ICSharpCode.WpfDesign.PropertyGrid; +using System.Windows.Input; +using ICSharpCode.WpfDesign.Designer.XamlBackend; +using ICSharpCode.Xaml; + +namespace ICSharpCode.WpfDesign.AddIn +{ + /// + /// IViewContent implementation that hosts the WPF designer. + /// + public class WpfSecondaryViewContent : AbstractViewContent, IWpfViewContent, IHasPropertyContainer, IUndoHandler, IToolsHost + { + public WpfSecondaryViewContent(WpfPrimaryViewContent primaryViewContent) + { + this.primaryViewContent = primaryViewContent; + this.TabPageText = "${res:FormsDesigner.DesignTabPages.DesignTabPage}"; + } + + WpfPrimaryViewContent primaryViewContent; + + public override Control Control + { + get { return WpfTools.DesignerHost; } + } + + public override void Load(OpenedFile file, Stream stream) + { + Context.Parse(new StreamReader(stream).ReadToEnd()); + } + + public override void Save(OpenedFile file, Stream stream) + { + if (Context.CanSave) { + new StreamWriter(stream).Write(Context.Save()); + } + else { + primaryViewContent.Save(file, stream); + } + } + + public override bool SupportsSwitchFromThisWithoutSaveLoad(OpenedFile file, IViewContent newView) + { + return newView == primaryViewContent && !Context.CanSave; + } + + #region WpfViewContent Implementation + + public XamlDesignContext Context + { + get { return primaryViewContent.Context; } + } + + public PropertyContainer PropertyContainer + { + get { return WpfTools.PropertyContainer; } + } + + public System.Windows.Forms.Control ToolsControl + { + get { return WpfTools.ToolboxHost; } + } + + public bool EnableRedo + { + get { return Context.UndoService.CanRedo; } + } + + public bool EnableUndo + { + get { return Context.UndoService.CanUndo; } + } + + public void Redo() + { + Context.UndoService.Redo(); + } + + public void Undo() + { + Context.UndoService.Undo(); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSideTabItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSideTabItem.cs new file mode 100644 index 0000000000..f5f68c408a --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfSideTabItem.cs @@ -0,0 +1,37 @@ +// +// +// +// +// $Revision: 2573 $ +// + +using System; +using System.Drawing; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace ICSharpCode.WpfDesign.AddIn +{ + /// + /// Description of WpfSideTabItem. + /// + public class WpfSideTabItem : SharpDevelopSideTabItem + { + public WpfSideTabItem(Type componentType) : base(componentType.Name, new CreateComponentTool(componentType)) + { + CanBeRenamed = false; +// this.Icon = tag.Bitmap; + } + + ///create a default tabitem : a pointer icon with an empty toolboxitem + public WpfSideTabItem() : base("Pointer") + { + CanBeRenamed = false; + CanBeDeleted = false; + Bitmap pointerBitmap = new Bitmap(IconService.GetBitmap("Icons.16x16.FormsDesigner.PointerIcon"), 16, 16); + this.Icon = pointerBitmap; + this.Tag = null; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfToolbox.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfToolbox.cs new file mode 100644 index 0000000000..2a32cd6228 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfToolbox.cs @@ -0,0 +1,128 @@ +// +// +// +// +// $Revision: 3435 $ +// + +using System; +using System.Diagnostics; +using System.Windows.Forms; + +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Widgets.SideBar; +using WPF = System.Windows.Controls; + +namespace ICSharpCode.WpfDesign.AddIn +{ + /// + /// Manages the WpfToolbox. + /// + public class WpfToolbox + { + static WpfToolbox instance; + + public static WpfToolbox Instance { + get { + WorkbenchSingleton.AssertMainThread(); + if (instance == null) { + instance = new WpfToolbox(); + } + return instance; + } + } + + IToolService toolService; + WpfSideBar sideBar; + + public WpfToolbox() + { + sideBar = new WpfSideBar(); + SideTab sideTab = new SideTab(sideBar, "Windows Presentation Foundation"); + sideTab.DisplayName = StringParser.Parse(sideTab.Name); + sideTab.CanBeDeleted = false; + sideTab.ChoosedItemChanged += OnChoosedItemChanged; + + sideTab.Items.Add(new WpfSideTabItem()); + //foreach (Type t in Metadata.GetPopularControls()) + // sideTab.Items.Add(new WpfSideTabItem(t)); + + sideBar.Tabs.Add(sideTab); + sideBar.ActiveTab = sideTab; + } + + void OnChoosedItemChanged(object sender, EventArgs e) + { + if (toolService != null) { + ITool newTool = null; + if (sideBar.ActiveTab != null && sideBar.ActiveTab.ChoosedItem != null) { + newTool = sideBar.ActiveTab.ChoosedItem.Tag as ITool; + } + toolService.CurrentTool = newTool ?? toolService.PointerTool; + } + } + + public Control ToolboxControl { + get { return sideBar; } + } + + public IToolService ToolService { + get { return toolService; } + set { + if (toolService != null) { + toolService.CurrentToolChanged -= OnCurrentToolChanged; + } + toolService = value; + if (toolService != null) { + toolService.CurrentToolChanged += OnCurrentToolChanged; + OnCurrentToolChanged(null, null); + } + } + } + + void OnCurrentToolChanged(object sender, EventArgs e) + { + object tagToFind; + if (toolService.CurrentTool == toolService.PointerTool) { + tagToFind = null; + } else { + tagToFind = toolService.CurrentTool; + } + if (sideBar.ActiveTab.ChoosedItem != null) { + if (sideBar.ActiveTab.ChoosedItem.Tag == tagToFind) + return; + } + foreach (SideTabItem item in sideBar.ActiveTab.Items) { + if (item.Tag == tagToFind) { + sideBar.ActiveTab.ChoosedItem = item; + sideBar.Refresh(); + return; + } + } + foreach (SideTab tab in sideBar.Tabs) { + foreach (SideTabItem item in tab.Items) { + if (item.Tag == tagToFind) { + sideBar.ActiveTab = tab; + sideBar.ActiveTab.ChoosedItem = item; + sideBar.Refresh(); + return; + } + } + } + sideBar.ActiveTab.ChoosedItem = null; + sideBar.Refresh(); + } + + sealed class WpfSideBar : SharpDevelopSideBar + { + protected override object StartItemDrag(SideTabItem draggedItem) + { + if (this.ActiveTab.ChoosedItem != draggedItem && this.ActiveTab.Items.Contains(draggedItem)) { + this.ActiveTab.ChoosedItem = draggedItem; + } + return new System.Windows.DataObject(draggedItem.Tag); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfTools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfTools.cs new file mode 100644 index 0000000000..9bb5a64df9 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfTools.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.WpfDesign.Designer; +using ICSharpCode.WpfDesign.Designer.OutlineView; +using ICSharpCode.WpfDesign.Designer.PropertyGrid; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.WpfDesign.Designer.XamlBackend; +using System.Windows.Input; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public static class WpfTools + { + static WpfTools() + { + CreateToolbox(); + CreateOutline(); + CreatePropertyGrid(); + CreateDesigner(); + + WorkbenchSingleton.Workbench.ActiveViewContentChanged += new EventHandler(Workbench_ActiveViewContentChanged); + } + + public static Toolbox Toolbox; + public static Outline Outline; + public static PropertyGridView PropertyGridView; + public static DesignSurface Designer; + + public static SharpDevelopElementHost ToolboxHost; + public static SharpDevelopElementHost OutlineHost; + public static SharpDevelopElementHost PropertyGridViewHost; + public static SharpDevelopElementHost DesignerHost; + + public static PropertyContainer PropertyContainer; + + public static DesignContext ActiveContext + { + get + { + var wpfViewContent = WorkbenchSingleton.Workbench.ActiveViewContent as IWpfViewContent; + if (wpfViewContent != null) { + return wpfViewContent.Context; + } + return null; + } + } + + static void CreateToolbox() + { + Toolbox = new Toolbox(); + ToolboxHost = new SharpDevelopElementHost(Toolbox); + } + + static void CreateOutline() + { + Outline = new Outline(); + OutlineHost = new SharpDevelopElementHost(Outline); + + // see 3522 + Outline.AddCommandHandler(ApplicationCommands.Delete, + () => ApplicationCommands.Delete.Execute(null, Designer)); + } + + static void CreatePropertyGrid() + { + PropertyGridView = new PropertyGridView(); + PropertyGridViewHost = new SharpDevelopElementHost(PropertyGridView); + PropertyContainer = new PropertyContainer(); + PropertyContainer.PropertyGridReplacementControl = PropertyGridViewHost; + } + + static void CreateDesigner() + { + Designer = new DesignSurface(); + DesignerHost = new SharpDevelopElementHost(Designer); + DragDropExceptionHandler.HandleException = ICSharpCode.Core.MessageService.ShowError; + } + + static void Workbench_ActiveViewContentChanged(object sender, EventArgs e) + { + Toolbox.Context = ActiveContext; + Outline.Context = ActiveContext; + PropertyGridView.Context = ActiveContext; + Designer.Context = ActiveContext; + } + } + + public interface IWpfViewContent + { + XamlDesignContext Context { get; } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/XamlMapper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/XamlMapper.cs new file mode 100644 index 0000000000..ee465ebbcb --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/XamlMapper.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.Xaml; +using ICSharpCode.SharpDevelop.Dom; +using System.IO; +using System.Windows.Markup; +using ICSharpCode.SharpDevelop; +using System.Reflection; +using ICSharpCode.FormsDesigner.Services; +using ICSharpCode.WpfDesign.Designer.XamlBackend; + +namespace ICSharpCode.WpfDesign.AddIn +{ + public class XamlMapper + { + static XamlMapper() + { + ProjectService.SolutionLoaded += new EventHandler(ProjectService_SolutionLoaded); + } + + static void ProjectService_SolutionLoaded(object sender, SolutionEventArgs e) + { + //throw new NotImplementedException(); + } + + //TODO xamlDocs + static Dictionary xamlProjects = new Dictionary(); + + public static TypeResolutionService TypeResolutionServiceInstance = new TypeResolutionService(); + + public static XamlProject GetXamlProject(IProject p) + { + XamlProject result; + if (!xamlProjects.TryGetValue(p, out result)) { + result = CreateXamlProject(p); + xamlProjects[p] = result; + } + return result; + } + + static XamlProject CreateXamlProject(IProject domProject) + { + var result = new WpfProject(); + + var projectContent = ParserService.GetProjectContent(domProject); + result.ProjectAssembly = GetXamlAssembly(projectContent); + + foreach (var referenceContent in projectContent.ReferencedContents) { + result.AddReference(GetXamlAssembly(referenceContent)); + } + + foreach (var item in domProject.Items) { + if (item.ItemType == ItemType.Page) { + if (XamlConstants.HasXamlExtension(item.FileName)) { + result.LoadDocument(item.FileName); + } + } + //else if (item.ItemType == ItemType.ApplicationDefinition) { + // result.ApplicationDefinition = result.LoadDocument(item.FileName); + //} + } + + return result; + } + + public static XamlAssembly GetXamlAssembly(IProjectContent projectContent) + { + if (projectContent is ReflectionProjectContent) { + var assembly = TypeResolutionServiceInstance.LoadAssembly(projectContent); + return ReflectionMapper.GetXamlAssembly(assembly); + } + return new IdeXamlAssembly(projectContent); + } + + public static XamlDocument GetXamlDocument(string filePath) + { + if (ProjectService.OpenSolution != null) { + var domProject = ProjectService.OpenSolution.FindProjectContainingFile(filePath); + if (domProject != null) { + var xamlProject = GetXamlProject(domProject); + if (xamlProject != null) { + return xamlProject.LoadDocument(filePath); + } + } + } + return null; + } + + public static XamlType GetXamlType(IClass c) + { + throw new NotImplementedException(); + //return c.UserData as XamlType; + } + + public static XamlMember GetXamlMember(IMember m) + { + throw new NotImplementedException(); + } + + public static IProject GetDomProject(XamlProject p) + { + throw new NotImplementedException(); + } + + public static IClass GetDomClass(XamlType t) + { + throw new NotImplementedException(); + } + + public static IMember GetDomMember(XamlMember m) + { + throw new NotImplementedException(); + } + + //static IProjectContent GetProjectContent(OpenedFile file) + //{ + // if ((ProjectService.OpenSolution != null) && (file != null)) + // { + // IProject p = ProjectService.OpenSolution.FindProjectContainingFile(file.FileName); + // if (p != null) + // { + // return ParserService.GetProjectContent(p); + // } + // } + // return ParserService.DefaultProjectContent; + //} + + //IProjectContent pc = GetProjectContent(file); + //if (pc != null) { + // IClass c = pc.GetClassByReflectionName(property.DeclaringType.FullName, true); + // if (c != null) { + // IMember m = DefaultProjectContent.GetMemberByReflectionName(c, property.Name); + // if (m != null) + // return CodeCompletionData.GetDocumentation(m.Documentation); + // } + //} + //return null; + } + + class IdeXamlAssembly : XamlAssembly + { + public IdeXamlAssembly(IProjectContent projectContent) + { + this.ProjectContent = projectContent; + } + + public IProjectContent ProjectContent { get; private set; } + + public override IEnumerable XmlnsDefinitions + { + get { yield break; } + } + + public override string Name + { + get { return GetName(ProjectContent); } + } + + public override XamlType GetType(string fullName) + { + var domClass = ProjectContent.GetClass(fullName, 0); + return new IdeXamlType(domClass); + } + + static string GetName(IProjectContent projectContent) + { + var reflection = projectContent as ReflectionProjectContent; + if (reflection != null) { + return new AssemblyName(reflection.AssemblyFullName).Name; + } + var project = projectContent.Project as IProject; + if (project != null) { + return project.Name; + } + return null; + } + } + + class IdeXamlType : DefaultXamlType + { + public IdeXamlType(IClass domClass) + { + this.Class = domClass; + } + + public IClass Class { get; private set; } + } + + class IdeXamlMember : DefaultXamlMember + { + public IdeXamlMember(IMember domMember) + { + this.Member = domMember; + } + + public IMember Member { get; private set; } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/BasicMetadata.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/BasicMetadata.cs new file mode 100644 index 0000000000..1f3f9fc7e6 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/BasicMetadata.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Media; +using System.Windows; +using System.Windows.Input; +using System.Windows.Documents; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media.Imaging; +using System.Windows.Media.Media3D; +using System.Windows.Shapes; +using System.Windows.Media.Animation; +using System.Windows.Data; +using System.Windows.Automation; +using System.Windows.Media.Effects; +using System.Windows.Navigation; +using ICSharpCode.Xaml; + +namespace ICSharpCode.WpfDesign.Designer +{ + public class BasicMetadata : IRegisterMetadata + { + public void Register() + { + Metadata.StandardValueAdded += new EventHandler(Metadata_StandardValueAdded); + Metadata.TypeReplacerAdded += new EventHandler(Metadata_TypeReplacerAdded); + + Metadata.AddStandardValues(typeof(Brush), typeof(Brushes)); + Metadata.AddStandardValues(typeof(Color), typeof(Colors)); + Metadata.AddStandardValues(typeof(FontStretch), typeof(FontStretches)); + Metadata.AddStandardValues(typeof(FontWeight), typeof(FontWeights)); + Metadata.AddStandardValues(typeof(FontStyle), typeof(FontStyles)); + Metadata.AddStandardValues(typeof(Cursor), typeof(Cursors)); + Metadata.AddStandardValues(typeof(PixelFormat), typeof(PixelFormats)); + Metadata.AddStandardValues(typeof(TextDecorationCollection), typeof(TextDecorations)); + + Metadata.AddStandardValues(typeof(ICommand), typeof(ApplicationCommands)); + Metadata.AddStandardValues(typeof(ICommand), typeof(EditingCommands)); + Metadata.AddStandardValues(typeof(ICommand), typeof(NavigationCommands)); + Metadata.AddStandardValues(typeof(ICommand), typeof(ComponentCommands)); + Metadata.AddStandardValues(typeof(ICommand), typeof(MediaCommands)); + + Metadata.AddStandardValues(typeof(FontFamily), Fonts.SystemFontFamilies + .Select(f => new StandardValue() { Instance = f, Text = f.Source })); + + Metadata.AddPopularProperty(Line.Y2Property); + Metadata.AddPopularProperty(NavigationWindow.ShowsNavigationUIProperty); + Metadata.AddPopularProperty(FlowDocumentScrollViewer.DocumentProperty); + Metadata.AddPopularProperty(GridViewRowPresenterBase.ColumnsProperty); + Metadata.AddPopularProperty(ListView.ViewProperty); + Metadata.AddPopularProperty(DocumentPageView.PageNumberProperty); + Metadata.AddPopularProperty(Popup.PlacementProperty); + Metadata.AddPopularProperty(Popup.PopupAnimationProperty); + Metadata.AddPopularProperty(ScrollBar.ViewportSizeProperty); + Metadata.AddPopularProperty(UniformGrid.RowsProperty); + Metadata.AddPopularProperty(TabControl.TabStripPlacementProperty); + Metadata.AddPopularProperty(Line.X1Property); + Metadata.AddPopularProperty(Line.Y1Property); + Metadata.AddPopularProperty(Line.X2Property); + Metadata.AddPopularProperty(Polygon.PointsProperty); + Metadata.AddPopularProperty(Polyline.PointsProperty); + Metadata.AddPopularProperty(Path.DataProperty); + Metadata.AddPopularProperty(HeaderedContentControl.HeaderProperty); + Metadata.AddPopularProperty(MediaElement.UnloadedBehaviorProperty); + Metadata.AddPopularProperty(Shape.FillProperty); + Metadata.AddPopularProperty(Page.TitleProperty); + Metadata.AddPopularProperty(ItemsControl.ItemsSourceProperty); + Metadata.AddPopularProperty(Image.SourceProperty); + Metadata.AddPopularProperty(TextBlock.TextProperty); + Metadata.AddPopularProperty(DockPanel.LastChildFillProperty); + Metadata.AddPopularProperty(Expander.IsExpandedProperty); + Metadata.AddPopularProperty(Shape.StrokeProperty); + Metadata.AddPopularProperty(RangeBase.ValueProperty); + Metadata.AddPopularProperty(ItemsControl.ItemContainerStyleProperty); + Metadata.AddPopularProperty(ToggleButton.IsCheckedProperty); + Metadata.AddPopularProperty(Window.TitleProperty); + Metadata.AddPopularProperty(Viewport3DVisual.CameraProperty); + Metadata.AddPopularProperty(Frame.SourceProperty); + Metadata.AddPopularProperty(Rectangle.RadiusXProperty); + Metadata.AddPopularProperty(Rectangle.RadiusYProperty); + Metadata.AddPopularProperty(FrameworkElement.HeightProperty); + Metadata.AddPopularProperty(FrameworkElement.WidthProperty); + Metadata.AddPopularProperty(UniformGrid.ColumnsProperty); + Metadata.AddPopularProperty(RangeBase.MinimumProperty); + Metadata.AddPopularProperty(RangeBase.MaximumProperty); + Metadata.AddPopularProperty(ScrollBar.OrientationProperty); + Metadata.AddPopularProperty(ContentControl.ContentProperty); + Metadata.AddPopularProperty(Popup.IsOpenProperty); + Metadata.AddPopularProperty(TextElement.FontSizeProperty); + Metadata.AddPopularProperty(FrameworkElement.NameProperty); + Metadata.AddPopularProperty(Popup.HorizontalOffsetProperty); + Metadata.AddPopularProperty(Popup.VerticalOffsetProperty); + Metadata.AddPopularProperty(Window.WindowStyleProperty); + Metadata.AddPopularProperty(Shape.StrokeThicknessProperty); + Metadata.AddPopularProperty(TextElement.ForegroundProperty); + Metadata.AddPopularProperty(FrameworkElement.VerticalAlignmentProperty); + Metadata.AddPopularProperty(Button.IsDefaultProperty); + Metadata.AddPopularProperty(UIElement.RenderTransformOriginProperty); + Metadata.AddPopularProperty(TextElement.FontFamilyProperty); + Metadata.AddPopularProperty(FrameworkElement.HorizontalAlignmentProperty); + Metadata.AddPopularProperty(ToolBar.BandProperty); + Metadata.AddPopularProperty(ToolBar.BandIndexProperty); + Metadata.AddPopularProperty(ItemsControl.ItemTemplateProperty); + Metadata.AddPopularProperty(TextBlock.TextWrappingProperty); + Metadata.AddPopularProperty(FrameworkElement.MarginProperty); + Metadata.AddPopularProperty(RangeBase.LargeChangeProperty); + Metadata.AddPopularProperty(RangeBase.SmallChangeProperty); + Metadata.AddPopularProperty(Panel.BackgroundProperty); + Metadata.AddPopularProperty(Shape.StrokeMiterLimitProperty); + Metadata.AddPopularProperty(TextElement.FontWeightProperty); + Metadata.AddPopularProperty(StackPanel.OrientationProperty); + Metadata.AddPopularProperty(ListBox.SelectionModeProperty); + Metadata.AddPopularProperty(FrameworkElement.StyleProperty); + Metadata.AddPopularProperty(TextBox.TextProperty); + Metadata.AddPopularProperty(Window.SizeToContentProperty); + Metadata.AddPopularProperty(Window.ResizeModeProperty); + Metadata.AddPopularProperty(TextBlock.TextTrimmingProperty); + Metadata.AddPopularProperty(Window.ShowInTaskbarProperty); + Metadata.AddPopularProperty(Window.IconProperty); + Metadata.AddPopularProperty(UIElement.RenderTransformProperty); + Metadata.AddPopularProperty(Button.IsCancelProperty); + Metadata.AddPopularProperty(Border.BorderBrushProperty); + Metadata.AddPopularProperty(Block.TextAlignmentProperty); + Metadata.AddPopularProperty(Border.CornerRadiusProperty); + Metadata.AddPopularProperty(Border.BorderThicknessProperty); + Metadata.AddPopularProperty(TreeViewItem.IsSelectedProperty); + Metadata.AddPopularProperty(Border.PaddingProperty); + Metadata.AddPopularProperty(Shape.StretchProperty); + + Metadata.AddPopularProperty(typeof(Binding), "Path"); + Metadata.AddPopularProperty(typeof(Binding), "Source"); + Metadata.AddPopularProperty(typeof(Binding), "Mode"); + Metadata.AddPopularProperty(typeof(Binding), "RelativeSource"); + Metadata.AddPopularProperty(typeof(Binding), "ElementName"); + Metadata.AddPopularProperty(typeof(Binding), "Converter"); + Metadata.AddPopularProperty(typeof(Binding), "XPath"); + + Metadata.AddValueRange(Block.LineHeightProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(Canvas.BottomProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Canvas.LeftProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Canvas.TopProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Canvas.RightProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(ColumnDefinition.MaxWidthProperty, 0, double.PositiveInfinity); + Metadata.AddValueRange(DocumentViewer.MaxPagesAcrossProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(Figure.HorizontalOffsetProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Figure.VerticalOffsetProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(FlowDocument.MaxPageWidthProperty, 0, double.PositiveInfinity); + Metadata.AddValueRange(FlowDocument.MaxPageHeightProperty, 0, double.PositiveInfinity); + Metadata.AddValueRange(FlowDocumentPageViewer.ZoomProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(FlowDocumentPageViewer.ZoomIncrementProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(FlowDocumentPageViewer.MinZoomProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(FlowDocumentPageViewer.MaxZoomProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(FrameworkElement.MaxHeightProperty, 0, double.PositiveInfinity); + Metadata.AddValueRange(FrameworkElement.MaxWidthProperty, 0, double.PositiveInfinity); + Metadata.AddValueRange(Grid.ColumnSpanProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(Grid.RowSpanProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(GridSplitter.KeyboardIncrementProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(GridSplitter.DragIncrementProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(InkCanvas.BottomProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(InkCanvas.TopProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(InkCanvas.RightProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(InkCanvas.LeftProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Line.Y2Property, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Line.X1Property, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Line.Y1Property, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Line.X2Property, double.MinValue, double.MaxValue); + Metadata.AddValueRange(List.MarkerOffsetProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(List.StartIndexProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(Paragraph.TextIndentProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(RangeBase.ValueProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(RangeBase.MaximumProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(RangeBase.MinimumProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(RepeatButton.IntervalProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(RowDefinition.MaxHeightProperty, 0, double.PositiveInfinity); + Metadata.AddValueRange(Selector.SelectedIndexProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Slider.TickFrequencyProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Slider.SelectionStartProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(Slider.SelectionEndProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(TableCell.RowSpanProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(TableCell.ColumnSpanProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(TextBox.MinLinesProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(TextBox.MaxLinesProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(TextBoxBase.UndoLimitProperty, double.MinValue, double.MaxValue); + Metadata.AddValueRange(TextElement.FontSizeProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(Timeline.SpeedRatioProperty, double.Epsilon, double.MaxValue); + Metadata.AddValueRange(Timeline.DecelerationRatioProperty, 0, 1); + Metadata.AddValueRange(Timeline.AccelerationRatioProperty, 0, 1); + Metadata.AddValueRange(Track.ViewportSizeProperty, 0, double.PositiveInfinity); + Metadata.AddValueRange(UIElement.OpacityProperty, 0, 1); + + Metadata.HideProperty(typeof(UIElement), "RenderSize"); + Metadata.HideProperty(FrameworkElement.NameProperty); + Metadata.HideProperty(typeof(FrameworkElement), "Resources"); + Metadata.HideProperty(typeof(Window), "Owner"); + + //Metadata.DisablePlacement(typeof(Button)); + + //Metadata.AddPopularControl(typeof(Button)); + //Metadata.AddPopularControl(typeof(CheckBox)); + //Metadata.AddPopularControl(typeof(ComboBox)); + //Metadata.AddPopularControl(typeof(Label)); + //Metadata.AddPopularControl(typeof(TextBox)); + //Metadata.AddPopularControl(typeof(RadioButton)); + //Metadata.AddPopularControl(typeof(Canvas)); + //Metadata.AddPopularControl(typeof(Grid)); + //Metadata.AddPopularControl(typeof(Border)); + //Metadata.AddPopularControl(typeof(DockPanel)); + //Metadata.AddPopularControl(typeof(Expander)); + //Metadata.AddPopularControl(typeof(GroupBox)); + //Metadata.AddPopularControl(typeof(Image)); + //Metadata.AddPopularControl(typeof(InkCanvas)); + //Metadata.AddPopularControl(typeof(ListBox)); + //Metadata.AddPopularControl(typeof(ListView)); + //Metadata.AddPopularControl(typeof(Menu)); + //Metadata.AddPopularControl(typeof(PasswordBox)); + //Metadata.AddPopularControl(typeof(ProgressBar)); + //Metadata.AddPopularControl(typeof(RichTextBox)); + //Metadata.AddPopularControl(typeof(ScrollViewer)); + //Metadata.AddPopularControl(typeof(Slider)); + //Metadata.AddPopularControl(typeof(StackPanel)); + //Metadata.AddPopularControl(typeof(TabControl)); + //Metadata.AddPopularControl(typeof(ToolBar)); + //Metadata.AddPopularControl(typeof(TreeView)); + //Metadata.AddPopularControl(typeof(Viewbox)); + //Metadata.AddPopularControl(typeof(Viewport3D)); + //Metadata.AddPopularControl(typeof(WrapPanel)); + + Metadata.AddDefaultSize(typeof(UIElement), new Size(120, 100)); + Metadata.AddDefaultSize(typeof(ContentControl), new Size(double.NaN, double.NaN)); + Metadata.AddDefaultSize(typeof(Button), new Size(75, 23)); + + var s1 = new Size(120, double.NaN); + Metadata.AddDefaultSize(typeof(Slider), s1); + Metadata.AddDefaultSize(typeof(TextBox), s1); + Metadata.AddDefaultSize(typeof(PasswordBox), s1); + Metadata.AddDefaultSize(typeof(ComboBox), s1); + Metadata.AddDefaultSize(typeof(ProgressBar), s1); + + var s2 = new Size(120, 20); + Metadata.AddDefaultSize(typeof(ToolBar), s2); + Metadata.AddDefaultSize(typeof(Menu), s2); + } + + void Metadata_TypeReplacerAdded(object sender, TypeEventArgs e) + { + Runtime.AddTypeReplacer(e.Type, Metadata.GetTypeReplacer(e.Type)); + } + + void Metadata_StandardValueAdded(object sender, StandardValueEventArgs e) + { + StandardValues.AddStandardValue(e.Type, e.StandardValue.Text, e.StandardValue.Instance); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/CallExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/CallExtension.cs new file mode 100644 index 0000000000..1e1a4f5aa6 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/CallExtension.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Markup; +using System.Windows; +using System.Windows.Data; +using System.Windows.Input; +using System.Reflection; + +namespace ICSharpCode.WpfDesign.Designer +{ + public class CallExtension : MarkupExtension + { + public CallExtension(string methodName) + { + this.methodName = methodName; + } + + string methodName; + + public override object ProvideValue(IServiceProvider sp) + { + var t = (IProvideValueTarget)sp.GetService(typeof(IProvideValueTarget)); + return new CallCommand(t.TargetObject as FrameworkElement, methodName); + } + } + + public class CallCommand : DependencyObject, ICommand + { + public CallCommand(FrameworkElement element, string methodName) + { + this.element = element; + this.methodName = methodName; + element.DataContextChanged += target_DataContextChanged; + + BindingOperations.SetBinding(this, CanCallProperty, new Binding("DataContext.Can" + methodName) { + Source = element + }); + + GetMethod(); + } + + FrameworkElement element; + string methodName; + MethodInfo method; + + public static readonly DependencyProperty CanCallProperty = + DependencyProperty.Register("CanCall", typeof(bool), typeof(CallCommand), + new PropertyMetadata(true)); + + public bool CanCall + { + get { return (bool)GetValue(CanCallProperty); } + set { SetValue(CanCallProperty, value); } + } + + public object DataContext + { + get { return element.DataContext; } + } + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + + if (e.Property == CanCallProperty) { + RaiseCanExecuteChanged(); + } + } + + void GetMethod() + { + if (DataContext == null) { + method = null; + } + else { + method = DataContext.GetType().GetMethod(methodName, Type.EmptyTypes); + } + } + + void target_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) + { + GetMethod(); + RaiseCanExecuteChanged(); + } + + void RaiseCanExecuteChanged() + { + if (CanExecuteChanged != null) { + CanExecuteChanged(this, EventArgs.Empty); + } + } + + #region ICommand Members + + public event EventHandler CanExecuteChanged; + + public bool CanExecute(object parameter) + { + return method != null && CanCall; + } + + public void Execute(object parameter) + { + method.Invoke(DataContext, null); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Converters.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Converters.cs new file mode 100644 index 0000000000..8536f2fd24 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Converters.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows; +using System.Collections; +using ICSharpCode.WpfDesign.Designer.XamlBackend; +using ICSharpCode.WpfDesign.Designer.OutlineView; + +namespace ICSharpCode.WpfDesign.Designer.Converters +{ + public class IntFromEnumConverter : IValueConverter + { + public static IntFromEnumConverter Instance = new IntFromEnumConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (int)value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return Enum.ToObject(targetType, (int)value); + } + } + + public class HiddenWhenFalse : IValueConverter + { + public static HiddenWhenFalse Instance = new HiddenWhenFalse(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (bool)value ? Visibility.Visible : Visibility.Hidden; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class CollapsedWhenFalse : IValueConverter + { + public static CollapsedWhenFalse Instance = new CollapsedWhenFalse(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (bool)value ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class LevelConverter : IValueConverter + { + public static LevelConverter Instance = new LevelConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return new Thickness(2 + 14 * (int)value, 0, 0, 0); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class CollapsedWhenZero : IValueConverter + { + public static CollapsedWhenZero Instance = new CollapsedWhenZero(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value == null || (int)value == 0) { + return Visibility.Collapsed; + } + return Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class FalseWhenNull : IValueConverter + { + public static FalseWhenNull Instance = new FalseWhenNull(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value != null; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + public class BoldWhenTrue : IValueConverter + { + public static BoldWhenTrue Instance = new BoldWhenTrue(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (bool)value ? FontWeights.Bold : FontWeights.Normal; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + // Boxed int throw exception without converter (wpf bug?) + public class DummyConverter : IValueConverter + { + public static DummyConverter Instance = new DummyConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value; + } + } + + //public class OutlineNodeFromDesignItemConverter : IValueConverter + //{ + // public static OutlineNodeFromDesignItemConverter Instance = new OutlineNodeFromDesignItemConverter(); + + // public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + // { + // var designItem = value as XamlDesignItem; + // if (designItem != null) { + // return designItem.Annotation(); + // } + // return null; + // } + + // public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + // { + // return value; + // } + //} +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignPanel.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignPanel.cs new file mode 100644 index 0000000000..9c9d505a6d --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignPanel.cs @@ -0,0 +1,283 @@ +// +// +// +// +// $Revision: 2440 $ +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Threading; + +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Designer.Controls; + +namespace ICSharpCode.WpfDesign.Designer +{ + sealed class DesignPanel : Decorator, IDesignPanel + { + #region Hit Testing + /// + /// this element is always hit (unless HitTestVisible is set to false) + /// + sealed class EatAllHitTestRequests : UIElement + { + protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters) + { + return new GeometryHitTestResult(this, IntersectionDetail.FullyContains); + } + + protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) + { + return new PointHitTestResult(this, hitTestParameters.HitPoint); + } + } + + static void RunHitTest(Visual reference, Point point, HitTestFilterCallback filterCallback, HitTestResultCallback resultCallback) + { + VisualTreeHelper.HitTest(reference, filterCallback, resultCallback, + new PointHitTestParameters(point)); + } + + static HitTestFilterBehavior FilterHitTestInvisibleElements(DependencyObject potentialHitTestTarget) + { + UIElement element = potentialHitTestTarget as UIElement; + if (element != null) { + if (!(element.IsHitTestVisible && element.Visibility == Visibility.Visible)) { + return HitTestFilterBehavior.ContinueSkipSelfAndChildren; + } + } + return HitTestFilterBehavior.Continue; + } + + /// + /// Performs a custom hit testing lookup for the specified mouse event args. + /// + public DesignPanelHitTestResult HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface) + { + DesignPanelHitTestResult result = DesignPanelHitTestResult.NoHit; + HitTest(mousePosition, testAdorners, testDesignSurface, + delegate(DesignPanelHitTestResult r) { + result = r; + return false; + }); + return result; + } + + /// + /// Performs a hit test on the design surface, raising for each match. + /// Hit testing continues while the callback returns true. + /// + public void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface, Predicate callback) + { + if (mousePosition.X < 0 || mousePosition.Y < 0 || mousePosition.X > this.RenderSize.Width || mousePosition.Y > this.RenderSize.Height) { + return; + } + // First try hit-testing on the adorner layer. + + bool continueHitTest = true; + + if (testAdorners) { + RunHitTest( + _adornerLayer, mousePosition, FilterHitTestInvisibleElements, + delegate(HitTestResult result) { + if (result != null && result.VisualHit != null && result.VisualHit is Visual) { + DesignPanelHitTestResult customResult = new DesignPanelHitTestResult((Visual)result.VisualHit); + DependencyObject obj = result.VisualHit; + while (obj != null && obj != _adornerLayer) { + AdornerPanel adorner = obj as AdornerPanel; + if (adorner != null) { + customResult.AdornerHit = adorner; + } + obj = VisualTreeHelper.GetParent(obj); + } + continueHitTest = callback(customResult); + return continueHitTest ? HitTestResultBehavior.Continue : HitTestResultBehavior.Stop; + } + else { + return HitTestResultBehavior.Continue; + } + }); + } + + if (continueHitTest && testDesignSurface) { + RunHitTest( + this.Child, mousePosition, delegate { return HitTestFilterBehavior.Continue; }, + delegate(HitTestResult result) { + if (result != null && result.VisualHit != null && result.VisualHit is Visual) { + DesignPanelHitTestResult customResult = new DesignPanelHitTestResult((Visual)result.VisualHit); + + IViewService viewService = _context.ViewService; + DependencyObject obj = result.VisualHit; + while (obj != null) { + if ((customResult.ModelHit = viewService.GetModel(obj)) != null) + break; + obj = VisualTreeHelper.GetParent(obj); + } + if (customResult.ModelHit == null) { + customResult.ModelHit = _context.ModelService.Root; + } + continueHitTest = callback(customResult); + return continueHitTest ? HitTestResultBehavior.Continue : HitTestResultBehavior.Stop; + } + else { + return HitTestResultBehavior.Continue; + } + } + ); + } + } + #endregion + + #region Fields + Constructor + DesignContext _context; + readonly EatAllHitTestRequests _eatAllHitTestRequests; + readonly AdornerLayer _adornerLayer; + + public DesignPanel() + { + this.Focusable = true; + this.VerticalAlignment = VerticalAlignment.Top; + this.HorizontalAlignment = HorizontalAlignment.Left; + this.AllowDrop = true; + this.DataContext = null; + DesignerProperties.SetIsInDesignMode(this, true); + + _eatAllHitTestRequests = new EatAllHitTestRequests(); + _eatAllHitTestRequests.MouseDown += delegate { + // ensure the design panel has focus while the user is interacting with it + this.Focus(); + }; + _eatAllHitTestRequests.AllowDrop = true; + _adornerLayer = new AdornerLayer(this); + } + #endregion + + #region Properties + + /// + /// Gets/Sets the design context. + /// + public DesignContext Context + { + get { return _context; } + set { _context = value; } + } + + public ICollection Adorners + { + get + { + return _adornerLayer.Adorners; + } + } + + /// + /// Gets/Sets if the design content is visible for hit-testing purposes. + /// + public bool IsContentHitTestVisible + { + get { return !_eatAllHitTestRequests.IsHitTestVisible; } + set { _eatAllHitTestRequests.IsHitTestVisible = !value; } + } + + /// + /// Gets/Sets if the adorner layer is visible for hit-testing purposes. + /// + public bool IsAdornerLayerHitTestVisible + { + get { return _adornerLayer.IsHitTestVisible; } + set { _adornerLayer.IsHitTestVisible = value; } + } + + #endregion + + #region Visual Child Management + public override UIElement Child + { + get { return base.Child; } + set + { + if (base.Child == value) + return; + if (value == null) { + // Child is being set from some value to null + + // remove _adornerLayer and _eatAllHitTestRequests + RemoveVisualChild(_adornerLayer); + RemoveVisualChild(_eatAllHitTestRequests); + } + else if (base.Child == null) { + // Child is being set from null to some value + AddVisualChild(_adornerLayer); + AddVisualChild(_eatAllHitTestRequests); + } + base.Child = value; + } + } + + protected override Visual GetVisualChild(int index) + { + if (base.Child != null) { + if (index == 0) + return base.Child; + else if (index == 1) + return _eatAllHitTestRequests; + else if (index == 2) + return _adornerLayer; + } + return base.GetVisualChild(index); + } + + protected override int VisualChildrenCount + { + get + { + if (base.Child != null) + return 3; + else + return base.VisualChildrenCount; + } + } + + protected override Size MeasureOverride(Size constraint) + { + Size result = base.MeasureOverride(constraint); + if (this.Child != null) { + _adornerLayer.Measure(constraint); + _eatAllHitTestRequests.Measure(constraint); + } + return result; + } + + protected override Size ArrangeOverride(Size arrangeSize) + { + Size result = base.ArrangeOverride(arrangeSize); + if (this.Child != null) { + Rect r = new Rect(new Point(0, 0), arrangeSize); + _adornerLayer.Arrange(r); + _eatAllHitTestRequests.Arrange(r); + } + return result; + } + #endregion + + protected override void OnQueryCursor(QueryCursorEventArgs e) + { + base.OnQueryCursor(e); + if (_context != null) { + Cursor cursor = _context.ToolService.CurrentTool.Cursor; + if (cursor != null) { + e.Cursor = cursor; + e.Handled = true; + } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface.xaml new file mode 100644 index 0000000000..c907bfcf1e --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface.xaml @@ -0,0 +1,13 @@ + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface.xaml.cs new file mode 100644 index 0000000000..23cb6a9cac --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface.xaml.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace ICSharpCode.WpfDesign.Designer +{ + public partial class DesignSurface + { + public DesignSurface() + { + InitializeComponent(); + } + + public static readonly DependencyProperty ContextProperty = + DependencyProperty.Register("Context", typeof(DesignContext), typeof(DesignSurface)); + + public DesignContext Context + { + get { return (DesignContext)GetValue(ContextProperty); } + set { SetValue(ContextProperty, value); } + } + + protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) + { + if (Context != null && e.OriginalSource == uxZoom.ScrollViewer) + { + UnselectAll(); + Context.ToolService.Reset(); + } + } + + void UnselectAll() + { + Context.SelectionService.Select(null); + } + + #region Commands + + public bool HasContext() + { + return Context != null; + } + + public bool CanUndo() + { + return Context != null && Context.UndoService.CanUndo; + } + + public void Undo() + { + IUndoAction action = Context.UndoService.UndoActions.First(); + Context.UndoService.Undo(); + Context.SelectionService.Select(ModelTools.GetLiveElements(action.AffectedItems)); + } + + public bool CanRedo() + { + return Context != null && Context.UndoService.CanRedo; + } + + public void Redo() + { + IUndoAction action = Context.UndoService.RedoActions.First(); + Context.UndoService.Redo(); + Context.SelectionService.Select(ModelTools.GetLiveElements(action.AffectedItems)); + } + + public bool CanCopy() + { + return false; + } + + public void Copy() + { + } + + public bool CanCut() + { + return false; + } + + public void Cut() + { + } + + public bool CanDelete() + { + return Context != null && ModelTools.CanDeleteComponents(Context.SelectionService.SelectedItems); + } + + public void Delete() + { + ModelTools.DeleteComponents(Context.SelectionService.SelectedItems); + } + + public bool CanPaste() + { + return false; + } + + public void Paste() + { + } + + //TODO: Do not select layout root + public void SelectAll() + { + var items = ModelTools.Descendants(Context.ModelService.Root) + .Where(item => ModelTools.CanSelectComponent(item)).ToArray(); + Context.SelectionService.Select(items); + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface1.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface1.xaml new file mode 100644 index 0000000000..0fe0ad99df --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface1.xaml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface1.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface1.xaml.cs new file mode 100644 index 0000000000..4f09e107aa --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DesignSurface1.xaml.cs @@ -0,0 +1,258 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Xml; +using ICSharpCode.WpfDesign.Designer.Xaml; +using ICSharpCode.WpfDesign.Designer.Services; +using System.Diagnostics; +using ICSharpCode.WpfDesign.XamlDom; +using System.Threading; +using System.Globalization; + +namespace ICSharpCode.WpfDesign.Designer +{ + /// + /// Surface hosting the WPF designer. + /// + public partial class DesignSurface + { + static DesignSurface() + { + //TODO: this is for converters (see PropertyGrid) + Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + } + + public DesignSurface() + { + InitializeComponent(); + + this.AddCommandHandler(ApplicationCommands.Undo, Undo, CanUndo); + this.AddCommandHandler(ApplicationCommands.Redo, Redo, CanRedo); + this.AddCommandHandler(ApplicationCommands.Copy, Copy, HasSelection); + this.AddCommandHandler(ApplicationCommands.Cut, Cut, HasSelection); + this.AddCommandHandler(ApplicationCommands.Delete, Delete, CanDelete); + this.AddCommandHandler(ApplicationCommands.Paste, Paste, CanPaste); + this.AddCommandHandler(ApplicationCommands.SelectAll, SelectAll, CanSelectAll); + } + + protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) + { + if (e.OriginalSource == uxZoom.ScrollViewer) { + UnselectAll(); + } + } + + DesignContext _designContext; + + /// + /// Gets the active design context. + /// + public DesignContext DesignContext { + get { return _designContext; } + } + + /// + /// Initializes the designer content from the specified XmlReader. + /// + public void LoadDesigner(XmlReader xamlReader, XamlLoadSettings loadSettings) + { + UnloadDesigner(); + loadSettings = loadSettings ?? new XamlLoadSettings(); + loadSettings.CustomServiceRegisterFunctions.Add( + context => context.Services.AddService(typeof(IDesignPanel), _designPanel)); + InitializeDesigner(new XamlDesignContext(xamlReader, loadSettings)); + } + + /// + /// Saves the designer content into the specified XmlWriter. + /// + public void SaveDesigner(XmlWriter writer) + { + _designContext.Save(writer); + } + + void InitializeDesigner(DesignContext context) + { + _designContext = context; + _designPanel.Context = context; + + if (context.RootItem != null) { + _sceneContainer.Child = context.RootItem.View; + } + + context.Services.RunWhenAvailable( + undoService => undoService.UndoStackChanged += delegate { + CommandManager.InvalidateRequerySuggested(); + } + ); + context.Services.Selection.SelectionChanged += delegate { + CommandManager.InvalidateRequerySuggested(); + }; + } + + /// + /// Unloads the designer content. + /// + public void UnloadDesigner() + { + if (_designContext != null) { + foreach (object o in _designContext.Services.AllServices) { + IDisposable d = o as IDisposable; + if (d != null) d.Dispose(); + } + } + _designContext = null; + _designPanel.Context = null; + _sceneContainer.Child = null; + _designPanel.Adorners.Clear(); + } + + #region Commands + + public bool CanUndo() + { + UndoService undoService = GetService(); + return undoService != null && undoService.CanUndo; + } + + public void Undo() + { + UndoService undoService = GetService(); + IUndoAction action = undoService.UndoActions.First(); + Debug.WriteLine("Undo " + action.Title); + undoService.Undo(); + _designContext.Services.Selection.SetSelectedComponents(GetLiveElements(action.AffectedElements)); + } + + public bool CanRedo() + { + UndoService undoService = GetService(); + return undoService != null && undoService.CanRedo; + } + + public void Redo() + { + UndoService undoService = GetService(); + IUndoAction action = undoService.RedoActions.First(); + Debug.WriteLine("Redo " + action.Title); + undoService.Redo(); + _designContext.Services.Selection.SetSelectedComponents(GetLiveElements(action.AffectedElements)); + } + + public bool HasSelection() + { + return false; + } + + public void Copy() + { + } + + public void Cut() + { + } + + public bool CanDelete() + { + if (_designContext != null) { + return ModelTools.CanDeleteComponents(_designContext.Services.Selection.SelectedItems); + } + return false; + } + + public void Delete() + { + if (_designContext != null) { + ModelTools.DeleteComponents(_designContext.Services.Selection.SelectedItems); + } + } + + public bool CanPaste() + { + return false; + } + + public void Paste() + { + } + + public bool CanSelectAll() + { + return DesignContext != null; + } + + //TODO: Do not select layout root + public void SelectAll() + { + var items = Descendants(DesignContext.RootItem).Where(item => ModelTools.CanSelectComponent(item)).ToArray(); + DesignContext.Services.Selection.SetSelectedComponents(items); + } + + public void UnselectAll() + { + DesignContext.Services.Selection.SetSelectedComponents(null); + } + + //TODO: Share with Outline / PlacementBehavior + public static IEnumerable DescendantsAndSelf(DesignItem item) + { + yield return item; + foreach (var child in Descendants(item)) { + yield return child; + } + } + + public static IEnumerable Descendants(DesignItem item) + { + if (item.ContentPropertyName != null) { + var content = item.ContentProperty; + if (content.IsCollection) { + foreach (var child in content.CollectionElements) { + foreach (var child2 in DescendantsAndSelf(child)) { + yield return child2; + } + } + } else { + if (content.Value != null) { + foreach (var child2 in DescendantsAndSelf(content.Value)) { + yield return child2; + } + } + } + } + } + + // Filters an element list, dropping all elements that are not part of the xaml document + // (e.g. because they were deleted). + static List GetLiveElements(ICollection items) + { + List result = new List(items.Count); + foreach (DesignItem item in items) { + if (ModelTools.IsInDocument(item) && ModelTools.CanSelectComponent(item)) { + result.Add(item); + } + } + return result; + } + + T GetService() where T : class + { + if (_designContext != null) + return _designContext.Services.GetService(); + else + return null; + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DragDropExceptionHandler.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DragDropExceptionHandler.cs new file mode 100644 index 0000000000..3ccdd8af8f --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/DragDropExceptionHandler.cs @@ -0,0 +1,24 @@ +// +// +// +// +// $Revision: 2573 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Designer +{ + /// + /// When the designer is hosted in a Windows.Forms application, exceptions in + /// drag'n'drop handlers are silently ignored. + /// Applications hosting the designer should specify a delegate to their own exception handling + /// method. The default is Environment.FailFast. + /// + public static class DragDropExceptionHandler + { + public static Action HandleException = delegate(Exception ex) { + Environment.FailFast(ex.ToString()); + }; + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ExtensionMethods.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ExtensionMethods.cs new file mode 100644 index 0000000000..0a87291bd2 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ExtensionMethods.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System.Collections; +using System.Windows; +using System.Windows.Media; +using System.Windows.Input; + +namespace ICSharpCode.WpfDesign.Designer +{ + public static class ExtensionMethods + { + public static double Coerce(this double d, double min, double max) + { + return Math.Max(Math.Min(d, max), min); + } + + public static void AddRange(this ICollection col, IEnumerable items) + { + foreach (var item in items) { + col.Add(item); + } + } + + public static object GetDataContext(this RoutedEventArgs e) + { + var f = e.OriginalSource as FrameworkElement; + if (f != null) { + return f.DataContext; + } + return null; + } + + public static T FindAncestor(this DependencyObject d, string name) where T : class + { + while (true) { + if (d == null) return null; + if (d is T && d is FrameworkElement && (d as FrameworkElement).Name == name) return d as T; + d = VisualTreeHelper.GetParent(d); + } + } + + public static T FindAncestor(this DependencyObject d) where T : class + { + while (true) { + if (d == null) return null; + if (d is T) return d as T; + d = VisualTreeHelper.GetParent(d); + } + } + + public static T FindChild(this DependencyObject d) where T : class + { + if (d is T) return d as T; + int n = VisualTreeHelper.GetChildrenCount(d); + for (int i = 0; i < n; i++) { + var child = VisualTreeHelper.GetChild(d, i); + var result = FindChild(child); + if (result != null) return result; + } + return null; + } + + public static void AddCommandHandler(this UIElement element, ICommand command, Action execute) + { + AddCommandHandler(element, command, execute, null); + } + + public static void AddCommandHandler(this UIElement element, ICommand command, Action execute, Func canExecute) + { + var cb = new CommandBinding(command); + if (canExecute != null) { + cb.CanExecute += delegate(object sender, CanExecuteRoutedEventArgs e) { + e.CanExecute = canExecute(); + e.Handled = true; + }; + } + cb.Executed += delegate(object sender, ExecutedRoutedEventArgs e) { + execute(); + }; + element.CommandBindings.Add(cb); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ModelTools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ModelTools.cs new file mode 100644 index 0000000000..fec97a2ef4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ModelTools.cs @@ -0,0 +1,306 @@ +// +// +// +// +// $Revision: 3518 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Linq; + +namespace ICSharpCode.WpfDesign.Designer +{ + /// + /// Static helper methods for working with the designer DOM. + /// + public static class ModelTools + { + /// + /// Compares the positions of a and b in the model file. + /// + public static int ComparePositionInModelFile(DesignItem a, DesignItem b) + { + // first remember all parent properties of a + HashSet aProps = new HashSet(); + DesignItem tmp = a; + while (tmp != null) { + aProps.Add(tmp.ParentProperty); + tmp = tmp.Parent; + } + + // now walk up b's parent tree until a matching property is found + tmp = b; + while (tmp != null) { + DesignItemProperty prop = tmp.ParentProperty; + if (aProps.Contains(prop)) { + if (prop.IsCollection) { + return prop.CollectionElements.IndexOf(a).CompareTo(prop.CollectionElements.IndexOf(b)); + } + else { + return 0; + } + } + } + return 0; + } + + /// + /// Gets if the specified design item is in the document it belongs to. + /// + /// True for live objects, false for deleted objects. + public static bool IsInDocument(DesignItem item) + { + return item.Context.ModelService.Root == GetRoot(item); + } + + public static DesignItem GetRoot(DesignItem item) + { + while (item.Parent != null) { + item = item.Parent; + } + return item; + } + + /// + /// Gets if the specified components can be deleted. + /// + public static bool CanDeleteComponents(IEnumerable items) + { + IPlacementBehavior b = PlacementOperation.GetPlacementBehavior(items); + return b != null + && b.CanPlace(items, PlacementType.Delete, PlacementAlignment.Center); + } + + public static bool CanSelectComponent(DesignItem item) + { + return item.View != null; + } + + /// + /// Deletes the specified components from their parent containers. + /// If the deleted components are currently selected, they are deselected before they are deleted. + /// + public static void DeleteComponents(IEnumerable items) + { + DesignItem parent = items.First().Parent; + PlacementOperation operation = PlacementOperation.Start(items, PlacementType.Delete); + try { + ISelectionService selectionService = items.First().Context.SelectionService; + selectionService.Select(items, SelectionTypes.Remove); + // if the selection is empty after deleting some components, select the parent of the deleted component + if (selectionService.SelectionCount == 0 && !items.Contains(parent)) { + selectionService.Select(new DesignItem[] { parent }); + } + operation.DeleteItemsAndCommit(); + } + catch { + operation.Abort(); + throw; + } + } + + internal static Size GetDefaultSize(DesignItem createdItem) + { + var s = Metadata.GetDefaultSize(createdItem.ComponentType); + if (double.IsNaN(s.Width)) { + s.Width = GetWidth(createdItem.View); + } + if (double.IsNaN(s.Height)) { + s.Height = GetHeight(createdItem.View); + } + return s; + } + + internal static double GetWidth(UIElement element) + { + double v = (double)element.GetValue(FrameworkElement.WidthProperty); + if (double.IsNaN(v)) + return element.RenderSize.Width; + else + return v; + } + + internal static double GetHeight(UIElement element) + { + double v = (double)element.GetValue(FrameworkElement.HeightProperty); + if (double.IsNaN(v)) + return element.RenderSize.Height; + else + return v; + } + + public static void Resize(DesignItem item, double newWidth, double newHeight) + { + if (newWidth != GetWidth(item.View)) { + item.Properties.GetProperty(FrameworkElement.WidthProperty).SetValue(newWidth); + } + if (newHeight != GetHeight(item.View)) { + item.Properties.GetProperty(FrameworkElement.HeightProperty).SetValue(newHeight); + } + } + + //TODO: Share with Outline / PlacementBehavior + public static IEnumerable DescendantsAndSelf(DesignItem item) + { + yield return item; + foreach (var child in Descendants(item)) { + yield return child; + } + } + + public static IEnumerable Descendants(DesignItem item) + { + foreach (var child in Children(item)) { + foreach (var child2 in DescendantsAndSelf(child)) { + yield return child2; + } + } + } + + public static IEnumerable Children(DesignItem item) + { + var content = item.Content; + if (content != null) { + if (content.IsCollection) { + foreach (var child in content.CollectionElements) { + yield return child; + } + } + else { + if (content.Value != null) { + yield return content.Value; + } + } + } + } + + // Filters an element list, dropping all elements that are not part of the xaml document + // (e.g. because they were deleted). + public static IEnumerable GetLiveElements(IEnumerable items) + { + foreach (DesignItem item in items) { + if (IsInDocument(item) && CanSelectComponent(item)) { + yield return item; + } + } + } + public static bool CanAdd(DesignItem container, IEnumerable items, bool copy) + { + throw new NotImplementedException(); + } + + public static void Add(DesignItem container, IEnumerable items, bool copy) + { + throw new NotImplementedException(); + } + + public static bool CanInsert(DesignItem container, IEnumerable items, DesignItem after, bool copy) + { + throw new NotImplementedException(); + } + + public static void Insert(DesignItem container, IEnumerable items, DesignItem after, bool copy) + { + throw new NotImplementedException(); + } + + public static void Remove(DesignItem item) + { + throw new NotImplementedException(); + } + + public static DesignItem Clone(DesignItem item) + { + throw new NotImplementedException(); + } + + //public void Remove() + //{ + // if (ParentProperty != null) + // { + // if (ParentProperty.IsCollection) + // { + // ParentProperty.CollectionElements.Remove(this); + // } + // else + // { + // ParentProperty.Reset(); + // } + // } + //} + + // TODO: Outline and IPlacementBehavior must use the same logic (put it inside DesignItem) + //public bool CanInsert(IEnumerable nodes, OutlineNode after, bool copy) + //{ + // if (DesignItem.ContentPropertyName == null) return false; + + // if (DesignItem.Content.IsCollection) { + // foreach (var node in nodes) { + // if (!ICSharpCode.Xaml.CollectionSupport.CanCollectionAdd(DesignItem.Content.ReturnType, + // node.DesignItem.ComponentType)) { + // return false; + // } + // } + // return true; + // } + // else { + // return after == null && nodes.Count() == 1 && + // DesignItem.Content.DeclaringType.IsAssignableFrom( + // nodes.First().DesignItem.ComponentType); + // } + //} + + //public void Insert(IEnumerable nodes, OutlineNode after, bool copy) + //{ + // if (copy) { + // nodes = nodes.Select(n => OutlineNode.Create(ModelTools.Clone(n.DesignItem))); + // } + // else { + // foreach (var node in nodes) { + // ModelTools.Remove(node.DesignItem); + // } + // } + + // var index = after == null ? 0 : Children.IndexOf(after) + 1; + + // var content = DesignItem.Content; + // if (content.IsCollection) { + // foreach (var node in nodes) { + // content.CollectionElements.Insert(index++, node.DesignItem); + // } + // } + // else { + // content.SetValue(nodes.First().DesignItem); + // } + //} + + //void UpdateChildren() + //{ + // Children.Clear(); + + // if (DesignItem.ContentPropertyName != null) { + // var content = DesignItem.Content; + // if (content.IsCollection) { + // UpdateChildrenCore(content.CollectionElements); + // } + // else { + // if (content.Value != null) { + // UpdateChildrenCore(new[] { content.Value }); + // } + // } + // } + //} + + //void UpdateChildrenCore(IEnumerable items) + //{ + // foreach (var item in items) { + // if (ModelTools.CanSelectComponent(item)) { + // var node = OutlineNode.Create(item); + // Children.Add(node); + // } + // } + //} + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Properties/AssemblyInfo.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..885478aad2 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +using System.Windows; +using System.Windows.Markup; + +[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] + +[assembly: XmlnsPrefix("http://sharpdevelop.net", "sd")] +[assembly: XmlnsDefinition("http://sharpdevelop.net", "ICSharpCode.WpfDesign.Designer")] +[assembly: XmlnsDefinition("http://sharpdevelop.net", "ICSharpCode.WpfDesign.Designer.Controls")] +[assembly: XmlnsDefinition("http://sharpdevelop.net", "ICSharpCode.WpfDesign.Designer.PropertyGrid")] +[assembly: XmlnsDefinition("http://sharpdevelop.net", "ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors")] + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ServiceRequiredException.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ServiceRequiredException.cs new file mode 100644 index 0000000000..f5905b1470 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/ServiceRequiredException.cs @@ -0,0 +1,58 @@ +// +// +// +// +// $Revision: 2222 $ +// + +using System; +using System.Runtime.Serialization; + +namespace ICSharpCode.WpfDesign.Designer +{ + /// + /// Exception class used for designer failures. + /// + [Serializable] + public class ServiceRequiredException : DesignerException + { + /// + /// Create a new ServiceRequiredException instance. + /// + public ServiceRequiredException(Type serviceType) + : this("Service " + serviceType.FullName + " is required.") + { + } + + /// + /// Create a new ServiceRequiredException instance. + /// + public ServiceRequiredException() + { + } + + /// + /// Create a new ServiceRequiredException instance. + /// + public ServiceRequiredException(string message) + : base(message) + { + } + + /// + /// Create a new ServiceRequiredException instance. + /// + public ServiceRequiredException(string message, Exception innerException) + : base(message, innerException) + { + } + + /// + /// Create a new ServiceRequiredException instance. + /// + protected ServiceRequiredException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/SharedInstances.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/SharedInstances.cs new file mode 100644 index 0000000000..6c7829dc91 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/SharedInstances.cs @@ -0,0 +1,24 @@ +// +// +// +// +// $Revision: 2441 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Designer +{ + static class SharedInstances + { + internal static readonly object BoxedTrue = true; + internal static readonly object BoxedFalse = false; + internal static readonly object[] EmptyObjectArray = new object[0]; + internal static readonly DesignItem[] EmptyDesignItemArray = new DesignItem[0]; + + internal static object Box(bool value) + { + return value ? BoxedTrue : BoxedFalse; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Toolbox.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Toolbox.xaml new file mode 100644 index 0000000000..2c3f17fa8f --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Toolbox.xaml @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Toolbox.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Toolbox.xaml.cs new file mode 100644 index 0000000000..a04b70875a --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Toolbox.xaml.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Drawing; +using System.Windows.Interop; +using System.Windows.Markup; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace ICSharpCode.WpfDesign.Designer +{ + public partial class Toolbox + { + public Toolbox() + { + InitializeComponent(); + uxList.SelectionChanged += new SelectionChangedEventHandler(uxList_SelectionChanged); + ToolService.Instance.CurrentToolChanged += new EventHandler(Instance_CurrentToolChanged); + } + + public static readonly DependencyProperty ContextProperty = + DesignSurface.ContextProperty.AddOwner(typeof(Toolbox)); + + public DesignContext Context + { + get { return (DesignContext)GetValue(ContextProperty); } + set { SetValue(ContextProperty, value); } + } + + public void Load(string content) + { + var data = XamlReader.Parse(content) as ToolboxData; + uxList.ItemsSource = data; + } + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + if (e.Property == ContextProperty) { + OnContextChanged(e.OldValue as DesignContext, e.NewValue as DesignContext); + } + } + + void OnContextChanged(DesignContext oldContext, DesignContext newContext) + { + if (newContext != null) { + ToolService.Instance.SwitchDesignPanel(newContext.DesignPanel); + } + } + + void Instance_CurrentToolChanged(object sender, EventArgs e) + { + var componentTool = ToolService.Instance.CurrentTool as CreateComponentTool; + if (componentTool != null) { + uxList.SelectedValue = componentTool.ComponentType; + } + else { + uxList.UnselectAll(); + } + } + + void uxList_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (uxList.SelectedValue != null) { + ToolService.Instance.CurrentTool = new CreateComponentTool(uxList.SelectedValue as Type); + } + else { + ToolService.Instance.Reset(); + } + } + } + + public class ToolboxData : List + { + } + + public class ToolboxItem + { + public Type Type { get; set; } + public Type FormsType { get; set; } + + public ImageSource Icon + { + get + { + if (FormsType != null) { + var bitmap = ToolboxBitmapAttribute.Default.GetImage(FormsType) as Bitmap; + return Imaging.CreateBitmapSourceFromHBitmap( + bitmap.GetHbitmap(), + IntPtr.Zero, + Int32Rect.Empty, + null); + } + return null; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj new file mode 100644 index 0000000000..3b1ed76e65 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj @@ -0,0 +1,314 @@ + + + {78CC29AC-CC79-4355-B1F2-97936DF198AC} + Debug + AnyCPU + Library + ICSharpCode.WpfDesign.Designer + ICSharpCode.WpfDesign.Designer + False + False + 4 + false + ..\..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ + ..\..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.Designer.xml + 1591 + v3.5 + + + true + Full + True + DEBUG;TRACE + False + + + False + None + False + TRACE + + + False + Auto + 4194304 + AnyCPU + 4096 + + + ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ + ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.Designer.xml + + + + + False + False + 3.0 + + + False + False + 3.0 + + + + + 3.5 + + + + + + 3.0 + + + False + 3.0 + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + EnumBar.xaml + + + + Code + + + + + + + + + + + + + + DesignSurface.xaml + + + + + + Code + + + + + Code + + + + + Code + + + + + + + + + + + + + + + + + + Outline.xaml + Code + + + + + + + BoolEditor.xaml + + + + BrushEditorPopup.xaml + + + BrushEditorView.xaml + + + BrushTypeEditor.xaml + + + + ColorPicker.xaml + + + GradientBrushEditor.xaml + + + GradientSlider.xaml + + + + + SolidBrushEditor.xaml + + + EventEditor.xaml + + + NumberEditor.xaml + + + PropertyContextMenu.xaml + + + + PropertyGridView.xaml + + + + + ChooseClassDialog.xaml + + + + + + + + + + + + Code + + + + + + + + + + Toolbox.xaml + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + + + Designer + MSBuild:Compile + + + + + + + + + + + + + + + + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD} + Xaml + + + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F} + WpfDesign + + + \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/WpfProject.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/WpfProject.cs new file mode 100644 index 0000000000..cf7cdc00e4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/WpfProject.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.Xaml; + +namespace ICSharpCode.WpfDesign.Designer.XamlBackend +{ + public class WpfProject : XamlProject + { + public WpfProject() + { + Metadata.RegisterAssembly(typeof(WpfProject).Assembly); + } + } + + public class DefaultWpfProject : WpfProject + { + public DefaultWpfProject() + { + AddReference(XamlConstants.MscorlibAssembly); + AddReference(XamlConstants.WindowsBaseAssembly); + AddReference(XamlConstants.PresentationCoreAssembly); + AddReference(XamlConstants.PresentationFrameworkAssembly); + + foreach (var item in AllAssemblies) { + TypeFinder.RegisterAssembly(item); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlComponentService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlComponentService.cs new file mode 100644 index 0000000000..48cf4aede6 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlComponentService.cs @@ -0,0 +1,49 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using ICSharpCode.Xaml; +using System.Windows.Markup; + +namespace ICSharpCode.WpfDesign.Designer.XamlBackend +{ + class XamlComponentService : IComponentService + { + public XamlComponentService(XamlDesignContext context) + { + this.context = context; + } + + XamlDesignContext context; + + DesignItem RegisterComponentForDesigner(ObjectNode objectNode) + { + XamlDesignItem item = new XamlDesignItem(objectNode, context); + objectNode.Annotate(item); + if (ComponentRegistered != null) + { + ComponentRegistered(this, new DesignItemEventArgs(item)); + } + return item; + } + + public DesignItem RegisterXamlComponentRecursive(ObjectNode objectNode) + { + foreach (var node in objectNode.Descendants().OfType()) + { + RegisterComponentForDesigner(node); + } + return RegisterComponentForDesigner(objectNode); + } + + #region IComponentService Members + + public event EventHandler ComponentRegistered; + + public DesignItem RegisterComponentForDesigner(object component) + { + return RegisterComponentForDesigner(context.Document.CreateObject(component)); + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignContext.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignContext.cs new file mode 100644 index 0000000000..9387351fdc --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignContext.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.Xaml; +using System.IO; +using ICSharpCode.WpfDesign.Designer.Services; +using System.ComponentModel; +using System.Windows.Input; + +namespace ICSharpCode.WpfDesign.Designer.XamlBackend +{ + public class XamlDesignContext : DesignContext + { + public XamlDesignContext(XamlDocument doc) + { + this.doc = doc; + var modelService = new XamlModelService(this); + + AddService(typeof(IModelService), modelService); + AddService(typeof(IDesignPanel), new DesignPanel() { Context = this }); + AddService(typeof(ICommandService), new CommandService(this)); + AddService(typeof(ISelectionService), new DefaultSelectionService()); + AddService(typeof(IToolService), Services.ToolService.Instance); + AddService(typeof(IUndoService), new UndoService(this)); + AddService(typeof(IErrorService), new DefaultErrorService(this)); + AddService(typeof(IViewService), new ViewService(this)); + AddService(typeof(OptionService), new OptionService()); + AddService(typeof(ITopLevelWindowService), new WpfTopLevelWindowService()); + + foreach (var assembly in Metadata.RegisteredAssemblies) { + ExtensionManager.RegisterAssembly(assembly); + } + + modelService.Initialize(); + } + + XamlDocument doc; + + public XamlDocument Document + { + get { return doc; } + } + + public override void Parse(string text) + { + doc.Parse(text); + ParseSuggested = false; + } + + public override bool CanSave + { + get { return doc.CanSave; } + } + + public override string Save() + { + return doc.Save(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItem.cs new file mode 100644 index 0000000000..dd85ec7ae0 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItem.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.Xaml; +using System.Windows; + +namespace ICSharpCode.WpfDesign.Designer.XamlBackend +{ + public class XamlDesignItem : DesignItem, IHasAnnotations + { + public XamlDesignItem(ObjectNode objectNode, XamlDesignContext designContext) + { + this.objectNode = objectNode; + this.designContext = designContext; + this.properties = new XamlDesignItemPropertyCollection(this); + } + + ObjectNode objectNode; + XamlDesignContext designContext; + XamlDesignItemPropertyCollection properties; + + public override event ModelChangedEventHandler ModelChanged; + + public ObjectNode ObjectNode + { + get { return objectNode; } + } + + public override object Component + { + get { return objectNode.Instance; } + } + + public override Type ComponentType + { + get { return objectNode.Type.SystemType; } + } + + public override UIElement View + { + get { return Component as UIElement; } + } + + public override DesignContext Context + { + get { return designContext; } + } + + public override DesignItem Parent + { + get + { + if (objectNode.ParentMember == null) { + return null; + } + var parentObject = objectNode.ParentMember.ParentObject; + if (parentObject == null) { + return null; + } + if (parentObject.IsRetrieved) { + parentObject = parentObject.ParentMember.ParentObject; + } + return parentObject.GetAnnotation(); + } + } + + public override DesignItemProperty ParentProperty + { + get + { + if (objectNode.ParentMember == null) { + return null; + } + return XamlDesignItemProperty.Create(this, objectNode.ParentMember.Property); + } + } + + public override DesignItemPropertyCollection Properties + { + get { return properties; } + } + + public override string Name + { + get + { + return objectNode.Name; + } + set + { + objectNode.Name = value; + var args = new ModelChangedEventArgs() { + Property = XamlDesignItemProperty.Create(this, objectNode.Property(Directive.Name)) + }; + RaiseModelChanged(args); + } + } + + public override DesignItemProperty Content + { + get + { + if (objectNode.Content != null) { + return XamlDesignItemProperty.Create(this, objectNode.Content); + } + return null; + } + } + + internal void RaiseModelChanged(ModelChangedEventArgs e) + { + if (ModelChanged != null) { + ModelChanged(this, e); + } + (Context.ModelService as XamlModelService).RaiseModelChanged(e); + } + + #region IHasAnnotations Members + + public void AnnotateWith(T annotation) where T : class + { + objectNode.AnnotateWith(annotation); + } + + public T GetAnnotation() where T : class + { + return objectNode.GetAnnotation(); + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemCollection.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemCollection.cs new file mode 100644 index 0000000000..260aefdc49 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemCollection.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections.ObjectModel; +using ICSharpCode.Xaml; + +namespace ICSharpCode.WpfDesign.Designer.XamlBackend +{ + class XamlDesignItemCollection : Collection + { + public XamlDesignItemCollection(XamlDesignItemProperty designProperty) + { + this.designProperty = designProperty; + + foreach (var objectNode in designProperty.XamlProperty.Collection.OfType()) + { + this.Items.Add(objectNode.GetAnnotation()); + } + } + + XamlDesignItemProperty designProperty; + + protected override void InsertItem(int index, DesignItem item) + { + designProperty.DesignItem.Context.UndoService.Execute(new InsertAction(this, index, item)); + } + + protected override void RemoveItem(int index) + { + designProperty.DesignItem.Context.UndoService.Execute(new RemoveAction(this, index)); + } + + protected override void SetItem(int index, DesignItem item) + { + RemoveItem(index); + InsertItem(index, item); + } + + protected override void ClearItems() + { + while (Count > 0) + { + RemoveItem(Count - 1); + } + } + + void InsertCore(int index, DesignItem item) + { + this.Items.Insert(index, item); + designProperty.XamlProperty.Collection.Insert(index, (item as XamlDesignItem).ObjectNode); + + var args = new ModelChangedEventArgs() { + Property = designProperty, + NewItem = item + }; + designProperty.XamlDesignItem.RaiseModelChanged(args); + } + + void RemoveCore(int index, DesignItem item) + { + this.Items.RemoveAt(index); + designProperty.XamlProperty.Collection.RemoveAt(index); + + var args = new ModelChangedEventArgs() { + Property = designProperty, + OldItem = item + }; + designProperty.XamlDesignItem.RaiseModelChanged(args); + } + + class InsertAction : IUndoAction + { + public InsertAction(XamlDesignItemCollection collection, int index, DesignItem item) + { + this.collection = collection; + this.index = index; + this.item = item; + } + + XamlDesignItemCollection collection; + int index; + DesignItem item; + + public IEnumerable AffectedItems + { + get { return new DesignItem[] { item }; } + } + + public string Title + { + get { return "Insert into collection"; } + } + + public void Do() + { + collection.InsertCore(index, item); + } + + public void Undo() + { + collection.RemoveCore(index, item); + } + } + + class RemoveAction : IUndoAction + { + public RemoveAction(XamlDesignItemCollection collection, int index) + { + this.collection = collection; + this.index = index; + this.item = collection[index]; + } + + XamlDesignItemCollection collection; + int index; + DesignItem item; + + public IEnumerable AffectedItems + { + get { return new DesignItem[] { item }; } + } + + public string Title + { + get { return "Remove from collection"; } + } + + public void Do() + { + collection.RemoveCore(index, item); + } + + public void Undo() + { + collection.InsertCore(index, item); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemProperty.cs new file mode 100644 index 0000000000..fc1ec4859b --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemProperty.cs @@ -0,0 +1,237 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.Xaml; +using ICSharpCode.WpfDesign.Designer.Services; +using System.Windows; + +namespace ICSharpCode.WpfDesign.Designer.XamlBackend +{ + public class XamlDesignItemProperty : DesignItemProperty + { + public static XamlDesignItemProperty Create(XamlDesignItem designItem, XamlProperty xamlProperty) + { + var result = xamlProperty.GetAnnotation(); + if (result == null) { + result = new XamlDesignItemProperty(designItem, xamlProperty); + xamlProperty.AnnotateWith(result); + } + return result; + } + + XamlDesignItemProperty(XamlDesignItem designItem, XamlProperty xamlProperty) + { + this.designItem = designItem; + this.xamlProperty = xamlProperty; + if (IsCollection) { + this.collectionElements = new XamlDesignItemCollection(this); + } + } + + XamlDesignItem designItem; + XamlProperty xamlProperty; + XamlDesignItemCollection collectionElements; + static IList emptyCollectionElements = new DesignItem[] { }; + + public override event EventHandler IsSetChanged; + public override event EventHandler ValueChanged; + public override event EventHandler ValueOnInstanceChanged; + + public XamlDesignItem XamlDesignItem + { + get { return designItem; } + } + + public XamlProperty XamlProperty + { + get { return xamlProperty; } + } + + public XamlMember XamlMember + { + get { return xamlProperty.Member; } + } + + public override string Name + { + get { return XamlMember.Name; } + } + + public override Type ReturnType + { + get { return XamlMember.ValueType.SystemType; } + } + + public override Type DeclaringType + { + get { return XamlMember.OwnerType.SystemType; } + } + + public override string Category + { + get { throw new NotImplementedException(); } + } + + public override bool IsCollection + { + get { return XamlMember.ValueType.IsCollection; } + } + + public override bool IsEvent + { + get { return XamlMember.IsEvent; } + } + + public override IList CollectionElements + { + get { return collectionElements ?? emptyCollectionElements; } + } + + public override DesignItem Value + { + get + { + if (xamlProperty.IsSet) { + return xamlProperty.Value.GetAnnotation(); + } + return null; + } + } + + public override object ValueOnInstance + { + get + { + return xamlProperty.ValueOnInstance; + } + set + { + throw new NotImplementedException(); + } + } + + public override bool IsSet + { + get { return xamlProperty.IsSet; } + } + + public override bool IsNameProperty + { + get { return XamlProperty.Member.IsNameProperty; } + } + + public override DesignItem DesignItem + { + get { return designItem; } + } + + public override DependencyProperty DependencyProperty + { + get { return null; } + } + + public override bool IsAdvanced + { + get { throw new NotImplementedException(); } + } + + public override void SetValue(object value) + { + var newValue = xamlProperty.PrepareValue(value); + var action = new PropertyChangeAction(this, newValue, true); + designItem.Context.UndoService.Execute(action); + } + + public override void Reset() + { + var action = new PropertyChangeAction(this, null, false); + designItem.Context.UndoService.Execute(action); + xamlProperty.Reset(); + } + + void SetValueCore(XamlValue value) + { + xamlProperty.Set(value); + var args = new ModelChangedEventArgs() { + Property = this + }; + designItem.RaiseModelChanged(args); + } + + void ResetCore() + { + if (xamlProperty.IsSet) { + xamlProperty.Reset(); + var args = new ModelChangedEventArgs() { + Property = this, + }; + designItem.RaiseModelChanged(args); + } + } + + class PropertyChangeAction : IUndoAction + { + public PropertyChangeAction(XamlDesignItemProperty designProperty, XamlValue newValue, bool newIsSet) + { + this.designProperty = designProperty; + this.newValue = newValue; + this.newIsSet = newIsSet; + + oldIsSet = designProperty.IsSet; + oldValue = designProperty.XamlProperty.Value; + } + + XamlDesignItemProperty designProperty; + XamlValue oldValue; + XamlValue newValue; + bool oldIsSet; + bool newIsSet; + + public string Title + { + get + { + if (newIsSet) + return "Set " + designProperty.Name; + else + return "Reset " + designProperty.Name; + } + } + + public void Do() + { + if (newIsSet) + designProperty.SetValueCore(newValue); + else + designProperty.ResetCore(); + } + + public void Undo() + { + if (oldIsSet) + designProperty.SetValueCore(oldValue); + else + designProperty.ResetCore(); + } + + public IEnumerable AffectedItems + { + get + { + return new DesignItem[] { designProperty.DesignItem }; + } + } + + public bool MergeWith(PropertyChangeAction other) + { + if (designProperty.XamlMember == other.designProperty.XamlMember) { + newIsSet = other.newIsSet; + newValue = other.newValue; + return true; + } + return false; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemPropertyCollection.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemPropertyCollection.cs new file mode 100644 index 0000000000..c0b2731870 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlDesignItemPropertyCollection.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.WpfDesign.Designer.XamlBackend +{ + class XamlDesignItemPropertyCollection : DesignItemPropertyCollection + { + public XamlDesignItemPropertyCollection(XamlDesignItem item) + { + this.item = item; + } + + XamlDesignItem item; + + public override DesignItemProperty GetProperty(string name) + { + return XamlDesignItemProperty.Create(item, item.ObjectNode.Property(name)); + } + + public override DesignItemProperty GetAttachedProperty(Type ownerType, string name) + { + return XamlDesignItemProperty.Create(item, item.ObjectNode.Property(ownerType, name)); + } + + public override IEnumerator GetEnumerator() + { + yield break; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlModelService.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlModelService.cs new file mode 100644 index 0000000000..974a008264 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/XamlBackend/XamlModelService.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.Xaml; + +namespace ICSharpCode.WpfDesign.Designer.XamlBackend +{ + public class XamlModelService : IModelService + { + public XamlModelService(XamlDesignContext context) + { + this.context = context; + } + + public void Initialize() + { + context.Document.RootChanged += new EventHandler(doc_RootChanged); + UpdateRoot(); + } + + XamlDesignContext context; + DesignItem root; + + public event EventHandler RootChanged; + public event ModelChangedEventHandler ModelChanged; + public event EventHandler ItemCreated; + + public DesignItem Root + { + get { return root; } + set { Document.Root = (value as XamlDesignItem).ObjectNode; } + } + + XamlDocument Document + { + get { return context.Document; } + } + + DesignPanel DesignPanel + { + get { return context.DesignPanel as DesignPanel; } + } + + public string ClassName + { + get + { + if (Document.Root != null) { + return Document.Root.Property(Directive.Class).ValueText; + } + return null; + } + } + + public DesignItem CreateItem(object component) + { + return CreateItem(Document.CreateObject(component)); + } + + DesignItem CreateItemRecursive(ObjectNode objectNode) + { + foreach (var node in objectNode.Descendants().OfType()) { + CreateItem(node); + } + return CreateItem(objectNode); + } + + DesignItem CreateItem(ObjectNode objectNode) + { + var result = objectNode.GetAnnotation(); + if (result == null) { + result = new XamlDesignItem(objectNode, context); + objectNode.AnnotateWith(result); + if (ItemCreated != null) { + ItemCreated(this, new DesignItemEventArgs(result)); + } + } + return result; + } + + internal void RaiseModelChanged(ModelChangedEventArgs e) + { + if (ModelChanged != null) { + ModelChanged(this, e); + } + } + + void doc_RootChanged(object sender, EventArgs e) + { + UpdateRoot(); + } + + void UpdateRoot() + { + root = null; + DesignPanel.Child = null; + + if (Document.Root != null) { + root = CreateItemRecursive(Document.Root); + DesignPanel.Child = root.View; + } + + context.SelectionService.Select(null); + + if (RootChanged != null) { + RootChanged(this, EventArgs.Empty); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Properties/AssemblyInfo.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..e02abfc9b0 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj new file mode 100644 index 0000000000..3b81d29053 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj @@ -0,0 +1,99 @@ + + + {943DBBB3-E84E-4CF4-917C-C05AFA8743C1} + Debug + AnyCPU + Library + ICSharpCode.WpfDesign.Tests + ICSharpCode.WpfDesign.Tests + ..\..\..\..\..\..\bin\UnitTests\ + False + False + 4 + false + + + 2.0 + + + false + + + v3.5 + + + true + Full + True + DEBUG;TRACE + False + + + False + None + False + TRACE + + + False + Auto + 4194304 + AnyCPU + 4096 + + + ..\..\..\..\..\bin\UnitTests\ + + + + + ..\..\..\..\..\Tools\NUnit\nunit.framework.dll + False + + + + + + 3.5 + + + + 3.5 + + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + + + + + + + + + + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD} + Xaml + + + {78CC29AC-CC79-4355-B1F2-97936DF198AC} + WpfDesign.Designer + + + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F} + WpfDesign + + + \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/app.config b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/app.config new file mode 100644 index 0000000000..e531f7e030 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/app.config @@ -0,0 +1,15 @@ + + + + +
+ + + + + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln index 8e9b6fbf80..d388742d0a 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.sln @@ -1,17 +1,23 @@  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.XamlDom", "WpfDesign.XamlDom\Project\WpfDesign.XamlDom.csproj", "{88DA149F-21B2-48AB-82C4-28FB6BDFD783}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.AddIn", "WpfDesign.AddIn\WpfDesign.AddIn.csproj", "{9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.Designer", "WpfDesign.Designer\Project\WpfDesign.Designer.csproj", "{78CC29AC-CC79-4355-B1F2-97936DF198AC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlDesigner", "..\..\..\..\samples\XamlDesigner\XamlDesigner.csproj", "{27DA2B5C-2AAA-4478-AB00-3E184273C241}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign", "WpfDesign\Project\WpfDesign.csproj", "{66A378A1-E9F4-4AD5-8946-D0EC06C2902F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign", "WpfDesign\WpfDesign.csproj", "{66A378A1-E9F4-4AD5-8946-D0EC06C2902F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.Tests", "WpfDesign.Designer\Tests\WpfDesign.Tests.csproj", "{943DBBB3-E84E-4CF4-917C-C05AFA8743C1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.Tests", "WpfDesign.Tests\WpfDesign.Tests.csproj", "{943DBBB3-E84E-4CF4-917C-C05AFA8743C1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.AddIn", "WpfDesign.AddIn\WpfDesign.AddIn.csproj", "{9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.Designer", "WpfDesign.Designer\WpfDesign.Designer.csproj", "{78CC29AC-CC79-4355-B1F2-97936DF198AC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlDesigner", "..\..\..\..\samples\XamlDesigner\XamlDesigner.csproj", "{27DA2B5C-2AAA-4478-AB00-3E184273C241}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xaml", "..\..\BackendBindings\Xaml\Xaml\Xaml.csproj", "{B4E5C965-7BB9-4AE9-85FB-C47480B879AD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xaml.Tests", "..\..\BackendBindings\Xaml\Xaml.Tests\Xaml.Tests.csproj", "{EDF67E30-F45F-40C5-8B68-4A22FFD02A2E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlBinding", "..\..\BackendBindings\Xaml\XamlBinding\XamlBinding.csproj", "{7C96B65D-28A5-4F28-A35B-8D83CE831EE8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlBinding.Tests", "..\..\BackendBindings\Xaml\XamlBinding.Tests\XamlBinding.Tests.csproj", "{F390DA70-1FE1-4715-81A0-389AB010C130}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -19,22 +25,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Debug|Any CPU.Build.0 = Debug|Any CPU - {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Release|Any CPU.ActiveCfg = Release|Any CPU - {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Release|Any CPU.Build.0 = Release|Any CPU - {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Release|Any CPU.Build.0 = Release|Any CPU - {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Release|Any CPU.Build.0 = Release|Any CPU - {943DBBB3-E84E-4CF4-917C-C05AFA8743C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {943DBBB3-E84E-4CF4-917C-C05AFA8743C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {943DBBB3-E84E-4CF4-917C-C05AFA8743C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {943DBBB3-E84E-4CF4-917C-C05AFA8743C1}.Release|Any CPU.Build.0 = Release|Any CPU {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}.Debug|Any CPU.Build.0 = Debug|Any CPU {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -43,6 +33,34 @@ Global {27DA2B5C-2AAA-4478-AB00-3E184273C241}.Debug|Any CPU.Build.0 = Debug|Any CPU {27DA2B5C-2AAA-4478-AB00-3E184273C241}.Release|Any CPU.ActiveCfg = Release|Any CPU {27DA2B5C-2AAA-4478-AB00-3E184273C241}.Release|Any CPU.Build.0 = Release|Any CPU + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Release|Any CPU.Build.0 = Release|Any CPU + {943DBBB3-E84E-4CF4-917C-C05AFA8743C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {943DBBB3-E84E-4CF4-917C-C05AFA8743C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {943DBBB3-E84E-4CF4-917C-C05AFA8743C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {943DBBB3-E84E-4CF4-917C-C05AFA8743C1}.Release|Any CPU.Build.0 = Release|Any CPU + {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Release|Any CPU.Build.0 = Release|Any CPU + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD}.Release|Any CPU.Build.0 = Release|Any CPU + {EDF67E30-F45F-40C5-8B68-4A22FFD02A2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDF67E30-F45F-40C5-8B68-4A22FFD02A2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDF67E30-F45F-40C5-8B68-4A22FFD02A2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDF67E30-F45F-40C5-8B68-4A22FFD02A2E}.Release|Any CPU.Build.0 = Release|Any CPU + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Release|Any CPU.Build.0 = Release|Any CPU + {F390DA70-1FE1-4715-81A0-389AB010C130}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F390DA70-1FE1-4715-81A0-389AB010C130}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F390DA70-1FE1-4715-81A0-389AB010C130}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F390DA70-1FE1-4715-81A0-389AB010C130}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/ChangeGroup.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/ChangeGroup.cs new file mode 100644 index 0000000000..73114932db --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/ChangeGroup.cs @@ -0,0 +1,47 @@ +// +// +// +// +// $Revision: 2237 $ +// + +using System; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Base class for change groups. + /// + public abstract class ChangeGroup : IDisposable + { + string title; + + /// + /// Gets/Sets the title of the change group. + /// + public string Title { + get { return title; } + set { title = value; } + } + + /// + /// Commits the change group. + /// + public abstract void Commit(); + + /// + /// Aborts the change group. + /// + public abstract void Abort(); + + /// + /// Is called when the change group is disposed. Should Abort the change group if it is not already committed. + /// + protected abstract void Disposed(); + + void IDisposable.Dispose() + { + Disposed(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignContext.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignContext.cs new file mode 100644 index 0000000000..94fca705ef --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignContext.cs @@ -0,0 +1,140 @@ +// +// +// +// +// $Revision: 3509 $ +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Xml; +using System.IO; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign +{ + /// + /// The context that the designer uses. + /// + public abstract class DesignContext : ServiceContainer + { + /// + /// Creates a new DesignContext instance. + /// + protected DesignContext() + { + AddService(typeof(ExtensionManager), new ExtensionManager(this)); + } + + public bool ParseSuggested { get; set; } + + public abstract void Parse(string text); + + /// + /// Gets whether the design context can be saved. + /// + public abstract bool CanSave { get; } + + /// + /// Save the designed elements to stream. + /// + public abstract string Save(); + + /// + /// Gets the . + /// Throws an exception if the service is not found. + /// + public ISelectionService SelectionService + { + get + { + return GetServiceOrThrowException(); + } + } + + /// + /// Gets the . + /// Throws an exception if the service is not found. + /// + public IToolService ToolService + { + get + { + return GetServiceOrThrowException(); + } + } + + /// + /// Gets the . + /// Throws an exception if the service is not found. + /// + public IViewService ViewService + { + get + { + return GetServiceOrThrowException(); + } + } + + /// + /// Gets the . + /// Throws an exception if the service is not found. + /// + public ExtensionManager ExtensionManager + { + get + { + return GetServiceOrThrowException(); + } + } + + /// + /// Gets the . + /// Throws an exception if the service is not found. + /// + public IDesignPanel DesignPanel + { + get + { + return GetServiceOrThrowException(); + } + } + + /// + /// Gets the . + /// Throws an exception if the service is not found. + /// + public IUndoService UndoService + { + get + { + return GetServiceOrThrowException(); + } + } + + /// + /// Gets the . + /// Throws an exception if the service is not found. + /// + public IModelService ModelService + { + get + { + return GetServiceOrThrowException(); + } + } + + /// + /// Gets the . + /// Throws an exception if the service is not found. + /// + public ICommandService CommandService + { + get + { + return GetServiceOrThrowException(); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignItem.cs new file mode 100644 index 0000000000..3823758cf3 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignItem.cs @@ -0,0 +1,219 @@ +// +// +// +// +// $Revision: 3283 $ +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Windows; + +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign +{ + /// + /// The DesignItem connects a component with the service system and the designers. + /// Equivalent to Cider's ModelItem. + /// + public abstract class DesignItem + { + /// + /// Gets the component this DesignSite was created for. + /// + public abstract object Component { get; } + + /// + /// Gets the component type of this design site. + /// This value may be different from Component.GetType() if a CustomInstanceFactory created + /// an object using a different type (e.g. ComponentType=Window but Component.GetType()=WindowClone). + /// + public abstract Type ComponentType { get; } + + /// + /// Gets the view used for the component. + /// + public abstract UIElement View { get; } + + /// + /// Gets the design context. + /// + public abstract DesignContext Context { get; } + + /// + /// Gets the parent design item. + /// + public abstract DesignItem Parent { get; } + + /// + /// Gets the property where this DesignItem is used as a value. + /// + public abstract DesignItemProperty ParentProperty { get; } + + /// + /// Gets properties set on the design item. + /// + public abstract DesignItemPropertyCollection Properties { get; } + + /// + /// Gets/Sets the name of the design item. + /// + public abstract string Name { get; set; } + + public abstract DesignItemProperty Content { get; } + + public string ContentPropertyName + { + get + { + if (Content != null) { + return Content.Name; + } + return null; + } + } + + /// + /// Opens a new change group used to batch several changes. + /// ChangeGroups work as transactions and are used to support the Undo/Redo system. + /// Note: the ChangeGroup applies to the whole , not just to + /// this item! + /// + public IChangeGroup OpenGroup(string changeGroupTitle) + { + return Context.UndoService.OpenGroup(changeGroupTitle, new DesignItem[] { this }); + } + + /// + /// This event is raised whenever a model property on the DesignItem changes. + /// + public abstract event ModelChangedEventHandler ModelChanged; + + public override string ToString() + { + return GetType().Name + ": " + ComponentType.Name; + } + + #region Extensions support + private struct ExtensionEntry + { + internal readonly Extension Extension; + internal readonly ExtensionServer Server; + + public ExtensionEntry(Extension extension, ExtensionServer server) + { + this.Extension = extension; + this.Server = server; + } + } + + ExtensionServer[] _extensionServers; + bool[] _extensionServerIsApplied; + + List _extensions = new List(); + + /// + /// Gets the extensions registered for this DesignItem. + /// + public IEnumerable Extensions + { + get + { + foreach (ExtensionEntry entry in _extensions) { + yield return entry.Extension; + } + } + } + + internal void SetExtensionServers(ExtensionManager extensionManager, ExtensionServer[] extensionServers) + { + Debug.Assert(_extensionServers == null); + Debug.Assert(extensionServers != null); + + _extensionServers = extensionServers; + _extensionServerIsApplied = new bool[extensionServers.Length]; + + for (int i = 0; i < _extensionServers.Length; i++) { + bool shouldApply = _extensionServers[i].ShouldApplyExtensions(this); + if (shouldApply != _extensionServerIsApplied[i]) { + _extensionServerIsApplied[i] = shouldApply; + ApplyUnapplyExtensionServer(extensionManager, shouldApply, _extensionServers[i]); + } + } + } + + internal void ReapplyExtensionServer(ExtensionManager extensionManager, ExtensionServer server) + { + Debug.Assert(_extensionServers != null); + + for (int i = 0; i < _extensionServers.Length; i++) { + if (_extensionServers[i] == server) { + bool shouldApply = server.ShouldApplyExtensions(this); + if (shouldApply != _extensionServerIsApplied[i]) { + _extensionServerIsApplied[i] = shouldApply; + ApplyUnapplyExtensionServer(extensionManager, shouldApply, server); + } + } + } + } + + private void ApplyUnapplyExtensionServer(ExtensionManager extensionManager, bool shouldApply, ExtensionServer server) + { + if (shouldApply) { + // add extensions + foreach (Extension ext in extensionManager.CreateExtensions(server, this)) { + _extensions.Add(new ExtensionEntry(ext, server)); + } + } + else { + // remove extensions + _extensions.RemoveAll( + delegate(ExtensionEntry entry) { + if (entry.Server == server) { + server.RemoveExtension(entry.Extension); + return true; + } + else { + return false; + } + }); + } + } + #endregion + + #region Manage behavior + readonly 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"); + if (!bevahiorInterface.IsInstanceOfType(behaviorImplementation)) + throw new ArgumentException("behaviorImplementation must implement bevahiorInterface", "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/DesignItemProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignItemProperty.cs new file mode 100644 index 0000000000..1e9aba51bf --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignItemProperty.cs @@ -0,0 +1,208 @@ +// +// +// +// +// $Revision: 3434 $ +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Windows; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Represents a property of a DesignItem. + /// All changes done via the DesignItemProperty class are represented in the underlying model (e.g. XAML). + /// All such changes are recorded in the currently running designer transaction (), + /// enabling Undo/Redo support. + /// Warning: Changes directly done to control instances might not be reflected in the model. + /// + public abstract class DesignItemProperty + { + /// + /// Gets the property name. + /// + public abstract string Name { get; } + + /// + /// Gets the return type of the property. + /// + public abstract Type ReturnType { get; } + + /// + /// Gets the type that declares the property. + /// + public abstract Type DeclaringType { get; } + + /// + /// Gets the category of the property. + /// + public abstract string Category { get; } + + /// + /// Gets the type converter used to convert property values to/from string. + /// + public virtual TypeConverter TypeConverter + { + get { return TypeDescriptor.GetConverter(this.ReturnType); } + } + + /// + /// Gets if the property represents a collection. + /// + public abstract bool IsCollection { get; } + + /// + /// Gets if the property represents an event. + /// + public abstract bool IsEvent { get; } + + /// + /// Gets the elements represented by the collection. + /// + public abstract IList CollectionElements { get; } + + /// + /// Gets the value of the property. This property returns null if the value is not set, + /// or if the value is set to a primitive value. + /// + public abstract DesignItem Value { get; } + + /// + /// Is raised when the value of the property changes (by calling or ). + /// + public abstract event EventHandler ValueChanged; + + public abstract event EventHandler ValueOnInstanceChanged; + + /// + /// 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! + /// + public abstract object ValueOnInstance { get; set; } + + /// + /// Sets the value of the property. + /// + public abstract void SetValue(object value); + + /// + /// Gets if the property is set on the design item. + /// + public abstract bool IsSet { get; } + + public abstract bool IsNameProperty { get; } + + /// + /// Occurs when the value of the IsSet property changes. + /// + public abstract event EventHandler IsSetChanged; + + /// + /// Resets the property value to the default, possibly removing it from the list of properties. + /// + public abstract void Reset(); + + public abstract DesignItem DesignItem { get; } + + public abstract DependencyProperty DependencyProperty { get; } + + public abstract bool IsAdvanced { get; } + + public string FullName + { + get + { + return DeclaringType.FullName + "." + Name; + } + } + + public string DependencyFullName + { + get + { + if (DependencyProperty != null) { + return DependencyProperty.GetFullName(); + } + return FullName; + } + } + + public override string ToString() + { + return GetType().Name + ": " + Name; + } + } + + /// + /// Represents a collection of design item properties. + /// + public abstract class DesignItemPropertyCollection : IEnumerable + { + /// + /// Gets the property with the specified name. + /// + public DesignItemProperty this[string name] + { + get { return GetProperty(name); } + } + + /// + /// Gets the design item property representing the specified dependency property. + /// The property must not be an attached property. + /// + public DesignItemProperty this[DependencyProperty dependencyProperty] + { + get + { + Debug.Assert(DependencyPropertyDescriptor.FromProperty(dependencyProperty, dependencyProperty.OwnerType).IsAttached == false); + return GetProperty(dependencyProperty); + } + } + + /// + /// Gets the design item property with the specified name. + /// + public abstract DesignItemProperty GetProperty(string name); + + /// + /// Gets the attached property on the specified owner with the specified name. + /// + public abstract DesignItemProperty GetAttachedProperty(Type ownerType, string name); + + /// + /// Gets the design item property representing the specified dependency property. + /// The property must not be an attached property. + /// + public DesignItemProperty GetProperty(DependencyProperty dependencyProperty) + { + if (dependencyProperty == null) + throw new ArgumentNullException("dependencyProperty"); + return GetProperty(dependencyProperty.Name); + } + + /// + /// Gets the design item property representing the specified attached dependency property. + /// + public DesignItemProperty GetAttachedProperty(DependencyProperty dependencyProperty) + { + if (dependencyProperty == null) + throw new ArgumentNullException("dependencyProperty"); + return GetAttachedProperty(dependencyProperty.OwnerType, dependencyProperty.Name); + } + + /// + /// Gets an enumerator to enumerate the properties that have a non-default value. + /// + public abstract IEnumerator GetEnumerator(); + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignPanelHitTestResult.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignPanelHitTestResult.cs new file mode 100644 index 0000000000..2b6567f3b1 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignPanelHitTestResult.cs @@ -0,0 +1,113 @@ +// +// +// +// +// $Revision: 2439 $ +// + +using System; +using System.Windows; +using System.Windows.Media; +using ICSharpCode.WpfDesign.Adorners; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Describes the result of a call. + /// + public struct DesignPanelHitTestResult : IEquatable + { + /// + /// Represents the result that nothing was hit. + /// + public static readonly DesignPanelHitTestResult NoHit = new DesignPanelHitTestResult(); + + readonly Visual _visualHit; + AdornerPanel _adornerHit; + DesignItem _modelHit; + + /// + /// The actual visual that was hit. + /// + public Visual VisualHit + { + get { return _visualHit; } + } + + /// + /// The adorner panel containing the adorner that was hit. + /// + public AdornerPanel AdornerHit + { + get { return _adornerHit; } + set { _adornerHit = value; } + } + + /// + /// The model item that was hit. + /// + public DesignItem ModelHit + { + get { return _modelHit; } + set { _modelHit = value; } + } + + /// + /// Create a new DesignPanelHitTestResult instance. + /// + public DesignPanelHitTestResult(Visual visualHit) + { + this._visualHit = visualHit; + this._adornerHit = null; + this._modelHit = null; + } + + #region Equals and GetHashCode implementation + // The code in this region is useful if you want to use this structure in collections. + // If you don't need it, you can just remove the region and the ": IEquatable" declaration. + + /// + /// Tests if this hit test result equals the other result. + /// + public override bool Equals(object obj) + { + if (obj is DesignPanelHitTestResult) + return Equals((DesignPanelHitTestResult)obj); // use Equals method below + else + return false; + } + + /// + /// Tests if this hit test result equals the other result. + /// + public bool Equals(DesignPanelHitTestResult other) + { + // add comparisions for all members here + return _visualHit == other._visualHit && _adornerHit == other._adornerHit && _modelHit == other._modelHit; + } + + /// + /// Gets the hash code. + /// + public override int GetHashCode() + { + // combine the hash codes of all members here (e.g. with XOR operator ^) + return (_visualHit != null ? _visualHit.GetHashCode() : 0) + ^ (_adornerHit != null ? _adornerHit.GetHashCode() : 0) + ^ (_modelHit != null ? _modelHit.GetHashCode() : 0); + } + + /// + public static bool operator ==(DesignPanelHitTestResult lhs, DesignPanelHitTestResult rhs) + { + return lhs.Equals(rhs); + } + + /// + public static bool operator !=(DesignPanelHitTestResult lhs, DesignPanelHitTestResult rhs) + { + return !(lhs.Equals(rhs)); // use operator == and negate result + } + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignerException.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignerException.cs new file mode 100644 index 0000000000..07f1990a04 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/DesignerException.cs @@ -0,0 +1,50 @@ +// +// +// +// +// $Revision: 2220 $ +// + +using System; +using System.Runtime.Serialization; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Exception class used for designer failures. + /// + [Serializable] + public class DesignerException : Exception + { + /// + /// Create a new DesignerException instance. + /// + public DesignerException() + { + } + + /// + /// Create a new DesignerException instance. + /// + public DesignerException(string message) + : base(message) + { + } + + /// + /// Create a new DesignerException instance. + /// + public DesignerException(string message, Exception innerException) + : base(message, innerException) + { + } + + /// + /// Create a new DesignerException instance. + /// + protected DesignerException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/EventArgs.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/EventArgs.cs new file mode 100644 index 0000000000..8fd6b88e4b --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/EventArgs.cs @@ -0,0 +1,60 @@ +// +// +// +// +// $Revision: 2222 $ +// + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Event arguments specifying a component as parameter. + /// + public class DesignItemEventArgs : EventArgs + { + readonly DesignItem _item; + + /// + /// Creates a new ComponentEventArgs instance. + /// + public DesignItemEventArgs(DesignItem item) + { + _item = item; + } + + /// + /// The component affected by the event. + /// + public DesignItem Item + { + get { return _item; } + } + } + + /// + /// Event arguments specifying a component as parameter. + /// + public class DesignItemCollectionEventArgs : EventArgs + { + readonly ICollection _items; + + /// + /// Creates a new ComponentCollectionEventArgs instance. + /// + public DesignItemCollectionEventArgs(ICollection items) + { + _items = items; + } + + /// + /// The components affected by the event. + /// + public ICollection Items + { + get { return _items; } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/HashSet.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/HashSet.cs new file mode 100644 index 0000000000..cb74b84b61 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/HashSet.cs @@ -0,0 +1,202 @@ +// +// +// +// +// $Revision: 3285 $ +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Represents a set of items. The set does not preserve the order of items and does not allow items to + /// be added twice. + /// It supports collection change notifications and is cloned by sharing the underlying + /// data structure and delaying the actual copy until the next change. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] + public sealed class HashSet : ICollection, ICollection, ICloneable, INotifyCollectionChanged + where T : class + { + Dictionary _dict; + bool _copyOnWrite; + + /// + /// This event is raised whenever the collection changes. + /// + public event NotifyCollectionChangedEventHandler CollectionChanged; + + /// + /// Creates a new, empty set. + /// + public HashSet() + { + _dict = new Dictionary(); + } + + /// + /// Creates a copy of the existing set. + /// + public HashSet(HashSet existingSet) + { + existingSet._copyOnWrite = true; + this._copyOnWrite = true; + _dict = existingSet._dict; + } + + /// + /// Adds the item to the set. + /// Trying to add null will return false without changing the collection. + /// + /// True when the item was added, false when it was not added because it already is in the set + public bool Add(T item) + { + if (item == null) + return false; + if (_dict.ContainsKey(item)) { + return false; + } else { + CopyIfRequired(); + _dict.Add(item, null); + if (CollectionChanged != null) { + CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); + } + return true; + } + } + + /// + /// Adds a list of items to the set. This is equivalent to calling for each item in . + /// + public void AddRange(IEnumerable items) + { + foreach (T item in items) { + Add(item); + } + } + + private void CopyIfRequired() + { + if (_copyOnWrite) { + _copyOnWrite = false; + _dict = new Dictionary(_dict); + } + } + + /// + /// Removes all items from the set. + /// + public void Clear() + { + _dict.Clear(); + } + + /// + /// Tests if this set contains the specified item. + /// Checking for null always returns false. + /// + public bool Contains(T item) + { + if (item == null) + return false; + else + return _dict.ContainsKey(item); + } + + /// + /// Gets the number of items in the collection. + /// + public int Count { + get { return _dict.Count; } + } + + /// + /// Removes an item from the set. + /// Trying to remove null will return false without changing the collection. + /// + public bool Remove(T item) + { + if (item == null) + return false; + CopyIfRequired(); + if (_dict.Remove(item)) { + if (CollectionChanged != null) { + CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); + } + return true; + } else { + return false; + } + } + + /// + /// Copy all items to the specified array. + /// + void ICollection.CopyTo(T[] array, int arrayIndex) + { + _dict.Keys.CopyTo(array, arrayIndex); + } + + void ICollection.Add(T item) + { + this.Add(item); + } + + bool ICollection.IsReadOnly { + get { return false; } + } + + #region IEnumerable Members + /// + /// Gets an enumerator to enumerate the items in the set. + /// + public IEnumerator GetEnumerator() + { + return _dict.Keys.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _dict.Keys.GetEnumerator(); + } + #endregion + + #region ICollection Members + + void ICollection.CopyTo(Array array, int index) + { + ((ICollection)_dict).CopyTo(array, index); + } + + bool ICollection.IsSynchronized { + get { return false; } + } + + object ICollection.SyncRoot { + get { return null; } + } + + #endregion + + #region ICloneable Members + + /// + /// Create a copy of this set. + /// + public HashSet Clone() + { + return new HashSet(this); + } + + object ICloneable.Clone() + { + return this.Clone(); + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Metadata.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Metadata.cs new file mode 100644 index 0000000000..66bff1fb9b --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Metadata.cs @@ -0,0 +1,413 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Reflection; +using System.Collections; +using System.Windows; +using System.ComponentModel; +using System.Diagnostics; + +namespace ICSharpCode.WpfDesign +{ + public static class Metadata + { + public static string GetFullName(this DependencyProperty p) + { + return p.OwnerType.FullName + "." + p.Name; + } + + //static Dictionary> standardValues = new Dictionary>(); + + //public static void AddStandardValues(Type type, Type valuesContainer) + //{ + // AddStandardValues(type, valuesContainer + // .GetProperties(BindingFlags.Public | BindingFlags.Static) + // .Select(p => p.GetValue(null, null))); + //} + + //public static void AddStandardValues(Type type, IEnumerable values) + //{ + // List list; + // lock (standardValues) { + // if (!standardValues.TryGetValue(type, out list)) { + // list = new List(); + // standardValues[type] = list; + // } + // foreach (var v in values) { + // list.Add(v); + // if (StandardValueAdded != null) { + // StandardValueAdded(null, new StandardValueEventArgs() { StandardValue = v }); + // } + // } + // } + //} + + //public static IEnumerable GetStandardValues(Type type) + //{ + // if (type.IsEnum) { + // return Enum.GetValues(type); + // } + // List values; + // lock (standardValues) { + // if (standardValues.TryGetValue(type, out values)) { + // return values; + // } + // } + // return null; + //} + + static Dictionary> standardValues = new Dictionary>(); + static Dictionary standardValueFromInstance = new Dictionary(); + + public static void AddStandardValues(Type type, Type valuesContainer) + { + AddStandardValues(type, valuesContainer + .GetProperties(BindingFlags.Public | BindingFlags.Static) + .Select(p => new StandardValue() { + Instance = p.GetValue(null, null), + Text = p.Name + })); + } + + public static void AddStandardValues(Type type, IEnumerable values) + { + List list; + lock (standardValues) { + lock (standardValueFromInstance) { + if (!standardValues.TryGetValue(type, out list)) { + list = new List(); + standardValues[type] = list; + } + foreach (var v in values) { + list.Add(v); + standardValueFromInstance[v.Instance] = v; + + if (StandardValueAdded != null) { + StandardValueAdded(null, new StandardValueEventArgs() { + Type = type, + StandardValue = v + }); + } + } + } + } + } + + public static IEnumerable GetStandardValues(Type type) + { + if (type.IsEnum) { + var enumValues = Enum.GetValues(type); + var enumNames = Enum.GetNames(type); + + for (int i = 0; i < enumValues.Length; i++) { + yield return new StandardValue() { + Instance = enumValues.GetValue(i), + Text = enumNames[i], + }; + } + } + List values; + lock (standardValues) { + if (standardValues.TryGetValue(type, out values)) { + foreach (var value in values) { + yield return value; + } + } + } + } + + public static StandardValue GetStandardValue(object value) + { + lock (standardValueFromInstance) { + StandardValue standardValue; + if (standardValueFromInstance.TryGetValue(value, out standardValue)) { + return standardValue; + } + } + return null; + } + + //static Dictionary categories = new Dictionary(); + + //public static void AddCategory(DependencyProperty p, string category) + //{ + // lock (categories) { + // categories[p.GetFullName()] = category; + // } + //} + + //public static void AddCategory(Type type, string property, string category) + //{ + // lock (categories) { + // categories[type + "." + property] = category; + // } + //} + + //public static string GetCategory(DesignItemProperty p) + //{ + // string result; + // lock (categories) { + // if (categories.TryGetValue(p.DependencyFullName, out result)) { + // return result; + // } + // } + // return p.Category; + //} + + //static HashSet advancedProperties = new HashSet(); + + //public static void AddAdvancedProperty(DependencyProperty p) + //{ + // lock (advancedProperties) { + // advancedProperties.Add(p.GetFullName()); + // } + //} + + //public static void AddAdvancedProperty(Type type, string member) + //{ + // lock (advancedProperties) { + // advancedProperties.Add(type.FullName + "." + member); + // } + //} + + //public static bool IsAdvanced(DesignItemProperty p) + //{ + // lock (advancedProperties) { + // if (advancedProperties.Contains(p.DependencyFullName)) { + // return true; + // } + // } + // return p.IsAdvanced; + //} + + static HashSet hiddenProperties = new HashSet(); + + public static void HideProperty(DependencyProperty p) + { + lock (hiddenProperties) { + hiddenProperties.Add(p.GetFullName()); + } + } + + public static void HideProperty(Type type, string member) + { + lock (hiddenProperties) { + hiddenProperties.Add(type.FullName + "." + member); + } + } + + public static bool IsBrowsable(DesignItemProperty p) + { + lock (hiddenProperties) { + if (hiddenProperties.Contains(p.DependencyFullName)) { + return false; + } + } + return true; + } + + //public static string[] CategoryOrder { get; set; } + + static HashSet popularProperties = new HashSet(); + + public static void AddPopularProperty(DependencyProperty p) + { + lock (popularProperties) { + popularProperties.Add(p.GetFullName()); + } + } + + public static void AddPopularProperty(Type type, string member) + { + lock (popularProperties) { + popularProperties.Add(type.FullName + "." + member); + } + } + + public static bool IsPopularProperty(DesignItemProperty p) + { + lock (popularProperties) { + if (popularProperties.Contains(p.DependencyFullName)) { + return true; + } + } + return false; + } + + //static HashSet popularControls = new HashSet(); + + //public static void AddPopularControl(Type t) + //{ + // lock (popularControls) { + // popularControls.Add(t); + // } + //} + + //public static IEnumerable GetPopularControls() + //{ + // lock (popularControls) { + // foreach (var t in popularControls) { + // yield return t; + // } + // } + //} + + //public static bool IsPopularControl(Type t) + //{ + // lock (popularControls) { + // return popularControls.Contains(t); + // } + //} + + static Dictionary ranges = new Dictionary(); + + public static void AddValueRange(DependencyProperty p, double min, double max) + { + lock (ranges) { + ranges[p.GetFullName()] = new NumberRange() { Min = min, Max = max }; + } + } + + public static NumberRange GetValueRange(DesignItemProperty p) + { + NumberRange r; + lock (ranges) { + if (ranges.TryGetValue(p.DependencyFullName, out r)) { + return r; + } + } + return null; + } + + static HashSet placementDisabled = new HashSet(); + + public static void DisablePlacement(Type type) + { + lock (placementDisabled) { + placementDisabled.Add(type); + } + } + + public static bool IsPlacementDisabled(Type type) + { + lock (placementDisabled) { + return placementDisabled.Contains(type); + } + } + + static Dictionary defaultSizes = new Dictionary(); + + public static void AddDefaultSize(Type t, Size s) + { + lock (defaultSizes) { + defaultSizes[t] = s; + } + } + + public static Size GetDefaultSize(Type t) + { + Size s; + lock (defaultSizes) { + while (t != null) { + if (defaultSizes.TryGetValue(t, out s)) { + return s; + } + t = t.BaseType; + } + } + return new Size(double.NaN, double.NaN); + } + + static Dictionary typeReplacers = new Dictionary(); + + public static void AddTypeReplacer(Type type, Type replacer) + { + lock (typeReplacers) { + typeReplacers[type] = replacer; + if (TypeReplacerAdded != null) { + TypeReplacerAdded(null, new TypeEventArgs() { Type = type }); + } + } + } + + public static Type GetTypeReplacer(Type type) + { + Type replacer; + lock (typeReplacers) { + typeReplacers.TryGetValue(type, out replacer); + return replacer; + } + } + + static HashSet registeredAssemblies = new HashSet(); + + public static IEnumerable RegisteredAssemblies + { + get { return registeredAssemblies; } + } + + public static void RegisterAssembly(Assembly assembly) + { + if (!registeredAssemblies.Contains(assembly)) { + + ICSharpCode.WpfDesign.PropertyGrid.EditorManager.RegisterAssembly(assembly); + + foreach (var t in assembly.GetTypes()) { + if (t.GetInterface("IRegisterMetadata") == typeof(IRegisterMetadata)) { + var m = Activator.CreateInstance(t) as IRegisterMetadata; + m.Register(); + } + } + foreach (var t in assembly.GetTypes()) { + foreach (ReplacerForAttribute a in t.GetCustomAttributes(typeof(ReplacerForAttribute), false)) { + AddTypeReplacer(a.Type, t); + } + } + + registeredAssemblies.Add(assembly); + } + } + + public static event EventHandler StandardValueAdded; + public static event EventHandler TypeReplacerAdded; + } + + public class StandardValueEventArgs : EventArgs + { + public Type Type; + public StandardValue StandardValue; + } + + public class TypeEventArgs : EventArgs + { + public Type Type; + } + + public class StandardValue + { + public object Instance; + public string Text; + } + + public class NumberRange + { + public double Min; + public double Max; + } + + public class ReplacerForAttribute : Attribute + { + public ReplacerForAttribute(Type type) + { + this.Type = type; + } + + public Type Type { get; private set; } + } + + public interface IRegisterMetadata + { + void Register(); + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/MouseInteraction.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/MouseInteraction.cs new file mode 100644 index 0000000000..50eeff7bf3 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/MouseInteraction.cs @@ -0,0 +1,29 @@ +// +// +// +// +// $Revision: 2415 $ +// + +using System; +using System.Windows; +using System.Windows.Input; + +using ICSharpCode.WpfDesign.Adorners; + +namespace ICSharpCode.WpfDesign +{ + // Interfaces for mouse interaction on the design surface. + + /// + /// Behavior interface implemented by elements to handle the mouse down event + /// on them. + /// + public interface IHandlePointerToolMouseDown + { + /// + /// Called to handle the mouse down event. + /// + void HandleSelectionMouseDown(IDesignPanel designPanel, MouseButtonEventArgs e, DesignPanelHitTestResult result); + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementAlignment.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementAlignment.cs new file mode 100644 index 0000000000..efa9a39bdd --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementAlignment.cs @@ -0,0 +1,109 @@ +// +// +// +// +// $Revision: 2441 $ +// + +using System; +using System.Windows; + +namespace ICSharpCode.WpfDesign +{ + /// + /// A combination of HorizontalAlignment/VerticalAlignment. + /// + public struct PlacementAlignment : IEquatable + { + readonly HorizontalAlignment horizontal; + readonly VerticalAlignment vertical; + + /// + /// Gets the horizontal component. + /// + public HorizontalAlignment Horizontal + { + get { return horizontal; } + } + + /// + /// Gets the vertical component. + /// + public VerticalAlignment Vertical + { + get { return vertical; } + } + + /// + /// Creates a new instance of the PlacementAlignment structure. + /// + public PlacementAlignment(HorizontalAlignment horizontal, VerticalAlignment vertical) + { + if (horizontal == HorizontalAlignment.Stretch) + throw new ArgumentException("Strech is not a valid value", "horizontal"); + if (vertical == VerticalAlignment.Stretch) + throw new ArgumentException("Strech is not a valid value", "vertical"); + this.horizontal = horizontal; + this.vertical = vertical; + } + + #region Equals and GetHashCode implementation + /// Compares this to . + public override bool Equals(object obj) + { + if (obj is PlacementAlignment) + return Equals((PlacementAlignment)obj); // use Equals method below + else + return false; + } + + /// Compares this to . + public bool Equals(PlacementAlignment other) + { + return this.horizontal == other.horizontal && this.vertical == other.vertical; + } + + /// + /// Gets the hash code. + /// + public override int GetHashCode() + { + unchecked { + return horizontal.GetHashCode() * 27 + vertical.GetHashCode(); + } + } + + /// Compares to . + public static bool operator ==(PlacementAlignment lhs, PlacementAlignment rhs) + { + return lhs.Equals(rhs); + } + + /// Compares to . + public static bool operator !=(PlacementAlignment lhs, PlacementAlignment rhs) + { + return !(lhs.Equals(rhs)); + } + #endregion + + + /// Top left + public static readonly PlacementAlignment TopLeft = new PlacementAlignment(HorizontalAlignment.Left, VerticalAlignment.Top); + /// Top center + public static readonly PlacementAlignment Top = new PlacementAlignment(HorizontalAlignment.Center, VerticalAlignment.Top); + /// Top right + public static readonly PlacementAlignment TopRight = new PlacementAlignment(HorizontalAlignment.Right, VerticalAlignment.Top); + /// Center left + public static readonly PlacementAlignment Left = new PlacementAlignment(HorizontalAlignment.Left, VerticalAlignment.Center); + /// Center center + public static readonly PlacementAlignment Center = new PlacementAlignment(HorizontalAlignment.Center, VerticalAlignment.Center); + /// Center right + public static readonly PlacementAlignment Right = new PlacementAlignment(HorizontalAlignment.Right, VerticalAlignment.Center); + /// Bottom left + public static readonly PlacementAlignment BottomLeft = new PlacementAlignment(HorizontalAlignment.Left, VerticalAlignment.Bottom); + /// Bottom center + public static readonly PlacementAlignment Bottom = new PlacementAlignment(HorizontalAlignment.Center, VerticalAlignment.Bottom); + /// Bottom right + public static readonly PlacementAlignment BottomRight = new PlacementAlignment(HorizontalAlignment.Right, VerticalAlignment.Bottom); + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementBehavior.cs new file mode 100644 index 0000000000..bd3f19f675 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementBehavior.cs @@ -0,0 +1,75 @@ +// +// +// +// +// $Revision: 3337 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Behavior interface implemented by container elements to support resizing + /// child elements. + /// + public interface IPlacementBehavior + { + /// + /// Gets if the child element can be resized. + /// + bool CanPlace(IEnumerable childItems, PlacementType type, PlacementAlignment position); + + /// + /// Starts placement mode for this container. + /// + void BeginPlacement(PlacementOperation operation); + + /// + /// Ends placement mode for this container. + /// + void EndPlacement(PlacementOperation operation); + + /// + /// Gets the original position of the child item. + /// + Rect GetPosition(PlacementOperation operation, DesignItem child); + + void BeforeSetPosition(PlacementOperation operation); + + /// + /// Updates the placement of the element specified in the placement operation. + /// + void SetPosition(PlacementInformation info); + + /// + /// Gets if leaving this container is allowed for the specified operation. + /// + bool CanLeaveContainer(PlacementOperation operation); + + /// + /// Remove the placed children from this container. + /// + void LeaveContainer(PlacementOperation operation); + + /// + /// Gets if entering this container is allowed for the specified operation. + /// + bool CanEnterContainer(PlacementOperation operation); + + /// + /// Let the placed children enter this container. + /// + void EnterContainer(PlacementOperation operation); + } + + /// + /// Behavior interface for root elements (elements where item.Parent is null). + /// Is used instead of to support resizing the root element. + /// + public interface IRootPlacementBehavior : IPlacementBehavior + { + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementInformation.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementInformation.cs new file mode 100644 index 0000000000..d70b1f8ceb --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementInformation.cs @@ -0,0 +1,64 @@ +// +// +// +// +// $Revision: 3337 $ +// + +using System; +using System.Windows; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Stores information about the placement of an individual item during a . + /// + public sealed class PlacementInformation + { + Rect originalBounds, bounds; + readonly DesignItem item; + readonly PlacementOperation operation; + + internal PlacementInformation(DesignItem item, PlacementOperation operation) + { + this.item = item; + this.operation = operation; + } + + /// + /// The item being placed. + /// + public DesignItem Item + { + get { return item; } + } + + /// + /// The to which this PlacementInformation belongs. + /// + public PlacementOperation Operation + { + get { return operation; } + } + + /// + /// Gets/sets the original bounds. + /// + public Rect OriginalBounds + { + get { return originalBounds; } + set { originalBounds = value; } + } + + /// + /// Gets/sets the current bounds of the item. + /// + public Rect Bounds + { + get { return bounds; } + set { bounds = value; } + } + + public PlacementAlignment ResizeThumbAlignment { get; set; } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementOperation.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementOperation.cs new file mode 100644 index 0000000000..a5dd0cb16c --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementOperation.cs @@ -0,0 +1,302 @@ +// +// +// +// +// $Revision: 3077 $ +// + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Diagnostics; +using System.Windows; +using System.Windows.Input; + +using ICSharpCode.WpfDesign.Adorners; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Stores data about a placement operation. + /// + public sealed class PlacementOperation + { + readonly IChangeGroup changeGroup; + readonly ReadOnlyCollection placedItems; + readonly PlacementType type; + DesignItem currentContainer; + IPlacementBehavior currentContainerBehavior; + bool isAborted, isCommitted; + + #region Properties + /// + /// The items being placed. + /// + public ReadOnlyCollection PlacedItems + { + get { return placedItems; } + } + + /// + /// The type of the placement being done. + /// + public PlacementType Type + { + get { return type; } + } + + /// + /// Gets if the placement operation was aborted. + /// + public bool IsAborted + { + get { return isAborted; } + } + + /// + /// Gets if the placement operation was committed. + /// + public bool IsCommitted + { + get { return isCommitted; } + } + + /// + /// Gets the current container for the placement operation. + /// + public DesignItem CurrentContainer + { + get { return currentContainer; } + } + + /// + /// Gets the placement behavior for the current container. + /// + public IPlacementBehavior CurrentContainerBehavior + { + get { return currentContainerBehavior; } + } + + #endregion + + #region Container changing + /// + /// Make the placed item switch the container. + /// This method assumes that you already have checked if changing the container is possible. + /// + public void ChangeContainer(DesignItem newContainer) + { + if (newContainer == null) + throw new ArgumentNullException("newContainer"); + if (isAborted || isCommitted) + throw new InvalidOperationException("The operation is not running anymore."); + if (currentContainer == newContainer) + return; + + if (!currentContainerBehavior.CanLeaveContainer(this)) + throw new NotSupportedException("The items cannot be removed from their parent container."); + + try { + currentContainerBehavior.LeaveContainer(this); + + System.Windows.Media.GeneralTransform transform = currentContainer.View.TransformToVisual(newContainer.View); + foreach (PlacementInformation info in placedItems) { + info.OriginalBounds = transform.TransformBounds(info.OriginalBounds); + info.Bounds = transform.TransformBounds(info.Bounds); + } + + currentContainer = newContainer; + currentContainerBehavior = newContainer.GetBehavior(); + + Debug.Assert(currentContainerBehavior != null); + currentContainerBehavior.EnterContainer(this); + } + catch (Exception ex) { + Debug.WriteLine(ex.ToString()); + Abort(); + throw; + } + } + #endregion + + #region Delete Items + /// + /// Deletes the items being placed, and commits the placement operation. + /// + public void DeleteItemsAndCommit() + { + if (isAborted || isCommitted) + throw new InvalidOperationException("The operation is not running anymore."); + if (!currentContainerBehavior.CanLeaveContainer(this)) + throw new NotSupportedException("The items cannot be removed from their parent container."); + + currentContainerBehavior.LeaveContainer(this); + Commit(); + } + #endregion + + #region Start + /// + /// Starts a new placement operation that changes the placement of . + /// + /// The items to be placed. + /// The type of the placement. + /// A PlacementOperation object. + /// + /// You MUST call either or on the returned PlacementOperation + /// once you are done with it, otherwise a ChangeGroup will be left open and Undo/Redo will fail to work! + /// + public static PlacementOperation Start(IEnumerable placedItems, PlacementType type) + { + if (placedItems == null) + throw new ArgumentNullException("placedItems"); + if (type == null) + throw new ArgumentNullException("type"); + DesignItem[] items = placedItems.ToArray(); + if (items.Length == 0) + throw new ArgumentException("placedItems.Length must be > 0"); + + PlacementOperation op = new PlacementOperation(items, type); + try { + if (op.currentContainerBehavior == null) + throw new InvalidOperationException("Starting the operation is not supported"); + + op.currentContainerBehavior.BeginPlacement(op); + foreach (PlacementInformation info in op.placedItems) { + info.OriginalBounds = op.currentContainerBehavior.GetPosition(op, info.Item); + info.Bounds = info.OriginalBounds; + } + } + catch (Exception ex) { + Debug.WriteLine(ex.ToString()); + op.changeGroup.Abort(); + throw; + } + return op; + } + private PlacementOperation(DesignItem[] items, PlacementType type) + { + PlacementInformation[] information = new PlacementInformation[items.Length]; + for (int i = 0; i < information.Length; i++) { + information[i] = new PlacementInformation(items[i], this); + } + this.placedItems = new ReadOnlyCollection(information); + this.type = type; + + this.currentContainer = items[0].Parent; + this.currentContainerBehavior = GetPlacementBehavior(items); + + this.changeGroup = items[0].Context.UndoService.OpenGroup(type.ToString(), items); + } + + /// + /// Gets the placement behavior associated with the specified items. + /// + public static IPlacementBehavior GetPlacementBehavior(IEnumerable items) + { + if (items == null) + throw new ArgumentNullException("items"); + if (items.Count() == 0) + return null; + DesignItem parent = items.First().Parent; + foreach (DesignItem item in items.Skip(1)) { + if (item.Parent != parent) + return null; + } + if (parent != null) + return parent.GetBehavior(); + else if (items.Count() == 1) + return items.First().GetBehavior(); + else + return null; + } + #endregion + + #region StartInsertNewComponents + /// + /// Try to insert new components into the container. + /// + /// The container that should become the parent of the components. + /// The components to add to the container. + /// The rectangle specifying the position the element should get. + /// The type + /// The operation that inserts the new components, or null if inserting is not possible. + public static PlacementOperation TryStartInsertNewComponents(DesignItem container, IList placedItems, IList positions, PlacementType type) + { + if (container == null) + throw new ArgumentNullException("container"); + if (placedItems == null) + throw new ArgumentNullException("placedItems"); + if (positions == null) + throw new ArgumentNullException("positions"); + if (type == null) + throw new ArgumentNullException("type"); + if (placedItems.Count == 0) + throw new ArgumentException("placedItems.Count must be > 0"); + if (placedItems.Count != positions.Count) + throw new ArgumentException("positions.Count must be = placedItems.Count"); + + DesignItem[] items = placedItems.ToArray(); + + PlacementOperation op = new PlacementOperation(items, type); + try { + for (int i = 0; i < items.Length; i++) { + op.placedItems[i].OriginalBounds = op.placedItems[i].Bounds = positions[i]; + } + op.currentContainer = container; + op.currentContainerBehavior = container.GetBehavior(); + if (op.currentContainerBehavior == null || !op.currentContainerBehavior.CanEnterContainer(op)) { + op.changeGroup.Abort(); + return null; + } + op.currentContainerBehavior.EnterContainer(op); + } + catch (Exception ex) { + Debug.WriteLine(ex.ToString()); + op.changeGroup.Abort(); + throw; + } + return op; + } + #endregion + + #region ChangeGroup handling + /// + /// Gets/Sets the description of the underlying change group. + /// + public string Description + { + get { return changeGroup.Title; } + } + + /// + /// Aborts the operation. + /// This aborts the underlying change group, reverting all changes done while the operation was running. + /// + public void Abort() + { + if (!isAborted) { + if (isCommitted) + throw new InvalidOperationException("PlacementOperation is committed."); + isAborted = true; + currentContainerBehavior.EndPlacement(this); + changeGroup.Abort(); + } + } + + /// + /// Commits the operation. + /// This commits the underlying change group. + /// + public void Commit() + { + if (isAborted || isCommitted) + throw new InvalidOperationException("PlacementOperation is already aborted/committed."); + isCommitted = true; + currentContainerBehavior.EndPlacement(this); + changeGroup.Commit(); + } + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementType.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementType.cs new file mode 100644 index 0000000000..9e10e2b2d9 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PlacementType.cs @@ -0,0 +1,67 @@ +// +// +// +// +// $Revision: 2443 $ +// + +using System; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Describes how a placement is done. + /// + public sealed class PlacementType + { + /// + /// Placement is done by resizing an element in a drag'n'drop operation. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly PlacementType Resize = Register("Resize"); + + /// + /// Placement is done by moving an element in a drag'n'drop operation. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly PlacementType Move = Register("Move"); + + /// + /// Adding an element to a specified position in the container. + /// AddItem is used when dragging a toolbox item to the design surface. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly PlacementType AddItem = Register("AddItem"); + + /// + /// Not a "real" placement, but deleting the element. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly PlacementType Delete = Register("Delete"); + + readonly string name; + + private PlacementType(string name) + { + this.name = name; + } + + /// + /// Creates a new unique PlacementKind. + /// + /// The name to return from a ToString() call. + /// Note that two PlacementTypes with the same name are NOT equal! + public static PlacementType Register(string name) + { + return new PlacementType(name); + } + + /// + /// Gets the name used to register this PlacementType. + /// + public override string ToString() + { + return name; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Properties/AssemblyInfo.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..8c114539a1 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System; + +[assembly: CLSCompliant(true)] diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/ServiceContainer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/ServiceContainer.cs new file mode 100644 index 0000000000..c5942f059d --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/ServiceContainer.cs @@ -0,0 +1,114 @@ +// +// +// +// +// $Revision: 3511 $ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign +{ + /// + /// The is a built-in service that manages the list of services. + /// You can only add services to it, removing or replacing services is not supported because + /// many designers depend on keeping their services available. + /// + public class ServiceContainer : IServiceProvider + { + readonly Dictionary _services = new Dictionary(); + readonly Dictionary _waitingSubscribers = new Dictionary(); + + /// + /// Gets a collection of all registered services. + /// + public IEnumerable AllServices + { + get + { + return _services.Values; + } + } + + /// + /// Adds a new service to the container. + /// + /// + /// The type of the service interface to use as a key for the service. + /// + /// + /// The service instance implementing that interface. + /// + public void AddService(Type serviceInterface, object serviceInstance) + { + if (serviceInterface == null) + throw new ArgumentNullException("serviceInterface"); + if (serviceInstance == null) + throw new ArgumentNullException("serviceInstance"); + + //TODO: replace required by ITopLevelWindowService + _services[serviceInterface] = serviceInstance; + + Delegate subscriber; + if (_waitingSubscribers.TryGetValue(serviceInterface, out subscriber)) { + _waitingSubscribers.Remove(serviceInterface); + subscriber.DynamicInvoke(serviceInstance); + } + } + + /// + /// Gets the service object of the specified type. + /// Returns null when the service is not available. + /// + public object GetService(Type serviceType) + { + object instance; + _services.TryGetValue(serviceType, out instance); + return instance; + } + + /// + /// Gets the service object of the type T. + /// Returns null when the service is not available. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")] + public T GetService() where T : class + { + return (T)GetService(typeof(T)); + } + + public T GetServiceOrThrowException() where T : class + { + T service = (T)GetService(typeof(T)); + if (service == null) { + throw new DesignerException("Could not find guaranteed service " + typeof(T).FullName); + } + return service; + } + + /// + /// Subscribes to the service of type T. + /// serviceAvailableAction will be called after the service gets available. If the service is already available, + /// the action will be called immediately. + /// + public void SubscribeToService(Action serviceAvailableAction) where T : class + { + T service = GetService(); + if (service != null) { + serviceAvailableAction(service); + } + else { + Type serviceInterface = typeof(T); + Delegate existingSubscriber; + if (_waitingSubscribers.TryGetValue(serviceInterface, out existingSubscriber)) { + _waitingSubscribers[serviceInterface] = Delegate.Combine(existingSubscriber, serviceAvailableAction); + } + else { + _waitingSubscribers[serviceInterface] = serviceAvailableAction; + } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Services.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Services.cs new file mode 100644 index 0000000000..5fbb1473b6 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Services.cs @@ -0,0 +1,303 @@ +// +// +// +// +// $Revision: 3246 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; + +namespace ICSharpCode.WpfDesign +{ + #region ISelectionService + /// + /// Defines the type how a selection can be changed. + /// + [Flags] + public enum SelectionTypes + { + /// + /// No selection type specified. + /// + None = 0, + /// + /// Automatically determine the selection type using the currently pressed + /// modifier keys. + /// + Auto = 1, + /// + /// Change the primary selection only. + /// + Primary = 2, + /// + /// Toggle the selection. + /// + Toggle = 4, + /// + /// Add to the selection. + /// + Add = 8, + /// + /// Remove from the selection. + /// + Remove = 0x10, + /// + /// Replace the selection. + /// + Replace = 0x20 + } + + /// + /// Manages selecting components. + /// + public interface ISelectionService + { + /// Occurs when the current selection is about to change. + event EventHandler SelectionChanging; + + /// Occurs after the current selection has changed. + event EventHandler SelectionChanged; + + /// Occurs when the primary selection is about to change. + event EventHandler PrimarySelectionChanging; + /// Occurs after the primary selection has changed. + event EventHandler PrimarySelectionChanged; + + /// + /// Gets if the specified component is selected. + /// + bool IsSelected(DesignItem item); + + /// + /// Gets the collection of selected components. + /// This is a copy of the actual selected components collection, the returned copy + /// of the collection will not reflect future changes to the selection. + /// + IEnumerable SelectedItems { get; } + + /// Gets the count of selected objects. + /// The number of selected objects. + int SelectionCount { get; } + + /// + /// Replaces the current selection with the specified selection. + /// + void Select(IEnumerable items); + + /// + /// Modifies the current selection using the specified components and selectionType. + /// + void Select(IEnumerable items, SelectionTypes selectionType); + + /// Gets the object that is currently the primary selected object. + /// The object that is currently the primary selected object. + DesignItem PrimarySelection { get; } + } + #endregion + + #region IViewService + /// + /// Service for getting the view for a model or the model for a view. + /// + public interface IViewService + { + /// + /// Gets the model represented by the specified view element. + /// + DesignItem GetModel(DependencyObject view); + + /// + /// Gets the view for the specified model item. + /// This is equivalent to using model.View. + /// + DependencyObject GetView(DesignItem model); + } + #endregion + + #region IPropertyDescriptionService + /// + /// Used to get a description for properties. + /// + public interface IPropertyDescriptionService + { + /// + /// Gets a WPF object representing a graphical description of the property. + /// + object GetDescription(DesignItemProperty property); + } + #endregion + + #region IErrorService + /// + /// Service for showing error UI. + /// + public interface IErrorService + { + /// + /// Shows an error tool tip. + /// + void ShowErrorTooltip(FrameworkElement attachTo, UIElement errorElement); + } + #endregion + + #region IEventHandlerService + /// + /// Service for providing the designer with information about available event handlers. + /// + public interface IEventHandlerService + { + /// + /// Creates an event handler for the specified event. + /// + void CreateEventHandler(DesignItemProperty eventProperty); + + /// + /// Gets the default event of the specified design item. + /// + DesignItemProperty GetDefaultEvent(DesignItem item); + } + #endregion + + #region ITopLevelWindowService + /// + /// Represents a top level window. + /// + public interface ITopLevelWindow + { + /// + /// Sets child.Owner to the top level window. + /// + void SetOwner(Window child); + + /// + /// Activates the window. + /// + bool Activate(); + } + + /// + /// Provides a method to get the top-level-window of any UIElement. + /// If the WPF Designer is hosted inside a Windows.Forms application, the hosting environment + /// should specify a ITopLevelWindowService implementation that works with both WPF and Windows.Forms + /// top-level-windows. + /// + public interface ITopLevelWindowService + { + /// + /// Gets the top level window that contains the specified element. + /// + ITopLevelWindow GetTopLevelWindow(UIElement element); + } + #endregion + + #region IUndoService + + public interface IUndoAction + { + /// + /// The list of items affected by the action. + /// + IEnumerable AffectedItems { get; } + + /// + /// The title of the action. + /// + string Title { get; } + + void Do(); + void Undo(); + } + + public interface IChangeGroup : IUndoAction, IDisposable + { + void Commit(); + void Abort(); + } + + public interface ITextContainer + { + string Text { get; set; } + } + + public interface ITextAction : IUndoAction + { + } + + public interface IUndoService + { + bool CanRedo { get; } + bool CanUndo { get; } + IEnumerable RedoActions { get; } + IEnumerable UndoActions { get; } + event EventHandler UndoStackChanged; + + void Undo(); + void Redo(); + void Clear(); + + void Execute(IUndoAction action); + void Done(IUndoAction action); + + /// + /// Opens a new change group used to batch several changes. + /// ChangeGroups work as transactions and are used to support the Undo/Redo system. + /// + IChangeGroup OpenGroup(string title, IEnumerable affectedItems); + } + + #endregion + + #region IModelService + + public interface IModelService + { + /// + /// Gets the root design item. + /// + DesignItem Root { get; set; } + + event EventHandler RootChanged; + + event ModelChangedEventHandler ModelChanged; + + event EventHandler ItemCreated; + + DesignItem CreateItem(object component); + } + + public delegate void ModelChangedEventHandler(object sender, ModelChangedEventArgs e); + + public class ModelChangedEventArgs : EventArgs + { + public DesignItemProperty Property; + public DesignItem OldItem; + public DesignItem NewItem; + } + + #endregion + + #region ICommandService + + public interface ICommandService + { + bool CanUndo(); + bool CanRedo(); + bool CanCopy(); + bool CanPaste(); + bool CanCut(); + bool CanSelectAll(); + bool CanDelete(); + + void Undo(); + void Redo(); + void Copy(); + void Paste(); + void Cut(); + void SelectAll(); + void Delete(); + } + + #endregion +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Tools.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Tools.cs new file mode 100644 index 0000000000..4120caffd4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Tools.cs @@ -0,0 +1,134 @@ +// +// +// +// +// $Revision: 3509 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +using ICSharpCode.WpfDesign.Adorners; + +namespace ICSharpCode.WpfDesign +{ + /// + /// Describes a tool that can handle input on the design surface. + /// Modelled after the description on http://urbanpotato.net/Default.aspx/document/2300 + /// + public interface ITool + { + /// + /// Gets the cursor used by the tool. + /// + Cursor Cursor { get; } + + /// + /// Activates the tool, attaching its event handlers to the design panel. + /// + void Activate(IDesignPanel designPanel); + + /// + /// Deactivates the tool, detaching its event handlers from the design panel. + /// + void Deactivate(IDesignPanel designPanel); + } + + /// + /// Service that manages tool selection. + /// + public interface IToolService + { + /// + /// Gets the 'pointer' tool. + /// The pointer tool is the default tool for selecting and moving elements. + /// + ITool PointerTool { get; } + + /// + /// Gets/Sets the currently selected tool. + /// + ITool CurrentTool { get; set; } + + /// + /// Is raised when the current tool changes. + /// + event EventHandler CurrentToolChanged; + + void Reset(); + } + + /// + /// Interface for the design panel. The design panel is the UIElement containing the + /// designed elements and is responsible for handling mouse and keyboard events. + /// + public interface IDesignPanel : IInputElement + { + /// + /// Gets the design context used by the DesignPanel. + /// + DesignContext Context { get; } + + /// + /// Gets/Sets if the design content is visible for hit-testing purposes. + /// + bool IsContentHitTestVisible { get; set; } + + /// + /// Gets/Sets if the adorner layer is visible for hit-testing purposes. + /// + bool IsAdornerLayerHitTestVisible { get; set; } + + /// + /// Gets the list of adorners displayed on the design panel. + /// + ICollection Adorners { get; } + + /// + /// Performs a hit test on the design surface. + /// + DesignPanelHitTestResult HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface); + + /// + /// Performs a hit test on the design surface, raising for each match. + /// Hit testing continues while the callback returns true. + /// + void HitTest(Point mousePosition, bool testAdorners, bool testDesignSurface, Predicate callback); + + // The following members were missing in , but + // are supported on the DesignPanel: + + /// + /// Occurs when a mouse button is pressed. + /// + event MouseButtonEventHandler MouseDown; + + /// + /// Occurs when a mouse button is released. + /// + event MouseButtonEventHandler MouseUp; + + /// + /// Occurs when a drag operation enters the design panel. + /// + event DragEventHandler DragEnter; + + /// + /// Occurs when a drag operation is over the design panel. + /// + event DragEventHandler DragOver; + + /// + /// Occurs when a drag operation leaves the design panel. + /// + event DragEventHandler DragLeave; + + /// + /// Occurs when an element is dropped on the design panel. + /// + event DragEventHandler Drop; + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj new file mode 100644 index 0000000000..c4e70725ac --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj @@ -0,0 +1,127 @@ + + + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F} + Debug + AnyCPU + Library + ICSharpCode.WpfDesign + ICSharpCode.WpfDesign + ..\..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.xml + False + False + 4 + false + True + ..\..\..\..\Main\ICSharpCode.SharpDevelop.snk + False + File + ..\..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ + False + -Microsoft.Globalization#CA1303 + v3.5 + + + true + Full + True + DEBUG;TRACE + False + + + False + None + False + TRACE + + + False + Auto + 4194304 + AnyCPU + 4096 + + + ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ + ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.xml + + + + + False + + + False + + + + 3.5 + + + + + False + + + + + Properties\GlobalAssemblyInfo.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ComboBoxEditor.xaml + + + TextBoxEditor.xaml + + + + + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + \ No newline at end of file diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj b/src/Libraries/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj index 630966139c..9f453de374 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj +++ b/src/Libraries/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj @@ -216,4 +216,4 @@ ..\src\Tools\UpdateAssemblyInfo\bin\Debug\UpdateAssemblyInfo.exe - + \ No newline at end of file diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Undo/UndoStack.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Undo/UndoStack.cs index 8908bc04aa..d2dd2a5932 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Undo/UndoStack.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Undo/UndoStack.cs @@ -28,6 +28,8 @@ namespace ICSharpCode.TextEditor.Undo /// public event EventHandler ActionRedone; + public event OperationEventHandler OperationPushed; + /// /// Gets/Sets if changes to the document are protocolled by the undo stack. /// Used internally to disable the undo stack temporarily while undoing an action. @@ -89,7 +91,11 @@ namespace ICSharpCode.TextEditor.Undo undoGroupDepth--; //Util.LoggingService.Debug("Close undo group (new depth=" + undoGroupDepth + ")"); if (undoGroupDepth == 0 && actionCountInUndoGroup > 1) { - undostack.Push(new UndoQueue(undostack, actionCountInUndoGroup)); + UndoQueue op = new UndoQueue(undostack, actionCountInUndoGroup); + undostack.Push(op); + if (OperationPushed != null) { + OperationPushed(this, new OperationEventArgs(op)); + } } } @@ -213,4 +219,22 @@ namespace ICSharpCode.TextEditor.Undo } } } + + public class OperationEventArgs : EventArgs + { + public OperationEventArgs(IUndoableOperation op) + { + this.op = op; + } + + IUndoableOperation op; + + public IUndoableOperation Operation { + get { + return op; + } + } + } + + public delegate void OperationEventHandler(object sender, OperationEventArgs e); } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs index 371a881b76..d0a6fca9c9 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs @@ -49,9 +49,14 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor return true; } + protected virtual TextEditorDisplayBindingWrapper CreateWrapper(OpenedFile file) + { + return new TextEditorDisplayBindingWrapper(file); + } + public virtual IViewContent CreateContentForFile(OpenedFile file) { - TextEditorDisplayBindingWrapper b2 = new TextEditorDisplayBindingWrapper(file); + TextEditorDisplayBindingWrapper b2 = CreateWrapper(file); file.ForceInitializeView(b2); // load file to initialize folding etc. b2.textEditorControl.Dock = DockStyle.Fill; diff --git a/src/SharpDevelop.sln b/src/SharpDevelop.sln index a61719bfe0..57c38f50cd 100644 --- a/src/SharpDevelop.sln +++ b/src/SharpDevelop.sln @@ -1,174 +1,178 @@  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 -# SharpDevelop 3.0.0.3558 +# SharpDevelop 3.0.0.3548 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AddIns", "AddIns", "{14A277EE-7DF1-4529-B639-7D1EF334C1C5}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Display Bindings", "Display Bindings", "{4EA396ED-64AD-4AD0-A67A-AB363F3E0C79}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{CE5B42B7-6E8C-4385-9E97-F4023FC16BF2}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WpfDesign", "WpfDesign", "{388C3979-2621-4839-A955-7E5C03BA0B63}" - ProjectSection(SolutionItems) = postProject - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpRefactoring", "AddIns\Misc\SharpRefactoring\SharpRefactoring.csproj", "{3CA90546-3B4C-4663-9445-C4E9371750A7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.AddIn", "AddIns\DisplayBindings\WpfDesign\WpfDesign.AddIn\WpfDesign.AddIn.csproj", "{9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceAnalysis", "AddIns\Misc\SourceAnalysis\SourceAnalysis.csproj", "86CE7B3F-6273-4215-9E36-6184D98F854E" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SearchAndReplace", "AddIns\Misc\SearchAndReplace\Project\SearchAndReplace.csproj", "{9196DD8A-B4D4-4780-8742-C5762E547FC2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.XamlDom", "AddIns\DisplayBindings\WpfDesign\WpfDesign.XamlDom\Project\WpfDesign.XamlDom.csproj", "{88DA149F-21B2-48AB-82C4-28FB6BDFD783}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddinScout", "AddIns\Misc\AddinScout\Project\AddinScout.csproj", "{4B8F0F98-8BE1-402B-AA8B-C8D548577B38}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.Designer", "AddIns\DisplayBindings\WpfDesign\WpfDesign.Designer\Project\WpfDesign.Designer.csproj", "{78CC29AC-CC79-4355-B1F2-97936DF198AC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartPage", "AddIns\Misc\StartPage\Project\StartPage.csproj", "{7D5C266F-D6FF-4D14-B315-0C0FC6C4EF51}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign", "AddIns\DisplayBindings\WpfDesign\WpfDesign\Project\WpfDesign.csproj", "{66A378A1-E9F4-4AD5-8946-D0EC06C2902F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegExpTk", "AddIns\Misc\RegExpTk\Project\RegExpTk.csproj", "{64A3E5E6-90BF-47F6-94DF-68C94B62C817}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClassDiagram", "ClassDiagram", "{DB137F0B-9B62-4232-AE92-F7BE0280B8D3}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HighlightingEditor", "AddIns\Misc\HighlightingEditor\Project\HighlightingEditor.csproj", "{8A462940-E5E9-4E85-982D-D4C006EE31D4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FiletypeRegisterer", "AddIns\Misc\FiletypeRegisterer\Project\FiletypeRegisterer.csproj", "{D022A6CE-7438-41E8-AC64-F2DE18EC54C6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{6604365C-C702-4C10-9BA8-637F1E3D4D0D}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Diagrams", "AddIns\DisplayBindings\ClassDiagram\DiagramRouter\Diagrams.csproj", "{0991423A-DBF6-4C89-B365-A1DF1EB32E42}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.Core", "AddIns\Misc\Debugger\Debugger.Core\Project\Debugger.Core.csproj", "{1D18D788-F7EE-4585-A23B-34DC8EC63CB8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassDiagramAddin", "AddIns\DisplayBindings\ClassDiagram\ClassDiagramAddin\ClassDiagramAddin.csproj", "{5A1354DF-4989-4BB4-BC6B-D627C2E9FA13}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.AddIn", "AddIns\Misc\Debugger\Debugger.AddIn\Project\Debugger.AddIn.csproj", "{EC06F96A-AEEC-49D6-B03D-AB87C6EB674C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassCanvas", "AddIns\DisplayBindings\ClassDiagram\ClassCanvas\ClassCanvas.csproj", "{08F772A1-F0BE-433E-8B37-F6522953DB05}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlHelp2", "AddIns\Misc\HtmlHelp2\Project\HtmlHelp2.csproj", "{918487B7-2153-4618-BBB3-344DBDDF2A2A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IconEditor", "IconEditor", "{0D37CE59-B0EF-4F3C-B9EB-8557E53A448B}" - ProjectSection(SolutionItems) = postProject - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddInManager", "AddIns\Misc\AddInManager\Project\AddInManager.csproj", "{F93E52FD-DA66-4CE5-A0CB-BCD902811122}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IconEditorAddIn", "AddIns\DisplayBindings\IconEditor\IconEditorAddIn\IconEditorAddIn.csproj", "{DFB936AD-90EE-4B4F-941E-4F4A636F0D92}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PInvokeAddIn", "AddIns\Misc\PInvokeAddIn\Project\PInvokeAddIn.csproj", "{5EEB99CF-EA2B-4733-80A6-CE9192D68170}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IconEditor", "AddIns\DisplayBindings\IconEditor\IconEditor\IconEditor.csproj", "{DC1CCE11-CB91-40FA-9C47-4D9EB5D67BFD}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCoverage", "AddIns\Misc\CodeCoverage\Project\CodeCoverage.csproj", "{08ce9972-283b-44f4-82fa-966f7dfa6b7a}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlEditor", "AddIns\DisplayBindings\XmlEditor\Project\XmlEditor.csproj", "{6B717BD1-CD5E-498C-A42E-9E6A4584DC48}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTesting", "AddIns\Misc\UnitTesting\UnitTesting.csproj", "{1F261725-6318-4434-A1B1-6C70CE4CD324}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsDesigner", "AddIns\DisplayBindings\FormsDesigner\Project\FormsDesigner.csproj", "{7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57}" +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "HtmlHelp2JScriptGlobals", "AddIns\Misc\HtmlHelp2\JScriptGlobals\HtmlHelp2JScriptGlobals.vbproj", "{E54A5AD2-418D-4A85-BA5E-CD803DE38715}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceEditor", "AddIns\DisplayBindings\ResourceEditor\Project\ResourceEditor.csproj", "{CBC6C247-747B-4908-B09A-4D2E0F640B6B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SubversionAddIn", "AddIns\Misc\SubversionAddIn\Project\SubversionAddIn.csproj", "{17F4D7E0-6933-4C2E-8714-FD7E98D625D5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexEditor", "AddIns\DisplayBindings\HexEditor\Project\HexEditor.csproj", "{E618A9CD-A39F-4925-A538-E8A3FEF24E54}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysis", "AddIns\Misc\CodeAnalysis\CodeAnalysis.csproj", "{3EAA45A9-735C-4AC7-A799-947B93EA449D}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backends", "Backends", "{FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ComponentInspector", "ComponentInspector", "{BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{982E8BC1-ACD7-4dbf-96AB-B2CE67D6A008}") = "FSharpBinding", "AddIns\BackendBindings\FSharp\FSharpBinding\Project\FSharpBinding.fsproj", "{99BAE3A2-C40D-40D2-A7B4-EBB4798F36E4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlBinding", "AddIns\BackendBindings\XamlBinding\Project\XamlBinding.csproj", "{7C96B65D-28A5-4F28-A35B-8D83CE831EE8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixBinding", "AddIns\BackendBindings\WixBinding\Project\WixBinding.csproj", "{e1b288a2-08ee-4318-8bbb-8ab72c69e33e}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentInspector", "AddIns\Misc\ComponentInspector\ComponentInspector\ComponentInspector.csproj", "{000E4F64-5D0D-4EB1-B0BF-1A62ADBC6EAD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryToBooConverter", "AddIns\BackendBindings\Boo\NRefactoryToBooConverter\Project\NRefactoryToBooConverter.csproj", "{DBCF20A1-BA13-4582-BFA9-74DE4D987B73}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentInspector.AddIn", "AddIns\Misc\ComponentInspector\ComponentInspector.AddIn\ComponentInspector.AddIn.csproj", "{869951D5-A0D6-4DC6-9F1D-E6B9A12AC446}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooBinding", "AddIns\BackendBindings\Boo\BooBinding\Project\BooBinding.csproj", "{4AC2D5F1-F671-480C-A075-6BF62B3721B2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentInspector.Core", "AddIns\Misc\ComponentInspector\ComponentInspector.Core\ComponentInspector.Core.csproj", "{E6F4983F-DE41-4AEC-88E7-1FA9AFB4E6FF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILAsmBinding", "AddIns\BackendBindings\ILAsmBinding\Project\ILAsmBinding.csproj", "{6e59af58-f635-459a-9a35-c9ac41c00339}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceToolkit", "AddIns\Misc\ResourceToolkit\Project\ResourceToolkit.csproj", "{461606BD-E824-4D0A-8CBA-01810B1F5E02}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VBNetBinding", "AddIns\BackendBindings\VBNetBinding\Project\VBNetBinding.csproj", "{BF38FB72-B380-4196-AF8C-95749D726C61}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReflectorAddIn", "AddIns\Misc\ReflectorAddIn\ReflectorAddIn\Project\ReflectorAddIn.csproj", "{8AA421C8-D7AF-4957-9F43-5135328ACB24}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpBinding", "AddIns\BackendBindings\CSharpBinding\Project\CSharpBinding.csproj", "{1F1AC7CD-D154-45BB-8EAF-804CA8055F5A}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backends", "Backends", "{FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C}" + ProjectSection(SolutionItems) = postProject + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Python", "Python", "{8CF9DB5A-A2F6-4A88-BABA-100912EAF6E8}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.Build.Tasks", "AddIns\BackendBindings\Python\Python.Build.Tasks\Project\Python.Build.Tasks.csproj", "{D332F2D1-2CF1-43B7-903C-844BD5211A7E}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PythonBinding", "AddIns\BackendBindings\Python\PythonBinding\Project\PythonBinding.csproj", "{8D732610-8FC6-43BA-94C9-7126FD7FE361}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{CE5B42B7-6E8C-4385-9E97-F4023FC16BF2}" - ProjectSection(SolutionItems) = postProject - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.Build.Tasks", "AddIns\BackendBindings\Python\Python.Build.Tasks\Project\Python.Build.Tasks.csproj", "{D332F2D1-2CF1-43B7-903C-844BD5211A7E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReflectorAddIn", "AddIns\Misc\ReflectorAddIn\ReflectorAddIn\Project\ReflectorAddIn.csproj", "{8AA421C8-D7AF-4957-9F43-5135328ACB24}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpBinding", "AddIns\BackendBindings\CSharpBinding\Project\CSharpBinding.csproj", "{1F1AC7CD-D154-45BB-8EAF-804CA8055F5A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceToolkit", "AddIns\Misc\ResourceToolkit\Project\ResourceToolkit.csproj", "{461606BD-E824-4D0A-8CBA-01810B1F5E02}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VBNetBinding", "AddIns\BackendBindings\VBNetBinding\Project\VBNetBinding.csproj", "{BF38FB72-B380-4196-AF8C-95749D726C61}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ComponentInspector", "ComponentInspector", "{BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C}" - ProjectSection(SolutionItems) = postProject - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILAsmBinding", "AddIns\BackendBindings\ILAsmBinding\Project\ILAsmBinding.csproj", "{6e59af58-f635-459a-9a35-c9ac41c00339}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentInspector.Core", "AddIns\Misc\ComponentInspector\ComponentInspector.Core\ComponentInspector.Core.csproj", "{E6F4983F-DE41-4AEC-88E7-1FA9AFB4E6FF}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooBinding", "AddIns\BackendBindings\Boo\BooBinding\Project\BooBinding.csproj", "{4AC2D5F1-F671-480C-A075-6BF62B3721B2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentInspector.AddIn", "AddIns\Misc\ComponentInspector\ComponentInspector.AddIn\ComponentInspector.AddIn.csproj", "{869951D5-A0D6-4DC6-9F1D-E6B9A12AC446}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactoryToBooConverter", "AddIns\BackendBindings\Boo\NRefactoryToBooConverter\Project\NRefactoryToBooConverter.csproj", "{DBCF20A1-BA13-4582-BFA9-74DE4D987B73}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ComponentInspector", "AddIns\Misc\ComponentInspector\ComponentInspector\ComponentInspector.csproj", "{000E4F64-5D0D-4EB1-B0BF-1A62ADBC6EAD}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WixBinding", "AddIns\BackendBindings\WixBinding\Project\WixBinding.csproj", "{e1b288a2-08ee-4318-8bbb-8ab72c69e33e}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysis", "AddIns\Misc\CodeAnalysis\CodeAnalysis.csproj", "{3EAA45A9-735C-4AC7-A799-947B93EA449D}" +Project("{982E8BC1-ACD7-4dbf-96AB-B2CE67D6A008}") = "FSharpBinding", "AddIns\BackendBindings\FSharp\FSharpBinding\Project\FSharpBinding.fsproj", "{99BAE3A2-C40D-40D2-A7B4-EBB4798F36E4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SubversionAddIn", "AddIns\Misc\SubversionAddIn\Project\SubversionAddIn.csproj", "{17F4D7E0-6933-4C2E-8714-FD7E98D625D5}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Xaml", "Xaml", "{A81F8F26-9817-4206-863B-AE9D9EA076BD}" + ProjectSection(SolutionItems) = postProject + EndProjectSection EndProject -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "HtmlHelp2JScriptGlobals", "AddIns\Misc\HtmlHelp2\JScriptGlobals\HtmlHelp2JScriptGlobals.vbproj", "{E54A5AD2-418D-4A85-BA5E-CD803DE38715}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xaml", "AddIns\BackendBindings\Xaml\Xaml\Xaml.csproj", "{B4E5C965-7BB9-4AE9-85FB-C47480B879AD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTesting", "AddIns\Misc\UnitTesting\UnitTesting.csproj", "{1F261725-6318-4434-A1B1-6C70CE4CD324}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlBinding", "AddIns\BackendBindings\Xaml\XamlBinding\XamlBinding.csproj", "{7C96B65D-28A5-4F28-A35B-8D83CE831EE8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCoverage", "AddIns\Misc\CodeCoverage\Project\CodeCoverage.csproj", "{08ce9972-283b-44f4-82fa-966f7dfa6b7a}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Display Bindings", "Display Bindings", "{4EA396ED-64AD-4AD0-A67A-AB363F3E0C79}" + ProjectSection(SolutionItems) = postProject + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PInvokeAddIn", "AddIns\Misc\PInvokeAddIn\Project\PInvokeAddIn.csproj", "{5EEB99CF-EA2B-4733-80A6-CE9192D68170}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexEditor", "AddIns\DisplayBindings\HexEditor\Project\HexEditor.csproj", "{E618A9CD-A39F-4925-A538-E8A3FEF24E54}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddInManager", "AddIns\Misc\AddInManager\Project\AddInManager.csproj", "{F93E52FD-DA66-4CE5-A0CB-BCD902811122}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceEditor", "AddIns\DisplayBindings\ResourceEditor\Project\ResourceEditor.csproj", "{CBC6C247-747B-4908-B09A-4D2E0F640B6B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlHelp2", "AddIns\Misc\HtmlHelp2\Project\HtmlHelp2.csproj", "{918487B7-2153-4618-BBB3-344DBDDF2A2A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsDesigner", "AddIns\DisplayBindings\FormsDesigner\Project\FormsDesigner.csproj", "{7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{6604365C-C702-4C10-9BA8-637F1E3D4D0D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlEditor", "AddIns\DisplayBindings\XmlEditor\Project\XmlEditor.csproj", "{6B717BD1-CD5E-498C-A42E-9E6A4584DC48}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IconEditor", "IconEditor", "{0D37CE59-B0EF-4F3C-B9EB-8557E53A448B}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.AddIn", "AddIns\Misc\Debugger\Debugger.AddIn\Project\Debugger.AddIn.csproj", "{EC06F96A-AEEC-49D6-B03D-AB87C6EB674C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IconEditor", "AddIns\DisplayBindings\IconEditor\IconEditor\IconEditor.csproj", "{DC1CCE11-CB91-40FA-9C47-4D9EB5D67BFD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.Core", "AddIns\Misc\Debugger\Debugger.Core\Project\Debugger.Core.csproj", "{1D18D788-F7EE-4585-A23B-34DC8EC63CB8}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IconEditorAddIn", "AddIns\DisplayBindings\IconEditor\IconEditorAddIn\IconEditorAddIn.csproj", "{DFB936AD-90EE-4B4F-941E-4F4A636F0D92}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FiletypeRegisterer", "AddIns\Misc\FiletypeRegisterer\Project\FiletypeRegisterer.csproj", "{D022A6CE-7438-41E8-AC64-F2DE18EC54C6}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClassDiagram", "ClassDiagram", "{DB137F0B-9B62-4232-AE92-F7BE0280B8D3}" + ProjectSection(SolutionItems) = postProject + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HighlightingEditor", "AddIns\Misc\HighlightingEditor\Project\HighlightingEditor.csproj", "{8A462940-E5E9-4E85-982D-D4C006EE31D4}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassCanvas", "AddIns\DisplayBindings\ClassDiagram\ClassCanvas\ClassCanvas.csproj", "{08F772A1-F0BE-433E-8B37-F6522953DB05}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegExpTk", "AddIns\Misc\RegExpTk\Project\RegExpTk.csproj", "{64A3E5E6-90BF-47F6-94DF-68C94B62C817}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassDiagramAddin", "AddIns\DisplayBindings\ClassDiagram\ClassDiagramAddin\ClassDiagramAddin.csproj", "{5A1354DF-4989-4BB4-BC6B-D627C2E9FA13}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartPage", "AddIns\Misc\StartPage\Project\StartPage.csproj", "{7D5C266F-D6FF-4D14-B315-0C0FC6C4EF51}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Diagrams", "AddIns\DisplayBindings\ClassDiagram\DiagramRouter\Diagrams.csproj", "{0991423A-DBF6-4C89-B365-A1DF1EB32E42}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddinScout", "AddIns\Misc\AddinScout\Project\AddinScout.csproj", "{4B8F0F98-8BE1-402B-AA8B-C8D548577B38}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WpfDesign", "WpfDesign", "{388C3979-2621-4839-A955-7E5C03BA0B63}" + ProjectSection(SolutionItems) = postProject + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SearchAndReplace", "AddIns\Misc\SearchAndReplace\Project\SearchAndReplace.csproj", "{9196DD8A-B4D4-4780-8742-C5762E547FC2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign", "AddIns\DisplayBindings\WpfDesign\WpfDesign\WpfDesign.csproj", "{66A378A1-E9F4-4AD5-8946-D0EC06C2902F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceAnalysis", "AddIns\Misc\SourceAnalysis\SourceAnalysis.csproj", "86CE7B3F-6273-4215-9E36-6184D98F854E" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.Designer", "AddIns\DisplayBindings\WpfDesign\WpfDesign.Designer\WpfDesign.Designer.csproj", "{78CC29AC-CC79-4355-B1F2-97936DF198AC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpRefactoring", "AddIns\Misc\SharpRefactoring\SharpRefactoring.csproj", "{3CA90546-3B4C-4663-9445-C4E9371750A7}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign.AddIn", "AddIns\DisplayBindings\WpfDesign\WpfDesign.AddIn\WpfDesign.AddIn.csproj", "{9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{9421EDF4-9769-4BE9-B5A6-C87DE221D73C}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aga.Controls", "Libraries\TreeViewAdv\Aga.Controls\Aga.Controls.csproj", "{E73BB233-D88B-44A7-A98F-D71EE158381D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "Libraries\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Build.Tasks", "Libraries\ICSharpCode.Build.Tasks\Project\ICSharpCode.Build.Tasks.csproj", "{4139CCF6-FB49-4A9D-B2CF-331E9EA3198D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TextEditor", "Libraries\ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj", "{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WinFormsUI", "Libraries\DockPanel_Src\WinFormsUI\WinFormsUI.csproj", "{D3C782BA-178E-4235-A3BA-8C11DEBB6BEE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.TextEditor", "Libraries\ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj", "{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Build.Tasks", "Libraries\ICSharpCode.Build.Tasks\Project\ICSharpCode.Build.Tasks.csproj", "{4139CCF6-FB49-4A9D-B2CF-331E9EA3198D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "Libraries\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aga.Controls", "Libraries\TreeViewAdv\Aga.Controls\Aga.Controls.csproj", "{E73BB233-D88B-44A7-A98F-D71EE158381D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{5A3EBEBA-0560-41C1-966B-23F7D03A5486}" ProjectSection(SolutionItems) = postProject EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core.WinForms", "Main\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj", "{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.BuildWorker", "Main\ICSharpCode.SharpDevelop.BuildWorker\ICSharpCode.SharpDevelop.BuildWorker.csproj", "{C3CBC8E3-81D8-4C5B-9941-DCCD12D50B1F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Dom", "Main\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj", "{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}" +Project("{00000000-0000-0000-0000-000000000000}") = "Tools", "Tools\Tools.build", "B13EFF7F-7EA4-4B68-A375-D112105E9182" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Widgets", "Main\ICSharpCode.SharpDevelop.Widgets\Project\ICSharpCode.SharpDevelop.Widgets.csproj", "{8035765F-D51F-4A0C-A746-2FD100E19419}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartUp", "Main\StartUp\Project\StartUp.csproj", "{1152B71B-3C05-4598-B20D-823B5D40559E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Sda", "Main\ICSharpCode.SharpDevelop.Sda\ICSharpCode.SharpDevelop.Sda.csproj", "{80318B5F-A25D-45AB-8A95-EF31D2370A4C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core", "Main\Core\Project\ICSharpCode.Core.csproj", "{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop", "Main\Base\Project\ICSharpCode.SharpDevelop.csproj", "{2748AD25-9C63-4E12-877B-4DCE96FBED54}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core", "Main\Core\Project\ICSharpCode.Core.csproj", "{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Sda", "Main\ICSharpCode.SharpDevelop.Sda\ICSharpCode.SharpDevelop.Sda.csproj", "{80318B5F-A25D-45AB-8A95-EF31D2370A4C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartUp", "Main\StartUp\Project\StartUp.csproj", "{1152B71B-3C05-4598-B20D-823B5D40559E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Widgets", "Main\ICSharpCode.SharpDevelop.Widgets\Project\ICSharpCode.SharpDevelop.Widgets.csproj", "{8035765F-D51F-4A0C-A746-2FD100E19419}" EndProject -Project("{00000000-0000-0000-0000-000000000000}") = "Tools", "Tools\Tools.build", "B13EFF7F-7EA4-4B68-A375-D112105E9182" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Dom", "Main\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj", "{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.BuildWorker", "Main\ICSharpCode.SharpDevelop.BuildWorker\ICSharpCode.SharpDevelop.BuildWorker.csproj", "{C3CBC8E3-81D8-4C5B-9941-DCCD12D50B1F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core.WinForms", "Main\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj", "{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -352,10 +356,6 @@ Global {E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|Any CPU.Build.0 = Release|Any CPU {E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Release|Any CPU.Build.0 = Release|Any CPU - {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Release|Any CPU.ActiveCfg = Release|Any CPU {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Debug|Any CPU.Build.0 = Debug|Any CPU {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}.Release|Any CPU.Build.0 = Release|Any CPU @@ -364,10 +364,6 @@ Global {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Release|Any CPU.Build.0 = Release|Any CPU {78CC29AC-CC79-4355-B1F2-97936DF198AC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Debug|Any CPU.Build.0 = Debug|Any CPU - {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Release|Any CPU.Build.0 = Release|Any CPU - {88DA149F-21B2-48AB-82C4-28FB6BDFD783}.Release|Any CPU.ActiveCfg = Release|Any CPU {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}.Debug|Any CPU.Build.0 = Debug|Any CPU {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}.Release|Any CPU.Build.0 = Release|Any CPU @@ -416,76 +412,85 @@ Global {3CA90546-3B4C-4663-9445-C4E9371750A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3CA90546-3B4C-4663-9445-C4E9371750A7}.Release|Any CPU.Build.0 = Release|Any CPU {3CA90546-3B4C-4663-9445-C4E9371750A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD}.Release|Any CPU.Build.0 = Release|Any CPU + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Release|Any CPU.Build.0 = Release|Any CPU + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution - {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} - {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} - {E618A9CD-A39F-4925-A538-E8A3FEF24E54} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} - {CBC6C247-747B-4908-B09A-4D2E0F640B6B} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} - {7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} - {6B717BD1-CD5E-498C-A42E-9E6A4584DC48} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} - {0D37CE59-B0EF-4F3C-B9EB-8557E53A448B} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} - {DB137F0B-9B62-4232-AE92-F7BE0280B8D3} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} - {388C3979-2621-4839-A955-7E5C03BA0B63} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} - {66A378A1-E9F4-4AD5-8946-D0EC06C2902F} = {388C3979-2621-4839-A955-7E5C03BA0B63} - {78CC29AC-CC79-4355-B1F2-97936DF198AC} = {388C3979-2621-4839-A955-7E5C03BA0B63} - {88DA149F-21B2-48AB-82C4-28FB6BDFD783} = {388C3979-2621-4839-A955-7E5C03BA0B63} - {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865} = {388C3979-2621-4839-A955-7E5C03BA0B63} - {08F772A1-F0BE-433E-8B37-F6522953DB05} = {DB137F0B-9B62-4232-AE92-F7BE0280B8D3} - {5A1354DF-4989-4BB4-BC6B-D627C2E9FA13} = {DB137F0B-9B62-4232-AE92-F7BE0280B8D3} - {0991423A-DBF6-4C89-B365-A1DF1EB32E42} = {DB137F0B-9B62-4232-AE92-F7BE0280B8D3} - {DC1CCE11-CB91-40FA-9C47-4D9EB5D67BFD} = {0D37CE59-B0EF-4F3C-B9EB-8557E53A448B} - {DFB936AD-90EE-4B4F-941E-4F4A636F0D92} = {0D37CE59-B0EF-4F3C-B9EB-8557E53A448B} - {8CF9DB5A-A2F6-4A88-BABA-100912EAF6E8} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {1F1AC7CD-D154-45BB-8EAF-804CA8055F5A} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {BF38FB72-B380-4196-AF8C-95749D726C61} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {6e59af58-f635-459a-9a35-c9ac41c00339} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {4AC2D5F1-F671-480C-A075-6BF62B3721B2} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {DBCF20A1-BA13-4582-BFA9-74DE4D987B73} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {e1b288a2-08ee-4318-8bbb-8ab72c69e33e} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {7C96B65D-28A5-4F28-A35B-8D83CE831EE8} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {99BAE3A2-C40D-40D2-A7B4-EBB4798F36E4} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} - {8D732610-8FC6-43BA-94C9-7126FD7FE361} = {8CF9DB5A-A2F6-4A88-BABA-100912EAF6E8} - {D332F2D1-2CF1-43B7-903C-844BD5211A7E} = {8CF9DB5A-A2F6-4A88-BABA-100912EAF6E8} - {3CA90546-3B4C-4663-9445-C4E9371750A7} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - 86CE7B3F-6273-4215-9E36-6184D98F854E = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {9196DD8A-B4D4-4780-8742-C5762E547FC2} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {4B8F0F98-8BE1-402B-AA8B-C8D548577B38} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {7D5C266F-D6FF-4D14-B315-0C0FC6C4EF51} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {64A3E5E6-90BF-47F6-94DF-68C94B62C817} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {8A462940-E5E9-4E85-982D-D4C006EE31D4} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {D022A6CE-7438-41E8-AC64-F2DE18EC54C6} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {6604365C-C702-4C10-9BA8-637F1E3D4D0D} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {918487B7-2153-4618-BBB3-344DBDDF2A2A} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {F93E52FD-DA66-4CE5-A0CB-BCD902811122} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {5EEB99CF-EA2B-4733-80A6-CE9192D68170} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {08ce9972-283b-44f4-82fa-966f7dfa6b7a} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {1F261725-6318-4434-A1B1-6C70CE4CD324} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {E54A5AD2-418D-4A85-BA5E-CD803DE38715} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {17F4D7E0-6933-4C2E-8714-FD7E98D625D5} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {3EAA45A9-735C-4AC7-A799-947B93EA449D} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {461606BD-E824-4D0A-8CBA-01810B1F5E02} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} + {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} = {14A277EE-7DF1-4529-B639-7D1EF334C1C5} {8AA421C8-D7AF-4957-9F43-5135328ACB24} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} - {000E4F64-5D0D-4EB1-B0BF-1A62ADBC6EAD} = {BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C} - {869951D5-A0D6-4DC6-9F1D-E6B9A12AC446} = {BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C} - {E6F4983F-DE41-4AEC-88E7-1FA9AFB4E6FF} = {BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C} - {1D18D788-F7EE-4585-A23B-34DC8EC63CB8} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D} + {461606BD-E824-4D0A-8CBA-01810B1F5E02} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {3EAA45A9-735C-4AC7-A799-947B93EA449D} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {17F4D7E0-6933-4C2E-8714-FD7E98D625D5} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {E54A5AD2-418D-4A85-BA5E-CD803DE38715} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {1F261725-6318-4434-A1B1-6C70CE4CD324} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {08ce9972-283b-44f4-82fa-966f7dfa6b7a} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {5EEB99CF-EA2B-4733-80A6-CE9192D68170} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {F93E52FD-DA66-4CE5-A0CB-BCD902811122} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {918487B7-2153-4618-BBB3-344DBDDF2A2A} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {6604365C-C702-4C10-9BA8-637F1E3D4D0D} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {D022A6CE-7438-41E8-AC64-F2DE18EC54C6} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {8A462940-E5E9-4E85-982D-D4C006EE31D4} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {64A3E5E6-90BF-47F6-94DF-68C94B62C817} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {7D5C266F-D6FF-4D14-B315-0C0FC6C4EF51} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {4B8F0F98-8BE1-402B-AA8B-C8D548577B38} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {9196DD8A-B4D4-4780-8742-C5762E547FC2} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + 86CE7B3F-6273-4215-9E36-6184D98F854E = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} + {3CA90546-3B4C-4663-9445-C4E9371750A7} = {CE5B42B7-6E8C-4385-9E97-F4023FC16BF2} {EC06F96A-AEEC-49D6-B03D-AB87C6EB674C} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D} - {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} - {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} - {D3C782BA-178E-4235-A3BA-8C11DEBB6BEE} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} - {4139CCF6-FB49-4A9D-B2CF-331E9EA3198D} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} + {1D18D788-F7EE-4585-A23B-34DC8EC63CB8} = {6604365C-C702-4C10-9BA8-637F1E3D4D0D} + {E6F4983F-DE41-4AEC-88E7-1FA9AFB4E6FF} = {BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C} + {869951D5-A0D6-4DC6-9F1D-E6B9A12AC446} = {BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C} + {000E4F64-5D0D-4EB1-B0BF-1A62ADBC6EAD} = {BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C} + {A81F8F26-9817-4206-863B-AE9D9EA076BD} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {99BAE3A2-C40D-40D2-A7B4-EBB4798F36E4} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {e1b288a2-08ee-4318-8bbb-8ab72c69e33e} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {DBCF20A1-BA13-4582-BFA9-74DE4D987B73} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {4AC2D5F1-F671-480C-A075-6BF62B3721B2} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {6e59af58-f635-459a-9a35-c9ac41c00339} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {BF38FB72-B380-4196-AF8C-95749D726C61} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {1F1AC7CD-D154-45BB-8EAF-804CA8055F5A} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {8CF9DB5A-A2F6-4A88-BABA-100912EAF6E8} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {D332F2D1-2CF1-43B7-903C-844BD5211A7E} = {8CF9DB5A-A2F6-4A88-BABA-100912EAF6E8} + {8D732610-8FC6-43BA-94C9-7126FD7FE361} = {8CF9DB5A-A2F6-4A88-BABA-100912EAF6E8} + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8} = {A81F8F26-9817-4206-863B-AE9D9EA076BD} + {B4E5C965-7BB9-4AE9-85FB-C47480B879AD} = {A81F8F26-9817-4206-863B-AE9D9EA076BD} + {388C3979-2621-4839-A955-7E5C03BA0B63} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} + {DB137F0B-9B62-4232-AE92-F7BE0280B8D3} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} + {0D37CE59-B0EF-4F3C-B9EB-8557E53A448B} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} + {6B717BD1-CD5E-498C-A42E-9E6A4584DC48} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} + {7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} + {CBC6C247-747B-4908-B09A-4D2E0F640B6B} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} + {E618A9CD-A39F-4925-A538-E8A3FEF24E54} = {4EA396ED-64AD-4AD0-A67A-AB363F3E0C79} + {DFB936AD-90EE-4B4F-941E-4F4A636F0D92} = {0D37CE59-B0EF-4F3C-B9EB-8557E53A448B} + {DC1CCE11-CB91-40FA-9C47-4D9EB5D67BFD} = {0D37CE59-B0EF-4F3C-B9EB-8557E53A448B} + {0991423A-DBF6-4C89-B365-A1DF1EB32E42} = {DB137F0B-9B62-4232-AE92-F7BE0280B8D3} + {5A1354DF-4989-4BB4-BC6B-D627C2E9FA13} = {DB137F0B-9B62-4232-AE92-F7BE0280B8D3} + {08F772A1-F0BE-433E-8B37-F6522953DB05} = {DB137F0B-9B62-4232-AE92-F7BE0280B8D3} + {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865} = {388C3979-2621-4839-A955-7E5C03BA0B63} + {78CC29AC-CC79-4355-B1F2-97936DF198AC} = {388C3979-2621-4839-A955-7E5C03BA0B63} + {66A378A1-E9F4-4AD5-8946-D0EC06C2902F} = {388C3979-2621-4839-A955-7E5C03BA0B63} {E73BB233-D88B-44A7-A98F-D71EE158381D} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} - {C3CBC8E3-81D8-4C5B-9941-DCCD12D50B1F} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} - B13EFF7F-7EA4-4B68-A375-D112105E9182 = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} - {1152B71B-3C05-4598-B20D-823B5D40559E} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} - {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} - {2748AD25-9C63-4E12-877B-4DCE96FBED54} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} - {80318B5F-A25D-45AB-8A95-EF31D2370A4C} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} - {8035765F-D51F-4A0C-A746-2FD100E19419} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} - {924EE450-603D-49C1-A8E5-4AFAA31CE6F3} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + {4139CCF6-FB49-4A9D-B2CF-331E9EA3198D} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} + {D3C782BA-178E-4235-A3BA-8C11DEBB6BEE} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} + {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} = {9421EDF4-9769-4BE9-B5A6-C87DE221D73C} {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + {8035765F-D51F-4A0C-A746-2FD100E19419} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + {80318B5F-A25D-45AB-8A95-EF31D2370A4C} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + {2748AD25-9C63-4E12-877B-4DCE96FBED54} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + {1152B71B-3C05-4598-B20D-823B5D40559E} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + B13EFF7F-7EA4-4B68-A375-D112105E9182 = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} + {C3CBC8E3-81D8-4C5B-9941-DCCD12D50B1F} = {5A3EBEBA-0560-41C1-966B-23F7D03A5486} EndGlobalSection EndGlobal