From 70c3b777cd8e1faa4d35c18f54332c0b6020a0b6 Mon Sep 17 00:00:00 2001 From: Christian Hornung Date: Sat, 16 Aug 2008 19:49:13 +0000 Subject: [PATCH] Windows.Forms designer now uses OpenedFile for all files it modifies. This ensures that all code and designer views of the same form class are synchronized correctly. Fixes SD2-1175: .Designer.cs file is saved even if user chooses not to save changes. ActiveWindowStateConditionEvaluator now checks the dirty state of all view contents of the active window, not only the active view content. This makes the 'enabled' state of the save button consistent with its function. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3390 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/Designer/BooDesignerLoader.cs | 39 +- .../Src/Designer/FormsDesignerBinding.cs | 9 +- .../Project/Src/PythonDesignerGenerator.cs | 23 +- .../Project/Src/PythonDesignerLoader.cs | 13 +- .../Src/PythonDesignerLoaderProvider.cs | 7 +- .../Src/PythonFormsDesignerDisplayBinding.cs | 3 +- ...efHasFullyQualifiedBaseClassTestFixture.cs | 19 +- ...rgeFindsInitializeComponentsTestFixture.cs | 6 +- .../InsertNewEventHandlerTestFixture.cs | 9 +- .../Designer/NullDocumentPassedToLoader.cs | 32 -- .../Designer/NullGeneratorPassedToLoader.cs | 6 +- .../OneCompatibleMethodTestFixture.cs | 4 +- ...PythonDesignerLoaderProviderTestFixture.cs | 7 +- .../PythonDesignerLoaderTestFixture.cs | 14 +- .../FormsDesignerDisplayBindingTestFixture.cs | 2 +- .../Test/PythonBinding.Tests.csproj | 1 - .../Utils/DerivedFormDesignerViewContent.cs | 4 +- .../Test/Utils/DerivedPythonDesignerLoader.cs | 2 +- .../Test/Utils/MockDesignerGenerator.cs | 14 +- .../Test/Utils/MockOpenedFile.cs | 5 + .../Project/Src/Gui/WixDialogDesigner.cs | 117 ++++-- .../Src/Gui/WixDialogDesignerGenerator.cs | 19 +- .../AbstractDesignerGenerator.cs | 166 +++------ .../CSharpDesignerGenerator.cs | 4 +- .../DesignerGenerator/IDesignerGenerator.cs | 8 + .../VBNetDesignerGenerator.cs | 2 +- .../DesignerGenerator/XmlDesignerGenerator.cs | 15 +- .../DesignerLoader/DesignerLoaderProvider.cs | 15 +- .../NRefactoryDesignerLoader.cs | 28 +- .../Src/DesignerLoader/XmlDesignerLoader.cs | 12 +- .../Project/Src/DesignerViewContent.cs | 345 ++++++++++++------ .../Project/Src/SecondaryDisplayBinding.cs | 6 +- .../Src/Services/DesignerResourceService.cs | 10 - .../Src/Services/EventBindingService.cs | 36 +- .../Project/Src/Services/ResourceStore.cs | 2 +- .../ActiveWindowStateEvaluator.cs | 5 +- 36 files changed, 529 insertions(+), 480 deletions(-) delete mode 100644 src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NullDocumentPassedToLoader.cs diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/BooDesignerLoader.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/BooDesignerLoader.cs index 8ff1019cab..a6be2c8a3f 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/BooDesignerLoader.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/BooDesignerLoader.cs @@ -25,23 +25,14 @@ namespace Grunwald.BooBinding.Designer { public class BooDesignerLoader : AbstractCodeDomDesignerLoader { - TextEditorControl textEditorControl; - - public string TextContent { - get { - return textEditorControl.Document.TextContent; - } - } - protected override bool IsReloadNeeded() { - return base.IsReloadNeeded() || TextContent != lastTextContent; + return base.IsReloadNeeded() || this.Generator.ViewContent.DesignerCodeFileContent != lastTextContent; } - public BooDesignerLoader(TextEditorControl textEditorControl, IDesignerGenerator generator) + public BooDesignerLoader(IDesignerGenerator generator) : base(generator) { - this.textEditorControl = textEditorControl; } string lastTextContent; @@ -63,7 +54,7 @@ namespace Grunwald.BooBinding.Designer CodeCompileUnit ParseForm() { - ParseInformation parseInfo = ParserService.ParseFile(textEditorControl.FileName, textEditorControl.Text, false); + ParseInformation parseInfo = ParserService.ParseFile(this.Generator.ViewContent.DesignerCodeFile.FileName, this.Generator.ViewContent.DesignerCodeFileContent, false); Module module = ParseFormAsModule(); #if DEBUG @@ -89,15 +80,15 @@ namespace Grunwald.BooBinding.Designer // The module is cached while loading so that // determining the localization model and generating the CodeDOM // does not require the code to be parsed twice. - if (this.parsedModule != null && lastTextContent == TextContent) { + if (this.parsedModule != null && lastTextContent == this.Generator.ViewContent.DesignerCodeFileContent) { return this.parsedModule; } - lastTextContent = TextContent; + lastTextContent = this.Generator.ViewContent.DesignerCodeFileContent; - ParseInformation parseInfo = ParserService.ParseFile(textEditorControl.FileName, textEditorControl.Text, false); + ParseInformation parseInfo = ParserService.ParseFile(this.Generator.ViewContent.DesignerCodeFile.FileName, this.Generator.ViewContent.DesignerCodeFileContent, false); // ensure that there are no syntax errors in the file: - Module mainModule = Parse(textEditorControl.FileName, lastTextContent); + Module mainModule = Parse(this.Generator.ViewContent.DesignerCodeFile.FileName, lastTextContent); IClass formClass; bool isFirstClassInFile; @@ -117,17 +108,7 @@ namespace Grunwald.BooBinding.Designer throw new FormsDesignerLoadException("formClass.BaseClass returned null."); cld.BaseTypes.Add(new SimpleTypeReference(formClass.BaseClass.FullyQualifiedName)); - string fileName = initMethod.DeclaringType.CompilationUnit.FileName; - Module parsedModule; - if (FileUtility.IsEqualFileName(fileName, textEditorControl.FileName)) { - parsedModule = mainModule; - } else { - string fileContent = ParserService.GetParseableFileContent(fileName); - parsedModule = Parse(fileName, fileContent); - - // Update list of fields in designer file. Fixes SD2-973. - ParserService.ParseFile(fileName, fileContent, false); - } + System.Diagnostics.Debug.Assert(FileUtility.IsEqualFileName(initMethod.DeclaringType.CompilationUnit.FileName, this.Generator.ViewContent.DesignerCodeFile.FileName)); foreach (IField f in formClass.Fields) { if (f.ReturnType.IsDefaultReturnType) { @@ -139,7 +120,7 @@ namespace Grunwald.BooBinding.Designer } // Now find InitializeComponent in parsed module and put it into our new module - foreach (TypeMember m in parsedModule.Members) { + foreach (TypeMember m in mainModule.Members) { TypeDefinition td = m as TypeDefinition; if (td == null) continue; @@ -158,7 +139,7 @@ namespace Grunwald.BooBinding.Designer throw new FormsDesignerLoadException("Could not find InitializeComponent in parsed module."); } - Module Parse(string fileName, string fileContent) + static Module Parse(string fileName, string fileContent) { BooParsingStep step = new BooParsingStep(); diff --git a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/FormsDesignerBinding.cs b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/FormsDesignerBinding.cs index 112e085c14..7748d36331 100644 --- a/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/FormsDesignerBinding.cs +++ b/src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/Designer/FormsDesignerBinding.cs @@ -52,7 +52,7 @@ namespace Grunwald.BooBinding.Designer return new IViewContent[0]; } - IDesignerLoaderProvider loader = new BooDesignerLoaderProvider(((ITextEditorControlProvider)viewContent).TextEditorControl); + IDesignerLoaderProvider loader = new BooDesignerLoaderProvider(); IDesignerGenerator generator = new BooDesignerGenerator(); return new IViewContent[] { new FormsDesignerViewContent(viewContent, loader, generator) }; } @@ -60,16 +60,13 @@ namespace Grunwald.BooBinding.Designer public class BooDesignerLoaderProvider : IDesignerLoaderProvider { - TextEditorControl textEditorControl; - - public BooDesignerLoaderProvider(TextEditorControl textEditorControl) + public BooDesignerLoaderProvider() { - this.textEditorControl = textEditorControl; } public System.ComponentModel.Design.Serialization.DesignerLoader CreateLoader(IDesignerGenerator generator) { - return new BooDesignerLoader(textEditorControl, generator); + return new BooDesignerLoader(generator); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerGenerator.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerGenerator.cs index 9441eb92be..cf8f41fb6c 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerGenerator.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerGenerator.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.PythonBinding /// public class PythonDesignerGenerator : IDesignerGenerator { - PythonProvider pythonProvider = new PythonProvider(); + readonly PythonProvider pythonProvider = new PythonProvider(); FormsDesignerViewContent viewContent; public PythonDesignerGenerator() @@ -52,7 +52,12 @@ namespace ICSharpCode.PythonBinding { this.viewContent = null; } - + + public OpenedFile DetermineDesignerCodeFile() + { + return this.ViewContent.PrimaryFile; + } + /// /// Saves the changes made in the designer back to the source file. /// @@ -79,7 +84,7 @@ namespace ICSharpCode.PythonBinding // Insert the event handler at the end of the class with an extra // new line before it. - IDocument doc = viewContent.Document; + IDocument doc = viewContent.DesignerCodeFileDocument; string eventHandler = CreateEventHandler(eventMethodName, body, "\t"); string newContent = "\r\n" + eventHandler; int line = doc.LineSegmentCollection.Count; @@ -91,7 +96,7 @@ namespace ICSharpCode.PythonBinding position = line + 1; // Set the filename so it refers to the form being designed. - file = viewContent.TextEditorControl.FileName; + file = viewContent.DesignerCodeFile.FileName; return true; } @@ -103,8 +108,7 @@ namespace ICSharpCode.PythonBinding public ICollection GetCompatibleMethods(EventDescriptor edesc) { // Get the form or user control class. - TextEditorControl textEditor = viewContent.TextEditorControl; - ParseInformation parseInfo = ParseFile(textEditor.FileName, textEditor.Text); + ParseInformation parseInfo = ParseFile(this.ViewContent.DesignerCodeFile.FileName, this.ViewContent.DesignerCodeFileContent); // Look at the form's methods and see which are compatible. ArrayList methods = new ArrayList(); @@ -130,9 +134,8 @@ namespace ICSharpCode.PythonBinding /// protected virtual void MergeFormChanges(GeneratedInitializeComponentMethod generatedInitializeComponent) { - TextEditorControl textEditor = viewContent.TextEditorControl; - ParseInformation parseInfo = ParseFile(textEditor.FileName, textEditor.Text); - generatedInitializeComponent.Merge(textEditor.Document, parseInfo.BestCompilationUnit); + ParseInformation parseInfo = ParseFile(this.ViewContent.DesignerCodeFile.FileName, this.ViewContent.DesignerCodeFileContent); + generatedInitializeComponent.Merge(this.ViewContent.DesignerCodeFileDocument, parseInfo.BestCompilationUnit); } /// @@ -147,7 +150,7 @@ namespace ICSharpCode.PythonBinding /// /// Gets the view content attached to this generator. /// - protected FormsDesignerViewContent ViewContent { + public FormsDesignerViewContent ViewContent { get { return viewContent; } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerLoader.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerLoader.cs index 4c38bfbfe8..dbf340cd48 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerLoader.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerLoader.cs @@ -20,16 +20,9 @@ namespace ICSharpCode.PythonBinding /// public class PythonDesignerLoader : AbstractCodeDomDesignerLoader { - IDocument document; - - public PythonDesignerLoader(IDocument document, IDesignerGenerator generator) + public PythonDesignerLoader(IDesignerGenerator generator) : base(generator) { - if (document == null) { - throw new ArgumentException("Document cannot be null", "document"); - } - - this.document = document; } /// @@ -38,7 +31,7 @@ namespace ICSharpCode.PythonBinding /// protected override CodeCompileUnit Parse() { - return PythonDesignerCodeDomGenerator.Parse(document.TextContent); + return PythonDesignerCodeDomGenerator.Parse(this.Generator.ViewContent.DesignerCodeFileContent); } protected override void Write(CodeCompileUnit unit) @@ -48,7 +41,7 @@ namespace ICSharpCode.PythonBinding protected override CodeDomLocalizationModel GetCurrentLocalizationModelFromDesignedFile() { - string content = this.document.TextContent; + string content = this.Generator.ViewContent.DesignerCodeFileContent; if (content.Contains(@"resources.GetObject('$this.AutoScroll')")) { return CodeDomLocalizationModel.PropertyAssignment; diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerLoaderProvider.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerLoaderProvider.cs index 9783bfc238..d024a436ba 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerLoaderProvider.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonDesignerLoaderProvider.cs @@ -15,16 +15,13 @@ namespace ICSharpCode.PythonBinding { public class PythonDesignerLoaderProvider : IDesignerLoaderProvider { - IDocument document; - - public PythonDesignerLoaderProvider(IDocument document) + public PythonDesignerLoaderProvider() { - this.document = document; } public DesignerLoader CreateLoader(IDesignerGenerator generator) { - return new PythonDesignerLoader(document, generator); + return new PythonDesignerLoader(generator); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormsDesignerDisplayBinding.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormsDesignerDisplayBinding.cs index 628d22f65e..0c8edb5f75 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormsDesignerDisplayBinding.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonFormsDesignerDisplayBinding.cs @@ -53,8 +53,7 @@ namespace ICSharpCode.PythonBinding } } - TextEditorControl textEditor = ((ITextEditorControlProvider)viewContent).TextEditorControl; - IDesignerLoaderProvider loader = new PythonDesignerLoaderProvider(textEditor.Document); + IDesignerLoaderProvider loader = new PythonDesignerLoaderProvider(); IDesignerGenerator generator = new PythonDesignerGenerator(); return new IViewContent[] { new FormsDesignerViewContent(viewContent, loader, generator) }; } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/FormCodeTypeRefHasFullyQualifiedBaseClassTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/FormCodeTypeRefHasFullyQualifiedBaseClassTestFixture.cs index 668658cbc0..39de3690e8 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/FormCodeTypeRefHasFullyQualifiedBaseClassTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/FormCodeTypeRefHasFullyQualifiedBaseClassTestFixture.cs @@ -7,12 +7,9 @@ using System; using System.CodeDom; -using System.CodeDom.Compiler; -using System.IO; + +using ICSharpCode.FormsDesigner; using ICSharpCode.PythonBinding; -using ICSharpCode.TextEditor; -using ICSharpCode.TextEditor.Document; -using IronPython.CodeDom; using NUnit.Framework; using PythonBinding.Tests.Utils; @@ -33,11 +30,13 @@ namespace PythonBinding.Tests.Designer public void SetUpFixture() { PythonDesignerGenerator generator = new PythonDesignerGenerator(); - DocumentFactory factory = new DocumentFactory(); - IDocument doc = factory.CreateDocument(); - doc.TextContent = GetFormCode(); - DerivedPythonDesignerLoader loader = new DerivedPythonDesignerLoader(doc, generator); - codeCompileUnit = loader.CallParse(); + using(FormsDesignerViewContent view = new FormsDesignerViewContent(null, new MockOpenedFile("Test.py"))) { + view.DesignerCodeFileContent = GetFormCode(); + generator.Attach(view); + DerivedPythonDesignerLoader loader = new DerivedPythonDesignerLoader(generator); + codeCompileUnit = loader.CallParse(); + generator.Detach(); + } foreach (CodeNamespace n in codeCompileUnit.Namespaces) { foreach (CodeTypeDeclaration typeDecl in n.Types) { diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratorMergeFindsInitializeComponentsTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratorMergeFindsInitializeComponentsTestFixture.cs index 6bf9c56e9d..3ce6d51d99 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratorMergeFindsInitializeComponentsTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/GeneratorMergeFindsInitializeComponentsTestFixture.cs @@ -56,8 +56,8 @@ namespace PythonBinding.Tests.Designer generator = new DerivedPythonDesignerGenerator(); mockViewContent = new MockTextEditorViewContent(); - mockViewContent.TextEditorControl.Document.TextContent = GetTextEditorCode(); - viewContent = new FormsDesignerViewContent(mockViewContent, null, null); + viewContent = new FormsDesignerViewContent(mockViewContent, new MockOpenedFile("Test.py")); + viewContent.DesignerCodeFileContent = GetTextEditorCode(); generator.Attach(viewContent); viewContentAttached = generator.GetViewContent(); @@ -133,7 +133,7 @@ namespace PythonBinding.Tests.Designer "\t\tself.ClientSize = System.Drawing.Size(499, 309)\r\n" + "\t\tself.Name = 'MainForm'\r\n" + "\t\tself.ResumeLayout(false)\r\n"; - Assert.AreEqual(expectedText, viewContent.TextEditorControl.Document.TextContent); + Assert.AreEqual(expectedText, viewContent.DesignerCodeFileContent); } string GetTextEditorCode() diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/InsertNewEventHandlerTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/InsertNewEventHandlerTestFixture.cs index 382a0d8d66..0a215ea040 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/InsertNewEventHandlerTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/InsertNewEventHandlerTestFixture.cs @@ -32,10 +32,9 @@ namespace PythonBinding.Tests.Designer { DerivedPythonDesignerGenerator generator = new DerivedPythonDesignerGenerator(); mockViewContent = new MockTextEditorViewContent(); - mockViewContent.TextEditorControl.Document.TextContent = GetTextEditorCode(); - mockViewContent.TextEditorControl.FileName = @"C:\Projects\Python\mainform.py"; - viewContent = new DerivedFormDesignerViewContent(mockViewContent, null, null); + viewContent = new DerivedFormDesignerViewContent(mockViewContent, new MockOpenedFile(@"C:\Projects\Python\mainform.py")); generator.Attach(viewContent); + viewContent.DesignerCodeFileContent = GetTextEditorCode(); MockEventDescriptor mockEventDescriptor = new MockEventDescriptor("Click"); insertedEventHandler = generator.InsertComponentEvent(null, mockEventDescriptor, "button1_click", String.Empty, out file, out position); @@ -49,7 +48,7 @@ namespace PythonBinding.Tests.Designer "\t\tpass"; expectedCode = expectedCode + "\r\n" + eventHandler; - Assert.AreEqual(expectedCode, mockViewContent.TextEditorControl.Document.TextContent); + Assert.AreEqual(expectedCode, viewContent.DesignerCodeFileContent); } /// @@ -102,7 +101,7 @@ namespace PythonBinding.Tests.Designer [Test] public void FileNameSameAsDocumentFileName() { - Assert.AreEqual(mockViewContent.TextEditorControl.FileName, file); + Assert.AreEqual(viewContent.DesignerCodeFile.FileName, file); } } } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NullDocumentPassedToLoader.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NullDocumentPassedToLoader.cs deleted file mode 100644 index 7420534aac..0000000000 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NullDocumentPassedToLoader.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// -// -// -// $Revision$ -// - -using System; -using ICSharpCode.PythonBinding; -using NUnit.Framework; - -namespace PythonBinding.Tests.Designer -{ - /// - /// Tests that the PythonDesignerLoader throws an exception - /// when created with a null IDocument. - /// - [TestFixture] - public class NullDocumentPassedToLoader - { - [Test] - public void ThrowsException() - { - try { - PythonDesignerLoader loader = new PythonDesignerLoader(null, new PythonDesignerGenerator()); - Assert.Fail("Expected an argument exception before this line."); - } catch (ArgumentException ex) { - Assert.AreEqual("document", ex.ParamName); - } - } - } -} diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NullGeneratorPassedToLoader.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NullGeneratorPassedToLoader.cs index fbe2bc4431..e15166e288 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NullGeneratorPassedToLoader.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/NullGeneratorPassedToLoader.cs @@ -14,7 +14,7 @@ namespace PythonBinding.Tests.Designer { /// /// Tests that the PythonDesignerLoader throws an exception - /// when created with a null IDocument. + /// when created with a null IDesignerGenerator. /// [TestFixture] public class NullGeneratorPassedToLoader @@ -23,9 +23,7 @@ namespace PythonBinding.Tests.Designer public void ThrowsException() { try { - DocumentFactory factory = new DocumentFactory(); - IDocument doc = factory.CreateDocument(); - PythonDesignerLoader loader = new PythonDesignerLoader(doc, null); + PythonDesignerLoader loader = new PythonDesignerLoader(null); Assert.Fail("Expected an argument exception before this line."); } catch (ArgumentException ex) { Assert.AreEqual("generator", ex.ParamName); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/OneCompatibleMethodTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/OneCompatibleMethodTestFixture.cs index e34da90d1e..43c31fd00d 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/OneCompatibleMethodTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/OneCompatibleMethodTestFixture.cs @@ -34,8 +34,8 @@ namespace PythonBinding.Tests.Designer { DerivedPythonDesignerGenerator generator = new DerivedPythonDesignerGenerator(); MockTextEditorViewContent mockViewContent = new MockTextEditorViewContent(); - mockViewContent.TextEditorControl.Document.TextContent = GetTextEditorCode(); - DerivedFormDesignerViewContent viewContent = new DerivedFormDesignerViewContent(mockViewContent, null, null); + DerivedFormDesignerViewContent viewContent = new DerivedFormDesignerViewContent(mockViewContent, new MockOpenedFile("Test.py")); + viewContent.DesignerCodeFileContent = GetTextEditorCode(); // Create parse info. PythonParser parser = new PythonParser(); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonDesignerLoaderProviderTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonDesignerLoaderProviderTestFixture.cs index 129cbefc8d..0a20470052 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonDesignerLoaderProviderTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonDesignerLoaderProviderTestFixture.cs @@ -8,10 +8,9 @@ using System; using System.ComponentModel.Design.Serialization; using ICSharpCode.PythonBinding; -using ICSharpCode.TextEditor.Document; using IronPython.CodeDom; using NUnit.Framework; - + namespace PythonBinding.Tests.Designer { /// @@ -26,9 +25,7 @@ namespace PythonBinding.Tests.Designer [TestFixtureSetUp] public void SetUpFixture() { - DocumentFactory factory = new DocumentFactory(); - IDocument document = factory.CreateDocument(); - provider = new PythonDesignerLoaderProvider(document); + provider = new PythonDesignerLoaderProvider(); generator = new PythonDesignerGenerator(); } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonDesignerLoaderTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonDesignerLoaderTestFixture.cs index 854c23458a..c586239b6e 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonDesignerLoaderTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Designer/PythonDesignerLoaderTestFixture.cs @@ -11,9 +11,9 @@ using System.CodeDom.Compiler; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.IO; - -using ICSharpCode.TextEditor.Document; +using ICSharpCode.FormsDesigner; using ICSharpCode.PythonBinding; +using ICSharpCode.TextEditor.Document; using IronPython.CodeDom; using NUnit.Framework; using PythonBinding.Tests.Utils; @@ -26,6 +26,7 @@ namespace PythonBinding.Tests.Designer [TestFixture] public class PythonDesignerLoaderTestFixture { + FormsDesignerViewContent view; DerivedPythonDesignerLoader loader; MockDesignerGenerator generator; MockTypeResolutionService mockTypeResolutionService; @@ -36,12 +37,11 @@ namespace PythonBinding.Tests.Designer public void SetUpFixture() { generator = new MockDesignerGenerator(); + view = new FormsDesignerViewContent(null, new MockOpenedFile("Test.py")); + generator.Attach(view); - DocumentFactory factory = new DocumentFactory(); - IDocument document = factory.CreateDocument(); - document.TextEditorProperties.ConvertTabsToSpaces = false; - document.TextContent = GetFormCode(); - loader = new DerivedPythonDesignerLoader(document, generator); + view.DesignerCodeFileContent = GetFormCode(); + loader = new DerivedPythonDesignerLoader(generator); // Begin load. mockDesignerLoaderHost = new MockDesignerLoaderHost(); diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/FormsDesignerDisplayBindingTestFixture.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/FormsDesignerDisplayBindingTestFixture.cs index 5d18224641..20501f47d5 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/FormsDesignerDisplayBindingTestFixture.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/FormsDesignerDisplayBindingTestFixture.cs @@ -131,7 +131,7 @@ namespace PythonBinding.Tests { MockTextEditorViewContent view = new MockTextEditorViewContent(); IViewContent[] views = null; - using (FormsDesignerViewContent formsDesigner = new FormsDesignerViewContent(view, null, null)) { + using (FormsDesignerViewContent formsDesigner = new FormsDesignerViewContent(view, new MockOpenedFile("test.py"))) { view.SecondaryViewContents.Add(formsDesigner); views = displayBinding.CreateSecondaryViewContent(view); } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj index be2b70bb09..c35904f59d 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/PythonBinding.Tests.csproj @@ -113,7 +113,6 @@ - diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedFormDesignerViewContent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedFormDesignerViewContent.cs index 2f0eb4be19..5e23db034c 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedFormDesignerViewContent.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedFormDesignerViewContent.cs @@ -20,8 +20,8 @@ namespace PythonBinding.Tests.Utils { bool mergeFormChangesCalled; - public DerivedFormDesignerViewContent(IViewContent view, IDesignerLoaderProvider loader, IDesignerGenerator generator) - : base(view, loader, generator) + public DerivedFormDesignerViewContent(IViewContent view, ICSharpCode.SharpDevelop.OpenedFile mockFile) + : base(view, mockFile) { } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedPythonDesignerLoader.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedPythonDesignerLoader.cs index d1cf95b0ac..96ec50050d 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedPythonDesignerLoader.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/DerivedPythonDesignerLoader.cs @@ -30,7 +30,7 @@ namespace PythonBinding.Tests.Utils bool loadingAfterOnEndLoad; CodeCompileUnit codeCompileUnit; - public DerivedPythonDesignerLoader(IDocument document, IDesignerGenerator generator) : base(document, generator) + public DerivedPythonDesignerLoader(IDesignerGenerator generator) : base(generator) { } diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockDesignerGenerator.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockDesignerGenerator.cs index 4c7b83effd..68e54f2f53 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockDesignerGenerator.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockDesignerGenerator.cs @@ -21,6 +21,7 @@ namespace PythonBinding.Tests.Utils public class MockDesignerGenerator : IDesignerGenerator { CodeCompileUnit codeCompileUnit; + FormsDesignerViewContent viewContent; public MockDesignerGenerator() { @@ -40,14 +41,23 @@ namespace PythonBinding.Tests.Utils } } + public FormsDesignerViewContent ViewContent { + get { return this.viewContent; } + } + public void Attach(FormsDesignerViewContent viewContent) { - throw new NotImplementedException(); + this.viewContent = viewContent; } public void Detach() { - throw new NotImplementedException(); + this.viewContent = null; + } + + public ICSharpCode.SharpDevelop.OpenedFile DetermineDesignerCodeFile() + { + return this.viewContent.DesignerCodeFile; } public void MergeFormChanges(CodeCompileUnit unit) diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockOpenedFile.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockOpenedFile.cs index 0a1b1fc7dc..cf87d04384 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockOpenedFile.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockOpenedFile.cs @@ -21,6 +21,11 @@ namespace PythonBinding.Tests.Utils { } + public MockOpenedFile(string fileName) + { + this.FileName = fileName; + } + public override IList RegisteredViewContents { get { throw new NotImplementedException(); diff --git a/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixDialogDesigner.cs b/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixDialogDesigner.cs index 177f58cb24..2dc96b9fa8 100644 --- a/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixDialogDesigner.cs +++ b/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixDialogDesigner.cs @@ -6,7 +6,6 @@ // using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; @@ -19,6 +18,7 @@ using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Project; using ICSharpCode.TextEditor; +using ICSharpCode.TextEditor.Document; namespace ICSharpCode.WixBinding { @@ -61,6 +61,28 @@ namespace ICSharpCode.WixBinding return null; } + // The FormsDesignerViewContent normally operates independently of any + // text editor. The following overrides connect the forms designer + // directly to the underlying XML text editor so that the caret positioning + // and text selection operations done by the WiX designer actually + // become visible in the text editor. + + public override IDocument PrimaryFileDocument { + get { return ((ITextEditorControlProvider)this.PrimaryViewContent).TextEditorControl.Document; } + } + + public override IDocument DesignerCodeFileDocument { + get { return this.PrimaryFileDocument; } + } + + public override System.Text.Encoding PrimaryFileEncoding { + get { return ((ITextEditorControlProvider)this.PrimaryViewContent).TextEditorControl.Encoding; } + } + + public override System.Text.Encoding DesignerCodeFileEncoding { + get { return this.PrimaryFileEncoding; } + } + /// /// Attempts to open the Wix dialog from the document currently /// associated with this designer. @@ -71,43 +93,78 @@ namespace ICSharpCode.WixBinding JumpToDialogElement(id); if (base.Host != null) { // Reload so the correct dialog is displayed. - base.SaveToPrimary(); + this.MergeAndUnloadDesigner(); DialogId = id; - base.LoadFromPrimary(); + this.ReloadDesignerFromMemory(); } else { // Need to open the designer. DialogId = id; OpenDesigner(); } } - - protected override void LoadFromPrimary() + + protected override void LoadInternal(OpenedFile file, Stream stream) { - try { - if (!ignoreDialogIdSelectedInTextEditor) { - string dialogId = GetDialogIdSelectedInTextEditor(); - if (dialogId == null) { - dialogId = GetFirstDialogIdInTextEditor(); - JumpToDialogElement(dialogId); + if (file == this.PrimaryFile) { + try { + if (!ignoreDialogIdSelectedInTextEditor) { + string dialogId = GetDialogIdSelectedInTextEditor(); + if (dialogId == null) { + dialogId = GetFirstDialogIdInTextEditor(); + JumpToDialogElement(dialogId); + } + DialogId = dialogId; } - DialogId = dialogId; + wixProject = GetProject(); + } catch (XmlException ex) { + // Let the Wix designer loader try to load the XML and generate + // an error message. + DialogId = "InvalidXML"; + AddToErrorList(ex); } - wixProject = GetProject(); - } catch (XmlException ex) { - // Let the Wix designer loader try to load the XML and generate - // an error message. - DialogId = "InvalidXML"; - AddToErrorList(ex); } - base.LoadFromPrimary(); + base.LoadInternal(file, stream); } + #region Switch...WithoutSaveLoad + + // These four methods prevent the text editor from doing a full save/load + // cycle when switching views. This allows the text editor to keep its + // selection and caret position. + + public override bool SupportsSwitchFromThisWithoutSaveLoad(OpenedFile file, IViewContent newView) + { + return newView == this || newView == this.PrimaryViewContent; + } + + public override void SwitchFromThisWithoutSaveLoad(OpenedFile file, IViewContent newView) + { + if (newView != this) { + this.MergeAndUnloadDesigner(); + } + } + + public override bool SupportsSwitchToThisWithoutSaveLoad(OpenedFile file, IViewContent oldView) + { + return this.DesignerCodeFile != null && + (oldView == this || oldView == this.PrimaryViewContent); + } + + public override void SwitchToThisWithoutSaveLoad(OpenedFile file, IViewContent oldView) + { + if (oldView != this) { + this.ReloadDesignerFromMemory(); + } + } + + #endregion + /// /// Gets the Wix document filename. /// public string DocumentFileName { get { - return base.viewContent.PrimaryFileName; + return this.PrimaryFileName; } } @@ -125,7 +182,7 @@ namespace ICSharpCode.WixBinding /// public string GetDocumentXml() { - return GetActiveTextEditorText(); + return this.DesignerCodeFileContent; } /// @@ -183,24 +240,12 @@ namespace ICSharpCode.WixBinding return null; } - /// - /// Gets the text from the active text editor. - /// - string GetActiveTextEditorText() - { - TextAreaControl textArea = ActiveTextAreaControl; - if (textArea != null) { - return textArea.Document.TextContent; - } - return String.Empty; - } - /// /// Gets the active text area control. /// TextAreaControl ActiveTextAreaControl { get { - ITextEditorControlProvider provider = viewContent as ITextEditorControlProvider; + ITextEditorControlProvider provider = this.PrimaryViewContent as ITextEditorControlProvider; if (provider != null) { return provider.TextEditorControl.ActiveTextAreaControl; } @@ -211,7 +256,7 @@ namespace ICSharpCode.WixBinding void AddToErrorList(XmlException ex) { TaskService.ClearExceptCommentTasks(); - TaskService.Add(new Task(base.viewContent.PrimaryFileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1, TaskType.Error)); + TaskService.Add(new Task(this.PrimaryFileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1, TaskType.Error)); WorkbenchSingleton.Workbench.GetPad(typeof(ErrorListPad)).BringPadToFront(); } @@ -224,7 +269,7 @@ namespace ICSharpCode.WixBinding Solution openSolution = ProjectService.OpenSolution; if (openSolution != null) { foreach (IProject project in openSolution.Projects) { - if (project.IsFileInProject(base.viewContent.PrimaryFileName)) { + if (project.IsFileInProject(this.PrimaryFileName)) { return project as WixProject; } } diff --git a/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixDialogDesignerGenerator.cs b/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixDialogDesignerGenerator.cs index 0de2ffafd5..dae743f544 100644 --- a/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixDialogDesignerGenerator.cs +++ b/src/AddIns/BackendBindings/WixBinding/Project/Src/Gui/WixDialogDesignerGenerator.cs @@ -16,7 +16,10 @@ using System.Xml; using ICSharpCode.Core; using ICSharpCode.FormsDesigner; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.TextEditor; using ICSharpCode.TextEditor.Document; using Microsoft.CSharp; @@ -51,6 +54,15 @@ namespace ICSharpCode.WixBinding } } + public FormsDesignerViewContent ViewContent { + get { return this.view; } + } + + public OpenedFile DetermineDesignerCodeFile() + { + return this.view.PrimaryFile; + } + public void Attach(FormsDesignerViewContent viewContent) { this.view = viewContent; @@ -67,17 +79,18 @@ namespace ICSharpCode.WixBinding void IWixDialogDesignerGenerator.MergeFormChanges(string dialogId, XmlElement dialogElement) { // Get the text region we are replacing. - IDocument document = view.Document; + IDocument document = view.DesignerCodeFileDocument; DomRegion region = WixDocument.GetElementRegion(new StringReader(document.TextContent), "Dialog", dialogId); if (region.IsEmpty) { throw new FormsDesignerLoadException(String.Format(StringParser.Parse("${res:ICSharpCode.WixBinding.DialogDesignerGenerator.DialogIdNotFoundMessage}"), dialogId)); } // Get the replacement dialog xml. - ITextEditorProperties properties = view.TextEditorControl.TextEditorProperties; + TextEditorControl textEditorControl = ((ITextEditorControlProvider)view.PrimaryViewContent).TextEditorControl; + ITextEditorProperties properties = textEditorControl.TextEditorProperties; string replacementXml = WixDocument.GetXml(dialogElement, properties.LineTerminator, properties.ConvertTabsToSpaces, properties.IndentationSize); // Replace the xml and select the inserted text. - WixDocumentEditor editor = new WixDocumentEditor(view.TextEditorControl.ActiveTextAreaControl); + WixDocumentEditor editor = new WixDocumentEditor(textEditorControl.ActiveTextAreaControl); editor.Replace(region, replacementXml); } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs index 3ce18050a1..3a81e38e88 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/AbstractDesignerGenerator.cs @@ -11,18 +11,15 @@ using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; -using System.Drawing; using System.IO; using System.Reflection; + using ICSharpCode.Core; using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.TextEditor; using ICSharpCode.TextEditor.Document; -using SearchAndReplace; using ReflectionLayer = ICSharpCode.SharpDevelop.Dom.ReflectionLayer; namespace ICSharpCode.FormsDesigner @@ -30,7 +27,7 @@ namespace ICSharpCode.FormsDesigner public abstract class AbstractDesignerGenerator : IDesignerGenerator { /// The currently open part of the class being designed. - protected IClass currentClassPart; + IClass currentClassPart; /// The complete class being designed. IClass completeClass; /// The class part containing the designer code. @@ -38,7 +35,6 @@ namespace ICSharpCode.FormsDesigner IMethod initializeComponents; FormsDesignerViewContent viewContent; - bool failedDesignerInitialize = false; CodeDomProvider provider; public CodeDomProvider CodeDomProvider { @@ -56,6 +52,14 @@ namespace ICSharpCode.FormsDesigner } } + /// + /// Gets the part of the designed class that is open in the source code editor which the designer view is attached to. + /// + protected IClass CurrentClassPart { + get { return this.currentClassPart; } + set { this.currentClassPart = value; } + } + public void Attach(FormsDesignerViewContent viewContent) { this.viewContent = viewContent; @@ -66,6 +70,27 @@ namespace ICSharpCode.FormsDesigner this.viewContent = null; } + public OpenedFile DetermineDesignerCodeFile() + { + // get new initialize components + ParseInformation info = ParserService.ParseFile(this.viewContent.PrimaryFileName, this.viewContent.PrimaryFileContent, false); + ICompilationUnit cu = info.BestCompilationUnit; + foreach (IClass c in cu.Classes) { + if (FormsDesignerSecondaryDisplayBinding.BaseClassIsFormOrControl(c)) { + this.currentClassPart = c; + this.initializeComponents = FormsDesignerSecondaryDisplayBinding.GetInitializeComponents(c); + if (this.initializeComponents != null) { + string designerFile = this.initializeComponents.DeclaringType.CompilationUnit.FileName; + if (designerFile != null) { + return FileService.GetOrCreateOpenedFile(designerFile); + } + } + } + } + + throw new FormsDesignerLoadException("Could not find InitializeComponent method in any part of the open class."); + } + /// /// Removes the field declaration with the specified name from the source file. /// @@ -76,14 +101,13 @@ namespace ICSharpCode.FormsDesigner Reparse(); IField field = GetField(formClass, fieldName); if (field != null) { - int startOffset = document.PositionToOffset(new TextLocation(0, field.Region.BeginLine - 1)); - int endOffset = document.PositionToOffset(new TextLocation(0, field.Region.EndLine)); - document.Remove(startOffset, endOffset - startOffset); + int startOffset = this.ViewContent.DesignerCodeFileDocument.PositionToOffset(new TextLocation(0, field.Region.BeginLine - 1)); + int endOffset = this.ViewContent.DesignerCodeFileDocument.PositionToOffset(new TextLocation(0, field.Region.EndLine)); + this.ViewContent.DesignerCodeFileDocument.Remove(startOffset, endOffset - startOffset); } else if ((field = GetField(completeClass, fieldName)) != null) { // TODO: Remove the field in the part where it is declared LoggingService.Warn("Removing field declaration in non-designer part currently not supported"); } - SaveDocument(); } catch (Exception ex) { MessageService.ShowError(ex); } @@ -114,19 +138,18 @@ namespace ICSharpCode.FormsDesigner Reparse(); IField oldField = GetField(formClass, newField.Name); if (oldField != null) { - int startOffset = document.PositionToOffset(new TextLocation(0, oldField.Region.BeginLine - 1)); - int endOffset = document.PositionToOffset(new TextLocation(0, oldField.Region.EndLine)); - document.Replace(startOffset, endOffset - startOffset, tabs + GenerateFieldDeclaration(domGenerator, newField) + Environment.NewLine); + int startOffset = this.ViewContent.DesignerCodeFileDocument.PositionToOffset(new TextLocation(0, oldField.Region.BeginLine - 1)); + int endOffset = this.ViewContent.DesignerCodeFileDocument.PositionToOffset(new TextLocation(0, oldField.Region.EndLine)); + this.ViewContent.DesignerCodeFileDocument.Replace(startOffset, endOffset - startOffset, tabs + GenerateFieldDeclaration(domGenerator, newField) + Environment.NewLine); } else { if ((oldField = GetField(completeClass, newField.Name)) != null) { // TODO: Replace the field in the part where it is declared LoggingService.Warn("Field declaration replacement in non-designer part currently not supported"); } else { - int endOffset = document.PositionToOffset(new TextLocation(0, initializeComponents.BodyRegion.EndLine)); - document.Insert(endOffset, tabs + GenerateFieldDeclaration(domGenerator, newField) + Environment.NewLine); + int endOffset = this.ViewContent.DesignerCodeFileDocument.PositionToOffset(new TextLocation(0, initializeComponents.BodyRegion.EndLine)); + this.ViewContent.DesignerCodeFileDocument.Insert(endOffset, tabs + GenerateFieldDeclaration(domGenerator, newField) + Environment.NewLine); } } - SaveDocument(); } catch (Exception ex) { MessageService.ShowError(ex); } @@ -183,14 +206,13 @@ namespace ICSharpCode.FormsDesigner string statements = writer.ToString(); // initializeComponents.BodyRegion.BeginLine + 1 - DomRegion bodyRegion = GetReplaceRegion(document, initializeComponents); + DomRegion bodyRegion = GetReplaceRegion(this.ViewContent.DesignerCodeFileDocument, initializeComponents); if (bodyRegion.BeginColumn <= 0 || bodyRegion.EndColumn <= 0) throw new InvalidOperationException("Column must be > 0"); - int startOffset = document.PositionToOffset(new TextLocation(bodyRegion.BeginColumn - 1, bodyRegion.BeginLine - 1)); - int endOffset = document.PositionToOffset(new TextLocation(bodyRegion.EndColumn - 1, bodyRegion.EndLine - 1)); + int startOffset = this.ViewContent.DesignerCodeFileDocument.PositionToOffset(new TextLocation(bodyRegion.BeginColumn - 1, bodyRegion.BeginLine - 1)); + int endOffset = this.ViewContent.DesignerCodeFileDocument.PositionToOffset(new TextLocation(bodyRegion.EndColumn - 1, bodyRegion.EndLine - 1)); - document.Replace(startOffset, endOffset - startOffset, statements); - SaveDocument(); + this.ViewContent.DesignerCodeFileDocument.Replace(startOffset, endOffset - startOffset, statements); // apply changes the designer made to field declarations // first loop looks for added and changed fields @@ -222,7 +244,7 @@ namespace ICSharpCode.FormsDesigner // we must not modify the c.Fields collection while it is enumerated removedFields.ForEach(RemoveField); - ParserService.EnqueueForParsing(designerFile, document.TextContent); + ParserService.EnqueueForParsing(this.ViewContent.DesignerCodeFile.FileName, this.ViewContent.DesignerCodeFileDocument.TextContent); } /// @@ -230,7 +252,7 @@ namespace ICSharpCode.FormsDesigner /// the CodeDom field declaration newField. /// /// true, if the fields are different in type or modifiers, otherwise false. - bool FieldChanged(IField oldField, CodeMemberField newField) + static bool FieldChanged(IField oldField, CodeMemberField newField) { // compare types if (oldField.ReturnType != null && oldField.ReturnType.GetUnderlyingClass() != null) { // ignore type changes to untyped VB fields @@ -263,90 +285,24 @@ namespace ICSharpCode.FormsDesigner return false; } - IDocument document; - string saveDocumentToFile; - string designerFile; - - /// - /// The document containing the content of the . Can be a - /// text editor document or independent of a text editor if partial classes are used. - /// - protected IDocument Document { - get { return document; } - set { document = value; } - } - /// - /// only set when InitializeComponent was loaded from code-behind file that was not open, - /// is normally either null or the same value as . - /// - protected string SaveDocumentToFile { - get { return saveDocumentToFile; } - set { saveDocumentToFile = value; } - } - /// - /// file that contains InitializeComponents - /// - protected string DesignerFile { - get { return designerFile; } - set { designerFile = value; } - } - - void SaveDocument() - { - if (saveDocumentToFile != null) { - NamedFileOperationDelegate method = delegate(string fileName) { - using (StreamWriter writer = new StreamWriter(fileName, false, System.Text.Encoding.UTF8)) { - writer.Write(document.TextContent); - } - }; - FileUtility.ObservedSave(method, saveDocumentToFile, FileErrorPolicy.Inform); - } - } - protected void Reparse() { - saveDocumentToFile = null; - // get new initialize components - string content = viewContent.Document.TextContent; - ParseInformation info = ParserService.ParseFile(viewContent.TextEditorControl.FileName, content, false); - ICompilationUnit cu = (ICompilationUnit)info.BestCompilationUnit; + ParseInformation info = ParserService.ParseFile(this.ViewContent.DesignerCodeFile.FileName, this.ViewContent.DesignerCodeFileContent, false); + ICompilationUnit cu = info.BestCompilationUnit; foreach (IClass c in cu.Classes) { if (FormsDesignerSecondaryDisplayBinding.BaseClassIsFormOrControl(c)) { - initializeComponents = FormsDesignerSecondaryDisplayBinding.GetInitializeComponents(c); - if (initializeComponents != null) { - designerFile = initializeComponents.DeclaringType.CompilationUnit.FileName; - string designerContent; - if (FileUtility.IsEqualFileName(viewContent.TextEditorControl.FileName, designerFile)) { - designerContent = content; - document = viewContent.Document; - } else { - IViewContent designerFileViewContent = FileService.GetOpenFile(designerFile); - if (designerFileViewContent == null) { - document = new DocumentFactory().CreateDocument(); - designerContent = ParserService.GetParseableFileContent(designerFile); - document.TextContent = designerContent; - saveDocumentToFile = designerFile; - } else { - ITextEditorControlProvider tecp = designerFileViewContent as ITextEditorControlProvider; - if (tecp == null) - throw new ApplicationException("designer file viewcontent must implement ITextEditorControlProvider"); - document = tecp.TextEditorControl.Document; - designerContent = document.TextContent; - } - ParserService.ParseFile(designerFile, designerContent, false); - initializeComponents = FormsDesignerSecondaryDisplayBinding.GetInitializeComponents(c); - } - using (StringReader r = new StringReader(designerContent)) { - int count = initializeComponents.Region.BeginLine; + this.initializeComponents = FormsDesignerSecondaryDisplayBinding.GetInitializeComponents(c); + if (this.initializeComponents != null) { + using (StringReader r = new StringReader(this.ViewContent.DesignerCodeFileContent)) { + int count = this.initializeComponents.Region.BeginLine; for (int i = 1; i < count; i++) r.ReadLine(); string line = r.ReadLine(); tabs = GetIndentation(line); } - this.currentClassPart = c; this.completeClass = c.GetCompoundClass(); - this.formClass = initializeComponents.DeclaringType; + this.formClass = this.initializeComponents.DeclaringType; break; } } @@ -378,19 +334,15 @@ namespace ICSharpCode.FormsDesigner /// public virtual bool InsertComponentEvent(IComponent component, EventDescriptor edesc, string eventMethodName, string body, out string file, out int position) { - if (this.failedDesignerInitialize) { - position = 0; - file = currentClassPart.CompilationUnit.FileName; - return false; - } - Reparse(); foreach (IMethod method in completeClass.Methods) { if (method.Name == eventMethodName) { file = method.DeclaringType.CompilationUnit.FileName; - if (FileUtility.IsEqualFileName(file, this.designerFile)) { - position = GetCursorLine(document, method); + if (FileUtility.IsEqualFileName(file, this.ViewContent.PrimaryFileName)) { + position = GetCursorLine(this.ViewContent.PrimaryFileDocument, method); + } else if (FileUtility.IsEqualFileName(file, this.ViewContent.DesignerCodeFile.FileName)) { + position = GetCursorLine(this.ViewContent.DesignerCodeFileDocument, method); } else { try { position = GetCursorLine(FindReferencesAndRenameHelper.GetDocumentInformation(file).CreateDocument(), method); @@ -402,16 +354,18 @@ namespace ICSharpCode.FormsDesigner return true; } } + viewContent.MergeFormChanges(); Reparse(); file = currentClassPart.CompilationUnit.FileName; int line = GetEventHandlerInsertionLine(currentClassPart); - int offset = viewContent.Document.GetLineSegment(line - 1).Offset; + int offset = this.viewContent.PrimaryFileDocument.GetLineSegment(line - 1).Offset; - viewContent.Document.Insert(offset, CreateEventHandler(edesc.EventType, eventMethodName, body, tabs)); + this.viewContent.PrimaryFileDocument.Insert(offset, CreateEventHandler(edesc.EventType, eventMethodName, body, tabs)); position = line + GetCursorLineAfterEventHandlerCreation(); + this.viewContent.PrimaryFile.MakeDirty(); return true; } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/CSharpDesignerGenerator.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/CSharpDesignerGenerator.cs index 677fdbcc7c..d61246d446 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/CSharpDesignerGenerator.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/CSharpDesignerGenerator.cs @@ -79,7 +79,7 @@ namespace ICSharpCode.FormsDesigner protected string GenerateParams(Type eventType, bool paramNames) { CSharpOutputVisitor v = new CSharpOutputVisitor(); - MethodDeclaration md = ConvertEventInvokeMethodToNRefactory(currentClassPart, eventType, "name"); + MethodDeclaration md = ConvertEventInvokeMethodToNRefactory(CurrentClassPart, eventType, "name"); if (md != null) { v.AppendCommaSeparatedList(md.Parameters); } @@ -100,7 +100,7 @@ namespace ICSharpCode.FormsDesigner CSharpDesignerGenerator gen = new CSharpDesignerGenerator(); - gen.currentClassPart = c; + gen.CurrentClassPart = c; int line = gen.GetEventHandlerInsertionLine(c); int offset = document.GetLineSegment(line - 1).Offset; diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/IDesignerGenerator.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/IDesignerGenerator.cs index d30c85173e..9dbc0bf73a 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/IDesignerGenerator.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/IDesignerGenerator.cs @@ -12,6 +12,8 @@ using System.Collections; using System.ComponentModel; using System.Reflection; +using ICSharpCode.SharpDevelop; + namespace ICSharpCode.FormsDesigner { public interface IDesignerGenerator @@ -21,6 +23,12 @@ namespace ICSharpCode.FormsDesigner } void Attach(FormsDesignerViewContent viewContent); void Detach(); + FormsDesignerViewContent ViewContent { get; } + /// + /// Gets the OpenedFile for the file which contains the code to be modified by the forms designer. + /// This method must never return null. If it cannot find that file, it must throw an exception. + /// + OpenedFile DetermineDesignerCodeFile(); void MergeFormChanges(CodeCompileUnit unit); bool InsertComponentEvent(IComponent component, EventDescriptor edesc, string eventMethodName, string body, out string file, out int position); ICollection GetCompatibleMethods(EventDescriptor edesc); diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/VBNetDesignerGenerator.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/VBNetDesignerGenerator.cs index 2588cc1187..94b7add6ee 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/VBNetDesignerGenerator.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/VBNetDesignerGenerator.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.FormsDesigner protected string GenerateParams(Type eventType) { VBNetOutputVisitor v = new VBNetOutputVisitor(); - MethodDeclaration md = ConvertEventInvokeMethodToNRefactory(currentClassPart, eventType, "name"); + MethodDeclaration md = ConvertEventInvokeMethodToNRefactory(this.CurrentClassPart, eventType, "name"); if (md != null) { v.AppendCommaSeparatedList(md.Parameters); } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/XmlDesignerGenerator.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/XmlDesignerGenerator.cs index 08dd1381ba..69de7b86c6 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/XmlDesignerGenerator.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerGenerator/XmlDesignerGenerator.cs @@ -17,6 +17,8 @@ using System.Reflection; using System.Windows.Forms; using System.Xml; +using ICSharpCode.SharpDevelop; + namespace ICSharpCode.FormsDesigner { public class XmlDesignerGenerator : IDesignerGenerator @@ -29,6 +31,10 @@ namespace ICSharpCode.FormsDesigner } } + public FormsDesignerViewContent ViewContent { + get { return this.viewContent; } + } + public void Attach(FormsDesignerViewContent viewContent) { this.viewContent = viewContent; @@ -39,6 +45,11 @@ namespace ICSharpCode.FormsDesigner this.viewContent = null; } + public OpenedFile DetermineDesignerCodeFile() + { + return this.viewContent.PrimaryFile; + } + public void MergeFormChanges(CodeCompileUnit unit) { StringWriter writer = new StringWriter(); @@ -55,13 +66,13 @@ namespace ICSharpCode.FormsDesigner } xml.WriteEndElement(); //xml.WriteEndDocument(); - viewContent.Document.TextContent = writer.ToString(); + viewContent.DesignerCodeFileContent = writer.ToString(); } public bool InsertComponentEvent(IComponent component, EventDescriptor edesc, string eventMethodName, string body, out string file, out int position) { position = 0; - file = this.viewContent.TextEditorControl.FileName; + file = this.viewContent.PrimaryFileName; return false; } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/DesignerLoaderProvider.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/DesignerLoaderProvider.cs index 18cdc9e73c..474cb572ee 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/DesignerLoaderProvider.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/DesignerLoaderProvider.cs @@ -19,33 +19,28 @@ namespace ICSharpCode.FormsDesigner public class NRefactoryDesignerLoaderProvider : IDesignerLoaderProvider { - SupportedLanguage language; - TextEditorControl textEditorControl; + readonly SupportedLanguage language; - public NRefactoryDesignerLoaderProvider(SupportedLanguage language, TextEditorControl textEditorControl) + public NRefactoryDesignerLoaderProvider(SupportedLanguage language) { this.language = language; - this.textEditorControl = textEditorControl; } public DesignerLoader CreateLoader(IDesignerGenerator generator) { - return new NRefactoryDesignerLoader(language, textEditorControl, generator); + return new NRefactoryDesignerLoader(language, generator); } } public class XmlDesignerLoaderProvider : IDesignerLoaderProvider { - TextEditorControl textEditorControl; - - public XmlDesignerLoaderProvider(TextEditorControl textEditorControl) + public XmlDesignerLoaderProvider() { - this.textEditorControl = textEditorControl; } public DesignerLoader CreateLoader(IDesignerGenerator generator) { - return new XmlDesignerLoader(textEditorControl, generator); + return new XmlDesignerLoader(generator); } } } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs index e9810d1b25..d67fdfac9c 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/NRefactoryDesignerLoader.cs @@ -39,24 +39,15 @@ namespace ICSharpCode.FormsDesigner { SupportedLanguage language; - TextEditorControl textEditorControl; - - public string TextContent { - get { - return textEditorControl.Document.TextContent; - } - } - protected override bool IsReloadNeeded() { - return base.IsReloadNeeded() || TextContent != lastTextContent; + return base.IsReloadNeeded() || this.Generator.ViewContent.DesignerCodeFileContent != lastTextContent; } - public NRefactoryDesignerLoader(SupportedLanguage language, TextEditorControl textEditorControl, IDesignerGenerator generator) + public NRefactoryDesignerLoader(SupportedLanguage language, IDesignerGenerator generator) : base(generator) { this.language = language; - this.textEditorControl = textEditorControl; } string lastTextContent; @@ -101,9 +92,9 @@ namespace ICSharpCode.FormsDesigner { LoggingService.Debug("NRefactoryDesignerLoader.Parse()"); - lastTextContent = TextContent; + lastTextContent = this.Generator.ViewContent.DesignerCodeFileContent; - ParseInformation parseInfo = ParserService.GetParseInformation(textEditorControl.FileName); + ParseInformation parseInfo = ParserService.GetParseInformation(this.Generator.ViewContent.DesignerCodeFile.FileName); IClass formClass; bool isFirstClassInFile; @@ -138,7 +129,14 @@ namespace ICSharpCode.FormsDesigner } if (found) continue; - string fileContent = ParserService.GetParseableFileContent(fileName); + string fileContent; + if (FileUtility.IsEqualFileName(fileName, this.Generator.ViewContent.PrimaryFileName)) { + fileContent = this.Generator.ViewContent.PrimaryFileContent; + } else if (FileUtility.IsEqualFileName(fileName, this.Generator.ViewContent.DesignerCodeFile.FileName)) { + fileContent = this.Generator.ViewContent.DesignerCodeFileContent; + } else { + fileContent = ParserService.GetParseableFileContent(fileName); + } ICSharpCode.NRefactory.IParser p = ICSharpCode.NRefactory.ParserFactory.CreateParser(language, new StringReader(fileContent)); p.Parse(); @@ -300,7 +298,7 @@ namespace ICSharpCode.FormsDesigner protected override CodeDomLocalizationModel GetCurrentLocalizationModelFromDesignedFile() { - ParseInformation parseInfo = ParserService.GetParseInformation(this.textEditorControl.FileName); + ParseInformation parseInfo = ParserService.ParseFile(this.Generator.ViewContent.DesignerCodeFile.FileName, this.Generator.ViewContent.DesignerCodeFileContent, false); IClass formClass; bool isFirstClassInFile; diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/XmlDesignerLoader.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/XmlDesignerLoader.cs index 425a5040cc..eb094d8cbe 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/XmlDesignerLoader.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerLoader/XmlDesignerLoader.cs @@ -21,18 +21,10 @@ namespace ICSharpCode.FormsDesigner { public class XmlDesignerLoader : BasicDesignerLoader, IObjectCreator { - TextEditorControl textEditorControl; IDesignerGenerator generator; - public string TextContent { - get { - return textEditorControl.Document.TextContent; - } - } - - public XmlDesignerLoader(TextEditorControl textEditorControl, IDesignerGenerator generator) + public XmlDesignerLoader(IDesignerGenerator generator) { - this.textEditorControl = textEditorControl; this.generator = generator; } @@ -51,7 +43,7 @@ namespace ICSharpCode.FormsDesigner { XmlLoader loader = new XmlLoader(); loader.ObjectCreator = this; - loader.CreateObjectFromXmlDefinition(TextContent); + loader.CreateObjectFromXmlDefinition(this.generator.ViewContent.DesignerCodeFileContent); } protected override void PerformFlush(IDesignerSerializationManager serializationManager) diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs index 8fe9525571..f0f6c66c91 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs @@ -7,12 +7,12 @@ using System; using System.Collections; -using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Drawing; -using System.Reflection; +using System.IO; +using System.Text; using System.Windows.Forms; using ICSharpCode.Core; @@ -21,64 +21,80 @@ using ICSharpCode.FormsDesigner.UndoRedo; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Gui; -using ICSharpCode.TextEditor; using ICSharpCode.TextEditor.Document; -using ICSharpCode.SharpDevelop.Widgets.SideBar; +using ICSharpCode.TextEditor.Util; namespace ICSharpCode.FormsDesigner { - public class FormsDesignerViewContent : AbstractSecondaryViewContent, IClipboardHandler, IUndoHandler, IHasPropertyContainer, IContextHelpProvider, IToolsHost + public class FormsDesignerViewContent : AbstractViewContentHandlingLoadErrors, IClipboardHandler, IUndoHandler, IHasPropertyContainer, IContextHelpProvider, IToolsHost { - protected bool failedDesignerInitialize; - - protected IViewContent viewContent; - protected ITextEditorControlProvider textAreaControlProvider; - Panel p = new Panel(); DesignSurface designSurface; bool disposing; + bool loadingDesigner; - IDesignerLoaderProvider loaderProvider; - IDesignerGenerator generator; + readonly IViewContent primaryViewContent; + readonly IDesignerLoaderProvider loaderProvider; + readonly IDesignerGenerator generator; readonly ResourceStore resourceStore; FormsDesignerUndoEngine undoEngine; - public override Control Control { - get { - return p; - } - } + Encoding primaryFileEncoding; + readonly IDocument primaryFileDocument = new DocumentFactory().CreateDocument(); + Encoding designerCodeFileEncoding; + OpenedFile designerCodeFile; + IDocument designerCodeFileDocument; - public DesignSurface DesignSurface { + protected DesignSurface DesignSurface { get { return designSurface; } } - public TextEditorControl TextEditorControl { + public IDesignerHost Host { get { - return textAreaControlProvider.TextEditorControl; + if (designSurface == null) + return null; + return (IDesignerHost)designSurface.GetService(typeof(IDesignerHost)); } } - public IDocument Document { - get { - return TextEditorControl.Document; - } + + public OpenedFile DesignerCodeFile { + get { return this.designerCodeFile; } } - internal new ICollection Files { - get { return base.Files; } + public virtual IDocument PrimaryFileDocument { + get { return this.primaryFileDocument; } } - public IDesignerHost Host { - get { - if (designSurface == null) - return null; - return (IDesignerHost)designSurface.GetService(typeof(IDesignerHost)); - } + public string PrimaryFileContent { + get { return this.PrimaryFileDocument.TextContent; } + set { this.PrimaryFileDocument.TextContent = value; } + } + + public virtual Encoding PrimaryFileEncoding { + get { return this.primaryFileEncoding; } + } + + public virtual IDocument DesignerCodeFileDocument { + get { return this.designerCodeFileDocument; } + } + + public string DesignerCodeFileContent { + get { return this.DesignerCodeFileDocument.TextContent; } + set { this.DesignerCodeFileDocument.TextContent = value; } } - public FormsDesignerViewContent(IViewContent viewContent, IDesignerLoaderProvider loaderProvider, IDesignerGenerator generator) - : base(viewContent) + + public virtual Encoding DesignerCodeFileEncoding { + get { return this.designerCodeFileEncoding; } + } + + public IViewContent PrimaryViewContent { + get { return this.primaryViewContent; } + } + + FormsDesignerViewContent(IViewContent primaryViewContent) + : base() { this.TabPageText = "${res:FormsDesigner.DesignTabPages.DesignTabPage}"; @@ -86,16 +102,15 @@ namespace ICSharpCode.FormsDesigner FormKeyHandler.Insert(); } - this.loaderProvider = loaderProvider; - this.generator = generator; + this.primaryViewContent = primaryViewContent; + p.BackColor = Color.White; p.RightToLeft = RightToLeft.No; // Make sure auto-scaling is based on the correct font. // This is required on Vista, I don't know why it works correctly in XP p.Font = Control.DefaultFont; - this.viewContent = viewContent; - this.textAreaControlProvider = viewContent as ITextEditorControlProvider; + this.UserControl = this.p; this.resourceStore = new ResourceStore(this); @@ -105,6 +120,122 @@ namespace ICSharpCode.FormsDesigner } } + public FormsDesignerViewContent(IViewContent primaryViewContent, IDesignerLoaderProvider loaderProvider, IDesignerGenerator generator) + : this(primaryViewContent) + { + if (loaderProvider == null) + throw new ArgumentNullException("loaderProvider"); + if (generator == null) + throw new ArgumentNullException("generator"); + + this.loaderProvider = loaderProvider; + this.generator = generator; + this.generator.Attach(this); + + this.Files.Add(this.primaryViewContent.PrimaryFile); + } + + /// + /// This constructor allows running in unit test mode with a mock file. + /// + public FormsDesignerViewContent(IViewContent primaryViewContent, OpenedFile mockFile) + : this(primaryViewContent) + { + this.primaryFileDocument = new DocumentFactory().CreateDocument(); + this.designerCodeFileDocument = this.primaryFileDocument; + this.designerCodeFileEncoding = System.Text.Encoding.UTF8; + this.designerCodeFile = mockFile; + } + + protected override void LoadInternal(OpenedFile file, System.IO.Stream stream) + { + LoggingService.Debug("Forms designer: Load " + file.FileName); + + if (file == this.PrimaryFile) { + + this.primaryFileEncoding = ParserService.DefaultFileEncoding; + this.primaryFileDocument.TextContent = FileReader.ReadFileContent(stream, ref this.primaryFileEncoding); + + LoggingService.Debug("Forms designer: Determining designer code file for " + file.FileName); + OpenedFile newDesignerCodeFile = this.generator.DetermineDesignerCodeFile(); + if (newDesignerCodeFile == null) { + throw new InvalidOperationException("The designer code file could not be determined."); + } + + if (this.designerCodeFile != null && newDesignerCodeFile != this.designerCodeFile) { + this.Files.Remove(this.designerCodeFile); + } + this.designerCodeFile = newDesignerCodeFile; + + if (this.designerCodeFile == this.PrimaryFile) { + + LoggingService.Debug("Forms designer: Designer code file is equal to primary file. Reloading designer."); + + this.UnloadDesigner(); + this.designerCodeFileEncoding = this.PrimaryFileEncoding; + this.designerCodeFileDocument = this.PrimaryFileDocument; + this.LoadAndDisplayDesigner(); + + } else if (!this.Files.Contains(this.designerCodeFile)) { + LoggingService.Debug("Forms designer: Adding designer code file " + this.designerCodeFile.FileName); + this.Files.Insert(1, this.designerCodeFile); + } + + } else if (file == this.DesignerCodeFile) { + + LoggingService.Debug("Forms designer: Reloading designer because of LoadInternal on DesignerCodeFile"); + + this.UnloadDesigner(); + this.designerCodeFileEncoding = ParserService.DefaultFileEncoding; + this.designerCodeFileDocument = new DocumentFactory().CreateDocument(); + this.designerCodeFileDocument.TextContent = FileReader.ReadFileContent(stream, ref this.designerCodeFileEncoding); + this.LoadAndDisplayDesigner(); + + } else { + + // Loading a resource file + + bool mustReload; + if (this.designSurface != null && !this.loadingDesigner) { + LoggingService.Debug("Forms designer: Reloading designer because of LoadInternal on resource file"); + this.UnloadDesigner(); + mustReload = true; + } else { + mustReload = false; + } + LoggingService.Debug("Forms designer: Loading " + file.FileName + " in resource store"); + this.resourceStore.Load(file, stream); + if (mustReload) { + this.LoadAndDisplayDesigner(); + } + + } + } + + protected override void SaveInternal(OpenedFile file, System.IO.Stream stream) + { + LoggingService.Debug("Forms designer: Save " + file.FileName); + if (hasUnmergedChanges) { + this.MergeFormChanges(); + } + if (file == this.DesignerCodeFile) { + using(StreamWriter writer = new StreamWriter(stream, this.DesignerCodeFileEncoding)) { + writer.Write(this.DesignerCodeFileContent); + } + } else if (file == this.PrimaryFile) { + using(StreamWriter writer = new StreamWriter(stream, this.PrimaryFileEncoding)) { + writer.Write(this.PrimaryFileContent); + } + } else { + this.resourceStore.Save(file, stream); + } + } + + internal void AddResourceFile(OpenedFile file) + { + this.Files.Add(file); + } + void LoadDesigner() { LoggingService.Info("Form Designer: BEGIN INITIALIZE"); @@ -119,7 +250,7 @@ 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(viewContent.PrimaryFileName)); + serviceContainer.AddService(typeof(ITypeResolutionService), new TypeResolutionService(this.PrimaryFileName)); serviceContainer.AddService(typeof(DesignerOptionService), new SharpDevelopDesignerOptionService()); serviceContainer.AddService(typeof(ITypeDiscoveryService), new TypeDiscoveryService()); serviceContainer.AddService(typeof(MemberRelationshipService), new DefaultMemberRelationshipService()); @@ -131,14 +262,12 @@ namespace ICSharpCode.FormsDesigner designSurface = CreateDesignSurface(serviceContainer); serviceContainer.AddService(typeof(System.ComponentModel.Design.IMenuCommandService), new ICSharpCode.FormsDesigner.Services.MenuCommandService(p, designSurface)); - ICSharpCode.FormsDesigner.Services.EventBindingService eventBindingService = new ICSharpCode.FormsDesigner.Services.EventBindingService(designSurface); + ICSharpCode.FormsDesigner.Services.EventBindingService eventBindingService = new ICSharpCode.FormsDesigner.Services.EventBindingService(this, designSurface); serviceContainer.AddService(typeof(System.ComponentModel.Design.IEventBindingService), eventBindingService); DesignerLoader designerLoader = loaderProvider.CreateLoader(generator); designSurface.BeginLoad(designerLoader); - generator.Attach(this); - undoEngine = new FormsDesignerUndoEngine(Host); serviceContainer.AddService(typeof(UndoEngine), undoEngine); @@ -170,29 +299,10 @@ namespace ICSharpCode.FormsDesigner void MakeDirty(object sender, ComponentChangedEventArgs args) { hasUnmergedChanges = true; - this.PrimaryFile.MakeDirty(); + this.DesignerCodeFile.MakeDirty(); this.resourceStore.MarkResourceFilesAsDirty(); } - public override void Load(OpenedFile file, System.IO.Stream stream) - { - if (file == PrimaryFile) { - base.Load(file, stream); - } else { - this.resourceStore.Load(file, stream); - } - } - - public override void Save(OpenedFile file, System.IO.Stream stream) - { - if (file == PrimaryFile) { - base.Save(file, stream); - } else { - if (hasUnmergedChanges) SaveToPrimary(); - this.resourceStore.Save(file, stream); - } - } - bool shouldUpdateSelectableObjects = false; void TransactionClose(object sender, DesignerTransactionCloseEventArgs e) @@ -212,14 +322,14 @@ namespace ICSharpCode.FormsDesigner void UnloadDesigner() { + LoggingService.Debug("FormsDesigner unloading, setting ActiveDesignSurface to null"); designSurfaceManager.ActiveDesignSurface = null; PropertyPad.PropertyValueChanged -= PropertyValueChanged; - if (generator != null) { - generator.Detach(); - } - bool savedIsDirty = this.PrimaryFile.IsDirty; + bool savedIsDirty = (this.DesignerCodeFile == null) ? false : this.DesignerCodeFile.IsDirty; p.Controls.Clear(); - this.PrimaryFile.IsDirty = savedIsDirty; + if (this.DesignerCodeFile != null) { + this.DesignerCodeFile.IsDirty = savedIsDirty; + } // We cannot dispose the design surface now because of SD2-451: // When the switch to the source view was triggered by a double-click on an event @@ -259,60 +369,60 @@ namespace ICSharpCode.FormsDesigner } } - public void Reload() + void LoadAndDisplayDesigner() { try { - failedDesignerInitialize = false; + + this.loadingDesigner = true; + LoadDesigner(); - bool savedIsDirty = this.PrimaryFile.IsDirty; + bool savedIsDirty = this.DesignerCodeFile.IsDirty; if (designSurface != null && p.Controls.Count == 0) { Control designer = designSurface.View as Control; designer.Dock = DockStyle.Fill; p.Controls.Add(designer); + LoggingService.Debug("FormsDesigner loaded, setting ActiveDesignSurface to " + this.designSurface.ToString()); designSurfaceManager.ActiveDesignSurface = this.designSurface; } - this.PrimaryFile.IsDirty = savedIsDirty; + this.DesignerCodeFile.IsDirty = savedIsDirty; + } catch (Exception e) { - failedDesignerInitialize = true; - TextBox errorText = new TextBox(); - errorText.ScrollBars = ScrollBars.Both; - errorText.Multiline = true; + + string mainErrorMessage; if (e.InnerException is FormsDesignerLoadException) { - errorText.Text = e.InnerException.Message; + mainErrorMessage = e.InnerException.Message; } else if (e is FormsDesignerLoadException) { - errorText.Text = e.Message; + mainErrorMessage = e.Message; } else if (designSurface != null && !designSurface.IsLoaded && designSurface.LoadErrors != null) { - errorText.Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.ErrorLoadingDesigner}\r\n\r\n"); + mainErrorMessage = StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.ErrorLoadingDesigner}\r\n\r\n"); foreach(Exception le in designSurface.LoadErrors) { - errorText.Text += le.ToString(); - errorText.Text += "\r\n"; + mainErrorMessage += le.ToString(); + mainErrorMessage += "\r\n"; } } else { - errorText.Text = e.ToString(); + mainErrorMessage = e.ToString(); } - errorText.Dock = DockStyle.Fill; - p.Controls.Add(errorText); - Control title = new Label(); - title.Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.LoadErrorCheckSourceCodeForErrors}"); - title.Dock = DockStyle.Top; - p.Controls.Add(title); + throw new FormsDesignerLoadException(StringParser.Parse("${res:ICSharpCode.SharpDevelop.FormDesigner.LoadErrorCheckSourceCodeForErrors}") + Environment.NewLine + mainErrorMessage + Environment.NewLine, e); + + } finally { + this.loadingDesigner = false; } } public virtual void MergeFormChanges() { - if (this.failedDesignerInitialize) { + if (this.HasLoadError) { return; } - bool isDirty = this.PrimaryFile.IsDirty; + bool isDirty = this.DesignerCodeFile.IsDirty; LoggingService.Info("Merging form changes..."); designSurface.Flush(); this.resourceStore.CommitAllResourceChanges(); LoggingService.Info("Finished merging form changes"); hasUnmergedChanges = false; - this.PrimaryFile.IsDirty = isDirty; + this.DesignerCodeFile.IsDirty = isDirty; } public void ShowSourceCode() @@ -323,7 +433,10 @@ namespace ICSharpCode.FormsDesigner public void ShowSourceCode(int lineNumber) { ShowSourceCode(); - textAreaControlProvider.TextEditorControl.ActiveTextAreaControl.JumpTo(lineNumber - 1); + ITextEditorControlProvider tecp = this.primaryViewContent as ITextEditorControlProvider; + if (tecp != null) { + tecp.TextEditorControl.ActiveTextAreaControl.JumpTo(lineNumber - 1); + } } public void ShowSourceCode(IComponent component, EventDescriptor edesc, string eventMethodName) @@ -332,7 +445,7 @@ namespace ICSharpCode.FormsDesigner string file; bool eventCreated = generator.InsertComponentEvent(component, edesc, eventMethodName, "", out file, out position); if (eventCreated) { - if (FileUtility.IsEqualFileName(file, this.TextEditorControl.FileName)) { + if (FileUtility.IsEqualFileName(file, this.primaryViewContent.PrimaryFileName)) { ShowSourceCode(position); } else { FileService.JumpToFilePosition(file, position - 1, 0); @@ -360,6 +473,10 @@ namespace ICSharpCode.FormsDesigner { disposing = true; try { + // base.Dispose() is called first because it may trigger a call + // to SaveInternal which requires the designer to be loaded. + base.Dispose(); + } finally { this.UnloadDesigner(); @@ -368,27 +485,18 @@ namespace ICSharpCode.FormsDesigner this.IsActiveViewContentChanged -= this.IsActiveViewContentChangedHandler; } + if (this.generator != null) { + this.generator.Detach(); + } + this.resourceStore.Dispose(); p.Dispose(); p = null; - } finally { - base.Dispose(); } } - protected override void LoadFromPrimary() - { - UnloadDesigner(); - Reload(); - } - - protected override void SaveToPrimary() - { - MergeFormChanges(); - } - void SelectionChangedHandler(object sender, EventArgs args) { UpdatePropertyPadSelection((ISelectionService)sender); @@ -569,18 +677,31 @@ namespace ICSharpCode.FormsDesigner if (e.ChangedItem.PropertyDescriptor.Name == "Language") { if (!e.OldValue.Equals(e.ChangedItem.Value)) { LoggingService.Debug("Reloading designer due to language change."); - propertyContainer.Clear(); - if (!failedDesignerInitialize) { - MergeFormChanges(); - } - UnloadDesigner(); - Reload(); - UpdatePropertyPad(); + this.MergeAndUnloadDesigner(); + this.ReloadDesignerFromMemory(); } } } } + protected void MergeAndUnloadDesigner() + { + propertyContainer.Clear(); + if (!this.HasLoadError) { + MergeFormChanges(); + } + UnloadDesigner(); + } + + protected void ReloadDesignerFromMemory() + { + using(MemoryStream ms = new MemoryStream(this.DesignerCodeFileEncoding.GetBytes(this.DesignerCodeFileContent), false)) { + this.Load(this.DesignerCodeFile, ms); + } + + UpdatePropertyPad(); + } + public virtual Control ToolsControl { get { return ToolboxProvider.FormsDesignerSideBar; } } diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/SecondaryDisplayBinding.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/SecondaryDisplayBinding.cs index 79f795e051..49382c7bce 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/SecondaryDisplayBinding.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/SecondaryDisplayBinding.cs @@ -124,15 +124,15 @@ namespace ICSharpCode.FormsDesigner switch (fileExtension) { case ".cs": - loader = new NRefactoryDesignerLoaderProvider(SupportedLanguage.CSharp, ((ITextEditorControlProvider)viewContent).TextEditorControl); + loader = new NRefactoryDesignerLoaderProvider(SupportedLanguage.CSharp); generator = new CSharpDesignerGenerator(); break; case ".vb": - loader = new NRefactoryDesignerLoaderProvider(SupportedLanguage.VBNet, ((ITextEditorControlProvider)viewContent).TextEditorControl); + loader = new NRefactoryDesignerLoaderProvider(SupportedLanguage.VBNet); generator = new VBNetDesignerGenerator(); break; case ".xfrm": - loader = new XmlDesignerLoaderProvider(((ITextEditorControlProvider)viewContent).TextEditorControl); + loader = new XmlDesignerLoaderProvider(); generator = new XmlDesignerGenerator(); break; default: diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs index 568fcf7b4f..3c11ebe1ab 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs @@ -6,18 +6,8 @@ // using System; -using System.Collections.Generic; -using System.ComponentModel.Design; -using System.ComponentModel.Design.Serialization; using System.Globalization; -using System.IO; -using System.Resources; -using System.Text; - using ICSharpCode.Core; -using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Gui; -using ICSharpCode.SharpDevelop.Project; namespace ICSharpCode.FormsDesigner.Services { diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/EventBindingService.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/EventBindingService.cs index 08e46669bf..0ac8cda700 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/EventBindingService.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/EventBindingService.cs @@ -15,9 +15,13 @@ namespace ICSharpCode.FormsDesigner.Services { public class EventBindingService : System.ComponentModel.Design.EventBindingService { + readonly FormsDesignerViewContent formDesigner; - public EventBindingService(IServiceProvider provider) : base(provider) + public EventBindingService(FormsDesignerViewContent formDesigner, IServiceProvider provider) : base(provider) { + if (formDesigner == null) + throw new ArgumentNullException("formDesigner"); + this.formDesigner = formDesigner; } protected override string CreateUniqueMethodName(IComponent component, EventDescriptor e) @@ -28,26 +32,11 @@ namespace ICSharpCode.FormsDesigner.Services // sohuld look around in form class for compatiable methodes protected override ICollection GetCompatibleMethods(EventDescriptor e) { - IWorkbenchWindow window = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow; - if (window != null) { - FormsDesignerViewContent formDesigner = window.ActiveViewContent as FormsDesignerViewContent; - - if (formDesigner != null) { - return formDesigner.GetCompatibleMethods(e); - } - } - return new string[]{}; + return this.formDesigner.GetCompatibleMethods(e); } protected override bool ShowCode() { - IWorkbenchWindow window = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow; - if (window == null) { - return false; - } - - FormsDesignerViewContent formDesigner = window.ActiveViewContent as FormsDesignerViewContent; - if (formDesigner != null) { formDesigner.ShowSourceCode(); return true; @@ -57,13 +46,6 @@ namespace ICSharpCode.FormsDesigner.Services protected override bool ShowCode(int lineNumber) { - IWorkbenchWindow window = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow; - if (window == null) { - return false; - } - - FormsDesignerViewContent formDesigner = window.ActiveViewContent as FormsDesignerViewContent; - if (formDesigner != null) { formDesigner.ShowSourceCode(lineNumber); return true; @@ -73,12 +55,6 @@ namespace ICSharpCode.FormsDesigner.Services protected override bool ShowCode(IComponent component, EventDescriptor edesc, string methodName) { - IWorkbenchWindow window = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow; - if (window == null || edesc == null || edesc.Name == null || edesc.Name.Length == 0) { - return false; - } - FormsDesignerViewContent formDesigner = window.ActiveViewContent as FormsDesignerViewContent; - if (formDesigner != null) { formDesigner.ShowSourceCode(component, edesc, methodName); return true; diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ResourceStore.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ResourceStore.cs index 31515eafe1..e38a47e3ae 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ResourceStore.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/ResourceStore.cs @@ -67,7 +67,7 @@ namespace ICSharpCode.FormsDesigner.Services } resourceByFile[storage.OpenedFile] = storage; // adding the opened file to the view content will load the file content into ResourceStorage.buffer - viewContent.Files.Add(storage.OpenedFile); + viewContent.AddResourceFile(storage.OpenedFile); } public void Dispose() diff --git a/src/Main/Base/Project/Src/Internal/ConditionEvaluators/ActiveWindowStateEvaluator.cs b/src/Main/Base/Project/Src/Internal/ConditionEvaluators/ActiveWindowStateEvaluator.cs index a11473b7fb..b752267f0b 100644 --- a/src/Main/Base/Project/Src/Internal/ConditionEvaluators/ActiveWindowStateEvaluator.cs +++ b/src/Main/Base/Project/Src/Internal/ConditionEvaluators/ActiveWindowStateEvaluator.cs @@ -6,6 +6,7 @@ // using System; +using System.Linq; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Gui; @@ -38,7 +39,7 @@ namespace ICSharpCode.SharpDevelop bool isWindowStateOk = false; if (windowState != WindowState.None) { if ((windowState & WindowState.Dirty) > 0) { - isWindowStateOk |= WorkbenchSingleton.Workbench.ActiveViewContent.IsDirty; + isWindowStateOk |= WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ViewContents.Any(vc => vc.IsDirty); } if ((windowState & WindowState.Untitled) > 0) { isWindowStateOk |= IsUntitled(WorkbenchSingleton.Workbench.ActiveViewContent); @@ -52,7 +53,7 @@ namespace ICSharpCode.SharpDevelop if (nowindowState != WindowState.None) { if ((nowindowState & WindowState.Dirty) > 0) { - isWindowStateOk &= !WorkbenchSingleton.Workbench.ActiveViewContent.IsDirty; + isWindowStateOk &= !WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ViewContents.Any(vc => vc.IsDirty); } if ((nowindowState & WindowState.Untitled) > 0) {