From 567c4e9e4873c21bb275c6f77e1d66f4810d9c6a Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Mon, 29 Sep 2008 19:00:56 +0000 Subject: [PATCH 01/51] Fixed SD2-1349 - WiX setup files editor shows misleading error when unable to find any TARGETDIR Directory or DirectoryRef elements. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3567 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../resources/StringResources.es-mx.resources | Bin 328963 -> 328959 bytes data/resources/StringResources.es.resources | Bin 329034 -> 329030 bytes data/resources/StringResources.nl.resources | Bin 322519 -> 323617 bytes .../Project/Src/Gui/WixPackageFilesControl.cs | 5 ++ .../Project/Src/IWixPackageFilesView.cs | 6 ++ .../Project/Src/WixPackageFilesEditor.cs | 2 +- .../NoRootDirectoryFoundTestFixture.cs | 60 ++++++++++++++++++ .../NoWixProductFileTestFixture.cs | 4 +- .../Test/Utils/MockWixPackageFilesView.cs | 12 ++++ .../WixBinding/Test/WixBinding.Tests.csproj | 1 + .../Resources/StringResources.resources | Bin 315091 -> 315437 bytes 11 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 src/AddIns/BackendBindings/WixBinding/Test/PackageFiles/NoRootDirectoryFoundTestFixture.cs diff --git a/data/resources/StringResources.es-mx.resources b/data/resources/StringResources.es-mx.resources index 705997f51bb9c199070b5d5d61d6e3c9fdd97286..370bda7ef7c22a8ba2f5b936f7a7faa6ec2aa8c1 100644 GIT binary patch delta 9580 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 I?0!r5KS8<(9RL6T diff --git a/data/resources/StringResources.es.resources b/data/resources/StringResources.es.resources index 175bed9e412b7491551a434c7182ff7c3ab29cc5..9b3542cbbd390564d5a2e752aab40732f1ac7f2d 100644 GIT binary patch delta 9629 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 delta 9633 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 diff --git a/data/resources/StringResources.nl.resources b/data/resources/StringResources.nl.resources index 52c47b27317aa5ae95735876b4c341d1a315f583..ad0bc2cc8f6176cc40053220c2b8ef1396b69f54 100644 GIT binary patch delta 27603 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
  • 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 delta 27188 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 diff --git a/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixPackageFilesControl.cs b/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixPackageFilesControl.cs index e4964ed0b2..6150e4e023 100644 --- a/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixPackageFilesControl.cs +++ b/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixPackageFilesControl.cs @@ -184,6 +184,11 @@ namespace ICSharpCode.WixBinding } } + public void ShowNoRootDirectoryFoundMessage() + { + ShowErrorMessage(StringParser.Parse("${res:ICSharpCode.WixBinding.PackageFilesView.NoRootDirectoryFoundMessage}")); + } + public void ShowNoSourceFileFoundMessage(string projectName) { ShowErrorMessage(String.Format(StringParser.Parse("${res:ICSharpCode.WixBinding.PackageFilesView.NoWixFileFoundInProjectMessage}"), projectName)); diff --git a/src/AddIns/BackendBindings/WixBinding/Project/Src/IWixPackageFilesView.cs b/src/AddIns/BackendBindings/WixBinding/Project/Src/IWixPackageFilesView.cs index c5b98ecc5a..790c7ce032 100644 --- a/src/AddIns/BackendBindings/WixBinding/Project/Src/IWixPackageFilesView.cs +++ b/src/AddIns/BackendBindings/WixBinding/Project/Src/IWixPackageFilesView.cs @@ -29,6 +29,12 @@ namespace ICSharpCode.WixBinding /// files could not be read because they contain errors. /// void ShowSourceFilesContainErrorsMessage(); + + /// + /// Displays a message indicating that no //w:Product/w:Directory[@Id="TARGETDIR"] or + /// //w:DirectoryRef[@Id="TARGETDIR"] element could be found. + /// + void ShowNoRootDirectoryFoundMessage(); /// /// Adds the directories that will be displayed. Each directory may contain its diff --git a/src/AddIns/BackendBindings/WixBinding/Project/Src/WixPackageFilesEditor.cs b/src/AddIns/BackendBindings/WixBinding/Project/Src/WixPackageFilesEditor.cs index facbc2f688..a91fd0ba84 100644 --- a/src/AddIns/BackendBindings/WixBinding/Project/Src/WixPackageFilesEditor.cs +++ b/src/AddIns/BackendBindings/WixBinding/Project/Src/WixPackageFilesEditor.cs @@ -81,7 +81,7 @@ namespace ICSharpCode.WixBinding if (errors) { view.ShowSourceFilesContainErrorsMessage(); } else if (document == null) { - view.ShowNoSourceFileFoundMessage(project.Name); + view.ShowNoRootDirectoryFoundMessage(); } else { SelectedElementChanged(); } diff --git a/src/AddIns/BackendBindings/WixBinding/Test/PackageFiles/NoRootDirectoryFoundTestFixture.cs b/src/AddIns/BackendBindings/WixBinding/Test/PackageFiles/NoRootDirectoryFoundTestFixture.cs new file mode 100644 index 0000000000..20cfd07ceb --- /dev/null +++ b/src/AddIns/BackendBindings/WixBinding/Test/PackageFiles/NoRootDirectoryFoundTestFixture.cs @@ -0,0 +1,60 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.WixBinding; +using NUnit.Framework; +using System; +using System.IO; +using WixBinding.Tests.Utils; + +namespace WixBinding.Tests.PackageFiles +{ + /// + /// Tests that the package editor will display an error message indicating that no target directory + /// could be found the WiX files. Previously the editor would display an error message that + /// there were no WiX files - SD2-1349. + /// + [TestFixture] + public class NoRootDirectoryFoundFixture : PackageFilesTestFixtureBase + { + [TestFixtureSetUp] + public void SetUpFixture() + { + base.InitFixture(); + } + + [Test] + public void NoSourceFileFoundErrorNotShown() + { + Assert.IsFalse(view.IsNoSourceFileFoundMessageDisplayed); + } + + [Test] + public void NoRootDirectoryFoundMessageIsShown() + { + Assert.IsTrue(view.IsNoRootDirectoryFoundMessageDisplayed); + } + + /// + /// Deliberately use WiX 2.0's namespace so the test fixture will not find any + /// target directory element. + /// + protected override string GetWixXml() + { + return "\r\n" + + "\t\r\n" + + "\t\t\r\n" + + "\t\r\n" + + ""; + } + } +} diff --git a/src/AddIns/BackendBindings/WixBinding/Test/PackageFiles/NoWixProductFileTestFixture.cs b/src/AddIns/BackendBindings/WixBinding/Test/PackageFiles/NoWixProductFileTestFixture.cs index 4da7c71cb2..34142eed23 100644 --- a/src/AddIns/BackendBindings/WixBinding/Test/PackageFiles/NoWixProductFileTestFixture.cs +++ b/src/AddIns/BackendBindings/WixBinding/Test/PackageFiles/NoWixProductFileTestFixture.cs @@ -34,9 +34,9 @@ namespace WixBinding.Tests.PackageFiles } [Test] - public void NoSourceFileFound() + public void NoRootDirectoryFound() { - Assert.IsTrue(view.IsNoSourceFileFoundMessageDisplayed); + Assert.IsTrue(view.IsNoRootDirectoryFoundMessageDisplayed); } protected override string GetWixXml() diff --git a/src/AddIns/BackendBindings/WixBinding/Test/Utils/MockWixPackageFilesView.cs b/src/AddIns/BackendBindings/WixBinding/Test/Utils/MockWixPackageFilesView.cs index fb4a7955b6..2e403bd3ef 100644 --- a/src/AddIns/BackendBindings/WixBinding/Test/Utils/MockWixPackageFilesView.cs +++ b/src/AddIns/BackendBindings/WixBinding/Test/Utils/MockWixPackageFilesView.cs @@ -19,6 +19,7 @@ namespace WixBinding.Tests.Utils bool noSourceFileFoundMessageDisplayed; bool sourceFilesContainErrorsMessageDisplayed; bool noDifferencesFoundMessageDisplayed; + bool noRootDirectoryFoundMessageDisplayed; string projectName; WixDirectoryElement rootDirectory; bool selectedItemAccessed; @@ -37,6 +38,11 @@ namespace WixBinding.Tests.Utils { } + public void ShowNoRootDirectoryFoundMessage() + { + noRootDirectoryFoundMessageDisplayed = true; + } + public void ShowNoSourceFileFoundMessage(string projectName) { noSourceFileFoundMessageDisplayed = true; @@ -198,6 +204,12 @@ namespace WixBinding.Tests.Utils return noDifferencesFoundMessageDisplayed; } } + + public bool IsNoRootDirectoryFoundMessageDisplayed { + get { + return noRootDirectoryFoundMessageDisplayed; + } + } public WixPackageFilesDiffResult[] DiffResults { get { diff --git a/src/AddIns/BackendBindings/WixBinding/Test/WixBinding.Tests.csproj b/src/AddIns/BackendBindings/WixBinding/Test/WixBinding.Tests.csproj index 5fe567e986..6b8e1ffac1 100644 --- a/src/AddIns/BackendBindings/WixBinding/Test/WixBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/WixBinding/Test/WixBinding.Tests.csproj @@ -57,6 +57,7 @@ + diff --git a/src/Main/StartUp/Project/Resources/StringResources.resources b/src/Main/StartUp/Project/Resources/StringResources.resources index d99680512ad84aee5c49cf2ee108b980ccd991be..0a4c60856093335ea96347b6e6db10ca56ba57aa 100644 GIT binary patch delta 24576 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 delta 24372 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 Date: Mon, 29 Sep 2008 23:59:54 +0000 Subject: [PATCH 02/51] Fixed SD2-1384: Attribute fully qualified name using wrong namespace git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3569 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Main/Base/Test/NRefactoryResolverTests.cs | 15 +++++++++++++++ .../Src/Implementations/AttributeReturnType.cs | 15 ++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Main/Base/Test/NRefactoryResolverTests.cs b/src/Main/Base/Test/NRefactoryResolverTests.cs index fd94a4e24e..441d4b9e06 100644 --- a/src/Main/Base/Test/NRefactoryResolverTests.cs +++ b/src/Main/Base/Test/NRefactoryResolverTests.cs @@ -2468,5 +2468,20 @@ End Module"; result = ResolveVB(program, "ITest", 5, 40, ExpressionContext.Type); Assert.AreEqual("RootNamespace.ITest", result.ResolvedClass.FullyQualifiedName); } + + [Test] + public void SD2_1384() + { + string program = @"using System; +class Flags { + [Flags] + enum Test { } +}"; + TypeResolveResult result = Resolve(program, "Flags.Test", 3, 1, ExpressionContext.Type); + Assert.AreEqual("Flags.Test", result.ResolvedClass.FullyQualifiedName); + + IReturnType rt = result.ResolvedClass.Attributes[0].AttributeType; + Assert.AreEqual("System.FlagsAttribute", rt.FullyQualifiedName); + } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AttributeReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AttributeReturnType.cs index 14f034406b..79bae7d521 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AttributeReturnType.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AttributeReturnType.cs @@ -6,6 +6,7 @@ // using System; +using System.Linq; namespace ICSharpCode.SharpDevelop.Dom { @@ -32,10 +33,18 @@ namespace ICSharpCode.SharpDevelop.Dom public override IReturnType BaseType { get { - if (scrt1.GetUnderlyingClass() != null) - return scrt1; - else + IClass class1 = scrt1.GetUnderlyingClass(); + IClass class2 = scrt1.GetUnderlyingClass(); + if (class1 != null && class2 != null) { + if (class1.ClassInheritanceTree.Any(c => c.FullyQualifiedName == "System.Attribute")) + return scrt1; + else + return scrt2; + } else if (class2 != null) { return scrt2; + } else { + return scrt1; + } } } } From f08eb73a1676aaad31702e7414b2c9a09ce5da51 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 30 Sep 2008 11:13:33 +0000 Subject: [PATCH 03/51] Fixed typo that caused unit test failure. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3570 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/Implementations/AttributeReturnType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AttributeReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AttributeReturnType.cs index 79bae7d521..6fecbf674c 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AttributeReturnType.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AttributeReturnType.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.SharpDevelop.Dom public override IReturnType BaseType { get { IClass class1 = scrt1.GetUnderlyingClass(); - IClass class2 = scrt1.GetUnderlyingClass(); + IClass class2 = scrt2.GetUnderlyingClass(); if (class1 != null && class2 != null) { if (class1.ClassInheritanceTree.Any(c => c.FullyQualifiedName == "System.Attribute")) return scrt1; From f54b4e40abf61ba18d31672200b468275d31c9d9 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 30 Sep 2008 14:19:28 +0000 Subject: [PATCH 04/51] Performance tweaks to code completion: - don't duplicate search for nested classes in referenced project contents - MemberLookupHelper.GetTypeInheritanceTree: use HashSet instead of List to find duplicate types - DefaultClass.ClassInheritanceTree: cache the inheritance tree Fixes SD2-1460 - Extreme delay requesting code completion for PropertyTabsCollection when Linq is imported git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3573 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Test/Utils/MockProjectContent.cs | 2 +- .../Project/Src/XamlCompilationUnit.cs | 2 +- .../Test/Utils/MockProjectContent.cs | 2 +- .../RefactoringMenuBuilder.cs | 2 +- .../Commands/ClassBookmarkMenuBuilder.cs | 2 +- .../ICSharpCode.SharpDevelop.Dom.csproj | 1 + .../Project/Src/CecilReader.cs | 2 +- .../Project/Src/DomCache.cs | 45 ++++++++++++ .../Src/Implementations/DefaultClass.cs | 21 +++--- .../Implementations/SearchClassReturnType.cs | 70 ++++--------------- .../Src/Implementations/SystemTypes.cs | 2 +- .../Project/Src/MemberLookupHelper.cs | 3 +- .../ProjectContent/DefaultProjectContent.cs | 53 +++++++------- .../Src/ProjectContent/IProjectContent.cs | 20 +++++- .../Src/ReflectionLayer/ReflectionClass.cs | 2 +- 15 files changed, 128 insertions(+), 101 deletions(-) create mode 100644 src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/DomCache.cs diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs index 72cde6d511..2e0aa325ce 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs @@ -272,7 +272,7 @@ namespace PythonBinding.Tests.Utils return namespaceContents; } - public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, bool lookInReferences) + public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, GetClassOptions options) { return GetClass(typeName, typeParameterCount); } diff --git a/src/AddIns/BackendBindings/XamlBinding/Project/Src/XamlCompilationUnit.cs b/src/AddIns/BackendBindings/XamlBinding/Project/Src/XamlCompilationUnit.cs index 65b24aafc5..b1a6e3b442 100644 --- a/src/AddIns/BackendBindings/XamlBinding/Project/Src/XamlCompilationUnit.cs +++ b/src/AddIns/BackendBindings/XamlBinding/Project/Src/XamlCompilationUnit.cs @@ -82,7 +82,7 @@ namespace XamlBinding { string namespaceName = att.PositionalArguments[1] as string; if (xmlNamespace.Equals(att.PositionalArguments[0]) && namespaceName != null) { - IClass c = projectContent.GetClass(namespaceName + "." + className, 0, LanguageProperties.CSharp, false); + IClass c = projectContent.GetClass(namespaceName + "." + className, 0, LanguageProperties.CSharp, GetClassOptions.None); if (c != null) return c.DefaultReturnType; } diff --git a/src/AddIns/Misc/UnitTesting/Test/Utils/MockProjectContent.cs b/src/AddIns/Misc/UnitTesting/Test/Utils/MockProjectContent.cs index d6bf8aafbc..1869056e35 100644 --- a/src/AddIns/Misc/UnitTesting/Test/Utils/MockProjectContent.cs +++ b/src/AddIns/Misc/UnitTesting/Test/Utils/MockProjectContent.cs @@ -118,7 +118,7 @@ namespace UnitTesting.Tests.Utils throw new NotImplementedException(); } - public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, bool lookInReferences) + public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, GetClassOptions options) { throw new NotImplementedException(); } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs index aff87cf737..6f4caf2db1 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringMenuBuilder.cs @@ -197,7 +197,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring void SearchAllClassesWithName(List searchResults, IProjectContent pc, string name, LanguageProperties language) { foreach (string ns in pc.NamespaceNames) { - IClass c = pc.GetClass(ns + "." + name, 0, language, false); + IClass c = pc.GetClass(ns + "." + name, 0, language, GetClassOptions.None); if (c != null) searchResults.Add(c); } diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs b/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs index 2b3fe72b0f..139f6226fa 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs +++ b/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs @@ -89,7 +89,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands } ParserService.ParseCurrentViewContent(); - c = c.ProjectContent.GetClass(c.FullyQualifiedName, c.TypeParameters.Count, c.ProjectContent.Language, false); + c = c.ProjectContent.GetClass(c.FullyQualifiedName, c.TypeParameters.Count, c.ProjectContent.Language, GetClassOptions.LookForInnerClass); c = GetCurrentPart(c); if (c == null) { return new ToolStripMenuItem[0]; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj index 5d955e3a10..bba40cc76a 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/ICSharpCode.SharpDevelop.Dom.csproj @@ -64,6 +64,7 @@ + diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs index 889f1b6a45..461566feb4 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs @@ -179,7 +179,7 @@ namespace ICSharpCode.SharpDevelop.Dom : base(compilationUnit, declaringType) { this.FullyQualifiedName = fullName; - this.UseInheritanceCache = true; + this.KeepInheritanceTree = true; AddAttributes(compilationUnit.ProjectContent, this.Attributes, td.CustomAttributes); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/DomCache.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/DomCache.cs new file mode 100644 index 0000000000..36c0dbab22 --- /dev/null +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/DomCache.cs @@ -0,0 +1,45 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.SharpDevelop.Dom +{ + static class DomCache + { + /// + /// Clear the static searchclass cache. You should call this method + /// whenever the DOM changes. + /// + /// + /// automatically called by DefaultProjectContent.UpdateCompilationUnit + /// and DefaultProjectContent.OnReferencedContentsChanged. + /// + public static void Clear() + { + List oldActions; + lock (lockObject) { + oldActions = actions; + actions = new List(); + } + foreach (Action a in oldActions) { + a(); + } + } + + static readonly object lockObject = new Object(); + static List actions = new List(); + + public static void RegisterForClear(Action action) + { + lock (lockObject) { + actions.Add(action); + } + } + } +} diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs index 0540404528..ba22beb063 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs @@ -60,7 +60,7 @@ namespace ICSharpCode.SharpDevelop.Dom copy.UserData = this.UserData; return copy; } - */ + */ byte flags; const byte hasPublicOrInternalStaticMembersFlag = 0x02; @@ -348,13 +348,14 @@ namespace ICSharpCode.SharpDevelop.Dom return CompareTo((IClass)o); } - List inheritanceTreeCache; + volatile List inheritanceTreeCache; public IEnumerable ClassInheritanceTree { get { - if (inheritanceTreeCache != null) - return inheritanceTreeCache; - List visitedList = new List(); + List visitedList = inheritanceTreeCache; + if (visitedList != null) + return visitedList; + visitedList = new List(); Queue typesToVisit = new Queue(); bool enqueuedLastBaseType = false; IClass currentClass = this; @@ -378,13 +379,17 @@ namespace ICSharpCode.SharpDevelop.Dom currentClass = nextType.GetUnderlyingClass(); } } while (nextType != null); - if (UseInheritanceCache) - inheritanceTreeCache = visitedList; + inheritanceTreeCache = visitedList; + if (!KeepInheritanceTree) + DomCache.RegisterForClear(delegate { inheritanceTreeCache = null; }); return visitedList; } } - protected bool UseInheritanceCache = false; + /// + /// Specifies whether to keep the inheritance tree when the DomCache is cleared. + /// + protected bool KeepInheritanceTree = false; public IReturnType GetBaseType(int index) { diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs index 8c7d49d4a3..99e590b037 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; +using System.Threading; namespace ICSharpCode.SharpDevelop.Dom { @@ -41,70 +42,29 @@ namespace ICSharpCode.SharpDevelop.Dom shortName = name.Substring(pos + 1); } - // we need to use a static Dictionary as cache to provide a easy was to clear all cached - // BaseTypes. - // When the cached BaseTypes could not be cleared as soon as the parse information is updated - // (in contrast to a check if the parse information was updated when the base type is needed - // the next time), we can get a memory leak: - // The cached type of a property in Class1 is Class2. Then Class2 is updated, but the property - // in Class1 is not needed again -> the reference causes the GC to keep the old version - // of Class2 in memory. - // The solution is this static cache which is cleared when some parse information updates. - // That way, there can never be any reference to an out-of-date class. - static Dictionary cache = new Dictionary(new ReferenceComparer()); + volatile IReturnType cachedBaseType; + int isSearching; // 0=false, 1=true - class ReferenceComparer : IEqualityComparer + void ClearCachedBaseType() { - public bool Equals(SearchClassReturnType x, SearchClassReturnType y) - { - return x == y; // don't use x.Equals(y) - Equals might cause a FullyQualifiedName lookup on its own - } - - public int GetHashCode(SearchClassReturnType obj) - { - return obj.GetObjectHashCode(); - } + cachedBaseType = null; } - /// - /// Clear the static searchclass cache. You should call this method - /// whenever the DOM changes. - /// - /// - /// automatically called by DefaultProjectContent.UpdateCompilationUnit - /// and DefaultProjectContent.OnReferencedContentsChanged. - /// - internal static void ClearCache() - { - lock (cache) { - cache.Clear(); - } - } - - bool isSearching; - public override IReturnType BaseType { get { - IReturnType type; - lock (cache) { - if (isSearching) - return null; - - if (cache.TryGetValue(this, out type)) - return type; - - isSearching = true; - } + IReturnType type = cachedBaseType; + if (type != null) + return type; + if (Interlocked.CompareExchange(ref isSearching, 1, 0) != 0) + return null; try { type = pc.SearchType(new SearchTypeRequest(name, typeParameterCount, declaringClass, caretLine, caretColumn)).Result; - lock (cache) { - isSearching = false; - cache[this] = type; - } + cachedBaseType = type; + if (type != null) + DomCache.RegisterForClear(ClearCachedBaseType); return type; - } catch { - isSearching = false; - throw; + } finally { + isSearching = 0; } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SystemTypes.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SystemTypes.cs index d74838e33b..f972323738 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SystemTypes.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SystemTypes.cs @@ -111,7 +111,7 @@ namespace ICSharpCode.SharpDevelop.Dom public override IClass GetUnderlyingClass() { - return pc.GetClass("System.Void", 0, LanguageProperties.CSharp, true); + return pc.GetClass("System.Void", 0, LanguageProperties.CSharp, GetClassOptions.LookInReferences); } public override List GetMethods() diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs index f4bdad4fb1..e5bcfc5113 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs @@ -699,6 +699,7 @@ namespace ICSharpCode.SharpDevelop.Dom return resultList; } + HashSet visitedSet = new HashSet(); List visitedList = new List(); Queue typesToVisit = new Queue(); bool enqueuedLastBaseType = false; @@ -708,7 +709,7 @@ namespace ICSharpCode.SharpDevelop.Dom IReturnType nextType; do { if (currentClass != null) { - if (!visitedList.Contains(currentType)) { + if (visitedSet.Add(currentType)) { visitedList.Add(currentType); foreach (IReturnType type in currentClass.BaseTypes) { typesToVisit.Enqueue(TranslateIfRequired(currentType, type)); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs index 430f025868..a9d66b7090 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs @@ -229,7 +229,7 @@ namespace ICSharpCode.SharpDevelop.Dom lock (namespaces) { AddClassToNamespaceListInternal(addClass); } - SearchClassReturnType.ClearCache(); + DomCache.Clear(); } /// @@ -462,7 +462,7 @@ namespace ICSharpCode.SharpDevelop.Dom foreach (IAttribute attr in unit.Attributes) assemblyAttributes.Remove(attr); } - SearchClassReturnType.ClearCache(); + DomCache.Clear(); } public void UpdateCompilationUnit(ICompilationUnit oldUnit, ICompilationUnit parserOutput, string fileName) @@ -481,7 +481,7 @@ namespace ICSharpCode.SharpDevelop.Dom } assemblyAttributes.AddRange(parserOutput.Attributes); } - SearchClassReturnType.ClearCache(); + DomCache.Clear(); } protected void RemoveClass(IClass @class) @@ -554,14 +554,9 @@ namespace ICSharpCode.SharpDevelop.Dom } #region Default Parser Layer dependent functions - public IClass GetClass(string typeName) - { - return GetClass(typeName, 0); - } - public IClass GetClass(string typeName, int typeParameterCount) { - return GetClass(typeName, typeParameterCount, language, true); + return GetClass(typeName, typeParameterCount, language, GetClassOptions.Default); } protected IClass GetClassInternal(string typeName, int typeParameterCount, LanguageProperties language) @@ -587,7 +582,7 @@ namespace ICSharpCode.SharpDevelop.Dom return c.IsPublic || c.ProjectContent == this; } - public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, bool lookInReferences) + public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, GetClassOptions options) { IClass c = GetClassInternal(typeName, typeParameterCount, language); if (c != null && c.TypeParameters.Count == typeParameterCount) { @@ -595,10 +590,10 @@ namespace ICSharpCode.SharpDevelop.Dom } // Search in references: - if (lookInReferences) { + if ((options & GetClassOptions.LookInReferences) != 0) { lock (referencedContents) { foreach (IProjectContent content in referencedContents) { - IClass contentClass = content.GetClass(typeName, typeParameterCount, language, false); + IClass contentClass = content.GetClass(typeName, typeParameterCount, language, GetClassOptions.None); if (contentClass != null) { if (contentClass.TypeParameters.Count == typeParameterCount && IsAccessibleClass(contentClass)) @@ -616,19 +611,21 @@ namespace ICSharpCode.SharpDevelop.Dom return c; } - // not found -> maybe nested type -> trying to find class that contains this one. - int lastIndex = typeName.LastIndexOf('.'); - if (lastIndex > 0) { - string outerName = typeName.Substring(0, lastIndex); - IClass upperClass = GetClass(outerName, typeParameterCount, language, lookInReferences); - if (upperClass != null) { - foreach (IClass upperBaseClass in upperClass.ClassInheritanceTree) { - IList innerClasses = upperBaseClass.InnerClasses; - if (innerClasses != null) { - string innerName = typeName.Substring(lastIndex + 1); - foreach (IClass innerClass in innerClasses) { - if (language.NameComparer.Equals(innerClass.Name, innerName)) { - return innerClass; + if ((options & GetClassOptions.LookForInnerClass) != 0) { + // not found -> maybe nested type -> trying to find class that contains this one. + int lastIndex = typeName.LastIndexOf('.'); + if (lastIndex > 0) { + string outerName = typeName.Substring(0, lastIndex); + IClass upperClass = GetClass(outerName, typeParameterCount, language, options); + if (upperClass != null) { + foreach (IClass upperBaseClass in upperClass.ClassInheritanceTree) { + IList innerClasses = upperBaseClass.InnerClasses; + if (innerClasses != null) { + string innerName = typeName.Substring(lastIndex + 1); + foreach (IClass innerClass in innerClasses) { + if (language.NameComparer.Equals(innerClass.Name, innerName)) { + return innerClass; + } } } } @@ -895,9 +892,9 @@ namespace ICSharpCode.SharpDevelop.Dom int typeParameterCount = className[className.Length - 1] - '0'; if (typeParameterCount < 0) typeParameterCount = 0; className = className.Substring(0, className.Length - 2); - return GetClass(className, typeParameterCount, LanguageProperties.CSharp, lookInReferences); + return GetClass(className, typeParameterCount, LanguageProperties.CSharp, GetClassOptions.Default); } else { - return GetClass(className, 0, LanguageProperties.CSharp, lookInReferences); + return GetClass(className, 0, LanguageProperties.CSharp, GetClassOptions.Default); } } @@ -999,7 +996,7 @@ namespace ICSharpCode.SharpDevelop.Dom protected virtual void OnReferencedContentsChanged(EventArgs e) { systemTypes = null; // re-create system types - SearchClassReturnType.ClearCache(); + DomCache.Clear(); if (ReferencedContentsChanged != null) { ReferencedContentsChanged(this, e); } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs index fb8cc6c4c3..e7ad8cee88 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs @@ -89,7 +89,7 @@ namespace ICSharpCode.SharpDevelop.Dom bool NamespaceExists(string name); ArrayList GetNamespaceContents(string nameSpace); - IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, bool lookInReferences); + IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, GetClassOptions options); bool NamespaceExists(string name, LanguageProperties language, bool lookInReferences); /// /// Adds the contents of the specified to the . @@ -113,6 +113,24 @@ namespace ICSharpCode.SharpDevelop.Dom FilePosition GetPosition(IEntity entity); } + [Flags] + public enum GetClassOptions + { + None = 0, + /// + /// Also look in referenced project contents. + /// + LookInReferences = 1, + /// + /// Try if the class is an inner class. + /// + LookForInnerClass = 2, + /// + /// Default = LookInReferences + LookForInnerClass + /// + Default = LookInReferences | LookForInnerClass + } + public struct SearchTypeRequest { public readonly string Name; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionClass.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionClass.cs index 06b3eff4b2..6d24ab937c 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionClass.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ReflectionLayer/ReflectionClass.cs @@ -105,7 +105,7 @@ namespace ICSharpCode.SharpDevelop.Dom.ReflectionLayer FullyQualifiedName = fullName; } - this.UseInheritanceCache = true; + this.KeepInheritanceTree = true; try { AddAttributes(compilationUnit.ProjectContent, this.Attributes, CustomAttributeData.GetCustomAttributes(type)); From 04be1cd83a987249b0503d676fa967d953332055 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 30 Sep 2008 15:59:28 +0000 Subject: [PATCH 05/51] Add cache for MemberLookupHelper.GetTypeInheritanceTree. Improves performance when there are many extension methods available for code completion. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3574 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/MemberLookupHelper.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs index e5bcfc5113..46566ff33e 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs @@ -669,6 +669,15 @@ namespace ICSharpCode.SharpDevelop.Dom } } + readonly static Dictionary> getTypeInheritanceTreeCache = new Dictionary>(); + + static void ClearGetTypeInheritanceTreeCache() + { + lock (getTypeInheritanceTreeCache) { + getTypeInheritanceTreeCache.Clear(); + } + } + /// /// Gets all types the specified type inherits from (all classes and interfaces). /// Unlike the class inheritance tree, this method takes care of type arguments and calculates the type @@ -679,6 +688,12 @@ namespace ICSharpCode.SharpDevelop.Dom if (typeToListInheritanceTreeFor == null) throw new ArgumentNullException("typeToListInheritanceTreeFor"); + lock (getTypeInheritanceTreeCache) { + IEnumerable result; + if (getTypeInheritanceTreeCache.TryGetValue(typeToListInheritanceTreeFor, out result)) + return result; + } + IClass classToListInheritanceTreeFor = typeToListInheritanceTreeFor.GetUnderlyingClass(); if (classToListInheritanceTreeFor == null) return new IReturnType[] { typeToListInheritanceTreeFor }; @@ -727,6 +742,12 @@ namespace ICSharpCode.SharpDevelop.Dom currentClass = nextType.GetUnderlyingClass(); } } while (nextType != null); + lock (getTypeInheritanceTreeCache) { + if (getTypeInheritanceTreeCache.Count == 0) { + DomCache.RegisterForClear(ClearGetTypeInheritanceTreeCache); + } + getTypeInheritanceTreeCache[typeToListInheritanceTreeFor] = visitedList; + } return visitedList; } #endregion From ed46c19785b4cdb50896cc52850f6952196851e9 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 1 Oct 2008 22:44:24 +0000 Subject: [PATCH 06/51] Remove ClassWizard AddIn. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3576 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../ClassWizard/ClassWizard.addin | 0 .../ClassWizard/ClassWizard.csproj | 21 +- samples/ClassWizard/ClassWizard.sln | 18 ++ .../ClassWizard/Configuration/AssemblyInfo.cs | 0 .../ClassWizard/Resources/AddClassForm.xfrm | 0 .../ClassWizard/Resources/ClassesList.xfrm | 0 .../ClassWizard/Src/AddClassForm.cs | 0 .../ClassWizard/Src/AddNewClassCommand.cs | 0 .../ClassWizard/Src/AddNewInterfaceCommand.cs | 0 .../ClassWizard/Src/ClassesList.cs | 0 src/Setup/Files.wxs | 8 - src/Setup/Setup.wxs | 2 - src/SharpDevelop.sln | 295 +++++++++--------- 13 files changed, 171 insertions(+), 173 deletions(-) rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/ClassWizard.addin (100%) rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/ClassWizard.csproj (78%) create mode 100644 samples/ClassWizard/ClassWizard.sln rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/Configuration/AssemblyInfo.cs (100%) rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/Resources/AddClassForm.xfrm (100%) rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/Resources/ClassesList.xfrm (100%) rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/Src/AddClassForm.cs (100%) rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/Src/AddNewClassCommand.cs (100%) rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/Src/AddNewInterfaceCommand.cs (100%) rename {src/AddIns/DisplayBindings/ClassDiagram => samples}/ClassWizard/Src/ClassesList.cs (100%) diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/ClassWizard.addin b/samples/ClassWizard/ClassWizard.addin similarity index 100% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/ClassWizard.addin rename to samples/ClassWizard/ClassWizard.addin diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/ClassWizard.csproj b/samples/ClassWizard/ClassWizard.csproj similarity index 78% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/ClassWizard.csproj rename to samples/ClassWizard/ClassWizard.csproj index 493876aaa2..7c9928cb3d 100644 --- a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/ClassWizard.csproj +++ b/samples/ClassWizard/ClassWizard.csproj @@ -6,24 +6,24 @@ Debug AnyCPU {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4} - ..\..\..\..\..\AddIns\AddIns\Misc\ClassWizard\ + ..\..\AddIns\Samples\ClassWizard False False 4 false + C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis obj\Debug\ False DEBUG;TRACE - True + true Full True Program - ..\..\..\..\..\bin\SharpDevelop.exe + ..\..\bin\SharpDevelop.exe - obj\ obj\Release\ True TRACE @@ -51,9 +51,6 @@ - - Configuration\GlobalAssemblyInfo.cs - @@ -61,27 +58,27 @@ - + {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 diff --git a/samples/ClassWizard/ClassWizard.sln b/samples/ClassWizard/ClassWizard.sln new file mode 100644 index 0000000000..9a3305f025 --- /dev/null +++ b/samples/ClassWizard/ClassWizard.sln @@ -0,0 +1,18 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +# SharpDevelop 3.0.0.3558 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassWizard", "ClassWizard.csproj", "{8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Release|Any CPU.Build.0 = Release|Any CPU + {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Release|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Configuration/AssemblyInfo.cs b/samples/ClassWizard/Configuration/AssemblyInfo.cs similarity index 100% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Configuration/AssemblyInfo.cs rename to samples/ClassWizard/Configuration/AssemblyInfo.cs diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Resources/AddClassForm.xfrm b/samples/ClassWizard/Resources/AddClassForm.xfrm similarity index 100% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Resources/AddClassForm.xfrm rename to samples/ClassWizard/Resources/AddClassForm.xfrm diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Resources/ClassesList.xfrm b/samples/ClassWizard/Resources/ClassesList.xfrm similarity index 100% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Resources/ClassesList.xfrm rename to samples/ClassWizard/Resources/ClassesList.xfrm diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Src/AddClassForm.cs b/samples/ClassWizard/Src/AddClassForm.cs similarity index 100% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Src/AddClassForm.cs rename to samples/ClassWizard/Src/AddClassForm.cs diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Src/AddNewClassCommand.cs b/samples/ClassWizard/Src/AddNewClassCommand.cs similarity index 100% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Src/AddNewClassCommand.cs rename to samples/ClassWizard/Src/AddNewClassCommand.cs diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Src/AddNewInterfaceCommand.cs b/samples/ClassWizard/Src/AddNewInterfaceCommand.cs similarity index 100% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Src/AddNewInterfaceCommand.cs rename to samples/ClassWizard/Src/AddNewInterfaceCommand.cs diff --git a/src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Src/ClassesList.cs b/samples/ClassWizard/Src/ClassesList.cs similarity index 100% rename from src/AddIns/DisplayBindings/ClassDiagram/ClassWizard/Src/ClassesList.cs rename to samples/ClassWizard/Src/ClassesList.cs diff --git a/src/Setup/Files.wxs b/src/Setup/Files.wxs index b89841868f..160757ed43 100644 --- a/src/Setup/Files.wxs +++ b/src/Setup/Files.wxs @@ -1521,14 +1521,6 @@ - - - - - - - - diff --git a/src/Setup/Setup.wxs b/src/Setup/Setup.wxs index f6c6e7e8bb..d7921bcf22 100644 --- a/src/Setup/Setup.wxs +++ b/src/Setup/Setup.wxs @@ -421,8 +421,6 @@ - - diff --git a/src/SharpDevelop.sln b/src/SharpDevelop.sln index d9f6fba020..df7d6c2684 100644 --- a/src/SharpDevelop.sln +++ b/src/SharpDevelop.sln @@ -1,178 +1,176 @@  Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 -# SharpDevelop 3.0.0.3360 +# SharpDevelop 3.0.0.3558 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}") = "WpfDesign.XamlDom", "AddIns\DisplayBindings\WpfDesign\WpfDesign.XamlDom\Project\WpfDesign.XamlDom.csproj", "{88DA149F-21B2-48AB-82C4-28FB6BDFD783}" +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.Designer", "AddIns\DisplayBindings\WpfDesign\WpfDesign.Designer\Project\WpfDesign.Designer.csproj", "{78CC29AC-CC79-4355-B1F2-97936DF198AC}" +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", "AddIns\DisplayBindings\WpfDesign\WpfDesign\Project\WpfDesign.csproj", "{66A378A1-E9F4-4AD5-8946-D0EC06C2902F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartPage", "AddIns\Misc\StartPage\Project\StartPage.csproj", "{7D5C266F-D6FF-4D14-B315-0C0FC6C4EF51}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClassDiagram", "ClassDiagram", "{DB137F0B-9B62-4232-AE92-F7BE0280B8D3}" - ProjectSection(SolutionItems) = postProject - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegExpTk", "AddIns\Misc\RegExpTk\Project\RegExpTk.csproj", "{64A3E5E6-90BF-47F6-94DF-68C94B62C817}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassWizard", "AddIns\DisplayBindings\ClassDiagram\ClassWizard\ClassWizard.csproj", "{8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}" +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}") = "Diagrams", "AddIns\DisplayBindings\ClassDiagram\DiagramRouter\Diagrams.csproj", "{0991423A-DBF6-4C89-B365-A1DF1EB32E42}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FiletypeRegisterer", "AddIns\Misc\FiletypeRegisterer\Project\FiletypeRegisterer.csproj", "{D022A6CE-7438-41E8-AC64-F2DE18EC54C6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassDiagramAddin", "AddIns\DisplayBindings\ClassDiagram\ClassDiagramAddin\ClassDiagramAddin.csproj", "{5A1354DF-4989-4BB4-BC6B-D627C2E9FA13}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{6604365C-C702-4C10-9BA8-637F1E3D4D0D}" + ProjectSection(SolutionItems) = postProject + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassEditor", "AddIns\DisplayBindings\ClassDiagram\ClassEditor\ClassEditor.csproj", "{F5E059BB-96C2-4398-BED0-8598CD434173}" +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}") = "ClassCanvas", "AddIns\DisplayBindings\ClassDiagram\ClassCanvas\ClassCanvas.csproj", "{08F772A1-F0BE-433E-8B37-F6522953DB05}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Debugger.AddIn", "AddIns\Misc\Debugger\Debugger.AddIn\Project\Debugger.AddIn.csproj", "{EC06F96A-AEEC-49D6-B03D-AB87C6EB674C}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IconEditor", "IconEditor", "{0D37CE59-B0EF-4F3C-B9EB-8557E53A448B}" - ProjectSection(SolutionItems) = postProject - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HtmlHelp2", "AddIns\Misc\HtmlHelp2\Project\HtmlHelp2.csproj", "{918487B7-2153-4618-BBB3-344DBDDF2A2A}" 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}") = "AddInManager", "AddIns\Misc\AddInManager\Project\AddInManager.csproj", "{F93E52FD-DA66-4CE5-A0CB-BCD902811122}" 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}") = "PInvokeAddIn", "AddIns\Misc\PInvokeAddIn\Project\PInvokeAddIn.csproj", "{5EEB99CF-EA2B-4733-80A6-CE9192D68170}" 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}") = "CodeCoverage", "AddIns\Misc\CodeCoverage\Project\CodeCoverage.csproj", "{08ce9972-283b-44f4-82fa-966f7dfa6b7a}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsDesigner", "AddIns\DisplayBindings\FormsDesigner\Project\FormsDesigner.csproj", "{7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTesting", "AddIns\Misc\UnitTesting\UnitTesting.csproj", "{1F261725-6318-4434-A1B1-6C70CE4CD324}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResourceEditor", "AddIns\DisplayBindings\ResourceEditor\Project\ResourceEditor.csproj", "{CBC6C247-747B-4908-B09A-4D2E0F640B6B}" +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}") = "HexEditor", "AddIns\DisplayBindings\HexEditor\Project\HexEditor.csproj", "{E618A9CD-A39F-4925-A538-E8A3FEF24E54}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SubversionAddIn", "AddIns\Misc\SubversionAddIn\Project\SubversionAddIn.csproj", "{17F4D7E0-6933-4C2E-8714-FD7E98D625D5}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backends", "Backends", "{FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysis", "AddIns\Misc\CodeAnalysis\CodeAnalysis.csproj", "{3EAA45A9-735C-4AC7-A799-947B93EA449D}" +EndProject +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}") = "PythonBinding", "AddIns\BackendBindings\Python\PythonBinding\Project\PythonBinding.csproj", "{8D732610-8FC6-43BA-94C9-7126FD7FE361}" +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}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpBinding", "AddIns\BackendBindings\CSharpBinding\Project\CSharpBinding.csproj", "{1F1AC7CD-D154-45BB-8EAF-804CA8055F5A}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misc", "Misc", "{CE5B42B7-6E8C-4385-9E97-F4023FC16BF2}" - ProjectSection(SolutionItems) = postProject - EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VBNetBinding", "AddIns\BackendBindings\VBNetBinding\Project\VBNetBinding.csproj", "{BF38FB72-B380-4196-AF8C-95749D726C61}" 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}") = "ILAsmBinding", "AddIns\BackendBindings\ILAsmBinding\Project\ILAsmBinding.csproj", "{6e59af58-f635-459a-9a35-c9ac41c00339}" 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}") = "BooBinding", "AddIns\BackendBindings\Boo\BooBinding\Project\BooBinding.csproj", "{4AC2D5F1-F671-480C-A075-6BF62B3721B2}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ComponentInspector", "ComponentInspector", "{BDDDCD01-D2FE-4EAD-9425-4B6B91922C7C}" - ProjectSection(SolutionItems) = postProject - EndProjectSection +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.Core", "AddIns\Misc\ComponentInspector\ComponentInspector.Core\ComponentInspector.Core.csproj", "{E6F4983F-DE41-4AEC-88E7-1FA9AFB4E6FF}" +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}") = "ComponentInspector.AddIn", "AddIns\Misc\ComponentInspector\ComponentInspector.AddIn\ComponentInspector.AddIn.csproj", "{869951D5-A0D6-4DC6-9F1D-E6B9A12AC446}" +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}") = "ComponentInspector", "AddIns\Misc\ComponentInspector\ComponentInspector\ComponentInspector.csproj", "{000E4F64-5D0D-4EB1-B0BF-1A62ADBC6EAD}" +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}") = "CodeAnalysis", "AddIns\Misc\CodeAnalysis\CodeAnalysis.csproj", "{3EAA45A9-735C-4AC7-A799-947B93EA449D}" +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}") = "SubversionAddIn", "AddIns\Misc\SubversionAddIn\Project\SubversionAddIn.csproj", "{17F4D7E0-6933-4C2E-8714-FD7E98D625D5}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HexEditor", "AddIns\DisplayBindings\HexEditor\Project\HexEditor.csproj", "{E618A9CD-A39F-4925-A538-E8A3FEF24E54}" 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}") = "ResourceEditor", "AddIns\DisplayBindings\ResourceEditor\Project\ResourceEditor.csproj", "{CBC6C247-747B-4908-B09A-4D2E0F640B6B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTesting", "AddIns\Misc\UnitTesting\UnitTesting.csproj", "{1F261725-6318-4434-A1B1-6C70CE4CD324}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FormsDesigner", "AddIns\DisplayBindings\FormsDesigner\Project\FormsDesigner.csproj", "{7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCoverage", "AddIns\Misc\CodeCoverage\Project\CodeCoverage.csproj", "{08ce9972-283b-44f4-82fa-966f7dfa6b7a}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlEditor", "AddIns\DisplayBindings\XmlEditor\Project\XmlEditor.csproj", "{6B717BD1-CD5E-498C-A42E-9E6A4584DC48}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PInvokeAddIn", "AddIns\Misc\PInvokeAddIn\Project\PInvokeAddIn.csproj", "{5EEB99CF-EA2B-4733-80A6-CE9192D68170}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "IconEditor", "IconEditor", "{0D37CE59-B0EF-4F3C-B9EB-8557E53A448B}" + ProjectSection(SolutionItems) = postProject + EndProjectSection 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}") = "IconEditor", "AddIns\DisplayBindings\IconEditor\IconEditor\IconEditor.csproj", "{DC1CCE11-CB91-40FA-9C47-4D9EB5D67BFD}" 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}") = "IconEditorAddIn", "AddIns\DisplayBindings\IconEditor\IconEditorAddIn\IconEditorAddIn.csproj", "{DFB936AD-90EE-4B4F-941E-4F4A636F0D92}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{6604365C-C702-4C10-9BA8-637F1E3D4D0D}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ClassDiagram", "ClassDiagram", "{DB137F0B-9B62-4232-AE92-F7BE0280B8D3}" 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}" -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}") = "ClassCanvas", "AddIns\DisplayBindings\ClassDiagram\ClassCanvas\ClassCanvas.csproj", "{08F772A1-F0BE-433E-8B37-F6522953DB05}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FiletypeRegisterer", "AddIns\Misc\FiletypeRegisterer\Project\FiletypeRegisterer.csproj", "{D022A6CE-7438-41E8-AC64-F2DE18EC54C6}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassEditor", "AddIns\DisplayBindings\ClassDiagram\ClassEditor\ClassEditor.csproj", "{F5E059BB-96C2-4398-BED0-8598CD434173}" 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}") = "ClassDiagramAddin", "AddIns\DisplayBindings\ClassDiagram\ClassDiagramAddin\ClassDiagramAddin.csproj", "{5A1354DF-4989-4BB4-BC6B-D627C2E9FA13}" 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}") = "Diagrams", "AddIns\DisplayBindings\ClassDiagram\DiagramRouter\Diagrams.csproj", "{0991423A-DBF6-4C89-B365-A1DF1EB32E42}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StartPage", "AddIns\Misc\StartPage\Project\StartPage.csproj", "{7D5C266F-D6FF-4D14-B315-0C0FC6C4EF51}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WpfDesign", "WpfDesign", "{388C3979-2621-4839-A955-7E5C03BA0B63}" + ProjectSection(SolutionItems) = postProject + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AddinScout", "AddIns\Misc\AddinScout\Project\AddinScout.csproj", "{4B8F0F98-8BE1-402B-AA8B-C8D548577B38}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WpfDesign", "AddIns\DisplayBindings\WpfDesign\WpfDesign\Project\WpfDesign.csproj", "{66A378A1-E9F4-4AD5-8946-D0EC06C2902F}" 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.Designer", "AddIns\DisplayBindings\WpfDesign\WpfDesign.Designer\Project\WpfDesign.Designer.csproj", "{78CC29AC-CC79-4355-B1F2-97936DF198AC}" 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.XamlDom", "AddIns\DisplayBindings\WpfDesign\WpfDesign.XamlDom\Project\WpfDesign.XamlDom.csproj", "{88DA149F-21B2-48AB-82C4-28FB6BDFD783}" 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 @@ -356,10 +354,6 @@ Global {0991423A-DBF6-4C89-B365-A1DF1EB32E42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0991423A-DBF6-4C89-B365-A1DF1EB32E42}.Release|Any CPU.Build.0 = Release|Any CPU {0991423A-DBF6-4C89-B365-A1DF1EB32E42}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Release|Any CPU.Build.0 = Release|Any CPU - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Release|Any CPU.ActiveCfg = Release|Any CPU {E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|Any CPU.Build.0 = Debug|Any CPU {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 @@ -430,76 +424,75 @@ Global {3CA90546-3B4C-4663-9445-C4E9371750A7}.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} - {F5E059BB-96C2-4398-BED0-8598CD434173} = {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} - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4} = {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} + {99BAE3A2-C40D-40D2-A7B4-EBB4798F36E4} = {FEB825FA-4AD8-425D-8E4A-B5A18EE1B81C} + {7C96B65D-28A5-4F28-A35B-8D83CE831EE8} = {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} + {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} + {F5E059BB-96C2-4398-BED0-8598CD434173} = {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} + {88DA149F-21B2-48AB-82C4-28FB6BDFD783} = {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 From 3c45d0ddaea99af157e42000910a61aecbd7ef01 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 2 Oct 2008 21:52:18 +0000 Subject: [PATCH 07/51] Remove ClassEditor. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3577 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- samples/ClassWizard/ClassWizard.addin | 24 - samples/ClassWizard/ClassWizard.csproj | 88 --- samples/ClassWizard/ClassWizard.sln | 18 - .../ClassWizard/Configuration/AssemblyInfo.cs | 20 - .../ClassWizard/Resources/AddClassForm.xfrm | 215 ------- .../ClassWizard/Resources/ClassesList.xfrm | 39 -- samples/ClassWizard/Src/AddClassForm.cs | 189 ------ samples/ClassWizard/Src/AddNewClassCommand.cs | 34 -- .../ClassWizard/Src/AddNewInterfaceCommand.cs | 13 - samples/ClassWizard/Src/ClassesList.cs | 185 ------ .../ClassDiagramAddin/ClassDiagramAddin.addin | 14 +- .../ClassDiagramAddin.csproj | 5 - .../Src/ClassDiagramViewContent.cs | 14 - .../ClassDiagramAddin/Src/ClassEditorPad.cs | 191 ------ .../ClassDiagram/ClassEditor/AssemblyInfo.cs | 22 - .../ClassEditor/ClassEditor.Designer.cs | 177 ------ .../ClassDiagram/ClassEditor/ClassEditor.cs | 577 ------------------ .../ClassEditor/ClassEditor.csproj | 87 --- .../ClassDiagram/ClassEditor/ClassEditor.resx | 120 ---- .../ClassEditor/MemberDataEditors.cs | 52 -- .../ClassEditor/MemberEventArgs.cs | 73 --- .../ClassEditor/ParameterEventArgs.cs | 79 --- .../ClassDiagram/ClassEditor/closebrace.bmp | Bin 246 -> 0 bytes .../ClassDiagram/ClassEditor/comma.bmp | Bin 246 -> 0 bytes .../ClassDiagram/ClassEditor/emptybraces.bmp | Bin 246 -> 0 bytes .../ClassDiagram/ClassEditor/openbrace.bmp | Bin 246 -> 0 bytes src/Setup/Files.wxs | 3 - src/Setup/Setup.wxs | 1 - src/SharpDevelop.sln | 287 +++++---- 29 files changed, 145 insertions(+), 2382 deletions(-) delete mode 100644 samples/ClassWizard/ClassWizard.addin delete mode 100644 samples/ClassWizard/ClassWizard.csproj delete mode 100644 samples/ClassWizard/ClassWizard.sln delete mode 100644 samples/ClassWizard/Configuration/AssemblyInfo.cs delete mode 100644 samples/ClassWizard/Resources/AddClassForm.xfrm delete mode 100644 samples/ClassWizard/Resources/ClassesList.xfrm delete mode 100644 samples/ClassWizard/Src/AddClassForm.cs delete mode 100644 samples/ClassWizard/Src/AddNewClassCommand.cs delete mode 100644 samples/ClassWizard/Src/AddNewInterfaceCommand.cs delete mode 100644 samples/ClassWizard/Src/ClassesList.cs delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassDiagramAddin/Src/ClassEditorPad.cs delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/AssemblyInfo.cs delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/ClassEditor.Designer.cs delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/ClassEditor.cs delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/ClassEditor.csproj delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/ClassEditor.resx delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/MemberDataEditors.cs delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/MemberEventArgs.cs delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/ParameterEventArgs.cs delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/closebrace.bmp delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/comma.bmp delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/emptybraces.bmp delete mode 100644 src/AddIns/DisplayBindings/ClassDiagram/ClassEditor/openbrace.bmp diff --git a/samples/ClassWizard/ClassWizard.addin b/samples/ClassWizard/ClassWizard.addin deleted file mode 100644 index 5584338752..0000000000 --- a/samples/ClassWizard/ClassWizard.addin +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/samples/ClassWizard/ClassWizard.csproj b/samples/ClassWizard/ClassWizard.csproj deleted file mode 100644 index 7c9928cb3d..0000000000 --- a/samples/ClassWizard/ClassWizard.csproj +++ /dev/null @@ -1,88 +0,0 @@ - - - Library - ClassWizard - ClassWizard - Debug - AnyCPU - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4} - ..\..\AddIns\Samples\ClassWizard - False - False - 4 - false - C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis - - - obj\Debug\ - False - DEBUG;TRACE - true - Full - True - Program - ..\..\bin\SharpDevelop.exe - - - obj\Release\ - True - TRACE - False - None - False - - - False - Auto - 4194304 - AnyCPU - 4096 - - - - - - - - - - - Always - - - - - - - - - - - - {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 - - - - \ No newline at end of file diff --git a/samples/ClassWizard/ClassWizard.sln b/samples/ClassWizard/ClassWizard.sln deleted file mode 100644 index 9a3305f025..0000000000 --- a/samples/ClassWizard/ClassWizard.sln +++ /dev/null @@ -1,18 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -# SharpDevelop 3.0.0.3558 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassWizard", "ClassWizard.csproj", "{8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Release|Any CPU.Build.0 = Release|Any CPU - {8C59E80D-C4E4-4F36-9AD8-47C40F6E58B4}.Release|Any CPU.ActiveCfg = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/samples/ClassWizard/Configuration/AssemblyInfo.cs b/samples/ClassWizard/Configuration/AssemblyInfo.cs deleted file mode 100644 index 518aa5f7fc..0000000000 --- a/samples/ClassWizard/Configuration/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -// -// -// -// -// - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Information about this assembly is defined by the following -// attributes. -// -// change them to the information which is associated with the assembly -// you compile. -[assembly: AssemblyTitle("ClassWizard")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] diff --git a/samples/ClassWizard/Resources/AddClassForm.xfrm b/samples/ClassWizard/Resources/AddClassForm.xfrm deleted file mode 100644 index 7f03f67af4..0000000000 --- a/samples/ClassWizard/Resources/AddClassForm.xfrm +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/ClassWizard/Resources/ClassesList.xfrm b/samples/ClassWizard/Resources/ClassesList.xfrm deleted file mode 100644 index 35961fd0f5..0000000000 --- a/samples/ClassWizard/Resources/ClassesList.xfrm +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/samples/ClassWizard/Src/AddClassForm.cs b/samples/ClassWizard/Src/AddClassForm.cs deleted file mode 100644 index ba52695e08..0000000000 --- a/samples/ClassWizard/Src/AddClassForm.cs +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Created by SharpDevelop. - * User: itai - * Date: 12/22/2006 - * Time: 3:34 PM - * - * To change this template use Tools | Options | Coding | Edit Standard Headers. - */ - -using System; -using System.IO; -using System.Windows.Forms; - -using ICSharpCode.SharpDevelop; -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Project; -using ICSharpCode.SharpDevelop.Gui.XmlForms; -using ICSharpCode.SharpDevelop.Gui; -using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; -using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.SharpDevelop.Dom.Refactoring; -using ICSharpCode.SharpDevelop.Refactoring; - -namespace ClassWizard -{ - public class AddClassForm : BaseSharpDevelopForm - { - public AddClassForm() - { - SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("ClassWizard.Resources.AddClassForm.xfrm")); - Get public abstract event EventHandler ValueChanged; + /// + /// Is raised when the property changes. + /// This event is not raised when the value is changed without going through the designer infrastructure. + /// public abstract event EventHandler ValueOnInstanceChanged; /// @@ -104,18 +108,34 @@ namespace ICSharpCode.WpfDesign /// public abstract void Reset(); + /// + /// Gets the parent design item. + /// public abstract DesignItem DesignItem { get; } + /// + /// Gets the dependency property, or null if this property does not represent a dependency property. + /// public abstract DependencyProperty DependencyProperty { get; } - public abstract bool IsAdvanced { get; } + /// + /// Gets if this property is considered "advanced" and should be hidden by default in a property grid. + /// + public virtual bool IsAdvanced { get { return false; } } + /// + /// Gets the full name of the property (DeclaringType.FullName + "." + Name). + /// public string FullName { get { return DeclaringType.FullName + "." + Name; } } + /// + /// Gets the full name of the dependency property. Returns the normal FullName if the property + /// isn't a dependency property. + /// public string DependencyFullName { get { if (DependencyProperty != null) { diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs index ee7eab0225..d5c29f5bdf 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Metadata.cs @@ -10,24 +10,41 @@ using System.Diagnostics; namespace ICSharpCode.WpfDesign { + /// + /// Contains helper methods for retrieving meta data. + /// public static class Metadata { + /// + /// Gets the full name of a dependency property (OwnerType.FullName + "." + Name). + /// public static string GetFullName(this DependencyProperty p) { return p.OwnerType.FullName + "." + p.Name; } + // TODO: do we really want to store these values in a static dictionary? + // Why not per-design context (as a service?) static Dictionary> standardValues = new Dictionary>(); + /// + /// Registers a set of standard values for a by using the + /// public static properties of the type . + /// + /// Metadata.AddStandardValues(typeof(Brush), typeof(Brushes)); public static void AddStandardValues(Type type, Type valuesContainer) { - AddStandardValues(type, valuesContainer - .GetProperties(BindingFlags.Public | BindingFlags.Static) - .Select(p => p.GetValue(null, null))); + AddStandardValues(type, + valuesContainer.GetProperties(BindingFlags.Public | BindingFlags.Static) + .Select(p => p.GetValue(null, null))); } + /// + /// Registers a set of standard for a . + /// + /// You can call this method multiple times to add additional standard values. public static void AddStandardValues(Type type, IEnumerable values) - { + { List list; lock (standardValues) { if (!standardValues.TryGetValue(type, out list)) { @@ -40,6 +57,9 @@ namespace ICSharpCode.WpfDesign } } + /// + /// Retrieves the standard values for the specified . + /// public static IEnumerable GetStandardValues(Type type) { if (type.IsEnum) { @@ -109,27 +129,36 @@ namespace ICSharpCode.WpfDesign static HashSet hiddenProperties = new HashSet(); + /// + /// Hides the specified property (marks it as not browsable). + /// public static void HideProperty(DependencyProperty p) { - lock (hiddenProperties) { - hiddenProperties.Add(p.GetFullName()); - } + lock (hiddenProperties) { + hiddenProperties.Add(p.GetFullName()); + } } + /// + /// Hides the specified property (marks it as not browsable). + /// public static void HideProperty(Type type, string member) { - lock (hiddenProperties) { - hiddenProperties.Add(type.FullName + "." + member); - } + lock (hiddenProperties) { + hiddenProperties.Add(type.FullName + "." + member); + } } + /// + /// Gets whether the specified property is browsable (should be visible in property grids). + /// public static bool IsBrowsable(DesignItemProperty p) { - lock (hiddenProperties) { - if (hiddenProperties.Contains(p.DependencyFullName)) { - return false; - } - } + lock (hiddenProperties) { + if (hiddenProperties.Contains(p.DependencyFullName)) { + return false; + } + } return true; } @@ -137,57 +166,76 @@ namespace ICSharpCode.WpfDesign static HashSet popularProperties = new HashSet(); + /// + /// Registers a popular property (shown first in the property grid). + /// public static void AddPopularProperty(DependencyProperty p) { - lock (popularProperties) { - popularProperties.Add(p.GetFullName()); - } + lock (popularProperties) { + popularProperties.Add(p.GetFullName()); + } } + /// + /// Registers a popular property (shown first in the property grid). + /// public static void AddPopularProperty(Type type, string member) { - lock (popularProperties) { - popularProperties.Add(type.FullName + "." + member); - } + lock (popularProperties) { + popularProperties.Add(type.FullName + "." + member); + } } + /// + /// Gets whether the specified property was registered as popular. + /// public static bool IsPopularProperty(DesignItemProperty p) { - lock (popularProperties) { - if (popularProperties.Contains(p.DependencyFullName)) { - return true; - } - } - return false; + lock (popularProperties) { + if (popularProperties.Contains(p.DependencyFullName)) { + return true; + } + } + return false; } static HashSet popularControls = new HashSet(); + /// + /// Registers a popular control (visible in the default toolbox). + /// public static void AddPopularControl(Type t) { - lock (popularControls) { - popularControls.Add(t); - } + lock (popularControls) { + popularControls.Add(t); + } } + /// + /// Gets the list of popular controls. + /// public static IEnumerable GetPopularControls() { - lock (popularControls) { - foreach (var t in popularControls) { - yield return t; - } - } + lock (popularControls) { + return popularControls.ToArray(); + } } + /// + /// Gets whether the specified control was registered as popular. + /// public static bool IsPopularControl(Type t) { - lock (popularControls) { - return popularControls.Contains(t); - } + lock (popularControls) { + return popularControls.Contains(t); + } } - static Dictionary ranges = new Dictionary(); + static Dictionary ranges = new Dictionary(); + /// + /// Registers the value range for the property. + /// public static void AddValueRange(DependencyProperty p, double min, double max) { lock (ranges) { @@ -195,6 +243,9 @@ namespace ICSharpCode.WpfDesign } } + /// + /// Gets the registered value range for the property, or null if no range was registered. + /// public static NumberRange GetValueRange(DesignItemProperty p) { NumberRange r; @@ -208,6 +259,9 @@ namespace ICSharpCode.WpfDesign static HashSet placementDisabled = new HashSet(); + /// + /// Disables the default placement behaviour (setting the ContentProperty) for the type. + /// public static void DisablePlacement(Type type) { lock (placementDisabled) { @@ -215,6 +269,9 @@ namespace ICSharpCode.WpfDesign } } + /// + /// Gets whether thr default placement behaviour (setting the ContentProperty) was disabled for the type. + /// public static bool IsPlacementDisabled(Type type) { lock (placementDisabled) { @@ -222,33 +279,50 @@ namespace ICSharpCode.WpfDesign } } - 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 defaultSizes = new Dictionary(); + + /// + /// Registers a default size for new controls of the specified type. + /// + public static void AddDefaultSize(Type t, Size s) + { + lock (defaultSizes) { + defaultSizes[t] = s; + } + } + + /// + /// Gets the default size for new controls of the specified type, + /// or new Size(double.NaN, double.NaN) if no default size was registered. + /// + 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); + } } + /// + /// Represets the minimum and maximum valid value for a double property. + /// public class NumberRange { - public double Min; - public double Max; + /// + /// Gets/Sets the minimum value. + /// + public double Min { get; set; } + + /// + /// Gets/Sets the maximum value. + /// + public double Max { get; set; } } } diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs index 82d6eec9a8..af34bd436a 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PlacementBehavior.cs @@ -37,6 +37,9 @@ namespace ICSharpCode.WpfDesign /// Rect GetPosition(PlacementOperation operation, DesignItem child); + /// + /// Is called before SetPosition is called for the placed items. + /// void BeforeSetPosition(PlacementOperation operation); /// diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/Category.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/Category.cs index 722775806e..2ca2918a62 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/Category.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/Category.cs @@ -8,8 +8,14 @@ using ICSharpCode.WpfDesign.PropertyGrid; namespace ICSharpCode.WpfDesign.PropertyGrid { + /// + /// View-Model class for a property grid category. + /// public class Category : INotifyPropertyChanged { + // don't warn on missing XML comments in View-Model + #pragma warning disable 1591 + public Category(string name) { Name = name; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs index d226cdfc7b..9c30e60b95 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs @@ -12,8 +12,14 @@ using System.Windows.Markup; namespace ICSharpCode.WpfDesign.PropertyGrid { + /// + /// View-Model class for the property grid. + /// public class PropertyNode : INotifyPropertyChanged { + // don't warn on missing XML comments in View-Model + #pragma warning disable 1591 + static object Unset = new object(); public DesignItemProperty[] Properties { get; private set; } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs index 46566ff33e..7816da3771 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs @@ -93,7 +93,9 @@ namespace ICSharpCode.SharpDevelop.Dom hashCode *= 1000000579; if (p.IsOut || p.IsRef) hashCode += 1; - hashCode += p.ReturnType.GetHashCode(); + if (p.ReturnType != null) { + hashCode += p.ReturnType.GetHashCode(); + } } } cachedHashes[obj] = hashCode; From 751002111b88213e59b7254bac9955e716441614 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 4 Oct 2008 14:24:20 +0000 Subject: [PATCH 13/51] Allow setting integers to hex numbers. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3583 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/TreeModel/ValueNode.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs index 6787ebb4ca..ed4adb0f31 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Windows.Forms; using Debugger.Expressions; @@ -68,7 +69,7 @@ namespace Debugger.AddIn.TreeModel canSetText = false; if (val.Type.IsInteger) { - canSetText = + canSetText = (val.Expression is LocalVariableIdentifierExpression) || (val.Expression is ParameterIdentifierExpression) || (val.Expression is ArrayIndexerExpression) || @@ -139,7 +140,17 @@ namespace Debugger.AddIn.TreeModel Value val = null; try { val = this.Expression.Evaluate(WindowsDebugger.DebuggedProcess.SelectedStackFrame); - val.PrimitiveValue = newText; + if (val.Type.IsInteger && newText.StartsWith("0x")) { + try { + val.PrimitiveValue = long.Parse(newText.Substring(2), NumberStyles.HexNumber); + } catch (FormatException) { + throw new NotSupportedException(); + } catch (OverflowException) { + throw new NotSupportedException(); + } + } else { + val.PrimitiveValue = newText; + } this.Text = newText; return true; } catch (NotSupportedException) { From 213abd0b2abd5bf3ac8985f021eb974e5d4ffb21 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 4 Oct 2008 14:30:41 +0000 Subject: [PATCH 14/51] Fixed null reference exception when debugger is running. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3584 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Debugger.AddIn/Project/Src/IsBreakpointCondition.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/IsBreakpointCondition.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/IsBreakpointCondition.cs index f738c0798b..edf1420543 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/IsBreakpointCondition.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/IsBreakpointCondition.cs @@ -141,8 +141,10 @@ namespace Debugger.AddIn } } - foreach (string item in BreakpointAction.GetNames(typeof(BreakpointAction))) { - items.Add(MakeItem("${res:MainWindow.Windows.Debug.Conditional.Breakpoints." + item + "}", item, point, point.Action.ToString(), delegate(object sender, EventArgs e) {HandleItem(sender);})); + if (point != null) { + foreach (string item in BreakpointAction.GetNames(typeof(BreakpointAction))) { + items.Add(MakeItem("${res:MainWindow.Windows.Debug.Conditional.Breakpoints." + item + "}", item, point, point.Action.ToString(), delegate(object sender, EventArgs e) {HandleItem(sender);})); + } } return items.ToArray(); From c19717ac7e79f2f09ae2560ad2f9f7878c54d10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Sat, 4 Oct 2008 14:41:42 +0000 Subject: [PATCH 15/51] Methods for reading and writing of process memory. Test that breaks string immutability using memory write. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3585 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/Control/Process.cs | 25 ++++++ .../Src/Interop/CorDebug/ICorDebugProcess.cs | 2 +- .../Debugger.Core/Project/Src/Values/Value.cs | 10 +++ .../Autogenerated/ICorDebugProcess.cs | 6 +- .../Project/Debugger.Tests.csproj | 1 + .../Src/TestPrograms/MemoryReadWrite.cs | 85 +++++++++++++++++++ 6 files changed, 125 insertions(+), 4 deletions(-) create mode 100644 src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/MemoryReadWrite.cs diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process.cs index 604e33e76e..ed38b87499 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process.cs @@ -171,6 +171,31 @@ namespace Debugger } } } + + /// Read the specified amount of memory at the given memory address + /// The content of the memory. The amount of the read memory may be less then requested. + public unsafe byte[] ReadMemory(ulong address, int size) + { + byte[] buffer = new byte[size]; + int readCount; + fixed(byte* pBuffer = buffer) { + readCount = (int)corProcess.ReadMemory(address, (uint)size, new IntPtr(pBuffer)); + } + if (readCount != size) Array.Resize(ref buffer, readCount); + return buffer; + } + + /// Writes the given buffer at the specified memory address + /// The number of bytes written + public unsafe int WriteMemory(ulong address, byte[] buffer) + { + if (buffer.Length == 0) return 0; + int written; + fixed(byte* pBuffer = buffer) { + written = (int)corProcess.WriteMemory(address, (uint)buffer.Length, new IntPtr(pBuffer)); + } + return written; + } } [Serializable] diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorDebug/ICorDebugProcess.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorDebug/ICorDebugProcess.cs index 32a263c8d3..4fffcab784 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorDebug/ICorDebugProcess.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorDebug/ICorDebugProcess.cs @@ -55,7 +55,7 @@ namespace Debugger.Interop.CorDebug [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] void ReadMemory([In] ulong address, [In] uint size, [Out] IntPtr buffer, [ComAliasName("Debugger.Interop.CorDebug.ULONG_PTR")] out uint read); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] - void WriteMemory([In] ulong address, [In] uint size, [In] ref byte buffer, [ComAliasName("Debugger.Interop.CorDebug.ULONG_PTR")] out uint written); + void WriteMemory([In] ulong address, [In] uint size, [In] IntPtr buffer, [ComAliasName("Debugger.Interop.CorDebug.ULONG_PTR")] out uint written); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] void ClearCurrentException([In] uint threadID); [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)] diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs index ee64abce02..90023d8469 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs @@ -91,6 +91,16 @@ namespace Debugger } } + /// + /// Gets the address in memory where this value is stored + /// + [Debugger.Tests.IgnoreAttribute] + public ulong Address { + get { + return corValue.Address; + } + } + /// Gets value indication whether the value is a reference /// Value types also return true if they are boxed public bool IsReference { diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/Autogenerated/ICorDebugProcess.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/Autogenerated/ICorDebugProcess.cs index fbd6c41fd9..000d7fd919 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/Autogenerated/ICorDebugProcess.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/Autogenerated/ICorDebugProcess.cs @@ -1,4 +1,4 @@ -// +// // // // @@ -237,10 +237,10 @@ namespace Debugger.Wrappers.CorDebug return read; } - public uint WriteMemory(ulong address, uint size, ref byte buffer) + public uint WriteMemory(ulong address, uint size, System.IntPtr buffer) { uint written; - this.WrappedObject.WriteMemory(address, size, ref buffer, out written); + this.WrappedObject.WriteMemory(address, size, buffer, out written); return written; } diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj index a848676e8b..93f58590fe 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj @@ -60,6 +60,7 @@ + diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/MemoryReadWrite.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/MemoryReadWrite.cs new file mode 100644 index 0000000000..40b78f4b20 --- /dev/null +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/MemoryReadWrite.cs @@ -0,0 +1,85 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace Debugger.Tests.TestPrograms +{ + public class MemoryReadWrite + { + public static void Main() + { + string hello = "Hello"; + string world = " !"; + System.Diagnostics.Debugger.Break(); + System.Diagnostics.Debug.WriteLine(hello + " " + world); + } + } +} + +#if TEST_CODE +namespace Debugger.Tests { + public partial class DebuggerTests + { + [NUnit.Framework.Test] + public void MemoryReadWrite() + { + StartTest("MemoryReadWrite.cs"); + + ulong addrHello = process.SelectedStackFrame.GetLocalVariableValue("hello").Address; + ulong addrWorld = process.SelectedStackFrame.GetLocalVariableValue("world").Address; + + addrHello = DeRef(process.ReadMemory(addrHello, 4)); + addrWorld = DeRef(process.ReadMemory(addrWorld, 4)); + + byte[] hello = process.ReadMemory(addrHello, 22); + byte[] world = process.ReadMemory(addrWorld, 24); + + ObjectDump("hello", ToHex(hello)); + ObjectDump("world", ToHex(world)); + + process.WriteMemory(addrWorld + 12, new byte[] {0x77, 0x0, 0x6F, 0x0, 0x72, 0x0, 0x6C, 0x0, 0x64, 0x0}); + + EndTest(); + } + + ulong DeRef(byte[] ptr) + { + return (ulong)(ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24)); + } + + string ToHex(byte[] buffer) + { + string hex = ""; + foreach(byte b in buffer) { + hex += b.ToString("X") + " "; + } + return hex; + } + } +} +#endif + +#if EXPECTED_OUTPUT + + + + + mscorlib.dll (No symbols) + MemoryReadWrite.exe (Has symbols) + System.dll (No symbols) + Break MemoryReadWrite.cs:18,4-18,40 + EC 8 33 79 6 0 0 0 5 0 0 0 48 0 65 0 6C 0 6C 0 6F 0 + EC 8 33 79 7 0 0 0 6 0 0 0 20 0 20 0 20 0 20 0 20 0 21 0 + System.Configuration.dll (No symbols) + System.Xml.dll (No symbols) + Hello world!\r\n + + + +#endif // EXPECTED_OUTPUT \ No newline at end of file From 9b16a1757d3ff313568fa65c87fc9b2085541918 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 4 Oct 2008 15:13:43 +0000 Subject: [PATCH 16/51] DebugOptions: EditRawProperty (=allow using MSBuild replacements) git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3586 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../ProjectOptions/AbstractBuildOptions.cs | 4 +++- .../OptionPanels/ProjectOptions/DebugOptions.cs | 12 ++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/AbstractBuildOptions.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/AbstractBuildOptions.cs index 5fef875377..8ea3a4b7ed 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/AbstractBuildOptions.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/AbstractBuildOptions.cs @@ -80,7 +80,9 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels Get("xmlDocumentation").Enabled = Get("xmlDocumentation").Checked; if (Get("xmlDocumentation").Checked) { if (Get("xmlDocumentation").Text.Length == 0) { - Get("xmlDocumentation").Text = Path.ChangeExtension(FileUtility.GetRelativePath(baseDirectory, project.OutputAssemblyFullPath), ".xml"); + Get("xmlDocumentation").Text = MSBuildInternals.Escape( + Path.ChangeExtension(FileUtility.GetRelativePath(baseDirectory, project.OutputAssemblyFullPath), + ".xml")); } } else { Get("xmlDocumentation").Text = ""; diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/DebugOptions.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/DebugOptions.cs index 7788b0a3ab..c14447fab1 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/DebugOptions.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/ProjectOptions/DebugOptions.cs @@ -19,9 +19,9 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels SetupFromXmlResource("ProjectOptions.DebugOptions.xfrm"); ConnectBrowseButton("startExternalProgramBrowseButton", "startExternalProgramTextBox", "${res:SharpDevelop.FileFilter.ExecutableFiles}|*.exe;*.com;*.pif;*.bat;*.cmd", - TextBoxEditMode.EditEvaluatedProperty); + TextBoxEditMode.EditRawProperty); ConnectBrowseFolder("workingDirectoryBrowseButton", "workingDirectoryTextBox", - TextBoxEditMode.EditEvaluatedProperty); + TextBoxEditMode.EditRawProperty); InitializeHelper(); @@ -35,20 +35,20 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels b.DefaultLocation = PropertyStorageLocations.ConfigurationSpecific; locationButton = b.CreateLocationButtonInPanel("startActionGroupBox"); - b = helper.BindString("startExternalProgramTextBox", "StartProgram", TextBoxEditMode.EditEvaluatedProperty); + b = helper.BindString("startExternalProgramTextBox", "StartProgram", TextBoxEditMode.EditRawProperty); b.DefaultLocation = PropertyStorageLocations.ConfigurationSpecific; b.RegisterLocationButton(locationButton); - b = helper.BindString("startBrowserInURLTextBox", "StartURL", TextBoxEditMode.EditEvaluatedProperty); + b = helper.BindString("startBrowserInURLTextBox", "StartURL", TextBoxEditMode.EditRawProperty); b.DefaultLocation = PropertyStorageLocations.ConfigurationSpecific; b.RegisterLocationButton(locationButton); Get("startExternalProgram").CheckedChanged += UpdateEnabledStates; Get("startBrowserInURL").CheckedChanged += UpdateEnabledStates; - b = helper.BindString("commandLineArgumentsTextBox", "StartArguments", TextBoxEditMode.EditEvaluatedProperty); + b = helper.BindString("commandLineArgumentsTextBox", "StartArguments", TextBoxEditMode.EditRawProperty); locationButton = b.CreateLocationButtonInPanel("startOptionsGroupBox"); - b = helper.BindString("workingDirectoryTextBox", "StartWorkingDirectory", TextBoxEditMode.EditEvaluatedProperty); + b = helper.BindString("workingDirectoryTextBox", "StartWorkingDirectory", TextBoxEditMode.EditRawProperty); b.RegisterLocationButton(locationButton); UpdateEnabledStates(this, EventArgs.Empty); From 0a42c419c3147cb88994345675689faaa0028246 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 4 Oct 2008 16:58:46 +0000 Subject: [PATCH 17/51] Add unit test that checks that SharpDevelop.exe, BuildWorker.exe and booc.exe all use the same value for the 32-bit-flag. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3588 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Main/Base/Test/CheckAssemblyFlags.cs | 63 +++++++++++++++++++ .../ICSharpCode.SharpDevelop.Tests.csproj | 1 + 2 files changed, 64 insertions(+) create mode 100644 src/Main/Base/Test/CheckAssemblyFlags.cs diff --git a/src/Main/Base/Test/CheckAssemblyFlags.cs b/src/Main/Base/Test/CheckAssemblyFlags.cs new file mode 100644 index 0000000000..8d56ae8e45 --- /dev/null +++ b/src/Main/Base/Test/CheckAssemblyFlags.cs @@ -0,0 +1,63 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.IO; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Util; +using NUnit.Framework; +using System.Text.RegularExpressions; + +namespace ICSharpCode.SharpDevelop.Tests +{ + [TestFixture] + public class CheckAssemblyFlags + { + string binPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ".."); + + bool Get32BitFlags(string assembly) + { + assembly = Path.Combine(binPath, assembly); + string corflags = FileUtility.GetSdkPath("corflags.exe"); + Assert.IsNotNull(corflags, "corflags.exe not found, this test requires the .NET SDK!"); + ProcessRunner pr = new ProcessRunner(); + Console.WriteLine(corflags + " " + assembly); + pr.Start(corflags, assembly); + if (!pr.WaitForExit(5000)) { + pr.Kill(); + throw new InvalidOperationException("Timeout running corflags"); + } else { + Console.WriteLine(pr.StandardOutput); + Match m = Regex.Match(pr.StandardOutput, @"32BIT\s*:\s*([01])"); + if (m.Success) { + return m.Groups[1].Value == "1"; + } else { + throw new InvalidOperationException("Invalid corflags output"); + } + } + } + + // All these processes must use the same value for 32-bit-flag: + [Test] + public void CheckSharpDevelop32Bit() + { + Assert.IsTrue(Get32BitFlags("SharpDevelop.exe")); + } + + [Test] + public void CheckBuildWorker32Bit() + { + Assert.IsTrue(Get32BitFlags("ICSharpCode.SharpDevelop.BuildWorker.exe")); + } + + [Test] + public void CheckBooCompiler32Bit() + { + Assert.IsTrue(Get32BitFlags(@"..\src\AddIns\BackendBindings\Boo\RequiredLibraries\booc.exe")); + } + } +} diff --git a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj index 6e183ebc54..bcf03b94aa 100644 --- a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj +++ b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj @@ -52,6 +52,7 @@ + From 9c88a25ccd56fd48ca9c557da530d69fca7fcbd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Sat, 4 Oct 2008 17:13:21 +0000 Subject: [PATCH 18/51] Some exceptions may not be interceptable in release code git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3589 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs index d9050458ec..ed0cfcb2fa 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs @@ -233,6 +233,9 @@ namespace Debugger return false; } throw; + } catch (ArgumentException) { + // May happen in release code with does not have any symbols + return false; } Process.AsyncContinue(DebuggeeStateAction.Keep); From 825952a177d25a4a6c03ab5dd44751b804212b44 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 5 Oct 2008 17:44:57 +0000 Subject: [PATCH 19/51] Fixed NullReferenceException for code completion on pointer variables. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3590 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs | 5 +++++ .../Project/Src/Implementations/PointerReturnType.cs | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) 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 2ad46c7620..edda2c2d1b 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs @@ -508,5 +508,10 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor Control IToolsHost.ToolsControl { get { return TextEditorSideBar.Instance; } } + + public override string ToString() + { + return "[" + GetType().Name + " " + this.PrimaryFileName + "]"; + } } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/PointerReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/PointerReturnType.cs index 6854548032..c6f81bf96d 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/PointerReturnType.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/PointerReturnType.cs @@ -41,6 +41,7 @@ namespace ICSharpCode.SharpDevelop.Dom { if (rt == null) return false; PointerReturnType prt = rt.CastToDecoratingReturnType(); + if (prt == null) return false; return baseType.Equals(prt.baseType); } @@ -71,12 +72,12 @@ namespace ICSharpCode.SharpDevelop.Dom public override List GetMethods() { - return base.GetMethods(); + return new List(); } public override List GetProperties() { - return base.GetProperties(); + return new List(); } public override IClass GetUnderlyingClass() From 1710bc93343255435bf2ca0dfbec94d621a28dbc Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 6 Oct 2008 15:44:58 +0000 Subject: [PATCH 20/51] Implemented Code Completion support of -> Operator git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3591 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/CSharpCompletionBinding.cs | 39 ++++++++++++++++++- .../AbstractCompletionDataProvider.cs | 2 +- .../Project/Src/CSharp/ExpressionFinder.cs | 7 ++-- .../Src/NRefactoryResolver/ResolveVisitor.cs | 12 ++++++ 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs index a24953710f..50302da7a4 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs @@ -95,6 +95,15 @@ namespace CSharpBinding } else if (ch == '.') { editor.ShowCompletionWindow(new CSharpCodeCompletionDataProvider(), ch); return true; + } else if (ch == '>') { + if (IsInComment(editor)) return false; + LineSegment segment = editor.Document.GetLineSegmentForOffset(editor.ActiveTextAreaControl.Caret.Offset); + TextWord sign = segment.GetWord(editor.ActiveTextAreaControl.Caret.Column - 1); + if (sign.Word == "-") { + editor.ShowCompletionWindow(new PointerArrowCompletionDataProvider(), ch); + + return true; + } } if (char.IsLetter(ch) && CodeCompletionOptions.CompleteWhenTyping) { @@ -108,7 +117,7 @@ namespace CSharpBinding ExpressionResult result = ef.FindExpression(editor.Text, cursor); LoggingService.Debug("CC: Beginning to type a word, result=" + result); if (result.Context != ExpressionContext.IdentifierExpected) { - editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(result.Context) { + editor.ShowCompletionWindow(new CtrlSpaceCompletionDataProvider(result.Context) { ShowTemplates = true, AllowCompleteExistingExpression = afterUnderscore }, '\0'); @@ -131,6 +140,34 @@ namespace CSharpBinding } } + class PointerArrowCompletionDataProvider : CodeCompletionDataProvider + { + protected override ResolveResult Resolve(ExpressionResult expressionResult, int caretLineNumber, int caretColumn, string fileName, string fileContent) + { + ResolveResult rr = base.Resolve(expressionResult, caretLineNumber, caretColumn, fileName, fileContent); + if (rr != null && rr.ResolvedType != null) { + PointerReturnType prt = rr.ResolvedType.CastToDecoratingReturnType(); + if (prt != null) + return new ResolveResult(rr.CallingClass, rr.CallingMember, prt.BaseType); + } + return null; + } + + protected override ExpressionResult GetExpression(ICSharpCode.TextEditor.TextArea textArea) + { + ICSharpCode.TextEditor.Document.IDocument document = textArea.Document; + IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(fileName); + if (expressionFinder == null) { + return new ExpressionResult(TextUtilities.GetExpressionBeforeOffset(textArea, textArea.Caret.Offset - 1)); + } else { + ExpressionResult res = expressionFinder.FindExpression(document.GetText(0, textArea.Caret.Offset - 1), textArea.Caret.Offset - 1); + if (overrideContext != null) + res.Context = overrideContext; + return res; + } + } + } + bool IsInComment(SharpDevelopTextAreaControl editor) { CSharpExpressionFinder ef = CreateExpressionFinder(editor.FileName); diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/AbstractCompletionDataProvider.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/AbstractCompletionDataProvider.cs index 3e089902eb..184282aa56 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/AbstractCompletionDataProvider.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/CompletionWindow/AbstractCompletionDataProvider.cs @@ -128,7 +128,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor return completionData.ToArray(); } - protected ExpressionResult GetExpression(TextArea textArea) + protected virtual ExpressionResult GetExpression(TextArea textArea) { IDocument document = textArea.Document; IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(fileName); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/ExpressionFinder.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/ExpressionFinder.cs index d557093489..3424fe1f5b 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/ExpressionFinder.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/ExpressionFinder.cs @@ -492,13 +492,14 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp // do not reset context - TrackCurrentContext will take care of this frame.lastExpressionStart = Location.Empty; break; + case Tokens.Pointer: case Tokens.Dot: case Tokens.DoubleColon: // let the current expression continue break; default: if (Tokens.IdentifierTokens[token.kind]) { - if (lastToken != Tokens.Dot && lastToken != Tokens.DoubleColon) { + if (lastToken != Tokens.Dot && lastToken != Tokens.DoubleColon && lastToken != Tokens.Pointer) { if (Tokens.ValidInsideTypeName[lastToken]) { frame.SetDefaultContext(); } @@ -821,7 +822,7 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp resultStartOffset = lastExpressionStartOffset; if (resultFrame.type == FrameType.Popped || lastExpressionStartOffset != resultStartOffset || - token.kind == Tokens.Dot || token.kind == Tokens.DoubleColon) + token.kind == Tokens.Dot || token.kind == Tokens.DoubleColon || token.kind == Tokens.Pointer) { // now we can change the context based on the next token @@ -865,7 +866,7 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp if (token.kind == Tokens.EOF) break; if (frame.parent == null) { - if (token.kind == Tokens.Dot || token.kind == Tokens.DoubleColon + if (token.kind == Tokens.Dot || token.kind == Tokens.DoubleColon || token.kind == Tokens.Pointer || token.kind == Tokens.OpenParenthesis || token.kind == Tokens.OpenSquareBracket) { lastValidPos = LocationToOffset(token.Location); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs index aaac809d46..e4bb5ffac2 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs @@ -522,6 +522,18 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver public override object VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) { + ResolveResult targetRR = Resolve(pointerReferenceExpression.TargetObject); + if (targetRR == null) + return null; + PointerReturnType type = targetRR.ResolvedType.CastToDecoratingReturnType(); + if (type != null) { + TypeResolveResult typeRR = targetRR as TypeResolveResult; + return resolver.ResolveMember(type.BaseType, pointerReferenceExpression.Identifier, + pointerReferenceExpression.TypeArguments, + NRefactoryResolver.IsInvoked(pointerReferenceExpression), + true, null + ); + } return null; } From 662e1cf6142ba01292cbb5a71739d7ea03120afb Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Wed, 8 Oct 2008 19:55:42 +0000 Subject: [PATCH 21/51] Added patch by Alex Prudkiy to fix sorting items in the combo box above the properties. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3592 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/Gui/Pads/PropertyPad/PropertyPad.cs | 44 +++++++- .../ICSharpCode.SharpDevelop.Tests.csproj | 3 + src/Main/Base/Test/PropertyPadSortingTests.cs | 106 ++++++++++++++++++ src/Main/Base/Test/Utils/MockComponent.cs | 47 ++++++++ src/Main/Base/Test/Utils/MockSite.cs | 48 ++++++++ 5 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 src/Main/Base/Test/PropertyPadSortingTests.cs create mode 100644 src/Main/Base/Test/Utils/MockComponent.cs create mode 100644 src/Main/Base/Test/Utils/MockSite.cs diff --git a/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs b/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs index c88fc7aa0c..d924724341 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs @@ -7,6 +7,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.Drawing; @@ -179,7 +180,7 @@ namespace ICSharpCode.SharpDevelop.Gui comboBox.Dock = DockStyle.Top; comboBox.DropDownStyle = ComboBoxStyle.DropDownList; comboBox.DrawMode = DrawMode.OwnerDrawFixed; - comboBox.Sorted = true; + comboBox.Sorted = false; comboBox.DrawItem += new DrawItemEventHandler(ComboBoxDrawItem); comboBox.MeasureItem += new MeasureItemEventHandler(ComboBoxMeasureItem); @@ -202,6 +203,45 @@ namespace ICSharpCode.SharpDevelop.Gui WorkbenchActiveContentChanged(null, null); } + /// + /// Returns a new collection of objects sorted by their ISite name otherwise by their type name. + /// + public static ICollection SortObjectsBySiteName(ICollection objects) + { + List unsortedObjects = new List(); + foreach (object o in objects) { + unsortedObjects.Add(o); + } + unsortedObjects.Sort(CompareObjectsBySiteName); + return unsortedObjects.ToArray(); + } + + /// + /// Compares two objects by their ISite name, otherwise by their type name. + /// + static int CompareObjectsBySiteName(object x, object y) + { + return String.Compare(GetObjectSiteName(x), GetObjectSiteName(y)); + } + + /// + /// Gets the site name otherwise the name of the type. + /// + static string GetObjectSiteName(object o) + { + if(o != null) { + IComponent component = o as IComponent; + if (component != null) { + ISite site = component.Site; + if (site != null) { + return site.Name; + } + } + return o.GetType().ToString(); + } + return String.Empty; + } + void SolutionClosedEvent(object sender, EventArgs e) { SetDesignableObjects(null); @@ -368,7 +408,7 @@ namespace ICSharpCode.SharpDevelop.Gui try { comboBox.Items.Clear(); if (coll != null) { - foreach (object obj in coll) { + foreach (object obj in SortObjectsBySiteName(coll)) { comboBox.Items.Add(obj); } } diff --git a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj index bcf03b94aa..cdc4b7bf1a 100644 --- a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj +++ b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj @@ -62,6 +62,7 @@ + @@ -75,11 +76,13 @@ + + diff --git a/src/Main/Base/Test/PropertyPadSortingTests.cs b/src/Main/Base/Test/PropertyPadSortingTests.cs new file mode 100644 index 0000000000..055cec8028 --- /dev/null +++ b/src/Main/Base/Test/PropertyPadSortingTests.cs @@ -0,0 +1,106 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Tests.Utils; +using NUnit.Framework; + +namespace ICSharpCode.SharpDevelop.Tests +{ + /// + /// Tests the PropertyPad's SortObjectsBySiteName method. + /// + [TestFixture] + public class PropertyPadSortingTests + { + [Test] + public void SimpleTypeNameSort() + { + string a = String.Empty; + int b = 0; + + object[] unsortedObjects = new object[] {a, b}; + object[] expectedSortedObjects = new object[] {b, a}; + + Assert.AreEqual(expectedSortedObjects, PropertyPad.SortObjectsBySiteName(unsortedObjects)); + } + + [Test] + public void FirstObjectIsNull() + { + string a = String.Empty; + object b = null; + + object[] unsortedObjects = new object[] {a, b}; + object[] expectedSortedObjects = new object[] {b, a}; + + Assert.AreEqual(expectedSortedObjects, PropertyPad.SortObjectsBySiteName(unsortedObjects)); + } + + [Test] + public void SortedBySite() + { + + MockSite site1 = new MockSite(); + site1.Name = "b"; + MockSite site2 = new MockSite(); + site2.Name = "a"; + MockSite site3 = new MockSite(); + site3.Name = "z"; + + MockComponent c1 = new MockComponent(); + c1.Site = site1; + MockComponent c2 = new MockComponent(); + c2.Site = site2; + MockComponent c3 = new MockComponent(); + c3.Site = site3; + + object[] unsortedObjects = new object[] {c1, c2, c3}; + object[] expectedSortedObjects = new object[] {c2, c1, c3}; + + Assert.AreEqual(expectedSortedObjects, PropertyPad.SortObjectsBySiteName(unsortedObjects)); + } + + [Test] + public void OneSiteIsNull() + { + MockSite site1 = new MockSite(); + site1.Name = "z"; + + MockComponent c1 = new MockComponent(); + c1.Site = site1; + MockComponent c2 = new MockComponent(); + + object[] unsortedObjects = new object[] {c1, c2}; + object[] expectedSortedObjects = new object[] {c2, c1}; + + Assert.AreEqual(expectedSortedObjects, PropertyPad.SortObjectsBySiteName(unsortedObjects)); + } + + [Test] + public void OneSiteNameIsNull() + { + MockSite site1 = new MockSite(); + site1.Name = "z"; + MockSite site2 = new MockSite(); + site2.Name = null; + + MockComponent c1 = new MockComponent(); + c1.Site = site1; + MockComponent c2 = new MockComponent(); + c2.Site = site2; + + object[] unsortedObjects = new object[] {c1, c2}; + object[] expectedSortedObjects = new object[] {c2, c1}; + + Assert.AreEqual(expectedSortedObjects, PropertyPad.SortObjectsBySiteName(unsortedObjects)); + } + + } +} diff --git a/src/Main/Base/Test/Utils/MockComponent.cs b/src/Main/Base/Test/Utils/MockComponent.cs new file mode 100644 index 0000000000..90dec16de4 --- /dev/null +++ b/src/Main/Base/Test/Utils/MockComponent.cs @@ -0,0 +1,47 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.ComponentModel; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + public class MockComponent : IComponent + { + ISite site; + + public MockComponent() + { + } + + public override string ToString() + { + if (site != null) { + return site.Name; + } + return base.ToString(); + } + + public event EventHandler Disposed; + + public ISite Site { + get { return site; } + set { site = value; } + } + + public void Dispose() + { + } + + protected virtual void OnDisposed(EventArgs e) + { + if (Disposed != null) { + Disposed(this, e); + } + } + } +} diff --git a/src/Main/Base/Test/Utils/MockSite.cs b/src/Main/Base/Test/Utils/MockSite.cs new file mode 100644 index 0000000000..d6bd70db1e --- /dev/null +++ b/src/Main/Base/Test/Utils/MockSite.cs @@ -0,0 +1,48 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.ComponentModel; + +namespace ICSharpCode.SharpDevelop.Tests.Utils +{ + public class MockSite : ISite + { + string name = String.Empty; + + public MockSite() + { + } + + public override string ToString() + { + return name; + } + + public IComponent Component { + get { return null; } + } + + public IContainer Container { + get { return null; } + } + + public bool DesignMode { + get { return false; } + } + + public string Name { + get { return name; } + set { name = value; } + } + + public object GetService(Type serviceType) + { + return null; + } + } +} From 557e32206512783e00941d7a22a74c0b91a78ec8 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sat, 11 Oct 2008 12:12:37 +0000 Subject: [PATCH 22/51] Added show caret line option to Markers and Rulers options panel. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3593 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- data/resources/StringResources.de.resources | Bin 308885 -> 309206 bytes .../resources/StringResources.es-mx.resources | Bin 328959 -> 329671 bytes data/resources/StringResources.es.resources | Bin 329030 -> 329742 bytes data/resources/StringResources.nl.resources | Bin 323617 -> 324295 bytes .../Resources/MarkersTextEditorPanel.xfrm | 95 +++++++++--------- .../OptionPanels/MarkersTextEditorPanel.cs | 2 + .../Resources/StringResources.resources | Bin 315437 -> 315903 bytes 7 files changed, 52 insertions(+), 45 deletions(-) diff --git a/data/resources/StringResources.de.resources b/data/resources/StringResources.de.resources index 80a014e1fb266aec626c3ca0d1b8e5f0470e9474..81950a129437d62a26944ba6ddf1184c1d2b85e2 100644 GIT binary patch delta 20186 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

    QAY6n3sCUqojN)}9- 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 Q$}^Em-hQQ{*`B8V2M0M&x&QzG delta 19770 zcmZ{L30#g@`~P*$=}wYVlBAN5BuSEllt_|F)-fncwn;)`8)O;7*v&(i8T**A@7Z@_ z-?NN;3u9l0u`j>x{oHLc@BjbKCv~oKo$Xq_*Y}*~dCxy{nEAwE+CuTix?inj)>_%h zGRvxHlE_N2-l9~?VfI-SY;$bYk@K^%l-r*o>#F->i;Oerl3t$?GDcmq1DEtH}S9p!l~$ZC^_I_PnIBe-b5~BI@TPsPA||)q4}A3rSNQ z71h2cDa?~-n=R3_a)K((!+d{9sys;0%ikn9=14l6Br~YKqohvlB)!@uslG|l-fKkb zi%Xg@L(t}-M29>CC4a4G_E(CEbrUpgAW?ly(9nsJ{-`Hu^m0KHQ=vDXXk>duv&s|M z92fL%7t!d&L=#IWDv9|o78i698(7&)(2Vwyx>O~aQQl6_j-it7^bk~Oi=>}COy?_l z1&AJs`a}zwT2@g%7^ob^On?y@*%P&&K-96Bq95){+APWP3v!uU@3QE66G~$+|Z{7>K8l-4RcSYy$GZa7WMHFejNP65|kYy1`bE_%J zZl_56BdPZVNhRF`{rXu_Vgp4dzLhk8HqnEZz#3dr3=SmOdUt`y3Rt{7KOHCq${XimHwyYTQuKlZS#r%PYF) ztmym{9J_&_=uwi+j1koIsiaU(LCc2`?O7n{P*+K9@w?S&qN$@L4VfY7V_g+T7dJ{e z5iM!|UO}B(5cR|D5{2^w~Yj4AHZHN6753BV&YLkhatR>w<+|~b0(7Gr= zOF|@tz}-2^B|UsZH1x8d6R!o;NR@Q@G2;EHpnFS*948<&VkK2@Q4~G_u~{Ey8bfq3 z5H`6fDcV+=A}ZTwgmqOEA4?PytjIM|(t+uMp0pKo3|pSphUhTzqaoI}g)at8fo~=f zohbubCn*|yo@g`twFmhWbVQQXBuR2O{5wd}r9UOzSRg28o}_{Eh&+*7E(wBubQd(h zU(wV=Nt+T>292wP9QYcISV0eu5Z!O7Xj>DaiWUftYD81~i7K$9b2)-$c`Mp_5R>;I zy82PlBv(aUo=9r_tssAQqU(=|-oxJU2r?T71jQ~%SKh#Hor$Om(aXz{f`y`A5i~j7 zh&s=Sm(**pq>=vc`j14f;PHUwf<~-^^*$mw5JBrd5q$@12H=#Loh7{qK%^sC`oTkQ ztORYZO!QB@prdnPfqSN3y*(|jcqls9*L2i7Bvu6~8WN_cZU|9=y`+o?qE6Y8nm;Al z4lH?Qq3G)jqG!bf+3uAzv@21GoUJ4ru$f{h=U5~_GvUx-)awTNhb z8`J12UI`^0OY%QN6#Na59U@|8f~0ZtfkZgG-wmQk^#L9o5Gjc4IZi~Uj=>1X#9pTm z%yE)_d;st{DX2jiNwX>uwYy__U&XIh!{d^y?FAheOB9Oae2WB@z$L3QMA0^imM%e1 zjReFj}7Zh<4 zupCU3JPvSDThjCm2JBdj(Q1w@o2x`czAMo4}7 zS6()6xe$F1Bkr6C2RI=b#%G`|X-Ir~MOQaT8nzR;1jRm8 z0N$38Rs-8!TOvU3B2O#@+4u^Y5C2|1EvYIN=pPDzLd_T+AZdz?q#X#Q&!}TXYQq~P zBsoV58W||4CJr^Ro1|S*()Lx7{si!RgH7GafD0!yR}|Y2W?LbtXeUYG6$I5Ui-2pY zXxJe^3F(6DH=`>24zt}Ry7^hq@lZh@U!YL+BkG1Qsf&#dDGk%U74#HwUk&jao+fEt zhM*PGP%Ht&@z~gfV?^U45e3NYqfHcLr0fv%yECdKOx^V;a%npJ-CxkC?})1SN$P;A zJEI?B5$Sh1SyC*}|BsHCAet!94W$UOCMa``dbvZqUv7yK2|8R)n08kyno&AjkyBksD;C2o&d397u8xzW$mg*7P(gnoCfnlY zIVjAD⁡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 diff --git a/data/resources/StringResources.es.resources b/data/resources/StringResources.es.resources index 9b3542cbbd390564d5a2e752aab40732f1ac7f2d..9f3b97e63b8b2a1182de9018d6c3c93390dbe362 100644 GIT binary patch delta 24943 zcmZvE2Urxz^L9-)gNO)-h=_=Yiin7Sm{1WFvj~{8BBG)Qh?oPWGv`&xoIUl-dY)Op zoO8}Op6Sey@12E|b=rEtdZCnE{O*_%Z0l^@VLRP!Yh$;&iahgq%GNUO71WgE;ez_O z6P=kYsOe*cK5P_JIzQ3OhD1%jDx@q?Xx$iv?Ee(hsEMF^ttCyquh42sg;EMiD*IK? z=i5ZpuMr(9q0pjv3jIhTI_oH?Scs(8){;IrNE+lp^v;&(X<3DuZBnRwZb_}jD<1UY zh@g`elID*P)W%ED{sDr1-V!u>o1jAf5-m3=p7~RbjFONS|`!YoT zmQ!fwd_nsLDm1=;q;fX|-E1uB1;(Actx%Ojg$_Sbnoz!G7|@;Qk3&S=mSZ7DqUc$Y z>a|m-SUpMc(BBt)zZ@oLSUw^z6H(egNx?Rf>{ko2e?#QoNYV)+T4=iGSukbPZ9!#v zO3I8^C_IK}?R7y78$*-M3Z48wRMAq>k-UO}yGqK9l`7)zrb$xbIfX3CNwV83=KRo?lE*hey~-$bsko#b_lYv%Bppu`G;}4=VJtsfA*yj!Nuir(6!Nws zsxnDX!72(>m_qcVqo9BC!j!udY7Wy+v=dY!6kCgyRAnhl3!$!`6Le-2bk{`En4*#_ z?ke;rTcHz357%Yw>wg41@8biRc`*PjYXeT>~*5)>Is1pD5XkILEGxUo(m8Stp#~Z zChAa;=!cZl%|p<*+=31rQK(5vsILamvgr`28Bw!4L>pox4U2+DE?4MC4}}Uem$a)r zQDhrQ7i+*zFjwO8-U*9e0N+SS#~KlhC@83{ zFVO^lqO!XXZyyx855W#R6SS&7k)4MmxB8M?@*xJtrYIEa1~30c^a1uc2hZ*5uF!yc z5TXcd+mq-t{?`74H+xFD1V`K0o2XZspl)-qllp>6&LnEQQjkqYg?3=4<1Y#dv=`KR zI+3-FLKmRsju0#w_!T=6@X{GRfw=rwohUqCL51Fz0`NsCbTM5}y0vMzx0_S*WXua^ zEk9k*%%(&I5bMpWnYMWQHtmfiW1=M8fP1A^C5kU8sCYdhr}u(Z!sq+uku=U*Qt9zT z^;{HkekiDZ9MP>rqJ)})f+k=!h`h}W?hG+s*_r~%c&1btE=jH@QpQL!!PXaQ2yzM} zsCfqN`4H_K#lIRt% zC9x|}7$WMD6VbI-h^{{{*MEY%5(GW^uF${t;0Nu>3OZMk$R6JNpteF&2PxD$M4`mL zU`q>yEP$0$)&Sb72zoX`p%$1d+Eby%uLX4}s*q_aQDK0~{4zx80HRtgF*(9FAW+hk zoeG`%2dQJZAgF`dtc9-Nh<9^A4-*8n+XXQ1gV^0$NTEhUiN^WEu}lit0qHn^s1BTS z$P55dML~R>Xi}^~UR@-O+@O#xE98C^iVwp0HLzP#LG!O5DsBqeqG3XPg~}mxSCqyd z%=|qG2-^jD2+sa8HzFZFkwZ#Bs1Ba)vreJCMG&u*C3&7AIt6u?97t3Un2--Z^dOdK zWPV8_pn<0U0tp2|4&XKXhC=--Ds-kW(Lq>!9m3jiCD0V=?NMH#`hh@FL`e#~W2`K*JiMN(P|_;+zZodLDYN=owk188@XXbloo zMSDrxfPe}l%Rd>szJd-Qm+W5wja`N*hDqALN6`I7fNf}}BTVq`LWNq_lJw>;L6gf! zY7vwo>G3sq>|H@u8w=VF4O}jST>;-eTEe#0NIV6A*Fg#`hSSXaAjk>}Yyo1b4lq+g zL4UamvU>+1k^DQ=QD_MS{;w@^LoJ2;u(^(7;0sPb)3b173up^M6-NI4cQ7y|r2|sz zX=MFjg68@wG`qAyr3Og4dR?K>*zK!yILuK&b^b&6ISBeQ9QGuI$_z#(e?a64N2>$j zXO}_Z%7Y>bPSy?46g)%FsTs&0%M@w{#MpxL{P!iIF0B+g3&8T}2ar3BA}YfNPzjZX zTqOFm6;1)P3Lir>sIH(YYlvpd6m%4*wf+wv+f_jeP%q4nAZjoX`5$n43%gr`Xz7o? zn=`RUHwgH*plN{j`S77r^923tikf1Jpo}31+m1vLg%!%(8PU@S@gIAH$a%d&gW@H% zY$53S4uvwEQ6xah7T%}_d;o`zC}XB5R5X<6^>geLfAu#3*OL^g_65+ITcH_<_czA? zPI&=ZnSw4OTJ}T8#whzf?-O+FI8ph72th>6mct4KwL^5ZK~kwglIGyA-&lBQJ3(R7 zU~?yhoGJ zBhX(TS`w0yV-(7Z8ltcTk?137JCf9mJJ{$>qQI2fu*C=<67r&iFPwpw&uvNcPccb< zBE&{2lIm1|e*m8Q!DbC=N}A9Cl@Th=dH({CgrF6F3i8HopL`~|`j6t*{l_WX%0;3KvWF=@cmCRJ@L=mb9%6(&K{DI5G5{%%6@~8{TiU`M$YgH zh31tq`&BAaX5-jJu6!8ccgCRG~2lj-9tq_zV^FM`KCTLIj1k zl++fuc4V@tV}M)Ao)>}|Y=pky0K2Lp)#70%>h_S-5sq^kC2=*_ z@)I2G?MuL3(aj3AgzgFgUk9kjLY)*^58dy9>zv@ekPWO(SaaG5J&I3A_V%Frk3|?S_m<|z9M3IFH!%OINrb}ao#8zKciFwz$Ad) z`YkftEuy)wQ}T5|OAwBaj|-X;jZkzY$_psohNFxHYQ~ncO_qUfEmt7&qOBBauu7qE z5IH}5*eVH$6dAj6N34#Bf3%h8F7(>~ew>y|p+ip)vAK}#Q&EtQ64avrs+nR)AH5K0 zi1dVqron+ODVN~Z(UozSKmqg$s&+!Y-rfxeRzuQ%^#px;gYxQ%LQmu1IY@aW;bE(6 zCH;J&P}*)Bvfzm=szM>*I2)mAS!aj5Kb)w8(Q;LzUvMt!L)CzJ5T*4{*>4yx=(GuyUJUBoqB!*-f`|1%_0Sxlh6vyM8u&H|Z`4Bsg&?@Q!+A&H+=r~^g>-x?H%u3$P!Yg#3bNXd z3ktbal@!(hxx!bWKtT1%WvKH2G@tS5cL2pKcC~I601We81b~^Q2zn7EOVK75xEQLI zz8eu)5vX=H;&9&t1OG#cMa5$SI94o8iz+##SY<-#i1gdla4;Sy=pwxKMjIGvl0vPJ zqkaM*W*)>*vL;;QG11m(h zqm=XpG>z^j$h8ux?WGE(1M+*$g2Er=6%!5!b0C+iKje-VoxfHN8AMQ67Mb7Oggg=U*dI6FeJ_RIK zM&VQxMN$f4ARSdY{=P&jR1a_v1UTMii?o3(z3ny1gQh61iW42Ej-o3RkaJm~1u%$j zL!=25)nl6hS6eBx$K+q7aPW^^f+_k(WLxZxx)iD-8+ zTn}bjji9bj8};ycg@P~RAO(|`iI%j`lc@cD6l_4pV}%uZ10X(Ji>QnbbOYaaD~}rY zEYi)X0MqdxPuq!gu(7o$=z#rSUYLFcIk`B(ZNnx2TWU(`45Mvw6*MtUlK%&jZ&jz1 zVPk+30KmpxxTV71ws;&|p)M5>KsXl8cah`(5B9<5Po&t1KOxXZKcgEss0N=mBvHF%G8jEz*vpG`82uVFx3F^8Q4vKS(zn`EhIJe9zDSJ`aPC>U( zM}BPuuSYa~g4h53Nl>ne@JgV~uGMgkJV5QXC<*hyar}s?BFyWeR^7Z(Q2%FeJlNW= zyPyf9p-xOZr!|h5b~q{mQZnZfwd#&MS=;1W&B=N`)pbKsVID7o^P zUR85*@jNG}C`yuQ*vT$8RN}}8$MzG2mNI!(_e|*pZ6APm6>#2H5hG=qAe4cT7au}& zh}eD}?nmkn&1ov=1QNqmWP&O1hg7)s5+v>T4LCQ!FY7=-Ydb3BI21?XB9evz<7}a1 z@2$8Y&bj#XYoi$^TJW10{~iH6I7rbeE$p4)XG2rffLLI zg*>6@0WaW|z(R{9xHLj-`2blZV-#dB1QPH$Wj*kE5ihfoG0 zbS{llDCBSG71@gR;ud!x5Uh|OxkVwiBq|h*5^ z6E3g+#tkQO@1>qNew8EY{ufG;(KtaP1MPYQb<8$>4RK2e1~#;WKqc0|Rk4ZNC_=5@ zDD*W|(%08W-<@&NL#jAg0(fx?z_l8_Hwezq2^&qrAq&;zO)umF6ra_4B6Y*4<)PWS zC}7jzB&S;78VRC>tj5(P%9iIF1ogE%sP8+Py)&Y1vPzdo1ptEj=o7^W5 z-WJ!+*xb}5I9$U@@A~6TurV?+4ib-R;=U^~1z(`RayalNXCPq15P)F334HR$pb41h zM>Du;HQ-l!+}Oa^7T$+YHE@dPh$3eY+}{&N%Hg=AZ3KfL*{+A#58eacI)$F)#%%%o z=43(4Zw27kj>LNg2l^+lWfagmK$Bwm9yu(gFDpvJ*1mc4WSGJ8;(l%a%mu9JdU>hxpzE`2LAvXWUFl zH30RCQA>1yj~zzMZ3j>A99#vLUL$ek8H3w?AoH-QI5(lJI)`A+3p|-H46rxQ6kOXo z#U==aAF8pT{ZM_r($<5^EI{H18eW1tD^J5E0N@raaf`eSvH%rrj|f@}WNd}c$wQIR zA0R!UzE1m!N)vEabgQ6QcLb%Ocqq_ap$*eoJ=CD#As<{1Fyn&>@a${2&xc*p=gxm~4RR_1q$bXFrqXc-VP)~r{fd?k< zP+#%tqp5AEM~dwk*whP`APAV}ixk=oaqIaI)n5i@L~${d~La9sgkDL)>Vf%(1z);>X!hy5faSU?R) zh>~15;toMr4NR1@tT!+jWyQ>VxID9fnD!Vn0tbOpNTxrCAP21|k3~@dcSVE@Er5)% z57z~k5XHd9&hOv@|6!}}6|1p=n%KiG_#FNjPvH<5W5#2?)420Qi0<}=eTw0-rY{nN zl{ZdqzPLL;?#P8a(h`4L9$~SW$T3K5;RwxC809J)a=yFi&pK{F&8y%n5BpCZ0#pfw zV&sng>J@GTshOvI!+BeuxiadfcBxlY&%Jn zfF!v~3#zshH>!W(ItF6)h5kbKW4l0=2;}~mK$)bYh&8zPu7Y^Th;(tUk*Q-{r<5%t zk-Nj-iNJBuiwBxL&9cLy)nmDl`g_w0jlud>@=e zVB#Ur4ya6J&ZG0rb5#j;UWk1=I0Ou1YBWIXMk4)8Wx#t&CdUokig7p>UqDEQRo<^X5_-2Ea7{e*^#e#X(D6#QhHLM3`bh})>f zV8X%mB-tv6x<{x|E6&#V^hCJ)gIw9igi{-eF#kS? zdkok)Lr}%hM5S(;rq**2z0aBcs^^w65|t&v)sr)cR>QD`QHeJ1fb-gMxG^$zY<*m2 zUBGGASE0f$abwd1&s-ykMkB*7M)hFR5ckPfh}L1*nszw;pe}cshY}_k8Tt*jZv~H< zqtKNpD11?JO{#+8GY_g?q|nwys2n{VkJO%m=xvXy4Y<$e{)pa&C{e}|h15bVi283= z5A1y%%G>j%{`GyEs<6)%1otk;UDO9jqmraMK#;m)Bt5K;+al=74URe+)%KxdR9H=Y~6Fr313Rq#=s0dyb#YqO%ZQMnn;cpdsR2G=|4#Cu1p+7LsraQP7glF5r zeY{ZyPPvMz_aj_z37!E1O`6pLvK)oW>;fv+hkusssnA9&bOs4?-BXk#r*Y$W5zovI z;HGW5Ler4TZID{RfR2SWpdvyb21AHZKzEZXF2h=)E{#PdK$Z|E@d^MC;zBTjXyYf$I}~?WJCQl=p~NU*n$gg8w12~K{tcDw{td;mTFO|yH(r$E8&iZw z?k1E#P4Sn&{+6PE>CHrE@pe1k9xnp)evX?Ws)@rpc;r2$FfW-bD)Wyi!djI(A(}Bw z)v2PnD6*4hOcldK;7+!mCSueEzxw^Ai(33*ns5;9cXCa8p-oyn^~K7ayy;;MN&w%Q0mdCW zIchm(Dlt>|iKFIGZ^j8H9ye1o6c5a!&dwFCY;6*?gyk+xc7L{KVa?NK2`lc|M%eSH z^}>O-nuN1(*u^6!K_S@;ruYGtrqxYtICLd=D$EkDqSY?$(+D$ST6b-d_F~*FLp)G| zx$bP?E+Thx;sj$MFRqm;TtvcdUit}J(0M8|G@_G7{SVoRPo)Zbv2eGcf-G(iu_fn> z+ZZz*+^y+xfH=FG@4d~MdHEdSByQ}^-li8j&J`uZ!`(R~G(m9j1EW<~2rIM|dG;9Q zLL-E&=R<)D=Ru0XdyIMR&J&GAr9Igq={z<(dp>LswujGkH|7auiv`eO2T)kF;WrDQ zLWn>{{Zneb7Y z{nmEk=gVNJsJ%wG>C0AGj){is)qFZiEYI2VP3zgSH-`XiSBOAyVJ}DShe#2tgd?Y| z5KY9(z3i@SBa7l`O5b8Fe(W{0ty34Tgm8AKGFtQIHNuC{_RzT0qM(Hsv>ks!jsE-i z&W)_OKyeqf_wkYgS(MzXgtzGYiziS`#01rh3AU{g_Ucr$gY>q^{i+3jT_vo={Czy) zNY)e;R*Q=2T5vTtMlDz^yu`tMMxccJCHy$q9Z^?&jqniX%>%Q^)_w6jFp9d+<9){N z^qwzkAl0{hhPQ*#QIt&MNEbM$-u>b)DBU;BP?An*vQ{{%mDBLnl_o=d-nbT0hUVn3 zTnA-DrWp~UkLkWnR1|G6ucrJrTZ9Y$yIy$m*L9Gydm7*E1s}>H`)cSCpeA93iCk>G zh+>xw5OHCep@%FsPt&G3*6Lnxjn%l?aPE!5SDZ*QHUchB9=uUh7PrlEWKlf1@Fv95 zzrTdh8EyEA3aXT3Q z_>FNpw723n%0JM;@EySaygR_1o?*7Id0M^CSKQ0c&qywkH79_?U;9|!O zj=Eye0Z#du#XfAWuo554Q!d#nDyzytJkm18qFsU$N=a)jwhw`q_h9xq9z1p*K(YpS zyJWB9!MFAaZ?y%8{c{jQ(?qZsa4=f}4^B&i4i+9X_67kx*gai%sSh#GTOVlZ`omFm zIi$gjzKNOXP=?nb-j^<_t4%?#tI>lvCVv%q9M=QFPzmoXvb^qVE(XQ_^EHu?r5}o9Kf`; zC=AW*6I$B~?OIxYMccmAScjSzq^FvP`OJ4L~5(|zR`~Nk;l{0Xp_Gh8$1DGXFo23cwJ_{^-tdFV0Z_Wu{4ml?*RRw1b zog+{qR#t7$)@9b)wNyv6hiWtE?fSy!7~i=gDstj^Tl-`@C4hCpR zGP}?IxY@x*bK^_UWB}SLG~Utt{1RY2^f=pI7Sl!RoJ=Y{V^8cOEBs_$?7Ds+}~}*N7Z^8xz*Y z^+PqjcN>SJh?5#NSK##9@TFEK`Sxv`e|n-{59{)L_aS_K?i~>-`k&McJVxDv&Vk(L z9uzVE4y37ZS2)-;hsBaLi_mR!>rwD)tc}jY&F`U-&OFKS_e3Azev0qi6Mfa-Q<@t= zln7pP9|+e1?Kq=7{{bA|>M-;*0K|dWL@zP%l@4)kqh0D;SathH(#J@zXgN zeu6=H#eJT^Il~{p9yX_SeWX5tvR6C;&K5n*>5oJQQRcK3N^R7-INi2p;!4t|D`>M%G$*#Ef*QD5O}lJ>O;TRlhe`EZ(jpNm0iW!%W>^axHrg{>|;qZu$# zJkmcKFkXhS60gq~e(>fc{NU>uGY-5&Y$yMV4XI~yP#%Dyx}DWf1*_HKke7h|N@tB- z`MpG{+xZef5|WeR_6n2+XEn6}d0t}YeO@6QMPim}T3`im`YY6&-Orkx>kZ11ysr^b z$!85;1SZ*Vx<>B&8Y-KhPadsq#srPc6THE!-f!ToCqazJCOTWygrCLH)w7(k8#Te* zi!dW*@=zaV4ff{dyA}I_E#Z?fG$2Qw`wEWA29}q5rU@x?5>1|w;$I@WTT{(+Xna_NLo@?rDJ^fmILgsCRcCewX zsh_Y&)ANRKXatJ3zZx!_>odGO`n=}lrMdBEcxBvqPW&t))d84eFcy`i+Qu?@e*`F zbLB98@(o^VaY3_3I6wO)9PvcI8@XK2^s6tA=R3BdlFrawt(8sB9|27y;g}w)qgMnv z`Wpkf*2gu@e?I_=9rQJNi=h{^vMo$3yuhb_iYn?(FbDIwpMdqiOoY|(3mSfu=Ched z*5fi^&#M;F7nqjavitHpa*E$mdD`M_I^f!u1j_wvgc>;1a*Fkd4Fu z{j(CEeWFuoagsb9ipqLj4bY-PkUV^y6!}WkvDrGUv0F&D4UpOm1$_ z=UU4WqSzHqvxXu9uCPrWnIM{8;Wq_kb-puASaNzE=^}<-VfWuCHol~lJBc(1ZhhxR#$n6bJlvpZKajy zmxGcw4EEG2s!14(6P%3jdrNk4&nuiq_vvZvq!6Taa*!VC(rb9p zl+Wdt4fEx^7&`=VqE6=f4$@P-fp$})y&*sLm+v}9<(IvL*L6OfU$#>sxoANd%smT8 zZ_C*0I8Ep}3epHZ{L@kTSS|!L^%u3hrPU48h&c!{fJ$&=Va&4JNjj===LLGfpGrk})oUSmv(~#Io{45q!atQ zL567{HqPes6$ftfEjQU$eFScSP&bJ6gW(TugdtM0<4)+CfG;&0RVuNA&@wY1^#WcD%5(GA_@q-C?D)EWjg* zODC>TOuC8(ceq0_Szi5+HQt-kiUD!OT|QS#HW0b)at-gS5%oNPs)g@zl!vUL7Qd@) zT$f-`M`6R)JYdhzyX;p&mSMkWVZm<2rKO0^F@b5*2n%je9J&~Q!Dew&iz9eO{%VIu zAfZjY%XVI}U}_2JE0*bVR#10S(5~ZZO7^P2Jke8H__T0M^ zP&^$|1*MjfC3sUQ>7;yPTQ6CeGfN>=c;DAlP)F@>A3ujPSiGdQ7=K^WFy`=r$MSt` zGv*1Oc)>b<-q$Q#Ph7aq4NJ=~^(IC)=djY!myef*`+h>ZzR@o3jX-vIpxL*!>ia+o z81Q-VMsI{&^#|I_1-O&8BT)uAY4$*q$4seR24lND;7(-_*eMTqQyE!LosT&}xTX(6 z#l=T@hzk!m*aunS5$H|1W;w_(qO5e}t3Jp>77w)u&LVo*WR)3x$?hSCmj%>&JmmDU zh>vREY@f~P!FqtV1o79L)_l$v0(E()2~>;|%OZ7pm4ndzA98Rxz~j(|{I-HD&$r9L zxA#Bf$WU2??EpD9Yw>Hp4;?)zWB(8Ut>Y#}?~6HnvtW5X|k-Sy}JQ z+k|QYM3N~1q*@05sz8()Qy%Bo{i{HzZEsFW^$Kvy3%}NwTmfr5F>|CXcn9#Q2!d0>9>mb51+HyLva~@#W(5fga z-aplLT7=!Jz^^i@BFrqGWmBBlz8Xe5J=6VJ8@*|c;%=`MHNEj)6pYZ7e4g=)YRH#0 zz}41Rqg-`lkM?Mr*F@WjpH&CGB!LKr*QUxMdZ=STY@UPIFc^z2`ZZm64Gdo%jI_23 z#0Y~^CyE;I$urN4?StYhZa>p>Qh^uMK+X308J7!@ZMaAXLc{X8)`%75o@=hF@7S5o zgkXZ!&v}WaKdoWY41N^_@Jyx!&pEiJ9H8EOp1tV5HGxclFLF%q@UvoX)t9tmN81;g z998)1LdBM+?@}z)#21>u-qw~C`Ccs)LgUa5*4n}94t$N!zw(6IaNPqha%g>6Z4@JS zYr{OxUhu2hGD>{V=MEF4|J6iop*H?kn@M-5A9aAZCF(%AeL%#yQu8vM*u4&1Z#al% z*VBmy>mV!^|7&ak6kl}*IB-bJ9@e%l+$aOY_#DKgb!Dh}62zb!M8|rF%UmzBS6xyM z>7hkE>7&~IMhq4{FZpgg$lU<+fyNAA_Tr)SWkq!wh;0p`UjrGOs}eo^jS?a{ywXCj z2+)LXDC6Uw~LQ z2eHOV0AKsYaBjc<{%69*Pplqi?x!tV`>Im?A8f>eh=&+Iy?7hj`n-B z;S?Co>zku`vHQRqI~${&`QPSHnCl1Kpc)4%a|<5U2KKMs0zCofG0%k_do>hoq+d<6 z#FnV>+hmP2+I+u-^b%b@7~+A$fvdEH!AF{x1jSRN{%W}JDa;~Pec)HkAdx;Gyp^=U zt$>#GHOnW_zW?cUR&QWc*h!OOFSvPnD;VdUnGF)A&`3mRMgX4s7e)!IS2JADMdu2pBg+ZGu}#d}5YGfay6o+NC#KNz*U!F=eb z$eY{C65PHW5TNKMPHcyhLPgMVcy5pEbiEyl+6JHaOjpgM?cfCd?ctJbKXGJx*-rHO z#2ebf6Ni3cr331qsh_w>2U$s(#WT8MPj}%k*^fH3LOc$o^dig-^y~oGd))#4_qQ%Z zR@=%-d!=ar9sI<>9c6WK!MwIM760gn?K}g27p~b6M|ZnU@Q45Yhr^Kvc7lR(edej1 zWCdaKS=&@$O%|NmK5IMH)`BV$bbT3K;EE2jP@OwNsFK-?ytp%9B;d2=)ip)6&zj|H za``CK@{xSHtMulxU7(h!QE-wjpEb1<<{B|bTsk?V3mpDQ6r#T$W;9#zw{C0o5A?J& z?3>l&r>+Fi>`+<6P<020sHZgd$RY;hjX=<9cf#lXKb=Sf{h;z5^gx%pmH424hUd)! zh1_4XYBFm^cj59yGj%hyJm|kxs;}1hjn9E2xSw*e(Rf~%B9jZq`lvwPo8|bZ#>F`5B zC+kq%;o@o7H}>x-TZy^fw27-TI&Cdm06YIN6L2hX5T|vn>e?B_MY+wVdcznCdZB)J zhiL=(TyGqI(00y-VvFyZ^g7)&P6mj)-#H>qR#nS_?rG3h#KGliplZP{=!>x^b=qMEUXWTq*%}xb>YA6J(gU|DDqkWDEJ^JMm^l>P=5V zkZ(wY`}_Ie=-fJ1I7o*d#QvkCJKH9~5a{$!nzCO%9Ncw6k3P^>kv@o?Uc9+4jzJ)} zE7P+%yczFiIw{MIPWL3~F4HjMj2XsqmG!amJV-UC8>A4`@~2)nB|~m~jhjh8?InFt zEjQ>31v&lXsJ=2>hX2G*G)H7f7L<%E^jhn0_mh<&I8*9lL3U7<@|gh;cvG@;$`b~Z z=!;5WBSz0yAe~bCOB>VAXEwYKoa&yer2{#4KV+ZdKiR*ZjFJzs)(RT{?VRZc?6J$# zo?S&ILxAuBPy&dyyrw@kv1T5mD3i&Z`{Q=HbEY;!Rqj3jfT#7yNttH3F;{^2CzD4G zfHBTz^4S5XY(8glzJa)N%jAr~kU3=_>XpL8=Z0fP`v%HD1xNBB=)iY3>#Xvi9n?1i zw+b+zHFq2&ePk>td~N__L(2)TmKtTmIAiRqK`03qkfN2RnwHUaUI`6L9`Oe}EOr6}`Ww@k?V8o&Aim_BYxf_RE1%`BxhxqZd!9NM2v*k;|Adnv zP2zZ{YQb0-wG;j)+FSDUDbPk1*-ebHG$hzG%qu20({oIdJ;t1t%+UK%5anEld!93D^8z;+&R>W^G!xsv&zbFF(6z`E)WVLrjd?py!MvPXGevE&Hn*n7Dr`Fy}5{RlqHmPym&SS3^$=v)-{u!N7F+=-ZUNl39^s+5<}V=EBeg> zGU#l04Ib`cX1idL?%6?94sXz7YcoGs@ZDMPWQ|>|X_K|A>FgUzt;0?HVWXMGJVi<> z)Lw2jqJFWBW}5#Y!bJT(}<9<sURliAU>am0zUjS`R->f+Cow-OfWN%1~ zMVxZv>3%>JY=mv;eDaZ`J3Q(%7Ui!C zaIU)mq7O$c(<-HweEB%!?<}(R zq>{^>(vH;l>16%v`A~3bJ-rv9$gP%hz@|m0J0kvv7es4T7lSu3AKzP^HTk+VP)5XJ z*lJ8ZKDWV4PF({0NLwszmDN0LIdDdk7(_R5GzS+i(bziSf6A?2Y#P-K|7Zx0Ty4ze z!k?C)%q-}j;3_Ul8Q!WN+PZRlL_G(*1pwx=e?l+&mf{K^5}lPbW?%lX6o%-5cEqnX zhc1KV`Z#FH^XF;Hu&Y@PymT4BV`I*_$}Y!T7k`b7TMo3p>%h~O0|mqKYkKIeYX2B! zdt>gKE3lynD^Mx-a#U~_)&&5ugxKlG?i;g2oV*ei4O@vzhFk@-Rs9(hFHx_6HnBff z{u2tAQb3zsZ&Vb27SJTEDK4AYN34R@|NRrO^AXQo%v*Q03fC`U3gE>$^HQ!neii2O zb<&1cu@2X-obcv`ld&qMv1ZTJ;OOqe8Ji68oGrD7?&F*^{YQ%V`lmm?T#JBTb^&kF zoJIb;2-ft!ptZM79KIR1fBWDD;;WM;zux1ZQQQT*JL6;)#qKX@sd)0p4Y<+KzH{Th z;AiFV%URu0F4~N4YE!gzOX=;3qFq75=h5lFA?py`(FM82S_EZWLGH9KYjX6I;4f>@ zJ*6P$TL&0hTaZT_H+QFQM66^K)OKx%2Z9s-TnFl@|E0EB59;-ToUk4@72oyG23%kR z!mpsSrr0_huQdXkHFvLP6-TX5=-1R+VWNZ1(n<`_KkIS&Mkr~Ld0fFw7`MRONJK+j z@0@e<4z}9U-M;$$QZnsv)=W}G9C0=xL07<=P14%b?Ypx$12o+%D~XrRIdndJGu$F= zGhF)uS_;HT6%29DVRV+9q;G3Jssrd1)s)b=~Eiv;rk zG#q%&R_L$8Rz%hy{3N?6FWruZ&>(t>C4~%6(%D{vLmVw+7(%Bc{4H&)vmTF~E2P0x z192PcXil6x#{9n8b6sYGZmr$DYA;M$;Yo|;QyQ~X6a7ZY-X+KQb=x4Uvx^Y}`i!7> ziIOgw9~I?0TakJ}vEsb{;4-3$i>4Oy(vAOt7uR<&)SwTI+l~mCrja9D4Db1!%zL)M zhda1v(4^}C1Dw@?usCuF4uw(f;?#wJkZtoU;Q#r)&8l`0Jas zyhFOG&(N-{xAog(?Y)X9JWa~{wHp`VTG+5KR(0Xff$$1X{1Q*ov)?Z1np?a4sa`nS zcc|9p{SkG+M+M@!B2^HNq=QD@7s^u7_tYxI|XCg^3vV12^Zdt zXY0%v8Ae|KPu&gGF2T<}_Tn)hxC8PwhM~H_dVgV5oHnY9O;eb&J1&`$X?tNFz6URa z>@RFsZOJZFO?H@+efQ#(hD%vvn((;2fQVaYL*2W9BiHvLSRd;P^%g%1Yk&}|+T+)g zx@3MFpMevmJKD(xKiWP#J`Fai1malsPnUhzDIHe_4cPVwo??L^B%k)OO0<6G8Ks9~ z^Iv`Jm4W-G&KNw(7`!0^y6A;=VvZGx?T1){@cWg&;c_vb@6{`=&lG&l?|tAk%O zn^&867^^iaV#L6vqc}S!;W_ycIYu1^roo0tM~}#c>dfETL59K>fjBgqDJbfw=lV|t4*h`8g52p=qvU-fm$g7|LB4_ zFYyUDT?@3$wG-O--QEc(B*x9a3Y}8vB!-Oxo1d2VUAU2hVr!lCX4zaf0|Yf9uR4jb zE8H|3tDx@2h_=Rvg?i7mQ|SIO3F>&_W|UxAG0=o#GISYsVSk$N*(ZKVuGgv3nJZms&4ZHpPo&Y}d0_+pypmKAd_Mk}*BU4ozPy@-p{Rc2mL z{MhpnD0{)HRVkn}7SDfmXY6 z_(T6J$F^4>>wNsUN;?PW>xNx{q1Jd9<_E=!Ctg8#9>4@znRe$YqU#y1oV4wt;lOdL z5PYva3~T9>*sHMqmtQ<3MBd^?q@%llokGnbr%SP~&8(6W-4O|(_EzWOm z;4nDi2E1)+ah`YsMc{6o=r4-n0if0yb`zc6C3y2qS=z#%0?pq7=$ihmj3`=?Z{NiG zPn%0Bcph}`ChXMt7G6R*gf`xDH@7V;wf9c1l;m@_@Fd|b`a+Dp8n-odmgLCWc+>3@ z=s^Zue~5|d_S|i}DU=&O>u+w*!|%uvmIcwS)rpl@k)J2uLD>0tZr^i9zTcj5UTKox z-Z#cQv0v8&_n7$Tg!ts7s3iCJ*!b=TcE!8L#KrWEiBC>&?;7Kt9GjTn-n?ehdUcwI zHfZV|8k-aoot%&~$UWiL_ogx3eBHy{yTr!C`?$ySO-|_R9*=nk#`aCtDEJ!Z-Zde* zpD}5x*ygSE{=V*sQAttmtzuidm-qE^AEdFxNA-^Bn-~=xW9IPak(`_uRIXg#=pHe> zqx$;xj*U)A=$p_j**7|&cew$v1Iq>Y`BlUhkL?@SBElZWwa>a-)$P8{aP~Nhuy0)3--dm)N-2Wb8UIb+tu-yo!7M-znR#thPvK|Nj7E Cj05ig delta 24649 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 delta 24562 zcmZWx1zeU%6Q5_72N4kw5fKp)5fu>;5fux&NX71Mz>ZU~yI*B&@y<9K>{j&b!tT5~ zyYoEj`|tBm-uJs7;?B;_&QAPicHh@K_IIA;_wvkIu9Zsu)lY1>BoeK+49VVE+j7q~ zQCh~?*OHBg=iYM6es(T-;>!Fj&D`&6TPk}5>hX_92pxl43^}QL(vb0j%nx9#{HcV44=r6fJsBk1U0sO>6REt59fbs-SaYASg^yTX#uT_cU6C@cA`Z(wG$*`F$nwFDL2qOrp^- zlInklf}xTc*OX+F1QSJQH2haVT0%UW;2dsWb{T?Bbt)@VdCqSAhn7R73GZKg)mz6x?(N|a|5;%b{lw{Y6V^(94|6*S?t zM&Z@ji9YK`AsO1d|6Powg}kPk}fpSXzL?E z2@i3)OM;@R64@*lWXnVW?t((AN$R~_qp2-4Y85T$bT&yxP7A8>FVU438im~_Dq$;V z$aF!a2q)JB{gF&mXPux8Jp?(=tOZ{#)@XGzL7vly+5{0@6&Cjr&hf)%O8U^4sPSE* zNu4FVX^-IhO`~JoHF|}^>~2j|vbm&wp~cA4;t-lENRJOL8}K5J@JtAPaO!&g>;*s zQ4e>bpf5xp;Ei>N(as(kMcothxBxualjtmd#(xu3yQrj1?(z7e4^i#?fIgN<&BH#Tg zS&sVnHM(C{P__1ww)K{Duo6*BQ9(uO61{#aXeDAl%vMr|5|Th&hN z9Y+*f9bT9WJ#dzp1z}j|e>|t9PDyXiJR>B@4MaD`NU}85=wdYlNFY)9eHzVol~m2u zGNYt(&*k<|>O7J403h6FqCS1$%M<|cT?G3JXbw1u>x|?XBj~a-(Uup228=_Jy%DrH zM$q41HF|y@@mfmI`JzNmtpP1HHJUM0qdp-T#jS-)t&osIE%v_7@!l^5bu0vcoIz9o z=&`6I(Lx~2_9hU89JMP8P~N4{x@~aKuY&#p5S3jE*v3}(vH^G}32L>Qs4wz!Uw(}m z4kwye2GL~E=*etJ96(eEA^FQ}fKHGgzCkp#heo1t0rmk8ZIksH6oM+lm?S5O@AH{zk7iHP%Kfs*D$X;ca(ZwC1L zEetz5&aVu?cE!F@oA15JpW ziwJ5DI4$KR$$vZ$?H1Yr6ry+sWbe#sNF?OL3!LJBpP)l4U@pMnz~Pb>qXIQ;2wa9` z+QR(LmtfQCl1{D>)YV5)>552_YY>j`3=I`D8>hdL9|r<{f3!xjAQ3C()u?l@M#~T{ zz26J6fqd`gsEm%(jjA^gwAMq=6U1*YDto)y8YM#8w=DtwH8irt$u5jV95@SFc1}$C~^d1r;JAPN}!<`BjmF}nFApLPj#+F=yT*U~BB&7b zoL5p%ha9M^eQ^e)h|4TNXJ%`3<5zebNk0u$cI#yTP&18E0Y=sXfM91eO7R5>!muHi zh|X_Dy$29Qj3atcTTsO{M7?Gs*#Ss}#|sL$s?t%TMUg~_btOfO6UAsON_!-Jwj(jN zc10!KBB;kRL5mP3s}~4*?uJU6Y&l!nJ-%@t*cc_}#!iiXxS*Otk0w6ItCE0+Jm?gr zYgDKfa_R}{DSkXR0hRk{=x>YLLf96T92rRCTTzyjUIKARKSYpR;;8QC??zP;7GfO0`I`f@qiGN zufd4nHHgavO^IfqsJKP~Qba(xXibJqCu;g$qc?LA(r7UPRskfYOX`6d)inW-`3upY z_L5?P1o>g@4wMrACnzUPB?UA_;l!uma` z!@!|LuMjI&0q3@8rYeM^0D2>dVWc({Q34Q~r;v+4O>!%Zvu-2m0soz;rO~)yM3!5E z9ES^Phq^X11U-HeNr6WMEuRV}Y(|kRVHp$P9G?K7DzZ^fP1t{TC77+Ipl$O7E@ z)ER5WBFriSw>;qg3Ne!IpjmZ>PtX4l@$?2|tWdH>{`1iGpz;mYQ9saqY=A=&5UXn^ zq1P@bsCz8Z9w<8q=Lk8h(T8q=9zGXj$tLMj1X`q4=#Y^U`RWrLfFoj8plg{!G#5>5 z+%Rmq6|K+|IOSJ#HNdj{DEYLV9Eo$blcauemW^e-8@;;%5Jq!* zYadZ0_L>U+^!7nZ_X+(1Fe4W9fY*XH-$uzo_Y{6z&@klR!4m-DPRKnsK`usGSF~{2)$JE0kKtHt6P%;(u=;x(EB#M>rqIhR*E~ zN-ZF>$~^QPqhXG`=rIaw*`yNDlnA21XfD?0LR&Tx7CWNR znm1^SQ&BFEzKK?n>WtCoIxM?=9BSWfMC~T6EQSAqn;k;0`2#`L+Xb!1LJw<=2Kr0- zbqG)`3g&c@X9&P}RllP&aY7MV$q8LDkR^pNTnfwScIur*V}lh04Q3%_jnHk_F`*iY~u08ns2J zGQ%x1f;_|bFBLSnIncf$Opg+~`ZIQ%kE&QrP!42lT{PmWkrKbpLHpSSZD}D?&U%tY z^o6Y&1LBbFQ(p=S`wOtq+VVZfHNGSej3YG~hWqjKLhg+afeY>d9KLEOvdO%A*jqHKV@yi9p1AQ*wxBp>WMscbM z78Ga5tJh4>*QtVzv9Egyp10yelKU+ZYktj`5;Ik-=@*_sy!++OppBzZjoJXZiT6e8Ljj~qB4s4{*&chacvOi50F=56+6*`kf zXpM>x9j<~~Xe~h971Sj-#HK!K$M1svZG?j~!^O)IRk1+TtGjSn22i>_MFBzRT|$O! zxI+|IN6@}$8s$MswnLi!1~(om2fx4^4U1{iWetw@$+EVhYpKP3VAA@yK;iNd19A7D zwBHA!3aAl5u+E|VNZ1iXV-fr|mNyj(1()oMbUBDv2AXx>Ea(bm5{BRz1rB_(9Pku? zBLgW*5H7_~Yzb2R*l~^Oe6utNc8@<-6dM9g)}Gd=W+8`sVIXus#8nJJ*r z$?It7YM^5IYIGK{?_L)7hgA4?bs5XkU~l{HwQ#U?M6=O1UVLhCujK6d68&q~WZc9; zB(;arlH3G!?jd5&6Vjo;r< zZl`=lpj<$Gd7ZuwHEPRF_Xa>+kHhx0X&-jSv3p5(&M`-S91V;{}cT4oMxiwns zkHAEl?;eM`wE`{iV+0<2y`n2{aSY4}!TnII|ICFZ3Xt++0Z|z!7+1p*UfJ1p9-KJP zhG@hLOH5_w_`6LcCCvpURKaDmCcp)i@xxzeyA}hi5YFxMNNR)fZ-az>ii+3_-R^8W zsKlV9YSTv}uQ+Hq87Z@tsMJZ^bxNQ!+k+e9df-YPqGlc7n+3Qf0v!Itv6ps)gCC=F z0}iDW6FF$X8KP+plBzpc?5nuDQYyN4v?R_r$!>Ra*Qf|54iUL~Tk2Htj<1dMUh+3$ zC5}i(j+6{XtNWupA!$fuKoTJ4t|ywd1Qa-5OVz5*KB2|YP+ouo!twkA zRDQA;?~K_ritmD~JEKwY+^Eovv2_K@$g1A)jiKq-0*D>3dVPSKk+!D?3-SOsM$OXj zqKZCamZY_)1}-JhFAo!Re-dT!ztG?n6~6H%3sM{D2`;i7`mWd`$r$ z(Uzsv+~en?-O-TTPwkObm+?Xk=>5GMfKEeqh+1_DTTWSv7l|>rRv@18!N9+S5xwn0 z^fC$E!w+=Iz^M~Ek#1LkcyNAVD`bTWund8+640HeJ&uQLSX5M_F&hQl#hQn>Ni66o z8dD|cX*ES6Xp!rG;Dv3pq|2i<3fYR61yn2A2LXeDVEJ+R->eZ^6HV`kNU=y7KL*&1 zoEq3rqiF(tP&uOSyDc+9oL#4$g8nnm7uexqi>uSnc>wmDL`yqZ_J_FESQC!N`d1p+ zlt2rCV|=kjI>9=JyTjAYf=X`1`y*=a<(|O1(nQ_XYIJ6-MzN?sbCIU+EEd=5?(v&j z0J))%*BXQ>4si!fsO@WwF3pp4=_Sf{do<=K6{o#`7ii*+|Bl!jihFQ7^t%VpFIz+D z;^?Q)d{*vB6w*>sSy;9X8rTJh_UcV=S%YdJziadiZOb13sxTd(Hw&%IWR&em10{7V zt&v2%8ZjNEV>{7&)TN>TrLKs+H*iUnDuVWQfRdvSVTghb`*3MNLX3v6?l|xGVH!;z zgvW;bP#i!v5`ee#A(Xd=<#D*~%LJvsOWg+HW)q4V94-01psk#I-f@2*#I0nP32B7+?rldww(Fp;vZ4ocaCQGUTH}pXev@C*$r-OKAfRgP{5qF^SmD>RTglCJQ za!&jez=!;v0{E^m8Ljd_lz`c|>I3eVp`U1jI7@7VX6OmbG^`?CtVZE6vJ0L@fX>ZO zz&;_V&m*C80#hcBz{~7lOUs%*@eeDY`9nuGd>}f|mv}A1^TYl{_+SBuco{mypFvmv z#P3Ao;TOnO8_4+h2y_QJmN|-;A5N6(0k8(xa^PQpJs|CKvY?ndNG3E8dAn&eX(nE- zJHlv(HTq*aI+vFCD5(ybvAkLVs_+)^37uOaBW_2-Q-Olq4&jrIdKULu&W<%v@){Pv z)5{BudIHauJh0TM9~^@#YYgx=aO~^SLA4~r5gQJ7=;h`cMk!v)R*WhaO*tw-9JE5tQF4K z4-I@aqF<0UjbbGY?~V0n8|LK3)0UM+haFH=M&X`Y?6ja2-_YhtJYAN>hG=oCA_a!$ zMM>BXRJsJz0sscT#rx44g!2>_dc2@;2aTFfK&AahqYDWAag(6LS>z;gaE}j+UkGhK z0N2I`H?vZb{y=TGk4^khD>na)z2=}Yx}kEGK<*{L;@1#y0}EM>)^-o}gM**Jxzm2Z z=X(f1|3&DWy>Z`~gpcH^1K3*OttbL*CGzx{TSJ=oL0GO`X{ zpGTuOhat?6{DpB1+dLeJUj-l9AhfIE_tf1G>m%u2HQd5`p$QB@s#MabHBx2XDnY0E zLQA-}2`u>w5RCwWYwn^Eyn&AgJR~jrL(n7q@DGGb13cfLq5LNV9TUP}XnUYjE)TAODQ!z)&<8sIg-Z-%}f-qXvRKCPR3+wgD?z*u=3 z?G{`ZT}P6=hLmcE=Zx1d*>rqv`IzV*+rCK{jtx(a$xv{Siozd_^eyilV#1MtfE z3daX_6`79*@#**!06o>zis&wF@ic)N*}Nc?rpJ>|yW^3X>g@vI^UomUYkf&;CJ=?x zz`NW@w4L3F9-$B?pSL8`^J{c>C0G)L~1N9 zlt-38x4O_}7aIO6FcEsZ^|&IPKo(@nj)o5Y`|-%)Tpy+Yxfj5z;|XYi1gK^$srWjg z-)7+cT19#`+2${KvO;12=sh&V3Y_tXyas6ZT9B1*N z%tgdALjUG0d>(cJc1P_f27&J&@G}yzDwG%l__ny=I@lDAXAkr&wIqqt`1HLeF6?cQ z;q`Gh9R?tic>RlnQlB9A7fHYG6jc76#2wR;+`w&YRD+384YVCm4aAcg36q6C$IKM= zy!KaN%W>22hsz96S=3*{%kOIi_~0~Afn9eCTYbbDXu#TJQCcmi!6jx2M=@g!_dR5? zdGYX>qN+$-!->aCiVMG*DFXDJnG4&^#!l^%H3$B8mhfVp1rf*Ba0drr?Bv3CW{Gfd zZw)H%XmE5n*a3>VeYR*w2rxbb$2s3F>cRq16=Qs)UPE;kqCK5KdTR1v`K zmkL|Ugu(Wfp5jgx=;Eo6Hemqw59i#2{-X< zz3DRlL{UTkh?{9wPX0{<^14J3AgnheJV-aE^K#*)=iNZm-el;tT=)vF4IK3)og;O* z2oymZ%!D(nR^?aWEuuDLSihs*CtW}g7yM25=o5Y#J6Vb?aTb|1ym8hkc+=!RPha?Q#vb7IRz6L+AD6W{+` z1nGZ(HQHe1dTT^+abu&AQVB^o)xCAXm8-55j(lzn0_};p_@^mX@xeS_CUxan;iCyo zT`Pu(5}ORuW=`@tWK7T|!%*o|KT&-XJFFK?MA*+0uDp3YBC72sBURGbT{+JN5hS`o zG;jt~S01$isXuU2LT}-w#t9omdws+v-01nuGcA7_$&Zh2gl5Y)`FFs1(iUN@)_Ge} z=i7=soA~83%~)&@dD|x8ryWy=2uRoraN3}@2~7f`UeC}blwHS*JiIAY%O?KL&?bQW zlZC(dyvc}N>>a?Hl7SvFNu`3)*C5z&@y$p*`y`b=it5eXwgC6%dI(4R+BAfEP=6YL zAD1K^y+uT@*a8c8nb=Hv?L?S(kJXWb&GJ|##>?S-wl>>oVXPg>sXSB z3a_^dUtYQmJmt0lmG1n9>@PkgDZF;$Ovd6^B6262=>~Eg-mx7iUOL&tU{E@X`svd< z(x=vCgo$v1!qx5Q<@xcMV`UOz4a1U~(|7MmE&0lMQ42wZp}VQ0cXyYf}Gj7m8)OJ(yA$d z!M&IaHYdlX2rvC5#&t5sx$8mY4%FFD+A2TIndLx_t;+f3ynkHV?xWIL{N7~JvOxcy<#S7(T7%NCrYW^9BocVPdCms=V_3U^D znajD4i&*~sC;--t&m9%Zv>=W>CYFfC+u8oONYHzMYot;sgz+JfC+9eUGBgUrt|qbf z31ENXcJ6z}+{BHqE6V2Wteq6C#P03N4t>O_?aD1_YB-!iNMFuef66)Grn&Q- zbE2gvvr`?;U=7mC;|;H8#tx4BIu$k!#nNk{yxP;C*l@S=kk~10VbUexZ&MvW)r*E1 zoLxBV5^`wtPQG_R#EU6Axx+;U4ppXWyrPOrJ|{XDWv2zl*rt>IPMsXXNU#GgXLA>tmof_t9qtv zHfH|3A{_Ioh*EnD#Bc0G{@|SUGpCPU1;hc$79Dx-H3U}cUCIoxqT4Q&Sv5t>E)@eM zIPQiho~s5@Ugc0P8jNLa`TiXd&Ve`Jq;b2HXB+YS8%Xh)yOhVGxY$ip+WfoK%nVU+ zw;~P|eRi8i9ezXAn_IB_z}+gW>hg>m!qy=S8}!G2rphynMNvHdHYDxc%_&b{B(*Z( z4s^Y?J5x6H|=V1*r9>V*5;QB|U=UA3a8;2;QfRZwPnbT2CObR#wVNMTyv_oZd;a z$U4*ODQ3FvQ+QF1_dbQFm^9&r^|C($cum}=z@eMAlB++0(y1>{(Jt&$hmKhVIW20ho5eC+S^i7=HHtXU0t&*{=etoRaUr=Uxd1{T$xp zdh(kW$cBY40sS{K$Jt+@PCVP6C7RNgIr6Yqu<$oN_{3D!5auqd5128Z!Dk;1bM}K- zJHV*94w&{gPHnI(c#R!h4ya)6@D{;b?0|WcxHl+a<=!Au%N{U|e)|o=d(s=^Mrhg| zp!n%=SR1O=*0AepWP5*L)szFOH-Mj&lx1%b`xdZ8E4Bs+@9-Y5%2)*y@!^W^gr|N8 z;|g5n19IW2v0n*(`5y3H;XMSr!U}QM*ff*uExu(^{7s%R2hBo=rBy}rL1l@w1*snp zLx!BGnLJJmvX9t$&@7hAK4HUIABB^3O{zt&51P@JPIVXW51PhHr#Nx@Pr?RYnC(I$ zB}Qe2tXED^4F&3;H>*iJkoPbmDC{S?BTxGm z=4+Zs^!<#a?U2G{H00Ix&xn_9DW;wn1d6!Kfh(8(7ilmoMWq3Ft7!H-=3l5VIZdfm zU4^|R?y@ysR@AvEW+A@!6^|_yzMzc$mUhb2uPC)UzF@24DGF@*i@TV)2AKx0ulgA#;~_e~RE+S{f#B5?pY9a4sf60V2LmdOKO{^L>Kg_B)P#OpxRp#kK6h|7Ez z-9*_#rYpeX!!N!I8xd*DL~xxSP@+}Zw6XbyA4uD7hg7DT>ddp1zG6VyE{etSeT~h$ z>C#1?gBQmJhQ;TlN-upAhC!wS3Te_o9Kar$tS(L+QV3OomuS*oTt39-G}%PFIAl6} zmXv|qUq}~Web_WXqLlu;>?>|j&jqBo9p>*s4i*8%?-raYrMqZym|sg7FX9d>Pqh*A zvDQj<5lauN_|4Cex(pYaGY2*Ji!SZ-bB9%by8NjYz*ViKll~XRG3I!(wXCc=|DjUR znEz@mU3DLf>zU)QY|>dDm^ps=NVDd|Y|=qb05Qa5GKep-NgI6wh#j*KcVE_Qxw4J) z5C{I?wl=b^ejXenIk&A0<&QQpK);W1Z*x2}yY$ct9Z|YrKH5@lu&XG0gzatRFM4B; z1Gst)>7BbS{9FUE&Akm^xsl%#hsDQJ)H8^DM;rk%;-kW1O5@))l*r z-&Jze1h}h4D~1kbvX62^teri^iH@?r{uT7$rWnxexNRO8q*pwyx*KD|i+PYI@yA(n zlI?T`y{SoG<|N&;9lXp@R%P{fcFqfXod83crm=Yu{qK&mgPW|vYQT5$BG`01l&7hU zWe#~FQ5<5aC$#K@Q~P2z&EB(|rH^$rjOV1;OcB^CpY*ft4QfJG>fU@ZKpa28uk*>p z;`s@l;Uc3%#glyBMRw8ap3IQ>GQV_lQ10sk2lg;*)9NHA=Lc6eaHYAwi7Ns%4&zYs zs9Rm7qnLV9`KC&)aA-Q1(mgbvr@P3imcZvu;`fuvMpbxa0qLpl!Ri|3>M%EHBhH^x zcIYK;m{K^&Us~~gH)*Rs2WNYe(;((3C_TkLC%JS%SzqKirH)dCcN9dx7CM!|Y3nY% z^)eWTsFj}F%w4)$hhx0au!<)yahKEdmLM2M^5n=uvVuMr<62zUL%Q?2LJ+VO<2vT} zeIZ#~^f}G$9V4FA3JzS zCw}A!vpb#5SmC1=KC2X~?kS5~hVQk@t8P*Kv0k-?y^)W;nD#fOIjIPYUMW+WGe0T< zP^$-yIwpsgmvq-7Fb*-tv0ez*u9>?z^ZvHNjt_bP_F}atplhO+ zbheE_JPkzrE@4T@mbJyjG(qanmRW_|id1Md6TQ(pG#m_%jJP6$KOW4Rmw?CxN~8<_@R1HYuY`2fa7iedPH5|cC-r+Jq`h{B9lWzp9k`f} zw8y9M$}aiL)nIlPg;RN?k1QjCQ2V-#{mDl?MJI)$AR1>!hUGj2iUj%Hg zQb4#TSP{x8{z#(VOG!WdE5^0V@#j*~TjV~^h5ckry(vBijx^~L{eVur&+~qNS&73+ zOWTCfh{f?>Xs;M5C|YrSI>x;-#_pV28ff_&h;bQ2w7hqrdEhwdkTV>p-Uk7&2OO=l zZ~#Q?#1&(+Ci(+R8p>AS$TG;}j~I7X%zn&eWU%;po;OvHW!X9a#WnB(kFF&P^6N72 zNmu}^)8K+imkt$>_zMG|O>d0R3aPP2S!u1uXU=2nEM{CV#o=FjIOr=gCzI6V$qU?8 z?S+9IXA1u(gmXbi%WI~%g!0lKkD+DC zqru95iAR^0bu~XV4CHU+rK_lUNy#e5;S~^|oi3@9M2KMqv8MI>OGaVW3gYtWT2Z#w zSA!74>0>`WR}n$H?-IYNC_8BiB(|x;#X8;EDy#3pHzYEE2fVFxI$GNIP{9rwjifg#_p-}H4k1>Rod%q z!PZ$V3*eVk(cbmNxMjxJhTBzxi>4U6Md`m{vUQfp{neyX9<%zYYiA6eP`835Itxp` z5bS;Q3eN~Z`+NHe$JK_`heM>Jy{g&itKMS+b=<+#r3>(BR(07@cft1wx|))v)sS9X zy9Q3_{}VA#kH#3CuTuY04Mf|u7R0vZJ|H@9 zt2)w6d^coP>PugIY@SZ==GXOMmeMzr!pP7ts4}AgurdtHqTvm0*8tu9 z{2MAtpqDS_Xb8-F^3&MYssc5-$#)ydO13qPVm^cp8snOx;4Ky9X@WO~N*^)g7RQI8 zlbU%u%a#SgkP%mJE1wv=Rq?gQWnr*UnLB(p3~Ar}4!+sI?W3SsOt`djO8*3~HcX=W z&wdnthet)@;{;6mi$CsgVz{g#zGHbfGQG-O_K(20^IeXOkk$1`ch$oP#Ch`72t@3< zyPOy$i?T~3oO~p6GAt4m;~vIACi9F)`0`U4^9eAEocEN1`MGoyoc}!%AnS5Z`Nxo5 zDN1^1r8ov#m<(g05HI!bsm;pjO~B}9GX9IzqJu#%%B31XZp=Nd(g@{xFqqOdU(yH_ zU^K>tAw2n7BXx_w*jov4X1y^oW)8+7=Geb6s_UwBerLwmA(wgc>W6qz?>T!pS?Tr) zGrYesls^vkaC13`74*v(H_8|n=bq6p!0UU;)b)Y4@zJsd+ciOpmG{01T|w|Bpw-Bvas8%P-33H+H0g{y zt0|5;1jOJh#25F_WKFxz_nX4Q3o#j*G3mywAYWhilbGWAK8(FgrikWfoX%%1Qe(Dl zj=FvW#55&A^c63R9SSf8j{Kszw6U*)0E|ro>@WYBb<(pv$T*O(#J>eJar}Rxoqg8N zr3yXZ*)3#wy<{fi`W8^>O$(Hwjt@9@OW91UeZc2B%K{wN8kjP<70kG&B|516Skuou z)=x7I9NY@-yZC@3TghJfGq9m6Rz@}0KDL6Tt^PDR>~vz@x<+~pG_G6fGX#6gH^^8N zpy$Up%{qpV+pUp7ML|q+mm=nh#$9cIaa${m8ER@z9w|-hr6u0cOU+fle=LLHNiL9A?8kDd0NaF#C+|c?@JKV z4q*_Rw#Ui7{lw`htp8H_R^y5t5ab2_QtvRv39$kVWCye|B@B+ndQD8?Ekzw)iOW^r zsGI6i5sH~K!>E~@q0lu3^yZ*vRUoV*6le!xR#hi;gsMIN!+8vxV&GpYX9{pgXQ1$K zXwg+x=T@Ci7iJkM88gLsdnXuRDFhgn4&fY~;hXgs8}Sg5D>GCMfY?->psBd|mkQB7 z;^|*pwTtW|z8SyUSu6Ch`CDxjVVm9x=P}03gvZ~??4@{UH<^pucYtT0nLT@S1D;j; zTXo%U@K-e*Bq9vnN@CjI{IZ*Dr7yvJ4K*K}GtwxW-6NRc~pZvlcL8Fx(dkIxLz_=eoUN=5`<& z>rLj|>F*UykcfjYXKZWCIqK6h$02>-;}w}})i~odYV#xB6pMRVju=GNtv*2e6mSM| z?!LIJgXp2BVqC`@&y0cD+sA!B?1oWzkjw?~Dv^91X0gsg~wM9MScS$ZBhe8_#PXA2K?CEjQn(r!=bH+i>C2`38 zPLKIO9J;uHkJ-MjtR^Nt=7_$yG0c6;^ZUv$eE|eD;zfO>7u)xfeq!lkj$ERy`U7#O zEB%o6k-q3VXZC~oCmwT|v9d5n4g#EG&Qmx(;WtClDYN=x=UoGk3nia${JeA_AbW_0 zSsCjM0OPm*U~HL{5o8ZN_KA`1{cvenG5~kU;ZOMd0N{7h6HXbQzEhil=#CCO;cBC@ zQ1DU4Ks1zZvx>|)2z!5h!podQ)-VfIjx2N{Jau6aY6f``&rqdqcc%t!B zV?Tqb#9-;CwdCaf=z(qzM*I(258dOQnum-VECVz0a`{uvJwy%^JD&0^r5xCcbIT!U zIhGBTHu#J+U5G2s915h2!<5MLEJKo)BD?4{pBYdAjrinH>8m%#*wk8$ow@Wd^brF< z1U@UKmcx+m!!ZVmrH!33bejLnbX%2Q!1-+oHeB_LH;sdKpm^&i%)N%A?Va=s#9T4= zN*ia2`JA?>-Eiq<=SS%gm;Jfv7?3OLZqGAR+CLn!f-z2031cTNGy)!K`P}qJgAusS zb$QNlBV>6o=DDfT$q@k7DbIQIMCgZsL&h=oW24C+hL1!QJD0f;#-99g90c3HFje_D zQdSn8FU;`3z&k@mU4vMK^NfOvTfa~~G6p_kgfSB#t{cQ|;^hm|XzfQK52laCdx`5y zjvNhm4t#0O+#4+eMUR(!a1kQiVKmGaHU=+?{a%{RG$|j|EHWIQTAZBz!mUl`>Rak@(8AV*ByH z`(ooUv-y=WWnl)zS$s9v3iE>T#+&=W@v^PR_nK4Ym}zOt(}lCz$XGlDn%{b328lrlo{9)n`JsOU zuL%g8KI10r-)7;Bn+7jUoC?5lefu-7F>`Gy;;Y76GaL;OAbav%m`{ZLM~;t}n3d6E zIv6KU2jhyYj3E1n6K~DfiktxeO`VSO8jN?}s!*scioeUEAr@G1?ion%^7yWO*3%d> z9U(%rdS`~Rp`k(kIz#zs7j}<(XC~xNbMC_O&QxL4Y=qCknXp)knc!aij{DAp3Z>pF zHx_363n`Z@AW{9jnY$oY5REejuKaQqUilWyg3)8&XE+FK#*BlQ^FCp=>?W3HE^*b|q%v3fFpFZO#5-R%Zs zX^<%GWv8F`4Z7N0ANN(=7t_z=#QA@d9&#a=QxBvI@BJHWv;};|*?sjR_$$76zFPX_ zu8zCJ0Ngk_;bLG{&Yx zToBa##FQAp{wwh4*=jZJ$cZbZvuyb-?a-rE!gn85!Usn|^8X!z4X!$?(5mG6uC6{x zKa;p=6+YV(KU8;|Npx6^!cz}Kd@nwY(_3GNahhHb=gMbS!*b_-WNwOY$^0(e3twCjJLiqPj+;=Sw2ro+<(khOT@23!}rX?%8r>>);JoOs?`<;=Y| zB7qlZ9CE>=c#CzKGD{1w-S}ObM{mNj%qfj$9x*wJ^Q}!lfY(_m6_Y@*6UtD{wBlTK zJsj--E`F7S&ZSBgLe*s8S1ZBGlVx3=nT+EPGX~A@O1?a8FdqYbtI!a! zFoQ4O+>Dp7V;BdSWA&`2U%)s#bIfhFpwiwF%BrRL?iOtLK`7HkXq2!O&0tw+POaYx zMNH zI~LQ=t$6ls*-*3L+q>1RL{C4PZDWAMAb>?#T^X`8kKKbrtAhDp(;z+fN?YsRc+qO2 zD+`xqMc{&a@lMeNTop37?DTOM`*DW@h}gNhdG1k%5oCAv;%Li2QMr&o;T-#=oqY}C z@l&OHA6ln#)INMGWf$c1RC2;O-+tutVV&C^kWp&j#0&T1IH&$k*t7kJsY?)`pdfP( zkR7bz=$;`VR(q1L8-N$L4{{nF#8cY4^qu_GI9Ru{*6=wJb~eVId<#sPE5F$*1KHs) zN|?7bN2SQY)*)b=pqZSQ2;r)Sq_cGxsK{Ppy+J*B2w(ka@iR5jx(f(nva%IFB^|Zi z9J$Zj#+U2=ft>!uTE%I7eJa>1m_l#=fl&L+I*V;xkHEG&t=aDg3jASfg#xWas0nctXaF7ZW%@47f10Gp104f6?zt}5=s~-o#9yo^HC+-*)%WNhf8D>rA zwYODIc0KShUe0VPa?*D5KxGzQ|Do9M(Bn8z)ofYR0wcbZa2x;=o=pXP+WOZgq_=g) zY?*chA(&U5K$Z>zb(m=f5F6+dei{e!nv*Drb3h!P!4%BOv|?E{6V6AS0mnvg1gT<$ ze+qR*wd|)5P}{Pl*;G+3p8{GQ$VzcLjs4GHVL;}>9CaxYHR>*?M!8NGcN(9@Jca=j z-WVHPJ&j0v54OO}#q4$l?-e<1ep;J58fl=un$!uPRTy(dEjQ$P=z*EM2hN~cRJ2jX zEXWu*v*TH~sez3NCkCb6S-j2mw&BE7@Ju_41C6mUby5SqdKQ+L29aq8^1Y9D1@*1@ z7<{E9(MF|e8?o6&m9NI)A_S}8sd5gNiuLM`VX3fQ$y7M6Y<4p?ewy= zQ;@CFzow{RYZg^3a_55=aPVkb(|LxNoEPEnSX(Z95$*O=TZLH#%?*}Z#QWR|TTZzs z8;TvaeDD&!knsK@a-q)^NI7H7l;u^IFnDTAcM{)iO`95`n_tG)R`Tjgce&eFeAkDaNX9`mZ?@`c%J$ z+U0*0hud)#BL6TZ!`Sm0INxKSoNlb`a}DMccB*t4Yqnp5PxE1nhXEzy(>2r$pUm-f z6%rwKrmYMK1Fys6p=b(Ky8(&~yWax1@4b#^#x8cI((yOo@sIY>VU(U-EX4_$pc~}N8G_fe&gHF$2}*<-;>r-E;Ah z`*?{MpKHfo_hsms9iOIJRnNsW7g_c6a%k40=dd2#JUaI4(xq42z?cDA_NHC>4T|mE XtxJq%-MCY~9&rP9d|YI8zUlt}F}agx diff --git a/src/Main/Base/Project/Resources/MarkersTextEditorPanel.xfrm b/src/Main/Base/Project/Resources/MarkersTextEditorPanel.xfrm index a7824aabcb..0f121b4f28 100644 --- a/src/Main/Base/Project/Resources/MarkersTextEditorPanel.xfrm +++ b/src/Main/Base/Project/Resources/MarkersTextEditorPanel.xfrm @@ -1,128 +1,133 @@ - - - - - + + + + + + + + + + + - - - + + + - - - - + + + + - - + - + + - - + - + + - - + - + + - - + - + + - - + + - - + - + + - - + + - - + - + + - - + - + + + + - - - - - - + + + + + - - diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/OptionPanels/MarkersTextEditorPanel.cs b/src/Main/Base/Project/Src/TextEditor/Gui/OptionPanels/MarkersTextEditorPanel.cs index 51dfd198ce..dac00be5e3 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/OptionPanels/MarkersTextEditorPanel.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/OptionPanels/MarkersTextEditorPanel.cs @@ -34,6 +34,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.OptionPanels ((CheckBox)ControlDictionary["showVRulerCheckBox"]).Checked = properties.ShowVerticalRuler; ((CheckBox)ControlDictionary["showTabCharsCheckBox"]).Checked = properties.ShowTabs; ((CheckBox)ControlDictionary["showSpaceCharsCheckBox"]).Checked = properties.ShowSpaces; + ((CheckBox)ControlDictionary["showCaretLineCheckBox"]).Checked = properties.CaretLine; ControlDictionary["vRulerRowTextBox"].Text = properties.VerticalRulerRow.ToString(); @@ -61,6 +62,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.OptionPanels properties.ShowVerticalRuler = ((CheckBox)ControlDictionary["showVRulerCheckBox"]).Checked; properties.ShowTabs = ((CheckBox)ControlDictionary["showTabCharsCheckBox"]).Checked; properties.ShowSpaces = ((CheckBox)ControlDictionary["showSpaceCharsCheckBox"]).Checked; + properties.CaretLine = ((CheckBox)ControlDictionary["showCaretLineCheckBox"]).Checked; try { properties.VerticalRulerRow = Int32.Parse(ControlDictionary["vRulerRowTextBox"].Text); diff --git a/src/Main/StartUp/Project/Resources/StringResources.resources b/src/Main/StartUp/Project/Resources/StringResources.resources index 0a4c60856093335ea96347b6e6db10ca56ba57aa..948adf71eb0643ef1ca946bd532c7fae31a825d9 100644 GIT binary patch delta 35635 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 From 41b1c801ca3347408447fa3a503c28e422654576 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sat, 11 Oct 2008 14:58:12 +0000 Subject: [PATCH 23/51] Fixed a problem where clicking an item in the Errors window would not show the source code if the file was being displayed in the forms designer. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3594 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Main/Base/Project/Src/Services/File/FileService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Main/Base/Project/Src/Services/File/FileService.cs b/src/Main/Base/Project/Src/Services/File/FileService.cs index fee01f3df7..11a197a288 100644 --- a/src/Main/Base/Project/Src/Services/File/FileService.cs +++ b/src/Main/Base/Project/Src/Services/File/FileService.cs @@ -474,6 +474,7 @@ namespace ICSharpCode.SharpDevelop IViewContent content = OpenFile(fileName); if (content is IPositionable) { // TODO: enable jumping to a particular view + content.WorkbenchWindow.ActiveViewContent = content; ((IPositionable)content).JumpTo(Math.Max(0, line), Math.Max(0, column)); } From d2fb81271ce604e46d61794187a41a6b78cc94b9 Mon Sep 17 00:00:00 2001 From: Christian Hornung Date: Sat, 11 Oct 2008 15:55:47 +0000 Subject: [PATCH 24/51] Fixed the Windows.Forms designer not reloading when a referenced assembly has been changed. TypeResolutionService now additionally keeps track of loaded assemblies on a per-instance basis to support this. Use Assembly.CodeBase instead of Location for determining the assembly path when possible because Location may refer to a shadow copy. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3595 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/DesignerViewContent.cs | 27 +++++++- .../Src/Gui/CustomComponentsSideTab.cs | 13 ++-- .../Src/Services/TypeResolutionService.cs | 63 ++++++++++++++++--- .../WpfDesign.AddIn/Src/MyTypeFinder.cs | 3 +- 4 files changed, 91 insertions(+), 15 deletions(-) diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs index e21b7487f4..241a8f2691 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs @@ -39,6 +39,7 @@ namespace ICSharpCode.FormsDesigner readonly IDesignerGenerator generator; readonly ResourceStore resourceStore; FormsDesignerUndoEngine undoEngine; + TypeResolutionService typeResolutionService; Encoding primaryFileEncoding; readonly IDocument primaryFileDocument = new DocumentFactory().CreateDocument(); @@ -260,7 +261,8 @@ namespace ICSharpCode.FormsDesigner serviceContainer.AddService(typeof(System.ComponentModel.Design.IResourceService), new DesignerResourceService(this.resourceStore)); AmbientProperties ambientProperties = new AmbientProperties(); serviceContainer.AddService(typeof(AmbientProperties), ambientProperties); - serviceContainer.AddService(typeof(ITypeResolutionService), new TypeResolutionService(this.PrimaryFileName)); + this.typeResolutionService = new TypeResolutionService(this.PrimaryFileName); + serviceContainer.AddService(typeof(ITypeResolutionService), this.typeResolutionService); serviceContainer.AddService(typeof(DesignerOptionService), new SharpDevelopDesignerOptionService()); serviceContainer.AddService(typeof(ITypeDiscoveryService), new TypeDiscoveryService()); serviceContainer.AddService(typeof(MemberRelationshipService), new DefaultMemberRelationshipService()); @@ -391,6 +393,7 @@ namespace ICSharpCode.FormsDesigner designSurface = null; } + this.typeResolutionService = null; this.loader = null; foreach (KeyValuePair entry in this.addedTypeDescriptionProviders) { @@ -550,8 +553,30 @@ namespace ICSharpCode.FormsDesigner void IsActiveViewContentChangedHandler(object sender, EventArgs e) { if (this.IsActiveViewContent) { + LoggingService.Debug("FormsDesigner view content activated, setting ActiveDesignSurface to " + ((this.DesignSurface == null) ? "null" : this.DesignSurface.ToString())); designSurfaceManager.ActiveDesignSurface = this.DesignSurface; + + if (this.DesignSurface != null && this.Host != null) { + // Reload designer when a referenced assembly has changed + // (the default Load/Save logic using OpenedFile cannot catch this case) + if (this.typeResolutionService.ReferencedAssemblyChanged) { + IDesignerLoaderService loaderService = this.DesignSurface.GetService(typeof(IDesignerLoaderService)) as IDesignerLoaderService; + if (loaderService != null) { + if (!this.Host.Loading) { + LoggingService.Info("Forms designer reloading due to change in referenced assembly"); + if (!loaderService.Reload()) { + MessageService.ShowMessage("The designer has detected that a referenced assembly has been changed, but the designer loader did not accept the reload command. Please reload the designer manually by closing and reopening this file."); + } + } else { + LoggingService.Debug("Forms designer detected change in referenced assembly, but is in load operation"); + } + } else { + MessageService.ShowMessage("The designer has detected that a referenced assembly has been changed, but it cannot reload itself because IDesignerLoaderService is unavailable. Please reload the designer manually by closing and reopening this file."); + } + } + } + } else { LoggingService.Debug("FormsDesigner view content deactivated, setting ActiveDesignSurface to null"); designSurfaceManager.ActiveDesignSurface = null; diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs index 8f27cc7216..be01e4e5c4 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs @@ -137,11 +137,16 @@ namespace ICSharpCode.FormsDesigner.Gui this.IsTransient = true; } - void Init() + void Init(IDesignerHost host) { LoggingService.Debug("Initializing MyToolBoxItem: " + className); + if (host == null) throw new ArgumentNullException("host"); if (assemblyLocation != null) { - Assembly asm = TypeResolutionService.LoadAssembly(assemblyLocation); + TypeResolutionService typeResolutionService = host.GetService(typeof(ITypeResolutionService)) as TypeResolutionService; + if (typeResolutionService == null) { + throw new InvalidOperationException("Cannot initialize CustomComponentToolBoxItem because the designer host does not provide a SharpDevelop TypeResolutionService."); + } + Assembly asm = typeResolutionService.LoadAssembly(assemblyLocation); if (asm != null && usedAssembly != asm) { Initialize(asm.GetType(className)); usedAssembly = asm; @@ -151,13 +156,13 @@ namespace ICSharpCode.FormsDesigner.Gui protected override IComponent[] CreateComponentsCore(IDesignerHost host) { - Init(); + Init(host); return base.CreateComponentsCore(host); } protected override IComponent[] CreateComponentsCore(IDesignerHost host, System.Collections.IDictionary defaultValues) { - Init(); + Init(host); return base.CreateComponentsCore(host, defaultValues); } } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs index e23a56fea5..7888d489b5 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/TypeResolutionService.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.ComponentModel.Design; using System.Diagnostics; using System.IO; +using System.Linq; using System.Reflection; using ICSharpCode.Core; @@ -78,6 +79,11 @@ namespace ICSharpCode.FormsDesigner.Services string formSourceFileName; IProjectContent callingProject; + ///

    + /// Dictionary of file name -> hash of loaded assemblies for the currently designed document. + /// Used to detect changes in references assemblies. + /// + readonly Dictionary loadedAssembliesForCurrentDocument = new Dictionary(StringComparer.Ordinal); /// /// Gets the project content of the project that created this TypeResolutionService. @@ -112,7 +118,7 @@ namespace ICSharpCode.FormsDesigner.Services /// /// Loads the assembly represented by the project content. Returns null on failure. /// - public static Assembly LoadAssembly(IProjectContent pc) + public Assembly LoadAssembly(IProjectContent pc) { // prevent StackOverflow when project contents have cyclic dependencies // Very popular example of cyclic dependency: System <-> System.Xml (yes, really!) @@ -156,10 +162,24 @@ namespace ICSharpCode.FormsDesigner.Services return Path.GetFileName(fileName).ToLowerInvariant() + File.GetLastWriteTimeUtc(fileName).Ticks.ToString(); } + static string GetOriginalAssemblyFullPath(Assembly asm) + { + if (asm == null) throw new ArgumentNullException("asm"); + try { + return new Uri(asm.CodeBase, UriKind.Absolute).LocalPath; + } catch (UriFormatException ex) { + LoggingService.Warn("Could not determine path for assembly '" + asm.ToString() + "', CodeBase='" + asm.CodeBase + "': " + ex.Message); + return asm.Location; + } catch (InvalidOperationException ex) { + LoggingService.Warn("Could not determine path for assembly '" + asm.ToString() + "', CodeBase='" + asm.CodeBase + "': " + ex.Message); + return asm.Location; + } + } + /// /// Loads the file in none-locking mode. Returns null on failure. /// - public static Assembly LoadAssembly(string fileName) + public Assembly LoadAssembly(string fileName) { if (!File.Exists(fileName)) return null; @@ -167,7 +187,7 @@ namespace ICSharpCode.FormsDesigner.Services // FIX for SD2-716, remove when designer gets its own AppDomain foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { try { - if (string.Equals(asm.Location, fileName, StringComparison.InvariantCultureIgnoreCase)) { + if (string.Equals(GetOriginalAssemblyFullPath(asm), fileName, StringComparison.OrdinalIgnoreCase)) { RegisterAssembly(asm); return asm; } @@ -257,17 +277,24 @@ namespace ICSharpCode.FormsDesigner.Services if (!designerAssemblies.Contains(asm)) designerAssemblies.Insert(0, asm); } + lock (this.loadedAssembliesForCurrentDocument) { + this.loadedAssembliesForCurrentDocument[fileName] = hash; + } assemblyDict[hash] = asm; return asm; } } - public static void RegisterAssembly(Assembly asm) + void RegisterAssembly(Assembly asm) { - string file = asm.Location; - if (file.Length > 0) { + string file = GetOriginalAssemblyFullPath(asm); + if (!String.IsNullOrEmpty(file)) { + string hash = GetHash(file); lock (assemblyDict) { - assemblyDict[GetHash(file)] = asm; + assemblyDict[hash] = asm; + } + lock (this.loadedAssembliesForCurrentDocument) { + this.loadedAssembliesForCurrentDocument[file] = hash; } } lock (designerAssemblies) { @@ -286,7 +313,7 @@ namespace ICSharpCode.FormsDesigner.Services return LoadAssembly(name, throwOnError); } - static Assembly LoadAssembly(AssemblyName name, bool throwOnError) + Assembly LoadAssembly(AssemblyName name, bool throwOnError) { try { Assembly asm = Assembly.Load(name); @@ -303,7 +330,7 @@ namespace ICSharpCode.FormsDesigner.Services { Assembly assembly = GetAssembly(name); if (assembly != null) { - return assembly.Location; + return GetOriginalAssemblyFullPath(assembly); } return null; } @@ -370,6 +397,12 @@ namespace ICSharpCode.FormsDesigner.Services LoggingService.Error(e); } if (assembly != null) { + string fileName = GetOriginalAssemblyFullPath(assembly); + if (!String.IsNullOrEmpty(fileName)) { + lock (this.loadedAssembliesForCurrentDocument) { + this.loadedAssembliesForCurrentDocument[fileName] = GetHash(fileName); + } + } lock (designerAssemblies) { if (!designerAssemblies.Contains(assembly)) designerAssemblies.Add(assembly); @@ -407,6 +440,18 @@ namespace ICSharpCode.FormsDesigner.Services ICSharpCode.Core.LoggingService.Warn("TODO: Add Assembly reference : " + name); } + /// + /// Gets whether an assembly referenced by the currently designed document + /// has been changed since it has been loaded. + /// + public bool ReferencedAssemblyChanged { + get { + return this.loadedAssembliesForCurrentDocument.Any( + pair => !File.Exists(pair.Key) || !String.Equals(pair.Value, GetHash(pair.Key), StringComparison.Ordinal) + ); + } + } + #region VSDesigner workarounds /// /// HACK - Ignore any requests for types from the Microsoft.VSDesigner diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/MyTypeFinder.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/MyTypeFinder.cs index 44a7855c86..69ea707f72 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/MyTypeFinder.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/MyTypeFinder.cs @@ -18,6 +18,7 @@ namespace ICSharpCode.WpfDesign.AddIn public class MyTypeFinder : XamlTypeFinder { OpenedFile file; + readonly TypeResolutionService typeResolutionService = new TypeResolutionService(); public static MyTypeFinder Create(OpenedFile file) { @@ -32,7 +33,7 @@ namespace ICSharpCode.WpfDesign.AddIn if (string.IsNullOrEmpty(name)) { IProjectContent pc = GetProjectContent(file); if (pc != null) { - return TypeResolutionService.LoadAssembly(pc); + return this.typeResolutionService.LoadAssembly(pc); } return null; } else { From 22cc95554049a77064885090b935bab0e396230e Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 11 Oct 2008 16:31:06 +0000 Subject: [PATCH 25/51] Fixed some minor bugs. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3596 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- data/templates/file/CSharp/CSharp.Struct.xft | 8 ++++---- .../Project/Src/CSharpCompletionBinding.cs | 5 ++--- .../Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs | 2 +- src/Main/Base/Test/CheckAssemblyFlags.cs | 4 ++-- .../Project/Src/NRefactoryResolver/ResolveVisitor.cs | 3 +-- src/prepareRelease.bat | 12 ------------ 6 files changed, 10 insertions(+), 24 deletions(-) delete mode 100644 src/prepareRelease.bat diff --git a/data/templates/file/CSharp/CSharp.Struct.xft b/data/templates/file/CSharp/CSharp.Struct.xft index 00f67a391c..8083411d91 100644 --- a/data/templates/file/CSharp/CSharp.Struct.xft +++ b/data/templates/file/CSharp/CSharp.Struct.xft @@ -57,14 +57,14 @@ namespace ${StandardNamespace} return member.GetHashCode(); } - public static bool operator ==(${ClassName} lhs, ${ClassName} rhs) + public static bool operator ==(${ClassName} left, ${ClassName} right) { - return lhs.Equals(rhs); + return left.Equals(right); } - public static bool operator !=(${ClassName} lhs, ${ClassName} rhs) + public static bool operator !=(${ClassName} left, ${ClassName} right) { - return !(lhs.Equals(rhs)); // use operator == and negate result + return !left.Equals(right); } #endregion } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs index 50302da7a4..e8fcc581fa 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs @@ -97,9 +97,8 @@ namespace CSharpBinding return true; } else if (ch == '>') { if (IsInComment(editor)) return false; - LineSegment segment = editor.Document.GetLineSegmentForOffset(editor.ActiveTextAreaControl.Caret.Offset); - TextWord sign = segment.GetWord(editor.ActiveTextAreaControl.Caret.Column - 1); - if (sign.Word == "-") { + char prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' '; + if (prevChar == '-') { editor.ShowCompletionWindow(new PointerArrowCompletionDataProvider(), ch); return true; diff --git a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs index e3440b6f7d..860ed1dfa0 100644 --- a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs +++ b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs @@ -542,7 +542,7 @@ namespace ICSharpCode.SharpDevelop.Gui { SdiWorkspaceWindow f = (SdiWorkspaceWindow)sender; f.CloseEvent -= CloseWindowEvent; - foreach (IViewContent vc in f.ViewContents) { + foreach (IViewContent vc in f.ViewContents.ToArray()) { ((IWorkbench)wbForm).CloseContent(vc); } if (f == oldSelectedWindow) { diff --git a/src/Main/Base/Test/CheckAssemblyFlags.cs b/src/Main/Base/Test/CheckAssemblyFlags.cs index 8d56ae8e45..2b5f60970c 100644 --- a/src/Main/Base/Test/CheckAssemblyFlags.cs +++ b/src/Main/Base/Test/CheckAssemblyFlags.cs @@ -25,8 +25,8 @@ namespace ICSharpCode.SharpDevelop.Tests string corflags = FileUtility.GetSdkPath("corflags.exe"); Assert.IsNotNull(corflags, "corflags.exe not found, this test requires the .NET SDK!"); ProcessRunner pr = new ProcessRunner(); - Console.WriteLine(corflags + " " + assembly); - pr.Start(corflags, assembly); + Console.WriteLine(corflags + " \"" + assembly + "\""); + pr.Start(corflags, "\"" + assembly + "\""); if (!pr.WaitForExit(5000)) { pr.Kill(); throw new InvalidOperationException("Timeout running corflags"); diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs index e4bb5ffac2..f75644f8f6 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs @@ -523,11 +523,10 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver public override object VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) { ResolveResult targetRR = Resolve(pointerReferenceExpression.TargetObject); - if (targetRR == null) + if (targetRR == null || targetRR.ResolvedType == null) return null; PointerReturnType type = targetRR.ResolvedType.CastToDecoratingReturnType(); if (type != null) { - TypeResolveResult typeRR = targetRR as TypeResolveResult; return resolver.ResolveMember(type.BaseType, pointerReferenceExpression.Identifier, pointerReferenceExpression.TypeArguments, NRefactoryResolver.IsInvoked(pointerReferenceExpression), diff --git a/src/prepareRelease.bat b/src/prepareRelease.bat deleted file mode 100644 index 678d618fb5..0000000000 --- a/src/prepareRelease.bat +++ /dev/null @@ -1,12 +0,0 @@ -rem Prepares a release by updating the changelog -pushd Tools -%windir%\microsoft.net\framework\v3.5\msbuild /t:PrepareRelease /property:Configuration=Release Tools.build -@popd -@IF %ERRORLEVEL% NEQ 0 PAUSE & EXIT -@echo. -@echo. -@echo. -@echo PrepareRelease.bat completed successfully. -@echo The change log has been updated and a REVISION file containing the current revision number has been created. -@echo. -@pause \ No newline at end of file From fef66a43e6a7e5966e5acb3e6d33b4653de9de3b Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 11 Oct 2008 16:38:58 +0000 Subject: [PATCH 26/51] Fixed exception opening StyleCop options when StyleCop is not installed git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3597 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/AnalysisProjectOptionsPanel.cs | 205 +++++++++--------- 1 file changed, 105 insertions(+), 100 deletions(-) diff --git a/src/AddIns/Misc/SourceAnalysis/Src/AnalysisProjectOptionsPanel.cs b/src/AddIns/Misc/SourceAnalysis/Src/AnalysisProjectOptionsPanel.cs index d6d0497668..bf89fb9c04 100644 --- a/src/AddIns/Misc/SourceAnalysis/Src/AnalysisProjectOptionsPanel.cs +++ b/src/AddIns/Misc/SourceAnalysis/Src/AnalysisProjectOptionsPanel.cs @@ -14,116 +14,121 @@ using ICSharpCode.SharpDevelop.Gui.OptionPanels; using ICSharpCode.SharpDevelop.Project; namespace MattEverson.SourceAnalysis { - public class AnalysisProjectOptionsPanel : AbstractProjectOptionPanel { + public class AnalysisProjectOptionsPanel : AbstractProjectOptionPanel { - public override void LoadPanelContents() { - InitializeHelper(); + public override void LoadPanelContents() { + InitializeHelper(); - var masterSettingsFile = helper.GetProperty("SourceAnalysisOverrideSettingsFile", "", true); - if (masterSettingsFile.Length == 0) { + var masterSettingsFile = helper.GetProperty("SourceAnalysisOverrideSettingsFile", "", true); + if (masterSettingsFile.Length == 0) { - helper.SetProperty("SourceAnalysisOverrideSettingsFile", - StyleCopWrapper.GetMasterSettingsFile(), - true, - PropertyStorageLocations.Base); - } + helper.SetProperty("SourceAnalysisOverrideSettingsFile", + StyleCopWrapper.GetMasterSettingsFile(), + true, + PropertyStorageLocations.Base); + } - AnalysisProjectOptions po = new AnalysisProjectOptions(); - po.Dock = DockStyle.Fill; - Controls.Add(po); + AnalysisProjectOptions po = new AnalysisProjectOptions(); + po.Dock = DockStyle.Fill; + Controls.Add(po); - ChooseStorageLocationButton btnEnable; - ChooseStorageLocationButton btnFileLocation; - btnEnable = helper.BindBoolean(po.EnableCheckBox, "RunSourceAnalysis", false).CreateLocationButton(po.EnableCheckBox); - btnFileLocation = helper.BindString(po.SettingsFileTextBox, "SourceAnalysisOverrideSettingsFile", TextBoxEditMode.EditRawProperty).CreateLocationButton(po.SettingsFileTextBox); - ConfigurationGuiBinding binding = po.CreateBinding(); - binding.RegisterLocationButton(btnEnable); - binding.RegisterLocationButton(btnFileLocation); + ChooseStorageLocationButton btnEnable; + ChooseStorageLocationButton btnFileLocation; + btnEnable = helper.BindBoolean(po.EnableCheckBox, "RunSourceAnalysis", false).CreateLocationButton(po.EnableCheckBox); + btnFileLocation = helper.BindString(po.SettingsFileTextBox, "SourceAnalysisOverrideSettingsFile", TextBoxEditMode.EditRawProperty).CreateLocationButton(po.SettingsFileTextBox); + ConfigurationGuiBinding binding = po.CreateBinding(); + binding.RegisterLocationButton(btnEnable); + binding.RegisterLocationButton(btnFileLocation); - helper.AddConfigurationSelector(this); + helper.AddConfigurationSelector(this); - po.ModifyStyleCopSettingsButton.Click += ModifyStyleCopSettingsClick; - } + po.ModifyStyleCopSettingsButton.Click += ModifyStyleCopSettingsClick; + } - void ModifyStyleCopSettingsClick(object sender, EventArgs e) { - var settingsFile = helper.GetProperty("SourceAnalysisOverrideSettingsFile", "", true); - - if (settingsFile == StyleCopWrapper.GetMasterSettingsFile()) { - if (ConfirmSwitchFromMaster()) { - settingsFile = CopyFromMaster(); - } - } + void ModifyStyleCopSettingsClick(object sender, EventArgs e) { + var settingsFile = helper.GetProperty("SourceAnalysisOverrideSettingsFile", "", true); + + if (settingsFile == StyleCopWrapper.GetMasterSettingsFile()) { + if (ConfirmSwitchFromMaster()) { + settingsFile = CopyFromMaster(); + } + } - if (!System.IO.File.Exists(settingsFile)) { - if (ConfirmReplaceMissingFile()) { - settingsFile = CopyFromMaster(); - } - else { - MessageService.ShowWarning("No settings file found to modify."); - return; - } - } + if (!System.IO.File.Exists(settingsFile)) { + if (ConfirmReplaceMissingFile()) { + settingsFile = CopyFromMaster(); + } + else { + MessageService.ShowWarning("No settings file found to modify."); + return; + } + } - var executable = Path.Combine(StyleCopWrapper.FindStyleCopPath(), "StyleCopSettingsEditor.exe"); - var parameters = "\"" + settingsFile + "\""; - if (!File.Exists(executable)) { - LoggingService.Debug("StyleCopSettingsEditor.exe: " + executable); - MessageService.ShowWarning("Unable to find the StyleCop Settings editor. Please specify the StyleCop location in Tools Options."); - return; - } - - using(Process p = Process.Start("\"" + executable + "\"", parameters)) { - // No need to wait for the settings dialog to close - we can leave it open. - } - } + string styleCopPath = StyleCopWrapper.FindStyleCopPath(); + string executable; + if (styleCopPath != null) + executable = Path.Combine(styleCopPath, "StyleCopSettingsEditor.exe"); + else + executable = null; + string parameters = "\"" + settingsFile + "\""; + if (!File.Exists(executable)) { + LoggingService.Debug("StyleCopSettingsEditor.exe: " + executable); + MessageService.ShowWarning("Unable to find the StyleCop Settings editor. Please specify the StyleCop location in Tools Options."); + return; + } + + using(Process p = Process.Start("\"" + executable + "\"", parameters)) { + // No need to wait for the settings dialog to close - we can leave it open. + } + } - private bool ConfirmReplaceMissingFile() { - var result = MessageBox.Show("A settings file is not present. Would you like to copy the master into the " + - "project folder?", - "Missing Settings File", - MessageBoxButtons.YesNo, - MessageBoxIcon.Exclamation, - MessageBoxDefaultButton.Button1 - ); - if (result == DialogResult.Yes) { - return true; - } else { - return false; - } - } - - private bool ConfirmSwitchFromMaster() - { - var result = MessageBox.Show("You are currently using the master settings file. Do you want to make a " - + "copy in the project folder instead?", - "Using Master Settings File", - MessageBoxButtons.YesNo, - MessageBoxIcon.Exclamation, - MessageBoxDefaultButton.Button1 - ); - if (result == DialogResult.Yes) - { - return true; - } - else - { - return false; - } - } + private bool ConfirmReplaceMissingFile() { + var result = MessageBox.Show("A settings file is not present. Would you like to copy the master into the " + + "project folder?", + "Missing Settings File", + MessageBoxButtons.YesNo, + MessageBoxIcon.Exclamation, + MessageBoxDefaultButton.Button1 + ); + if (result == DialogResult.Yes) { + return true; + } else { + return false; + } + } + + private bool ConfirmSwitchFromMaster() + { + var result = MessageBox.Show("You are currently using the master settings file. Do you want to make a " + + "copy in the project folder instead?", + "Using Master Settings File", + MessageBoxButtons.YesNo, + MessageBoxIcon.Exclamation, + MessageBoxDefaultButton.Button1 + ); + if (result == DialogResult.Yes) + { + return true; + } + else + { + return false; + } + } - private string CopyFromMaster() { - var newSettingsFile = helper.Project.Directory + "\\Settings.SourceAnalysis"; - System.IO.File.Copy( - StyleCopWrapper.GetMasterSettingsFile(), - newSettingsFile, - true - ); - helper.SetProperty("SourceAnalysisOverrideSettingsFile", - newSettingsFile, - true, - PropertyStorageLocations.Base - ); - return newSettingsFile; - } - } + private string CopyFromMaster() { + var newSettingsFile = helper.Project.Directory + "\\Settings.SourceAnalysis"; + System.IO.File.Copy( + StyleCopWrapper.GetMasterSettingsFile(), + newSettingsFile, + true + ); + helper.SetProperty("SourceAnalysisOverrideSettingsFile", + newSettingsFile, + true, + PropertyStorageLocations.Base + ); + return newSettingsFile; + } + } } From 55a20e60263ba6e5908ea99f57e91132d3669285 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 11 Oct 2008 16:45:25 +0000 Subject: [PATCH 27/51] Fixed NullReferenceException in TaskListPad.IsInScope git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3598 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/Gui/Pads/TaskList/TaskListPad.cs | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs b/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs index ae5ffaafa0..c8028c7e35 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs @@ -156,7 +156,7 @@ namespace ICSharpCode.SharpDevelop.Gui } public void UpdateItems() - { + { this.taskView.BeginUpdate(); this.taskView.ClearTasks(); @@ -182,22 +182,23 @@ namespace ICSharpCode.SharpDevelop.Gui IClass current = GetCurrentClass(); IClass itemClass = GetCurrentClass(item); - switch (this.selectedScopeIndex) - { + switch (this.selectedScopeIndex) { case 0: - foreach (AbstractProject proj in ProjectService.OpenSolution.Projects) - if (proj.FindFile(item.FileName) != null) - return true; - + if (ProjectService.OpenSolution != null) { + foreach (AbstractProject proj in ProjectService.OpenSolution.Projects) { + if (proj.FindFile(item.FileName) != null) + return true; + } + } return false; case 1: - return ((WorkbenchSingleton.Workbench.ActiveViewContent != null) && (ProjectService.CurrentProject.FindFile(item.FileName) != null)); + return ProjectService.CurrentProject != null && ProjectService.CurrentProject.FindFile(item.FileName) != null; case 2: - return ((WorkbenchSingleton.Workbench.ActiveViewContent != null) && (WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName == item.FileName)); + return WorkbenchSingleton.Workbench.ActiveViewContent != null && WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName == item.FileName; case 3: - return ((current != null) && (itemClass != null) && (current.Namespace == itemClass.Namespace)); + return current != null && itemClass != null && current.Namespace == itemClass.Namespace; case 4: - return ((current != null) && (itemClass != null) && (current == itemClass)); + return current != null && itemClass != null && current == itemClass; } return true; @@ -210,10 +211,9 @@ namespace ICSharpCode.SharpDevelop.Gui ParseInformation parseInfo = ParserService.GetParseInformation(WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName); if (parseInfo != null) { - if (WorkbenchSingleton.Workbench.ActiveViewContent.Control is ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.SharpDevelopTextAreaControl) - {SharpDevelopTextAreaControl ctrl = WorkbenchSingleton.Workbench.ActiveViewContent.Control - as SharpDevelopTextAreaControl; - IClass c = parseInfo.MostRecentCompilationUnit.GetInnermostClass(ctrl.ActiveTextAreaControl.Caret.Line, ctrl.ActiveTextAreaControl.Caret.Column); + IPositionable positionable = WorkbenchSingleton.Workbench.ActiveViewContent as IPositionable; + if (positionable != null) { + IClass c = parseInfo.MostRecentCompilationUnit.GetInnermostClass(positionable.Line, positionable.Column); if (c != null) return c; } } From 7efa7d9571ce5a1adff9d54130066ac3315aba1f Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 12 Oct 2008 14:42:14 +0000 Subject: [PATCH 28/51] Fixed null reference exception that could occur if the TextBoxTextChanged event was fired before the XmlTreeEditor was created. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3599 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/XmlTreeViewContainerControl.cs | 8 +++-- ...extChangedBeforeEditorLoadedTestFixture.cs | 33 +++++++++++++++++++ .../XmlEditor/Test/XmlEditor.Tests.csproj | 1 + 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 src/AddIns/DisplayBindings/XmlEditor/Test/Tree/TextBoxTextChangedBeforeEditorLoadedTestFixture.cs diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs index 4275bb841e..820eebe6f0 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs @@ -808,9 +808,11 @@ namespace ICSharpCode.XmlEditor /// protected void TextBoxTextChanged(object sender, EventArgs e) { - bool previousIsDirty = dirty; - editor.TextContentChanged(); - OnXmlChanged(previousIsDirty); + if (editor != null) { + bool previousIsDirty = dirty; + editor.TextContentChanged(); + OnXmlChanged(previousIsDirty); + } } /// diff --git a/src/AddIns/DisplayBindings/XmlEditor/Test/Tree/TextBoxTextChangedBeforeEditorLoadedTestFixture.cs b/src/AddIns/DisplayBindings/XmlEditor/Test/Tree/TextBoxTextChangedBeforeEditorLoadedTestFixture.cs new file mode 100644 index 0000000000..2488e1b1b2 --- /dev/null +++ b/src/AddIns/DisplayBindings/XmlEditor/Test/Tree/TextBoxTextChangedBeforeEditorLoadedTestFixture.cs @@ -0,0 +1,33 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Windows.Forms; +using System.Xml; + +using ICSharpCode.Core; +using ICSharpCode.XmlEditor; +using NUnit.Framework; +using XmlEditor.Tests.Utils; + +namespace XmlEditor.Tests.Tree +{ + /// + /// Fixes a null exception that could occur if the TextBoxTextChanged event is fired before the + /// XmlTreeEditor is created. + /// + [TestFixture] + public class TextBoxTextChangedBeforeEditorLoadedTestFixture + { + [Test] + public void FireTextBoxTextChangedEventBeforeXmlTreeEditorCreated() + { + DerivedXmlTreeViewContainerControl treeViewContainer = new DerivedXmlTreeViewContainerControl(); + treeViewContainer.CallTextBoxTextChanged(); + } + } +} diff --git a/src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj b/src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj index 8ebcff94b7..425c16def0 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj +++ b/src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj @@ -90,6 +90,7 @@ + From b982652de520d886f9e42ef5bd13f85bb35c1bbd Mon Sep 17 00:00:00 2001 From: Christian Hornung Date: Tue, 14 Oct 2008 15:41:36 +0000 Subject: [PATCH 29/51] Add unit tests for ClassInheritanceTree, including failing (ignored) test that shows the cause of SD2-1474. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3600 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../ClassInheritanceTreeTests.cs | 121 ++++++++++++++++++ .../ICSharpCode.SharpDevelop.Dom.Tests.csproj | 1 + 2 files changed, 122 insertions(+) create mode 100644 src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ClassInheritanceTreeTests.cs diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ClassInheritanceTreeTests.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ClassInheritanceTreeTests.cs new file mode 100644 index 0000000000..c247f3895c --- /dev/null +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ClassInheritanceTreeTests.cs @@ -0,0 +1,121 @@ +// +// +// +// +// $Revision$ +// + +using System; + +using ICSharpCode.SharpDevelop.Tests; + +using NUnit.Framework; +using NUnit.Framework.SyntaxHelpers; + +namespace ICSharpCode.SharpDevelop.Dom.Tests +{ + [TestFixture] + public sealed class ClassInheritanceTreeTests + { + #region Test helper methods + + readonly NRefactoryResolverTests helper = new NRefactoryResolverTests(); + ICompilationUnit cu; + IClass objectClass, baseClass, derivedClass; + + void Prepare(string code, string baseClassName, string derivedClassName) + { + cu = helper.Parse("a.cs", code); + + objectClass = cu.ProjectContent.GetClass("System.Object", 0); + Assert.That(objectClass, Is.Not.Null, "Could not find class for System.Object in project content."); + + baseClass = cu.ProjectContent.GetClass(baseClassName, 0); + Assert.That(baseClass, Is.Not.Null, "Could not find class for '" + baseClassName + "' in project content."); + + derivedClass = cu.ProjectContent.GetClass(derivedClassName, 0); + Assert.That(derivedClass, Is.Not.Null, "Could not find class for '" + derivedClassName + "' in project content."); + } + + void CheckDerivedClassInheritanceTree() + { + Assert.That(derivedClass.ClassInheritanceTree, Is.EqualTo( + new [] {derivedClass, baseClass, objectClass} + )); + } + + #endregion + + const string CodeSameNamespace = @" +namespace A { + class Base { + } + class Derived : Base { + } +} +"; + + [Test] + public void DerivedClassInheritanceTreeSameNamespace() + { + Prepare(CodeSameNamespace, "A.Base", "A.Derived"); + CheckDerivedClassInheritanceTree(); + } + + [Test] + public void DerivedClassInheritanceTreeAfterGetFullyQualifiedNameSameNamespace() + { + Prepare(CodeSameNamespace, "A.Base", "A.Derived"); + Assert.That(baseClass.FullyQualifiedName, Is.EqualTo("A.Base")); + Assert.That(derivedClass.FullyQualifiedName, Is.EqualTo("A.Derived")); + CheckDerivedClassInheritanceTree(); + } + + [Test] + public void DerivedClassInheritanceTreeAfterCheckBaseTypesSameNamespace() + { + Prepare(CodeSameNamespace, "A.Base", "A.Derived"); + Assert.That(derivedClass.BaseTypes, Is.EquivalentTo(new [] {baseClass.DefaultReturnType})); + CheckDerivedClassInheritanceTree(); + } + + + + const string CodeDifferentNamespaceUsing = @" +namespace A { + class Base { + } +} +namespace B { + using A; + class Derived : Base { + } +} +"; + + [Test] + public void DerivedClassInheritanceTreeDifferentNamespaceUsing() + { + Prepare(CodeDifferentNamespaceUsing, "A.Base", "B.Derived"); + CheckDerivedClassInheritanceTree(); + } + + [Test] + public void DerivedClassInheritanceTreeAfterGetFullyQualifiedNameDifferentNamespaceUsing() + { + Prepare(CodeDifferentNamespaceUsing, "A.Base", "B.Derived"); + Assert.That(baseClass.FullyQualifiedName, Is.EqualTo("A.Base")); + Assert.That(derivedClass.FullyQualifiedName, Is.EqualTo("B.Derived")); + CheckDerivedClassInheritanceTree(); + } + + [Test] + [Ignore("Bugfix needed (this is the cause for SD2-1474).")] + public void DerivedClassInheritanceTreeAfterCheckBaseTypesDifferentNamespaceUsing() + { + Prepare(CodeDifferentNamespaceUsing, "A.Base", "B.Derived"); + Assert.That(derivedClass.BaseTypes, Is.EquivalentTo(new [] {baseClass.DefaultReturnType})); + CheckDerivedClassInheritanceTree(); + } + } +} diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj index 8393922042..2507bd1ae7 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ICSharpCode.SharpDevelop.Dom.Tests.csproj @@ -44,6 +44,7 @@ + From 1850c9362d0f60c9b56056891e1faad621c1a07a Mon Sep 17 00:00:00 2001 From: Christian Hornung Date: Wed, 15 Oct 2008 14:57:27 +0000 Subject: [PATCH 30/51] Fixed SD2-1471 (Renaming MainForm event handler does not update MainForm.Designer file) by adding IFileDocumentProvider as a generalization of ITextEditorControlProvider to properly support view contents that open multiple documents. Adaptations to ParserService and ParseableFileContentEnumerator to make sure they always use the most recent version of the file content. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3601 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Test/Utils/MockTextEditorViewContent.cs | 7 +++ .../Test/Utils/MockTextEditorViewContent.cs | 7 +++ .../AbstractDesignerGenerator.cs | 8 +-- .../Project/Src/DesignerViewContent.cs | 13 ++++- .../XmlEditor/Project/Src/XmlView.cs | 10 ++++ .../Project/ICSharpCode.SharpDevelop.csproj | 1 + .../Project/Src/Services/File/FileService.cs | 4 ++ .../Services/ParserService/ParserService.cs | 10 ++++ .../ParseableFileContentEnumerator.cs | 30 +++++++++++ .../FindReferencesAndRenameHelper.cs | 53 +++++++++++-------- .../Gui/Editor/IFileDocumentProvider.cs | 27 ++++++++++ .../Gui/Editor/ITextAreaControlProvider.cs | 2 +- .../Gui/Editor/TextEditorBasedPad.cs | 6 +++ .../Gui/Editor/TextEditorDisplayBinding.cs | 9 ++++ 14 files changed, 156 insertions(+), 31 deletions(-) create mode 100644 src/Main/Base/Project/Src/TextEditor/Gui/Editor/IFileDocumentProvider.cs diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockTextEditorViewContent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockTextEditorViewContent.cs index 9fa8c3aeaf..e4401dfb92 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockTextEditorViewContent.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockTextEditorViewContent.cs @@ -6,8 +6,10 @@ // using System; +using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.TextEditor; +using ICSharpCode.TextEditor.Document; namespace PythonBinding.Tests.Utils { @@ -27,5 +29,10 @@ namespace PythonBinding.Tests.Utils public TextEditorControl TextEditorControl { get { return textEditor; } } + + public IDocument GetDocumentForFile(OpenedFile file) + { + throw new NotImplementedException(); + } } } diff --git a/src/AddIns/BackendBindings/WixBinding/Test/Utils/MockTextEditorViewContent.cs b/src/AddIns/BackendBindings/WixBinding/Test/Utils/MockTextEditorViewContent.cs index 0b4699f30c..08ca2e515b 100644 --- a/src/AddIns/BackendBindings/WixBinding/Test/Utils/MockTextEditorViewContent.cs +++ b/src/AddIns/BackendBindings/WixBinding/Test/Utils/MockTextEditorViewContent.cs @@ -6,9 +6,11 @@ // using ICSharpCode.Core; +using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.TextEditor; +using ICSharpCode.TextEditor.Document; using System; using System.Collections.Generic; using System.Windows.Forms; @@ -31,6 +33,11 @@ namespace WixBinding.Tests.Utils return null; } } + + public IDocument GetDocumentForFile(OpenedFile file) + { + return null; + } #endregion } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs index 9912eb44c1..073753fa25 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs @@ -192,13 +192,7 @@ namespace ICSharpCode.FormsDesigner if (formClass.Name != this.formClass.Name) { LoggingService.Info("Renaming form to " + formClass.Name); - Dictionary providedFileDocuments = new Dictionary(); - providedFileDocuments.Add(this.ViewContent.DesignerCodeFile.FileName, this.ViewContent.DesignerCodeFileDocument); - if (!this.ViewContent.PrimaryFile.Equals(this.ViewContent.DesignerCodeFile)) { - System.Diagnostics.Debug.Assert(!this.ViewContent.DesignerCodeFileDocument.Equals(this.ViewContent.PrimaryFileDocument)); - providedFileDocuments.Add(this.ViewContent.PrimaryFileName, this.ViewContent.PrimaryFileDocument); - } - ICSharpCode.SharpDevelop.Refactoring.FindReferencesAndRenameHelper.RenameClass(this.formClass, formClass.Name, providedFileDocuments); + ICSharpCode.SharpDevelop.Refactoring.FindReferencesAndRenameHelper.RenameClass(this.formClass, formClass.Name); this.ViewContent.DesignerCodeFile.MakeDirty(); this.ViewContent.PrimaryFile.MakeDirty(); Reparse(); diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs index 241a8f2691..c841df9f4e 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs @@ -27,7 +27,7 @@ using ICSharpCode.TextEditor.Util; namespace ICSharpCode.FormsDesigner { - public class FormsDesignerViewContent : AbstractViewContentHandlingLoadErrors, IClipboardHandler, IUndoHandler, IHasPropertyContainer, IContextHelpProvider, IToolsHost + public class FormsDesignerViewContent : AbstractViewContentHandlingLoadErrors, IClipboardHandler, IUndoHandler, IHasPropertyContainer, IContextHelpProvider, IToolsHost, IFileDocumentProvider { readonly Control pleaseWaitLabel = new Label() {Text=StringParser.Parse("${res:Global.PleaseWait}"), TextAlign=ContentAlignment.MiddleCenter}; DesignSurface designSurface; @@ -93,6 +93,17 @@ namespace ICSharpCode.FormsDesigner get { return this.designerCodeFileEncoding; } } + public IDocument GetDocumentForFile(OpenedFile file) + { + if (file == this.DesignerCodeFile) { + return this.DesignerCodeFileDocument; + } else if (file == this.PrimaryFile) { + return this.PrimaryFileDocument; + } else { + return null; + } + } + public IViewContent PrimaryViewContent { get { return this.primaryViewContent; } } diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs index 1d29cc6fa5..a46ffbab7b 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs @@ -699,6 +699,16 @@ namespace ICSharpCode.XmlEditor return xmlEditor; } } + + public IDocument GetDocumentForFile(OpenedFile file) + { + if (file == this.PrimaryFile) { + return this.TextEditorControl.Document; + } else { + return null; + } + } + #endregion #region IPositionable interface diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index df1f92ca4a..8d5bf9644d 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -511,6 +511,7 @@ + diff --git a/src/Main/Base/Project/Src/Services/File/FileService.cs b/src/Main/Base/Project/Src/Services/File/FileService.cs index 11a197a288..64c28c0d92 100644 --- a/src/Main/Base/Project/Src/Services/File/FileService.cs +++ b/src/Main/Base/Project/Src/Services/File/FileService.cs @@ -295,6 +295,10 @@ namespace ICSharpCode.SharpDevelop } } + /// + /// Gets a list of the names of the files that are open as primary files + /// in view contents. + /// public static IList GetOpenFiles() { List fileNames = new List(); diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 5337f2dee1..ca878a1fc3 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -14,9 +14,11 @@ using System.Text; using System.Threading; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.TextEditor.Document; using RegistryContentPair = System.Collections.Generic.KeyValuePair; @@ -638,6 +640,14 @@ namespace ICSharpCode.SharpDevelop OpenedFile file = FileService.GetOpenedFile(fileName); if (file != null) { + IFileDocumentProvider p = file.CurrentView as IFileDocumentProvider; + if (p != null) { + IDocument document = p.GetDocumentForFile(file); + if (document != null) { + return document.TextContent; + } + } + using(Stream s = file.OpenRead()) { // load file Encoding encoding = DefaultFileEncoding; diff --git a/src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentEnumerator.cs b/src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentEnumerator.cs index 63ed5023eb..71c05b13c0 100644 --- a/src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentEnumerator.cs +++ b/src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentEnumerator.cs @@ -12,7 +12,9 @@ using System.IO; using System.Text; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.TextEditor.Document; namespace ICSharpCode.SharpDevelop.Project { @@ -83,6 +85,25 @@ namespace ICSharpCode.SharpDevelop.Project // Loading the source files is done asynchronously: // While one file is parsed, the next is already loaded from disk. + // Load file from memory if it is open + OpenedFile file = FileService.GetOpenedFile(fileName); + if (file != null) { + string content; + if (isOnMainThread) { + content = GetFileContentFromFileDocumentProvider(file); + } else { + content = WorkbenchSingleton.SafeThreadFunction(GetFileContentFromFileDocumentProvider, file); + } + if (content != null) { + return content; + } + + using(Stream s = file.OpenRead()) { + Encoding encoding = defaultEncoding; + return ICSharpCode.TextEditor.Util.FileReader.ReadFileContent(s, ref encoding); + } + } + // load file return ICSharpCode.TextEditor.Util.FileReader.ReadFileContent(fileName, defaultEncoding); } @@ -165,5 +186,14 @@ namespace ICSharpCode.SharpDevelop.Project } return null; } + + static string GetFileContentFromFileDocumentProvider(OpenedFile file) + { + IFileDocumentProvider p = file.CurrentView as IFileDocumentProvider; + if (p == null) return null; + IDocument document = p.GetDocumentForFile(file); + if (document == null) return null; + return document.TextContent; + } } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs index 4df66c0bae..638b7e66e8 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs @@ -131,11 +131,6 @@ namespace ICSharpCode.SharpDevelop.Refactoring } public static void RenameClass(IClass c, string newName) - { - RenameClass(c, newName, null); - } - - public static void RenameClass(IClass c, string newName, IDictionary providedFileDocuments) { c = c.GetCompoundClass(); // get compound class if class is partial @@ -154,7 +149,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring } } - FindReferencesAndRenameHelper.RenameReferences(list, newName, providedFileDocuments); + FindReferencesAndRenameHelper.RenameReferences(list, newName); } static IList GetClassParts(IClass c) @@ -369,25 +364,36 @@ namespace ICSharpCode.SharpDevelop.Refactoring SearchResultPanel.Instance.ShowSearchResults(new SearchResult(pattern, results)); } - public static void RenameReferences(List list, string newName) - { - RenameReferences(list, newName, null); + sealed class FileView { + public IViewContent ViewContent { get; set; } + public OpenedFile OpenedFile { get; set; } } - public static void RenameReferences(List list, string newName, IDictionary providedFileDocuments) + public static void RenameReferences(List list, string newName) { - Dictionary modifiedDocuments = new Dictionary(); + Dictionary modifiedDocuments = new Dictionary(); List modifications = new List(); foreach (Reference r in list) { - ICSharpCode.TextEditor.Document.IDocument document; - IViewContent viewContent; + ICSharpCode.TextEditor.Document.IDocument document = null; + IViewContent viewContent = null; - if (providedFileDocuments == null || !providedFileDocuments.TryGetValue(FileUtility.NormalizePath(r.FileName), out document)) { + OpenedFile file = FileService.GetOpenedFile(r.FileName); + if (file != null) { + viewContent = file.CurrentView; + IFileDocumentProvider p = viewContent as IFileDocumentProvider; + if (p != null) { + document = p.GetDocumentForFile(file); + } + } + + if (document == null) { viewContent = FileService.OpenFile(r.FileName, false); - ITextEditorControlProvider p = viewContent as ITextEditorControlProvider; - document = (p == null) ? null : p.TextEditorControl.Document; - } else { - viewContent = null; + IFileDocumentProvider p = viewContent as IFileDocumentProvider; + if (p != null) { + file = FileService.GetOpenedFile(r.FileName); + System.Diagnostics.Debug.Assert(file != null, "OpenedFile not found after opening the file."); + document = p.GetDocumentForFile(file); + } } if (document == null) { @@ -396,16 +402,19 @@ namespace ICSharpCode.SharpDevelop.Refactoring } if (!modifiedDocuments.ContainsKey(document)) { - modifiedDocuments.Add(document, viewContent); + modifiedDocuments.Add(document, new FileView() {ViewContent = viewContent, OpenedFile = file}); document.UndoStack.StartUndoGroup(); } ModifyDocument(modifications, document, r.Offset, r.Length, newName); } - foreach (KeyValuePair entry in modifiedDocuments) { + foreach (KeyValuePair entry in modifiedDocuments) { entry.Key.UndoStack.EndUndoGroup(); - if (entry.Value != null) { - ParserService.ParseViewContent(entry.Value); + entry.Value.OpenedFile.MakeDirty(); + if (entry.Value.ViewContent is IEditable) { + ParserService.ParseViewContent(entry.Value.ViewContent); + } else { + ParserService.ParseFile(entry.Value.OpenedFile.FileName, entry.Key.TextContent, !entry.Value.OpenedFile.IsUntitled); } } } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/IFileDocumentProvider.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/IFileDocumentProvider.cs new file mode 100644 index 0000000000..e97b1ca8a3 --- /dev/null +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/IFileDocumentProvider.cs @@ -0,0 +1,27 @@ +// +// +// +// +// $Revision$ +// + +using System; + +using ICSharpCode.TextEditor.Document; + +namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor +{ + /// + /// Interface for view contents that provide a text editor document + /// for one or more s. + /// + public interface IFileDocumentProvider + { + /// + /// Gets the edited document for the specified file. + /// + /// The to get the document for. + /// The edited document for the specified file, or null if this view does not provide a document for the specified file. + IDocument GetDocumentForFile(OpenedFile file); + } +} diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ITextAreaControlProvider.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ITextAreaControlProvider.cs index 93dec18a90..4a664f297b 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ITextAreaControlProvider.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/ITextAreaControlProvider.cs @@ -10,7 +10,7 @@ using ICSharpCode.TextEditor; namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor { - public interface ITextEditorControlProvider + public interface ITextEditorControlProvider : IFileDocumentProvider { TextEditorControl TextEditorControl { get; diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorBasedPad.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorBasedPad.cs index 60d096c51b..7d02a61520 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorBasedPad.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorBasedPad.cs @@ -11,6 +11,7 @@ using System.Windows.Forms; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.TextEditor; +using ICSharpCode.TextEditor.Document; namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor { @@ -64,6 +65,11 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } + public virtual IDocument GetDocumentForFile(OpenedFile file) + { + return null; + } + PrintDocument IPrintable.PrintDocument { get { return this.TextEditorControl.PrintDocument; 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 edda2c2d1b..ff8a0e0cca 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs @@ -78,6 +78,15 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } } + public IDocument GetDocumentForFile(OpenedFile file) + { + if (file == this.PrimaryFile) { + return this.TextEditorControl.Document; + } else { + return null; + } + } + public bool EnableUndo { get { return textEditorControl.EnableUndo; From cd400c7cc03a2b4258b93c6203f2a0ee978259fc Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 15 Oct 2008 17:40:39 +0000 Subject: [PATCH 31/51] Fixed SD2-1474 (ClassInheritanceTree returns incorrect results) git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3602 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/Implementations/DefaultClass.cs | 17 ++++++++++++++--- .../ClassInheritanceTreeTests.cs | 1 - 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs index ba22beb063..05b2e505d7 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultClass.cs @@ -358,6 +358,7 @@ namespace ICSharpCode.SharpDevelop.Dom visitedList = new List(); Queue typesToVisit = new Queue(); bool enqueuedLastBaseType = false; + bool hasErrors = false; IClass currentClass = this; IReturnType nextType; do { @@ -377,11 +378,21 @@ namespace ICSharpCode.SharpDevelop.Dom } if (nextType != null) { currentClass = nextType.GetUnderlyingClass(); + if (currentClass == null) + hasErrors = true; } } while (nextType != null); - inheritanceTreeCache = visitedList; - if (!KeepInheritanceTree) - DomCache.RegisterForClear(delegate { inheritanceTreeCache = null; }); + + + // A SearchType request causes the inheritance tree to be generated, but if it was + // this classes' base type that caused the SearchType request, the GetUnderlyingClass() + // will fail and we will produce an incomplete inheritance tree. + // So we don't cache incomplete inheritance trees for parsed classes (fixes SD2-1474). + if (!hasErrors || KeepInheritanceTree) { + inheritanceTreeCache = visitedList; + if (!KeepInheritanceTree) + DomCache.RegisterForClear(delegate { inheritanceTreeCache = null; }); + } return visitedList; } } diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ClassInheritanceTreeTests.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ClassInheritanceTreeTests.cs index c247f3895c..4a2e3e8342 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ClassInheritanceTreeTests.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/ClassInheritanceTreeTests.cs @@ -110,7 +110,6 @@ namespace B { } [Test] - [Ignore("Bugfix needed (this is the cause for SD2-1474).")] public void DerivedClassInheritanceTreeAfterCheckBaseTypesDifferentNamespaceUsing() { Prepare(CodeDifferentNamespaceUsing, "A.Base", "B.Derived"); From d2f3fac28cebf9eb8967fce1f882002737f30b54 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 18 Oct 2008 14:12:11 +0000 Subject: [PATCH 32/51] Mark HistoryView as IsViewOnly git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3603 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/Gui/HistoryViewDisplayBinding/HistoryView.cs | 4 ++++ src/Main/Base/Project/Src/Services/File/OpenedFile.cs | 1 + 2 files changed, 5 insertions(+) diff --git a/src/AddIns/Misc/SubversionAddIn/Project/Src/Gui/HistoryViewDisplayBinding/HistoryView.cs b/src/AddIns/Misc/SubversionAddIn/Project/Src/Gui/HistoryViewDisplayBinding/HistoryView.cs index c999c8b2b3..c4598d5d8c 100644 --- a/src/AddIns/Misc/SubversionAddIn/Project/Src/Gui/HistoryViewDisplayBinding/HistoryView.cs +++ b/src/AddIns/Misc/SubversionAddIn/Project/Src/Gui/HistoryViewDisplayBinding/HistoryView.cs @@ -33,5 +33,9 @@ namespace ICSharpCode.Svn protected override void SaveToPrimary() { } + + public override bool IsViewOnly { + get { return true; } + } } } diff --git a/src/Main/Base/Project/Src/Services/File/OpenedFile.cs b/src/Main/Base/Project/Src/Services/File/OpenedFile.cs index 6e33d74d0b..79f9fb73be 100644 --- a/src/Main/Base/Project/Src/Services/File/OpenedFile.cs +++ b/src/Main/Base/Project/Src/Services/File/OpenedFile.cs @@ -203,6 +203,7 @@ namespace ICSharpCode.SharpDevelop if (IsUntitled) throw new InvalidOperationException("Cannot save an untitled file to disk!"); + LoggingService.Debug("Save " + FileName); bool safeSaving = FileService.SaveUsingTemporaryFile && File.Exists(FileName); string saveAs = safeSaving ? FileName + ".bak" : FileName; using (FileStream fs = new FileStream(saveAs, FileMode.Create, FileAccess.Write)) { From 17a10b74b61921254e55e4b14af953c4af69705c Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 18 Oct 2008 14:35:16 +0000 Subject: [PATCH 33/51] Make FileChangeWatcher reload a file not only when there were external writes to the file, but also when the file was replaced by an external app. Fixes reloading the file when doing "svn revert". git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3604 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/Gui/WorkbenchSingleton.cs | 21 ++++++++++++++ .../Src/Services/File/FileChangeWatcher.cs | 28 +++++++++++-------- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs b/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs index e273590a4b..2a6f0264e1 100644 --- a/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs +++ b/src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs @@ -311,6 +311,27 @@ namespace ICSharpCode.SharpDevelop.Gui { caller.BeginCall(method, new object[] { arg1, arg2, arg3 }); } + + /// + /// Calls a method on the GUI thread, but delays the call a bit. + /// + public static void CallLater(int delayMilliseconds, Action method) + { + if (delayMilliseconds <= 0) + throw new ArgumentOutOfRangeException("delayMilliseconds", delayMilliseconds, "Value must be positive"); + if (method == null) + throw new ArgumentNullException("method"); + SafeThreadAsyncCall( + delegate { + Timer t = new Timer(); + t.Interval = delayMilliseconds; + t.Tick += delegate { + t.Stop(); + method(); + }; + t.Start(); + }); + } #endregion static void OnWorkbenchCreated() diff --git a/src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs b/src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs index e8ecd1ea45..66eac96cb0 100644 --- a/src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs +++ b/src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs @@ -80,8 +80,8 @@ namespace ICSharpCode.SharpDevelop public bool Enabled { get { return enabled; } - set { - enabled = value; + set { + enabled = value; SetWatcher(); } } @@ -111,11 +111,12 @@ namespace ICSharpCode.SharpDevelop if (watcher == null) { watcher = new FileSystemWatcher(); watcher.SynchronizingObject = WorkbenchSingleton.MainForm; - watcher.Changed += new FileSystemEventHandler(this.OnFileChangedEvent); + watcher.Changed += OnFileChangedEvent; + watcher.Created += OnFileChangedEvent; + watcher.Renamed += OnFileChangedEvent; } watcher.Path = Path.GetDirectoryName(fileName); watcher.Filter = Path.GetFileName(fileName); - watcher.NotifyFilter = NotifyFilters.LastWrite; watcher.EnableRaisingEvents = true; } catch (PlatformNotSupportedException) { if (watcher != null) { @@ -127,15 +128,18 @@ namespace ICSharpCode.SharpDevelop void OnFileChangedEvent(object sender, FileSystemEventArgs e) { - if (e.ChangeType != WatcherChangeTypes.Deleted) { - if (file == null) - return; - LoggingService.Debug("File " + file.FileName + " was changed externally"); + LoggingService.Debug("File " + file.FileName + " was changed externally: " + e.ChangeType); + if (file == null) + return; + if (!wasChangedExternally) { wasChangedExternally = true; if (WorkbenchSingleton.Workbench.IsActiveWindow) { - // delay showing message a bit, prevents showing two messages - // when the file changes twice in quick succession - WorkbenchSingleton.SafeThreadAsyncCall(MainForm_Activated, this, EventArgs.Empty); + // delay reloading message a bit, prevents showing two messages + // when the file changes twice in quick succession; and prevents + // trying to reload the file while it is still being written + WorkbenchSingleton.CallLater( + 500, + delegate { MainForm_Activated(this, EventArgs.Empty); } ); } } } @@ -149,6 +153,8 @@ namespace ICSharpCode.SharpDevelop return; string fileName = file.FileName; + if (!File.Exists(fileName)) + return; string message = StringParser.Parse("${res:ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor.TextEditorDisplayBinding.FileAlteredMessage}", new string[,] {{"File", Path.GetFullPath(fileName)}}); if ((AutoLoadExternalChangesOption && file.IsDirty == false) From 2bffb7e184d6d5e72a30356833e2cec60e65e9e9 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 19 Oct 2008 00:14:17 +0000 Subject: [PATCH 34/51] Update Clipboard.ContainsText using a separate thread. Fix/workaround for SD2-1466 - SharpDevelop freezes when debugged application sets clipboard text. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3605 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/Gui/TextAreaClipboardHandler.cs | 27 ++++++-- .../Project/ICSharpCode.SharpDevelop.csproj | 1 + .../Base/Project/Src/Commands/EditCommands.cs | 3 +- .../Src/TextEditor/ClipboardHandling.cs | 67 +++++++++++++++++++ .../Gui/Editor/TextEditorDisplayBinding.cs | 1 + 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 src/Main/Base/Project/Src/TextEditor/ClipboardHandling.cs diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaClipboardHandler.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaClipboardHandler.cs index 5b035388cf..47e1c9af9d 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaClipboardHandler.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextAreaClipboardHandler.cs @@ -32,14 +32,33 @@ namespace ICSharpCode.TextEditor } } + public delegate bool ClipboardContainsTextDelegate(); + + /// + /// Is called when CachedClipboardContainsText should be updated. + /// If this property is null (the default value), the text editor uses + /// System.Windows.Forms.Clipboard.ContainsText. + /// + /// + /// This property is useful if you want to prevent the default Clipboard.ContainsText + /// behaviour that waits for the clipboard to be available - the clipboard might + /// never become available if it is owned by a process that is paused by the debugger. + /// + public static ClipboardContainsTextDelegate GetClipboardContainsText; + public bool EnablePaste { get { if (!textArea.EnableCutOrPaste) return false; - try { - return Clipboard.ContainsText(); - } catch (ExternalException) { - return false; + ClipboardContainsTextDelegate d = GetClipboardContainsText; + if (d != null) { + return d(); + } else { + try { + return Clipboard.ContainsText(); + } catch (ExternalException) { + return false; + } } } } diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 8d5bf9644d..00cebf1b63 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -473,6 +473,7 @@ + diff --git a/src/Main/Base/Project/Src/Commands/EditCommands.cs b/src/Main/Base/Project/Src/Commands/EditCommands.cs index 8ff4b2906f..6c9ae8279e 100644 --- a/src/Main/Base/Project/Src/Commands/EditCommands.cs +++ b/src/Main/Base/Project/Src/Commands/EditCommands.cs @@ -5,6 +5,7 @@ // $Revision$ // +using ICSharpCode.SharpDevelop.DefaultEditor; using System; using System.Windows.Forms; using ICSharpCode.Core; @@ -122,7 +123,7 @@ namespace ICSharpCode.SharpDevelop.Commands get { return comboBox.SelectionLength > 0; } } public bool EnablePaste { - get { return ClipboardWrapper.ContainsText; } + get { return ClipboardHandling.GetClipboardContainsText(); } } public bool EnableDelete { get { return true; } diff --git a/src/Main/Base/Project/Src/TextEditor/ClipboardHandling.cs b/src/Main/Base/Project/Src/TextEditor/ClipboardHandling.cs new file mode 100644 index 0000000000..401125ed27 --- /dev/null +++ b/src/Main/Base/Project/Src/TextEditor/ClipboardHandling.cs @@ -0,0 +1,67 @@ +// +// +// +// +// $Revision$ +// + +using ICSharpCode.Core.WinForms; +using System; +using System.Threading; +using ICSharpCode.SharpDevelop.Gui; + +namespace ICSharpCode.SharpDevelop.DefaultEditor +{ + /// + /// This class fixes SD2-1466: SharpDevelop freezes when debugged application sets clipboard text. + /// The problem is that Clipboard.ContainsText may wait for the application owning the clipboard, + /// which in turn may currently wait for SharpDevelop (through the debugger) + /// + static class ClipboardHandling + { + public static void Initialize() + { + ICSharpCode.TextEditor.TextAreaClipboardHandler.GetClipboardContainsText = GetClipboardContainsText; + WorkbenchSingleton.MainForm.Activated += WorkbenchSingleton_MainForm_Activated; + } + + static void WorkbenchSingleton_MainForm_Activated(object sender, EventArgs e) + { + UpdateClipboardContainsText(); + } + + static bool clipboardContainsText; + + public static bool GetClipboardContainsText() + { + WorkbenchSingleton.DebugAssertMainThread(); + if (WorkbenchSingleton.Workbench.IsActiveWindow) { + UpdateClipboardContainsText(); + } + return clipboardContainsText; + } + + static Thread updateThread; + + static void UpdateClipboardContainsText() + { + if (updateThread != null) + return; + Thread t = new Thread(new ThreadStart(DoUpdate)); + t.SetApartmentState(ApartmentState.STA); + t.IsBackground = true; + updateThread = t; + t.Start(); + t.Join(50); // wait a few ms in case the clipboard can be accessed without problems + } + + static void DoUpdate() + { + try { + clipboardContainsText = ClipboardWrapper.ContainsText; + } finally { + updateThread = null; + } + } + } +} 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 ff8a0e0cca..371a881b76 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs @@ -33,6 +33,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor HighlightingManager.Manager.AddSyntaxModeFileProvider(new ICSharpCode.SharpDevelop.DefaultEditor.Codons.AddInTreeSyntaxModeProvider()); HighlightingManager.Manager.AddSyntaxModeFileProvider(new FileSyntaxModeProvider(Path.Combine(PropertyService.DataDirectory, "modes"))); HighlightingManager.Manager.AddSyntaxModeFileProvider(new FileSyntaxModeProvider(modeDir)); + ClipboardHandling.Initialize(); } /// From 9815697f230cd1d996e6eb0040e1e73aa6998f64 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 19 Oct 2008 00:44:29 +0000 Subject: [PATCH 35/51] Fixed build git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3606 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Base/Project/Src/TextEditor/ClipboardHandling.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Main/Base/Project/Src/TextEditor/ClipboardHandling.cs b/src/Main/Base/Project/Src/TextEditor/ClipboardHandling.cs index 401125ed27..24f03db1e5 100644 --- a/src/Main/Base/Project/Src/TextEditor/ClipboardHandling.cs +++ b/src/Main/Base/Project/Src/TextEditor/ClipboardHandling.cs @@ -22,7 +22,13 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor public static void Initialize() { ICSharpCode.TextEditor.TextAreaClipboardHandler.GetClipboardContainsText = GetClipboardContainsText; - WorkbenchSingleton.MainForm.Activated += WorkbenchSingleton_MainForm_Activated; + if (WorkbenchSingleton.MainForm != null) { + WorkbenchSingleton.MainForm.Activated += WorkbenchSingleton_MainForm_Activated; + } else { + WorkbenchSingleton.WorkbenchCreated += delegate { + WorkbenchSingleton.MainForm.Activated += WorkbenchSingleton_MainForm_Activated; + }; + } } static void WorkbenchSingleton_MainForm_Activated(object sender, EventArgs e) @@ -35,7 +41,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor public static bool GetClipboardContainsText() { WorkbenchSingleton.DebugAssertMainThread(); - if (WorkbenchSingleton.Workbench.IsActiveWindow) { + if (WorkbenchSingleton.Workbench != null && WorkbenchSingleton.Workbench.IsActiveWindow) { UpdateClipboardContainsText(); } return clipboardContainsText; From 385f08cdaa554b4de0c34e168bef39bcc16f7171 Mon Sep 17 00:00:00 2001 From: Christian Hornung Date: Sun, 19 Oct 2008 14:03:43 +0000 Subject: [PATCH 36/51] Fixed SD2-1468 - Custom components tab does not show control with missing constructor. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3607 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs index be01e4e5c4..147e954e64 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Gui/CustomComponentsSideTab.cs @@ -88,8 +88,9 @@ namespace ICSharpCode.FormsDesigner.Gui continue; } foreach (IClass c in pc.Classes) { - if (!c.Methods.Any( - (IMethod method) => method.IsConstructor && method.IsPublic && method.Parameters.Count == 0 + var ctors = c.Methods.Where(method => method.IsConstructor); + if (ctors.Any() && !ctors.Any( + (IMethod method) => method.IsPublic && method.Parameters.Count == 0 )) { // do not include classes that don't have a public parameterless constructor continue; From a7e361e83b076b7580affd3b7b526dd80af8d0c0 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Mon, 20 Oct 2008 19:25:57 +0000 Subject: [PATCH 37/51] Inner classes with a TestFixture attribute are now shown in the Unit Tests and can be tested individually. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3608 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Misc/UnitTesting/Src/RemovedClasses.cs | 56 +++++++++ src/AddIns/Misc/UnitTesting/Src/TestClass.cs | 26 ++-- .../UnitTesting/Src/TestClassCollection.cs | 2 +- .../Misc/UnitTesting/Src/TestProject.cs | 49 ++++---- .../Src/UnitTestApplicationStartHelper.cs | 2 +- .../InnerClassMethodRenamedTestFixture.cs | 73 ++++++++++++ .../InnerClassNameChangesTestFixture.cs | 69 +++++++++++ .../Test/Project/InnerClassTestFixture.cs | 79 +++++++++++++ ...sTestFixtureAttributeRemovedTestFixture.cs | 61 ++++++++++ .../Test/Project/InnerClassTestFixtureBase.cs | 70 +++++++++++ .../Test/Project/RemovedClassesTestFixture.cs | 111 ++++++++++++++++++ .../Test/UnitTestCommandLineTests.cs | 12 ++ .../UnitTesting/Test/UnitTesting.Tests.csproj | 6 + .../Misc/UnitTesting/Test/Utils/MockClass.cs | 91 ++++++-------- .../Misc/UnitTesting/UnitTesting.csproj | 1 + 15 files changed, 610 insertions(+), 98 deletions(-) create mode 100644 src/AddIns/Misc/UnitTesting/Src/RemovedClasses.cs create mode 100644 src/AddIns/Misc/UnitTesting/Test/Project/InnerClassMethodRenamedTestFixture.cs create mode 100644 src/AddIns/Misc/UnitTesting/Test/Project/InnerClassNameChangesTestFixture.cs create mode 100644 src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixture.cs create mode 100644 src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixtureAttributeRemovedTestFixture.cs create mode 100644 src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixtureBase.cs create mode 100644 src/AddIns/Misc/UnitTesting/Test/Project/RemovedClassesTestFixture.cs diff --git a/src/AddIns/Misc/UnitTesting/Src/RemovedClasses.cs b/src/AddIns/Misc/UnitTesting/Src/RemovedClasses.cs new file mode 100644 index 0000000000..6a93a6d086 --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Src/RemovedClasses.cs @@ -0,0 +1,56 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.UnitTesting +{ + /// + /// Used to determine which classes have been removed by the user in the project. + /// + public class RemovedClasses + { + Dictionary classDictionary = new Dictionary(); + + public RemovedClasses() + { + } + + public void Add(IList classes) + { + foreach (IClass c in classes) { + classDictionary[c.DotNetName] = c; + foreach (IClass innerClass in c.InnerClasses) { + classDictionary[innerClass.DotNetName] = innerClass; + } + } + } + + /// + /// + /// + /// + public void Remove(IClass c) + { + classDictionary.Remove(c.DotNetName); + foreach (IClass innerClass in c.InnerClasses) { + classDictionary.Remove(innerClass.DotNetName); + } + } + + public IList GetMissingClasses() + { + List missingClasses = new List(); + foreach (IClass c in classDictionary.Values) { + missingClasses.Add(c); + } + return missingClasses; + } + } +} diff --git a/src/AddIns/Misc/UnitTesting/Src/TestClass.cs b/src/AddIns/Misc/UnitTesting/Src/TestClass.cs index 7b77cda9c6..4bff9a706a 100644 --- a/src/AddIns/Misc/UnitTesting/Src/TestClass.cs +++ b/src/AddIns/Misc/UnitTesting/Src/TestClass.cs @@ -37,9 +37,7 @@ namespace ICSharpCode.UnitTesting /// Gets the underlying IClass for this test class. /// public IClass Class { - get { - return c; - } + get { return c; } } /// @@ -132,7 +130,10 @@ namespace ICSharpCode.UnitTesting /// Gets the name of the class. /// public string Name { - get { + get { + if (c.DeclaringType != null) { + return String.Concat(c.DeclaringType.Name, "+", c.Name); + } return c.Name; } } @@ -141,16 +142,17 @@ namespace ICSharpCode.UnitTesting /// Gets the fully qualified name of the class. /// public string QualifiedName { - get { - return c.FullyQualifiedName; - } + get { return c.DotNetName; } } /// /// Gets the namespace of this class. /// public string Namespace { - get { + get { + if (c.DeclaringType != null) { + return c.DeclaringType.Namespace; + } return c.Namespace; } } @@ -159,18 +161,14 @@ namespace ICSharpCode.UnitTesting /// Gets the root namespace for this class. /// public string RootNamespace { - get { - return GetRootNamespace(c.Namespace); - } + get { return GetRootNamespace(c.Namespace); } } /// /// Gets the test result for this class. /// public TestResultType Result { - get { - return testResultType; - } + get { return testResultType; } set { TestResultType previousTestResultType = testResultType; testResultType = value; diff --git a/src/AddIns/Misc/UnitTesting/Src/TestClassCollection.cs b/src/AddIns/Misc/UnitTesting/Src/TestClassCollection.cs index 464e131b88..504c09a324 100644 --- a/src/AddIns/Misc/UnitTesting/Src/TestClassCollection.cs +++ b/src/AddIns/Misc/UnitTesting/Src/TestClassCollection.cs @@ -100,7 +100,7 @@ namespace ICSharpCode.UnitTesting protected override string GetKeyForItem(TestClass item) { - return item.Class.FullyQualifiedName; + return item.QualifiedName; } protected override void InsertItem(int index, TestClass item) diff --git a/src/AddIns/Misc/UnitTesting/Src/TestProject.cs b/src/AddIns/Misc/UnitTesting/Src/TestProject.cs index c8eb3427c4..54d85fb763 100644 --- a/src/AddIns/Misc/UnitTesting/Src/TestProject.cs +++ b/src/AddIns/Misc/UnitTesting/Src/TestProject.cs @@ -34,9 +34,7 @@ namespace ICSharpCode.UnitTesting /// Returns the underlying project. /// public IProject Project { - get { - return project; - } + get { return project; } } /// @@ -114,9 +112,7 @@ namespace ICSharpCode.UnitTesting /// Gets the project's name. /// public string Name { - get { - return project.Name; - } + get { return project.Name; } } /// @@ -152,8 +148,7 @@ namespace ICSharpCode.UnitTesting } /// - /// Updates the classes and methods based on the new parse - /// information. + /// Updates the classes and methods based on the new parse information. /// /// The old compiliation unit /// (ParseInformationEventArgs.ParseInformation.BestCompilationUnit as ICompilationUnit) @@ -165,28 +160,25 @@ namespace ICSharpCode.UnitTesting return; } - Dictionary classDictionary = new Dictionary(); - Dictionary wasUpdatedDictionary = new Dictionary(); + RemovedClasses removedClasses = new RemovedClasses(); if (oldUnit != null) { - foreach (IClass c in oldUnit.Classes) { - classDictionary[c.FullyQualifiedName] = c; - wasUpdatedDictionary[c.FullyQualifiedName] = false; - } + removedClasses.Add(oldUnit.Classes); } if (newUnit != null) { foreach (IClass c in newUnit.Classes) { UpdateTestClass(c); - wasUpdatedDictionary[c.FullyQualifiedName] = true; + foreach (IClass innerClass in c.InnerClasses) { + UpdateTestClass(innerClass); + removedClasses.Remove(innerClass); + } + removedClasses.Remove(c); } } // Remove missing classes. - foreach (KeyValuePair entry in wasUpdatedDictionary) { - if (!entry.Value) { - IClass c = classDictionary[entry.Key]; - TestClasses.Remove(c.FullyQualifiedName); - } + foreach (IClass c in removedClasses.GetMissingClasses()) { + TestClasses.Remove(c.DotNetName); } } @@ -224,14 +216,14 @@ namespace ICSharpCode.UnitTesting /// void UpdateTestClass(IClass c) { - if (TestClasses.Contains(c.FullyQualifiedName)) { + if (TestClasses.Contains(c.DotNetName)) { if (TestClass.IsTestClass(c)) { - TestClass testClass = TestClasses[c.FullyQualifiedName]; + TestClass testClass = TestClasses[c.DotNetName]; testClass.UpdateClass(c); } else { // TestFixture attribute has been removed so // remove the class from the set of TestClasses. - TestClasses.Remove(c.FullyQualifiedName); + TestClasses.Remove(c.DotNetName); } } else { // TestFixture attribute may have been recently added to @@ -239,7 +231,7 @@ namespace ICSharpCode.UnitTesting // check if the class is actually a test class since // AddNewTestClass does this anyway. AddNewTestClass(c); - } + } } void GetTestClasses() @@ -251,6 +243,13 @@ namespace ICSharpCode.UnitTesting testClasses.Add(new TestClass(c)); } } + foreach (IClass innerClass in c.InnerClasses) { + if (TestClass.IsTestClass(innerClass)) { + if (!testClasses.Contains(innerClass.DotNetName)) { + testClasses.Add(new TestClass(innerClass)); + } + } + } } } @@ -263,6 +262,6 @@ namespace ICSharpCode.UnitTesting rootNamespaces.Add(rootNamespace); } } - } + } } } diff --git a/src/AddIns/Misc/UnitTesting/Src/UnitTestApplicationStartHelper.cs b/src/AddIns/Misc/UnitTesting/Src/UnitTestApplicationStartHelper.cs index 65250b7a3e..5156e7a679 100644 --- a/src/AddIns/Misc/UnitTesting/Src/UnitTestApplicationStartHelper.cs +++ b/src/AddIns/Misc/UnitTesting/Src/UnitTestApplicationStartHelper.cs @@ -119,7 +119,7 @@ namespace ICSharpCode.UnitTesting NamespaceFilter = namespaceFilter; } if (fixture != null) { - Fixture = fixture.FullyQualifiedName; + Fixture = fixture.DotNetName; if (test != null) { Test = test.Name; } diff --git a/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassMethodRenamedTestFixture.cs b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassMethodRenamedTestFixture.cs new file mode 100644 index 0000000000..92a772e053 --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassMethodRenamedTestFixture.cs @@ -0,0 +1,73 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.UnitTesting; +using NUnit.Framework; +using UnitTesting.Tests.Utils; + +namespace UnitTesting.Tests.Project +{ + /// + /// Tests what happens when a test method is renamed inside an inner class. + /// + [TestFixture] + public class InnerClassMethodRemovedTestFixture : InnerClassTestFixtureBase + { + TestClass innerTestClass; + + [SetUp] + public void Init() + { + base.InitBase(); + + DefaultCompilationUnit oldUnit = new DefaultCompilationUnit(projectContent); + oldUnit.Classes.Add(outerClass); + + // Create new compilation unit with inner class that has its method renamed. + DefaultCompilationUnit newUnit = new DefaultCompilationUnit(projectContent); + MockClass newOuterClass = new MockClass("MyTests.A"); + newOuterClass.ProjectContent = projectContent; + projectContent.Classes.Add(newOuterClass); + newOuterClass.SetCompoundClass(newOuterClass); + newUnit.Classes.Add(newOuterClass); + + // Create the inner test class. + MockClass newInnerClass = new MockClass("MyTests.A.InnerATest", "MyTests.A+InnerATest"); + newInnerClass.Attributes.Add(new MockAttribute("TestFixture")); + newInnerClass.ProjectContent = projectContent; + newInnerClass.DeclaringType = outerClass; // Declaring type is outer class. + newInnerClass.SetCompoundClass(newInnerClass); + newOuterClass.InnerClasses.Add(newInnerClass); + + MockMethod method = new MockMethod("FooBarRenamed"); + method.Attributes.Add(new MockAttribute("Test")); + method.DeclaringType = newInnerClass; + newInnerClass.Methods.Add(method); + outerClass.InnerClasses.Add(newInnerClass); + + // Update TestProject's parse info. + testProject.UpdateParseInfo(oldUnit, newUnit); + + innerTestClass = testProject.TestClasses["MyTests.A+InnerATest"]; + } + + [Test] + public void NewTestMethodExists() + { + TestMethod method = innerTestClass.TestMethods[0]; + Assert.AreEqual("FooBarRenamed", method.Name); + } + + [Test] + public void OldTestMethodRemoved() + { + Assert.AreEqual(1, innerTestClass.TestMethods.Count); + } + } +} diff --git a/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassNameChangesTestFixture.cs b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassNameChangesTestFixture.cs new file mode 100644 index 0000000000..fe25ec2d67 --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassNameChangesTestFixture.cs @@ -0,0 +1,69 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.UnitTesting; +using NUnit.Framework; +using UnitTesting.Tests.Utils; + +namespace UnitTesting.Tests.Project +{ + /// + /// Tests that the TestProject is correctly updated after the inner class name changes. + /// + [TestFixture] + public class InnerClassNameChangesTestFixture : InnerClassTestFixtureBase + { + [SetUp] + public void Init() + { + base.InitBase(); + + DefaultCompilationUnit oldUnit = new DefaultCompilationUnit(projectContent); + oldUnit.Classes.Add(outerClass); + + // Create new compilation unit with extra class. + DefaultCompilationUnit newUnit = new DefaultCompilationUnit(projectContent); + MockClass newOuterClass = new MockClass("MyTests.A"); + newOuterClass.ProjectContent = projectContent; + projectContent.Classes.Add(newOuterClass); + newOuterClass.SetCompoundClass(newOuterClass); + newUnit.Classes.Add(newOuterClass); + + // Create the inner test class. + // Note the use of the DotNetName "MyTests.A+InnerTest". + MockClass newInnerClass = new MockClass("MyTests.A.InnerATestMod", "MyTests.A+InnerATestMod"); + newInnerClass.Attributes.Add(new MockAttribute("TestFixture")); + newInnerClass.ProjectContent = projectContent; + newInnerClass.DeclaringType = outerClass; // Declaring type is outer class. + newOuterClass.InnerClasses.Add(newInnerClass); + + // Update TestProject's parse info. + testProject.UpdateParseInfo(oldUnit, newUnit); + } + + [Test] + public void NewInnerClassAdded() + { + Assert.IsTrue(testProject.TestClasses.Contains("MyTests.A+InnerATestMod")); + } + + [Test] + public void OldInnerClassRemoved() + { + Assert.IsFalse(testProject.TestClasses.Contains("MyTests.A+InnerATest")); + } + + [Test] + public void OneTestClassRemain() + { + Assert.AreEqual(1, testProject.TestClasses.Count); + } + } +} diff --git a/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixture.cs b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixture.cs new file mode 100644 index 0000000000..dec18f4aa4 --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixture.cs @@ -0,0 +1,79 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.UnitTesting; +using NUnit.Framework; +using UnitTesting.Tests.Utils; + +namespace UnitTesting.Tests.Project +{ + /// + /// Tests that a class with an inner test fixture is recognised, for example: + /// + /// public class A + /// { + /// [TestFixture] + /// public class InnerATest + /// { + /// [Test] + /// public void FooBar() + /// { + /// } + /// } + /// } + /// + /// In this case the FooBar test is identified via: "A+InnerATest.FooBar". + /// + [TestFixture] + public class InnerClassTestFixture : InnerClassTestFixtureBase + { + [SetUp] + public void Init() + { + base.InitBase(); + } + + [Test] + public void OneTestClassFound() + { + Assert.AreEqual(1, testProject.TestClasses.Count); + } + + [Test] + public void TestClassQualifiedName() + { + Assert.AreEqual("MyTests.A+InnerATest", testClass.QualifiedName); + } + + [Test] + public void TestClassName() + { + Assert.AreEqual("A+InnerATest", testClass.Name); + } + + [Test] + public void NoTestClassesForNamespaceMyTestsA() + { + Assert.AreEqual(0, testProject.GetTestClasses("MyTests.A").Length); + } + + [Test] + public void OneTestClassForNamespaceMyTests() + { + Assert.AreEqual(1, testProject.GetTestClasses("MyTests").Length); + } + + [Test] + public void NamespaceForInnerClassIsDeclaringTypesNamespace() + { + Assert.AreEqual("MyTests", testClass.Namespace); + } + } +} diff --git a/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixtureAttributeRemovedTestFixture.cs b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixtureAttributeRemovedTestFixture.cs new file mode 100644 index 0000000000..fbb6d94d95 --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixtureAttributeRemovedTestFixture.cs @@ -0,0 +1,61 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.UnitTesting; +using NUnit.Framework; +using UnitTesting.Tests.Utils; + +namespace UnitTesting.Tests.Project +{ + /// + /// Tests that the inner test class is removed when its TestFixture attribute is removed. + /// + [TestFixture] + public class InnerClassTestFixtureAttributeRemovedTestFixture : InnerClassTestFixtureBase + { + [SetUp] + public void Init() + { + base.InitBase(); + + DefaultCompilationUnit oldUnit = new DefaultCompilationUnit(projectContent); + oldUnit.Classes.Add(outerClass); + + // Create new compilation unit with inner class that no longer has the TestFixture attribute. + DefaultCompilationUnit newUnit = new DefaultCompilationUnit(projectContent); + MockClass newOuterClass = new MockClass("MyTests.A"); + newOuterClass.ProjectContent = projectContent; + projectContent.Classes.Add(newOuterClass); + newOuterClass.SetCompoundClass(newOuterClass); + newUnit.Classes.Add(newOuterClass); + + // Create the inner test class. + MockClass newInnerClass = new MockClass("MyTests.A.InnerATest", "MyTests.A+InnerATest"); + newInnerClass.ProjectContent = projectContent; + newInnerClass.DeclaringType = outerClass; // Declaring type is outer class. + newInnerClass.SetCompoundClass(newInnerClass); + newOuterClass.InnerClasses.Add(newInnerClass); + + // Update TestProject's parse info. + testProject.UpdateParseInfo(oldUnit, newUnit); + } + + [Test] + public void NoTestClasses() + { + Assert.AreEqual(0, testProject.TestClasses.Count); + } + + [Test] + public void InnerTestClassRemoved() + { + Assert.IsFalse(testProject.TestClasses.Contains("MyTests.A+InnerATest")); + } + } +} diff --git a/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixtureBase.cs b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixtureBase.cs new file mode 100644 index 0000000000..ea82c73f54 --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Test/Project/InnerClassTestFixtureBase.cs @@ -0,0 +1,70 @@ +// +// +// +// +// $Revision$ +// + +using System; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.UnitTesting; +using UnitTesting.Tests.Utils; + +namespace UnitTesting.Tests.Project +{ + /// + /// Base class for testing inner classes with TestFixture information. + /// + public class InnerClassTestFixtureBase + { + protected TestClass testClass; + protected MockClass innerClass; + protected TestProject testProject; + protected MockProjectContent projectContent; + protected MockClass outerClass; + + protected void InitBase() + { + projectContent = new MockProjectContent(); + projectContent.Language = LanguageProperties.None; + + // Create the base test class. + outerClass = new MockClass("MyTests.A"); + outerClass.ProjectContent = projectContent; + projectContent.Classes.Add(outerClass); + + // Create the inner test class. + // Note the use of the DotNetName "MyTests.A+InnerTest". + innerClass = new MockClass("MyTests.A.InnerATest", "MyTests.A+InnerATest"); + innerClass.Attributes.Add(new MockAttribute("TestFixture")); + innerClass.ProjectContent = projectContent; + innerClass.DeclaringType = outerClass; // Declaring type is outer class. + + MockMethod method = new MockMethod("FooBar"); + method.Attributes.Add(new MockAttribute("Test")); + method.DeclaringType = innerClass; + innerClass.Methods.Add(method); + outerClass.InnerClasses.Add(innerClass); + + // Add another inner class that is not a test class. + MockClass nonTestInnerClass = new MockClass("MyTests.A.InnerBClass"); + nonTestInnerClass.ProjectContent = projectContent; + nonTestInnerClass.DeclaringType = outerClass; // Declaring type is outer class. + outerClass.InnerClasses.Add(nonTestInnerClass); + + // Add another inner class with the same name as the InnerATest. + // This makes sure duplicate classes are not added. + MockClass duplicateInnerClass = new MockClass("MyTests.A.InnerATest", "MyTests.A+InnerATest"); + duplicateInnerClass.Attributes.Add(new MockAttribute("TestFixture")); + duplicateInnerClass.ProjectContent = projectContent; + duplicateInnerClass.DeclaringType = outerClass; // Declaring type is outer class. + outerClass.InnerClasses.Add(duplicateInnerClass); + + testProject = new TestProject(null, projectContent); + if (testProject.TestClasses.Count > 0) { + testClass = testProject.TestClasses[0]; + } + } + } +} diff --git a/src/AddIns/Misc/UnitTesting/Test/Project/RemovedClassesTestFixture.cs b/src/AddIns/Misc/UnitTesting/Test/Project/RemovedClassesTestFixture.cs new file mode 100644 index 0000000000..c616251244 --- /dev/null +++ b/src/AddIns/Misc/UnitTesting/Test/Project/RemovedClassesTestFixture.cs @@ -0,0 +1,111 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Text; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.UnitTesting; +using NUnit.Framework; +using UnitTesting.Tests.Utils; + +namespace UnitTesting.Tests.Project +{ + [TestFixture] + public class RemovedClassesTestFixture + { + RemovedClasses removedClasses; + MockClass myClass; + MockClass anotherClass; + MockClass innerClass; + + [SetUp] + public void Init() + { + myClass = new MockClass("MyTests.MyClass"); + innerClass = new MockClass("MyTests.MyClass.InnerClass", "MyTests.MyClass+InnerClass"); + myClass.InnerClasses.Add(innerClass); + + anotherClass = new MockClass("MyTests.AnotherClass"); + + List classes = new List(); + classes.Add(myClass); + classes.Add(anotherClass); + + removedClasses = new RemovedClasses(); + removedClasses.Add(classes); + } + + [Test] + public void InnerClassesIncludedInMissingClasses() + { + List expectedClasses = new List(); + expectedClasses.Add(myClass); + expectedClasses.Add(innerClass); + expectedClasses.Add(anotherClass); + + AssertContains(expectedClasses, removedClasses.GetMissingClasses()); + } + + /// + /// Should remove inner class too. + /// + [Test] + public void RemoveMyClass() + { + removedClasses.Remove(myClass); + + List expectedClasses = new List(); + expectedClasses.Add(anotherClass); + + AssertContains(expectedClasses, removedClasses.GetMissingClasses()); + } + + [Test] + public void RemoveInnerClass() + { + removedClasses.Remove(innerClass); + + List expectedClasses = new List(); + expectedClasses.Add(myClass); + expectedClasses.Add(anotherClass); + + AssertContains(expectedClasses, removedClasses.GetMissingClasses()); + } + + [Test] + public void DotNetNameUsedWhenAddingClasses() + { + MockClass c = new MockClass("MyTests.MyClass.InnerClass", "MyTests.MyClass+InnerClass"); + List classes = new List(); + classes.Add(c); + + RemovedClasses removedClasses = new RemovedClasses(); + removedClasses.Add(classes); + removedClasses.Remove(c); + + Assert.AreEqual(0, removedClasses.GetMissingClasses().Count); + } + + void AssertContains(IList expectedClasses, IList actualClasses) + { + foreach (IClass c in expectedClasses) { + Assert.IsTrue(actualClasses.Contains(c), "Class missing: " + c.FullyQualifiedName + " Actual:\r\n" + GetClassNames(actualClasses)); + } + Assert.AreEqual(expectedClasses.Count, actualClasses.Count, "Actual:\r\n" + GetClassNames(actualClasses)); + } + + string GetClassNames(IList classes) + { + StringBuilder names = new StringBuilder(); + foreach (IClass c in classes) { + names.AppendLine(c.FullyQualifiedName); + } + return names.ToString(); + } + } +} diff --git a/src/AddIns/Misc/UnitTesting/Test/UnitTestCommandLineTests.cs b/src/AddIns/Misc/UnitTesting/Test/UnitTestCommandLineTests.cs index 406ae603af..a371b60fb7 100644 --- a/src/AddIns/Misc/UnitTesting/Test/UnitTestCommandLineTests.cs +++ b/src/AddIns/Misc/UnitTesting/Test/UnitTestCommandLineTests.cs @@ -209,6 +209,18 @@ namespace UnitTesting.Tests { helper.Initialize(project, null, null); Assert.AreSame(project, helper.Project); + } + + [Test] + public void TestInnerClassSpecifiedInInitialize() + { + MockClass testFixture = new MockClass("MyTests.TestFixture.InnerTest", "MyTests.TestFixture+InnerTest"); + helper.Initialize(project, testFixture, null); + helper.NoLogo = false; + helper.ShadowCopy = true; + + string expectedCommandLine = "\"C:\\Projects\\MyTests\\MyTests.dll\" /run=\"MyTests.TestFixture+InnerTest\""; + Assert.AreEqual(expectedCommandLine, helper.GetArguments()); } } } diff --git a/src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj b/src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj index 4ad35683e7..eb555c53b2 100644 --- a/src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj +++ b/src/AddIns/Misc/UnitTesting/Test/UnitTesting.Tests.csproj @@ -62,6 +62,12 @@ + + + + + + diff --git a/src/AddIns/Misc/UnitTesting/Test/Utils/MockClass.cs b/src/AddIns/Misc/UnitTesting/Test/Utils/MockClass.cs index e3b5c6fe5a..a6c03d2b25 100644 --- a/src/AddIns/Misc/UnitTesting/Test/Utils/MockClass.cs +++ b/src/AddIns/Misc/UnitTesting/Test/Utils/MockClass.cs @@ -17,25 +17,36 @@ namespace UnitTesting.Tests.Utils DomRegion region = DomRegion.Empty; IList attributes = new List(); IList methods = new List(); + IList innerClasses = new List(); string fullyQualifiedName = String.Empty; string name = String.Empty; string ns = String.Empty; IClass compoundClass; IClass baseClass; + string dotNetName = String.Empty; + IClass declaringType; public MockClass() { } - public MockClass(string fullyQualifiedName) + public MockClass(string fullyQualifiedName) : this(fullyQualifiedName, fullyQualifiedName) + { + } + + public MockClass(string fullyQualifiedName, string dotNetName) { FullyQualifiedName = fullyQualifiedName; + this.dotNetName = dotNetName; + } + + public override string ToString() + { + return dotNetName; } public string FullyQualifiedName { - get { - return fullyQualifiedName; - } + get { return fullyQualifiedName; } set { fullyQualifiedName = value; int index = fullyQualifiedName.LastIndexOf('.'); @@ -49,74 +60,45 @@ namespace UnitTesting.Tests.Utils } public string Name { - get { - return name; - } - set { - name = value; - } + get { return name; } + set { name = value; } } public string Namespace { - get { - return ns; - } - set { - ns = value; - } + get { return ns; } + set { ns = value; } } public ClassType ClassType { - get { - return ClassType.Class; - } + get { return ClassType.Class; } } public IProjectContent ProjectContent { - get { - return projectContent; - } - set { - projectContent = value; - } + get { return projectContent; } + set { projectContent = value; } } public DomRegion Region { - get { - return region; - } - set { - region = value; - } + get { return region; } + set { region = value; } } public IList Methods { - get { - return methods; - } + get { return methods; } } public IClass BaseClass { - get { - return baseClass; - } - set { - baseClass = value; - } + get { return baseClass; } + set { baseClass = value; } } public ModifierEnum Modifiers { - get { - return ModifierEnum.None; - } - set { - } + get { return ModifierEnum.None; } + set { } } public IList Attributes { - get { - return attributes; - } + get { return attributes; } } public IClass GetCompoundClass() @@ -136,9 +118,7 @@ namespace UnitTesting.Tests.Utils } public string DotNetName { - get { - throw new NotImplementedException(); - } + get { return dotNetName; } } public ICompilationUnit CompilationUnit { @@ -160,9 +140,7 @@ namespace UnitTesting.Tests.Utils } public IList InnerClasses { - get { - throw new NotImplementedException(); - } + get { return innerClasses; } } public IList Fields { @@ -223,9 +201,8 @@ namespace UnitTesting.Tests.Utils } public IClass DeclaringType { - get { - throw new NotImplementedException(); - } + get { return declaringType; } + set { declaringType = value; } } public string Documentation { diff --git a/src/AddIns/Misc/UnitTesting/UnitTesting.csproj b/src/AddIns/Misc/UnitTesting/UnitTesting.csproj index 182deb1ead..de3907f52c 100644 --- a/src/AddIns/Misc/UnitTesting/UnitTesting.csproj +++ b/src/AddIns/Misc/UnitTesting/UnitTesting.csproj @@ -62,6 +62,7 @@ + From 1069fc57dc7976893cb8c8f483bd3d23df3a6436 Mon Sep 17 00:00:00 2001 From: Ivan Shumilin Date: Tue, 21 Oct 2008 11:56:25 +0000 Subject: [PATCH 38/51] 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 From 3035c83c8e96e06241a59238c3f56d811ed5d0fd Mon Sep 17 00:00:00 2001 From: Ivan Shumilin Date: Tue, 21 Oct 2008 12:20:35 +0000 Subject: [PATCH 39/51] second attempt... git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3610 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Xaml.Tests/Properties/AssemblyInfo.cs | 1 + .../Xaml/Xaml/Properties/AssemblyInfo.cs | 1 + .../Properties/AssemblyInfo.cs | 1 + .../XamlBinding/Properties/AssemblyInfo.cs | 10 + .../Controls/AdornerLayer.cs | 298 +++++++++++++ .../Controls/ContainerDragHandle.cs | 32 ++ .../Controls/ControlStyles.xaml | 416 ++++++++++++++++++ .../Controls/DragListener.cs | 111 +++++ .../Controls/DropDownButton.cs | 33 ++ .../Controls/EnterTextBox.cs | 31 ++ .../WpfDesign.Designer/Controls/EnumBar.xaml | 7 + .../Controls/EnumBar.xaml.cs | 112 +++++ .../WpfDesign.Designer/Controls/EnumButton.cs | 26 ++ .../Controls/ErrorBalloon.cs | 23 + .../GrayOutDesignerExceptActiveArea.cs | 121 +++++ .../Controls/GridAdorner.cs | 371 ++++++++++++++++ .../Controls/NumericUpDown.cs | 302 +++++++++++++ .../Controls/NumericUpDown.xaml | 149 +++++++ .../Controls/PanelMoveAdorner.cs | 34 ++ .../Controls/ResizeThumb.cs | 89 ++++ .../Controls/SelectionFrame.cs | 32 ++ .../Controls/WindowClone.cs | 212 +++++++++ .../Controls/ZoomControl.cs | 201 +++++++++ .../Extensions/BorderForInvisibleControl.cs | 31 ++ .../Extensions/CanvasPlacementSupport.cs | 84 ++++ .../Extensions/DefaultPlacementBehavior.cs | 95 ++++ .../Extensions/GridAdornerProvider.cs | 136 ++++++ .../Extensions/GridPlacementSupport.cs | 292 ++++++++++++ .../Extensions/Initializers.cs | 52 +++ .../Extensions/PanelInitializer.cs | 156 +++++++ .../Extensions/PanelMove.cs | 27 ++ .../Extensions/PanelSelectionHandler.cs | 170 +++++++ .../Extensions/ResizeThumbExtension.cs | 150 +++++++ .../SelectedElementRectangleExtension.cs | 50 +++ .../Extensions/SnaplinePlacementBehavior.cs | 312 +++++++++++++ .../Extensions/TabItemClickableExtension.cs | 32 ++ .../Extensions/TopLeftContainerDragHandle.cs | 44 ++ .../Extensions/TypeReplacement.cs | 11 + .../Extensions/WindowResizeBehavior.cs | 86 ++++ .../WpfDesign.Designer/Images/Class.png | Bin 0 -> 624 bytes .../Images/PanToolCursor.cur | Bin 0 -> 326 bytes .../Images/PanToolCursorMouseDown.cur | Bin 0 -> 326 bytes .../WpfDesign.Designer/Images/Tag.png | Bin 0 -> 389 bytes .../WpfDesign.Designer/Images/ZoomIn.png | Bin 0 -> 635 bytes .../WpfDesign.Designer/Images/ZoomOut.png | Bin 0 -> 647 bytes .../OutlineView/DragListener.cs | 57 +++ .../OutlineView/DragTreeView.cs | 326 ++++++++++++++ .../OutlineView/DragTreeViewItem.cs | 119 +++++ .../OutlineView/IconItem.cs | 35 ++ .../OutlineView/Outline.xaml | 31 ++ .../OutlineView/Outline.xaml.cs | 94 ++++ .../OutlineView/OutlineNode.cs | 96 ++++ .../OutlineView/OutlineTreeView.cs | 28 ++ .../OutlineView/OutlineView.xaml | 154 +++++++ .../PropertyGrid/Editors/BoolEditor.xaml | 7 + .../PropertyGrid/Editors/BoolEditor.xaml.cs | 26 ++ .../Editors/BrushEditor/BrushEditor.cs | 207 +++++++++ .../Editors/BrushEditor/BrushEditorPopup.xaml | 11 + .../BrushEditor/BrushEditorPopup.xaml.cs | 36 ++ .../Editors/BrushEditor/BrushEditorView.xaml | 81 ++++ .../BrushEditor/BrushEditorView.xaml.cs | 51 +++ .../Editors/BrushEditor/BrushTypeEditor.xaml | 13 + .../BrushEditor/BrushTypeEditor.xaml.cs | 36 ++ .../Editors/BrushEditor/ColorHelper.cs | 92 ++++ .../Editors/BrushEditor/ColorPicker.xaml | 233 ++++++++++ .../Editors/BrushEditor/ColorPicker.xaml.cs | 184 ++++++++ .../BrushEditor/GradientBrushEditor.xaml | 12 + .../BrushEditor/GradientBrushEditor.xaml.cs | 24 + .../Editors/BrushEditor/GradientSlider.xaml | 109 +++++ .../BrushEditor/GradientSlider.xaml.cs | 159 +++++++ .../Editors/BrushEditor/NormalizedPanel.cs | 68 +++ .../Editors/BrushEditor/Picker.cs | 137 ++++++ .../Editors/BrushEditor/SolidBrushEditor.xaml | 19 + .../BrushEditor/SolidBrushEditor.xaml.cs | 33 ++ .../PropertyGrid/Editors/EventEditor.xaml | 9 + .../PropertyGrid/Editors/EventEditor.xaml.cs | 71 +++ .../PropertyGrid/Editors/NumberEditor.xaml | 9 + .../PropertyGrid/Editors/NumberEditor.xaml.cs | 121 +++++ .../PropertyGrid/PropertyContextMenu.xaml | 25 ++ .../PropertyGrid/PropertyContextMenu.xaml.cs | 51 +++ .../PropertyGrid/PropertyGrid.cs | 285 ++++++++++++ .../PropertyGrid/PropertyGridView.xaml | 356 +++++++++++++++ .../PropertyGrid/PropertyGridView.xaml.cs | 101 +++++ .../Services/ChooseClass.cs | 99 +++++ .../Services/ChooseClassDialog.xaml | 70 +++ .../Services/ChooseClassDialog.xaml.cs | 112 +++++ .../Services/ChooseClassServiceBase.cs | 23 + .../Services/ClickOrDragMouseGesture.cs | 52 +++ .../Services/CommandService.cs | 94 ++++ .../Services/CreateComponentTool.cs | 259 +++++++++++ .../Services/DragMoveMouseGesture.cs | 66 +++ .../Services/ErrorService.cs | 88 ++++ .../Services/MouseGestureBase.cs | 112 +++++ .../WpfDesign.Designer/Services/MoveLogic.cs | 140 ++++++ .../Services/OptionService.cs | 22 + .../Services/PointerTool.cs | 53 +++ .../Services/SelectionService.cs | 180 ++++++++ .../WpfDesign.Designer/Services/TextAction.cs | 51 +++ .../Services/ToolService.cs | 79 ++++ .../Services/UndoService.cs | 391 ++++++++++++++++ .../Services/ViewService.cs | 57 +++ .../Services/WpfTopLevelWindowService.cs | 44 ++ .../Services/XamlErrorService.cs | 31 ++ .../WpfDesign.Designer/Themes/Generic.xaml | 7 + .../Designer/ModelTestHelper.cs | 87 ++++ .../WpfDesign.Tests/Designer/ModelTests.cs | 245 +++++++++++ .../Designer/PlacementTests.cs | 50 +++ .../WpfDesign.Tests/Xaml/ExampleClass.cs | 89 ++++ .../Xaml/ExampleClassContainer.cs | 26 ++ .../WpfDesign.Tests/Xaml/ExampleService.cs | 44 ++ .../Xaml/MarkupExtensionTests.cs | 111 +++++ .../WpfDesign.Tests/Xaml/SamplesTests.cs | 133 ++++++ .../WpfDesign.Tests/Xaml/SimpleLoadTests.cs | 292 ++++++++++++ .../Xaml/SystemTypesLoadTest.cs | 35 ++ .../WpfDesign.Tests/Xaml/TestHelper.cs | 94 ++++ .../WpfDesign.Tests/Xaml/WhitespaceTests.cs | 131 ++++++ .../Xaml/XamlTypeFinderTests.cs | 70 +++ .../WpfDesign/Adorners/AdornerPanel.cs | 212 +++++++++ .../WpfDesign/Adorners/AdornerPlacement.cs | 39 ++ .../Adorners/AdornerPlacementSpace.cs | 33 ++ .../WpfDesign/Adorners/AdornerProvider.cs | 163 +++++++ .../Adorners/AdornerProviderClasses.cs | 50 +++ .../WpfDesign/Adorners/RelativePlacement.cs | 211 +++++++++ .../WpfDesign/Extensions/BehaviorExtension.cs | 21 + .../Extensions/CustomInstanceFactory.cs | 68 +++ .../WpfDesign/Extensions/DefaultExtension.cs | 119 +++++ .../Extensions/DefaultInitializer.cs | 23 + .../WpfDesign/Extensions/Extension.cs | 25 ++ .../Extensions/ExtensionForAttribute.cs | 56 +++ .../WpfDesign/Extensions/ExtensionManager.cs | 260 +++++++++++ .../WpfDesign/Extensions/ExtensionServer.cs | 75 ++++ .../Extensions/ExtensionServerAttribute.cs | 42 ++ .../Extensions/LogicalExtensionServers.cs | 75 ++++ .../Extensions/ReplacementForAttribute.cs | 18 + .../Extensions/SelectionExtensionServer.cs | 145 ++++++ .../WpfDesign/PropertyGrid/Category.cs | 82 ++++ .../WpfDesign/PropertyGrid/EditorManager.cs | 75 ++++ .../PropertyGrid/Editors/ComboBoxEditor.xaml | 10 + .../Editors/ComboBoxEditor.xaml.cs | 38 ++ .../PropertyGrid/Editors/TextBoxEditor.xaml | 9 + .../Editors/TextBoxEditor.xaml.cs | 38 ++ .../PropertyGrid/PropertyEditorAttribute.cs | 50 +++ .../WpfDesign/PropertyGrid/PropertyNode.cs | 304 +++++++++++++ .../SortedObservableCollection.cs | 60 +++ .../PropertyGrid/TypeEditorAttribute.cs | 39 ++ .../WpfDesign/PropertyGrid/TypeHelper.cs | 64 +++ 146 files changed, 13688 insertions(+) create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml.Tests/Properties/AssemblyInfo.cs create mode 100644 src/AddIns/BackendBindings/Xaml/Xaml/Properties/AssemblyInfo.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/Properties/AssemblyInfo.cs create mode 100644 src/AddIns/BackendBindings/Xaml/XamlBinding/Properties/AssemblyInfo.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/AdornerLayer.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ContainerDragHandle.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ControlStyles.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/DragListener.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/DropDownButton.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnterTextBox.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumBar.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumBar.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumButton.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ErrorBalloon.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/GrayOutDesignerExceptActiveArea.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/GridAdorner.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/NumericUpDown.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/NumericUpDown.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/PanelMoveAdorner.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ResizeThumb.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/SelectionFrame.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/WindowClone.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ZoomControl.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/BorderForInvisibleControl.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/CanvasPlacementSupport.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/DefaultPlacementBehavior.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/GridAdornerProvider.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/GridPlacementSupport.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/Initializers.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelInitializer.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelMove.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelSelectionHandler.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/ResizeThumbExtension.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/SelectedElementRectangleExtension.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/SnaplinePlacementBehavior.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TabItemClickableExtension.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TopLeftContainerDragHandle.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TypeReplacement.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/WindowResizeBehavior.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/Class.png create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/PanToolCursor.cur create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/PanToolCursorMouseDown.cur create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/Tag.png create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/ZoomIn.png create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/ZoomOut.png create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragListener.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragTreeView.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragTreeViewItem.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/IconItem.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/Outline.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/Outline.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineNode.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineTreeView.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineView.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BoolEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BoolEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditor.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorPopup.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorPopup.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushTypeEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushTypeEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/ColorHelper.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/ColorPicker.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/ColorPicker.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/GradientBrushEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/GradientBrushEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/GradientSlider.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/GradientSlider.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/NormalizedPanel.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/Picker.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/SolidBrushEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/SolidBrushEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/EventEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/EventEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/NumberEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/NumberEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/PropertyContextMenu.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/PropertyContextMenu.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/PropertyGrid.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/PropertyGridView.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/PropertyGridView.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/ChooseClass.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/ChooseClassDialog.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/ChooseClassDialog.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/ChooseClassServiceBase.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/ClickOrDragMouseGesture.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/CommandService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/CreateComponentTool.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/DragMoveMouseGesture.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/ErrorService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/MouseGestureBase.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/MoveLogic.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/OptionService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/PointerTool.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/SelectionService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/TextAction.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/ToolService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/UndoService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/ViewService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/WpfTopLevelWindowService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Services/XamlErrorService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Themes/Generic.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Designer/ModelTestHelper.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Designer/ModelTests.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Designer/PlacementTests.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/ExampleClass.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/ExampleClassContainer.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/ExampleService.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/MarkupExtensionTests.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SamplesTests.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SimpleLoadTests.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SystemTypesLoadTest.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/TestHelper.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/WhitespaceTests.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/XamlTypeFinderTests.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPanel.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPlacement.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPlacementSpace.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerProvider.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerProviderClasses.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/RelativePlacement.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/BehaviorExtension.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/CustomInstanceFactory.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/DefaultExtension.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/DefaultInitializer.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/Extension.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionForAttribute.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionManager.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionServer.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionServerAttribute.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/LogicalExtensionServers.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ReplacementForAttribute.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/SelectionExtensionServer.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Category.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/EditorManager.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/ComboBoxEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/ComboBoxEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/TextBoxEditor.xaml create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/TextBoxEditor.xaml.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/PropertyEditorAttribute.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/PropertyNode.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/SortedObservableCollection.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/TypeEditorAttribute.cs create mode 100644 src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/TypeHelper.cs diff --git a/src/AddIns/BackendBindings/Xaml/Xaml.Tests/Properties/AssemblyInfo.cs b/src/AddIns/BackendBindings/Xaml/Xaml.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..e02abfc9b0 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/Properties/AssemblyInfo.cs b/src/AddIns/BackendBindings/Xaml/Xaml/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..e02abfc9b0 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/Xaml/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/Properties/AssemblyInfo.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..5f282702bb --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/Xaml/XamlBinding/Properties/AssemblyInfo.cs b/src/AddIns/BackendBindings/Xaml/XamlBinding/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..8010e8d1a4 --- /dev/null +++ b/src/AddIns/BackendBindings/Xaml/XamlBinding/Properties/AssemblyInfo.cs @@ -0,0 +1,10 @@ +// +// +// +// +// $Revision: 2564 $ +// + +using System.Reflection; + +[assembly: AssemblyDescription("Provides XAML integration in code-completion")] \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/AdornerLayer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/AdornerLayer.cs new file mode 100644 index 0000000000..91edbbd38d --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/AdornerLayer.cs @@ -0,0 +1,298 @@ +// +// +// +// +// $Revision: 3077 $ +// + +//#define DEBUG_ADORNERLAYER + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +using ICSharpCode.WpfDesign.Adorners; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// A control that displays adorner panels. + /// + sealed class AdornerLayer : Panel + { + #region AdornerPanelCollection + internal sealed class AdornerPanelCollection : ICollection + { + readonly AdornerLayer _layer; + + public AdornerPanelCollection(AdornerLayer layer) + { + this._layer = layer; + } + + public int Count { + get { return _layer.Children.Count; } + } + + public bool IsReadOnly { + get { return false; } + } + + public void Add(AdornerPanel item) + { + if (item == null) + throw new ArgumentNullException("item"); + + _layer.AddAdorner(item); + } + + public void Clear() + { + _layer.ClearAdorners(); + } + + public bool Contains(AdornerPanel item) + { + if (item == null) + throw new ArgumentNullException("item"); + + return VisualTreeHelper.GetParent(item) == _layer; + } + + public void CopyTo(AdornerPanel[] array, int arrayIndex) + { + foreach (AdornerPanel panel in this) + array[arrayIndex++] = panel; + } + + public bool Remove(AdornerPanel item) + { + if (item == null) + throw new ArgumentNullException("item"); + + return _layer.RemoveAdorner(item); + } + + public IEnumerator GetEnumerator() + { + foreach (AdornerPanel panel in _layer.Children) { + yield return panel; + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } + #endregion + + AdornerPanelCollection _adorners; + readonly UIElement _designPanel; + + #if DEBUG_ADORNERLAYER + int _totalAdornerCount; + #endif + + + internal AdornerLayer(UIElement designPanel) + { + this._designPanel = designPanel; + + this.LayoutUpdated += OnLayoutUpdated; + + _adorners = new AdornerPanelCollection(this); + } + + void OnLayoutUpdated(object sender, EventArgs e) + { + UpdateAllAdorners(false); + #if DEBUG_ADORNERLAYER + Debug.WriteLine("Adorner LayoutUpdated. AdornedElements=" + _dict.Count + + ", visible adorners=" + VisualChildrenCount + ", total adorners=" + (_totalAdornerCount)); + #endif + } + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + base.OnRenderSizeChanged(sizeInfo); + UpdateAllAdorners(true); + } + + internal AdornerPanelCollection Adorners { + get { + return _adorners; + } + } + + sealed class AdornerInfo + { + internal readonly List adorners = new List(); + internal bool isVisible; + internal Rect position; + } + + // adorned element => AdornerInfo + Dictionary _dict = new Dictionary(); + + void ClearAdorners() + { + if (_dict.Count == 0) + return; // already empty + + this.Children.Clear(); + _dict = new Dictionary(); + + #if DEBUG_ADORNERLAYER + _totalAdornerCount = 0; + Debug.WriteLine("AdornerLayer cleared."); + #endif + } + + AdornerInfo GetOrCreateAdornerInfo(UIElement adornedElement) + { + AdornerInfo info; + if (!_dict.TryGetValue(adornedElement, out info)) { + info = _dict[adornedElement] = new AdornerInfo(); + info.isVisible = adornedElement.IsDescendantOf(_designPanel); + } + return info; + } + + AdornerInfo GetExistingAdornerInfo(UIElement adornedElement) + { + AdornerInfo info; + _dict.TryGetValue(adornedElement, out info); + return info; + } + + void AddAdorner(AdornerPanel adornerPanel) + { + if (adornerPanel.AdornedElement == null) + throw new DesignerException("adornerPanel.AdornedElement must be set"); + + AdornerInfo info = GetOrCreateAdornerInfo(adornerPanel.AdornedElement); + info.adorners.Add(adornerPanel); + + if (info.isVisible) { + AddAdornerToChildren(adornerPanel); + } + + #if DEBUG_ADORNERLAYER + Debug.WriteLine("Adorner added. AdornedElements=" + _dict.Count + + ", visible adorners=" + VisualChildrenCount + ", total adorners=" + (++_totalAdornerCount)); + #endif + } + + void AddAdornerToChildren(AdornerPanel adornerPanel) + { + UIElementCollection children = this.Children; + int i = 0; + for (i = 0; i < children.Count; i++) { + AdornerPanel p = (AdornerPanel)children[i]; + if (p.Order.CompareTo(adornerPanel.Order) > 0) { + break; + } + } + children.Insert(i, adornerPanel); + } + + protected override Size MeasureOverride(Size availableSize) + { + Size infiniteSize = new Size(double.PositiveInfinity, double.PositiveInfinity); + foreach (AdornerPanel adorner in this.Children) { + adorner.Measure(infiniteSize); + } + return new Size(0, 0); + } + + protected override Size ArrangeOverride(Size finalSize) + { + foreach (AdornerPanel adorner in this.Children) { + adorner.Arrange(new Rect(new Point(0, 0), adorner.DesiredSize)); + if (adorner.AdornedElement.IsDescendantOf(_designPanel)) { + adorner.RenderTransform = (Transform)adorner.AdornedElement.TransformToAncestor(_designPanel); + } + } + return finalSize; + } + + bool RemoveAdorner(AdornerPanel adornerPanel) + { + if (adornerPanel.AdornedElement == null) + return false; + + AdornerInfo info = GetExistingAdornerInfo(adornerPanel.AdornedElement); + if (info == null) + return false; + + if (info.adorners.Remove(adornerPanel)) { + if (info.isVisible) { + this.Children.Remove(adornerPanel); + } + + if (info.adorners.Count == 0) { + _dict.Remove(adornerPanel.AdornedElement); + } + + #if DEBUG_ADORNERLAYER + Debug.WriteLine("Adorner removed. AdornedElements=" + _dict.Count + + ", visible adorners=" + VisualChildrenCount + ", total adorners=" + (--_totalAdornerCount)); + #endif + + return true; + } else { + return false; + } + } + + public void UpdateAdornersForElement(UIElement element, bool forceInvalidate) + { + AdornerInfo info = GetExistingAdornerInfo(element); + if (info != null) { + UpdateAdornersForElement(element, info, forceInvalidate); + } + } + + Rect GetPositionCache(UIElement element) + { + Transform t = (Transform)element.TransformToAncestor(_designPanel); + return new Rect(new Point(t.Value.OffsetX, t.Value.OffsetY), element.RenderSize); + } + + void UpdateAdornersForElement(UIElement element, AdornerInfo info, bool forceInvalidate) + { + if (element.IsDescendantOf(_designPanel)) { + if (!info.isVisible) { + info.isVisible = true; + // make adorners visible: + info.adorners.ForEach(AddAdornerToChildren); + } + Rect c = GetPositionCache(element); + if (forceInvalidate || !info.position.Equals(c)) { + info.position = c; + foreach (AdornerPanel p in info.adorners) { + p.InvalidateMeasure(); + } + this.InvalidateArrange(); + } + } else { + if (info.isVisible) { + info.isVisible = false; + // make adorners invisible: + info.adorners.ForEach(this.Children.Remove); + } + } + } + + void UpdateAllAdorners(bool forceInvalidate) + { + foreach (KeyValuePair pair in _dict) { + UpdateAdornersForElement(pair.Key, pair.Value, forceInvalidate); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ContainerDragHandle.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ContainerDragHandle.cs new file mode 100644 index 0000000000..310e082774 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ContainerDragHandle.cs @@ -0,0 +1,32 @@ +// +// +// +// +// $Revision: 2243 $ +// + +using System; +using System.Windows.Controls; +using System.Windows; +using System.Windows.Media; +using System.Windows.Shapes; +using System.Windows.Controls.Primitives; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// A thumb where the look can depend on the IsPrimarySelection property. + /// Used by UIElementSelectionRectangle. + /// + public class ContainerDragHandle : Control + { + static ContainerDragHandle() + { + //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. + //This style is defined in themes\generic.xaml + DefaultStyleKeyProperty.OverrideMetadata(typeof(ContainerDragHandle), new FrameworkPropertyMetadata(typeof(ContainerDragHandle))); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ControlStyles.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ControlStyles.xaml new file mode 100644 index 0000000000..c38dff1ff7 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ControlStyles.xaml @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/DragListener.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/DragListener.cs new file mode 100644 index 0000000000..1785779481 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/DragListener.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Input; +using System.Diagnostics; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + public delegate void DragHandler(DragListener drag); + + public class DragListener + { + static DragListener() + { + InputManager.Current.PostProcessInput += new ProcessInputEventHandler(PostProcessInput); + } + + public DragListener(IInputElement target) + { + Target = target; + + Target.PreviewMouseLeftButtonDown += Target_MouseDown; + Target.PreviewMouseMove += Target_MouseMove; + Target.PreviewMouseLeftButtonUp += Target_MouseUp; + } + + static DragListener CurrentListener; + + static void PostProcessInput(object sender, ProcessInputEventArgs e) + { + if (CurrentListener != null) { + var a = e.StagingItem.Input as KeyEventArgs; + if (a != null && a.Key == Key.Escape) { + Mouse.Capture(null); + CurrentListener.IsDown = false; + CurrentListener.IsCanceled = true; + CurrentListener.Complete(); + } + } + } + + void Target_MouseDown(object sender, MouseButtonEventArgs e) + { + StartPoint = Mouse.GetPosition(null); + CurrentPoint = StartPoint; + DeltaDelta = new Vector(); + IsDown = true; + IsCanceled = false; + } + + void Target_MouseMove(object sender, MouseEventArgs e) + { + if (IsDown) { + DeltaDelta = e.GetPosition(null) - CurrentPoint; + CurrentPoint += DeltaDelta; + + if (!IsActive) { + if (Math.Abs(Delta.X) >= SystemParameters.MinimumHorizontalDragDistance || + Math.Abs(Delta.Y) >= SystemParameters.MinimumVerticalDragDistance) { + IsActive = true; + CurrentListener = this; + + if (Started != null) { + Started(this); + } + } + } + + if (IsActive && Changed != null) { + Changed(this); + } + } + } + + void Target_MouseUp(object sender, MouseButtonEventArgs e) + { + IsDown = false; + if (IsActive) { + Complete(); + } + } + + void Complete() + { + IsActive = false; + CurrentListener = null; + + if (Completed != null) { + Completed(this); + } + } + + public event DragHandler Started; + public event DragHandler Changed; + public event DragHandler Completed; + + public IInputElement Target { get; private set; } + public Point StartPoint { get; private set; } + public Point CurrentPoint { get; private set; } + public Vector DeltaDelta { get; private set; } + public bool IsActive { get; private set; } + public bool IsDown { get; private set; } + public bool IsCanceled { get; private set; } + + public Vector Delta { + get { return CurrentPoint - StartPoint; } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/DropDownButton.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/DropDownButton.cs new file mode 100644 index 0000000000..92895d25dd --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/DropDownButton.cs @@ -0,0 +1,33 @@ +// +// +// +// +// $Revision: 3246 $ +// + +using System; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Shapes; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// A button with a drop-down arrow. + /// + public class DropDownButton : Button + { + static readonly Geometry triangle = (Geometry)new GeometryConverter().ConvertFromInvariantString("M0,0 L1,0 0.5,1 z"); + + public DropDownButton() + { + Content = new Path { + Fill = Brushes.Black, + Data = triangle, + Width = 7, + Height = 3.5, + Stretch = Stretch.Fill + }; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnterTextBox.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnterTextBox.cs new file mode 100644 index 0000000000..a88814f70c --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnterTextBox.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Data; +using System.Windows; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + public class EnterTextBox : TextBox + { + protected override void OnKeyDown(KeyEventArgs e) + { + if (e.Key == Key.Enter) { + var b = BindingOperations.GetBindingExpressionBase(this, TextProperty); + if (b != null) { + b.UpdateSource(); + } + SelectAll(); + } + else if (e.Key == Key.Escape) { + var b = BindingOperations.GetBindingExpressionBase(this, TextProperty); + if (b != null) { + b.UpdateTarget(); + } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumBar.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumBar.xaml new file mode 100644 index 0000000000..531721005a --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumBar.xaml @@ -0,0 +1,7 @@ + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumBar.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumBar.xaml.cs new file mode 100644 index 0000000000..8d75cd3c24 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumBar.xaml.cs @@ -0,0 +1,112 @@ +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.Windows.Controls.Primitives; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + public partial class EnumBar + { + public EnumBar() + { + InitializeComponent(); + } + + Type currentEnumType; + + public static readonly DependencyProperty ValueProperty = + DependencyProperty.Register("Value", typeof(object), typeof(EnumBar), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); + + public object Value { + get { return (object)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + public static readonly DependencyProperty ContainerProperty = + DependencyProperty.Register("Container", typeof(Panel), typeof(EnumBar)); + + public Panel Container { + get { return (Panel)GetValue(ContainerProperty); } + set { SetValue(ContainerProperty, value); } + } + + public static readonly DependencyProperty ButtonStyleProperty = + DependencyProperty.Register("ButtonStyle", typeof(Style), typeof(EnumBar)); + + public Style ButtonStyle { + get { return (Style)GetValue(ButtonStyleProperty); } + set { SetValue(ButtonStyleProperty, value); } + } + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + + if (e.Property == ValueProperty) { + + var type = e.NewValue.GetType(); + + if (currentEnumType != type) { + currentEnumType = type; + uxPanel.Children.Clear(); + foreach (var v in Enum.GetValues(type)) { + var b = new EnumButton(); + b.Value = v; + b.Content = Enum.GetName(type, v); + b.SetBinding(StyleProperty, new Binding("ButtonStyle") { Source = this }); + b.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(button_PreviewMouseLeftButtonDown); + uxPanel.Children.Add(b); + } + } + + UpdateButtons(); + UpdateContainer(); + + } else if (e.Property == ContainerProperty) { + UpdateContainer(); + } + } + + void UpdateButtons() + { + foreach (EnumButton c in uxPanel.Children) { + if (c.Value.Equals(Value)) { + c.IsChecked = true; + } + else { + c.IsChecked = false; + } + } + } + + void UpdateContainer() + { + if (Container != null) { + for (int i = 0; i < uxPanel.Children.Count; i++) { + var c = uxPanel.Children[i] as EnumButton; + if (c.IsChecked.Value) + Container.Children[i].Visibility = Visibility.Visible; + else + Container.Children[i].Visibility = Visibility.Collapsed; + } + } + } + + void button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + Value = (sender as EnumButton).Value; + e.Handled = true; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumButton.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumButton.cs new file mode 100644 index 0000000000..1cb487ce90 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/EnumButton.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls.Primitives; +using System.Windows; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + public class EnumButton : ToggleButton + { + static EnumButton() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(EnumButton), + new FrameworkPropertyMetadata(typeof(EnumButton))); + } + + public static readonly DependencyProperty ValueProperty = + DependencyProperty.Register("Value", typeof(object), typeof(EnumButton)); + + public object Value { + get { return (object)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ErrorBalloon.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ErrorBalloon.cs new file mode 100644 index 0000000000..a823961ebe --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ErrorBalloon.cs @@ -0,0 +1,23 @@ +// +// +// +// +// $Revision: 2263 $ +// + +using System; +using System.Windows; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// An ErrorBalloon window. + /// + public class ErrorBalloon : Window + { + static ErrorBalloon() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ErrorBalloon), new FrameworkPropertyMetadata(typeof(ErrorBalloon))); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/GrayOutDesignerExceptActiveArea.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/GrayOutDesignerExceptActiveArea.cs new file mode 100644 index 0000000000..df7d4ed7af --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/GrayOutDesignerExceptActiveArea.cs @@ -0,0 +1,121 @@ +// +// +// +// +// $Revision: 3496 $ +// + +using System; +using System.Diagnostics; +using System.Windows; +using System.Windows.Media; +using System.Windows.Threading; +using System.Windows.Media.Animation; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// Gray out everything except a specific area. + /// + sealed class GrayOutDesignerExceptActiveArea : FrameworkElement + { + Geometry designSurfaceRectangle; + Geometry activeAreaGeometry; + Geometry combinedGeometry; + Brush grayOutBrush; + AdornerPanel adornerPanel; + IDesignPanel designPanel; + const double MaxOpacity = 0.3; + + public GrayOutDesignerExceptActiveArea() + { + this.GrayOutBrush = new SolidColorBrush(SystemColors.GrayTextColor); + this.GrayOutBrush.Opacity = MaxOpacity; + this.IsHitTestVisible = false; + } + + public Brush GrayOutBrush { + get { return grayOutBrush; } + set { grayOutBrush = value; } + } + + public Geometry ActiveAreaGeometry { + get { return activeAreaGeometry; } + set { + activeAreaGeometry = value; + combinedGeometry = new CombinedGeometry(GeometryCombineMode.Exclude, designSurfaceRectangle, activeAreaGeometry); + } + } + + protected override void OnRender(DrawingContext drawingContext) + { + drawingContext.DrawGeometry(grayOutBrush, null, combinedGeometry); + } + + Rect currentAnimateActiveAreaRectToTarget; + + internal void AnimateActiveAreaRectTo(Rect newRect) + { + if (newRect.Equals(currentAnimateActiveAreaRectToTarget)) + return; + activeAreaGeometry.BeginAnimation( + RectangleGeometry.RectProperty, + new RectAnimation(newRect, new Duration(new TimeSpan(0,0,0,0,100))), + HandoffBehavior.SnapshotAndReplace); + currentAnimateActiveAreaRectToTarget = newRect; + } + + internal static void Start(ref GrayOutDesignerExceptActiveArea grayOut, DesignContext context, UIElement activeContainer) + { + Debug.Assert(activeContainer != null); + Start(ref grayOut, context, activeContainer, new Rect(activeContainer.RenderSize)); + } + + internal static void Start(ref GrayOutDesignerExceptActiveArea grayOut, DesignContext context, UIElement activeContainer, Rect activeRectInActiveContainer) + { + Debug.Assert(context != null); + Debug.Assert(activeContainer != null); + DesignPanel designPanel = context.DesignPanel as DesignPanel; + OptionService optionService = context.GetService(); + if (designPanel != null && grayOut == null && optionService != null && optionService.GrayOutDesignSurfaceExceptParentContainerWhenDragging) { + grayOut = new GrayOutDesignerExceptActiveArea(); + grayOut.designSurfaceRectangle = new RectangleGeometry( + new Rect(new Point(0, 0), designPanel.RenderSize)); + grayOut.designPanel = designPanel; + grayOut.adornerPanel = new AdornerPanel(); + grayOut.adornerPanel.Order = AdornerOrder.BehindForeground; + grayOut.adornerPanel.SetAdornedElement(designPanel.Context.ModelService.Root.View, null); + grayOut.adornerPanel.Children.Add(grayOut); + grayOut.ActiveAreaGeometry = new RectangleGeometry(activeRectInActiveContainer, 0, 0, (Transform)activeContainer.TransformToVisual(grayOut.adornerPanel.AdornedElement)); + Animate(grayOut.GrayOutBrush, Brush.OpacityProperty, 0, MaxOpacity); + designPanel.Adorners.Add(grayOut.adornerPanel); + } + } + + static readonly TimeSpan animationTime = new TimeSpan(2000000); + + static void Animate(Animatable element, DependencyProperty property, double from, double to) + { + element.BeginAnimation(property, new DoubleAnimation(from, to, new Duration(animationTime), FillBehavior.Stop)); + } + + internal static void Stop(ref GrayOutDesignerExceptActiveArea grayOut) + { + if (grayOut != null) { + Animate(grayOut.GrayOutBrush, Brush.OpacityProperty, MaxOpacity, 0); + IDesignPanel designPanel = grayOut.designPanel; + AdornerPanel adornerPanelToRemove = grayOut.adornerPanel; + DispatcherTimer timer = new DispatcherTimer(); + timer.Interval = animationTime; + timer.Tick += delegate { + timer.Stop(); + designPanel.Adorners.Remove(adornerPanelToRemove); + }; + timer.Start(); + grayOut = null; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/GridAdorner.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/GridAdorner.cs new file mode 100644 index 0000000000..9de86625a2 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/GridAdorner.cs @@ -0,0 +1,371 @@ +// +// +// +// +// $Revision: 3285 $ +// + +using System; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; + +using ICSharpCode.WpfDesign.Adorners; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// Adorner that displays the blue bar next to grids that can be used to create new rows/column. + /// + public class GridRailAdorner : Control + { + static GridRailAdorner() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(GridRailAdorner), new FrameworkPropertyMetadata(typeof(GridRailAdorner))); + } + + readonly DesignItem gridItem; + readonly Grid grid; + readonly AdornerPanel adornerPanel; + readonly GridSplitterAdorner previewAdorner; + readonly Orientation orientation; + + public const double RailSize = 10; + public const double RailDistance = 6; + public const double SplitterWidth = 10; + + public GridRailAdorner(DesignItem gridItem, AdornerPanel adornerPanel, Orientation orientation) + { + Debug.Assert(gridItem != null); + Debug.Assert(adornerPanel != null); + + this.gridItem = gridItem; + this.grid = (Grid)gridItem.Component; + this.adornerPanel = adornerPanel; + this.orientation = orientation; + + if (orientation == Orientation.Horizontal) { + this.Height = RailSize; + previewAdorner = new GridColumnSplitterAdorner(gridItem, null, null); + } else { // vertical + this.Width = RailSize; + previewAdorner = new GridRowSplitterAdorner(gridItem, null, null); + } + previewAdorner.IsPreview = true; + previewAdorner.IsHitTestVisible = false; + } + + #region Handle mouse events to add a new row/column + protected override void OnMouseEnter(MouseEventArgs e) + { + base.OnMouseEnter(e); + adornerPanel.Children.Add(previewAdorner); + } + + protected override void OnMouseMove(MouseEventArgs e) + { + base.OnMouseMove(e); + RelativePlacement rp = new RelativePlacement(); + if (orientation == Orientation.Vertical) { + rp.XOffset = -(RailSize + RailDistance); + rp.WidthOffset = RailSize + RailDistance; + rp.WidthRelativeToContentWidth = 1; + rp.HeightOffset = SplitterWidth; + rp.YOffset = e.GetPosition(this).Y - SplitterWidth / 2; + } else { + rp.YOffset = -(RailSize + RailDistance); + rp.HeightOffset = RailSize + RailDistance; + rp.HeightRelativeToContentHeight = 1; + rp.WidthOffset = SplitterWidth; + rp.XOffset = e.GetPosition(this).X - SplitterWidth / 2; + } + AdornerPanel.SetPlacement(previewAdorner, rp); + } + + protected override void OnMouseLeave(MouseEventArgs e) + { + base.OnMouseLeave(e); + adornerPanel.Children.Remove(previewAdorner); + } + + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonDown(e); + e.Handled = true; + Focus(); + adornerPanel.Children.Remove(previewAdorner); + if (orientation == Orientation.Vertical) { + using (var changeGroup = gridItem.OpenGroup("Split grid row")) { + DesignItemProperty rowCollection = gridItem.Properties["RowDefinitions"]; + if (rowCollection.CollectionElements.Count == 0) { + DesignItem firstRow = gridItem.Context.ModelService.CreateItem(new RowDefinition()); + rowCollection.CollectionElements.Add(firstRow); + grid.UpdateLayout(); // let WPF assign firstRow.ActualHeight + } + double insertionPosition = e.GetPosition(this).Y; + for (int i = 0; i < grid.RowDefinitions.Count; i++) { + RowDefinition row = grid.RowDefinitions[i]; + if (row.Offset > insertionPosition) continue; + if (row.Offset + row.ActualHeight < insertionPosition) continue; + + // split row + GridLength oldLength = (GridLength)row.GetValue(RowDefinition.HeightProperty); + GridLength newLength1, newLength2; + SplitLength(oldLength, insertionPosition - row.Offset, row.ActualHeight, out newLength1, out newLength2); + DesignItem newRowDefinition = gridItem.Context.ModelService.CreateItem(new RowDefinition()); + rowCollection.CollectionElements.Insert(i + 1, newRowDefinition); + rowCollection.CollectionElements[i].Properties[RowDefinition.HeightProperty].SetValue(newLength1); + newRowDefinition.Properties[RowDefinition.HeightProperty].SetValue(newLength2); + + FixIndicesAfterSplit(i, Grid.RowProperty, Grid.RowSpanProperty); + changeGroup.Commit(); + gridItem.Context.SelectionService.Select(new DesignItem[] { newRowDefinition }, SelectionTypes.Auto); + break; + } + } + } else { + using (var changeGroup = gridItem.OpenGroup("Split grid column")) { + DesignItemProperty columnCollection = gridItem.Properties["ColumnDefinitions"]; + if (columnCollection.CollectionElements.Count == 0) { + DesignItem firstColumn = gridItem.Context.ModelService.CreateItem(new ColumnDefinition()); + columnCollection.CollectionElements.Add(firstColumn); + grid.UpdateLayout(); // let WPF assign firstColumn.ActualWidth + } + double insertionPosition = e.GetPosition(this).X; + for (int i = 0; i < grid.ColumnDefinitions.Count; i++) { + ColumnDefinition column = grid.ColumnDefinitions[i]; + if (column.Offset > insertionPosition) continue; + if (column.Offset + column.ActualWidth < insertionPosition) continue; + + // split column + GridLength oldLength = (GridLength)column.GetValue(ColumnDefinition.WidthProperty); + GridLength newLength1, newLength2; + SplitLength(oldLength, insertionPosition - column.Offset, column.ActualWidth, out newLength1, out newLength2); + DesignItem newColumnDefinition = gridItem.Context.ModelService.CreateItem(new ColumnDefinition()); + columnCollection.CollectionElements.Insert(i + 1, newColumnDefinition); + columnCollection.CollectionElements[i].Properties[ColumnDefinition.WidthProperty].SetValue(newLength1); + newColumnDefinition.Properties[ColumnDefinition.WidthProperty].SetValue(newLength2); + FixIndicesAfterSplit(i, Grid.ColumnProperty, Grid.ColumnSpanProperty); + changeGroup.Commit(); + gridItem.Context.SelectionService.Select(new DesignItem[] { newColumnDefinition }, SelectionTypes.Auto); + break; + } + } + } + } + + void FixIndicesAfterSplit(int splitIndex, DependencyProperty idxProperty, DependencyProperty spanProperty) + { + // increment ColSpan of all controls in the split column, increment Column of all controls in later columns: + foreach (DesignItem child in gridItem.Properties["Children"].CollectionElements) { + int start = (int)child.Properties.GetAttachedProperty(idxProperty).ValueOnInstance; + int span = (int)child.Properties.GetAttachedProperty(spanProperty).ValueOnInstance; + if (start <= splitIndex && splitIndex < start + span) { + child.Properties.GetAttachedProperty(spanProperty).SetValue(span + 1); + } else if (start > splitIndex) { + child.Properties.GetAttachedProperty(idxProperty).SetValue(start + 1); + } + } + } + + void SplitLength(GridLength oldLength, double insertionPosition, double oldActualValue, + out GridLength newLength1, out GridLength newLength2) + { + if (oldLength.IsAuto) { + oldLength = new GridLength(oldActualValue); + } + double percentage = insertionPosition / oldActualValue; + newLength1 = new GridLength(oldLength.Value * percentage, oldLength.GridUnitType); + newLength2 = new GridLength(oldLength.Value - newLength1.Value, oldLength.GridUnitType); + } + #endregion + } + + public abstract class GridSplitterAdorner : Control + { + public static readonly DependencyProperty IsPreviewProperty + = DependencyProperty.Register("IsPreview", typeof(bool), typeof(GridSplitterAdorner), new PropertyMetadata(SharedInstances.BoxedFalse)); + + protected readonly Grid grid; + protected readonly DesignItem gridItem; + protected readonly DesignItem firstRow, secondRow; // can also be columns + + internal GridSplitterAdorner(DesignItem gridItem, DesignItem firstRow, DesignItem secondRow) + { + Debug.Assert(gridItem != null); + this.grid = (Grid)gridItem.Component; + this.gridItem = gridItem; + this.firstRow = firstRow; + this.secondRow = secondRow; + } + + public bool IsPreview { + get { return (bool)GetValue(IsPreviewProperty); } + set { SetValue(IsPreviewProperty, SharedInstances.Box(value)); } + } + + IChangeGroup activeChangeGroup; + double mouseStartPos; + bool mouseIsDown; + + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + e.Handled = true; + if (CaptureMouse()) { + Focus(); + gridItem.Context.SelectionService.Select(new DesignItem[] { secondRow }, SelectionTypes.Auto); + mouseStartPos = GetCoordinate(e.GetPosition(grid)); + mouseIsDown = true; + } + } + + protected override void OnMouseMove(MouseEventArgs e) + { + if (mouseIsDown) { + double mousePos = GetCoordinate(e.GetPosition(grid)); + if (activeChangeGroup == null) { + if (Math.Abs(mousePos - mouseStartPos) + >= GetCoordinate(new Point(SystemParameters.MinimumHorizontalDragDistance, SystemParameters.MinimumVerticalDragDistance))) { + activeChangeGroup = gridItem.OpenGroup("Change grid row/column size"); + RememberOriginalSize(); + } + } + if (activeChangeGroup != null) { + ChangeSize(mousePos - mouseStartPos); + } + } + } + + protected GridLength original1, original2; + protected double originalPixelSize1, originalPixelSize2; + + protected abstract double GetCoordinate(Point point); + protected abstract void RememberOriginalSize(); + protected abstract DependencyProperty RowColumnSizeProperty { get; } + + void ChangeSize(double delta) + { + // delta = difference in pixels + + if (delta < -originalPixelSize1) delta = -originalPixelSize1; + if (delta > originalPixelSize2) delta = originalPixelSize2; + + // replace Auto lengths with absolute lengths if necessary + if (original1.IsAuto) original1 = new GridLength(originalPixelSize1); + if (original2.IsAuto) original2 = new GridLength(originalPixelSize2); + + GridLength new1; + if (original1.IsStar && originalPixelSize1 > 0) + new1 = new GridLength(original1.Value * (originalPixelSize1 + delta) / originalPixelSize1, GridUnitType.Star); + else + new1 = new GridLength(originalPixelSize1 + delta); + GridLength new2; + if (original2.IsStar && originalPixelSize2 > 0) + new2 = new GridLength(original2.Value * (originalPixelSize2 - delta) / originalPixelSize2, GridUnitType.Star); + else + new2 = new GridLength(originalPixelSize2 - delta); + firstRow.Properties[RowColumnSizeProperty].SetValue(new1); + secondRow.Properties[RowColumnSizeProperty].SetValue(new2); + ((UIElement)VisualTreeHelper.GetParent(this)).InvalidateArrange(); + } + + protected override void OnMouseUp(MouseButtonEventArgs e) + { + if (activeChangeGroup != null) { + activeChangeGroup.Commit(); + activeChangeGroup = null; + } + Stop(); + } + + protected override void OnLostMouseCapture(MouseEventArgs e) + { + Stop(); + } + + protected override void OnKeyDown(KeyEventArgs e) + { + if (e.Key == Key.Escape) { + e.Handled = true; + Stop(); + } + } + + protected void Stop() + { + ReleaseMouseCapture(); + mouseIsDown = false; + if (activeChangeGroup != null) { + activeChangeGroup.Abort(); + activeChangeGroup = null; + } + } + } + + public class GridRowSplitterAdorner : GridSplitterAdorner + { + static GridRowSplitterAdorner() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(GridRowSplitterAdorner), new FrameworkPropertyMetadata(typeof(GridRowSplitterAdorner))); + CursorProperty.OverrideMetadata(typeof(GridRowSplitterAdorner), new FrameworkPropertyMetadata(Cursors.SizeNS)); + } + + + internal GridRowSplitterAdorner(DesignItem gridItem, DesignItem firstRow, DesignItem secondRow) : base(gridItem, firstRow, secondRow) + { + } + + protected override double GetCoordinate(Point point) + { + return point.Y; + } + + protected override void RememberOriginalSize() + { + RowDefinition r1 = (RowDefinition)firstRow.Component; + RowDefinition r2 = (RowDefinition)secondRow.Component; + original1 = (GridLength)r1.GetValue(RowDefinition.HeightProperty); + original2 = (GridLength)r2.GetValue(RowDefinition.HeightProperty); + originalPixelSize1 = r1.ActualHeight; + originalPixelSize2 = r2.ActualHeight; + } + + protected override DependencyProperty RowColumnSizeProperty { + get { return RowDefinition.HeightProperty; } + } + } + + public sealed class GridColumnSplitterAdorner : GridSplitterAdorner + { + static GridColumnSplitterAdorner() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(GridColumnSplitterAdorner), new FrameworkPropertyMetadata(typeof(GridColumnSplitterAdorner))); + CursorProperty.OverrideMetadata(typeof(GridColumnSplitterAdorner), new FrameworkPropertyMetadata(Cursors.SizeWE)); + } + + internal GridColumnSplitterAdorner(DesignItem gridItem, DesignItem firstRow, DesignItem secondRow) : base(gridItem, firstRow, secondRow) + { + } + + protected override double GetCoordinate(Point point) + { + return point.X; + } + + protected override void RememberOriginalSize() + { + ColumnDefinition r1 = (ColumnDefinition)firstRow.Component; + ColumnDefinition r2 = (ColumnDefinition)secondRow.Component; + original1 = (GridLength)r1.GetValue(ColumnDefinition.WidthProperty); + original2 = (GridLength)r2.GetValue(ColumnDefinition.WidthProperty); + originalPixelSize1 = r1.ActualWidth; + originalPixelSize2 = r2.ActualWidth; + } + + protected override DependencyProperty RowColumnSizeProperty { + get { return ColumnDefinition.WidthProperty; } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/NumericUpDown.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/NumericUpDown.cs new file mode 100644 index 0000000000..255b35e834 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/NumericUpDown.cs @@ -0,0 +1,302 @@ +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.Windows.Controls.Primitives; +using System.Globalization; +using System.Diagnostics; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + public class NumericUpDown : Control + { + static NumericUpDown() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), + new FrameworkPropertyMetadata(typeof(NumericUpDown))); + } + + TextBox textBox; + DragRepeatButton upButton; + DragRepeatButton downButton; + + public static readonly DependencyProperty DecimalPlacesProperty = + DependencyProperty.Register("DecimalPlaces", typeof(int), typeof(NumericUpDown)); + + public int DecimalPlaces { + get { return (int)GetValue(DecimalPlacesProperty); } + set { SetValue(DecimalPlacesProperty, value); } + } + + public static readonly DependencyProperty MinimumProperty = + DependencyProperty.Register("Minimum", typeof(double), typeof(NumericUpDown)); + + public double Minimum { + get { return (double)GetValue(MinimumProperty); } + set { SetValue(MinimumProperty, value); } + } + + public static readonly DependencyProperty MaximumProperty = + DependencyProperty.Register("Maximum", typeof(double), typeof(NumericUpDown), + new FrameworkPropertyMetadata(100.0)); + + public double Maximum { + get { return (double)GetValue(MaximumProperty); } + set { SetValue(MaximumProperty, value); } + } + + public static readonly DependencyProperty ValueProperty = + DependencyProperty.Register("Value", typeof(double), typeof(NumericUpDown), + new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)); + + public double Value { + get { return (double)GetValue(ValueProperty); } + set { SetValue(ValueProperty, value); } + } + + public static readonly DependencyProperty SmallChangeProperty = + DependencyProperty.Register("SmallChange", typeof(double), typeof(NumericUpDown), + new FrameworkPropertyMetadata(1.0)); + + public double SmallChange { + get { return (double)GetValue(SmallChangeProperty); } + set { SetValue(SmallChangeProperty, value); } + } + + public static readonly DependencyProperty LargeChangeProperty = + DependencyProperty.Register("LargeChange", typeof(double), typeof(NumericUpDown), + new FrameworkPropertyMetadata(10.0)); + + public double LargeChange { + get { return (double)GetValue(LargeChangeProperty); } + set { SetValue(LargeChangeProperty, value); } + } + + bool IsDragging { + get { + return upButton.IsDragging; + } + set { + upButton.IsDragging = value; downButton.IsDragging = value; + } + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + upButton = (DragRepeatButton)Template.FindName("PART_UpButton", this); + downButton = (DragRepeatButton)Template.FindName("PART_DownButton", this); + textBox = (TextBox)Template.FindName("PART_TextBox", this); + + upButton.Click += new RoutedEventHandler(upButton_Click); + downButton.Click += new RoutedEventHandler(downButton_Click); + + var upDrag = new DragListener(upButton); + var downDrag = new DragListener(downButton); + + upDrag.Started += drag_Started; + upDrag.Changed += drag_Changed; + upDrag.Completed += drag_Completed; + + downDrag.Started += drag_Started; + downDrag.Changed += drag_Changed; + downDrag.Completed += drag_Completed; + + Print(); + } + + void drag_Started(DragListener drag) + { + OnDragStarted(); + } + + void drag_Changed(DragListener drag) + { + IsDragging = true; + MoveValue(-drag.DeltaDelta.Y * SmallChange); + } + + void drag_Completed(DragListener drag) + { + IsDragging = false; + OnDragCompleted(); + } + + void downButton_Click(object sender, RoutedEventArgs e) + { + if (!IsDragging) SmallDown(); + } + + void upButton_Click(object sender, RoutedEventArgs e) + { + if (!IsDragging) SmallUp(); + } + + protected virtual void OnDragStarted() + { + } + + protected virtual void OnDragCompleted() + { + } + + public void SmallUp() + { + MoveValue(SmallChange); + } + + public void SmallDown() + { + MoveValue(-SmallChange); + } + + public void LargeUp() + { + MoveValue(LargeChange); + } + + public void LargeDown() + { + MoveValue(-LargeChange); + } + + void MoveValue(double delta) + { + double result; + if (double.IsNaN(Value) || double.IsInfinity(Value)) { + SetValue(delta); + } + else if (double.TryParse(textBox.Text, out result)) { + SetValue(result + delta); + } + else { + SetValue(Value + delta); + } + } + + void Print() + { + if (textBox != null) { + textBox.Text = Value.ToString("F" + DecimalPlaces); + textBox.CaretIndex = int.MaxValue; + } + } + + //wpf bug?: Value = -1 updates bindings without coercing, workaround + //update: not derived from RangeBase - no problem + void SetValue(double newValue) + { + newValue = CoerceValue(newValue); + if (Value != newValue) { + Value = newValue; + } + } + + double CoerceValue(double newValue) + { + return Math.Max(Minimum, Math.Min(newValue, Maximum)); + } + + protected override void OnPreviewKeyDown(KeyEventArgs e) + { + base.OnPreviewKeyDown(e); + if (e.Key == Key.Enter) { + double result; + if (double.TryParse(textBox.Text, out result)) { + SetValue(result); + } + else { + Print(); + } + textBox.SelectAll(); + e.Handled = true; + } + else if (e.Key == Key.Up) { + SmallUp(); + e.Handled = true; + } + else if (e.Key == Key.Down) { + SmallDown(); + e.Handled = true; + } + else if (e.Key == Key.PageUp) { + LargeUp(); + e.Handled = true; + } + else if (e.Key == Key.PageDown) { + LargeDown(); + e.Handled = true; + } + //else if (e.Key == Key.Home) { + // Maximize(); + // e.Handled = true; + //} + //else if (e.Key == Key.End) { + // Minimize(); + // e.Handled = true; + //} + } + + //protected override void OnMouseWheel(MouseWheelEventArgs e) + //{ + // if (e.Delta > 0) + // { + // if (Keyboard.IsKeyDown(Key.LeftShift)) + // { + // LargeUp(); + // } + // else + // { + // SmallUp(); + // } + // } + // else + // { + // if (Keyboard.IsKeyDown(Key.LeftShift)) + // { + // LargeDown(); + // } + // else + // { + // SmallDown(); + // } + // } + // e.Handled = true; + //} + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + + if (e.Property == ValueProperty) { + SetValue((double)e.NewValue); + Print(); + } + else if (e.Property == SmallChangeProperty && + ReadLocalValue(LargeChangeProperty) == DependencyProperty.UnsetValue) { + LargeChange = SmallChange * 10; + } + } + } + + public class DragRepeatButton : RepeatButton + { + public static readonly DependencyProperty IsDraggingProperty = + DependencyProperty.Register("IsDragging", typeof(bool), typeof(DragRepeatButton)); + + public bool IsDragging { + get { return (bool)GetValue(IsDraggingProperty); } + set { SetValue(IsDraggingProperty, value); } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/NumericUpDown.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/NumericUpDown.xaml new file mode 100644 index 0000000000..224930ac98 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/NumericUpDown.xaml @@ -0,0 +1,149 @@ + + + + + #DADFEA + #E6EBEF + #B6BDD3 + #7F9DB9 + Black + #B6BDD3 + + + + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/PanelMoveAdorner.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/PanelMoveAdorner.cs new file mode 100644 index 0000000000..b06f7531b2 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/PanelMoveAdorner.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls; +using System.Windows; +using System.Windows.Input; +using ICSharpCode.WpfDesign.Designer.Services; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + public class PanelMoveAdorner : Control + { + static PanelMoveAdorner() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(PanelMoveAdorner), + new FrameworkPropertyMetadata(typeof(PanelMoveAdorner))); + } + + public PanelMoveAdorner(DesignItem item) + { + this.item = item; + } + + DesignItem item; + + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + e.Handled = true; + item.Context.SelectionService.Select(new DesignItem[] { item }, SelectionTypes.Auto); + new DragMoveMouseGesture(item, false).Start(item.Context.DesignPanel, e); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ResizeThumb.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ResizeThumb.cs new file mode 100644 index 0000000000..a917cc73b4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ResizeThumb.cs @@ -0,0 +1,89 @@ +// +// +// +// +// $Revision: 2415 $ +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Windows; +using System.Windows.Input; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// A thumb where the look can depend on the IsPrimarySelection property. + /// + public class ResizeThumb : Thumb + { + /// + /// Dependency property for . + /// + public static readonly DependencyProperty IsPrimarySelectionProperty + = DependencyProperty.Register("IsPrimarySelection", typeof(bool), typeof(ResizeThumb)); + + /// + /// Dependency property for . + /// + public static readonly DependencyProperty ResizeThumbVisibleProperty + = DependencyProperty.Register("ResizeThumbVisible", typeof(bool), typeof(ResizeThumb), new FrameworkPropertyMetadata(true)); + + internal PlacementAlignment Alignment; + + static ResizeThumb() + { + //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. + //This style is defined in themes\generic.xaml + DefaultStyleKeyProperty.OverrideMetadata(typeof(ResizeThumb), new FrameworkPropertyMetadata(typeof(ResizeThumb))); + } + + /// + /// Gets/Sets if the resize thumb is attached to the primary selection. + /// + public bool IsPrimarySelection { + get { return (bool)GetValue(IsPrimarySelectionProperty); } + set { SetValue(IsPrimarySelectionProperty, value); } + } + + /// + /// Gets/Sets if the resize thumb is visible. + /// + public bool ResizeThumbVisible { + get { return (bool)GetValue(ResizeThumbVisibleProperty); } + set { SetValue(ResizeThumbVisibleProperty, value); } + } + } + + /// + /// Resize thumb that automatically disappears if the adornered element is too small. + /// + sealed class ResizeThumbImpl : ResizeThumb + { + bool checkWidth, checkHeight; + + internal ResizeThumbImpl(bool checkWidth, bool checkHeight) + { + Debug.Assert((checkWidth && checkHeight) == false); + this.checkWidth = checkWidth; + this.checkHeight = checkHeight; + } + + protected override Size ArrangeOverride(Size arrangeBounds) + { + AdornerPanel parent = this.Parent as AdornerPanel; + if (parent != null && parent.AdornedElement != null) { + if (checkWidth) + this.ResizeThumbVisible = parent.AdornedElement.RenderSize.Width > 14; + else if (checkHeight) + this.ResizeThumbVisible = parent.AdornedElement.RenderSize.Height > 14; + } + return base.ArrangeOverride(arrangeBounds); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/SelectionFrame.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/SelectionFrame.cs new file mode 100644 index 0000000000..57451c0ac3 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/SelectionFrame.cs @@ -0,0 +1,32 @@ +// +// +// +// +// $Revision: 3283 $ +// + +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; + +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// The rectangle shown during a rubber-band selecting operation. + /// + public class SelectionFrame : Control + { + static SelectionFrame() + { + //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. + //This style is defined in themes\generic.xaml + DefaultStyleKeyProperty.OverrideMetadata(typeof(SelectionFrame), new FrameworkPropertyMetadata(typeof(SelectionFrame))); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/WindowClone.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/WindowClone.cs new file mode 100644 index 0000000000..3bdaea2b34 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/WindowClone.cs @@ -0,0 +1,212 @@ +// +// +// +// +// $Revision: 3210 $ +// + +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; + +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + /// + /// A custom control that imitates the properties of , but is not a top-level control. + /// + [ReplacerFor(typeof(Window))] + public class WindowClone : ContentControl + { + static WindowClone() + { + //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class. + //This style is defined in themes\generic.xaml + DefaultStyleKeyProperty.OverrideMetadata(typeof(WindowClone), new FrameworkPropertyMetadata(typeof(WindowClone))); + + Control.IsTabStopProperty.OverrideMetadata(typeof(WindowClone), new FrameworkPropertyMetadata(SharedInstances.BoxedFalse)); + KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(WindowClone), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); + KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(WindowClone), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); + KeyboardNavigation.ControlTabNavigationProperty.OverrideMetadata(typeof(WindowClone), new FrameworkPropertyMetadata(KeyboardNavigationMode.Cycle)); + FocusManager.IsFocusScopeProperty.OverrideMetadata(typeof(WindowClone), new FrameworkPropertyMetadata(SharedInstances.BoxedTrue)); + } + + /// + /// This property has no effect. (for compatibility with only). + /// + public bool AllowsTransparency { + get { return (bool)GetValue(Window.AllowsTransparencyProperty); } + set { SetValue(Window.AllowsTransparencyProperty, SharedInstances.Box(value)); } + } + + /// + /// This property has no effect. (for compatibility with only). + /// + [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), TypeConverter(typeof(DialogResultConverter))] + public bool? DialogResult { + get { + return null; + } + set { } + } + + /// + /// Specifies the icon to use. + /// + public ImageSource Icon { + get { return (ImageSource)GetValue(Window.IconProperty); } + set { SetValue(Window.IconProperty, value); } + } + + /// + /// This property has no effect. (for compatibility with only). + /// + [TypeConverter(typeof(LengthConverter))] + public double Left { + get { return (double)GetValue(Window.LeftProperty); } + set { SetValue(Window.LeftProperty, value); } + } + + Window owner; + + /// + /// This property has no effect. (for compatibility with only). + /// + public Window Owner { + get { return owner; } + set { owner = value; } + } + + /// + /// Gets or sets the resize mode. + /// + public ResizeMode ResizeMode { + get { return (ResizeMode)GetValue(Window.ResizeModeProperty); } + set { SetValue(Window.ResizeModeProperty, value); } + } + + public static readonly DependencyProperty ShowActivatedProperty = + DependencyProperty.Register("ShowActivated", typeof(bool), typeof(WindowClone)); + + public bool ShowActivated { + get { return (bool)GetValue(ShowActivatedProperty); } + set { SetValue(ShowActivatedProperty, value); } + } + + /// + /// This property has no effect. (for compatibility with only). + /// + public bool ShowInTaskbar { + get { return (bool)GetValue(Window.ShowInTaskbarProperty); } + set { SetValue(Window.ShowInTaskbarProperty, SharedInstances.Box(value)); } + } + + /// + /// Gets or sets a value that specifies whether a window will automatically size itself to fit the size of its content. + /// + public SizeToContent SizeToContent { + get { return (SizeToContent)GetValue(Window.SizeToContentProperty); } + set { SetValue(Window.SizeToContentProperty, value); } + } + + /// + /// The title to display in the Window's title bar. + /// + public string Title { + get { return (string)GetValue(Window.TitleProperty); } + set { SetValue(Window.TitleProperty, value); } + } + + /// + /// This property has no effect. (for compatibility with only). + /// + [TypeConverter(typeof(LengthConverter))] + public double Top { + get { return (double)GetValue(Window.TopProperty); } + set { SetValue(Window.TopProperty, value); } + } + + /// + /// This property has no effect. (for compatibility with only). + /// + public bool Topmost { + get { return (bool)GetValue(Window.TopmostProperty); } + set { SetValue(Window.TopmostProperty, SharedInstances.Box(value)); } + } + + WindowStartupLocation windowStartupLocation; + + /// + /// This property has no effect. (for compatibility with only). + /// + public WindowStartupLocation WindowStartupLocation { + get { return windowStartupLocation; } + set { windowStartupLocation = value; } + } + + /// + /// This property has no effect. (for compatibility with only). + /// + public WindowState WindowState { + get { return (WindowState) GetValue(Window.WindowStateProperty); } + set { SetValue(Window.WindowStateProperty, value); } + } + + /// + /// This property has no effect. (for compatibility with only). + /// + public WindowStyle WindowStyle { + get { return (WindowStyle)GetValue(Window.WindowStyleProperty); } + set { SetValue(Window.WindowStyleProperty, value); } + } + + #pragma warning disable 0067 + // disable "event is never used" warning + + /// + /// This event is never raised. (for compatibility with only). + /// + public event EventHandler Activated; + + /// + /// This event is never raised. (for compatibility with only). + /// + public event EventHandler Closed; + + /// + /// This event is never raised. (for compatibility with only). + /// + public event EventHandler Closing; + + /// + /// This event is never raised. (for compatibility with only). + /// + public event EventHandler ContentRendered; + + /// + /// This event is never raised. (for compatibility with only). + /// + public event EventHandler Deactivated; + + /// + /// This event is never raised. (for compatibility with only). + /// + public event EventHandler LocationChanged; + + /// + /// This event is never raised. (for compatibility with only). + /// + public event EventHandler SourceInitialized; + + /// + /// This event is never raised. (for compatibility with only). + /// + public event EventHandler StateChanged; + #pragma warning restore + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ZoomControl.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ZoomControl.cs new file mode 100644 index 0000000000..74e8211fe8 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Controls/ZoomControl.cs @@ -0,0 +1,201 @@ +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.Windows.Controls.Primitives; +using System.IO; +using System.Reflection; +using System.Resources; + +namespace ICSharpCode.WpfDesign.Designer.Controls +{ + public class ZoomControl : ContentControl + { + static ZoomControl() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(ZoomControl), + new FrameworkPropertyMetadata(typeof(ZoomControl))); + + PanToolCursor = new Cursor(GetStream("Images/PanToolCursor.cur")); + PanToolCursorMouseDown = new Cursor(GetStream("Images/PanToolCursorMouseDown.cur")); + } + + static Stream GetStream(string path) + { + var a = Assembly.GetExecutingAssembly(); + var m = new ResourceManager(a.GetName().Name + ".g", a); + var s = m.GetStream(path.ToLower()); + return s; + } + + static Cursor PanToolCursor; + static Cursor PanToolCursorMouseDown; + public static double ZoomFactor = 1.1; + public static double Minimum = 0.1; + public static double Maximum = 10; + + double startHorizontalOffset; + double startVericalOffset; + + internal ScrollViewer ScrollViewer; + Border container; + ScaleTransform transform; + Point startPoint; + bool isMouseDown; + bool pan; + + public static readonly DependencyProperty ZoomProperty = + DependencyProperty.Register("Zoom", typeof(double), typeof(ZoomControl), + new PropertyMetadata(1.0, null, CoerceZoom)); + + public double Zoom + { + get { return (double)GetValue(ZoomProperty); } + set { SetValue(ZoomProperty, value); } + } + + static object CoerceZoom(DependencyObject d, object baseValue) + { + var zoom = (double)baseValue; + return Math.Max(Minimum, Math.Min(Maximum, zoom)); + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + ScrollViewer = (ScrollViewer)Template.FindName("scrollViewer", this); + container = (Border)Template.FindName("container", this); + transform = new ScaleTransform(); + container.LayoutTransform = transform; + + var uxPlus = (ButtonBase)Template.FindName("uxPlus", this); + var uxMinus = (ButtonBase)Template.FindName("uxMinus", this); + var uxReset = (ButtonBase)Template.FindName("uxReset", this); + + uxPlus.Click += delegate { ZoomIn(); }; + uxMinus.Click += delegate { ZoomOut(); }; + uxReset.Click += delegate { Reset(); }; + } + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + if (e.Property == ZoomProperty) + { + transform.ScaleX = Zoom; + transform.ScaleY = Zoom; + CenterViewport((double)e.OldValue); + } + } + + protected override void OnKeyDown(KeyEventArgs e) + { + if (!pan && e.Key == Key.Space) + { + Cursor = PanToolCursor; + pan = true; + } + } + + protected override void OnKeyUp(KeyEventArgs e) + { + if (e.Key == Key.Space) + { + ClearValue(CursorProperty); + pan = false; + } + } + + protected override void OnPreviewMouseDown(MouseButtonEventArgs e) + { + if (pan) + { + Cursor = PanToolCursorMouseDown; + Mouse.Capture(this); // will call move + isMouseDown = true; + startPoint = e.GetPosition(this); + PanStart(); + } + } + + protected override void OnPreviewMouseMove(MouseEventArgs e) + { + if (isMouseDown && pan) + { + var endPoint = e.GetPosition(this); + PanContinue(endPoint - startPoint); + } + } + + protected override void OnPreviewMouseUp(MouseButtonEventArgs e) + { + if (isMouseDown) + { + Cursor = PanToolCursor; + isMouseDown = false; + Mouse.Capture(null); + } + } + + protected override void OnMouseEnter(MouseEventArgs e) + { + //TODO + //Focus(); + } + + public void Fit() + { + Zoom = Math.Min( + ScrollViewer.ActualWidth / container.ActualWidth, + ScrollViewer.ActualHeight / container.ActualHeight); + } + + public void ZoomIn() + { + Zoom *= ZoomFactor; + } + + public void ZoomOut() + { + Zoom /= ZoomFactor; + } + + public void Reset() + { + Zoom = 1; + ScrollViewer.ScrollToHorizontalOffset(0); + ScrollViewer.ScrollToVerticalOffset(0); + } + + void PanStart() + { + startHorizontalOffset = ScrollViewer.HorizontalOffset; + startVericalOffset = ScrollViewer.VerticalOffset; + } + + void PanContinue(Vector delta) + { + ScrollViewer.ScrollToHorizontalOffset(startHorizontalOffset - delta.X); + ScrollViewer.ScrollToVerticalOffset(startVericalOffset - delta.Y); + } + + void CenterViewport(double oldZoom) + { + var k = Zoom / oldZoom; + var add = (k * ScrollViewer.ViewportWidth - ScrollViewer.ViewportWidth) / 2; + ScrollViewer.ScrollToHorizontalOffset(k * ScrollViewer.HorizontalOffset + add); + add = (k * ScrollViewer.ViewportHeight - ScrollViewer.ViewportHeight) / 2; + ScrollViewer.ScrollToVerticalOffset(k * ScrollViewer.VerticalOffset + add); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/BorderForInvisibleControl.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/BorderForInvisibleControl.cs new file mode 100644 index 0000000000..95e048c4ac --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/BorderForInvisibleControl.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; +using System.Windows.Controls; +using System.Windows; +using ICSharpCode.WpfDesign.Designer.Controls; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + [ExtensionFor(typeof(Panel))] + public class BorderForInvisibleControl : PermanentAdornerProvider + { + protected override void OnInitialized() + { + base.OnInitialized(); + + var adornerPanel = new AdornerPanel(); + var border = new Border(); + border.BorderThickness = new Thickness(1); + border.BorderBrush = Brushes.WhiteSmoke; + border.IsHitTestVisible = false; + AdornerPanel.SetPlacement(border, AdornerPlacement.FillContent); + adornerPanel.Children.Add(border); + Adorners.Add(adornerPanel); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/CanvasPlacementSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/CanvasPlacementSupport.cs new file mode 100644 index 0000000000..75df141cdc --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/CanvasPlacementSupport.cs @@ -0,0 +1,84 @@ +// +// +// +// +// $Revision: 3337 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; + +using ICSharpCode.WpfDesign.Designer.Controls; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Provides behavior for . + /// + [ExtensionFor(typeof(Canvas), OverrideExtension=typeof(DefaultPlacementBehavior))] + public sealed class CanvasPlacementSupport : SnaplinePlacementBehavior + { + static double GetLeft(UIElement element) + { + double v = (double)element.GetValue(Canvas.LeftProperty); + if (double.IsNaN(v)) + return 0; + else + return v; + } + + static double GetTop(UIElement element) + { + double v = (double)element.GetValue(Canvas.TopProperty); + if (double.IsNaN(v)) + return 0; + else + return v; + } + + //TODO: Is default way ok? + //public override Rect GetPosition(PlacementOperation operation, DesignItem childItem) + //{ + // UIElement child = childItem.View; + // return new Rect(GetLeft(child), GetTop(child), ModelTools.GetWidth(child), ModelTools.GetHeight(child)); + //} + + public override void SetPosition(PlacementInformation info) + { + base.SetPosition(info); + info.Item.Properties[FrameworkElement.MarginProperty].Reset(); + + UIElement child = info.Item.View; + Rect newPosition = info.Bounds; + + if (newPosition.Left != GetLeft(child)) { + info.Item.Properties.GetAttachedProperty(Canvas.LeftProperty).SetValue(newPosition.Left); + } + if (newPosition.Top != GetTop(child)) { + info.Item.Properties.GetAttachedProperty(Canvas.TopProperty).SetValue(newPosition.Top); + } + } + + public override void LeaveContainer(PlacementOperation operation) + { + base.LeaveContainer(operation); + foreach (PlacementInformation info in operation.PlacedItems) { + info.Item.Properties.GetAttachedProperty(Canvas.LeftProperty).Reset(); + info.Item.Properties.GetAttachedProperty(Canvas.TopProperty).Reset(); + } + } + + public override void EnterContainer(PlacementOperation operation) + { + base.EnterContainer(operation); + foreach (PlacementInformation info in operation.PlacedItems) { + info.Item.Properties[FrameworkElement.HorizontalAlignmentProperty].Reset(); + info.Item.Properties[FrameworkElement.VerticalAlignmentProperty].Reset(); + info.Item.Properties[FrameworkElement.MarginProperty].Reset(); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/DefaultPlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/DefaultPlacementBehavior.cs new file mode 100644 index 0000000000..717942efec --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/DefaultPlacementBehavior.cs @@ -0,0 +1,95 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.WpfDesign.Extensions; +using System.Windows.Controls; +using System.Windows; +using ICSharpCode.WpfDesign.Designer.Controls; +using System.Diagnostics; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + [ExtensionFor(typeof(UIElement))] + public class DefaultPlacementBehavior : BehaviorExtension, IPlacementBehavior + { + protected override void OnInitialized() + { + base.OnInitialized(); + if (ExtendedItem.Content == null || + Metadata.IsPlacementDisabled(ExtendedItem.ComponentType)) + return; + ExtendedItem.AddBehavior(typeof(IPlacementBehavior), this); + } + + public virtual bool CanPlace(IEnumerable childItems, PlacementType type, PlacementAlignment position) + { + return true; + } + + public virtual void BeginPlacement(PlacementOperation operation) + { + } + + public virtual void EndPlacement(PlacementOperation operation) + { + } + + public virtual Rect GetPosition(PlacementOperation operation, DesignItem item) + { + var p = item.View.TranslatePoint(new Point(), operation.CurrentContainer.View); + return new Rect(p, item.View.RenderSize); + } + + public virtual void BeforeSetPosition(PlacementOperation operation) + { + } + + public virtual void SetPosition(PlacementInformation info) + { + ModelTools.Resize(info.Item, info.Bounds.Width, info.Bounds.Height); + } + + public virtual bool CanLeaveContainer(PlacementOperation operation) + { + return true; + } + + public virtual void LeaveContainer(PlacementOperation operation) + { + if (ExtendedItem.Content.IsCollection) { + foreach (var info in operation.PlacedItems) { + ExtendedItem.Content.CollectionElements.Remove(info.Item); + } + } else { + ExtendedItem.Content.Reset(); + } + } + + public virtual bool CanEnterContainer(PlacementOperation operation) + { + if (ExtendedItem.Content.IsCollection && + ICSharpCode.Xaml.CollectionSupport.CanCollectionAdd(ExtendedItem.Content.ReturnType, + operation.PlacedItems.Select(p => p.Item.Component))) + return true; + return !ExtendedItem.Content.IsSet; + } + + public virtual void EnterContainer(PlacementOperation operation) + { + if (ExtendedItem.Content.IsCollection) { + foreach (var info in operation.PlacedItems) { + ExtendedItem.Content.CollectionElements.Add(info.Item); + } + } else { + ExtendedItem.Content.SetValue(operation.PlacedItems[0].Item); + } + if (operation.Type == PlacementType.AddItem) { + foreach (var info in operation.PlacedItems) { + SetPosition(info); + } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/GridAdornerProvider.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/GridAdornerProvider.cs new file mode 100644 index 0000000000..687760eff9 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/GridAdornerProvider.cs @@ -0,0 +1,136 @@ +// +// +// +// +// $Revision: 3088 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Threading; + +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Designer.Controls; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Allows arranging the rows/column on a grid. + /// + [ExtensionFor(typeof(Grid))] + [ExtensionServer(typeof(LogicalOrExtensionServer))] + public class GridAdornerProvider : AdornerProvider + { + sealed class RowSplitterPlacement : AdornerPlacement + { + readonly RowDefinition row; + public RowSplitterPlacement(RowDefinition row) { this.row = row; } + + public override void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize) + { + adorner.Arrange(new Rect(-(GridRailAdorner.RailSize + GridRailAdorner.RailDistance), + row.Offset - GridRailAdorner.SplitterWidth / 2, + GridRailAdorner.RailSize + GridRailAdorner.RailDistance + adornedElementSize.Width, + GridRailAdorner.SplitterWidth)); + } + } + + sealed class ColumnSplitterPlacement : AdornerPlacement + { + readonly ColumnDefinition column; + public ColumnSplitterPlacement(ColumnDefinition column) { this.column = column; } + + public override void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize) + { + adorner.Arrange(new Rect(column.Offset - GridRailAdorner.SplitterWidth / 2, + -(GridRailAdorner.RailSize + GridRailAdorner.RailDistance), + GridRailAdorner.SplitterWidth, + GridRailAdorner.RailSize + GridRailAdorner.RailDistance + adornedElementSize.Height)); + } + } + + AdornerPanel adornerPanel = new AdornerPanel(); + GridRailAdorner topBar, leftBar; + + protected override void OnInitialized() + { + leftBar = new GridRailAdorner(this.ExtendedItem, adornerPanel, Orientation.Vertical); + topBar = new GridRailAdorner(this.ExtendedItem, adornerPanel, Orientation.Horizontal); + + RelativePlacement rp = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Stretch); + rp.XOffset -= GridRailAdorner.RailDistance; + AdornerPanel.SetPlacement(leftBar, rp); + rp = new RelativePlacement(HorizontalAlignment.Stretch, VerticalAlignment.Top); + rp.YOffset -= GridRailAdorner.RailDistance; + AdornerPanel.SetPlacement(topBar, rp); + + adornerPanel.Children.Add(leftBar); + adornerPanel.Children.Add(topBar); + this.Adorners.Add(adornerPanel); + + CreateSplitter(); + this.ExtendedItem.ModelChanged += OnModelChanged; + + base.OnInitialized(); + } + + protected override void OnRemove() + { + this.ExtendedItem.ModelChanged -= OnModelChanged; + base.OnRemove(); + } + + void OnModelChanged(object sender, ModelChangedEventArgs e) + { + if (e.Property.Name == "RowDefinitions" || e.Property.Name == "ColumnDefinitions") { + CreateSplitter(); + } + } + + readonly List splitterList = new List(); + /// + /// flag used to ensure that the asynchronus splitter creation is only enqueued once + /// + bool requireSplitterRecreation; + + void CreateSplitter() + { + if (requireSplitterRecreation) return; + requireSplitterRecreation = true; + + // splitter creation is delayed to prevent unnecessary splitter re-creation when multiple + // changes to the collection are done. + // It also ensures that the Offset property of new rows/columns is initialized when the splitter + // is added. + Dispatcher.CurrentDispatcher.BeginInvoke( + DispatcherPriority.Loaded, // Loaded = after layout, but before input + (Action)delegate { + requireSplitterRecreation = false; + foreach (GridSplitterAdorner splitter in splitterList) { + adornerPanel.Children.Remove(splitter); + } + splitterList.Clear(); + Grid grid = (Grid)this.ExtendedItem.Component; + IList col = this.ExtendedItem.Properties["RowDefinitions"].CollectionElements; + for (int i = 1; i < grid.RowDefinitions.Count; i++) { + RowDefinition row = grid.RowDefinitions[i]; + GridRowSplitterAdorner splitter = new GridRowSplitterAdorner(this.ExtendedItem, col[i-1], col[i]); + AdornerPanel.SetPlacement(splitter, new RowSplitterPlacement(row)); + adornerPanel.Children.Add(splitter); + splitterList.Add(splitter); + } + col = this.ExtendedItem.Properties["ColumnDefinitions"].CollectionElements; + for (int i = 1; i < grid.ColumnDefinitions.Count; i++) { + ColumnDefinition column = grid.ColumnDefinitions[i]; + GridColumnSplitterAdorner splitter = new GridColumnSplitterAdorner(this.ExtendedItem, col[i-1], col[i]); + AdornerPanel.SetPlacement(splitter, new ColumnSplitterPlacement(column)); + adornerPanel.Children.Add(splitter); + splitterList.Add(splitter); + } + }); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/GridPlacementSupport.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/GridPlacementSupport.cs new file mode 100644 index 0000000000..3476b03f70 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/GridPlacementSupport.cs @@ -0,0 +1,292 @@ +// +// +// +// +// $Revision: 3496 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Diagnostics; +using System.Windows.Controls; +using System.Windows.Media; + +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; +using ICSharpCode.WpfDesign.Designer.Controls; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Provides behavior for . + /// + [ExtensionFor(typeof(Grid), OverrideExtension=typeof(DefaultPlacementBehavior))] + public sealed class GridPlacementSupport : SnaplinePlacementBehavior + { + Grid grid; + + protected override void OnInitialized() + { + base.OnInitialized(); + grid = (Grid)this.ExtendedItem.Component; + } + + //TODO: Is default way ok? + //public override Rect GetPosition(PlacementOperation operation, DesignItem child) + //{ + // FrameworkElement obj = child.Component as FrameworkElement; + // if (obj == null) return new Rect(); + + // Thickness margin = obj.Margin; + + // double left, width, right; + // switch (obj.HorizontalAlignment) { + // case HorizontalAlignment.Stretch: + // left = GetColumnOffset(Grid.GetColumn(obj)) + margin.Left; + // right = GetColumnOffset(Grid.GetColumn(obj) + Grid.GetColumnSpan(obj)) - margin.Right; + // width = right - left; + // break; + // case HorizontalAlignment.Left: + // left = GetColumnOffset(Grid.GetColumn(obj)) + margin.Left; + // width = ModelTools.GetWidth(obj); + // right = left + width; + // break; + // case HorizontalAlignment.Right: + // right = GetColumnOffset(Grid.GetColumn(obj) + Grid.GetColumnSpan(obj)) - margin.Right; + // width = ModelTools.GetWidth(obj); + // left = right - width; + // break; + // case HorizontalAlignment.Center: + // throw new NotImplementedException(); + // default: + // throw new NotSupportedException(); + // } + + // double top, height, bottom; + // switch (obj.VerticalAlignment) { + // case VerticalAlignment.Stretch: + // top = GetRowOffset(Grid.GetRow(obj)) + margin.Top; + // bottom = GetRowOffset(Grid.GetRow(obj) + Grid.GetRowSpan(obj)) - margin.Bottom; + // height = bottom - top; + // break; + // case VerticalAlignment.Top: + // top = GetRowOffset(Grid.GetRow(obj)) + margin.Top; + // height = ModelTools.GetHeight(obj); + // bottom = top + height; + // break; + // case VerticalAlignment.Bottom: + // bottom = GetRowOffset(Grid.GetRow(obj) + Grid.GetRowSpan(obj)) - margin.Bottom; + // height = ModelTools.GetHeight(obj); + // top = bottom - height; + // break; + // case VerticalAlignment.Center: + // throw new NotImplementedException(); + // default: + // throw new NotSupportedException(); + // } + // return new Rect(left, top, Math.Max(0, width), Math.Max(0, height)); + //} + + double GetColumnOffset(int index) + { + // when the grid has no columns, we still need to return 0 for index=0 and grid.Width for index=1 + if (index == 0) + return 0; + else if (index < grid.ColumnDefinitions.Count) + return grid.ColumnDefinitions[index].Offset; + else + return grid.ActualWidth; + } + + double GetRowOffset(int index) + { + if (index == 0) + return 0; + else if (index < grid.RowDefinitions.Count) + return grid.RowDefinitions[index].Offset; + else + return grid.ActualHeight; + } + + const double epsilon = 0.00000001; + + int GetColumnIndex(double x) + { + if (grid.ColumnDefinitions.Count == 0) + return 0; + for (int i = 1; i < grid.ColumnDefinitions.Count; i++) { + if (x < grid.ColumnDefinitions[i].Offset - epsilon) + return i - 1; + } + return grid.ColumnDefinitions.Count - 1; + } + + int GetRowIndex(double y) + { + if (grid.RowDefinitions.Count == 0) + return 0; + for (int i = 1; i < grid.RowDefinitions.Count; i++) { + if (y < grid.RowDefinitions[i].Offset - epsilon) + return i - 1; + } + return grid.RowDefinitions.Count - 1; + } + + int GetEndColumnIndex(double x) + { + if (grid.ColumnDefinitions.Count == 0) + return 0; + for (int i = 1; i < grid.ColumnDefinitions.Count; i++) { + if (x <= grid.ColumnDefinitions[i].Offset + epsilon) + return i - 1; + } + return grid.ColumnDefinitions.Count - 1; + } + + int GetEndRowIndex(double y) + { + if (grid.RowDefinitions.Count == 0) + return 0; + for (int i = 1; i < grid.RowDefinitions.Count; i++) { + if (y <= grid.RowDefinitions[i].Offset + epsilon) + return i - 1; + } + return grid.RowDefinitions.Count - 1; + } + + static void SetColumn(DesignItem item, int column, int columnSpan) + { + Debug.Assert(item != null && column >= 0 && columnSpan > 0); + item.Properties.GetAttachedProperty(Grid.ColumnProperty).SetValue(column); + if (columnSpan == 1) { + item.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).Reset(); + } else { + item.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).SetValue(columnSpan); + } + } + + static void SetRow(DesignItem item, int row, int rowSpan) + { + Debug.Assert(item != null && row >= 0 && rowSpan > 0); + item.Properties.GetAttachedProperty(Grid.RowProperty).SetValue(row); + if (rowSpan == 1) { + item.Properties.GetAttachedProperty(Grid.RowSpanProperty).Reset(); + } else { + item.Properties.GetAttachedProperty(Grid.RowSpanProperty).SetValue(rowSpan); + } + } + + static HorizontalAlignment SuggestHorizontalAlignment(Rect itemBounds, Rect availableSpaceRect) + { + if (itemBounds.Right < (availableSpaceRect.Left + availableSpaceRect.Right) / 2) { + return HorizontalAlignment.Left; + } else if (itemBounds.Left > (availableSpaceRect.Left + availableSpaceRect.Right) / 2) { + return HorizontalAlignment.Right; + } else { + return HorizontalAlignment.Stretch; + } + } + + static VerticalAlignment SuggestVerticalAlignment(Rect itemBounds, Rect availableSpaceRect) + { + if (itemBounds.Bottom < (availableSpaceRect.Top + availableSpaceRect.Bottom) / 2) { + return VerticalAlignment.Top; + } else if (itemBounds.Top > (availableSpaceRect.Top + availableSpaceRect.Bottom) / 2) { + return VerticalAlignment.Bottom; + } else { + return VerticalAlignment.Stretch; + } + } + + GrayOutDesignerExceptActiveArea grayOut; + + public override void EndPlacement(PlacementOperation operation) + { + GrayOutDesignerExceptActiveArea.Stop(ref grayOut); + base.EndPlacement(operation); + } + + public override void SetPosition(PlacementInformation info) + { + base.SetPosition(info); + if (info.Operation.Type == PlacementType.AddItem) { + SetColumn(info.Item, GetColumnIndex(info.Bounds.Left), 1); + SetRow(info.Item, GetRowIndex(info.Bounds.Top), 1); + } else { + int leftColumnIndex = GetColumnIndex(info.Bounds.Left); + int rightColumnIndex = GetEndColumnIndex(info.Bounds.Right); + if (rightColumnIndex < leftColumnIndex) rightColumnIndex = leftColumnIndex; + SetColumn(info.Item, leftColumnIndex, rightColumnIndex - leftColumnIndex + 1); + int topRowIndex = GetRowIndex(info.Bounds.Top); + int bottomRowIndex = GetEndRowIndex(info.Bounds.Bottom); + if (bottomRowIndex < topRowIndex) bottomRowIndex = topRowIndex; + SetRow(info.Item, topRowIndex, bottomRowIndex - topRowIndex + 1); + + Rect availableSpaceRect = new Rect( + new Point(GetColumnOffset(leftColumnIndex), GetRowOffset(topRowIndex)), + new Point(GetColumnOffset(rightColumnIndex + 1), GetRowOffset(bottomRowIndex + 1)) + ); + if (grayOut != null) { + grayOut.AnimateActiveAreaRectTo(availableSpaceRect); + } else { + GrayOutDesignerExceptActiveArea.Start(ref grayOut, this.Context, this.ExtendedItem.View, availableSpaceRect); + } + + HorizontalAlignment ha = (HorizontalAlignment)info.Item.Properties[FrameworkElement.HorizontalAlignmentProperty].ValueOnInstance; + VerticalAlignment va = (VerticalAlignment)info.Item.Properties[FrameworkElement.VerticalAlignmentProperty].ValueOnInstance; + ha = SuggestHorizontalAlignment(info.Bounds, availableSpaceRect); + va = SuggestVerticalAlignment(info.Bounds, availableSpaceRect); + + info.Item.Properties[FrameworkElement.HorizontalAlignmentProperty].SetValue(ha); + info.Item.Properties[FrameworkElement.VerticalAlignmentProperty].SetValue(va); + + Thickness margin = new Thickness(0, 0, 0, 0); + if (ha == HorizontalAlignment.Left || ha == HorizontalAlignment.Stretch) + margin.Left = info.Bounds.Left - GetColumnOffset(leftColumnIndex); + if (va == VerticalAlignment.Top || va == VerticalAlignment.Stretch) + margin.Top = info.Bounds.Top - GetRowOffset(topRowIndex); + if (ha == HorizontalAlignment.Right || ha == HorizontalAlignment.Stretch) + margin.Right = GetColumnOffset(rightColumnIndex + 1) - info.Bounds.Right; + if (va == VerticalAlignment.Bottom || va == VerticalAlignment.Stretch) + margin.Bottom = GetRowOffset(bottomRowIndex + 1) - info.Bounds.Bottom; + info.Item.Properties[FrameworkElement.MarginProperty].SetValue(margin); + + if (ha == HorizontalAlignment.Stretch) + info.Item.Properties[FrameworkElement.WidthProperty].Reset(); + else + info.Item.Properties[FrameworkElement.WidthProperty].SetValue(info.Bounds.Width); + if (va == VerticalAlignment.Stretch) + info.Item.Properties[FrameworkElement.HeightProperty].Reset(); + else + info.Item.Properties[FrameworkElement.HeightProperty].SetValue(info.Bounds.Height); + } + } + + public override void LeaveContainer(PlacementOperation operation) + { + base.LeaveContainer(operation); + foreach (PlacementInformation info in operation.PlacedItems) { + if (info.Item.ComponentType == typeof(ColumnDefinition)) { + // TODO: combine the width of the deleted column with the previous column + this.ExtendedItem.Properties["ColumnDefinitions"].CollectionElements.Remove(info.Item); + } else if (info.Item.ComponentType == typeof(RowDefinition)) { + this.ExtendedItem.Properties["RowDefinitions"].CollectionElements.Remove(info.Item); + } else { + info.Item.Properties.GetAttachedProperty(Grid.RowProperty).Reset(); + info.Item.Properties.GetAttachedProperty(Grid.ColumnProperty).Reset(); + info.Item.Properties.GetAttachedProperty(Grid.RowSpanProperty).Reset(); + info.Item.Properties.GetAttachedProperty(Grid.ColumnSpanProperty).Reset(); + + HorizontalAlignment ha = (HorizontalAlignment)info.Item.Properties[FrameworkElement.HorizontalAlignmentProperty].ValueOnInstance; + VerticalAlignment va = (VerticalAlignment)info.Item.Properties[FrameworkElement.VerticalAlignmentProperty].ValueOnInstance; + + if (ha == HorizontalAlignment.Stretch) + info.Item.Properties[FrameworkElement.WidthProperty].SetValue(info.Bounds.Width); + if (va == VerticalAlignment.Stretch) + info.Item.Properties[FrameworkElement.HeightProperty].SetValue(info.Bounds.Height); + } + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/Initializers.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/Initializers.cs new file mode 100644 index 0000000000..4df3dd8482 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/Initializers.cs @@ -0,0 +1,52 @@ +// +// +// +// +// $Revision: 2667$ +// + +using System; +using System.Windows.Controls; +using ICSharpCode.WpfDesign.Extensions; +using System.Windows; +using System.Windows.Shapes; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.Designer.Extensions.Initializers +{ + [ExtensionFor(typeof(ContentControl))] + public class ContentControlInitializer : DefaultInitializer + { + public override void InitializeDefaults(DesignItem item) + { + DesignItemProperty contentProperty = item.Properties["Content"]; + if (contentProperty.ValueOnInstance == null) { + contentProperty.SetValue(item.ComponentType.Name); + } + } + } + + [ExtensionFor(typeof(HeaderedContentControl))] + public class HeaderedContentControlInitializer : DefaultInitializer + { + public override void InitializeDefaults(DesignItem item) + { + DesignItemProperty headerProperty = item.Properties["Header"]; + if (headerProperty.ValueOnInstance == null) { + headerProperty.SetValue(item.ComponentType.Name); + } + } + } + + [ExtensionFor(typeof(Shape))] + public class ShapeInitializer : DefaultInitializer + { + public override void InitializeDefaults(DesignItem item) + { + DesignItemProperty fillProperty = item.Properties["Fill"]; + if (fillProperty.ValueOnInstance == null) { + fillProperty.SetValue(Brushes.YellowGreen); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelInitializer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelInitializer.cs new file mode 100644 index 0000000000..08347369d9 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelInitializer.cs @@ -0,0 +1,156 @@ +// +// +// +// +// $Revision: 3077 $ +// + +using System; +using System.ComponentModel; +using System.Linq; +using System.Windows.Media; +using System.Windows.Controls; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Instance factory used to create Panel instances. + /// Sets the panels Brush to a transparent brush, and modifies the panel's type descriptor so that + /// the property value is reported as null when the transparent brush is used, and + /// setting the Brush to null actually restores the transparent brush. + /// + [ExtensionFor(typeof(Panel))] + public sealed class PanelInitializer : DefaultInitializer + { + Brush _transparentBrush = new SolidColorBrush(Colors.Transparent); + + public override void InitializeDefaults(DesignItem item) + { + Panel panel = item.Component as Panel; + if (panel != null) { + if (panel.Background == null) { + panel.Background = _transparentBrush; + } + TypeDescriptionProvider provider = new DummyValueInsteadOfNullTypeDescriptionProvider( + TypeDescriptor.GetProvider(panel), "Background", _transparentBrush); + TypeDescriptor.AddProvider(provider, panel); + } + } + } + + sealed class DummyValueInsteadOfNullTypeDescriptionProvider : TypeDescriptionProvider + { + // By using a TypeDescriptionProvider, we can intercept all access to the property that is + // using a PropertyDescriptor. WpfDesign.XamlDom uses a PropertyDescriptor for accessing + // properties (except for attached properties), so even DesignItemProperty/XamlProperty.ValueOnInstance + // will report null when the actual value is the dummy value. + + readonly string _propertyName; + readonly object _dummyValue; + + public DummyValueInsteadOfNullTypeDescriptionProvider(TypeDescriptionProvider existingProvider, + string propertyName, object dummyValue) + : base(existingProvider) + { + this._propertyName = propertyName; + this._dummyValue = dummyValue; + } + + public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance) + { + return new ShadowTypeDescriptor(this, base.GetTypeDescriptor(objectType, instance)); + } + + sealed class ShadowTypeDescriptor : CustomTypeDescriptor + { + readonly DummyValueInsteadOfNullTypeDescriptionProvider _parent; + + public ShadowTypeDescriptor(DummyValueInsteadOfNullTypeDescriptionProvider parent, + ICustomTypeDescriptor existingDescriptor) + : base(existingDescriptor) + { + this._parent = parent; + } + + public override PropertyDescriptorCollection GetProperties() + { + return Filter(base.GetProperties()); + } + + public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) + { + return Filter(base.GetProperties(attributes)); + } + + PropertyDescriptorCollection Filter(PropertyDescriptorCollection properties) + { + PropertyDescriptor property = properties[_parent._propertyName]; + if (property != null) { + if ((properties as System.Collections.IDictionary).IsReadOnly) { + properties = new PropertyDescriptorCollection(properties.Cast().ToArray()); + } + properties.Remove(property); + properties.Add(new ShadowPropertyDescriptor(_parent, property)); + } + return properties; + } + } + + sealed class ShadowPropertyDescriptor : PropertyDescriptor + { + readonly DummyValueInsteadOfNullTypeDescriptionProvider _parent; + readonly PropertyDescriptor _baseDescriptor; + + public ShadowPropertyDescriptor(DummyValueInsteadOfNullTypeDescriptionProvider parent, + PropertyDescriptor existingDescriptor) + : base(existingDescriptor) + { + this._parent = parent; + this._baseDescriptor = existingDescriptor; + } + + public override Type ComponentType { + get { return _baseDescriptor.ComponentType; } + } + + public override bool IsReadOnly { + get { return _baseDescriptor.IsReadOnly; } + } + + public override Type PropertyType { + get { return _baseDescriptor.PropertyType; } + } + + public override bool CanResetValue(object component) + { + return _baseDescriptor.CanResetValue(component); + } + + public override object GetValue(object component) + { + object value = _baseDescriptor.GetValue(component); + if (value == _parent._dummyValue) + return null; + else + return value; + } + + public override void ResetValue(object component) + { + _baseDescriptor.SetValue(component, _parent._dummyValue); + } + + public override void SetValue(object component, object value) + { + _baseDescriptor.SetValue(component, value ?? _parent._dummyValue); + } + + public override bool ShouldSerializeValue(object component) + { + return _baseDescriptor.ShouldSerializeValue(component) + && _baseDescriptor.GetValue(component) != _parent._dummyValue; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelMove.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelMove.cs new file mode 100644 index 0000000000..72f40633b2 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelMove.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; +using System.Windows.Controls; +using System.Windows; +using ICSharpCode.WpfDesign.Designer.Controls; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + [ExtensionFor(typeof(Panel))] + public class PanelMove : PermanentAdornerProvider + { + protected override void OnInitialized() + { + base.OnInitialized(); + + var adornerPanel = new AdornerPanel(); + var adorner = new PanelMoveAdorner(ExtendedItem); + AdornerPanel.SetPlacement(adorner, AdornerPlacement.FillContent); + adornerPanel.Children.Add(adorner); + Adorners.Add(adornerPanel); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelSelectionHandler.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelSelectionHandler.cs new file mode 100644 index 0000000000..fe2d63b1de --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/PanelSelectionHandler.cs @@ -0,0 +1,170 @@ +// +// +// +// +// $Revision: 3283 $ +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; + +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Designer.Controls; +using ICSharpCode.WpfDesign.Designer.Services; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Handles selection multiple controls inside a Panel. + /// + [ExtensionFor(typeof(Panel))] + public class PanelSelectionHandler : BehaviorExtension, IHandlePointerToolMouseDown + { + protected override void OnInitialized() + { + base.OnInitialized(); + this.ExtendedItem.AddBehavior(typeof(IHandlePointerToolMouseDown), this); + } + + public void HandleSelectionMouseDown(IDesignPanel designPanel, MouseButtonEventArgs e, DesignPanelHitTestResult result) + { + if (e.ChangedButton == MouseButton.Left && MouseGestureBase.IsOnlyButtonPressed(e, MouseButton.Left)) { + e.Handled = true; + new RangeSelectionGesture(result.ModelHit).Start(designPanel, e); + } + } + } + + sealed class RangeSelectionGesture : ClickOrDragMouseGesture + { + DesignItem container; + AdornerPanel adornerPanel; + SelectionFrame selectionFrame; + + GrayOutDesignerExceptActiveArea grayOut; + + public RangeSelectionGesture(DesignItem container) + { + this.container = container; + this.positionRelativeTo = container.View; + } + + protected override void OnDragStarted(MouseEventArgs e) + { + adornerPanel = new AdornerPanel(); + adornerPanel.SetAdornedElement(container.View, container); + + selectionFrame = new SelectionFrame(); + adornerPanel.Children.Add(selectionFrame); + + designPanel.Adorners.Add(adornerPanel); + + GrayOutDesignerExceptActiveArea.Start(ref grayOut, context, container.View); + } + + protected override void OnMouseMove(object sender, MouseEventArgs e) + { + base.OnMouseMove(sender, e); + if (hasDragStarted) { + SetPlacement(e.GetPosition(positionRelativeTo)); + } + } + + protected override void OnMouseUp(object sender, MouseButtonEventArgs e) + { + if (hasDragStarted == false) { + context.SelectionService.Select(new DesignItem[] { container }, SelectionTypes.Auto); + } else { + Point endPoint = e.GetPosition(positionRelativeTo); + Rect frameRect = new Rect( + Math.Min(startPoint.X, endPoint.X), + Math.Min(startPoint.Y, endPoint.Y), + Math.Abs(startPoint.X - endPoint.X), + Math.Abs(startPoint.Y - endPoint.Y) + ); + + ICollection items = GetChildDesignItemsInContainer(container, new RectangleGeometry(frameRect)); + if (items.Count == 0) { + items.Add(container); + } + context.SelectionService.Select(items, SelectionTypes.Auto); + } + Stop(); + } + + static ICollection GetChildDesignItemsInContainer( + DesignItem container, Geometry geometry) + { + HashSet resultItems = new HashSet(); + IViewService viewService = container.Context.ViewService; + + HitTestFilterCallback filterCallback = delegate(DependencyObject potentialHitTestTarget) { + FrameworkElement element = potentialHitTestTarget as FrameworkElement; + if (element != null) { + // ensure we are able to select elements with width/height=0 + if (element.ActualWidth == 0 || element.ActualHeight == 0) { + DependencyObject tmp = element; + DesignItem model = null; + while (tmp != null) { + model = viewService.GetModel(tmp); + if (model != null) break; + tmp = VisualTreeHelper.GetParent(tmp); + } + if (model != container) { + resultItems.Add(model); + return HitTestFilterBehavior.ContinueSkipChildren; + } + } + } + return HitTestFilterBehavior.Continue; + }; + + HitTestResultCallback resultCallback = delegate(HitTestResult result) { + if (((GeometryHitTestResult) result).IntersectionDetail == IntersectionDetail.FullyInside) { + // find the model for the visual contained in the selection area + DependencyObject tmp = result.VisualHit; + DesignItem model = null; + while (tmp != null) { + model = viewService.GetModel(tmp); + if (model != null) break; + tmp = VisualTreeHelper.GetParent(tmp); + } + if (model != container) { + resultItems.Add(model); + } + } + return HitTestResultBehavior.Continue; + }; + + VisualTreeHelper.HitTest(container.View, filterCallback, resultCallback, new GeometryHitTestParameters(geometry)); + return resultItems; + } + + void SetPlacement(Point endPoint) + { + RelativePlacement p = new RelativePlacement(); + p.XOffset = Math.Min(startPoint.X, endPoint.X); + p.YOffset = Math.Min(startPoint.Y, endPoint.Y); + p.WidthOffset = Math.Max(startPoint.X, endPoint.X) - p.XOffset; + p.HeightOffset = Math.Max(startPoint.Y, endPoint.Y) - p.YOffset; + AdornerPanel.SetPlacement(selectionFrame, p); + } + + protected override void OnStopped() + { + if (adornerPanel != null) { + designPanel.Adorners.Remove(adornerPanel); + adornerPanel = null; + } + GrayOutDesignerExceptActiveArea.Stop(ref grayOut); + selectionFrame = null; + base.OnStopped(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/ResizeThumbExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/ResizeThumbExtension.cs new file mode 100644 index 0000000000..7188b58bc5 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/ResizeThumbExtension.cs @@ -0,0 +1,150 @@ +// +// +// +// +// $Revision: 3337 $ +// + +using System; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls.Primitives; +using System.Windows.Input; + +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Designer.Controls; +using ICSharpCode.WpfDesign.Extensions; +using System.Collections.Generic; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// The resize thumb around a component. + /// + [ExtensionFor(typeof(FrameworkElement))] + public sealed class ResizeThumbExtension : PrimarySelectionAdornerProvider + { + readonly AdornerPanel adornerPanel; + readonly ResizeThumb[] resizeThumbs; + /// An array containing this.ExtendedItem as only element + readonly DesignItem[] extendedItemArray = new DesignItem[1]; + IPlacementBehavior resizeBehavior; + PlacementOperation operation; + IChangeGroup changeGroup; + + public ResizeThumbExtension() + { + adornerPanel = new AdornerPanel(); + adornerPanel.Order = AdornerOrder.Foreground; + this.Adorners.Add(adornerPanel); + + resizeThumbs = new ResizeThumb[] { + CreateThumb(PlacementAlignment.TopLeft, Cursors.SizeNWSE), + CreateThumb(PlacementAlignment.Top, Cursors.SizeNS), + CreateThumb(PlacementAlignment.TopRight, Cursors.SizeNESW), + CreateThumb(PlacementAlignment.Left, Cursors.SizeWE), + CreateThumb(PlacementAlignment.Right, Cursors.SizeWE), + CreateThumb(PlacementAlignment.BottomLeft, Cursors.SizeNESW), + CreateThumb(PlacementAlignment.Bottom, Cursors.SizeNS), + CreateThumb(PlacementAlignment.BottomRight, Cursors.SizeNWSE) + }; + } + + ResizeThumb CreateThumb(PlacementAlignment alignment, Cursor cursor) + { + ResizeThumb resizeThumb = new ResizeThumbImpl( cursor == Cursors.SizeNS, cursor == Cursors.SizeWE ); + resizeThumb.Cursor = cursor; + resizeThumb.Alignment = alignment; + AdornerPanel.SetPlacement(resizeThumb, new RelativePlacement(alignment.Horizontal, alignment.Vertical)); + adornerPanel.Children.Add(resizeThumb); + + DragListener drag = new DragListener(resizeThumb); + drag.Started += new DragHandler(drag_Started); + drag.Changed += new DragHandler(drag_Changed); + drag.Completed += new DragHandler(drag_Completed); + return resizeThumb; + } + + Size oldSize; + + void drag_Started(DragListener drag) + { + oldSize = new Size(ModelTools.GetWidth(ExtendedItem.View), ModelTools.GetHeight(ExtendedItem.View)); + if (resizeBehavior != null) + operation = PlacementOperation.Start(extendedItemArray, PlacementType.Resize); + else { + changeGroup = this.Context.UndoService.OpenGroup("Resize", extendedItemArray); + } + } + + void drag_Changed(DragListener drag) + { + double dx = 0; + double dy = 0; + var alignment = (drag.Target as ResizeThumb).Alignment; + + if (alignment.Horizontal == HorizontalAlignment.Left) dx = -drag.Delta.X; + if (alignment.Horizontal == HorizontalAlignment.Right) dx = drag.Delta.X; + if (alignment.Vertical == VerticalAlignment.Top) dy = -drag.Delta.Y; + if (alignment.Vertical == VerticalAlignment.Bottom) dy = drag.Delta.Y; + + var newWidth = Math.Max(0, oldSize.Width + dx); + var newHeight = Math.Max(0, oldSize.Height + dy); + + ModelTools.Resize(ExtendedItem, newWidth, newHeight); + + if (operation != null) { + var info = operation.PlacedItems[0]; + var result = info.OriginalBounds; + + if (alignment.Horizontal == HorizontalAlignment.Left) + result.X = Math.Min(result.Right, result.X - dx); + if (alignment.Vertical == VerticalAlignment.Top) + result.Y = Math.Min(result.Bottom, result.Y - dy); + result.Width = newWidth; + result.Height = newHeight; + + info.Bounds = result; + info.ResizeThumbAlignment = alignment; + operation.CurrentContainerBehavior.BeforeSetPosition(operation); + operation.CurrentContainerBehavior.SetPosition(info); + } + } + + void drag_Completed(DragListener drag) + { + if (operation != null) { + if (drag.IsCanceled) operation.Abort(); + else operation.Commit(); + operation = null; + } else { + if (drag.IsCanceled) changeGroup.Abort(); + else changeGroup.Commit(); + changeGroup = null; + } + } + + protected override void OnInitialized() + { + base.OnInitialized(); + extendedItemArray[0] = this.ExtendedItem; + this.Context.SelectionService.PrimarySelectionChanged += OnPrimarySelectionChanged; + resizeBehavior = PlacementOperation.GetPlacementBehavior(extendedItemArray); + OnPrimarySelectionChanged(null, null); + } + + protected override void OnRemove() + { + this.Context.SelectionService.PrimarySelectionChanged -= OnPrimarySelectionChanged; + base.OnRemove(); + } + + void OnPrimarySelectionChanged(object sender, EventArgs e) + { + bool isPrimarySelection = this.Context.SelectionService.PrimarySelection == this.ExtendedItem; + foreach (ResizeThumb g in adornerPanel.Children) { + g.IsPrimarySelection = isPrimarySelection; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/SelectedElementRectangleExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/SelectedElementRectangleExtension.cs new file mode 100644 index 0000000000..9d5868ebd7 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/SelectedElementRectangleExtension.cs @@ -0,0 +1,50 @@ +// +// +// +// +// $Revision: 2413 $ +// + +using System; +using System.Windows; +using System.Windows.Media; +using System.Windows.Shapes; + +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Draws a dotted line around selected UIElements. + /// + [ExtensionFor(typeof(UIElement))] + public sealed class SelectedElementRectangleExtension : SelectionAdornerProvider + { + /// + /// Creates a new SelectedElementRectangleExtension instance. + /// + public SelectedElementRectangleExtension() + { + Rectangle selectionRect = new Rectangle(); + selectionRect.SnapsToDevicePixels = true; + selectionRect.Stroke = Brushes.White; + selectionRect.IsHitTestVisible = false; + + Rectangle dottedRect = new Rectangle(); + dottedRect.SnapsToDevicePixels = true; + dottedRect.Stroke = Brushes.Black; + dottedRect.StrokeDashCap = PenLineCap.Square; + dottedRect.StrokeDashArray = new DoubleCollection(new double[] { 0, 2 }); + dottedRect.IsHitTestVisible = false; + + RelativePlacement placement = new RelativePlacement(HorizontalAlignment.Stretch, VerticalAlignment.Stretch); + placement.XOffset = -1; + placement.YOffset = -1; + placement.WidthOffset = 2; + placement.HeightOffset = 2; + + this.AddAdorners(placement, selectionRect, dottedRect); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/SnaplinePlacementBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/SnaplinePlacementBehavior.cs new file mode 100644 index 0000000000..de09e5f437 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/SnaplinePlacementBehavior.cs @@ -0,0 +1,312 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using ICSharpCode.WpfDesign.Extensions; +using System.ComponentModel; +using ICSharpCode.WpfDesign.Adorners; +using System.Windows.Controls; +using System.Windows.Media; +using System.Windows.Shapes; +using System.Windows.Automation.Peers; +using System.Windows.Controls.Primitives; +using System.Diagnostics; +using System.Windows.Input; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + public class SnaplinePlacementBehavior : DefaultPlacementBehavior + { + AdornerPanel adornerPanel; + Canvas surface; + List horizontalMap; + List verticalMap; + double? baseline; + + public static double Accuracy = 5; + public static double Margin = 8; + + public override void BeginPlacement(PlacementOperation operation) + { + base.BeginPlacement(operation); + CreateSurface(operation); + } + + public override void EndPlacement(PlacementOperation operation) + { + base.EndPlacement(operation); + DeleteSurface(); + } + + public override void EnterContainer(PlacementOperation operation) + { + base.EnterContainer(operation); + CreateSurface(operation); + } + + public override void LeaveContainer(PlacementOperation operation) + { + base.LeaveContainer(operation); + DeleteSurface(); + } + + public override void BeforeSetPosition(PlacementOperation operation) + { + base.BeforeSetPosition(operation); + if (surface == null) return; + + surface.Children.Clear(); + if (Keyboard.IsKeyDown(Key.LeftCtrl)) return; + + Rect bounds = Rect.Empty; + foreach (var item in operation.PlacedItems) { + bounds.Union(item.Bounds); + } + + var horizontalInput = new List(); + var verticalInput = new List(); + var info = operation.PlacedItems[0]; + + if (operation.Type == PlacementType.Resize) { + AddLines(bounds, 0, false, horizontalInput, verticalInput, info.ResizeThumbAlignment); + } else { + AddLines(bounds, 0, false, horizontalInput, verticalInput, null); + if (baseline.HasValue) { + var textOffset = bounds.Top + baseline.Value; + horizontalInput.Add(new Snapline() { Group = 1, Offset = textOffset, Start = bounds.Left, End = bounds.Right }); + } + } + + // debug + //foreach (var t in horizontalMap.Concat(horizontalInput)) { + // surface.Children.Add(new Line() { X1 = t.Start, X2 = t.End, Y1 = t.Offset, Y2 = t.Offset, Stroke = Brushes.Black }); + //} + //foreach (var t in verticalMap.Concat(verticalInput)) { + // surface.Children.Add(new Line() { X1 = t.Offset, X2 = t.Offset, Y1 = t.Start , Y2 = t.End, Stroke = Brushes.Black }); + //} + //return; + + List drawLines; + double delta; + + if (Snap(horizontalInput, horizontalMap, Accuracy, out drawLines, out delta)) { + + if (operation.Type == PlacementType.Resize) { + if (info.ResizeThumbAlignment.Vertical == VerticalAlignment.Top) { + bounds.Y += delta; + bounds.Height = Math.Max(0, bounds.Height - delta); + } else { + bounds.Height = Math.Max(0, bounds.Height + delta); + } + info.Bounds = bounds; + } else { + foreach (var item in operation.PlacedItems) { + var r = item.Bounds; + r.Y += delta; + item.Bounds = r; + } + } + + foreach (var d in drawLines) { + DrawLine(d.Start, d.Offset, d.End, d.Offset); + } + } + + if (Snap(verticalInput, verticalMap, Accuracy, out drawLines, out delta)) { + + if (operation.Type == PlacementType.Resize) { + if (info.ResizeThumbAlignment.Horizontal == HorizontalAlignment.Left) { + bounds.X += delta; + bounds.Width = Math.Max(0, bounds.Width - delta); + } else { + bounds.Width = Math.Max(0, bounds.Width + delta); + } + info.Bounds = bounds; + } else { + foreach (var item in operation.PlacedItems) { + var r = item.Bounds; + r.X += delta; + item.Bounds = r; + } + } + + foreach (var d in drawLines) { + DrawLine(d.Offset, d.Start, d.Offset, d.End); + } + } + } + + void CreateSurface(PlacementOperation operation) + { + //if (ExtendedItem.Services.GetService() != null) + { + surface = new Canvas(); + adornerPanel = new AdornerPanel(); + adornerPanel.SetAdornedElement(ExtendedItem.View, ExtendedItem); + AdornerPanel.SetPlacement(surface, AdornerPlacement.FillContent); + adornerPanel.Children.Add(surface); + ExtendedItem.Context.DesignPanel.Adorners.Add(adornerPanel); + + BuildMaps(operation); + + if (operation.Type != PlacementType.Resize && operation.PlacedItems.Count == 1) { + baseline = GetBaseline(operation.PlacedItems[0].Item.View); + } + } + } + + void BuildMaps(PlacementOperation operation) + { + horizontalMap = new List(); + verticalMap = new List(); + + var containerRect = new Rect(0, 0, ModelTools.GetWidth(ExtendedItem.View), ModelTools.GetHeight(ExtendedItem.View)); + AddLines(containerRect, -Margin, false); + + foreach (var item in ExtendedItem.Content.CollectionElements + .Except(operation.PlacedItems.Select(f => f.Item))) + { + var bounds = GetPosition(operation, item); + + AddLines(bounds, 0, false); + AddLines(bounds, Margin, true); + AddBaseline(item, bounds, horizontalMap); + } + } + + void AddLines(Rect r, double inflate, bool requireOverlap) + { + AddLines(r, inflate, requireOverlap, horizontalMap, verticalMap, null); + } + + void AddLines(Rect r, double inflate, bool requireOverlap, List h, List v, PlacementAlignment? filter) + { + Rect r2 = r; + r2.Inflate(inflate, inflate); + + if (filter == null || filter.Value.Vertical == VerticalAlignment.Top) + h.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Top - 1, Start = r.Left, End = r.Right }); + if (filter == null || filter.Value.Vertical == VerticalAlignment.Bottom) + h.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Bottom, Start = r.Left, End = r.Right }); + if (filter == null || filter.Value.Horizontal == HorizontalAlignment.Left) + v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Left - 1, Start = r.Top, End = r.Bottom }); + if (filter == null || filter.Value.Horizontal == HorizontalAlignment.Right) + v.Add(new Snapline() { RequireOverlap = requireOverlap, Offset = r2.Right, Start = r.Top, End = r.Bottom }); + } + + void AddBaseline(DesignItem item, Rect bounds, List list) + { + var baseline = GetBaseline(item.View); + if (baseline.HasValue) { + var textOffset = item.View.TranslatePoint(new Point(0, baseline.Value), ExtendedItem.View).Y; + list.Add(new Snapline() { Group = 1, Offset = textOffset, Start = bounds.Left, End = bounds.Right }); + } + } + + void DeleteSurface() + { + if (surface != null) { + ExtendedItem.Context.DesignPanel.Adorners.Remove(adornerPanel); + adornerPanel = null; + surface = null; + horizontalMap = null; + verticalMap = null; + } + } + + void DrawLine(double x1, double y1, double x2, double y2) + { + var line1 = new Line() { + X1 = x1, + Y1 = y1, + X2 = x2, + Y2 = y2, + StrokeThickness = 1, + Stroke = Brushes.White + }; + surface.Children.Add(line1); + + var line2 = new Line() { + X1 = x1, + Y1 = y1, + X2 = x2, + Y2 = y2, + StrokeThickness = 1, + Stroke = Brushes.Orange, + StrokeDashArray = new DoubleCollection(new double[] { 5, 2 }), + StrokeDashOffset = x1 + y1 // fix dashes + }; + surface.Children.Add(line2); + } + + //TODO: GlyphRun must be used + static double? GetBaseline(UIElement element) { + var textBox = element.FindChild(); + if (textBox != null) { + var r = textBox.GetRectFromCharacterIndex(0).Bottom; + return textBox.TranslatePoint(new Point(0, r), element).Y; + } + var textBlock = element.FindChild(); + if (textBlock != null) + return textBlock.TranslatePoint(new Point(0, textBlock.ActualHeight), element).Y; + + return null; + } + + static bool Snap(List input, List map, double accuracy, + out List drawLines, out double delta) + { + delta = double.MaxValue; + drawLines = null; + + foreach (var inputLine in input) { + foreach (var mapLine in map) { + if (Math.Abs(mapLine.Offset - inputLine.Offset) <= accuracy) { + if (!inputLine.RequireOverlap && !mapLine.RequireOverlap || + Math.Max(inputLine.Start, mapLine.Start) < Math.Min(inputLine.End, mapLine.End)) + { + if (mapLine.Group == inputLine.Group) + delta = mapLine.Offset - inputLine.Offset; + } + } + } + } + + if (delta == double.MaxValue) return false; + var offsetDict = new Dictionary(); + + foreach (var inputLine in input) { + inputLine.Offset += delta; + foreach (var mapLine in map) { + if (inputLine.Offset == mapLine.Offset) { + var offset = mapLine.Offset; + Snapline drawLine; + if (!offsetDict.TryGetValue(offset, out drawLine)) { + drawLine = new Snapline(); + drawLine.Start = double.MaxValue; + drawLine.End = double.MinValue; + offsetDict[offset] = drawLine; + } + drawLine.Offset = offset; + drawLine.Start = Math.Min(drawLine.Start, Math.Min(inputLine.Start, mapLine.Start)); + drawLine.End = Math.Max(drawLine.End, Math.Max(inputLine.End, mapLine.End)); + } + } + } + + drawLines = offsetDict.Values.ToList(); + return true; + } + + [DebuggerDisplay("Snapline: {Offset}")] + class Snapline + { + public double Offset; + public double Start; + public double End; + public bool RequireOverlap; + public int Group; + } + } +} \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TabItemClickableExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TabItemClickableExtension.cs new file mode 100644 index 0000000000..8985e650f1 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TabItemClickableExtension.cs @@ -0,0 +1,32 @@ +// +// +// +// +// $Revision: 2263 $ +// + +using System; +using System.Windows.Controls; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Makes TabItems clickable. + /// + [ExtensionFor(typeof(TabItem))] + [ExtensionServer(typeof(PrimarySelectionExtensionServer))] + public sealed class TabItemClickableExtension : DefaultExtension + { + /// + protected override void OnInitialized() + { + // When tab item becomes primary selection, make it the active tab page in its parent tab control. + TabItem tabItem = (TabItem)this.ExtendedItem.Component; + TabControl tabControl = tabItem.Parent as TabControl; + if (tabControl != null) { + tabControl.SelectedItem = tabItem; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TopLeftContainerDragHandle.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TopLeftContainerDragHandle.cs new file mode 100644 index 0000000000..45ab0bb478 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TopLeftContainerDragHandle.cs @@ -0,0 +1,44 @@ +// +// +// +// +// $Revision: 2313 $ +// + +using System; +using System.Windows.Controls; +using System.Windows; +using System.Windows.Media; +using System.Windows.Shapes; +using ICSharpCode.WpfDesign.Adorners; +using ICSharpCode.WpfDesign.Extensions; +using ICSharpCode.WpfDesign.Designer.Controls; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /* + /// + /// The drag handle displayed for panels. + /// + [ExtensionServer(typeof(PrimarySelectionExtensionServer))] + [ExtensionFor(typeof(Panel), OverrideExtension = typeof(TopLeftResizeThumb))] + public class TopLeftContainerDragHandle : AdornerProvider + { + /// + public TopLeftContainerDragHandle() + { + ContainerDragHandle rect = new ContainerDragHandle(); + + rect.PreviewMouseDown += delegate { + Services.Selection.SetSelectedComponents(new DesignItem[] { this.ExtendedItem }, SelectionTypes.Auto); + }; + + RelativePlacement p = new RelativePlacement(HorizontalAlignment.Left, VerticalAlignment.Top); + p.XOffset = -1; + p.YOffset = -1; + + AddAdorner(p, AdornerOrder.Background, rect); + } + } + */ +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TypeReplacement.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TypeReplacement.cs new file mode 100644 index 0000000000..c8ae2795e1 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/TypeReplacement.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + class TypeReplacement + { + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/WindowResizeBehavior.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/WindowResizeBehavior.cs new file mode 100644 index 0000000000..0376288e53 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Extensions/WindowResizeBehavior.cs @@ -0,0 +1,86 @@ +// +// +// +// +// $Revision: 3337 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Designer.Extensions +{ + /// + /// Supports resizing a Window. + /// + [ExtensionFor(typeof(Window))] + public class WindowResizeBehavior : BehaviorExtension, IRootPlacementBehavior + { + protected override void OnInitialized() + { + base.OnInitialized(); + this.ExtendedItem.AddBehavior(typeof(IRootPlacementBehavior), this); + } + + public bool CanPlace(IEnumerable children, PlacementType type, PlacementAlignment position) + { + return type == PlacementType.Resize && + (position == PlacementAlignment.Right + || position == PlacementAlignment.BottomRight + || position == PlacementAlignment.Bottom); + } + + + public void BeginPlacement(PlacementOperation operation) + { + } + + public void EndPlacement(PlacementOperation operation) + { + } + + public Rect GetPosition(PlacementOperation operation, DesignItem childItem) + { + UIElement child = childItem.View; + return new Rect(0, 0, ModelTools.GetWidth(child), ModelTools.GetHeight(child)); + } + + public void BeforeSetPosition(PlacementOperation operation) + { + } + + public void SetPosition(PlacementInformation info) + { + UIElement element = info.Item.View; + Rect newPosition = info.Bounds; + if (newPosition.Right != ModelTools.GetWidth(element)) { + info.Item.Properties[FrameworkElement.WidthProperty].SetValue(newPosition.Right); + } + if (newPosition.Bottom != ModelTools.GetHeight(element)) { + info.Item.Properties[FrameworkElement.HeightProperty].SetValue(newPosition.Bottom); + } + } + + public bool CanLeaveContainer(PlacementOperation operation) + { + return false; + } + + public void LeaveContainer(PlacementOperation operation) + { + throw new NotSupportedException(); + } + + public bool CanEnterContainer(PlacementOperation operation) + { + return false; + } + + public void EnterContainer(PlacementOperation operation) + { + throw new NotSupportedException(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/Class.png b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/Class.png new file mode 100644 index 0000000000000000000000000000000000000000..f8e82b5568b0529aaa1c413f61ddc92cc218e0ef GIT binary patch literal 624 zcmV-$0+0QPP)Px#1ZP1_K>z@;j|==^1poj5AY({UO#lFTCIA3{ga82g0001h=l}q9FaQARU;qF* zm;eA5aGbhPJOBUy32;bRa{vGma{vGma{-JZxd#9M0oh4JK~y+Tjg#LiLtz-lpU!fu zG(T1(SCZUt=a%wsxN~8~m~F)-tEJ|!Oq(3rp=~v1AvJf(Jy%?qA{P`X7euruKT==k zeWzn5#x71h@6-GJJWt>6dk6p(f9va=+R@ni>ueBbvpx9uAf!@lWkYm8Hrs{wcf!jH zA)hCNLe{b%9I&<3jn`Mg^E2W8o^X9lI6EVFJmy~^+Z`#rPpaCEw>QGm6XEujaB)dE zJ|?)`X7u%mFqurTVh?t@RPIo^N#YPvloqV4wBY83aDGn6<(OE6&1S=p-45^g801I< z>2w;K%~3AS(-lr>4U%XpxGl@An4Ye|;UQa_i7WNV^5P<|mD))ze$>P#w1KcNjHt!^ z9ak{e2$#!@fdS*%$z+lP7Azhl8m6?#n_zX=GQ#_Y82kH;Vu!;)nblQ&8zz+NyqKx7 z>pcUY*es{hNq)bdGMS9Q$T`a}tP#zNug6vr5C{ZFk|atc5*(naD!WQ2VvAz9)Rh@ z*%0a#ZG)pD2-;*}aOh_W|NVs(;dxX9gAkmf|EEw2Cir}YR6YUovy{(>b~_ya0000< KMNUMnLSTZaq7B;s literal 0 HcmV?d00001 diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/PanToolCursor.cur b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/PanToolCursor.cur new file mode 100644 index 0000000000000000000000000000000000000000..6d10c848cdc8d0d7a52bd81ee2f5e8b47d1ef9a2 GIT binary patch literal 326 zcmaLSu?@m75QX92iBKx!4vC7Clx#q@VT6=;1V%v=)EOlO1EfMJP>y#vqV%1wvZ(il?Nc7Gzh@zp nrv7_+LpkQg%uO=ZW`hf6NpSkcO~%!*QD1jo(QLVvXRG@KcZz>G literal 0 HcmV?d00001 diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/PanToolCursorMouseDown.cur b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/PanToolCursorMouseDown.cur new file mode 100644 index 0000000000000000000000000000000000000000..5f3c236bac7fdaf45d323e9e800e4f0ccedae28c GIT binary patch literal 326 zcmaLSF%E+;429u8Ffdiw$_Qh}-T;oqkvebyj=~W#AqG_UnWzgwar8NnEjbBP1o|GL z);quxc!^4k60|&~Gv`!ka~@`v52aiuaE-(rIvI|v{i-f;gU753Kcz{xJ-wkEdt>I3 XthL!9Q^*#5Vf|ArsdvQkyi4~7fDwUA literal 0 HcmV?d00001 diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/Tag.png b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Images/Tag.png new file mode 100644 index 0000000000000000000000000000000000000000..b7686f106b0931ea8140d4fbf72eb7413053f7d2 GIT binary patch literal 389 zcmV;00eb$4P) z7zJ2Ez_8~bKiNTJ(D{JhbKcWq5v!hmfEg0E`Sl0y#m|p{BaHYsTodXqMkH2FaCfdig(a=HrhF zNmtlV)TkHVj0m0o^n2E-7ymu_9^8|Uy99RuP)^!=>Z5xgxuBVkz60e@T>vvlG3APo zZNr^osf(ZfcWt=~4+F1BkM3oxc>W(GCl`GYdl0)+jEP)BDiIJYLps>`r!OuoocSclke}BKDu)TAH znXtUbl%TS`#n3xZaDb1bH%n`OjiY>(tyN!UW`CJdWrDoJ&QocIO<{pNQg2gehj@*w zLRWP@Tt%2>h$)z%hu-h`QGyO-tqUP z%IAWn%s*6erITc&yv@w$^w;k8+VA(p;_|cA?485oa+I~s>h!YI<$#{Gy5I7_;q$@a z^0L_Nqs!-qt&Qvgz$*-O5|(Cl0q z$xeX!Bn0#2_tpLH-Oi%-^c3-)M)iU*o5=IwbpZl8%28z%I6(ja0HjGoK~#8NWysT# z15pqF(2i|;?Hk*+Z7z-fN0REyLu$_B0g$tqT$Yj}28x8Iat$g~z5tL=q;a}EsdPpv z!>}seKbEA?Y;{gC)Z^KFLF#r#UyCsudC8v7AHdLs!jUM6#S=+AhQXN4DfDw{CO zmeqRm`1Jhp8U$oJ`TY9+`ThH^QFC^FaoN7Q?sahvZh-N2JV2Y<-Atx%BDiIJYLy~WUbjH0>0&y}FDu)N4dT6acN zalFIMqp-c%+~Yh_ZUXRO<{pkXoq->tU_0H zI!|y{YmQ1xM>|n)0001ge*jNUPft%xPEJei_WRoH_QBrpsn6_vqQL6(_Hlui-tzX& z>h!YI<)zB!f~L$rRC0EZrKG&g%;@yj?)KX6_tNV0#p3d_)$E@7RZcp0!U< zO}gLm!Qu14;qtrQ@UqzLqs!-qth<~a`uz0!{C!L{v;Y7AEp$>& zQvgx~PUV`z+3Z{z$^E{7(D(Wzp7TqB)!ojb_w*F;M)fh9$n)WK?*Rfj%28iBbHM-r z0HjGoK~#8NWysTV1OX5Lz&YBsZQHhu*!K4)si}L|+J0;Rs)E5}(FHU(5{ks{yO%7R z1BlDxN1x+~WJ4mwkjc0E>zmuVhesub>gwzJClCyUBQA{C>)ZHWDxJYl=kkSOsa&bn zG#FZ4tKI4L`h%e!!(g1w=8NTOy_o= SystemParameters.MinimumHorizontalDragDistance || + Math.Abs(currentPoint.Y - startPoint.Y) >= SystemParameters.MinimumVerticalDragDistance) { + ready = false; + if (DragStarted != null) { + DragStarted(this, args); + } + } + } + } + + void MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + ready = false; + target.ReleaseMouseCapture(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragTreeView.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragTreeView.cs new file mode 100644 index 0000000000..c2dfff4f73 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragTreeView.cs @@ -0,0 +1,326 @@ +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.Collections.Specialized; +using System.Collections; + +namespace ICSharpCode.WpfDesign.Designer.OutlineView +{ + // limitations: + // - Do not use ItemsSource (use Root) + // - Do not use Items (use Root) + public class DragTreeView : TreeView + { + static DragTreeView() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(DragTreeView), + new FrameworkPropertyMetadata(typeof(DragTreeView))); + } + + public DragTreeView() + { + AllowDrop = true; + new DragListener(this).DragStarted += new MouseButtonEventHandler(DragTreeView_DragStarted); + } + + DragTreeViewItem dropTarget; + DragTreeViewItem treeItem; + DragTreeViewItem dropAfter; + int part; + bool dropInside; + bool dropCopy; + bool canDrop; + + Border insertLine; + + public static readonly DependencyProperty RootProperty = + DependencyProperty.Register("Root", typeof(object), typeof(DragTreeView)); + + public object Root { + get { return (object)GetValue(RootProperty); } + set { SetValue(RootProperty, value); } + } + + //public object[] SelectedItems + //{ + // get { return Selection.Select(item => item.DataContext).ToArray(); } + //} + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + if (e.Property == RootProperty) { + ItemsSource = new[] { Root }; + } + } + + void DragTreeView_DragStarted(object sender, MouseButtonEventArgs e) + { + DragDrop.DoDragDrop(this, this, DragDropEffects.All); + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + insertLine = (Border)Template.FindName("PART_InsertLine", this); + } + + protected override DependencyObject GetContainerForItemOverride() + { + return new DragTreeViewItem(); + } + + protected override bool IsItemItsOwnContainerOverride(object item) + { + return item is DragTreeViewItem; + } + + protected override void OnDragEnter(DragEventArgs e) + { + ProcessDrag(e); + } + + protected override void OnDragOver(DragEventArgs e) + { + ProcessDrag(e); + } + + protected override void OnDrop(DragEventArgs e) + { + ProcessDrop(e); + } + + protected override void OnDragLeave(DragEventArgs e) + { + HideDropMarker(); + } + + void PrepareDropInfo(DragEventArgs e) + { + dropTarget = null; + dropAfter = null; + treeItem = (e.OriginalSource as DependencyObject).FindAncestor(); + + if (treeItem != null) { + var parent = ItemsControl.ItemsControlFromItemContainer(treeItem) as DragTreeViewItem; + ContentPresenter header = treeItem.HeaderPresenter; + Point p = e.GetPosition(header); + part = (int)(p.Y / (header.ActualHeight / 3)); + dropCopy = Keyboard.IsKeyDown(Key.LeftCtrl); + dropInside = false; + + if (part == 1 || parent == null) { + dropTarget = treeItem; + dropInside = true; + if (treeItem.Items.Count > 0) { + dropAfter = treeItem.ItemContainerGenerator.ContainerFromIndex(treeItem.Items.Count - 1) as DragTreeViewItem; + } + } + else if (part == 0) { + dropTarget = parent; + var index = dropTarget.ItemContainerGenerator.IndexFromContainer(treeItem); + if (index > 0) { + dropAfter = dropTarget.ItemContainerGenerator.ContainerFromIndex(index - 1) as DragTreeViewItem; + } + } + else { + dropTarget = parent; + dropAfter = treeItem; + } + } + } + + void ProcessDrag(DragEventArgs e) + { + e.Effects = DragDropEffects.None; + e.Handled = true; + canDrop = false; + + if (e.Data.GetData(GetType()) != this) return; + + HideDropMarker(); + PrepareDropInfo(e); + + if (dropTarget != null && CanInsertInternal()) { + canDrop = true; + e.Effects = dropCopy ? DragDropEffects.Copy : DragDropEffects.Move; + DrawDropMarker(); + } + } + + void ProcessDrop(DragEventArgs e) + { + HideDropMarker(); + + if (canDrop) { + InsertInternal(); + } + } + + void DrawDropMarker() + { + if (dropInside) { + dropTarget.IsDragHover = true; + } + else { + var header = treeItem.HeaderPresenter; + var p = header.TransformToVisual(this).Transform( + new Point(0, part == 0 ? 0 : header.ActualHeight)); + + insertLine.Visibility = Visibility.Visible; + insertLine.Margin = new Thickness(p.X, p.Y, 0, 0); + } + } + + void HideDropMarker() + { + insertLine.Visibility = Visibility.Collapsed; + if (dropTarget != null) { + dropTarget.IsDragHover = false; + } + } + + internal HashSet Selection = new HashSet(); + DragTreeViewItem upSelection; + + internal void ItemMouseDown(DragTreeViewItem item) + { + upSelection = null; + bool control = Keyboard.IsKeyDown(Key.LeftCtrl); + + if (Selection.Contains(item)) { + if (control) { + Unselect(item); + } + else { + upSelection = item; + } + } + else { + if (control) { + Select(item); + } + else { + SelectOnly(item); + } + } + } + + internal void ItemMouseUp(DragTreeViewItem item) + { + if (upSelection == item) { + SelectOnly(item); + } + upSelection = null; + } + + internal void ItemAttached(DragTreeViewItem item) + { + if (item.IsSelected) Selection.Add(item); + } + + internal void ItemDetached(DragTreeViewItem item) + { + if (item.IsSelected) Selection.Remove(item); + } + + internal void ItemIsSelectedChanged(DragTreeViewItem item) + { + if (item.IsSelected) { + Selection.Add(item); + } + else { + Selection.Remove(item); + } + } + + void Select(DragTreeViewItem item) + { + Selection.Add(item); + item.IsSelected = true; + OnSelectionChanged(); + } + + void Unselect(DragTreeViewItem item) + { + Selection.Remove(item); + item.IsSelected = false; + OnSelectionChanged(); + } + + void SelectOnly(DragTreeViewItem item) + { + ClearSelection(); + Select(item); + OnSelectionChanged(); + } + + void ClearSelection() + { + foreach (var treeItem in Selection.ToArray()) { + treeItem.IsSelected = false; + } + Selection.Clear(); + OnSelectionChanged(); + } + + void OnSelectionChanged() + { + } + + bool CanInsertInternal() + { + if (!dropCopy) { + var item = dropTarget; + while (true) { + if (Selection.Contains(item)) return false; + item = ItemsControl.ItemsControlFromItemContainer(item) as DragTreeViewItem; + if (item == null) break; + } + + if (Selection.Contains(dropAfter)) return false; + } + + return CanInsert(dropTarget, Selection.ToArray(), dropAfter, dropCopy); + } + + void InsertInternal() + { + var selection = Selection.ToArray(); + + if (!dropCopy) { + foreach (var item in Selection.ToArray()) { + var parent = ItemsControl.ItemsControlFromItemContainer(item) as DragTreeViewItem; + //TODO + if (parent != null) { + Remove(parent, item); + } + } + } + Insert(dropTarget, selection, dropAfter, dropCopy); + } + + protected virtual bool CanInsert(DragTreeViewItem target, DragTreeViewItem[] items, DragTreeViewItem after, bool copy) + { + return true; + } + + protected virtual void Insert(DragTreeViewItem target, DragTreeViewItem[] items, DragTreeViewItem after, bool copy) + { + } + + protected virtual void Remove(DragTreeViewItem target, DragTreeViewItem item) + { + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragTreeViewItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragTreeViewItem.cs new file mode 100644 index 0000000000..22394de453 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/DragTreeViewItem.cs @@ -0,0 +1,119 @@ +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.Windows.Controls.Primitives; + +namespace ICSharpCode.WpfDesign.Designer.OutlineView +{ + public class DragTreeViewItem : TreeViewItem + { + static DragTreeViewItem() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(DragTreeViewItem), + new FrameworkPropertyMetadata(typeof(DragTreeViewItem))); + } + + public DragTreeViewItem() + { + Loaded += new RoutedEventHandler(DragTreeViewItem_Loaded); + Unloaded += new RoutedEventHandler(DragTreeViewItem_Unloaded); + } + + void DragTreeViewItem_Loaded(object sender, RoutedEventArgs e) + { + ParentTree = this.FindAncestor(); + if (ParentTree != null) { + ParentTree.ItemAttached(this); + } + } + + void DragTreeViewItem_Unloaded(object sender, RoutedEventArgs e) + { + if (ParentTree != null) { + ParentTree.ItemDetached(this); + } + ParentTree = null; + } + + public new static readonly DependencyProperty IsSelectedProperty = + Selector.IsSelectedProperty.AddOwner(typeof(DragTreeViewItem)); + + public new bool IsSelected { + get { return (bool)GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + + public static readonly DependencyProperty IsDragHoverProperty = + DependencyProperty.Register("IsDragHover", typeof(bool), typeof(DragTreeViewItem)); + + public bool IsDragHover { + get { return (bool)GetValue(IsDragHoverProperty); } + set { SetValue(IsDragHoverProperty, value); } + } + + internal ContentPresenter HeaderPresenter { + get { return (ContentPresenter)Template.FindName("PART_Header", this); } + } + + public static readonly DependencyProperty LevelProperty = + DependencyProperty.Register("Level", typeof(int), typeof(DragTreeViewItem)); + + public int Level { + get { return (int)GetValue(LevelProperty); } + set { SetValue(LevelProperty, value); } + } + + public DragTreeView ParentTree { get; private set; } + + protected override void OnVisualParentChanged(DependencyObject oldParent) + { + base.OnVisualParentChanged(oldParent); + + var parentItem = ItemsControl.ItemsControlFromItemContainer(this) as DragTreeViewItem; + if (parentItem != null) Level = parentItem.Level + 1; + } + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + if (e.Property == IsSelectedProperty) { + if (ParentTree != null) { + ParentTree.ItemIsSelectedChanged(this); + } + } + } + + protected override DependencyObject GetContainerForItemOverride() + { + return new DragTreeViewItem(); + } + + protected override bool IsItemItsOwnContainerOverride(object item) + { + return item is DragTreeViewItem; + } + + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonDown(e); + if (e.Source is ToggleButton || e.Source is ItemsPresenter) return; + ParentTree.ItemMouseDown(this); + } + + protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonUp(e); + ParentTree.ItemMouseUp(this); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/IconItem.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/IconItem.cs new file mode 100644 index 0000000000..f6eead04e3 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/IconItem.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls; +using System.Windows; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.Designer.OutlineView +{ + public class IconItem : Control + { + static IconItem() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(IconItem), + new FrameworkPropertyMetadata(typeof(IconItem))); + } + + public static readonly DependencyProperty IconProperty = + DependencyProperty.Register("Icon", typeof(ImageSource), typeof(IconItem)); + + public ImageSource Icon { + get { return (ImageSource)GetValue(IconProperty); } + set { SetValue(IconProperty, value); } + } + + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register("Text", typeof(string), typeof(IconItem)); + + public string Text { + get { return (string)GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/Outline.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/Outline.xaml new file mode 100644 index 0000000000..f2d9f0ce2c --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/Outline.xaml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/Outline.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/Outline.xaml.cs new file mode 100644 index 0000000000..5b977e033f --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/Outline.xaml.cs @@ -0,0 +1,94 @@ +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.OutlineView +{ + public partial class Outline + { + public Outline() + { + InitializeComponent(); + } + + public static readonly DependencyProperty ContextProperty = + DesignSurface.ContextProperty.AddOwner(typeof(Outline)); + + public DesignContext Context + { + get { return (DesignContext)GetValue(ContextProperty); } + set { SetValue(ContextProperty, value); } + } + + protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) + { + base.OnPropertyChanged(e); + if (e.Property == ContextProperty) { + if (e.NewValue != null) { + AttachContext(e.NewValue as DesignContext); + } + if (e.OldValue != null) { + DetachContext(e.OldValue as DesignContext); + } + } + } + + void AttachContext(DesignContext context) + { + UpdateRoot(); + context.ModelService.RootChanged += ModelService_RootChanged; + context.ModelService.ModelChanged += ModelService_ModelChanged; + context.SelectionService.SelectionChanged += SelectionService_SelectionChanged; + } + + void DetachContext(DesignContext context) + { + UpdateRoot(); + context.ModelService.RootChanged -= ModelService_RootChanged; + context.ModelService.ModelChanged -= ModelService_ModelChanged; + context.SelectionService.SelectionChanged -= SelectionService_SelectionChanged; + } + + void ModelService_RootChanged(object sender, EventArgs e) + { + UpdateRoot(); + } + + void ModelService_ModelChanged(object sender, ModelChangedEventArgs e) + { + if (e.Property.IsNameProperty) { + OutlineNode.Create(e.Property.DesignItem).RaisePropertyChanged("Name"); + } + else if (e.Property == e.Property.DesignItem.Content) { + OutlineNode.Create(e.Property.DesignItem).RaisePropertyChanged("Children"); + } + } + + void SelectionService_SelectionChanged(object sender, DesignItemCollectionEventArgs e) + { + foreach (var item in e.Items) { + OutlineNode.Create(item).RaisePropertyChanged("IsSelected"); + } + } + + void UpdateRoot() + { + if (Context != null && Context.ModelService.Root != null) { + uxTree.Root = OutlineNode.Create(Context.ModelService.Root); + } + else { + uxTree.Root = null; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineNode.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineNode.cs new file mode 100644 index 0000000000..9a00d6d704 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineNode.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel; +using ICSharpCode.WpfDesign; +using System.Collections.ObjectModel; +using System.Collections; +using ICSharpCode.WpfDesign.Designer; +using ICSharpCode.WpfDesign.Designer.XamlBackend; + +namespace ICSharpCode.WpfDesign.Designer.OutlineView +{ + public class OutlineNode : INotifyPropertyChanged + { + public static OutlineNode Create(DesignItem item) + { + var xamlDesignItem = item as XamlDesignItem; + var result = xamlDesignItem.GetAnnotation(); + if (result == null) { + result = new OutlineNode(item); + xamlDesignItem.AnnotateWith(result); + } + return result; + } + + OutlineNode(DesignItem designItem) + { + DesignItem = designItem; + } + + public DesignItem DesignItem { get; private set; } + + bool isExpanded = true; + + public bool IsExpanded + { + get + { + return isExpanded; + } + set + { + isExpanded = value; + RaisePropertyChanged("IsExpanded"); + } + } + + public bool IsSelected + { + get + { + return DesignItem.Context.SelectionService.IsSelected(DesignItem); + } + set + { + DesignItem.Context.SelectionService.Select( + new[] { DesignItem }, value ? SelectionTypes.Add : SelectionTypes.Remove); + RaisePropertyChanged("IsSelected"); + } + } + + public OutlineNode[] Children + { + get + { + return ModelTools.Children(DesignItem) + .Select(item => Create(item)).ToArray(); + } + } + + public string Name + { + get + { + if (string.IsNullOrEmpty(DesignItem.Name)) { + return DesignItem.ComponentType.Name; + } + return DesignItem.ComponentType.Name + " (" + DesignItem.Name + ")"; + } + } + + #region INotifyPropertyChanged Members + + public event PropertyChangedEventHandler PropertyChanged; + + public void RaisePropertyChanged(string name) + { + if (PropertyChanged != null) { + PropertyChanged(this, new PropertyChangedEventArgs(name)); + } + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineTreeView.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineTreeView.cs new file mode 100644 index 0000000000..7f042ceb5d --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineTreeView.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.WpfDesign.Designer.OutlineView +{ + public class OutlineTreeView : DragTreeView + { + protected override bool CanInsert(DragTreeViewItem target, DragTreeViewItem[] items, DragTreeViewItem after, bool copy) + { + return ModelTools.CanInsert( + (target.DataContext as OutlineNode).DesignItem, + items.Select(t => (t.DataContext as OutlineNode).DesignItem), + after == null ? null : (after.DataContext as OutlineNode).DesignItem, + copy); + } + + protected override void Insert(DragTreeViewItem target, DragTreeViewItem[] items, DragTreeViewItem after, bool copy) + { + ModelTools.Insert( + (target.DataContext as OutlineNode).DesignItem, + items.Select(t => (t.DataContext as OutlineNode).DesignItem), + after == null ? null : (after.DataContext as OutlineNode).DesignItem, + copy); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineView.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineView.xaml new file mode 100644 index 0000000000..d43fad28ab --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/OutlineView/OutlineView.xaml @@ -0,0 +1,154 @@ + + + + + + + + #FFC73C + + + + + + \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BoolEditor.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BoolEditor.xaml new file mode 100644 index 0000000000..f088519992 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BoolEditor.xaml @@ -0,0 +1,7 @@ + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BoolEditor.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BoolEditor.xaml.cs new file mode 100644 index 0000000000..adf8b4a177 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BoolEditor.xaml.cs @@ -0,0 +1,26 @@ +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 ICSharpCode.WpfDesign.PropertyGrid; + +namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors +{ + [TypeEditor(typeof(bool))] + public partial class BoolEditor + { + public BoolEditor() + { + InitializeComponent(); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditor.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditor.cs new file mode 100644 index 0000000000..87ef6655d9 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditor.cs @@ -0,0 +1,207 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel; +using ICSharpCode.WpfDesign.PropertyGrid; +using System.Windows.Media; +using System.Reflection; +using System.Windows; + +namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.BrushEditor +{ + public class BrushEditor : INotifyPropertyChanged + { + public BrushEditor() + { + GradientStopCollection stops = new GradientStopCollection(); + stops.Add(new GradientStop(Colors.Black, 0)); + stops.Add(new GradientStop(Colors.White, 1)); + + linearGradientBrush = new LinearGradientBrush(stops); + linearGradientBrush.EndPoint = new Point(1, 0); + radialGradientBrush = new RadialGradientBrush(stops); + } + + public static BrushItem[] SystemBrushes = typeof(SystemColors) + .GetProperties(BindingFlags.Static | BindingFlags.Public) + .Where(p => p.PropertyType == typeof(SolidColorBrush)) + .Select(p => new BrushItem() { Name = p.Name, Brush = (Brush)p.GetValue(null, null) }) + .ToArray(); + + public static BrushItem[] SystemColors = typeof(SystemColors) + .GetProperties(BindingFlags.Static | BindingFlags.Public) + .Where(p => p.PropertyType == typeof(Color)) + .Select(p => new BrushItem() + { + Name = p.Name, + Brush = new SolidColorBrush((Color)p.GetValue(null, null)) + }) + .ToArray(); + + SolidColorBrush solidColorBrush = new SolidColorBrush(Colors.White); + LinearGradientBrush linearGradientBrush; + RadialGradientBrush radialGradientBrush; + + PropertyNode property; + + public PropertyNode Property { + get { + return property; + } + set { + property = value; + if (property != null) { + var f = property.Value as Freezable; + if (f != null && f.IsFrozen) property.Value = f.Clone(); + } + DetermineCurrentKind(); + RaisePropertyChanged("Property"); + RaisePropertyChanged("Brush"); + } + } + + public Brush Brush { + get { + if (property != null) { + return property.Value as Brush; + } + return null; + } + set { + if (property != null && property.Value != value) { + property.Value = value; + DetermineCurrentKind(); + RaisePropertyChanged("Brush"); + } + } + } + + void DetermineCurrentKind() + { + if (Brush == null) { + CurrentKind = BrushEditorKind.None; + } + else if (Brush is SolidColorBrush) { + solidColorBrush = Brush as SolidColorBrush; + CurrentKind = BrushEditorKind.Solid; + } + else if (Brush is LinearGradientBrush) { + linearGradientBrush = Brush as LinearGradientBrush; + radialGradientBrush.GradientStops = linearGradientBrush.GradientStops; + CurrentKind = BrushEditorKind.Linear; + } + else if (Brush is RadialGradientBrush) { + radialGradientBrush = Brush as RadialGradientBrush; + linearGradientBrush.GradientStops = linearGradientBrush.GradientStops; + CurrentKind = BrushEditorKind.Radial; + } + } + + BrushEditorKind currentKind; + + public BrushEditorKind CurrentKind { + get { + return currentKind; + } + set { + currentKind = value; + RaisePropertyChanged("CurrentKind"); + + switch (CurrentKind) { + case BrushEditorKind.None: + Brush = null; + break; + + case BrushEditorKind.Solid: + Brush = solidColorBrush; + break; + + case BrushEditorKind.Linear: + Brush = linearGradientBrush; + break; + + case BrushEditorKind.Radial: + Brush = radialGradientBrush; + break; + + case BrushEditorKind.List: + Brush = solidColorBrush; + break; + } + } + } + + public double GradientAngle { + get { + var x = linearGradientBrush.EndPoint.X - linearGradientBrush.StartPoint.X; + var y = linearGradientBrush.EndPoint.Y - linearGradientBrush.StartPoint.Y; + return Vector.AngleBetween(new Vector(1, 0), new Vector(x, -y)); + } + set { + var d = value * Math.PI / 180; + var p = new Point(Math.Cos(d), -Math.Sin(d)); + var k = 1 / Math.Max(Math.Abs(p.X), Math.Abs(p.Y)); + p.X *= k; + p.Y *= k; + var p2 = new Point(-p.X, -p.Y); + linearGradientBrush.StartPoint = new Point((p2.X + 1) / 2, (p2.Y + 1) / 2); + linearGradientBrush.EndPoint = new Point((p.X + 1) / 2, (p.Y + 1) / 2); + RaisePropertyChanged("GradientAngle"); + } + } + + public IEnumerable AvailableColors { + get { return SystemColors; } + } + + public IEnumerable AvailableBrushes { + get { return SystemBrushes; } + } + + public void MakeGradientHorizontal() + { + GradientAngle = 0; + } + + public void MakeGradientVertical() + { + GradientAngle = -90; + } + + public void Commit() + { + if (Brush != null) { + Property.Value = Brush.Clone(); + } + } + + #region INotifyPropertyChanged Members + + public event PropertyChangedEventHandler PropertyChanged; + + void RaisePropertyChanged(string name) + { + if (PropertyChanged != null) { + PropertyChanged(this, new PropertyChangedEventArgs(name)); + } + } + + #endregion + } + + public enum BrushEditorKind + { + None, + Solid, + Linear, + Radial, + List + } + + public class BrushItem + { + public string Name { get; set; } + public Brush Brush { get; set; } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorPopup.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorPopup.xaml new file mode 100644 index 0000000000..de8144b584 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorPopup.xaml @@ -0,0 +1,11 @@ + + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorPopup.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorPopup.xaml.cs new file mode 100644 index 0000000000..d9568035b8 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorPopup.xaml.cs @@ -0,0 +1,36 @@ +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.Diagnostics; + +namespace ICSharpCode.WpfDesign.Designer.PropertyGrid.Editors.BrushEditor +{ + public partial class BrushEditorPopup + { + public BrushEditorPopup() + { + InitializeComponent(); + } + + protected override void OnClosed(EventArgs e) + { + base.OnClosed(e); + BrushEditorView.BrushEditor.Commit(); + } + + protected override void OnKeyDown(KeyEventArgs e) + { + if (e.Key == Key.Escape) IsOpen = false; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml new file mode 100644 index 0000000000..8286f1060a --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/PropertyGrid/Editors/BrushEditor/BrushEditorView.xaml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + "); + button.Properties["Width"].SetValue(100.0); + AssertCanvasDesignerOutput(" + + + +"); + } + + /// + /// Non-trivial because of: use of attached properties, units for width+height + /// + [Test] + public void Intro3() + { + TestLoading(@" + + + Some Text + Some text at the bottom of the page. + Some More Text + + + + + + Some Text Below the Buttons + + + +"); + } + + /// + /// Using Hyperlinks + /// + [Test] + public void Intro4() + { + TestLoading(@" + + + Start Page + + Go To Page 2 + + +"); + } + + [Test] + public void Resources() + { + TestLoading(@" + + + + + +"); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SimpleLoadTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SimpleLoadTests.cs new file mode 100644 index 0000000000..6f99b53652 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SimpleLoadTests.cs @@ -0,0 +1,292 @@ +// +// +// +// +// $Revision: 3072 $ +// + +using System; +using NUnit.Framework; + +namespace ICSharpCode.WpfDesign.Tests.Xaml +{ + [TestFixture] + public class SimpleLoadTests : TestHelper + { + [Test] + public void Button() + { + TestLoading(@" + + "); + } + + [Test] + public void ButtonWithAttributes() + { + TestLoading(@" + + "); + } + + [Test] + public void ButtonWithElementAttribute() + { + TestLoading(@" + + "); + } + + [Test] + public void ExampleClassTest() + { + TestLoading(@" + + + "); + } + + [Test] + public void ExampleClassWithStringPropAttribute() + { + TestLoading(@" + + + "); + } + + [Test] + public void ExampleClassWithEscapedBraceStringPropAttribute() + { + TestLoading(@" + + + "); + } + + [Test] + public void ExampleClassUseDefaultProperty() + { + TestLoading(@" + + a test string + + "); + } + + [Test] + public void ExampleClassUseDefaultPropertyExplicitly() + { + TestLoading(@" + + + a test string + + + "); + } + + [Test] + public void ExampleClassUseDefaultPropertyBeforeOtherPropertyElement() + { + TestLoading(@" + + a test string + + otherValue + + + "); + } + + [Test] + public void ExampleClassUseDefaultPropertyAfterOtherPropertyElement() + { + TestLoading(@" + + + otherValue + + a test string + + "); + } + + [Test] + public void ExampleClassUseDefaultPropertyBetweenOtherPropertyElement() + { + TestLoading(@" + + + otherValue + + a test string + + otherValue2 + + + "); + } + + [Test] + public void Container() + { + TestLoading(@" + + + + + + + + "); + } + + [Test] + public void ContainerImplicitList() + { + TestLoading(@" + + + + + "); + } + + [Test] + public void ExampleServiceTest() + { + TestLoading(@" + + + "); + } + + [Test] + public void ExampleClassObjectPropWithStringValue() + { + TestLoading(@" + + + "); + } + + [Test] + public void ExampleClassObjectPropWithTypeValue() + { + TestLoading(@" + + + "); + } + + [Test] + public void ExampleClassObjectPropWithTypeValue2() + { + TestLoading(@" + + + "); + } + + [Test] + public void ExampleClassObjectPropWithNullValue() + { + TestLoading(@" + + + "); + } + + [Test] + public void ExampleClassObjectPropWithExplicitMarkupExtension() + { + TestLoading(@" + + + + + + "); + } + + [Test] + public void ExampleClassObjectPropWithExplicitMarkupExtension2() + { + TestLoading(@" + + + + + + "); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SystemTypesLoadTest.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SystemTypesLoadTest.cs new file mode 100644 index 0000000000..d0dee6ab14 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/SystemTypesLoadTest.cs @@ -0,0 +1,35 @@ +// +// +// +// +// $Revision: 2421 $ +// + + +using System; +using NUnit.Framework; + +namespace ICSharpCode.WpfDesign.Tests.Xaml +{ + [TestFixture] + public class SystemTypesLoadTest : TestHelper + { + [Test] + public void Int32() + { + TestLoading(@"3"); + } + + [Test] + public void Double() + { + TestLoading(@"3.1"); + } + + [Test] + public void String() + { + TestLoading(@"text"); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/TestHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/TestHelper.cs new file mode 100644 index 0000000000..a0fc142557 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/TestHelper.cs @@ -0,0 +1,94 @@ +// +// +// +// +// $Revision: 3070 $ +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Windows.Markup; +using System.Xml; + +using ICSharpCode.Xaml; +using NUnit.Framework; +using ICSharpCode.Xaml; +using System.Xml.Linq; +using ICSharpCode.WpfDesign.Designer.XamlBackend; + +namespace ICSharpCode.WpfDesign.Tests.Xaml +{ + public class TestHelper + { + static TestHelper() + { + TestXamlProject = new DefaultWpfProject(); + TestXamlProject.AddReference(typeof(TestHelper).Assembly); + } + + public static XamlProject TestXamlProject; + public static XNamespace TestNamespace = "clr-namespace:ICSharpCode.WpfDesign.Tests.Xaml;assembly=ICSharpCode.WpfDesign.Tests"; + + public static T[] ToArray(IEnumerable e) + { + return new List(e).ToArray(); + } + + public static void TestLoading(string xaml) + { + Debug.WriteLine("Load using builtin XamlReader:"); + ExampleClass.nextUniqueIndex = 0; + TestHelperLog.logBuilder = new StringBuilder(); + object officialResult = XamlReader.Load(new XmlTextReader(new StringReader(xaml))); + string officialLog = TestHelperLog.logBuilder.ToString(); + Assert.IsNotNull(officialResult, "officialResult is null"); + + Debug.WriteLine("Load using own XamlParser:"); + ExampleClass.nextUniqueIndex = 0; + TestHelperLog.logBuilder = new StringBuilder(); + + var doc = TestXamlProject.ParseDocument(xaml); + + Assert.IsNotNull(doc, "doc is null"); + object ownResult = doc.Root.Instance; + string ownLog = TestHelperLog.logBuilder.ToString(); + Assert.IsNotNull(ownResult, "ownResult is null"); + + TestHelperLog.logBuilder = null; + // compare: + string officialSaved = XamlWriter.Save(officialResult); + string ownSaved = XamlWriter.Save(ownResult); + + Debug.WriteLine("Official saved:"); + Debug.WriteLine(officialSaved); + Debug.WriteLine("Own saved:"); + Debug.WriteLine(ownSaved); + + Assert.AreEqual(officialSaved, ownSaved); + + Debug.WriteLine("Official log:"); + Debug.WriteLine(officialLog); + Debug.WriteLine("Own log:"); + Debug.WriteLine(ownLog); + + // compare logs: + //Assert.AreEqual(officialLog, ownLog); + } + } + + internal static class TestHelperLog + { + internal static StringBuilder logBuilder; + + internal static void Log(string text) + { + if (logBuilder != null) { + logBuilder.AppendLine(text); + Debug.WriteLine(text); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/WhitespaceTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/WhitespaceTests.cs new file mode 100644 index 0000000000..1267fc5fd2 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/WhitespaceTests.cs @@ -0,0 +1,131 @@ +// +// +// +// +// $Revision: 2626 $ +// + +using System; +using NUnit.Framework; + +namespace ICSharpCode.WpfDesign.Tests.Xaml +{ + [TestFixture] + public class WhitespaceTests : TestHelper + { + [Test] + public void TrimSurroundingWhitespace() + { + TestLoading(@" + + + a test string + + + "); + } + + [Test] + public void TrimConsecutiveWhitespace() + { + TestLoading(@" + + a test string + + "); + } + + [Test] + public void ConvertLineFeedToSpace() + { + TestLoading(@" + + a test + string + + "); + } + + [Test] + public void PreserveSurroundingWhitespace() + { + TestLoading(@" + + + a test string + + + "); + } + + [Test] + public void PreserveConsecutiveWhitespace() + { + TestLoading(@" + + a test string + + "); + } + + [Test] + public void PreserveLineFeed() + { + TestLoading(@" + + a test + string + + "); + } + + [Test] + public void CDataTest() + { + TestLoading(@" + + "); + } + + [Test] + public void CDataAndContentMixTest() + { + TestLoading(@" + + some text + ]]> + more text + "); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/XamlTypeFinderTests.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/XamlTypeFinderTests.cs new file mode 100644 index 0000000000..5a6494b1ba --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/Xaml/XamlTypeFinderTests.cs @@ -0,0 +1,70 @@ +// +// +// +// +// $Revision: 2421 $ +// + +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Markup; + +using ICSharpCode.Xaml; +using NUnit.Framework; +using System.Xml.Linq; + +namespace ICSharpCode.WpfDesign.Tests.Xaml +{ + [TestFixture] + public class XamlTypeFinderTests : TestHelper + { + void Test(Type t, XName name) + { + var result = TestXamlProject.TypeFinder.FindType(name); + Assert.AreEqual(t, result.SystemType); + } + + void TestExtension(Type t, XName name) + { + var result = TestXamlProject.TypeFinder.FindExtensionType(name); + Assert.AreEqual(t, result.SystemType); + } + + [Test] + public void FindWindow() + { + Test(typeof(Window), XamlConstants.Presentation2006Namespace + "Window"); + } + + [Test] + public void FindButton() + { + Test(typeof(Button), XamlConstants.Presentation2007Namespace + "Button"); + } + + [Test] + public void FindBindingMarkupExtension() + { + Test(typeof(StaticResourceExtension), XamlConstants.Presentation2007Namespace + "StaticResourceExtension"); + } + + [Test] + public void FindNullExtension() + { + Test(typeof(NullExtension), XamlConstants.XamlNamespace + "NullExtension"); + } + + [Test] + public void FindNullExtension2() + { + TestExtension(typeof(NullExtension), XamlConstants.XamlNamespace + "Null"); + } + + [Test] + public void FindExampleClass() + { + Test(typeof(ExampleClass), TestHelper.TestNamespace + "ExampleClass"); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPanel.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPanel.cs new file mode 100644 index 0000000000..79d482ad0c --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPanel.cs @@ -0,0 +1,212 @@ +// +// +// +// +// $Revision: 2415 $ +// + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.Adorners +{ + /// + /// Manages display of adorners on the design surface. + /// + public sealed class AdornerPanel : Panel + { + #region Attached Property Placement + /// + /// The dependency property used to store the placement of adorner visuals. + /// + public static readonly DependencyProperty PlacementProperty = DependencyProperty.RegisterAttached( + "Placement", typeof(AdornerPlacement), typeof(AdornerPanel), + new FrameworkPropertyMetadata(AdornerPlacement.FillContent, FrameworkPropertyMetadataOptions.AffectsParentMeasure) + ); + + /// + /// Gets the placement of the specified adorner. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] + public static AdornerPlacement GetPlacement(UIElement adorner) + { + if (adorner == null) + throw new ArgumentNullException("adorner"); + return (AdornerPlacement)adorner.GetValue(PlacementProperty); + } + + /// + /// Sets the placement of the specified adorner. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] + public static void SetPlacement(UIElement adorner, AdornerPlacement placement) + { + if (adorner == null) + throw new ArgumentNullException("adorner"); + if (placement == null) + throw new ArgumentNullException("placement"); + adorner.SetValue(PlacementProperty, placement); + } + #endregion + + UIElement _adornedElement; + DesignItem _adornedDesignItem; + AdornerOrder _Order = AdornerOrder.Content; + + + /// + /// Gets the element adorned by this AdornerPanel. + /// + public UIElement AdornedElement { + get { return _adornedElement; } + } + + /// + /// Gets the design item adorned by this AdornerPanel. + /// + public DesignItem AdornedDesignItem { + get { return _adornedDesignItem; } + } + + /// + /// Sets the AdornedElement and AdornedDesignItem properties. + /// This method can be called only once. + /// + public void SetAdornedElement(UIElement adornedElement, DesignItem adornedDesignItem) + { + if (adornedElement == null) + throw new ArgumentNullException("adornedElement"); + + if (_adornedElement == adornedElement && _adornedDesignItem == adornedDesignItem) { + return; // ignore calls when nothing was changed + } + + if (_adornedElement != null) + throw new InvalidOperationException("AdornedElement is already set."); + + _adornedElement = adornedElement; + _adornedDesignItem = adornedDesignItem; + } + + /// + /// Gets/Sets the order used to display the AdornerPanel relative to other AdornerPanels. + /// Do not change this property after the panel was added to an AdornerLayer! + /// + public AdornerOrder Order { + get { return _Order; } + set { _Order = value; } + } + + /// + protected override Size MeasureOverride(Size availableSize) + { + if (this.AdornedElement != null) { + foreach (DependencyObject v in this.VisualChildren) { + UIElement e = v as UIElement; + if (e != null) { + e.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); + } + } + return this.AdornedElement.RenderSize; + } else { + return base.MeasureOverride(availableSize); + } + } + + /// + protected override Size ArrangeOverride(Size finalSize) + { + foreach (UIElement element in base.InternalChildren) { + GetPlacement(element).Arrange(this, element, finalSize); + } + return finalSize; + } + + private DependencyObject[] VisualChildren { + get { + int count = VisualTreeHelper.GetChildrenCount(this); + DependencyObject[] children = new DependencyObject[count]; + for (int i = 0; i < children.Length; i++) { + children[i] = VisualTreeHelper.GetChild(this, i); + } + return children; + } + } + } + + /// + /// Describes where an Adorner is positioned on the Z-Layer. + /// + public struct AdornerOrder : IComparable, IEquatable + { + /// + /// The adorner is in the background layer. + /// + public static readonly AdornerOrder Background = new AdornerOrder(100); + + /// + /// The adorner is in the content layer. + /// + public static readonly AdornerOrder Content = new AdornerOrder(200); + + /// + /// The adorner is in the layer behind the foreground but above the content. This layer + /// is used for the gray-out effect. + /// + public static readonly AdornerOrder BehindForeground = new AdornerOrder(280); + + /// + /// The adorner is in the foreground layer. + /// + public static readonly AdornerOrder Foreground = new AdornerOrder(300); + + int i; + + internal AdornerOrder(int i) + { + this.i = i; + } + + /// + public override int GetHashCode() + { + return i.GetHashCode(); + } + + /// + public override bool Equals(object obj) + { + if (!(obj is AdornerOrder)) return false; + return this == (AdornerOrder)obj; + } + + /// + public bool Equals(AdornerOrder other) + { + return i == other.i; + } + + /// + /// Compares the to another AdornerOrder. + /// + public int CompareTo(AdornerOrder other) + { + return i.CompareTo(other.i); + } + + /// + public static bool operator ==(AdornerOrder leftHandSide, AdornerOrder rightHandSide) + { + return leftHandSide.i == rightHandSide.i; + } + + /// + public static bool operator !=(AdornerOrder leftHandSide, AdornerOrder rightHandSide) + { + return leftHandSide.i != rightHandSide.i; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPlacement.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPlacement.cs new file mode 100644 index 0000000000..934f29c1bf --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPlacement.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision: 2415 $ +// + +using System; +using System.Collections.ObjectModel; +using System.Windows; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.Adorners +{ + /// + /// Defines how a design-time adorner is placed. + /// + public abstract class AdornerPlacement + { + /// + /// A placement instance that places the adorner above the content, using the same bounds as the content. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly AdornerPlacement FillContent = new FillContentPlacement(); + + /// + /// Arranges the adorner element on the specified adorner panel. + /// + public abstract void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize); + + sealed class FillContentPlacement : AdornerPlacement + { + public override void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize) + { + adorner.Arrange(new Rect(adornedElementSize)); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPlacementSpace.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPlacementSpace.cs new file mode 100644 index 0000000000..cdbf945991 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerPlacementSpace.cs @@ -0,0 +1,33 @@ +// +// +// +// +// $Revision: 2415 $ +// + +using System; +using System.Collections.ObjectModel; +using System.Windows; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.Adorners +{ + /// + /// Describes the space in which an adorner is placed. + /// + public enum AdornerPlacementSpace + { + /// + /// The adorner is affected by the render transform of the adorned element. + /// + Render, + /// + /// The adorner is affected by the layout transform of the adorned element. + /// + Layout, + /// + /// The adorner is not affected by transforms of designed controls. + /// + Designer + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerProvider.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerProvider.cs new file mode 100644 index 0000000000..473d63f092 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerProvider.cs @@ -0,0 +1,163 @@ +// +// +// +// +// $Revision: 2415 $ +// + +using System; +using System.Collections.ObjectModel; +using System.Windows; +using System.Windows.Media; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Adorners +{ + /// + /// Base class for extensions that present adorners on the screen. + /// + /// + /// Cider adorner introduction: + /// http://blogs.msdn.com/jnak/archive/2006/04/24/580393.aspx + /// + /// Adorners are WPF elements that float on top of the design surface and track the + /// size and location of the elements they are adorning. All of the UI the designer + /// presents to the user, including snap lines, grab handles and grid rulers, + /// is composed of these adorners. + /// + /// About design-time adorners and their placement: + /// read http://myfun.spaces.live.com/blog/cns!AC1291870308F748!240.entry + /// and http://myfun.spaces.live.com/blog/cns!AC1291870308F748!242.entry + /// + public abstract class AdornerProvider : DefaultExtension + { + #region class AdornerCollection + /// + /// Describes a collection of adorner visuals. + /// + sealed class AdornerPanelCollection : Collection + { + readonly AdornerProvider _provider; + + internal AdornerPanelCollection(AdornerProvider provider) + { + this._provider = provider; + } + + /// + protected override void InsertItem(int index, AdornerPanel item) + { + base.InsertItem(index, item); + _provider.OnAdornerAdd(item); + } + + /// + protected override void RemoveItem(int index) + { + _provider.OnAdornerRemove(base[index]); + base.RemoveItem(index); + } + + /// + protected override void SetItem(int index, AdornerPanel item) + { + _provider.OnAdornerRemove(base[index]); + base.SetItem(index, item); + _provider.OnAdornerAdd(item); + } + + /// + protected override void ClearItems() + { + foreach (AdornerPanel v in this) { + _provider.OnAdornerRemove(v); + } + base.ClearItems(); + } + } + #endregion + + readonly AdornerPanelCollection _adorners; + bool isVisible; + + /// + /// Creates a new AdornerProvider instance. + /// + protected AdornerProvider() + { + _adorners = new AdornerPanelCollection(this); + } + + /// + /// Is called after the ExtendedItem was set. + /// This methods displays the registered adorners + /// + protected override void OnInitialized() + { + base.OnInitialized(); + isVisible = true; + foreach (AdornerPanel v in _adorners) { + OnAdornerAdd(v); + } + } + + /// + /// Is called when the extension is removed. + /// This method hides the registered adorners. + /// + protected override void OnRemove() + { + base.OnRemove(); + foreach (AdornerPanel v in _adorners) { + OnAdornerRemove(v); + } + isVisible = false; + } + + /// + /// Gets the list of adorners displayed by this AdornerProvider. + /// + public Collection Adorners { + get { return _adorners; } + } + + /// + /// Adds an UIElement as adorner with the specified placement. + /// + protected void AddAdorner(AdornerPlacement placement, AdornerOrder order, UIElement adorner) + { + AdornerPanel p = new AdornerPanel(); + p.Order = order; + AdornerPanel.SetPlacement(adorner, placement); + p.Children.Add(adorner); + this.Adorners.Add(p); + } + + /// + /// Adds several UIElements as adorners with the specified placement. + /// + protected void AddAdorners(AdornerPlacement placement, params UIElement[] adorners) + { + AdornerPanel p = new AdornerPanel(); + foreach (UIElement adorner in adorners) { + AdornerPanel.SetPlacement(adorner, placement); + p.Children.Add(adorner); + } + this.Adorners.Add(p); + } + + internal void OnAdornerAdd(AdornerPanel item) + { + if (!isVisible) return; + + item.SetAdornedElement(this.ExtendedItem.View, this.ExtendedItem); + Context.DesignPanel.Adorners.Add(item); + } + + internal void OnAdornerRemove(AdornerPanel item) + { + if (!isVisible) return; + Context.DesignPanel.Adorners.Remove(item); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerProviderClasses.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerProviderClasses.cs new file mode 100644 index 0000000000..6e043d6ac1 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/AdornerProviderClasses.cs @@ -0,0 +1,50 @@ +// +// +// +// +// $Revision: 3523 $ +// + +using System; +using ICSharpCode.WpfDesign.Extensions; + +namespace ICSharpCode.WpfDesign.Adorners +{ + // Some classes that derive from AdornerProvider to specify a certain ExtensionServer. + + /// + /// An adorner extension that is attached permanently. + /// + [ExtensionServer(typeof(DefaultExtensionServer.Permanent))] + public abstract class PermanentAdornerProvider : AdornerProvider + { + + } + + /// + /// An adorner extension that is attached to selected components. + /// + [ExtensionServer(typeof(SelectionExtensionServer))] + public abstract class SelectionAdornerProvider : AdornerProvider + { + + } + + /// + /// An adorner extension that is attached to the primary selection. + /// + [ExtensionServer(typeof(PrimarySelectionExtensionServer))] + public abstract class PrimarySelectionAdornerProvider : AdornerProvider + { + + } + + /// + /// An adorner extension that is attached to the secondary selection. + /// + [ExtensionServer(typeof(SecondarySelectionExtensionServer))] + public abstract class SecondarySelectionAdornerProvider : AdornerProvider + { + + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/RelativePlacement.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/RelativePlacement.cs new file mode 100644 index 0000000000..3e9878ceb1 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Adorners/RelativePlacement.cs @@ -0,0 +1,211 @@ +// +// +// +// +// $Revision: 2415 $ +// + +using System; +using System.Collections.ObjectModel; +using System.Windows; +using System.Windows.Media; + +namespace ICSharpCode.WpfDesign.Adorners +{ + // We have to support the different coordinate spaces as explained in + // http://myfun.spaces.live.com/blog/cns!AC1291870308F748!242.entry + + /// + /// Placement class providing properties for different kinds of relative placements. + /// + public sealed class RelativePlacement : AdornerPlacement + { + /// + /// Creates a new RelativePlacement instance. The default instance is a adorner with zero size, you + /// have to set some properties to define the placement. + /// + public RelativePlacement() + { + } + + /// + /// Creates a new RelativePlacement instance from the specified horizontal and vertical alignments. + /// + public RelativePlacement(HorizontalAlignment horizontal, VerticalAlignment vertical) + { + switch (horizontal) { + case HorizontalAlignment.Left: + widthRelativeToDesiredWidth = 1; + xRelativeToAdornerWidth = -1; + break; + case HorizontalAlignment.Right: + widthRelativeToDesiredWidth = 1; + xRelativeToContentWidth = 1; + break; + case HorizontalAlignment.Center: + widthRelativeToDesiredWidth = 1; + xRelativeToContentWidth = 0.5; + xRelativeToAdornerWidth = -0.5; + break; + case HorizontalAlignment.Stretch: + widthRelativeToContentWidth = 1; + break; + } + switch (vertical) { + case VerticalAlignment.Top: + heightRelativeToDesiredHeight = 1; + yRelativeToAdornerHeight = -1; + break; + case VerticalAlignment.Bottom: + heightRelativeToDesiredHeight = 1; + yRelativeToContentHeight = 1; + break; + case VerticalAlignment.Center: + heightRelativeToDesiredHeight = 1; + yRelativeToContentHeight = 0.5; + yRelativeToAdornerHeight = -0.5; + break; + case VerticalAlignment.Stretch: + heightRelativeToContentHeight = 1; + break; + } + } + + double widthRelativeToDesiredWidth, heightRelativeToDesiredHeight; + + /// + /// Gets/Sets the width of the adorner as factor relative to the desired adorner width. + /// + public double WidthRelativeToDesiredWidth { + get { return widthRelativeToDesiredWidth; } + set { widthRelativeToDesiredWidth = value; } + } + + /// + /// Gets/Sets the height of the adorner as factor relative to the desired adorner height. + /// + public double HeightRelativeToDesiredHeight { + get { return heightRelativeToDesiredHeight; } + set { heightRelativeToDesiredHeight = value; } + } + + double widthRelativeToContentWidth, heightRelativeToContentHeight; + + /// + /// Gets/Sets the width of the adorner as factor relative to the width of the adorned item. + /// + public double WidthRelativeToContentWidth { + get { return widthRelativeToContentWidth; } + set { widthRelativeToContentWidth = value; } + } + + /// + /// Gets/Sets the height of the adorner as factor relative to the height of the adorned item. + /// + public double HeightRelativeToContentHeight { + get { return heightRelativeToContentHeight; } + set { heightRelativeToContentHeight = value; } + } + + double widthOffset, heightOffset; + + /// + /// Gets/Sets an offset that is added to the adorner width for the size calculation. + /// + public double WidthOffset { + get { return widthOffset; } + set { widthOffset = value; } + } + + /// + /// Gets/Sets an offset that is added to the adorner height for the size calculation. + /// + public double HeightOffset { + get { return heightOffset; } + set { heightOffset = value; } + } + + Size CalculateSize(UIElement adorner, Size adornedElementSize) + { + return new Size(Math.Max(widthOffset + + widthRelativeToDesiredWidth * adorner.DesiredSize.Width + + widthRelativeToContentWidth * adornedElementSize.Width, 0), + Math.Max(heightOffset + + heightRelativeToDesiredHeight * adorner.DesiredSize.Height + + heightRelativeToContentHeight * adornedElementSize.Height, 0)); + } + + double xOffset, yOffset; + + /// + /// Gets/Sets an offset that is added to the adorner position. + /// + public double XOffset { + get { return xOffset; } + set { xOffset = value; } + } + + /// + /// Gets/Sets an offset that is added to the adorner position. + /// + public double YOffset { + get { return yOffset; } + set { yOffset = value; } + } + + double xRelativeToAdornerWidth, yRelativeToAdornerHeight; + + /// + /// Gets/Sets the left border of the adorner element as factor relative to the width of the adorner. + /// + public double XRelativeToAdornerWidth { + get { return xRelativeToAdornerWidth; } + set { xRelativeToAdornerWidth = value; } + } + + /// + /// Gets/Sets the top border of the adorner element as factor relative to the height of the adorner. + /// + public double YRelativeToAdornerHeight { + get { return yRelativeToAdornerHeight; } + set { yRelativeToAdornerHeight = value; } + } + + double xRelativeToContentWidth, yRelativeToContentHeight; + + /// + /// Gets/Sets the left border of the adorner element as factor relative to the width of the adorned content. + /// + public double XRelativeToContentWidth { + get { return xRelativeToContentWidth; } + set { xRelativeToContentWidth = value; } + } + + /// + /// Gets/Sets the top border of the adorner element as factor relative to the height of the adorned content. + /// + public double YRelativeToContentHeight { + get { return yRelativeToContentHeight; } + set { yRelativeToContentHeight = value; } + } + + Point CalculatePosition(Size adornedElementSize, Size adornerSize) + { + return new Point(xOffset + + xRelativeToAdornerWidth * adornerSize.Width + + xRelativeToContentWidth * adornedElementSize.Width, + yOffset + + yRelativeToAdornerHeight * adornerSize.Height + + yRelativeToContentHeight * adornedElementSize.Height); + } + + /// + /// Arranges the adorner element on the specified adorner panel. + /// + public override void Arrange(AdornerPanel panel, UIElement adorner, Size adornedElementSize) + { + Size adornerSize = CalculateSize(adorner, adornedElementSize); + adorner.Arrange(new Rect(CalculatePosition(adornedElementSize, adornerSize), adornerSize)); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/BehaviorExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/BehaviorExtension.cs new file mode 100644 index 0000000000..6753486ddf --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/BehaviorExtension.cs @@ -0,0 +1,21 @@ +// +// +// +// +// $Revision: 2413 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Base class for extensions that provide a behavior interface for the designed item. + /// These extensions are always loaded. They must have an parameter-less constructor. + /// + [ExtensionServer(typeof(DefaultExtensionServer.Permanent))] + public class BehaviorExtension : DefaultExtension + { + + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/CustomInstanceFactory.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/CustomInstanceFactory.cs new file mode 100644 index 0000000000..24e99278f9 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/CustomInstanceFactory.cs @@ -0,0 +1,68 @@ +// +// +// +// +// $Revision: 2237 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// A special kind of extension that is used to create instances of objects when loading XAML inside + /// the designer. + /// + /// + /// CustomInstanceFactory in Cider: http://blogs.msdn.com/jnak/archive/2006/04/10/572241.aspx + /// + [ExtensionServer(typeof(NeverApplyExtensionsExtensionServer))] + public class CustomInstanceFactory : Extension + { + /// + /// Gets a default instance factory that uses Activator.CreateInstance to create instances. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] + public static readonly CustomInstanceFactory DefaultInstanceFactory = new CustomInstanceFactory(); + + /// + /// Creates a new CustomInstanceFactory instance. + /// + protected CustomInstanceFactory() + { + } + + /// + /// Creates an instance of the specified type, passing the specified arguments to its constructor. + /// + public virtual object CreateInstance(Type type, params object[] arguments) + { + return Activator.CreateInstance(type, arguments); + } + } + + // An extension server that never applies its extensions - used for special extensions + // like CustomInstanceFactory + sealed class NeverApplyExtensionsExtensionServer : ExtensionServer + { + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return false; + } + + public override Extension CreateExtension(Type extensionType, DesignItem extendedItem) + { + throw new NotImplementedException(); + } + + public override void RemoveExtension(Extension extension) + { + throw new NotImplementedException(); + } + + // since the event is never raised, we don't have to store the event handlers + public override event EventHandler ShouldApplyExtensionsInvalidated { + add {} remove {} + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/DefaultExtension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/DefaultExtension.cs new file mode 100644 index 0000000000..f4e8ea0715 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/DefaultExtension.cs @@ -0,0 +1,119 @@ +// +// +// +// +// $Revision: 3523 $ +// + +using System; +using System.Diagnostics; +using System.Collections.Generic; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Base class for extensions that have an parameter-less constructor and are initialized using the + /// OnInitialize method. + /// + public class DefaultExtension : Extension + { + DesignItem _extendedItem; + + /// + /// Gets the item that is being extended by the BehaviorExtension. + /// + public DesignItem ExtendedItem { + get { + if (_extendedItem == null) + throw new InvalidOperationException("Cannot access BehaviorExtension.ExtendedItem: " + + "The property is not initialized yet. Please move initialization logic " + + "that depends on ExtendedItem into the OnInitialized method."); + return _extendedItem; + } + } + + /// + /// Gets the design context of the extended item. "Context" is equivalent to "ExtendedItem.Context". + /// + public DesignContext Context { + get { + return this.ExtendedItem.Context; + } + } + + /// + /// Is called after the ExtendedItem was set. + /// Override this method to register your behavior with the item. + /// + protected virtual void OnInitialized() + { + } + + /// + /// Is called when the extension is removed. + /// + protected virtual void OnRemove() + { + } + + internal void CallOnRemove() { OnRemove(); } + + internal void InitializeDefaultExtension(DesignItem extendedItem) + { + Debug.Assert(this._extendedItem == null); + Debug.Assert(extendedItem != null); + + this._extendedItem = extendedItem; + OnInitialized(); + } + } + + /// + /// Base class for extension servers that create extensions that derive from . + /// + public abstract class DefaultExtensionServer : ExtensionServer + { + /// + /// Creates an instance of the DefaultExtension and calls OnInitialize on it. + /// + public override Extension CreateExtension(Type extensionType, DesignItem extendedItem) + { + DefaultExtension ext = (DefaultExtension)Activator.CreateInstance(extensionType); + ext.InitializeDefaultExtension(extendedItem); + return ext; + } + + /// + /// Calls OnRemove() on the DefaultExtension. + /// + public override void RemoveExtension(Extension extension) + { + DefaultExtension defaultExtension = extension as DefaultExtension; + Debug.Assert(defaultExtension != null); + defaultExtension.CallOnRemove(); + } + + /// + /// This event is raised when ShouldApplyExtensions is invalidated for a set of items. + /// + public override event EventHandler ShouldApplyExtensionsInvalidated; + + /// + /// Raise the ShouldApplyExtensionsInvalidated event for the specified set of design items. + /// + protected void ReapplyExtensions(ICollection items) + { + if (ShouldApplyExtensionsInvalidated != null) { + ShouldApplyExtensionsInvalidated(this, new DesignItemCollectionEventArgs(items)); + } + } + + internal sealed class Permanent : DefaultExtensionServer + { + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return true; + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/DefaultInitializer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/DefaultInitializer.cs new file mode 100644 index 0000000000..d46f97714e --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/DefaultInitializer.cs @@ -0,0 +1,23 @@ +// +// +// +// +// $Revision: 2258 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Base class for extensions that initialize new controls with default values. + /// + [ExtensionServer(typeof(NeverApplyExtensionsExtensionServer))] + public abstract class DefaultInitializer : Extension + { + /// + /// Initializes the design item to default values. + /// + public abstract void InitializeDefaults(DesignItem item); + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/Extension.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/Extension.cs new file mode 100644 index 0000000000..04af461192 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/Extension.cs @@ -0,0 +1,25 @@ +// +// +// +// +// $Revision: 2224 $ +// + +using System; +using System.Diagnostics; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Base class for all Extensions. + /// + /// + /// The class design in the ICSharpCode.WpfDesign.Extensions namespace was made to match that of Cider + /// as described in the blog posts: + /// http://blogs.msdn.com/jnak/archive/2006/04/24/580393.aspx + /// http://blogs.msdn.com/jnak/archive/2006/08/04/687166.aspx + /// + public abstract class Extension + { + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionForAttribute.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionForAttribute.cs new file mode 100644 index 0000000000..5822d8f8fb --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionForAttribute.cs @@ -0,0 +1,56 @@ +// +// +// +// +// $Revision: 2224 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Attribute to specify that the decorated class is a WPF extension for the specified item type. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false)] + public sealed class ExtensionForAttribute : Attribute + { + Type _designedItemType; + Type _overrideExtension; + + /// + /// Gets the type of the item that is designed using this extension. + /// + public Type DesignedItemType { + get { return _designedItemType; } + } + + /// + /// Gets/Sets the type of another extension that this extension is overriding. + /// + public Type OverrideExtension { + get { return _overrideExtension; } + set { + _overrideExtension = value; + if (value != null) { + if (!typeof(Extension).IsAssignableFrom(value)) { + throw new ArgumentException("OverrideExtension must specify the type of an Extension."); + } + } + } + } + + /// + /// Create a new ExtensionForAttribute that specifies that the decorated class + /// is a WPF extension for the specified item type. + /// + public ExtensionForAttribute(Type designedItemType) + { + if (designedItemType == null) + throw new ArgumentNullException("designedItemType"); + if (!designedItemType.IsClass) + throw new ArgumentException("designedItemType must be a class"); + _designedItemType = designedItemType; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionManager.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionManager.cs new file mode 100644 index 0000000000..c2ca98b6dd --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionManager.cs @@ -0,0 +1,260 @@ +// +// +// +// +// $Revision: 3077 $ +// + +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Manages extension creation for a design context. + /// + public sealed class ExtensionManager + { + readonly DesignContext _context; + + internal ExtensionManager(DesignContext context) + { + Debug.Assert(context != null); + this._context = context; + + context.SubscribeToService(delegate(IModelService modelService) { + modelService.ItemCreated += OnItemCreated; + }); + } + + void OnItemCreated(object sender, DesignItemEventArgs e) + { + e.Item.SetExtensionServers(this, GetExtensionServersForItem(e.Item)); + } + + /// + /// Re-applies extensions from the ExtensionServer to the specified design items. + /// + void ReapplyExtensions(IEnumerable items, ExtensionServer server) + { + foreach (DesignItem item in items) { + if (item != null) { + item.ReapplyExtensionServer(this, server); + } + } + } + + #region Manage ExtensionEntries + sealed class ExtensionEntry + { + internal readonly Type ExtensionType; + internal readonly ExtensionServer Server; + internal readonly Type OverriddenExtensionType; + + public ExtensionEntry(Type extensionType, ExtensionServer server, Type overriddenExtensionType) + { + this.ExtensionType = extensionType; + this.Server = server; + this.OverriddenExtensionType = overriddenExtensionType; + } + } + + Dictionary> _extensions = new Dictionary>(); + + void AddExtensionEntry(Type extendedItemType, ExtensionEntry entry) + { + List list; + if (!_extensions.TryGetValue(extendedItemType, out list)) { + list = _extensions[extendedItemType] = new List(); + } + list.Add(entry); + } + + List GetExtensionEntries(Type extendedItemType) + { + List result; + if (extendedItemType.BaseType != null) + result = GetExtensionEntries(extendedItemType.BaseType); + else + result = new List(); + + List list; + if (_extensions.TryGetValue(extendedItemType, out list)) { + foreach (ExtensionEntry entry in list) { + if (entry.OverriddenExtensionType != null) { + result.RemoveAll(delegate(ExtensionEntry oldEntry) { + return oldEntry.ExtensionType == entry.OverriddenExtensionType; + }); + } + result.Add(entry); + } + } + return result; + } + + /// + /// Gets all the types of all extensions that are applied to the specified item type. + /// + public IEnumerable GetExtensionTypes(Type extendedItemType) + { + if (extendedItemType == null) + throw new ArgumentNullException("extendedItemType"); + foreach (ExtensionEntry entry in GetExtensionEntries(extendedItemType)) { + yield return entry.ExtensionType; + } + } + #endregion + + #region Create Extensions + static readonly ExtensionEntry[] emptyExtensionEntryArray = new ExtensionEntry[0]; + + IEnumerable GetExtensionEntries(DesignItem extendedItem) + { + if (extendedItem.Component == null) + return emptyExtensionEntryArray; + else + return GetExtensionEntries(extendedItem.ComponentType); + } + + ExtensionServer[] GetExtensionServersForItem(DesignItem item) + { + Debug.Assert(item != null); + + HashSet servers = new HashSet(); + foreach (ExtensionEntry entry in GetExtensionEntries(item)) { + servers.Add(entry.Server); + } + return servers.ToArray(); + } + + internal IEnumerable CreateExtensions(ExtensionServer server, DesignItem item) + { + Debug.Assert(server != null); + Debug.Assert(item != null); + + foreach (ExtensionEntry entry in GetExtensionEntries(item)) { + if (entry.Server == server) { + yield return server.CreateExtension(entry.ExtensionType, item); + } + } + } + #endregion + + #region RegisterAssembly + HashSet _registeredAssemblies = new HashSet(); + + /// + /// Registers extensions from the specified assembly. + /// + public void RegisterAssembly(Assembly assembly) + { + if (assembly == null) + throw new ArgumentNullException("assembly"); + + // object[] assemblyAttributes = assembly.GetCustomAttributes(typeof(IsWpfDesignerAssemblyAttribute), false); + // if (assemblyAttributes.Length == 0) + // return; + + if (!_registeredAssemblies.Add(assembly)) { + // the assembly already is registered, don't try to register it again. + return; + } + + // IsWpfDesignerAssemblyAttribute isWpfDesignerAssembly = (IsWpfDesignerAssemblyAttribute)assemblyAttributes[0]; + // foreach (Type type in isWpfDesignerAssembly.UsePrivateReflection ? assembly.GetTypes() : assembly.GetExportedTypes()) { + foreach (Type type in assembly.GetTypes()) { + object[] extensionForAttributes = type.GetCustomAttributes(typeof(ExtensionForAttribute), false); + if (extensionForAttributes.Length == 0) + continue; + + foreach (ExtensionForAttribute designerFor in extensionForAttributes) { + ExtensionServer server = GetServerForExtension(type); + AddExtensionEntry(designerFor.DesignedItemType, new ExtensionEntry(type, server, designerFor.OverrideExtension)); + } + } + } + #endregion + + #region Extension Server Creation + // extension server type => extension server instance + Dictionary _extensionServers = new Dictionary(); + + ExtensionServer GetServerForExtension(Type extensionType) + { + Debug.Assert(extensionType != null); + + object[] extensionServerAttributes = extensionType.GetCustomAttributes(typeof(ExtensionServerAttribute), true); + if (extensionServerAttributes.Length != 1) + throw new DesignerException("Extension types must have exactly one [ExtensionServer] attribute."); + + return GetExtensionServer((ExtensionServerAttribute)extensionServerAttributes[0]); + } + + /// + /// Gets the extension server for the specified extension server attribute. + /// + public ExtensionServer GetExtensionServer(ExtensionServerAttribute attribute) + { + if (attribute == null) + throw new ArgumentNullException("attribute"); + + Type extensionServerType = attribute.ExtensionServerType; + + ExtensionServer server; + if (_extensionServers.TryGetValue(extensionServerType, out server)) + return server; + + server = (ExtensionServer)Activator.CreateInstance(extensionServerType); + server.InitializeExtensionServer(_context); + _extensionServers[extensionServerType] = server; + server.ShouldApplyExtensionsInvalidated += delegate(object sender, DesignItemCollectionEventArgs e) { + ReapplyExtensions(e.Items, (ExtensionServer)sender); + }; + return server; + } + #endregion + + #region Special extensions (CustomInstanceFactory and DefaultInitializer) + static readonly object[] emptyObjectArray = new object[0]; + + /// + /// Create an instance of the specified type using the specified arguments. + /// The instance is created using a CustomInstanceFactory registered for the type, + /// or using reflection if no instance factory is found. + /// + public object CreateInstanceWithCustomInstanceFactory(Type instanceType, object[] arguments) + { + if (instanceType == null) + throw new ArgumentNullException("instanceType"); + if (arguments == null) + arguments = emptyObjectArray; + foreach (Type extensionType in GetExtensionTypes(instanceType)) { + if (typeof(CustomInstanceFactory).IsAssignableFrom(extensionType)) { + CustomInstanceFactory factory = (CustomInstanceFactory)Activator.CreateInstance(extensionType); + return factory.CreateInstance(instanceType, arguments); + } + } + return CustomInstanceFactory.DefaultInstanceFactory.CreateInstance(instanceType, arguments); + } + + /// + /// Applies all DefaultInitializer extensions on the design item. + /// + public void ApplyDefaultInitializers(DesignItem item) + { + if (item == null) + throw new ArgumentNullException("item"); + + foreach (ExtensionEntry entry in GetExtensionEntries(item)) { + if (typeof(DefaultInitializer).IsAssignableFrom(entry.ExtensionType)) { + DefaultInitializer initializer = (DefaultInitializer)Activator.CreateInstance(entry.ExtensionType); + initializer.InitializeDefaults(item); + } + } + } + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionServer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionServer.cs new file mode 100644 index 0000000000..7294ec160e --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionServer.cs @@ -0,0 +1,75 @@ +// +// +// +// +// $Revision: 2237 $ +// + +using System; +using System.Diagnostics; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// An ExtensionServer manages a creating and removing extensions of the specific extension type. + /// For a given DesignContext, a ExtensionServer is created only once. + /// The ExtensionServer can handle events raised by services without having to unregister its events + /// handlers because the ExtensionServer runs for the lifetime of the DesignContext. + /// + public abstract class ExtensionServer + { + DesignContext _context; + + /// + /// Gets the context this extension server was created for. + /// + public DesignContext Context { + [DebuggerStepThrough] + get { + if (_context == null) + throw new InvalidOperationException("Cannot access ExtensionServer.Context: " + + "The property is not initialized yet. Please move initialization logic " + + "that depends on Context into the OnInitialized method."); + return _context; + } + } + + internal void InitializeExtensionServer(DesignContext context) + { + Debug.Assert(this._context == null); + Debug.Assert(context != null); + this._context = context; + OnInitialized(); + } + + /// + /// Is called after the extension server is initialized and the property has been set. + /// + protected virtual void OnInitialized() + { + } + + /// + /// Gets if the extension manager should apply the extensions from this server to the specified item. + /// Is called by the ExtensionManager. + /// + public abstract bool ShouldApplyExtensions(DesignItem extendedItem); + + /// + /// Create an extension of the specified type. + /// Is called by the ExtensionManager. + /// + public abstract Extension CreateExtension(Type extensionType, DesignItem extendedItem); + + /// + /// This method is called before an extension is removed from its DesignItem because it should not be applied anymore. + /// Is called by the ExtensionManager. + /// + public abstract void RemoveExtension(Extension extension); + + /// + /// This event is raised when ShouldApplyExtensions is invalidated for a set of items. + /// + public abstract event EventHandler ShouldApplyExtensionsInvalidated; + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionServerAttribute.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionServerAttribute.cs new file mode 100644 index 0000000000..f1d81bf798 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ExtensionServerAttribute.cs @@ -0,0 +1,42 @@ +// +// +// +// +// $Revision: 2224 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Attribute to specify that the decorated class is an extension using the specified extension server. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)] + public sealed class ExtensionServerAttribute : Attribute + { + Type _extensionServerType; + + /// + /// Gets the type of the item that is designed using this extension. + /// + public Type ExtensionServerType { + get { return _extensionServerType; } + } + + /// + /// Create a new ExtensionServerAttribute that specifies that the decorated extension + /// uses the specified extension server. + /// + public ExtensionServerAttribute(Type extensionServerType) + { + if (extensionServerType == null) + throw new ArgumentNullException("extensionServerType"); + if (!typeof(ExtensionServer).IsAssignableFrom(extensionServerType)) + throw new ArgumentException("extensionServerType must derive from ExtensionServer"); + if (extensionServerType.GetConstructor(new Type[0]) == null) + throw new ArgumentException("extensionServerType must have a parameter-less constructor"); + _extensionServerType = extensionServerType; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/LogicalExtensionServers.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/LogicalExtensionServers.cs new file mode 100644 index 0000000000..3c55782ba4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/LogicalExtensionServers.cs @@ -0,0 +1,75 @@ +// +// +// +// +// $Revision: 2237 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Combines two extension servers using a logical OR. + /// + public sealed class LogicalOrExtensionServer : DefaultExtensionServer + where A : ExtensionServer + where B : ExtensionServer + { + ExtensionServer _a; + ExtensionServer _b; + + /// + protected override void OnInitialized() + { + base.OnInitialized(); + _a = Context.ExtensionManager.GetExtensionServer(new ExtensionServerAttribute(typeof(A))); + _b = Context.ExtensionManager.GetExtensionServer(new ExtensionServerAttribute(typeof(B))); + _a.ShouldApplyExtensionsInvalidated += OnShouldApplyExtensionsInvalidated; + _b.ShouldApplyExtensionsInvalidated += OnShouldApplyExtensionsInvalidated; + } + + void OnShouldApplyExtensionsInvalidated(object sender, DesignItemCollectionEventArgs e) + { + ReapplyExtensions(e.Items); + } + + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return _a.ShouldApplyExtensions(extendedItem) || _b.ShouldApplyExtensions(extendedItem); + } + } + + /// + /// Combines two extension servers using a logical AND. + /// + public sealed class LogicalAndExtensionServer : DefaultExtensionServer + where A : ExtensionServer + where B : ExtensionServer + { + ExtensionServer _a; + ExtensionServer _b; + + /// + protected override void OnInitialized() + { + base.OnInitialized(); + _a = Context.ExtensionManager.GetExtensionServer(new ExtensionServerAttribute(typeof(A))); + _b = Context.ExtensionManager.GetExtensionServer(new ExtensionServerAttribute(typeof(B))); + _a.ShouldApplyExtensionsInvalidated += OnShouldApplyExtensionsInvalidated; + _b.ShouldApplyExtensionsInvalidated += OnShouldApplyExtensionsInvalidated; + } + + void OnShouldApplyExtensionsInvalidated(object sender, DesignItemCollectionEventArgs e) + { + ReapplyExtensions(e.Items); + } + + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return _a.ShouldApplyExtensions(extendedItem) && _b.ShouldApplyExtensions(extendedItem); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ReplacementForAttribute.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ReplacementForAttribute.cs new file mode 100644 index 0000000000..7c4dacf8e4 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/ReplacementForAttribute.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.WpfDesign.Extensions +{ + [AttributeUsage(AttributeTargets.Class, Inherited = false)] + public class ReplacementForAttribute : Attribute + { + public ReplacementForAttribute(Type targetType) + { + this.TargetType = targetType; + } + + public Type TargetType { get; private set; } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/SelectionExtensionServer.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/SelectionExtensionServer.cs new file mode 100644 index 0000000000..5f7f11fdb5 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Extensions/SelectionExtensionServer.cs @@ -0,0 +1,145 @@ +// +// +// +// +// $Revision: 3283 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.Extensions +{ + /// + /// Applies an extension to the selected components. + /// + public class SelectionExtensionServer : DefaultExtensionServer + { + /// + /// Is called after the extension server is initialized and the Context property has been set. + /// + protected override void OnInitialized() + { + base.OnInitialized(); + Context.SelectionService.SelectionChanged += OnSelectionChanged; + } + + void OnSelectionChanged(object sender, DesignItemCollectionEventArgs e) + { + ReapplyExtensions(e.Items); + } + + /// + /// Gets if the item is selected. + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return Context.SelectionService.IsSelected(extendedItem); + } + } + + /// + /// Applies an extension to the selected components, but not to the primary selection. + /// + public class SecondarySelectionExtensionServer : SelectionExtensionServer + { + /// + /// Gets if the item is in the secondary selection. + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return base.ShouldApplyExtensions(extendedItem) && Context.SelectionService.PrimarySelection != extendedItem; + } + } + + /// + /// Applies an extension to the primary selection. + /// + public class PrimarySelectionExtensionServer : DefaultExtensionServer + { + DesignItem oldPrimarySelection; + + /// + /// Is called after the extension server is initialized and the Context property has been set. + /// + protected override void OnInitialized() + { + base.OnInitialized(); + this.Context.SelectionService.PrimarySelectionChanged += OnPrimarySelectionChanged; + } + + void OnPrimarySelectionChanged(object sender, EventArgs e) + { + DesignItem newPrimarySelection = this.Context.SelectionService.PrimarySelection; + if (oldPrimarySelection != newPrimarySelection) { + if (oldPrimarySelection == null) { + ReapplyExtensions(new DesignItem[] { newPrimarySelection }); + } else if (newPrimarySelection == null) { + ReapplyExtensions(new DesignItem[] { oldPrimarySelection }); + } else { + ReapplyExtensions(new DesignItem[] { oldPrimarySelection, newPrimarySelection }); + } + oldPrimarySelection = newPrimarySelection; + } + } + + /// + /// Gets if the item is the primary selection. + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return Context.SelectionService.PrimarySelection == extendedItem; + } + } + + /// + /// Applies an extension to the parent of the primary selection. + /// + public class PrimarySelectionParentExtensionServer : DefaultExtensionServer + { + /// + /// Is called after the extension server is initialized and the Context property has been set. + /// + protected override void OnInitialized() + { + base.OnInitialized(); + this.Context.SelectionService.PrimarySelectionChanged += OnPrimarySelectionChanged; + this.Context.ModelService.ModelChanged += OnModelChanged; + } + + DesignItem primarySelection; + DesignItem primarySelectionParent; + + void OnPrimarySelectionChanged(object sender, EventArgs e) + { + DesignItem newPrimarySelection = this.Context.SelectionService.PrimarySelection; + if (primarySelection != newPrimarySelection) { + primarySelection = newPrimarySelection; + UpdateExtensions(); + } + } + + void OnModelChanged(object sender, ModelChangedEventArgs e) + { + UpdateExtensions(); + } + + void UpdateExtensions() + { + DesignItem newPrimarySelectionParent = primarySelection != null ? primarySelection.Parent : null; + + if (primarySelectionParent != newPrimarySelectionParent) { + DesignItem oldPrimarySelectionParent = primarySelectionParent; + primarySelectionParent = newPrimarySelectionParent; + ReapplyExtensions(new DesignItem[] { oldPrimarySelectionParent, newPrimarySelectionParent }); + } + } + + /// + /// Gets if the item is the primary selection. + /// + public override bool ShouldApplyExtensions(DesignItem extendedItem) + { + return primarySelectionParent == extendedItem; + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Category.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Category.cs new file mode 100644 index 0000000000..663a8d7244 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Category.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections.ObjectModel; +using System.ComponentModel; + +namespace ICSharpCode.WpfDesign.PropertyGrid +{ + /// + /// View-Model class for a property grid category. + /// + public class Category : INotifyPropertyChanged + { + // don't warn on missing XML comments in View-Model + #pragma warning disable 1591 + + public Category(string name) + { + Name = name; + Properties = new PropertyNodeCollection(); + //MoreProperties = new ObservableCollection(); + } + + public string Name { get; private set; } + public PropertyNodeCollection Properties { get; private set; } + //public ObservableCollection MoreProperties { get; private set; } + + bool isExpanded = true; + + public bool IsExpanded { + get { + return isExpanded; + } + set { + isExpanded = value; + RaisePropertyChanged("IsExpanded"); + } + } + + //bool showMore; + //internal bool ShowMoreByFilter; + + //public bool ShowMore { + // get { + // return showMore; + // } + // set { + // showMore = value; + // RaisePropertyChanged("ShowMore"); + // } + //} + + bool isVisible; + + public bool IsVisible + { + get + { + return isVisible; + } + set + { + isVisible = value; + RaisePropertyChanged("IsVisible"); + } + } + + #region INotifyPropertyChanged Members + + public event PropertyChangedEventHandler PropertyChanged; + + void RaisePropertyChanged(string name) + { + if (PropertyChanged != null) { + PropertyChanged(this, new PropertyChangedEventArgs(name)); + } + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/EditorManager.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/EditorManager.cs new file mode 100644 index 0000000000..632e29c6cc --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/EditorManager.cs @@ -0,0 +1,75 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Collections.Generic; +using System.Reflection; +using System.Windows; +using System.Windows.Input; +using ICSharpCode.WpfDesign.PropertyGrid.Editors; + +namespace ICSharpCode.WpfDesign.PropertyGrid +{ + /// + /// Manages registered type and property editors. + /// + public static class EditorManager + { + // property return type => editor type + static Dictionary typeEditors = new Dictionary(); + // property full name => editor type + static Dictionary propertyEditors = new Dictionary(); + + /// + /// Creates a property editor for the specified + /// + public static FrameworkElement CreateEditor(DesignItemProperty property) + { + Type editorType; + if (!propertyEditors.TryGetValue(property.FullName, out editorType)) { + var type = property.ReturnType; + while (type != null) { + if (typeEditors.TryGetValue(type, out editorType)) { + break; + } + type = type.BaseType; + } + if (editorType == null) { + var standardValues = Metadata.GetStandardValues(property.ReturnType); + if (standardValues != null) { + return new ComboBoxEditor() { ItemsSource = standardValues }; + } + return new TextBoxEditor(); + } + } + return (FrameworkElement)Activator.CreateInstance(editorType); + } + + /// + /// Registers property editors defined in the specified assembly. + /// + internal static void RegisterAssembly(Assembly assembly) + { + if (assembly == null) + throw new ArgumentNullException("assembly"); + + foreach (Type type in assembly.GetExportedTypes()) { + foreach (TypeEditorAttribute editorAttribute in type.GetCustomAttributes(typeof(TypeEditorAttribute), false)) { + CheckValidEditor(type); + typeEditors[editorAttribute.SupportedPropertyType] = type; + } + foreach (PropertyEditorAttribute editorAttribute in type.GetCustomAttributes(typeof(PropertyEditorAttribute), false)) { + CheckValidEditor(type); + string propertyName = editorAttribute.PropertyDeclaringType.FullName + "." + editorAttribute.PropertyName; + propertyEditors[propertyName] = type; + } + } + } + + static void CheckValidEditor(Type type) + { + if (!typeof(FrameworkElement).IsAssignableFrom(type)) { + throw new DesignerException("Editor types must derive from FrameworkElement!"); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/ComboBoxEditor.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/ComboBoxEditor.xaml new file mode 100644 index 0000000000..037a1ad28e --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/ComboBoxEditor.xaml @@ -0,0 +1,10 @@ + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/ComboBoxEditor.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/ComboBoxEditor.xaml.cs new file mode 100644 index 0000000000..bef62a96f1 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/ComboBoxEditor.xaml.cs @@ -0,0 +1,38 @@ +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 ICSharpCode.WpfDesign.PropertyGrid; +using System.Windows.Controls.Primitives; + +namespace ICSharpCode.WpfDesign.PropertyGrid.Editors +{ + [TypeEditor(typeof(Enum))] + public partial class ComboBoxEditor + { + /// + /// Create a new ComboBoxEditor instance. + /// + public ComboBoxEditor() + { + InitializeComponent(); + } + + /// + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + var popup = (Popup)Template.FindName("PART_Popup", this); + popup.SetValue(FontWeightProperty, FontWeights.Normal); + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/TextBoxEditor.xaml b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/TextBoxEditor.xaml new file mode 100644 index 0000000000..a36db00d81 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/TextBoxEditor.xaml @@ -0,0 +1,9 @@ + + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/TextBoxEditor.xaml.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/TextBoxEditor.xaml.cs new file mode 100644 index 0000000000..54fd974a86 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/Editors/TextBoxEditor.xaml.cs @@ -0,0 +1,38 @@ +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.PropertyGrid.Editors +{ + public partial class TextBoxEditor + { + /// + /// Creates a new TextBoxEditor instance. + /// + public TextBoxEditor() + { + InitializeComponent(); + } + + /// + protected override void OnKeyDown(KeyEventArgs e) + { + if (e.Key == Key.Enter) { + BindingOperations.GetBindingExpressionBase(this, TextProperty).UpdateSource(); + SelectAll(); + } else if (e.Key == Key.Escape) { + BindingOperations.GetBindingExpression(this, TextProperty).UpdateTarget(); + } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/PropertyEditorAttribute.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/PropertyEditorAttribute.cs new file mode 100644 index 0000000000..e0c804ae53 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/PropertyEditorAttribute.cs @@ -0,0 +1,50 @@ +// +// +// +// +// $Revision: 2254 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.PropertyGrid +{ + /// + /// Attribute to specify that the decorated class is a editor for the specified property. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false)] + public sealed class PropertyEditorAttribute : Attribute + { + readonly Type propertyDeclaringType; + readonly string propertyName; + + /// + /// Creates a new PropertyEditorAttribute that specifies that the decorated class is a editor + /// for the ".". + /// + public PropertyEditorAttribute(Type propertyDeclaringType, string propertyName) + { + if (propertyDeclaringType == null) + throw new ArgumentNullException("propertyDeclaringType"); + if (propertyName == null) + throw new ArgumentNullException("propertyName"); + this.propertyDeclaringType = propertyDeclaringType; + this.propertyName = propertyName; + } + + /// + /// Gets the type that declares the property that the decorated editor supports. + /// + public Type PropertyDeclaringType { + get { return propertyDeclaringType; } + } + + /// + /// Gets the name of the property that the decorated editor supports. + /// + public string PropertyName { + get { return propertyName; } + } + } +} + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/PropertyNode.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/PropertyNode.cs new file mode 100644 index 0000000000..e893caeb41 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/PropertyNode.cs @@ -0,0 +1,304 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel; +using System.Windows; +using System.Windows.Controls; +using System.Collections.ObjectModel; +using System.Windows.Data; +using System.Windows.Media; +using System.Windows.Markup; + +namespace ICSharpCode.WpfDesign.PropertyGrid +{ + public class PropertyNode : INotifyPropertyChanged + { + static object Unset = new object(); + + public DesignItemProperty[] Properties { get; private set; } + bool raiseEvents = true; + bool hasStringConverter; + + public string Name { get { return FirstProperty.Name; } } + public bool IsEvent { get { return FirstProperty.IsEvent; } } + public DesignContext Context { get { return FirstProperty.DesignItem.Context; } } + public FrameworkElement Editor { get; private set; } + public DesignItemProperty FirstProperty { get { return Properties[0]; } } + + public PropertyNode Parent { get; private set; } + public int Level { get; private set; } + public Category Category { get; set; } + public ObservableCollection Children { get; private set; } + public ObservableCollection MoreChildren { get; private set; } + + bool isExpanded; + + public bool IsExpanded { + get { + return isExpanded; + } + set { + isExpanded = value; + UpdateChildren(); + RaisePropertyChanged("IsExpanded"); + } + } + + public bool HasChildren { + get { return Children.Count > 0 || MoreChildren.Count > 0; } + } + + public object Description { + get { + IPropertyDescriptionService s = Context.GetService(); + if (s != null) { + return s.GetDescription(FirstProperty); + } + return null; + } + } + + public object Value { + get { + if (IsAmbiguous) return null; + var result = FirstProperty.ValueOnInstance; + if (result == DependencyProperty.UnsetValue) return null; + return result; + } + set { + SetValueCore(value); + } + } + + public string ValueString { + get { + if (ValueItem == null || ValueItem.Component is MarkupExtension) { + if (Value == null) return null; + if (hasStringConverter) { + return FirstProperty.TypeConverter.ConvertToInvariantString(Value); + } + return "(" + Value.GetType().Name + ")"; + } + return "(" + ValueItem.ComponentType.Name + ")"; + } + set { + // TODO: Doesn't work for some reason + try { + Value = FirstProperty.TypeConverter.ConvertFromInvariantString(value); + } catch { + OnValueOnInstanceChanged(); + } + } + } + + public bool IsEnabled { + get { + return ValueItem == null && hasStringConverter; + } + } + + public bool IsSet { + get { + foreach (var p in Properties) { + if (p.IsSet) return true; + } + return false; + } + } + + public FontWeight FontWeight { + get { + return IsSet ? FontWeights.Bold : FontWeights.Normal; + } + } + + public Brush NameForeground { + get { + if (ValueItem != null) { + if (ValueItem.Component is BindingBase) + return Brushes.DarkGoldenrod; + if (ValueItem.Component is StaticResourceExtension || + ValueItem.Component is DynamicResourceExtension) + return Brushes.DarkGreen; + } + return SystemColors.WindowTextBrush; + } + } + + public DesignItem ValueItem { + get { + if (Properties.Length == 1) { + return FirstProperty.Value; + } + return null; + } + } + + public bool IsAmbiguous { + get { + foreach (var p in Properties) { + if (!object.Equals(p.ValueOnInstance, FirstProperty.ValueOnInstance)) { + return true; + } + } + return false; + } + } + + bool isVisible; + + public bool IsVisible + { + get + { + return isVisible; + } + set + { + isVisible = value; + RaisePropertyChanged("IsVisible"); + } + } + + public bool CanReset { + get { return IsSet; } + } + + public void Reset() + { + SetValueCore(Unset); + } + + public void CreateBinding() + { + Value = new Binding(); + IsExpanded = true; + } + + void SetValueCore(object value) + { + raiseEvents = false; + if (value == Unset) { + foreach (var p in Properties) { + p.Reset(); + } + } + else { + foreach (var p in Properties) { + p.SetValue(value); + } + } + raiseEvents = true; + OnValueChanged(); + } + + void OnValueChanged() + { + RaisePropertyChanged("IsSet"); + RaisePropertyChanged("Value"); + RaisePropertyChanged("ValueString"); + RaisePropertyChanged("IsAmbiguous"); + RaisePropertyChanged("FontWeight"); + RaisePropertyChanged("IsEnabled"); + RaisePropertyChanged("NameForeground"); + + UpdateChildren(); + } + + void OnValueOnInstanceChanged() + { + RaisePropertyChanged("Value"); + RaisePropertyChanged("ValueString"); + } + + public PropertyNode() + { + Children = new ObservableCollection(); + MoreChildren = new ObservableCollection(); + } + + PropertyNode(DesignItemProperty[] properties, PropertyNode parent) : this() + { + this.Parent = parent; + this.Level = parent == null ? 0 : parent.Level + 1; + Load(properties); + } + + public void Load(DesignItemProperty[] properties) + { + if (Properties != null) { + foreach (var property in Properties) { + property.ValueChanged -= new EventHandler(property_ValueChanged); + property.ValueOnInstanceChanged -= new EventHandler(property_ValueOnInstanceChanged); + } + } + + this.Properties = properties; + + foreach (var property in properties) { + property.ValueChanged += new EventHandler(property_ValueChanged); + property.ValueOnInstanceChanged += new EventHandler(property_ValueOnInstanceChanged); + } + + if (Editor == null) + Editor = EditorManager.CreateEditor(FirstProperty); + + hasStringConverter = + FirstProperty.TypeConverter.CanConvertFrom(typeof(string)) && + FirstProperty.TypeConverter.CanConvertTo(typeof(string)); + + OnValueChanged(); + } + + void property_ValueOnInstanceChanged(object sender, EventArgs e) + { + if (raiseEvents) OnValueOnInstanceChanged(); + } + + void property_ValueChanged(object sender, EventArgs e) + { + if (raiseEvents) OnValueChanged(); + } + + void UpdateChildren() + { + Children.Clear(); + MoreChildren.Clear(); + + if (Parent == null || Parent.IsExpanded) { + if (ValueItem != null) { + var list = TypeHelper.GetAvailableProperties(ValueItem.ComponentType) + .OrderBy(d => d.Name) + .Select(d => new PropertyNode(new[] { ValueItem.Properties[d.Name] }, this)); + + foreach (var node in list) { + if (Metadata.IsBrowsable(node.FirstProperty)) { + node.IsVisible = true; + if (Metadata.IsPopularProperty(node.FirstProperty)) { + Children.Add(node); + } else { + MoreChildren.Add(node); + } + } + } + } + } + + RaisePropertyChanged("HasChildren"); + } + + #region INotifyPropertyChanged Members + + public event PropertyChangedEventHandler PropertyChanged; + + void RaisePropertyChanged(string name) + { + if (PropertyChanged != null) { + PropertyChanged(this, new PropertyChangedEventArgs(name)); + } + } + + #endregion + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/SortedObservableCollection.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/SortedObservableCollection.cs new file mode 100644 index 0000000000..9197e0e87f --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/SortedObservableCollection.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections.ObjectModel; + +namespace ICSharpCode.WpfDesign.PropertyGrid +{ + /// + /// Extends ObservableCollection{T} with an AddSorted method to insert items in a sorted collection. + /// + public class SortedObservableCollection : ObservableCollection + { + /// + /// Creates a new SortedObservableCollection instance. + /// + /// The function to select the sorting key. + public SortedObservableCollection(Func keySelector) + { + this.keySelector = keySelector; + this.comparer = Comparer.Default; + } + + Func keySelector; + IComparer comparer; + + /// + /// Adds an item to a sorted collection. + /// + public void AddSorted(T item) + { + int i = 0; + int j = Count - 1; + + while (i <= j) { + int n = (i + j) / 2; + int c = comparer.Compare(keySelector(item), keySelector(this[n])); + + if (c == 0) { i = n; break; } + if (c > 0) i = n + 1; + else j = n - 1; + } + + Insert(i, item); + } + } + + /// + /// A SortedObservableCollection{PropertyNode, string} that sorts by the PropertyNode's Name. + /// + public class PropertyNodeCollection : SortedObservableCollection + { + /// + /// Creates a new PropertyNodeCollection instance. + /// + public PropertyNodeCollection() : base(n => n.Name) + { + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/TypeEditorAttribute.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/TypeEditorAttribute.cs new file mode 100644 index 0000000000..d61f8c4e56 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/TypeEditorAttribute.cs @@ -0,0 +1,39 @@ +// +// +// +// +// $Revision: 2254 $ +// + +using System; + +namespace ICSharpCode.WpfDesign.PropertyGrid +{ + /// + /// Attribute to specify that the decorated class is a editor for properties with the specified + /// return type. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple=true, Inherited=false)] + public sealed class TypeEditorAttribute : Attribute + { + readonly Type supportedPropertyType; + + /// + /// Creates a new TypeEditorAttribute that specifies that the decorated class is a editor + /// for properties with the return type "". + /// + public TypeEditorAttribute(Type supportedPropertyType) + { + if (supportedPropertyType == null) + throw new ArgumentNullException("supportedPropertyType"); + this.supportedPropertyType = supportedPropertyType; + } + + /// + /// Gets the supported property type. + /// + public Type SupportedPropertyType { + get { return supportedPropertyType; } + } + } +} diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/TypeHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/TypeHelper.cs new file mode 100644 index 0000000000..4a521b99b8 --- /dev/null +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/PropertyGrid/TypeHelper.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.ComponentModel; + +namespace ICSharpCode.WpfDesign.PropertyGrid +{ + /// + /// Helper class with static methods to get the list of available properties/events. + /// + public static class TypeHelper + { + /// + /// Gets the available properties common to all input types. + /// + /// List of input types. The list must have at least one element. + public static IEnumerable GetCommonAvailableProperties(IEnumerable types) + { + foreach (var pd1 in GetAvailableProperties(types.First())) { + bool propertyOk = true; + foreach (var type in types.Skip(1)) { + bool typeOk = false; + foreach (var pd2 in GetAvailableProperties(type)) { + if (pd1 == pd2) { + typeOk = true; + break; + } + } + if (!typeOk) { + propertyOk = false; + break; + } + } + if (propertyOk) yield return pd1; + } + } + + /// + /// Gets the available properties for the type. + /// + public static IEnumerable GetAvailableProperties(Type forType) + { + foreach (PropertyDescriptor p in TypeDescriptor.GetProperties(forType)) { + if (!p.IsBrowsable) continue; + if (p.IsReadOnly) continue; + if (p.Name.Contains(".")) continue; + yield return p; + } + } + + /// + /// Gets the available events for the type. + /// + public static IEnumerable GetAvailableEvents(Type forType) + { + foreach (EventDescriptor e in TypeDescriptor.GetEvents(forType)) { + if (!e.IsBrowsable) continue; + if (e.Name.Contains(".")) continue; + yield return e; + } + } + } +} From cb95a5a4a362a900f49bfedf1f0514e28c875dba Mon Sep 17 00:00:00 2001 From: Ivan Shumilin Date: Tue, 21 Oct 2008 13:58:35 +0000 Subject: [PATCH 40/51] Setup fix git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3611 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Setup/Files.wxs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Setup/Files.wxs b/src/Setup/Files.wxs index 4683377f83..cf738e7586 100644 --- a/src/Setup/Files.wxs +++ b/src/Setup/Files.wxs @@ -1248,7 +1248,7 @@ - + @@ -1375,8 +1375,7 @@ - - + From 89a3ce3a0aa1276ee40312d74007a1242cd8c1a4 Mon Sep 17 00:00:00 2001 From: Ivan Shumilin Date: Tue, 21 Oct 2008 14:55:49 +0000 Subject: [PATCH 41/51] Setup fix git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3612 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Setup/Files.wxs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Setup/Files.wxs b/src/Setup/Files.wxs index cf738e7586..9c81ad8418 100644 --- a/src/Setup/Files.wxs +++ b/src/Setup/Files.wxs @@ -1248,7 +1248,7 @@ - + From a2c98174e2ca25c5233e9031b86c034f22ad6fc1 Mon Sep 17 00:00:00 2001 From: Ivan Shumilin Date: Tue, 21 Oct 2008 16:21:10 +0000 Subject: [PATCH 42/51] Setup fix git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3613 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/AddIns/BackendBindings/Xaml/Xaml.Tests/Xaml.Tests.csproj | 2 +- src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj | 4 ++-- .../WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj | 4 ++++ .../WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj | 3 +++ .../DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj | 4 ++++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/AddIns/BackendBindings/Xaml/Xaml.Tests/Xaml.Tests.csproj b/src/AddIns/BackendBindings/Xaml/Xaml.Tests/Xaml.Tests.csproj index 8d2589e178..75fac2d2db 100644 --- a/src/AddIns/BackendBindings/Xaml/Xaml.Tests/Xaml.Tests.csproj +++ b/src/AddIns/BackendBindings/Xaml/Xaml.Tests/Xaml.Tests.csproj @@ -25,7 +25,7 @@ pdbonly true - bin\Release\ + ..\..\..\..\..\bin\UnitTests\ TRACE prompt 4 diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj b/src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj index 792291d5d2..3a7a9b2e87 100644 --- a/src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj +++ b/src/AddIns/BackendBindings/Xaml/Xaml/Xaml.csproj @@ -23,9 +23,9 @@ 4 - pdbonly + none true - bin\Release\ + ..\..\..\..\..\AddIns\AddIns\BackendBindings\XamlBinding\ TRACE prompt 4 diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj index 3b1ed76e65..6bcd3af223 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/WpfDesign.Designer.csproj @@ -39,6 +39,10 @@ ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.Designer.xml + + ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ + ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.Designer.xml + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj index 3b81d29053..d9c4f8ec1c 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Tests/WpfDesign.Tests.csproj @@ -44,6 +44,9 @@ ..\..\..\..\..\bin\UnitTests\ + + ..\..\..\..\..\bin\UnitTests\ + diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj index c4e70725ac..81b214d4cb 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/WpfDesign.csproj @@ -44,6 +44,10 @@ ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.xml + + ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ + ..\..\..\..\..\AddIns\AddIns\DisplayBindings\WpfDesign\ICSharpCode.WpfDesign.xml + From 754374cb0160501f0fc7e09285a598f0ddcd8f84 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Tue, 21 Oct 2008 18:39:09 +0000 Subject: [PATCH 43/51] Change GUIDs for setup components that changed when files were removed or added. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3614 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Setup/Files.wxs | 18 ++++++++++++------ src/Setup/Setup.wxs | 3 +++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Setup/Files.wxs b/src/Setup/Files.wxs index 9c81ad8418..1f1170e4df 100644 --- a/src/Setup/Files.wxs +++ b/src/Setup/Files.wxs @@ -1246,7 +1246,7 @@ - + @@ -1369,15 +1369,21 @@ - + - - + + + + - - + + + + + + diff --git a/src/Setup/Setup.wxs b/src/Setup/Setup.wxs index 9ffdb6323e..21c4366bf8 100644 --- a/src/Setup/Setup.wxs +++ b/src/Setup/Setup.wxs @@ -352,7 +352,10 @@ + + + From 63e7639f2b5fdd2da6191a7262ddfebffefd95c8 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Thu, 23 Oct 2008 21:05:10 +0000 Subject: [PATCH 44/51] Updated to IronPython 2.0 RC 1 git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3615 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Setup/Files.wxs | 3 +++ src/Setup/Setup.wxs | 1 + 2 files changed, 4 insertions(+) diff --git a/src/Setup/Files.wxs b/src/Setup/Files.wxs index 1f1170e4df..47458f3d51 100644 --- a/src/Setup/Files.wxs +++ b/src/Setup/Files.wxs @@ -1299,6 +1299,9 @@ + + + diff --git a/src/Setup/Setup.wxs b/src/Setup/Setup.wxs index 21c4366bf8..393123f071 100644 --- a/src/Setup/Setup.wxs +++ b/src/Setup/Setup.wxs @@ -419,6 +419,7 @@ + From 4c5360f876878d116714edead853419222893d89 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 25 Oct 2008 15:13:27 +0000 Subject: [PATCH 45/51] fixed SD2-1470 git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3616 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Base/Project/Src/Services/Debugger/DebuggerService.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs index 64f3800552..ef33be57b6 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs @@ -442,7 +442,11 @@ namespace ICSharpCode.SharpDevelop.Debugging if (currentValue != null) { debuggerCanShowValue = true; b.Append(" = "); - b.Append(currentValue); + if (currentValue.Length > 256) { + b.Append(currentValue.Substring(0, 256)); + b.Append("..."); + } else + b.Append(currentValue); } } return b.ToString(); From d06a8755283cb5d345b2674ed272bdf99991f937 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 26 Oct 2008 18:33:15 +0000 Subject: [PATCH 46/51] C++ sample: x64 support git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3617 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- samples/CppBackendBinding/CppProject.cs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/samples/CppBackendBinding/CppProject.cs b/samples/CppBackendBinding/CppProject.cs index a8b1492629..75ceb667f6 100644 --- a/samples/CppBackendBinding/CppProject.cs +++ b/samples/CppBackendBinding/CppProject.cs @@ -215,10 +215,15 @@ namespace CppBackendBinding { string productDir = GetPathFromRegistry(@"SOFTWARE\Microsoft\VisualStudio\9.0\Setup\VC", "ProductDir"); + string batFile = "vcvars32.bat"; + if (options.Platform == "x64") { + batFile = "vcvars64.bat"; + } + string commonTools = - GetFile(productDir != null ? Path.Combine(productDir, "bin\\vcvars32.bat") : null) - ?? GetFile("%VS90COMNTOOLS%\\vsvars32.bat") - ?? GetFile("%VS80COMNTOOLS%\\vsvars32.bat"); + GetFile(productDir != null ? Path.Combine(productDir, "bin\\" + batFile) : null) + ?? GetFile("%VS90COMNTOOLS%\\" + batFile) + ?? GetFile("%VS80COMNTOOLS%\\" + batFile); Process p = new Process(); p.StartInfo.FileName = "cmd.exe"; @@ -326,5 +331,15 @@ namespace CppBackendBinding return null; } } + + public override ICollection PlatformNames { + get { + List l = new List(); + foreach (XmlElement platformElement in document.DocumentElement["Platforms"]) { + l.Add(platformElement.GetAttribute("Name")); + } + return l.AsReadOnly(); + } + } } } From 3aef8c79fee5248dbf1854f73282e689cd3fd929 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Mon, 27 Oct 2008 20:09:08 +0000 Subject: [PATCH 47/51] The home key moves the cursor to the start of the line after the prompt in the Python Console. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3618 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/PythonConsole.cs | 11 +++++ .../PythonConsoleHomeKeyTestFixture.cs | 45 +++++++++++++++++++ .../Test/PythonBinding.Tests.csproj | 1 + 3 files changed, 57 insertions(+) create mode 100644 src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/PythonConsoleHomeKeyTestFixture.cs diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsole.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsole.cs index 18261ec308..cae773bcab 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsole.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonConsole.cs @@ -226,6 +226,9 @@ namespace ICSharpCode.PythonBinding switch (keyData) { case Keys.Back: return !CanBackspace; + case Keys.Home: + MoveToHomePosition(); + return true; } return false; } @@ -283,5 +286,13 @@ namespace ICSharpCode.PythonBinding PythonConsoleCompletionDataProvider completionProvider = new PythonConsoleCompletionDataProvider(this); textEditor.ShowCompletionWindow(completionProvider); } + + /// + /// The home position is at the start of the line after the prompt. + /// + void MoveToHomePosition() + { + textEditor.Column = promptLength; + } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/PythonConsoleHomeKeyTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/PythonConsoleHomeKeyTestFixture.cs new file mode 100644 index 0000000000..c23c6249b3 --- /dev/null +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Console/PythonConsoleHomeKeyTestFixture.cs @@ -0,0 +1,45 @@ +// +// +// +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using System.Threading; +using Microsoft.Scripting.Hosting.Shell; +using ICSharpCode.PythonBinding; +using NUnit.Framework; + +namespace PythonBinding.Tests.Console +{ + /// + /// The Home Key should return the user to the start of the line after the prompt. + /// + [TestFixture] + public class PythonConsoleHomeKeyTestFixture + { + MockTextEditor textEditor; + PythonConsole console; + string prompt = ">>> "; + + [SetUp] + public void Init() + { + textEditor = new MockTextEditor(); + console = new PythonConsole(textEditor, null); + console.Write(prompt, Style.Prompt); + } + + [Test] + public void HomeKeyPressedWhenNoUserTextInConsole() + { + textEditor.RaiseDialogKeyPressEvent(Keys.Home); + + int expectedColumn = prompt.Length; + Assert.AreEqual(expectedColumn, textEditor.Column); + } + } +} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj index ff58ed4dea..c708c705a2 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj @@ -73,6 +73,7 @@ + From 0bc307d4ebf97bc7b55c905a9fbed57a6bc29f8e Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 28 Oct 2008 17:06:07 +0000 Subject: [PATCH 48/51] Mark .exe, .dll and .bat files as executable (required for cygwin). git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3619 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../RequiredLibraries/ICSharpCode.SharpZipLib.dll | Bin samples/NAnt/NAnt.AddIn/Icons/build.bat | 0 .../FSharp/RequiredLibraries/FSharp.Build.Tasks.dll | Bin .../RequiredLibraries/ICSharpCode.SharpZipLib.dll | Bin .../Project/Resources/buildwin32resource.bat | 0 .../HtmlHelp2/RequiredLibraries/MSHelpControls.dll | Bin .../HtmlHelp2/RequiredLibraries/MSHelpServices.dll | Bin .../Misc/HtmlHelp2/RequiredLibraries/import.bat | 0 .../Misc/HtmlHelp2/RequiredLibraries/stdole.dll | Bin .../Project/Src/Parser/Frames/SharpCoco.exe | Bin src/Libraries/NRefactory/Project/Src/Parser/gen.bat | 0 src/Main/Base/Test/ConsoleApp/bin/ConsoleApp.exe | Bin src/Setup/buildSetup.bat | 0 src/Tools/Help/Help2Register.exe | Bin src/Tools/Help/MSHelpServices.dll | Bin src/Tools/Help/register.bat | 0 src/Tools/Help/source/CreateMsHelpAssembly.bat | 0 src/Tools/Help/source/MSHelpServices.dll | Bin src/Tools/Help/unregister.bat | 0 .../ICSharpCode.SharpZipLib.dll | Bin .../MSBuild.Community.Tasks.dll | Bin src/clean.bat | 0 src/debugbuild.bat | 0 src/releasebuild.bat | 0 24 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 samples/ICSharpCode.Core.Demo/RequiredLibraries/ICSharpCode.SharpZipLib.dll mode change 100644 => 100755 samples/NAnt/NAnt.AddIn/Icons/build.bat mode change 100644 => 100755 src/AddIns/BackendBindings/FSharp/RequiredLibraries/FSharp.Build.Tasks.dll mode change 100644 => 100755 src/AddIns/Misc/AddInManager/RequiredLibraries/ICSharpCode.SharpZipLib.dll mode change 100644 => 100755 src/AddIns/Misc/HtmlHelp2/Project/Resources/buildwin32resource.bat mode change 100644 => 100755 src/AddIns/Misc/HtmlHelp2/RequiredLibraries/MSHelpControls.dll mode change 100644 => 100755 src/AddIns/Misc/HtmlHelp2/RequiredLibraries/MSHelpServices.dll mode change 100644 => 100755 src/AddIns/Misc/HtmlHelp2/RequiredLibraries/import.bat mode change 100644 => 100755 src/AddIns/Misc/HtmlHelp2/RequiredLibraries/stdole.dll mode change 100644 => 100755 src/Libraries/NRefactory/Project/Src/Parser/Frames/SharpCoco.exe mode change 100644 => 100755 src/Libraries/NRefactory/Project/Src/Parser/gen.bat mode change 100644 => 100755 src/Main/Base/Test/ConsoleApp/bin/ConsoleApp.exe mode change 100644 => 100755 src/Setup/buildSetup.bat mode change 100644 => 100755 src/Tools/Help/Help2Register.exe mode change 100644 => 100755 src/Tools/Help/MSHelpServices.dll mode change 100644 => 100755 src/Tools/Help/register.bat mode change 100644 => 100755 src/Tools/Help/source/CreateMsHelpAssembly.bat mode change 100644 => 100755 src/Tools/Help/source/MSHelpServices.dll mode change 100644 => 100755 src/Tools/Help/unregister.bat mode change 100644 => 100755 src/Tools/MSBuildCommunityTasks/ICSharpCode.SharpZipLib.dll mode change 100644 => 100755 src/Tools/MSBuildCommunityTasks/MSBuild.Community.Tasks.dll mode change 100644 => 100755 src/clean.bat mode change 100644 => 100755 src/debugbuild.bat mode change 100644 => 100755 src/releasebuild.bat diff --git a/samples/ICSharpCode.Core.Demo/RequiredLibraries/ICSharpCode.SharpZipLib.dll b/samples/ICSharpCode.Core.Demo/RequiredLibraries/ICSharpCode.SharpZipLib.dll old mode 100644 new mode 100755 diff --git a/samples/NAnt/NAnt.AddIn/Icons/build.bat b/samples/NAnt/NAnt.AddIn/Icons/build.bat old mode 100644 new mode 100755 diff --git a/src/AddIns/BackendBindings/FSharp/RequiredLibraries/FSharp.Build.Tasks.dll b/src/AddIns/BackendBindings/FSharp/RequiredLibraries/FSharp.Build.Tasks.dll old mode 100644 new mode 100755 diff --git a/src/AddIns/Misc/AddInManager/RequiredLibraries/ICSharpCode.SharpZipLib.dll b/src/AddIns/Misc/AddInManager/RequiredLibraries/ICSharpCode.SharpZipLib.dll old mode 100644 new mode 100755 diff --git a/src/AddIns/Misc/HtmlHelp2/Project/Resources/buildwin32resource.bat b/src/AddIns/Misc/HtmlHelp2/Project/Resources/buildwin32resource.bat old mode 100644 new mode 100755 diff --git a/src/AddIns/Misc/HtmlHelp2/RequiredLibraries/MSHelpControls.dll b/src/AddIns/Misc/HtmlHelp2/RequiredLibraries/MSHelpControls.dll old mode 100644 new mode 100755 diff --git a/src/AddIns/Misc/HtmlHelp2/RequiredLibraries/MSHelpServices.dll b/src/AddIns/Misc/HtmlHelp2/RequiredLibraries/MSHelpServices.dll old mode 100644 new mode 100755 diff --git a/src/AddIns/Misc/HtmlHelp2/RequiredLibraries/import.bat b/src/AddIns/Misc/HtmlHelp2/RequiredLibraries/import.bat old mode 100644 new mode 100755 diff --git a/src/AddIns/Misc/HtmlHelp2/RequiredLibraries/stdole.dll b/src/AddIns/Misc/HtmlHelp2/RequiredLibraries/stdole.dll old mode 100644 new mode 100755 diff --git a/src/Libraries/NRefactory/Project/Src/Parser/Frames/SharpCoco.exe b/src/Libraries/NRefactory/Project/Src/Parser/Frames/SharpCoco.exe old mode 100644 new mode 100755 diff --git a/src/Libraries/NRefactory/Project/Src/Parser/gen.bat b/src/Libraries/NRefactory/Project/Src/Parser/gen.bat old mode 100644 new mode 100755 diff --git a/src/Main/Base/Test/ConsoleApp/bin/ConsoleApp.exe b/src/Main/Base/Test/ConsoleApp/bin/ConsoleApp.exe old mode 100644 new mode 100755 diff --git a/src/Setup/buildSetup.bat b/src/Setup/buildSetup.bat old mode 100644 new mode 100755 diff --git a/src/Tools/Help/Help2Register.exe b/src/Tools/Help/Help2Register.exe old mode 100644 new mode 100755 diff --git a/src/Tools/Help/MSHelpServices.dll b/src/Tools/Help/MSHelpServices.dll old mode 100644 new mode 100755 diff --git a/src/Tools/Help/register.bat b/src/Tools/Help/register.bat old mode 100644 new mode 100755 diff --git a/src/Tools/Help/source/CreateMsHelpAssembly.bat b/src/Tools/Help/source/CreateMsHelpAssembly.bat old mode 100644 new mode 100755 diff --git a/src/Tools/Help/source/MSHelpServices.dll b/src/Tools/Help/source/MSHelpServices.dll old mode 100644 new mode 100755 diff --git a/src/Tools/Help/unregister.bat b/src/Tools/Help/unregister.bat old mode 100644 new mode 100755 diff --git a/src/Tools/MSBuildCommunityTasks/ICSharpCode.SharpZipLib.dll b/src/Tools/MSBuildCommunityTasks/ICSharpCode.SharpZipLib.dll old mode 100644 new mode 100755 diff --git a/src/Tools/MSBuildCommunityTasks/MSBuild.Community.Tasks.dll b/src/Tools/MSBuildCommunityTasks/MSBuild.Community.Tasks.dll old mode 100644 new mode 100755 diff --git a/src/clean.bat b/src/clean.bat old mode 100644 new mode 100755 diff --git a/src/debugbuild.bat b/src/debugbuild.bat old mode 100644 new mode 100755 diff --git a/src/releasebuild.bat b/src/releasebuild.bat old mode 100644 new mode 100755 From 688611c98e521d6a1ad25ae36537a939efd13e2d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 28 Oct 2008 17:06:58 +0000 Subject: [PATCH 49/51] Don't swallow load errors git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3620 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs b/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs index 5bcbefa4c3..ea0e313ff4 100644 --- a/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs +++ b/src/AddIns/BackendBindings/Xaml/Xaml/XamlDocument.cs @@ -75,6 +75,7 @@ namespace ICSharpCode.Xaml } } catch (Exception x) { + Errors.Add(new XamlDocumentError { Message = x.ToString() }); } parsing = false; From 35c6d0154e21a83985b6e6e7775dbae72271e42a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 28 Oct 2008 17:07:11 +0000 Subject: [PATCH 50/51] Fixed NullReferenceException in FileChangeWatcher.OnFileChangedEvent git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3621 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs b/src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs index 66eac96cb0..1ab479d8d2 100644 --- a/src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs +++ b/src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs @@ -128,9 +128,9 @@ namespace ICSharpCode.SharpDevelop void OnFileChangedEvent(object sender, FileSystemEventArgs e) { - LoggingService.Debug("File " + file.FileName + " was changed externally: " + e.ChangeType); if (file == null) return; + LoggingService.Debug("File " + file.FileName + " was changed externally: " + e.ChangeType); if (!wasChangedExternally) { wasChangedExternally = true; if (WorkbenchSingleton.Workbench.IsActiveWindow) { From 994ffb18128cee8aed1da7d4cdbec8f756b51689 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 28 Oct 2008 17:10:57 +0000 Subject: [PATCH 51/51] Fixed bug in CompileModifiedProjectsOnly that could cause projects to not recompile even if they were changed. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3622 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/ICSharpCode.SharpDevelop.csproj | 1 - .../Base/Project/Src/Project/BuildEngine.cs | 1 + .../Base/Project/Src/Project/BuildResults.cs | 32 +++ .../CompileModifiedProjectsOnly.cs | 91 ++++++-- .../Services/StatusBar/StatusBarService.cs | 3 +- src/Main/Base/Project/Src/Util/HashSet.cs | 194 ------------------ 6 files changed, 104 insertions(+), 218 deletions(-) delete mode 100644 src/Main/Base/Project/Src/Util/HashSet.cs diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 00cebf1b63..6530ecf132 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -648,7 +648,6 @@ - diff --git a/src/Main/Base/Project/Src/Project/BuildEngine.cs b/src/Main/Base/Project/Src/Project/BuildEngine.cs index c9e5359bb6..8c77acc14a 100644 --- a/src/Main/Base/Project/Src/Project/BuildEngine.cs +++ b/src/Main/Base/Project/Src/Project/BuildEngine.cs @@ -468,6 +468,7 @@ namespace ICSharpCode.SharpDevelop.Project node.hasErrors = !success; projectsCurrentlyBuilding.Remove(node); + results.AddBuiltProject(node.project); if (progressMonitor != null) { progressMonitor.WorkDone += 1; } diff --git a/src/Main/Base/Project/Src/Project/BuildResults.cs b/src/Main/Base/Project/Src/Project/BuildResults.cs index 3a025eed2a..c2e67edc10 100644 --- a/src/Main/Base/Project/Src/Project/BuildResults.cs +++ b/src/Main/Base/Project/Src/Project/BuildResults.cs @@ -33,6 +33,10 @@ namespace ICSharpCode.SharpDevelop.Project { List errors = new List(); ReadOnlyCollection readOnlyErrors; + + List builtProjects = new List(); + ReadOnlyCollection readOnlyBuiltProjects; + BuildResultCode result; int errorCount, warningCount; @@ -54,6 +58,20 @@ namespace ICSharpCode.SharpDevelop.Project } } + /// + /// Adds a project to the list of built projects. + /// This method is thread-sage. + /// + public void AddBuiltProject(IBuildable buildable) + { + if (buildable == null) + throw new ArgumentNullException("buildable"); + lock (builtProjects) { + readOnlyBuiltProjects = null; + builtProjects.Add(buildable); + } + } + /// /// Gets the list of build errors or warnings. /// This property is thread-safe. @@ -69,6 +87,20 @@ namespace ICSharpCode.SharpDevelop.Project } } + /// + /// Gets the list of projects that were built. This property is thread-safe. + /// + public ReadOnlyCollection BuiltProjects { + get { + lock (builtProjects) { + if (readOnlyBuiltProjects == null) { + readOnlyBuiltProjects = Array.AsReadOnly(builtProjects.ToArray()); + } + return readOnlyBuiltProjects; + } + } + } + public BuildResultCode Result { get { return result; } set { result = value; } diff --git a/src/Main/Base/Project/Src/Services/ProjectService/CompileModifiedProjectsOnly.cs b/src/Main/Base/Project/Src/Services/ProjectService/CompileModifiedProjectsOnly.cs index 53e00287b4..0ec673f40e 100644 --- a/src/Main/Base/Project/Src/Services/ProjectService/CompileModifiedProjectsOnly.cs +++ b/src/Main/Base/Project/Src/Services/ProjectService/CompileModifiedProjectsOnly.cs @@ -37,7 +37,7 @@ namespace ICSharpCode.SharpDevelop.Project set { PropertyService.Set("BuildOnExecute", value); } } - static readonly HashSet unmodifiedProjects = new HashSet(); + static readonly Dictionary unmodifiedProjects = new Dictionary(); static BuildModifiedProjectsOnlyService() { @@ -57,16 +57,27 @@ namespace ICSharpCode.SharpDevelop.Project static void ProjectService_EndBuild(object sender, BuildEventArgs e) { - // at the end of an successful build, mark all projects as unmodified + // at the end of an successful build, mark all built projects as unmodified if (e.Results.Result == BuildResultCode.Success) { - if (ProjectService.OpenSolution != null) { - lock (unmodifiedProjects) { - unmodifiedProjects.AddRange(ProjectService.OpenSolution.Projects); + lock (unmodifiedProjects) { + CompilationPass pass = new CompilationPass(); + foreach (IBuildable b in e.Results.BuiltProjects) { + IProject p = GetProjectFromBuildable(b); + if (p != null) { + unmodifiedProjects[p] = pass; + } } } } } + static IProject GetProjectFromBuildable(IBuildable b) + { + while (b is Wrapper) + b = ((Wrapper)b).wrapped; + return b as IProject; + } + static void MarkAllForRecompilation(object sender, EventArgs e) { lock (unmodifiedProjects) { @@ -94,6 +105,11 @@ namespace ICSharpCode.SharpDevelop.Project return new DummyBuildable(buildable); case BuildOnExecuteSetting.BuildModifiedAndDependent: case BuildOnExecuteSetting.BuildOnlyModified: + lock (unmodifiedProjects) { + foreach (var pair in unmodifiedProjects) { + LoggingService.Debug(pair.Key.Name + ": " + pair.Value); + } + } return new WrapperFactory().GetWrapper(buildable); case BuildOnExecuteSetting.RegularBuild: return buildable; @@ -129,8 +145,26 @@ namespace ICSharpCode.SharpDevelop.Project } } + sealed class CompilationPass + { + public readonly int Index; + + static int nextIndex; + + public CompilationPass() + { + Index = System.Threading.Interlocked.Increment(ref nextIndex); + } + + public override string ToString() + { + return "[CompilationPass " + Index + "]"; + } + } + sealed class WrapperFactory { + public readonly CompilationPass CurrentPass = new CompilationPass(); readonly Dictionary dict = new Dictionary(); public IBuildable GetWrapper(IBuildable wrapped) @@ -146,8 +180,8 @@ namespace ICSharpCode.SharpDevelop.Project sealed class Wrapper : IBuildable { - IBuildable wrapped; - WrapperFactory factory; + internal readonly IBuildable wrapped; + internal readonly WrapperFactory factory; public Wrapper(IBuildable wrapped, WrapperFactory factory) { @@ -177,7 +211,19 @@ namespace ICSharpCode.SharpDevelop.Project return result; } - internal bool wasRecompiled; + CompilationPass lastCompilationPass; + + /// + /// Returns true if "this" was recompiled after "comparisonPass". + /// + internal bool WasRecompiledAfter(CompilationPass comparisonPass) + { + Debug.Assert(comparisonPass != null); + + if (lastCompilationPass == null) + return true; + return lastCompilationPass.Index > comparisonPass.Index; + } public void StartBuild(ProjectBuildOptions buildOptions, IBuildFeedbackSink feedbackSink) { @@ -185,28 +231,27 @@ namespace ICSharpCode.SharpDevelop.Project if (p == null) { wrapped.StartBuild(buildOptions, feedbackSink); } else { - bool isUnmodified; lock (unmodifiedProjects) { - isUnmodified = unmodifiedProjects.Contains(p); - // mark project as unmodified - unmodifiedProjects.Add(p); + if (!unmodifiedProjects.TryGetValue(p, out lastCompilationPass)) { + lastCompilationPass = null; + } } - if (isUnmodified && Setting == BuildOnExecuteSetting.BuildModifiedAndDependent) { + if (lastCompilationPass != null && Setting == BuildOnExecuteSetting.BuildModifiedAndDependent) { lock (cachedBuildDependencies) { - if (cachedBuildDependencies[buildOptions].OfType().Any(w=>w.wasRecompiled)) { - isUnmodified = false; + if (cachedBuildDependencies[buildOptions].OfType().Any(w=>w.WasRecompiledAfter(lastCompilationPass))) { + lastCompilationPass = null; } } } - if (isUnmodified) { + if (lastCompilationPass != null) { feedbackSink.ReportMessage( StringParser.Parse("${res:MainWindow.CompilerMessages.SkipProjectNoChanges}", new string[,] {{ "Name", p.Name }}) ); feedbackSink.Done(true); } else { - wasRecompiled = true; - wrapped.StartBuild(buildOptions, new BuildFeedbackSink(p, feedbackSink)); + lastCompilationPass = factory.CurrentPass; + wrapped.StartBuild(buildOptions, new BuildFeedbackSink(p, feedbackSink, factory.CurrentPass)); } } } @@ -219,13 +264,16 @@ namespace ICSharpCode.SharpDevelop.Project { IProject project; IBuildFeedbackSink sink; + CompilationPass currentPass; - public BuildFeedbackSink(IProject p, IBuildFeedbackSink sink) + public BuildFeedbackSink(IProject p, IBuildFeedbackSink sink, CompilationPass currentPass) { Debug.Assert(p != null); Debug.Assert(sink != null); + Debug.Assert(currentPass != null); this.project = p; this.sink = sink; + this.currentPass = currentPass; } public void ReportError(BuildError error) @@ -240,10 +288,9 @@ namespace ICSharpCode.SharpDevelop.Project public void Done(bool success) { - if (!success) { - // force recompilation if there was a build error + if (success) { lock (unmodifiedProjects) { - unmodifiedProjects.Remove(project); + unmodifiedProjects[project] = currentPass; } } sink.Done(success); diff --git a/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs b/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs index d90037c5ce..4d8bf20649 100644 --- a/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs +++ b/src/Main/Base/Project/Src/Services/StatusBar/StatusBarService.cs @@ -6,8 +6,9 @@ // using System; -using System.Linq; +using System.Collections.Generic; using System.Drawing; +using System.Linq; using System.Windows.Forms; using ICSharpCode.Core; diff --git a/src/Main/Base/Project/Src/Util/HashSet.cs b/src/Main/Base/Project/Src/Util/HashSet.cs deleted file mode 100644 index 8d25f9bc45..0000000000 --- a/src/Main/Base/Project/Src/Util/HashSet.cs +++ /dev/null @@ -1,194 +0,0 @@ -// -// -// -// -// $Revision$ -// - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; - -namespace ICSharpCode.SharpDevelop -{ - /// - /// Represents a set of items. The set does not preserve the order of items and does not allow items to - /// be added twice. - /// It 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 - where T : class - { - Dictionary _dict; - bool _copyOnWrite; - - /// - /// 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); - 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)) { - 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 - } -}