From d5c1f989cafee93b930b7b618ef1a5aed25ce0a8 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sat, 6 Jun 2009 10:08:14 +0000 Subject: [PATCH 01/18] Fixed build. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4244 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj index 369d9f51d1..cf641b2b3d 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj @@ -176,12 +176,15 @@ - + + + + From 94a674800b6e712aa237f374e333afc4497e529c Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sat, 6 Jun 2009 10:53:31 +0000 Subject: [PATCH 02/18] Schema namespace completion window now shown in XML editor. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4245 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/XmlCodeCompletionBinding.cs | 2 +- .../Project/Src/XmlCompletionDataProvider.cs | 4 +- .../Project/Src/XmlCompletionItem.cs | 2 +- .../DisplayBindings/XmlEditor/XmlEditor.sln | 66 +++++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 src/AddIns/DisplayBindings/XmlEditor/XmlEditor.sln diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCodeCompletionBinding.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCodeCompletionBinding.cs index b7953026d1..1f5f72c962 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCodeCompletionBinding.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCodeCompletionBinding.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.XmlEditor public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch) { - string text = string.Concat(editor.Document.GetText(0, editor.Caret.Offset), ch); + string text = editor.Document.GetText(0, editor.Caret.Offset); string extension = Path.GetExtension(editor.FileName); string defaultNamespacePrefix = XmlSchemaManager.GetNamespacePrefix(extension); XmlSchemaCompletionData defaultSchemaCompletionData = XmlSchemaManager.GetSchemaCompletionData(extension); diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionDataProvider.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionDataProvider.cs index 154bc6d1b0..63ee1b49a7 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionDataProvider.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionDataProvider.cs @@ -141,7 +141,7 @@ namespace ICSharpCode.XmlEditor public DefaultCompletionItemList GetAttributeCompletionData(XmlElementPath path) { - var list = new XmlCompletionItemList(); + XmlCompletionItemList list = new XmlCompletionItemList(); XmlSchemaCompletionData schema = FindSchema(path); if (schema != null) { @@ -155,7 +155,7 @@ namespace ICSharpCode.XmlEditor public DefaultCompletionItemList GetAttributeValueCompletionData(XmlElementPath path, string name) { - var list = new XmlCompletionItemList(); + XmlCompletionItemList list = new XmlCompletionItemList(); XmlSchemaCompletionData schema = FindSchema(path); if (schema != null) { diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionItem.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionItem.cs index 936e04ccca..5f9d68e5a0 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionItem.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionItem.cs @@ -69,7 +69,7 @@ namespace ICSharpCode.XmlEditor switch (dataType) { case XmlCompletionDataType.NamespaceUri: context.Editor.Document.Insert(context.StartOffset, "\""); - context.Editor.Document.Insert(context.EndOffset, "\""); + context.Editor.Document.Insert(context.EndOffset + 1, "\""); break; case XmlCompletionDataType.XmlAttribute: context.Editor.Document.Insert(context.EndOffset, "=\"\""); diff --git a/src/AddIns/DisplayBindings/XmlEditor/XmlEditor.sln b/src/AddIns/DisplayBindings/XmlEditor/XmlEditor.sln new file mode 100644 index 0000000000..de44b43702 --- /dev/null +++ b/src/AddIns/DisplayBindings/XmlEditor/XmlEditor.sln @@ -0,0 +1,66 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +# SharpDevelop 3.0.0.3800 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlEditor", "Project\XmlEditor.csproj", "{DCA2703D-250A-463E-A68A-07ED105AE6BD}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XmlEditor.Tests", "Test\XmlEditor.Tests.csproj", "{FC0FE702-A87D-4D70-A9B6-1ECCD611125F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit", "..\..\..\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj", "{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}" +EndProject +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.Presentation", "..\..\..\Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj", "{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core.WinForms", "..\..\..\Main\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj", "{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}" +EndProject +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.TextEditor", "..\..\..\Libraries\ICSharpCode.TextEditor\Project\ICSharpCode.TextEditor.csproj", "{2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DCA2703D-250A-463E-A68A-07ED105AE6BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCA2703D-250A-463E-A68A-07ED105AE6BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCA2703D-250A-463E-A68A-07ED105AE6BD}.Release|Any CPU.Build.0 = Release|Any CPU + {DCA2703D-250A-463E-A68A-07ED105AE6BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC0FE702-A87D-4D70-A9B6-1ECCD611125F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC0FE702-A87D-4D70-A9B6-1ECCD611125F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC0FE702-A87D-4D70-A9B6-1ECCD611125F}.Release|Any CPU.Build.0 = Release|Any CPU + {FC0FE702-A87D-4D70-A9B6-1ECCD611125F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.Build.0 = Release|Any CPU + {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.Build.0 = Release|Any CPU + {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|Any CPU.Build.0 = Release|Any CPU + {2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Release|Any CPU.Build.0 = Release|Any CPU + {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|Any CPU.Build.0 = Debug|Any CPU + {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|Any CPU.Build.0 = Release|Any CPU + {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|Any CPU.ActiveCfg = Release|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|Any CPU.Build.0 = Release|Any CPU + {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Any CPU.Build.0 = Release|Any CPU + {2D18BE89-D210-49EB-A9DD-2246FBB3DF6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + EndGlobalSection +EndGlobal From 5786346f6c34c6f6ea2beb47fe894e7f240d02f3 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sat, 6 Jun 2009 11:07:47 +0000 Subject: [PATCH 03/18] When autocompleting an xml element end tag the cursor is now left inside the element after completion and not put at the end of the inserted end tag. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4246 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../XmlEditor/Project/Src/XmlFormattingStrategy.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlFormattingStrategy.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlFormattingStrategy.cs index 190a27b2c5..ff16687c59 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlFormattingStrategy.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlFormattingStrategy.cs @@ -52,7 +52,9 @@ namespace ICSharpCode.XmlEditor } string tagString = tag.ToString(); if (tagString.Length > 0 && !tagString.StartsWith("!", StringComparison.Ordinal) && !tagString.StartsWith("?", StringComparison.Ordinal)) { + int caretOffset = editor.Caret.Offset; editor.Document.Insert(editor.Caret.Offset, ""); + editor.Caret.Offset = caretOffset; } } } From 85e78d67629290063c4831ec43ffc6b4ee99a7fa Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sat, 6 Jun 2009 11:32:00 +0000 Subject: [PATCH 04/18] Fixed bugs in XmlParser when getting the attribute value and attribute name when the attribute value contains an equals sign. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4247 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../XmlEditor/Project/Src/XmlParser.cs | 21 ++++++++++++++----- .../Parser/AttributeValueUnderCursorTests.cs | 2 ++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs index 407ae7feef..19d70bd547 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlParser.cs @@ -243,12 +243,15 @@ namespace ICSharpCode.XmlEditor } // Find equals sign. + bool foundQuoteChar = false; for (int i = index; i > elementStartIndex; --i) { char ch = xml[i]; - if (ch == '=') { + if (ch == '=' && foundQuoteChar) { index = i; ignoreEqualsSign = true; break; + } else if (IsQuoteChar(ch)) { + foundQuoteChar = true; } } } else { @@ -364,11 +367,14 @@ namespace ICSharpCode.XmlEditor // Find equals sign. int equalsSignIndex = -1; + bool foundQuoteChar = false; for (int i = index; i > elementStartIndex; --i) { char ch = xml[i]; - if (ch == '=') { + if (ch == '=' && foundQuoteChar) { equalsSignIndex = i; break; + } else if (IsQuoteChar(ch)) { + foundQuoteChar = true; } } @@ -378,12 +384,12 @@ namespace ICSharpCode.XmlEditor // Find attribute value. char quoteChar = ' '; - bool foundQuoteChar = false; + foundQuoteChar = false; StringBuilder attributeValue = new StringBuilder(); for (int i = equalsSignIndex; i < xml.Length; ++i) { char ch = xml[i]; if (!foundQuoteChar) { - if (ch == '\"' || ch == '\'') { + if (IsQuoteChar(ch)) { quoteChar = ch; foundQuoteChar = true; } @@ -391,7 +397,7 @@ namespace ICSharpCode.XmlEditor if (ch == quoteChar) { // End of attribute value. return attributeValue.ToString(); - } else if (IsAttributeValueChar(ch) || (ch == '\"' || ch == '\'')) { + } else if (IsAttributeValueChar(ch) || IsQuoteChar(ch)) { attributeValue.Append(ch); } else { // Invalid character found. @@ -783,5 +789,10 @@ namespace ICSharpCode.XmlEditor } return new XmlElementPath(); } + + static bool IsQuoteChar(char ch) + { + return (ch == '\"') || (ch == '\''); + } } } \ No newline at end of file diff --git a/src/AddIns/DisplayBindings/XmlEditor/Test/Parser/AttributeValueUnderCursorTests.cs b/src/AddIns/DisplayBindings/XmlEditor/Test/Parser/AttributeValueUnderCursorTests.cs index bbbddb9ac9..828618e238 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Test/Parser/AttributeValueUnderCursorTests.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Test/Parser/AttributeValueUnderCursorTests.cs @@ -85,6 +85,8 @@ namespace XmlEditor.Tests.Parser string xaml = ""; int offset = " Date: Sat, 6 Jun 2009 13:15:00 +0000 Subject: [PATCH 05/18] Added ICompletionListWindow interface to allow AddIns to control the completion window. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4248 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../AvalonEdit.AddIn/Src/CodeEditor.cs | 24 ++++++- .../AvalonEdit.AddIn/Src/CodeEditorAdapter.cs | 18 +++--- .../Src/SharpDevelopCompletionWindow.cs | 47 +++++++++++++- .../XmlEditor/Project/Src/XmlView.cs | 1 + .../CodeCompletion/CompletionList.cs | 6 +- .../CodeCompletion/CompletionWindow.cs | 30 +++++++-- .../CodeCompletion/CompletionWindowBase.cs | 8 +-- .../CodeCompletion/InsightWindow.cs | 5 +- .../Project/ICSharpCode.SharpDevelop.csproj | 2 + .../AvalonEdit/AvalonEditTextEditorAdapter.cs | 26 +++++--- .../CodeCompletion/ICompletionListWindow.cs | 24 +++++++ .../CodeCompletion/ICompletionWindow.cs | 62 +++++++++++++++++++ .../Editor/CodeCompletion/IInsightWindow.cs | 30 +-------- .../Base/Project/Src/Editor/ITextEditor.cs | 7 ++- .../Src/TextEditor/Gui/TextEditorAdapter.cs | 9 ++- 15 files changed, 230 insertions(+), 69 deletions(-) create mode 100644 src/Main/Base/Project/Src/Editor/CodeCompletion/ICompletionListWindow.cs create mode 100644 src/Main/Base/Project/Src/Editor/CodeCompletion/ICompletionWindow.cs diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs index c053007067..093a698d4d 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs @@ -401,7 +401,7 @@ namespace ICSharpCode.AvalonEdit.AddIn } } - CompletionWindow completionWindow; + SharpDevelopCompletionWindow completionWindow; SharpDevelopInsightWindow insightWindow; void CloseExistingCompletionWindows() @@ -414,26 +414,44 @@ namespace ICSharpCode.AvalonEdit.AddIn } } + public SharpDevelopCompletionWindow ActiveCompletionWindow { + get { return completionWindow; } + } + public SharpDevelopInsightWindow ActiveInsightWindow { get { return insightWindow; } } - internal void NotifyCompletionWindowOpened(CompletionWindow window) + internal void ShowCompletionWindow(SharpDevelopCompletionWindow window) { CloseExistingCompletionWindows(); completionWindow = window; window.Closed += delegate { completionWindow = null; }; + Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action( + delegate { + if (completionWindow == window) { + window.Show(); + } + } + )); } - internal void NotifyInsightWindowOpened(SharpDevelopInsightWindow window) + internal void ShowInsightWindow(SharpDevelopInsightWindow window) { CloseExistingCompletionWindows(); insightWindow = window; window.Closed += delegate { insightWindow = null; }; + Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action( + delegate { + if (insightWindow == window) { + window.Show(); + } + } + )); } IFormattingStrategy formattingStrategy; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs index 35e2c39c96..4ebe19cf00 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorAdapter.cs @@ -37,13 +37,17 @@ namespace ICSharpCode.AvalonEdit.AddIn get { return codeEditor.FormattingStrategy; } } - public override void ShowCompletionWindow(ICompletionItemList data) + public override ICompletionListWindow ActiveCompletionWindow { + get { return codeEditor.ActiveCompletionWindow; } + } + + public override ICompletionListWindow ShowCompletionWindow(ICompletionItemList data) { if (data == null || !data.Items.Any()) - return; - CompletionWindow window = new SharpDevelopCompletionWindow(this, this.TextEditor.TextArea, data); - codeEditor.NotifyCompletionWindowOpened(window); - window.Show(); + return null; + SharpDevelopCompletionWindow window = new SharpDevelopCompletionWindow(this, this.TextEditor.TextArea, data); + codeEditor.ShowCompletionWindow(window); + return window; } public override IInsightWindow ShowInsightWindow(IEnumerable items) @@ -58,9 +62,7 @@ namespace ICSharpCode.AvalonEdit.AddIn // don't open insight window when there are no items return null; } - codeEditor.NotifyInsightWindowOpened(insightWindow); - insightWindow.Show(); - + codeEditor.ShowInsightWindow(insightWindow); return insightWindow; } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopCompletionWindow.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopCompletionWindow.cs index bb482b4791..110ce2fabb 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopCompletionWindow.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopCompletionWindow.cs @@ -5,23 +5,60 @@ // $Revision$ // -using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using System; +using System.Linq; +using System.Windows; +using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; + using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.CodeCompletion; namespace ICSharpCode.AvalonEdit.AddIn { /// /// The code completion window. /// - public class SharpDevelopCompletionWindow : CompletionWindow + public class SharpDevelopCompletionWindow : CompletionWindow, ICompletionListWindow { + public ICompletionItem SelectedItem { + get { + return ((CodeCompletionDataAdapter)this.CompletionList.SelectedItem).Item; + } + set { + var itemAdapters = this.CompletionList.CompletionData.Cast(); + this.CompletionList.SelectedItem = itemAdapters.FirstOrDefault(a => a.Item == value); + } + } + + double ICompletionWindow.Width { + get { return this.Width; } + set { + // Disable virtualization if we use automatic width - this prevents the window from resizing + // when the user scrolls. + VirtualizingStackPanel.SetIsVirtualizing(this.CompletionList.ListBox, !double.IsNaN(value)); + this.Width = value; + if (double.IsNaN(value)) { + // enable size-to-width: + if (this.SizeToContent == SizeToContent.Manual) + this.SizeToContent = SizeToContent.Width; + else if (this.SizeToContent == SizeToContent.Height) + this.SizeToContent = SizeToContent.WidthAndHeight; + } else { + // disable size-to-width: + if (this.SizeToContent == SizeToContent.Width) + this.SizeToContent = SizeToContent.Manual; + else if (this.SizeToContent == SizeToContent.WidthAndHeight) + this.SizeToContent = SizeToContent.Height; + } + } + } + readonly ICompletionItemList itemList; public ICompletionItemList ItemList { @@ -92,6 +129,10 @@ namespace ICSharpCode.AvalonEdit.AddIn this.item = item; } + public ICompletionItem Item { + get { return item; } + } + public string Text { get { return item.Text; } } @@ -107,7 +148,7 @@ namespace ICSharpCode.AvalonEdit.AddIn } public ImageSource Image { - get { + get { IImage image = item.Image; return image != null ? image.ImageSource : null; } diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs index dc05bcac1f..40d619e42f 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs @@ -513,6 +513,7 @@ namespace ICSharpCode.XmlEditor try { XmlTextReader reader = new XmlTextReader(new StringReader(xml)); reader.WhitespaceHandling = WhitespaceHandling.None; + reader.XmlResolver = null; StringWriter indentedXmlWriter = new StringWriter(); XmlTextWriter writer = CreateXmlTextWriter(indentedXmlWriter, editor); diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionList.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionList.cs index cf8296c429..d1431b60a6 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionList.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionList.cs @@ -59,7 +59,11 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion /// Gets the list box. /// public CompletionListBox ListBox { - get { return listBox; } + get { + if (listBox == null) + ApplyTemplate(); + return listBox; + } } /// diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindow.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindow.cs index a8c5adba17..3de46cc818 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindow.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindow.cs @@ -32,6 +32,7 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion public CompletionWindow(TextArea textArea) : base(textArea) { // keep height automatic + this.CloseAutomatically = true; this.SizeToContent = SizeToContent.Height; this.Width = 175; this.Content = completionList; @@ -45,6 +46,7 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion completionList.InsertionRequested += completionList_InsertionRequested; completionList.SelectionChanged += completionList_SelectionChanged; + AttachEvents(); } #region ToolTip handling @@ -85,17 +87,19 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion { // prevent CompletionWindow from growing too large if (this.ActualHeight > 300) { - this.SizeToContent = SizeToContent.Manual; + if (this.SizeToContent == SizeToContent.Height) + this.SizeToContent = SizeToContent.Manual; + else if (this.SizeToContent == SizeToContent.WidthAndHeight) + this.SizeToContent = SizeToContent.Width; this.Height = 300; + } base.OnSourceInitialized(e); } - /// - protected override void AttachEvents() + void AttachEvents() { - base.AttachEvents(); this.TextArea.Caret.PositionChanged += CaretPositionChanged; this.TextArea.MouseWheel += textArea_MouseWheel; this.TextArea.PreviewTextInput += textArea_PreviewTextInput; @@ -185,10 +189,22 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion return completionList.ScrollViewer ?? completionList.ListBox ?? (UIElement)completionList; } + /// + /// Gets/Sets whether the completion window should close automatically. + /// The default value is true. + /// + public bool CloseAutomatically { get; set; } + + /// + protected override bool CloseOnFocusLost { + get { return this.CloseAutomatically; } + } + /// /// When this flag is set, code completion closes if the caret moves to the /// beginning of the allowed range. This is useful in Ctrl+Space and "complete when typing", /// but not in dot-completion. + /// Has no effect if CloseAutomatically is false. /// public bool CloseWhenCaretAtBeginning { get; set; } @@ -196,12 +212,14 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion { int offset = this.TextArea.Caret.Offset; if (offset == this.StartOffset) { - if (CloseWhenCaretAtBeginning) + if (CloseAutomatically && CloseWhenCaretAtBeginning) Close(); return; } if (offset < this.StartOffset || offset > this.EndOffset) { - Close(); + if (CloseAutomatically) { + Close(); + } } else { TextDocument document = this.TextArea.Document; if (document != null) { diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindowBase.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindowBase.cs index 8e127af985..126144807f 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindowBase.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/CompletionWindowBase.cs @@ -53,13 +53,12 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion this.AddHandler(MouseUpEvent, new MouseButtonEventHandler(OnMouseUp), true); startOffset = endOffset = this.TextArea.Caret.Offset; + + AttachEvents(); } #region Event Handlers - /// - /// Attaches events to the text area. - /// - protected virtual void AttachEvents() + void AttachEvents() { document = this.TextArea.Document; if (document != null) { @@ -203,7 +202,6 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); - AttachEvents(); if (document != null && this.StartOffset != this.TextArea.Caret.Offset) { SetPosition(new TextViewPosition(document.GetLocation(this.StartOffset))); diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/InsightWindow.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/InsightWindow.cs index 7693ded067..7306abff71 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/InsightWindow.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/InsightWindow.cs @@ -31,6 +31,7 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion public InsightWindow(TextArea textArea) : base(textArea) { this.CloseAutomatically = true; + AttachEvents(); } /// @@ -44,10 +45,8 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion get { return this.CloseAutomatically; } } - /// - protected override void AttachEvents() + void AttachEvents() { - base.AttachEvents(); this.TextArea.Caret.PositionChanged += CaretPositionChanged; } diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 6fa9a04c4e..c19d10a179 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -78,9 +78,11 @@ + + diff --git a/src/Main/Base/Project/Src/Editor/AvalonEdit/AvalonEditTextEditorAdapter.cs b/src/Main/Base/Project/Src/Editor/AvalonEdit/AvalonEditTextEditorAdapter.cs index a5667aa1a0..cd3d8fab5a 100644 --- a/src/Main/Base/Project/Src/Editor/AvalonEdit/AvalonEditTextEditorAdapter.cs +++ b/src/Main/Base/Project/Src/Editor/AvalonEdit/AvalonEditTextEditorAdapter.cs @@ -70,7 +70,7 @@ namespace ICSharpCode.SharpDevelop.Editor public ITextEditorCaret Caret { get; private set; } public ITextEditorOptions Options { get; private set; } - public virtual IFormattingStrategy FormattingStrategy { + public virtual IFormattingStrategy FormattingStrategy { get { return DefaultFormattingStrategy.DefaultInstance; } } @@ -143,14 +143,6 @@ namespace ICSharpCode.SharpDevelop.Editor get { return null; } } - void ITextEditor.ShowCompletionWindow(ICSharpCode.TextEditor.Gui.CompletionWindow.ICompletionDataProvider provider, char ch) - { - } - - public virtual void ShowCompletionWindow(ICompletionItemList data) - { - } - public object GetService(Type serviceType) { return textEditor.TextArea.GetService(serviceType); @@ -210,5 +202,21 @@ namespace ICSharpCode.SharpDevelop.Editor { return null; } + + + void ITextEditor.ShowCompletionWindow(ICSharpCode.TextEditor.Gui.CompletionWindow.ICompletionDataProvider provider, char ch) + { + } + + public virtual ICompletionListWindow ActiveCompletionWindow { + get { + return null; + } + } + + public virtual ICompletionListWindow ShowCompletionWindow(ICompletionItemList data) + { + return null; + } } } diff --git a/src/Main/Base/Project/Src/Editor/CodeCompletion/ICompletionListWindow.cs b/src/Main/Base/Project/Src/Editor/CodeCompletion/ICompletionListWindow.cs new file mode 100644 index 0000000000..1cd6f993d8 --- /dev/null +++ b/src/Main/Base/Project/Src/Editor/CodeCompletion/ICompletionListWindow.cs @@ -0,0 +1,24 @@ +/* + * Created by SharpDevelop. + * User: Daniel + * Date: 06.06.2009 + * Time: 13:08 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; + +namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion +{ + /// + /// Represents the completion window showing a ICompletionItemList. + /// + public interface ICompletionListWindow : ICompletionWindow + { + /// + /// Gets/Sets the currently selected item. + /// + ICompletionItem SelectedItem { get; set; } + } +} diff --git a/src/Main/Base/Project/Src/Editor/CodeCompletion/ICompletionWindow.cs b/src/Main/Base/Project/Src/Editor/CodeCompletion/ICompletionWindow.cs new file mode 100644 index 0000000000..b87cbe365f --- /dev/null +++ b/src/Main/Base/Project/Src/Editor/CodeCompletion/ICompletionWindow.cs @@ -0,0 +1,62 @@ +/* + * Created by SharpDevelop. + * User: Daniel + * Date: 06.06.2009 + * Time: 13:03 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; + +namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion +{ + /// + /// Base interface for IInsightWindow and ICompletionListWindow. + /// + public interface ICompletionWindow + { + /// + /// Closes the window. + /// + void Close(); + + /// + /// Occurs after the window was closed. + /// + event EventHandler Closed; + + /// + /// Gets/Sets the width of the window. + /// double.NaN is used to represent automatic width. + /// + /// For the completion list window default width is a fixed number - using automatic width + /// will reduce performance when a large number of items is shown. + /// + double Width { get; set; } + + /// + /// Gets/Sets the height of the window. + /// double.NaN is used to represent automatic height. + /// + double Height { get; set; } + + /// + /// Gets/Sets whether the window should close automatically. + /// The default value is true. + /// + bool CloseAutomatically { get; set; } + + /// + /// Gets/Sets the start of the text range in which the window stays open. + /// Has no effect if CloseAutomatically is false. + /// + int StartOffset { get; set; } + + /// + /// Gets/Sets the end of the text range in which the window stays open. + /// Has no effect if CloseAutomatically is false. + /// + int EndOffset { get; set; } + } +} diff --git a/src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindow.cs b/src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindow.cs index 2c7cfc4313..886142392c 100644 --- a/src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindow.cs +++ b/src/Main/Base/Project/Src/Editor/CodeCompletion/IInsightWindow.cs @@ -13,7 +13,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion /// /// Describes a set of insight items (e.g. multiple overloads of a method) to be displayed in the insight window. /// - public interface IInsightWindow + public interface IInsightWindow : ICompletionWindow { /// /// Gets the items to display. @@ -24,33 +24,5 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion /// Gets/Sets the item that is currently selected. /// IInsightItem SelectedItem { get; set; } - - /// - /// Gets/Sets whether the insight window should close automatically. - /// The default value is true. - /// - bool CloseAutomatically { get; set; } - - /// - /// Closes the insight window. - /// - void Close(); - - /// - /// Occurs after the insight window was closed. - /// - event EventHandler Closed; - - /// - /// Gets/Sets the start of the text range in which the insight window stays open. - /// Has no effect if CloseAutomatically is false. - /// - int StartOffset { get; set; } - - /// - /// Gets/Sets the end of the text range in which the insight window stays open. - /// Has no effect if CloseAutomatically is false. - /// - int EndOffset { get; set; } } } diff --git a/src/Main/Base/Project/Src/Editor/ITextEditor.cs b/src/Main/Base/Project/Src/Editor/ITextEditor.cs index a8b5f1e0cf..a55ed8e88f 100644 --- a/src/Main/Base/Project/Src/Editor/ITextEditor.cs +++ b/src/Main/Base/Project/Src/Editor/ITextEditor.cs @@ -71,7 +71,12 @@ namespace ICSharpCode.SharpDevelop.Editor string FileName { get; } - void ShowCompletionWindow(ICompletionItemList data); + ICompletionListWindow ShowCompletionWindow(ICompletionItemList data); + + /// + /// Gets the completion window that is currently open. + /// + ICompletionListWindow ActiveCompletionWindow { get; } /// /// Open a new insight window showing the specific insight items. diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/TextEditorAdapter.cs b/src/Main/Base/Project/Src/TextEditor/Gui/TextEditorAdapter.cs index 13bfcc83c6..bd06e31de8 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/TextEditorAdapter.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/TextEditorAdapter.cs @@ -151,11 +151,18 @@ namespace ICSharpCode.SharpDevelop } } - public void ShowCompletionWindow(ICompletionItemList items) + public ICompletionListWindow ActiveCompletionWindow { + get { + return null; + } + } + + public ICompletionListWindow ShowCompletionWindow(ICompletionItemList items) { if (sdtac != null) { sdtac.ShowCompletionWindow(new CompletionItemListAdapter(items), '.'); } + return null; } public string GetWordBeforeCaret() From f6bd5596bb81091dec8ed2f1467ab11ae7622a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Sat, 6 Jun 2009 15:28:20 +0000 Subject: [PATCH 06/18] MemoryReadWrite test updated for .NET 4.0 (but it is still ignored by default) git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4251 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/TestPrograms/MemoryReadWrite.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index 3d8435627a..0f62436995 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/MemoryReadWrite.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/MemoryReadWrite.cs @@ -75,8 +75,8 @@ namespace Debugger.Tests { MemoryReadWrite.exe (Has symbols) System.dll (No symbols) Break MemoryReadWrite.cs:18,4-18,40 - 0 A 33 79 6 0 0 0 5 0 0 0 48 0 65 0 6C 0 6C 0 6F 0 - 0 A 33 79 7 0 0 0 6 0 0 0 20 0 20 0 20 0 20 0 20 0 21 0 + 0 A 4D 3 6 0 0 0 5 0 0 0 48 0 65 0 6C 0 6C 0 6F 0 + 0 A 4D 3 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 From eb27110cbf291db554906824b463c8b9d2046c34 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 7 Jun 2009 17:11:55 +0000 Subject: [PATCH 07/18] XML schema namespaces now visible in completion window. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4264 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/XmlCodeCompletionBinding.cs | 64 +++++++------ .../Project/Src/XmlCompletionItem.cs | 15 +-- .../XmlEditor/Project/Src/XmlTreeView.cs | 2 +- .../XmlEditor/Project/Src/XmlView.cs | 95 ++++++------------- 4 files changed, 72 insertions(+), 104 deletions(-) diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCodeCompletionBinding.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCodeCompletionBinding.cs index 1f5f72c962..4b9e01317b 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCodeCompletionBinding.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCodeCompletionBinding.cs @@ -1,29 +1,28 @@ // // // -// +// // $Revision$ // using System; using System.IO; + +using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor.CodeCompletion; namespace ICSharpCode.XmlEditor { - /// - /// Description of XmlCodeCompletionBinding. - /// public class XmlCodeCompletionBinding : ICodeCompletionBinding { static XmlCodeCompletionBinding instance; public static XmlCodeCompletionBinding Instance { get { - if (instance == null) + if (instance == null) { instance = new XmlCodeCompletionBinding(); - + } return instance; } } @@ -33,45 +32,52 @@ namespace ICSharpCode.XmlEditor } public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch) - { + { string text = editor.Document.GetText(0, editor.Caret.Offset); - string extension = Path.GetExtension(editor.FileName); - string defaultNamespacePrefix = XmlSchemaManager.GetNamespacePrefix(extension); - XmlSchemaCompletionData defaultSchemaCompletionData = XmlSchemaManager.GetSchemaCompletionData(extension); - XmlCompletionDataProvider provider = new XmlCompletionDataProvider(XmlSchemaManager.SchemaCompletionDataItems, - defaultSchemaCompletionData, - defaultNamespacePrefix); - - editor.ShowCompletionWindow(provider.GenerateCompletionData(text, ch)); + XmlCompletionDataProvider provider = GetProvider(editor.FileName); + ICompletionItemList completionItems = provider.GenerateCompletionData(text, ch); + ICompletionListWindow completionWindow = editor.ShowCompletionWindow(completionItems); + if (completionWindow != null) { + XmlCompletionItem item = completionItems.SuggestedItem as XmlCompletionItem; + if (item.DataType == XmlCompletionDataType.NamespaceUri) { + completionWindow.Width = double.NaN; + } + } - if (ch == '<' || ch == ' ' || ch == '=') + if ((ch == '<') || (ch == ' ') || (ch == '=')) { return CodeCompletionKeyPressResult.Completed; - else - return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion; + } + return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion; } public bool CtrlSpace(ITextEditor editor) - { + { + // Attribute value completion. string text = editor.Document.Text; int offset = editor.Caret.Offset; - - string extension = Path.GetExtension(editor.FileName); - string defaultNamespacePrefix = XmlSchemaManager.GetNamespacePrefix(extension); - XmlSchemaCompletionData defaultSchemaCompletionData = XmlSchemaManager.GetSchemaCompletionData(extension); - XmlCompletionDataProvider provider = new XmlCompletionDataProvider(XmlSchemaManager.SchemaCompletionDataItems, - defaultSchemaCompletionData, - defaultNamespacePrefix); - - // Attribute value completion. if (XmlParser.IsInsideAttributeValue(text, offset)) { XmlElementPath path = XmlParser.GetActiveElementStartPath(text, offset); if (path.Elements.Count > 0) { + XmlCompletionDataProvider provider = GetProvider(editor.FileName); editor.ShowCompletionWindow(provider.GetAttributeValueCompletionData(path, XmlParser.GetAttributeNameAtIndex(text, offset))); return true; } } - return false; } + + public static XmlCompletionDataProvider GetProvider(string fileName) + { + string extension = Path.GetExtension(fileName); + if (PropertyService.DataDirectory != null) { + XmlSchemaCompletionDataCollection schemas = XmlSchemaManager.SchemaCompletionDataItems; + string defaultNamespacePrefix = XmlSchemaManager.GetNamespacePrefix(extension); + XmlSchemaCompletionData defaultSchemaCompletionData = XmlSchemaManager.GetSchemaCompletionData(extension); + return new XmlCompletionDataProvider(schemas, defaultSchemaCompletionData, defaultNamespacePrefix); + } + + // for unit tests + return new XmlCompletionDataProvider(new XmlSchemaCompletionDataCollection(), null, String.Empty); + } } } diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionItem.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionItem.cs index 5f9d68e5a0..2f370e9f92 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionItem.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlCompletionItem.cs @@ -28,10 +28,10 @@ namespace ICSharpCode.XmlEditor public class XmlCompletionItem : DefaultCompletionItem { XmlCompletionDataType dataType = XmlCompletionDataType.XmlElement; - string description = string.Empty; + string description = String.Empty; public XmlCompletionItem(string text) - : this(text, string.Empty, XmlCompletionDataType.XmlElement) + : this(text, String.Empty, XmlCompletionDataType.XmlElement) { } @@ -41,7 +41,7 @@ namespace ICSharpCode.XmlEditor } public XmlCompletionItem(string text, XmlCompletionDataType dataType) - : this(text, string.Empty, dataType) + : this(text, String.Empty, dataType) { } @@ -57,9 +57,11 @@ namespace ICSharpCode.XmlEditor /// the xs:annotation/xs:documentation element. /// public override string Description { - get { - return description; - } + get { return description; } + } + + public XmlCompletionDataType DataType { + get { return dataType; } } public override void Complete(CompletionContext context) @@ -83,6 +85,5 @@ namespace ICSharpCode.XmlEditor { return "[" + this.Text + "]"; } - } } diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeView.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeView.cs index 1f08c572b7..154aef7cdd 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeView.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeView.cs @@ -134,7 +134,7 @@ namespace ICSharpCode.XmlEditor protected override void LoadFromPrimary() { IFileDocumentProvider provider = this.PrimaryViewContent as IFileDocumentProvider; - treeViewContainer.LoadXml(provider.GetDocumentForFile(this.PrimaryFile).Text, XmlView.GetProvider(Path.GetExtension(this.PrimaryFileName))); + treeViewContainer.LoadXml(provider.GetDocumentForFile(this.PrimaryFile).Text, XmlCodeCompletionBinding.GetProvider(Path.GetExtension(this.PrimaryFileName))); XmlView view = XmlView.ForFile(this.PrimaryFile); if (view != null) { view.CheckIsWellFormed(); diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs index 40d619e42f..ef9153f3b2 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlView.cs @@ -1,7 +1,7 @@ // // // -// +// // $Revision$ // @@ -59,59 +59,38 @@ namespace ICSharpCode.XmlEditor public static XmlView ForViewContent(IViewContent view) { - if (view == null || view.PrimaryFile == null) + if ((view == null) || (view.PrimaryFile == null)) { return null; + } return ForFile(view.PrimaryFile); } static void FileClosedHandler(object sender, EventArgs e) { - if (sender is OpenedFile) + if (sender is OpenedFile) { mapping.Remove(sender as OpenedFile); + } } public string StylesheetFileName { get; set; } public XmlCompletionDataProvider GetProvider() { - return GetProvider(Path.GetExtension(File.FileName)); + return XmlCodeCompletionBinding.GetProvider(Path.GetExtension(File.FileName)); } - - public static XmlCompletionDataProvider GetProvider(string extension) - { - string defaultNamespacePrefix; - XmlSchemaCompletionData defaultSchemaCompletionData; - XmlSchemaCompletionDataCollection schemas; - - if (PropertyService.DataDirectory != null) { - schemas = XmlSchemaManager.SchemaCompletionDataItems; - defaultNamespacePrefix = XmlSchemaManager.GetNamespacePrefix(extension); - defaultSchemaCompletionData = XmlSchemaManager.GetSchemaCompletionData(extension); - } else { - // for NUnit tests - defaultNamespacePrefix = string.Empty; - schemas = new XmlSchemaCompletionDataCollection(); - defaultSchemaCompletionData = null; - } - - return new XmlCompletionDataProvider(schemas, - defaultSchemaCompletionData, - defaultNamespacePrefix); - } - + public ITextEditor TextEditor { get { foreach (IViewContent view in File.RegisteredViewContents) { ITextEditorProvider provider = view as ITextEditorProvider; - if (provider != null) { IDocument document = provider.GetDocumentForFile(File); - if (document != null) + if (document != null) { return provider.TextEditor; + } } } - return null; } } @@ -121,18 +100,16 @@ namespace ICSharpCode.XmlEditor get { foreach (IViewContent view in File.RegisteredViewContents) { XmlTreeView tree = view as XmlTreeView; - if (tree != null) + if (tree != null) { return tree; + } } - return null; } } public static XmlView ActiveXmlView { - get { - return XmlView.ForViewContent(WorkbenchSingleton.Workbench.ActiveViewContent); - } + get { return XmlView.ForViewContent(WorkbenchSingleton.Workbench.ActiveViewContent); } } /// @@ -207,9 +184,7 @@ namespace ICSharpCode.XmlEditor /// Checks that the xml in this view is well-formed. /// public bool IsWellFormed { - get { - return CheckIsWellFormed(); - } + get { return CheckIsWellFormed(); } } public bool CheckIsWellFormed() @@ -220,11 +195,9 @@ namespace ICSharpCode.XmlEditor XmlDocument Document = new XmlDocument(); Document.LoadXml(editor.Document.Text); return true; - } - catch (XmlException ex) { + } catch (XmlException ex) { AddTask(editor.FileName, ex.Message, ex.LinePosition - 1, ex.LineNumber - 1, TaskType.Error); - } - catch (WebException ex) { + } catch (WebException ex) { AddTask(editor.FileName, ex.Message, 0, 0, TaskType.Error); } return false; @@ -435,8 +408,7 @@ namespace ICSharpCode.XmlEditor public string[] InferSchema() { ITextEditor editor = TextEditor; - if (editor == null) - return null; + if (editor == null) return null; TaskService.ClearExceptCommentTasks(); if (IsWellFormed) { @@ -460,11 +432,9 @@ namespace ICSharpCode.XmlEditor public void FormatXml() { ITextEditor editor = TextEditor; - if (editor == null) - return; + if (editor == null) return; TaskService.ClearExceptCommentTasks(); - if (IsWellFormed) { ReplaceAll(editor.Document.Text); } else { @@ -479,8 +449,7 @@ namespace ICSharpCode.XmlEditor public void ReplaceAll(string xml) { ITextEditor editor = TextEditor; - if (editor == null) - return; + if (editor == null) return; string formattedXml = SimpleFormat(IndentedFormat(xml)); editor.Document.Text = formattedXml; @@ -507,8 +476,7 @@ namespace ICSharpCode.XmlEditor string indentedText = string.Empty; ITextEditor editor = TextEditor; - if (editor == null) - return indentedText; + if (editor == null) return indentedText; try { XmlTextReader reader = new XmlTextReader(new StringReader(xml)); @@ -524,7 +492,6 @@ namespace ICSharpCode.XmlEditor } catch(Exception) { indentedText = xml; } - return indentedText; } @@ -540,14 +507,14 @@ namespace ICSharpCode.XmlEditor OutputWindowWriteLine(StringParser.Parse("${res:MainWindow.XmlValidationMessages.ValidationStarted}")); if (IsSchema) { - if (!ValidateSchema()) - return; - } else { - if (!ValidateAgainstSchema()) + if (!ValidateSchema()) { return; + } + } else if (!ValidateAgainstSchema()) { + return; } - OutputWindowWriteLine(string.Empty); + OutputWindowWriteLine(String.Empty); OutputWindowWriteLine(StringParser.Parse("${res:MainWindow.XmlValidationMessages.ValidationSuccess}")); } @@ -555,7 +522,7 @@ namespace ICSharpCode.XmlEditor get { string extension = Path.GetExtension(File.FileName); if (extension != null) { - return string.Compare(".xsd", extension, StringComparison.OrdinalIgnoreCase) == 0; + return String.Compare(".xsd", extension, StringComparison.OrdinalIgnoreCase) == 0; } return false; } @@ -568,8 +535,7 @@ namespace ICSharpCode.XmlEditor bool ValidateAgainstSchema() { ITextEditor editor = TextEditor; - if (editor == null) - return false; + if (editor == null) return false; try { StringReader stringReader = new StringReader(editor.Document.Text); @@ -617,8 +583,7 @@ namespace ICSharpCode.XmlEditor bool ValidateSchema() { ITextEditor editor = TextEditor; - if (editor == null) - return false; + if (editor == null) return false; StringReader stringReader = new StringReader(editor.Document.Text); XmlTextReader xmlReader = new XmlTextReader(stringReader); @@ -686,8 +651,7 @@ namespace ICSharpCode.XmlEditor TaskService.ClearExceptCommentTasks(); ITextEditor editor = TextEditor; - if (editor == null) - return; + if (editor == null) return; if (IsWellFormed) { if (IsValidXsl(xsl)) { @@ -819,9 +783,6 @@ namespace ICSharpCode.XmlEditor /// /// Tries to get the filename from the inner exception otherwise returns the default filename. /// - /// - /// - /// static string GetFileNameFromInnerException(Exception ex, string defaultFileName) { XmlException innerException = ex.InnerException as XmlException; From 8a4b2018a567d65882130b489e4eb10c7bb01028 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 8 Jun 2009 19:22:58 +0000 Subject: [PATCH 08/18] Avoid NullReferenceException when pasting text. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4267 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Document/NewLineFinder.cs | 2 ++ .../Editing/EditingCommandHandler.cs | 28 ++++++++++--------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/NewLineFinder.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/NewLineFinder.cs index af7b85e4cf..3207220015 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/NewLineFinder.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/NewLineFinder.cs @@ -51,6 +51,8 @@ namespace ICSharpCode.AvalonEdit.Document /// public static string NormalizeNewLines(string input, string newLine) { + if (input == null) + return null; Debug.Assert(IsNewLine(newLine)); SimpleSegment ds = NextNewLine(input, 0); if (ds == SimpleSegment.Invalid) // text does not contain any new lines diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs index 737c48034f..439003c7c0 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs @@ -208,14 +208,14 @@ namespace ICSharpCode.AvalonEdit.Editing { TransformSelectedLines( delegate (TextArea textArea, DocumentLine line) { - int offset = line.Offset; - ISegment s = TextUtilities.GetSingleIndentationSegment(line.Document, offset, textArea.Options.IndentationSize); - if (s.Length > 0) { - s = textArea.ReadOnlySectionProvider.GetDeletableSegments(s).FirstOrDefault(); - if (s != null && s.Length > 0) { - textArea.Document.Remove(s.Offset, s.Length); - } + int offset = line.Offset; + ISegment s = TextUtilities.GetSingleIndentationSegment(line.Document, offset, textArea.Options.IndentationSize); + if (s.Length > 0) { + s = textArea.ReadOnlySectionProvider.GetDeletableSegments(s).FirstOrDefault(); + if (s != null && s.Length > 0) { + textArea.Document.Remove(s.Offset, s.Length); } + } }, target, args, DefaultSegmentType.CurrentLine); } #endregion @@ -344,12 +344,14 @@ namespace ICSharpCode.AvalonEdit.Editing string newLine = NewLineFinder.GetNewLineFromDocument(textArea.Document, textArea.Caret.Line); string text = NewLineFinder.NormalizeNewLines(Clipboard.GetText(), newLine); - bool fullLine = textArea.Options.CutCopyWholeLine && Clipboard.ContainsData(LineSelectedType); - if (fullLine) { - DocumentLine currentLine = textArea.Document.GetLineByNumber(textArea.Caret.Line); - textArea.Document.Insert(currentLine.Offset, text); - } else { - textArea.ReplaceSelectionWithText(text); + if (!string.IsNullOrEmpty(text)) { + bool fullLine = textArea.Options.CutCopyWholeLine && Clipboard.ContainsData(LineSelectedType); + if (fullLine) { + DocumentLine currentLine = textArea.Document.GetLineByNumber(textArea.Caret.Line); + textArea.Document.Insert(currentLine.Offset, text); + } else { + textArea.ReplaceSelectionWithText(text); + } } textArea.Caret.BringCaretToView(); args.Handled = true; From 8396a39d9cbc4b335a688053ac7a9d145cdc8c99 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 8 Jun 2009 19:55:46 +0000 Subject: [PATCH 09/18] Update AvalonDock to 1.2.2154. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4269 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- src/Libraries/AvalonDock/AvalonDock.csproj | 1 + .../DeserializationCallbackEventArgs.cs | 25 ++++ src/Libraries/AvalonDock/DockableContent.cs | 8 + src/Libraries/AvalonDock/DockablePane.cs | 6 +- src/Libraries/AvalonDock/DockingManager.cs | 140 ++++++++++++++---- src/Libraries/AvalonDock/FloatingWindow.cs | 24 ++- .../AvalonDock/Properties/AssemblyInfo.cs | 2 +- src/Libraries/AvalonDock/ResizingPanel.cs | 4 +- 8 files changed, 175 insertions(+), 35 deletions(-) create mode 100644 src/Libraries/AvalonDock/DeserializationCallbackEventArgs.cs diff --git a/src/Libraries/AvalonDock/AvalonDock.csproj b/src/Libraries/AvalonDock/AvalonDock.csproj index e80df4b000..9661c8aa27 100644 --- a/src/Libraries/AvalonDock/AvalonDock.csproj +++ b/src/Libraries/AvalonDock/AvalonDock.csproj @@ -76,6 +76,7 @@ + diff --git a/src/Libraries/AvalonDock/DeserializationCallbackEventArgs.cs b/src/Libraries/AvalonDock/DeserializationCallbackEventArgs.cs new file mode 100644 index 0000000000..cc8acf2248 --- /dev/null +++ b/src/Libraries/AvalonDock/DeserializationCallbackEventArgs.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace AvalonDock +{ + public class DeserializationCallbackEventArgs : EventArgs + { + public DeserializationCallbackEventArgs(string contentName) + { + Name = contentName; + } + + /// + /// Gets the name of the content to deserialize + /// + public string Name { get; protected set; } + + /// + /// Gets/Sets the content manually deserialized + /// + public DockableContent Content { get; set; } + } +} diff --git a/src/Libraries/AvalonDock/DockableContent.cs b/src/Libraries/AvalonDock/DockableContent.cs index 1c2e9aa736..c65d60ac58 100644 --- a/src/Libraries/AvalonDock/DockableContent.cs +++ b/src/Libraries/AvalonDock/DockableContent.cs @@ -156,6 +156,8 @@ namespace AvalonDock public readonly double Width; public readonly double Height; + public readonly AnchorStyle Anchor = AnchorStyle.None; + public DockableContentStateAndPosition( DockableContent cntToSave) { @@ -163,6 +165,12 @@ namespace AvalonDock ChildIndex = ContainerPane.Items.IndexOf(cntToSave); Width = ContainerPane.ActualWidth; Height = ContainerPane.ActualHeight; + + DockablePane dockablePane = ContainerPane as DockablePane; + if (dockablePane != null) + { + Anchor = dockablePane.Anchor; + } } } diff --git a/src/Libraries/AvalonDock/DockablePane.cs b/src/Libraries/AvalonDock/DockablePane.cs index cb126ee712..0f7c0dac92 100644 --- a/src/Libraries/AvalonDock/DockablePane.cs +++ b/src/Libraries/AvalonDock/DockablePane.cs @@ -47,6 +47,10 @@ namespace AvalonDock /// public enum AnchorStyle { + /// + /// No anchor style, while content is hosted in a or a + /// + None, /// /// Top border anchor /// @@ -135,7 +139,7 @@ namespace AvalonDock // Using a DependencyProperty as the backing store for Anchor. This enables animation, styling, binding, etc... public static readonly DependencyPropertyKey AnchorPropertyKey = - DependencyProperty.RegisterAttachedReadOnly("Anchor", typeof(AnchorStyle), typeof(DockablePane), new UIPropertyMetadata(AnchorStyle.Left)); + DependencyProperty.RegisterAttachedReadOnly("Anchor", typeof(AnchorStyle), typeof(DockablePane), new UIPropertyMetadata(AnchorStyle.None)); public override void OnApplyTemplate() diff --git a/src/Libraries/AvalonDock/DockingManager.cs b/src/Libraries/AvalonDock/DockingManager.cs index 8ce8c3e92d..dd2f4d6e96 100644 --- a/src/Libraries/AvalonDock/DockingManager.cs +++ b/src/Libraries/AvalonDock/DockingManager.cs @@ -213,8 +213,8 @@ namespace AvalonDock } set { - if (_activeDocument != value && - value.ContainerPane is DocumentPane) + if (_activeDocument != value/* && + value.ContainerPane is DocumentPane*/) { List listOfAllDocuments = FindContents(); listOfAllDocuments.ForEach((ManagedContent cnt) => @@ -685,6 +685,9 @@ namespace AvalonDock //remove the pane from its original children collection FrameworkElement parentElement = paneToAnchor.Parent as FrameworkElement; + if (anchor == AnchorStyle.None) + anchor = AnchorStyle.Right; + //Change anchor border according to FlowDirection if (FlowDirection == FlowDirection.RightToLeft) { @@ -801,6 +804,9 @@ namespace AvalonDock /// public void Anchor(Pane paneToAnchor, Pane relativePane, AnchorStyle anchor) { + if (anchor == AnchorStyle.None) + anchor = AnchorStyle.Right; + //Change anchor border according to FlowDirection if (FlowDirection == FlowDirection.RightToLeft) { @@ -832,6 +838,9 @@ namespace AvalonDock /// public void Anchor(DockablePane paneToAnchor, DocumentPane relativePane, AnchorStyle anchor) { + if (anchor == AnchorStyle.None) + anchor = AnchorStyle.Right; + //get a reference to the resizingpanel container of relativePane ResizingPanel relativePaneContainer = LogicalTreeHelper.GetParent(relativePane) as ResizingPanel; DocumentPaneResizingPanel relativeDocumentPaneContainer = relativePane.GetParentDocumentPaneResizingPanel(); @@ -981,6 +990,9 @@ namespace AvalonDock /// public void Anchor(DocumentPane paneToAnchor, DocumentPane relativePane, AnchorStyle anchor) { + if (anchor == AnchorStyle.None) + anchor = AnchorStyle.Right; + //get a reference to the resizingpanel container of relativePane ResizingPanel relativePaneContainer = LogicalTreeHelper.GetParent(relativePane) as ResizingPanel; DocumentPaneResizingPanel relativeDocumentPaneContainer = relativePane.GetParentDocumentPaneResizingPanel(); @@ -1083,6 +1095,9 @@ namespace AvalonDock /// public void Anchor(DockablePane paneToAnchor, DockablePane relativePane, AnchorStyle anchor) { + if (anchor == AnchorStyle.None) + anchor = AnchorStyle.Right; + //get a refernce to the resizingpanel container of relativePane ResizingPanel relativePaneContainer = LogicalTreeHelper.GetParent(relativePane) as ResizingPanel; Orientation requestedOrientation = @@ -1536,7 +1551,7 @@ namespace AvalonDock /// State desidered public void Show(DockableContent content, DockableContentState desideredState) { - Show(content, desideredState, AnchorStyle.Right); + Show(content, desideredState, AnchorStyle.None); } /// @@ -1696,6 +1711,14 @@ namespace AvalonDock DockablePane newHostpane = new DockablePane(); newHostpane.Items.Add(content); + if (desideredAnchor == AnchorStyle.None && + content.SavedStateAndPosition != null && + content.SavedStateAndPosition.Anchor != AnchorStyle.None) + desideredAnchor = content.SavedStateAndPosition.Anchor; + + if (desideredAnchor == AnchorStyle.None) + desideredAnchor = AnchorStyle.Right; + if (desideredAnchor == AnchorStyle.Left || desideredAnchor == AnchorStyle.Right) { @@ -1705,7 +1728,8 @@ namespace AvalonDock !double.IsNaN(content.SavedStateAndPosition.Width)) w = content.SavedStateAndPosition.Width; - //ResizingPanel.SetResizeWidth(newHostpane, w); + ResizingPanel.SetResizeWidth(newHostpane, new GridLength(w)); + ResizingPanel.SetEffectiveSize(newHostpane, new Size(w, 0.0)); } else { @@ -1715,7 +1739,8 @@ namespace AvalonDock !double.IsNaN(content.SavedStateAndPosition.Height)) h = content.SavedStateAndPosition.Height; - //ResizingPanel.SetResizeHeight(newHostpane, h); + ResizingPanel.SetResizeHeight(newHostpane, new GridLength(h)); + ResizingPanel.SetEffectiveSize(newHostpane, new Size(0.0, h)); } Anchor(newHostpane, desideredAnchor); @@ -2474,13 +2499,18 @@ namespace AvalonDock { if (content.State == DockableContentState.AutoHide) { - if ((content.Parent as DockablePane).Items.Count == 1) + DockablePane parentContainer = content.Parent as DockablePane; + if (parentContainer != null && + parentContainer.Items.Count == 1) ToggleAutoHide(content.Parent as DockablePane); } if (content.State == DockableContentState.DockableWindow || content.State == DockableContentState.FloatingWindow) { - if ((content.Parent as DockablePane).Items.Count == 1) + DockablePane parentContainer = content.Parent as DockablePane; + + if (parentContainer != null && + parentContainer.Items.Count == 1) { FloatingWindow floatingWindow = Window.GetWindow(content) as FloatingWindow; floatingWindow.Close(); @@ -2493,6 +2523,11 @@ namespace AvalonDock content.DetachFromContainerPane(); } + + public delegate void DeserializationCallbackHandler(object sender, DeserializationCallbackEventArgs e); + public DeserializationCallbackHandler DeserializationCallback { get; set; } + + void ShowAllHiddenContents() { while (_hiddenContents.Count > 0) @@ -2502,7 +2537,7 @@ namespace AvalonDock } } - void RestoreDocumentPaneLayout(XmlElement childElement, out DocumentPane mainExistingDocumentPane, out DocumentPaneResizingPanel existingDocumentPanel) + void RestoreDocumentPaneLayout(XmlElement childElement, out DocumentPane mainExistingDocumentPane, out DocumentPaneResizingPanel existingDocumentPanel, DockableContent[] dockableContents) { mainExistingDocumentPane = (Content is DocumentPane) ? Content as DocumentPane : GetMainDocumentPane(Content as ResizingPanel); existingDocumentPanel = mainExistingDocumentPane.GetParentDocumentPaneResizingPanel(); @@ -2534,17 +2569,36 @@ namespace AvalonDock { if (contentElement.HasAttribute("Name")) { - foreach (DockableContent content in DockableContents) + DockableContent foundContent = null; + string contentName = contentElement.GetAttribute("Name"); + foreach (DockableContent content in dockableContents) { - if (content.Name == contentElement.GetAttribute("Name")) + if (content.Name == contentName) { - DetachContentFromDockingManager(content); - mainExistingDocumentPane.Items.Add(content); - content.SetStateToDocument(); - content.RestoreLayout(contentElement); + foundContent = content; break; } } + + if (foundContent == null && + DeserializationCallback != null) + { + DeserializationCallbackEventArgs e = new DeserializationCallbackEventArgs(contentName); + DeserializationCallback(this, e); + + foundContent = e.Content; + } + + + if (foundContent != null) + { + DetachContentFromDockingManager(foundContent); + mainExistingDocumentPane.Items.Add(foundContent); + foundContent.SetStateToDocument(); + + //call custom layout persistence method + foundContent.RestoreLayout(contentElement); + } } } } @@ -2593,24 +2647,40 @@ namespace AvalonDock { if (contentElement.HasAttribute("Name")) { + DockableContent foundContent = null; + string contentName = contentElement.GetAttribute("Name"); foreach (DockableContent content in dockableContents) { - if (content.Name == contentElement.GetAttribute("Name")) + if (content.Name == contentName) { - DetachContentFromDockingManager(content); - pane.Items.Add(content); - content.SetStateToDock(); - if (contentElement.HasAttribute("AutoHide") && - XmlConvert.ToBoolean(contentElement.GetAttribute("AutoHide")) && - pane.Items.Count == 1) - toggleAutoHide = true; - - //call custom layout persistence method - content.RestoreLayout(contentElement); - + foundContent = content; break; } } + + if (foundContent == null && + DeserializationCallback != null) + { + DeserializationCallbackEventArgs e = new DeserializationCallbackEventArgs(contentName); + DeserializationCallback(this, e); + + foundContent = e.Content; + } + + + if (foundContent != null) + { + DetachContentFromDockingManager(foundContent); + pane.Items.Add(foundContent); + foundContent.SetStateToDock(); + if (contentElement.HasAttribute("AutoHide") && + XmlConvert.ToBoolean(contentElement.GetAttribute("AutoHide")) && + pane.Items.Count == 1) + toggleAutoHide = true; + + //call custom layout persistence method + foundContent.RestoreLayout(contentElement); + } } } if (pane.Items.Count > 0) @@ -2629,7 +2699,7 @@ namespace AvalonDock DocumentPaneResizingPanel existingDocumentPanel = null; DocumentPane mainExistingDocumentPane = null; - RestoreDocumentPaneLayout(childElement, out mainExistingDocumentPane, out existingDocumentPanel); + RestoreDocumentPaneLayout(childElement, out mainExistingDocumentPane, out existingDocumentPanel, dockableContents); if (existingDocumentPanel != null) { @@ -2723,7 +2793,7 @@ namespace AvalonDock DocumentPaneResizingPanel existingDocumentPanel = null; DocumentPane mainExistingDocumentPane = null; - RestoreDocumentPaneLayout(rootElement, out mainExistingDocumentPane, out existingDocumentPanel); + RestoreDocumentPaneLayout(rootElement, out mainExistingDocumentPane, out existingDocumentPanel, actualContents); if (existingDocumentPanel != null) { @@ -2776,14 +2846,24 @@ namespace AvalonDock foreach (XmlElement contentElement in paneElement.ChildNodes) { #region Find the content to transfer + string contentToFindName = contentElement.GetAttribute("Name"); foreach (DockableContent content in actualContents) { - if (contentElement.GetAttribute("Name") == content.Name) + if (contentToFindName == content.Name) { contentToTransfer = content; break; } - } + } + + if (contentToTransfer == null && + DeserializationCallback != null) + { + DeserializationCallbackEventArgs e = new DeserializationCallbackEventArgs(contentToFindName); + DeserializationCallback(this, e); + + contentToTransfer = e.Content; + } #endregion diff --git a/src/Libraries/AvalonDock/FloatingWindow.cs b/src/Libraries/AvalonDock/FloatingWindow.cs index 9eaa63473d..6ef4506a9a 100644 --- a/src/Libraries/AvalonDock/FloatingWindow.cs +++ b/src/Libraries/AvalonDock/FloatingWindow.cs @@ -117,6 +117,29 @@ namespace AvalonDock } + #region Active Content Management + ManagedContent lastActiveContent = null; + + protected override void OnActivated(EventArgs e) + { + if (Manager != null) + { + lastActiveContent = Manager.ActiveContent; + Manager.ActiveContent = HostedPane.SelectedItem as ManagedContent; + } + + base.OnActivated(e); + } + + protected override void OnDeactivated(EventArgs e) + { + if (Manager != null && lastActiveContent != null) + { + Manager.ActiveContent = lastActiveContent; + } + base.OnDeactivated(e); + } + #endregion public abstract Pane ClonePane(); @@ -368,7 +391,6 @@ namespace AvalonDock } #endregion - #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; diff --git a/src/Libraries/AvalonDock/Properties/AssemblyInfo.cs b/src/Libraries/AvalonDock/Properties/AssemblyInfo.cs index b841400406..e7f6ef4431 100644 --- a/src/Libraries/AvalonDock/Properties/AssemblyInfo.cs +++ b/src/Libraries/AvalonDock/Properties/AssemblyInfo.cs @@ -59,4 +59,4 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.2.2104")] +[assembly: AssemblyVersion("1.2.2154")] diff --git a/src/Libraries/AvalonDock/ResizingPanel.cs b/src/Libraries/AvalonDock/ResizingPanel.cs index 5e46ce9e23..d51d081ade 100644 --- a/src/Libraries/AvalonDock/ResizingPanel.cs +++ b/src/Libraries/AvalonDock/ResizingPanel.cs @@ -789,7 +789,7 @@ namespace AvalonDock #if DEBUG Debug.Assert(_splitterList.Count == Children.Count / 2); i = 0; - while (true) + while (Children.Count > 0) { Debug.Assert(Children[i] != null); Debug.Assert(!(Children[i] is ResizingPanelSplitter)); @@ -799,7 +799,7 @@ namespace AvalonDock Debug.Assert((Children[i] is ResizingPanelSplitter)); i++; - + } #endif splitterListIsDirty = false; From bce5fe49da79b298ae7b8d7fd11d24c2f9e7f24f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kon=C3=AD=C4=8Dek?= Date: Thu, 11 Jun 2009 15:25:55 +0000 Subject: [PATCH 10/18] Object graph visualizer - user can expand/collapse nodes. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4275 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Debugger.AddIn.csproj | 13 +- .../Graph/Drawing/NodeControl.xaml | 1 + .../Graph/Drawing/NodeControl.xaml.cs | 177 +++++++++++++----- .../Src/Visualizers/Graph/ExpandedNodes.cs | 38 ++++ .../Graph/Layout/PositionedGraph.cs | 7 +- .../Graph/Layout/PositionedNode.cs | 47 ++++- .../Graph/Layout/PositionedNodeProperty.cs | 22 +++ .../Layout/PositionedPropertyEventArgs.cs | 25 +++ .../Graph/Layout/Tree/TreeLayouter.cs | 17 +- .../Graph/ObjectGraph/ObjectGraphBuilder.cs | 10 +- .../Graph/ObjectGraph/ObjectProperty.cs | 4 + .../Graph/ObjectGraphVisualizerViewContent.cs | 39 ---- .../Graph/VisualizerWPFControl.xaml | 12 -- .../Graph/VisualizerWPFControl.xaml.cs | 33 ---- .../Graph/VisualizerWPFWindow.xaml.cs | 33 +++- .../VisualizerWinFormsControl.Designer.cs | 92 --------- .../Graph/VisualizerWinFormsControl.cs | 84 --------- 17 files changed, 316 insertions(+), 338 deletions(-) create mode 100644 src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ExpandedNodes.cs create mode 100644 src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedPropertyEventArgs.cs delete mode 100644 src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraphVisualizerViewContent.cs delete mode 100644 src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml delete mode 100644 src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml.cs delete mode 100644 src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.Designer.cs delete mode 100644 src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.cs diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj index cf641b2b3d..98b28217fe 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj @@ -170,13 +170,17 @@ - + + NodeControl.xaml + + + @@ -190,7 +194,6 @@ - @@ -202,11 +205,6 @@ - - - - VisualizerWPFControl.xaml - VisualizerWPFWindow.xaml @@ -300,7 +298,6 @@ - diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml index e135828cca..47e27957e1 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml @@ -16,6 +16,7 @@ + diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml.cs index 165fafea46..993ef83f94 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Drawing/NodeControl.xaml.cs @@ -4,6 +4,7 @@ // // $Revision$ // +using Debugger.AddIn.Visualizers.Graph.Layout; using System; using System.Collections.Generic; using System.Text; @@ -20,59 +21,133 @@ using Debugger.AddIn.Visualizers.Graph; namespace Debugger.AddIn.Visualizers.Graph.Drawing { - /// - /// UserControl used to display ObjectNode. - /// - public partial class NodeControl : UserControl - { - public NodeControl() - { - InitializeComponent(); - } + /// + /// UserControl used to display Positione. + /// + public partial class NodeControl : UserControl + { + /// + /// Creates new NodeControl displaying PositionedNode. + /// + /// PositionedNode displayed by the control. + public NodeControl(PositionedNode graphNode) : this() + { + //this.initializeWithGraphNode(graphNode); + this.GraphNode = graphNode; + } + + public NodeControl() + { + InitializeComponent(); + } + + public event EventHandler Expanded; + public event EventHandler Collapsed; - private ObjectNode node; - /// - /// ObjectNode that this control displays. - /// - public ObjectNode GraphNode - { - get - { - return node; - } - set - { - node = value; - int row = 0; - // dynamically create TextBlocks and insert them to the 2-column propertyGrid - foreach (var property in node.Properties) - { - propertyGrid.RowDefinitions.Add(new RowDefinition()); + private PositionedNode node; + /// + /// ObjectNode that this control displays. + /// + public PositionedNode GraphNode + { + get + { + return node; + } + private set + { + this.node = value; + } + } + + public void AddProperty(PositionedNodeProperty property) + { + int nRow = propertyGrid.RowDefinitions.Count; + + var row = new RowDefinition(); + propertyGrid.RowDefinitions.Add(row); + + if (!property.IsAtomic) + { + Button btnExpandCollapse = new Button(); + btnExpandCollapse.Tag = property; + btnExpandCollapse.Content = property.IsExpanded ? "-" : "+"; + btnExpandCollapse.Width = 20; + propertyGrid.Children.Add(btnExpandCollapse); + Grid.SetRow(btnExpandCollapse, nRow); + Grid.SetColumn(btnExpandCollapse, 0); + btnExpandCollapse.Click += new RoutedEventHandler(btnExpandCollapse_Click); + } - TextBlock txtName = createTextBlock(property.Name); - propertyGrid.Children.Add(txtName); - Grid.SetRow(txtName, row); - Grid.SetColumn(txtName, 0); + TextBlock txtName = createTextBlock(property.Name); + propertyGrid.Children.Add(txtName); + Grid.SetRow(txtName, nRow); + Grid.SetColumn(txtName, 1); - TextBlock txtValue = createTextBlock(property.Value); - propertyGrid.Children.Add(txtValue); - Grid.SetRow(txtValue, row); - Grid.SetColumn(txtValue, 1); + TextBlock txtValue = createTextBlock(property.Value); + propertyGrid.Children.Add(txtValue); + Grid.SetRow(txtValue, nRow); + Grid.SetColumn(txtValue, 2); + } + + /*public void Measure() + { + this.Measure(); + + int nRow = 0; + // dynamically create TextBlocks and insert them to the 2-column propertyGrid + foreach (var property in node.Properties) + { + - row++; - } - } - } - - /// - /// Creates TextBlock with given text. - /// - private TextBlock createTextBlock(string text) - { - TextBlock newTextblock = new TextBlock(); - newTextblock.Text = text; - newTextblock.Padding = new Thickness(4); - return newTextblock; - } - } + nRow++; + } + }*/ + + void btnExpandCollapse_Click(object sender, RoutedEventArgs e) + { + Button buttonClicked = ((Button)sender); + var property = (PositionedNodeProperty)buttonClicked.Tag; + + property.IsExpanded = !property.IsExpanded; + buttonClicked.Content = property.IsExpanded ? "-" : "+"; + if (property.IsExpanded) + { + OnPropertyExpanded(property); + } + else + { + OnPropertyCollapsed(property); + } + } + + /// + /// Creates TextBlock with given text. + /// + private TextBlock createTextBlock(string text) + { + TextBlock newTextblock = new TextBlock(); + newTextblock.Text = text; + newTextblock.Padding = new Thickness(4); + return newTextblock; + } + + #region event helpers + protected virtual void OnPropertyExpanded(PositionedNodeProperty property) + { + if (this.Expanded != null) + { + this.Expanded(this, new PositionedPropertyEventArgs(property)); + } + } + + protected virtual void OnPropertyCollapsed(PositionedNodeProperty property) + { + if (this.Collapsed != null) + { + this.Collapsed(this, new PositionedPropertyEventArgs(property)); + } + } + #endregion + } } diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ExpandedNodes.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ExpandedNodes.cs new file mode 100644 index 0000000000..8f29e49dde --- /dev/null +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ExpandedNodes.cs @@ -0,0 +1,38 @@ +// +// +// +// +// $Revision$ +// +using System; +using System.Collections.Generic; + +namespace Debugger.AddIn.Visualizers.Graph +{ + /// + /// Remembers which expressions the user has expanded. + /// + public class ExpandedNodes + { + private Dictionary expandedNodes = new Dictionary(); + + public ExpandedNodes() + { + } + + public bool IsExpanded(string expression) + { + return expandedNodes.ContainsKey(expression) && (expandedNodes[expression] == true); + } + + public void Expand(string expression) + { + expandedNodes[expression] = true; + } + + public void Collapse(string expression) + { + expandedNodes[expression] = false; + } + } +} diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraph.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraph.cs index f2d17f837e..31fe5e9c28 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraph.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedGraph.cs @@ -16,7 +16,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout /// public class PositionedGraph { - internal List nodes = new List(); + private List nodes = new List(); public System.Windows.Rect BoundingRect { @@ -39,6 +39,11 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout get { return nodes; } } + internal void AddNode(PositionedNode node) + { + this.nodes.Add(node); + } + /// /// All edges in the graph. /// diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs index 923759bad6..0199f60f14 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNode.cs @@ -25,6 +25,9 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout get { return objectNode; } } + public event EventHandler Expanded; + public event EventHandler Collapsed; + private List properties = new List(); public List Properties { @@ -34,10 +37,13 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout } } - public PositionedNodeProperty AddProperty(ObjectProperty objectProperty) + public PositionedNodeProperty AddProperty(ObjectProperty objectProperty, bool isExpanded) { var newProperty = new PositionedNodeProperty(objectProperty, this); + newProperty.IsExpanded = isExpanded; this.Properties.Add(newProperty); + this.nodeVisualControl.AddProperty(newProperty); + return newProperty; } @@ -49,8 +55,25 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout { this.objectNode = objectNode; - this.nodeVisualControl = new NodeControl(); - this.nodeVisualControl.GraphNode = this.objectNode; // display + this.nodeVisualControl = new NodeControl(this); // display + this.nodeVisualControl.Expanded += new EventHandler(NodeVisualControl_Expanded); + this.nodeVisualControl.Collapsed += new EventHandler(NodeVisualControl_Collapsed); + } + + private void NodeVisualControl_Expanded(object sender, PositionedPropertyEventArgs e) + { + // propagage event + OnPropertyExpanded(this, e); + } + + private void NodeVisualControl_Collapsed(object sender, PositionedPropertyEventArgs e) + { + // propagate event + OnPropertyCollapsed(this, e); + } + + public void Measure() + { this.nodeVisualControl.Measure(new Size(500, 500)); } @@ -100,5 +123,23 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout } } } + + #region event helpers + protected virtual void OnPropertyExpanded(object sender, PositionedPropertyEventArgs propertyArgs) + { + if (this.Expanded != null) + { + this.Expanded(sender, propertyArgs); + } + } + + protected virtual void OnPropertyCollapsed(object sender, PositionedPropertyEventArgs propertyArgs) + { + if (this.Collapsed != null) + { + this.Collapsed(sender, propertyArgs); + } + } + #endregion } } diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNodeProperty.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNodeProperty.cs index 9e07486fdb..85fc4ac103 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNodeProperty.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedNodeProperty.cs @@ -23,6 +23,8 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout this.containingNode = containingNode; } + public bool IsExpanded { get; set; } + private ObjectProperty objectProperty; /// /// Underlying . @@ -45,5 +47,25 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout /// Edge outgoing from this property to another . /// public PositionedEdge Edge { get; set; } + + /// + /// e.g. "Age" + /// + public string Name { get { return this.objectProperty.Name; } } + + /// + /// e.g. "19" + /// + public string Value { get { return this.objectProperty.Value; } } + + /// + /// Full Debugger expression used to obtain value of this property. + /// + public Debugger.Expressions.Expression Expression { get { return this.objectProperty.Expression; } } + + /// + /// Is this property of atomic type? (int, string, etc.) + /// + public bool IsAtomic { get { return this.objectProperty.IsAtomic; } } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedPropertyEventArgs.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedPropertyEventArgs.cs new file mode 100644 index 0000000000..c6d2417e26 --- /dev/null +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/PositionedPropertyEventArgs.cs @@ -0,0 +1,25 @@ +// +// +// +// +// $Revision$ +// +using System; + +namespace Debugger.AddIn.Visualizers.Graph.Layout +{ + /// + /// EventArgs carrying . + /// + public class PositionedPropertyEventArgs : EventArgs + { + private PositionedNodeProperty property; + + public PositionedPropertyEventArgs(PositionedNodeProperty property) + { + this.property = property; + } + + public PositionedNodeProperty Property { get { return this.property; } } + } +} diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs index bc89d000ad..c5f943fc97 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/Layout/Tree/TreeLayouter.cs @@ -36,7 +36,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout /// /// /// - public PositionedGraph CalculateLayout(ObjectGraph objectGraph, LayoutDirection direction) + public PositionedGraph CalculateLayout(ObjectGraph objectGraph, LayoutDirection direction, ExpandedNodes expandedNodes) { layoutDirection = direction; @@ -44,7 +44,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout treeNodeFor = new Dictionary(); seenNodes = new Dictionary(); - TreeNode tree = buildTreeRecursive(objectGraph.Root); + TreeNode tree = buildTreeRecursive(objectGraph.Root, expandedNodes); calculateNodePosRecursive(tree, 0, 0); var neatoRouter = new NeatoEdgeRouter(); @@ -53,14 +53,14 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout return resultGraph; } - private TreeNode buildTreeRecursive(ObjectNode objectGraphNode) + private TreeNode buildTreeRecursive(ObjectNode objectGraphNode, ExpandedNodes expandedNodes) { seenNodes.Add(objectGraphNode, null); TreeNode newTreeNode = TreeNode.Create(this.layoutDirection, objectGraphNode); newTreeNode.HorizontalMargin = horizNodeMargin; newTreeNode.VerticalMargin = vertNodeMargin; - resultGraph.nodes.Add(newTreeNode); + resultGraph.AddNode(newTreeNode); treeNodeFor[objectGraphNode] = newTreeNode; double subtreeSize = 0; @@ -78,19 +78,20 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout } else { - targetTreeNode = buildTreeRecursive(neighbor); + targetTreeNode = buildTreeRecursive(neighbor, expandedNodes); newEdgeIsTreeEdge = true; subtreeSize += targetTreeNode.SubtreeSize; } - var posNodeProperty = newTreeNode.AddProperty(property); + var posNodeProperty = newTreeNode.AddProperty(property, expandedNodes.IsExpanded(property.Expression.Code)); posNodeProperty.Edge = new TreeGraphEdge { IsTreeEdge = newEdgeIsTreeEdge, Name = property.Name, Source = posNodeProperty, Target = targetTreeNode }; } else { - // PositionedNodeProperty.Edge is null - newTreeNode.AddProperty(property); + // property.Edge stays null + newTreeNode.AddProperty(property, expandedNodes.IsExpanded(property.Expression.Code)); } } + newTreeNode.Measure(); subtreeSize = Math.Max(newTreeNode.LateralSizeWithMargin, subtreeSize); newTreeNode.SubtreeSize = subtreeSize; diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs index d41f1bf718..2984c6db57 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs @@ -80,7 +80,7 @@ namespace Debugger.AddIn.Visualizers.Graph /// /// Expression valid in the program being debugged (eg. variable name) /// Object graph - public ObjectGraph BuildGraphForExpression(string expression) + public ObjectGraph BuildGraphForExpression(string expression, ExpandedNodes expandedNodes) { if (string.IsNullOrEmpty(expression)) { @@ -92,7 +92,7 @@ namespace Debugger.AddIn.Visualizers.Graph // empty graph for null expression if (!debuggerService.GetValueFromName(expression).IsNull) { - resultGraph.Root = buildGraphRecursive(debuggerService.GetValueFromName(expression).GetPermanentReference()); + resultGraph.Root = buildGraphRecursive(debuggerService.GetValueFromName(expression).GetPermanentReference(), expandedNodes); } return resultGraph; @@ -103,7 +103,7 @@ namespace Debugger.AddIn.Visualizers.Graph /// /// The Value for which the subgraph will be built. /// ObjectNode representing the value + all recursive members. - private ObjectNode buildGraphRecursive(Value rootValue) + private ObjectNode buildGraphRecursive(Value rootValue, ExpandedNodes expandedNodes) { ObjectNode thisNode = createNewNode(rootValue); @@ -136,7 +136,7 @@ namespace Debugger.AddIn.Visualizers.Graph else { ObjectNode targetNode = null; - if (!isNull(memberExpr)) + if (!isNull(memberExpr) && expandedNodes.IsExpanded(memberExpr.Code)) { // for object members, edges are added Value memberValue = getPermanentReference(memberExpr); @@ -146,7 +146,7 @@ namespace Debugger.AddIn.Visualizers.Graph if (targetNode == null) { // if no node for memberValue exists, build the subgraph for the value - targetNode = buildGraphRecursive(memberValue); + targetNode = buildGraphRecursive(memberValue, expandedNodes); } } else diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectProperty.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectProperty.cs index 8f647d7fb7..52490e4235 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectProperty.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraph/ObjectProperty.cs @@ -19,18 +19,22 @@ namespace Debugger.AddIn.Visualizers.Graph /// e.g. "Age" /// public string Name { get; set; } + /// /// e.g. "19" /// public string Value { get; set; } + /// /// Expression used for obtaining this property /// public Debugger.Expressions.Expression Expression { get; set; } + /// /// Node that this property points to. Can be null. Always null if is true. /// public ObjectNode TargetNode { get; set; } + /// /// Is this property of atomic type? (int, string, etc.) /// diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraphVisualizerViewContent.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraphVisualizerViewContent.cs deleted file mode 100644 index 6a805f10e7..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/ObjectGraphVisualizerViewContent.cs +++ /dev/null @@ -1,39 +0,0 @@ -// -// -// -// -// $Revision$ -// -using System; -using System.Text; -using System.Windows.Forms; -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Gui; - -namespace Debugger.AddIn.Visualizers.Graph -{ - /// - /// ViewContent of the visualizer. - /// - public class ObjectGraphVisualizerViewContent : AbstractViewContent - { - VisualizerWinFormsControl control = new VisualizerWinFormsControl(); - - /// - /// The representing the view. - /// - public override object Control - { - get - { - return control; - } - } - - public ObjectGraphVisualizerViewContent() - { - this.TitleName = "Object graph visualizer"; - } - } -} diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml deleted file mode 100644 index 8446aed80f..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml +++ /dev/null @@ -1,12 +0,0 @@ - - - - Expression: - - - - - - \ No newline at end of file diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml.cs deleted file mode 100644 index f6b8aa7273..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFControl.xaml.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// -// -// -// $Revision$ -// -using System; -using System.Collections.Generic; -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 Debugger.AddIn.Visualizers.Graph -{ - /// - /// Interaction logic for VisualizerWPFControl.xaml - /// - public partial class VisualizerWPFControl : UserControl - { - public VisualizerWPFControl() - { - InitializeComponent(); - } - } -} \ No newline at end of file diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs index f17911cb25..a8aea03512 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWPFWindow.xaml.cs @@ -35,6 +35,11 @@ namespace Debugger.AddIn.Visualizers.Graph private PositionedGraph oldGraph; private PositionedGraph currentGraph; private GraphDrawer graphDrawer; + + /// + /// Long-lived map telling which nodes the user expanded. + /// + private ExpandedNodes expandedNodes; public VisualizerWPFWindow() { @@ -52,6 +57,8 @@ namespace Debugger.AddIn.Visualizers.Graph this.DataContext = this.layoutViewModel; this.graphDrawer = new GraphDrawer(this.canvas); + + this.expandedNodes = new ExpandedNodes(); } public void debuggerService_IsProcessRunningChanged(object sender, EventArgs e) @@ -90,7 +97,7 @@ namespace Debugger.AddIn.Visualizers.Graph try { ICSharpCode.Core.LoggingService.Debug("Debugger visualizer: Building graph for expression: " + txtExpression.Text); - this.objectGraph = graphBuilder.BuildGraphForExpression(txtExpression.Text); + this.objectGraph = graphBuilder.BuildGraphForExpression(txtExpression.Text, expandedNodes); } catch(DebuggerVisualizerException ex) { @@ -115,7 +122,8 @@ namespace Debugger.AddIn.Visualizers.Graph Layout.TreeLayouter layouter = new Layout.TreeLayouter(); this.oldGraph = this.currentGraph; - this.currentGraph = layouter.CalculateLayout(graph, layoutViewModel.SelectedEnumValue); + this.currentGraph = layouter.CalculateLayout(graph, layoutViewModel.SelectedEnumValue, this.expandedNodes); + registerExpandCollapseEvents(this.currentGraph); var graphDiff = new GraphMatcher().MatchGraphs(oldGraph, currentGraph); this.graphDrawer.StartAnimation(oldGraph, currentGraph, graphDiff); @@ -126,5 +134,26 @@ namespace Debugger.AddIn.Visualizers.Graph { MessageBox.Show(ex.Message, "Exception", MessageBoxButton.OK, MessageBoxImage.Error); } + + void registerExpandCollapseEvents(PositionedGraph posGraph) + { + foreach (var node in posGraph.Nodes) + { + node.Expanded += new EventHandler(node_Expanded); + node.Collapsed += new EventHandler(node_Collapsed); + } + } + + void node_Expanded(object sender, PositionedPropertyEventArgs e) + { + expandedNodes.Expand(e.Property.Expression.Code); + refreshGraph(); + } + + void node_Collapsed(object sender, PositionedPropertyEventArgs e) + { + expandedNodes.Collapse(e.Property.Expression.Code); + refreshGraph(); + } } } \ No newline at end of file diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.Designer.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.Designer.cs deleted file mode 100644 index 929ca9b041..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.Designer.cs +++ /dev/null @@ -1,92 +0,0 @@ -namespace Debugger.AddIn.Visualizers.Graph -{ - partial class VisualizerWinFormsControl - { - /// - /// Designer variable used to keep track of non-visual components. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Disposes resources used by the control. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing) { - if (components != null) { - components.Dispose(); - } - } - base.Dispose(disposing); - } - - /// - /// This method is required for Windows Forms designer support. - /// Do not change the method contents inside the source code editor. The Forms designer might - /// not be able to load this method if it was changed manually. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - this.txtExpression = new System.Windows.Forms.TextBox(); - this.btnInspect = new System.Windows.Forms.Button(); - this.lblInfo = new System.Windows.Forms.Label(); - this.lblExpression = new System.Windows.Forms.Label(); - this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); - this.SuspendLayout(); - // - // txtExpression - // - this.txtExpression.Location = new System.Drawing.Point(88, 13); - this.txtExpression.Name = "txtExpression"; - this.txtExpression.Size = new System.Drawing.Size(131, 20); - this.txtExpression.TabIndex = 0; - this.toolTip1.SetToolTip(this.txtExpression, "Expression (e.g. variable name) to be inspected"); - // - // btnInspect - // - this.btnInspect.Location = new System.Drawing.Point(225, 10); - this.btnInspect.Name = "btnInspect"; - this.btnInspect.Size = new System.Drawing.Size(75, 23); - this.btnInspect.TabIndex = 1; - this.btnInspect.Text = "Inspect"; - this.btnInspect.UseVisualStyleBackColor = true; - this.btnInspect.Click += new System.EventHandler(this.BtnInspectClick); - // - // lblInfo - // - this.lblInfo.Location = new System.Drawing.Point(11, 58); - this.lblInfo.Name = "lblInfo"; - this.lblInfo.Size = new System.Drawing.Size(349, 23); - this.lblInfo.TabIndex = 2; - this.lblInfo.Text = "< Result >"; - // - // lblExpression - // - this.lblExpression.Location = new System.Drawing.Point(11, 14); - this.lblExpression.Name = "lblExpression"; - this.lblExpression.Size = new System.Drawing.Size(71, 23); - this.lblExpression.TabIndex = 4; - this.lblExpression.Text = "Expression:"; - // - // VisualizerWinFormsControl - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.lblExpression); - this.Controls.Add(this.lblInfo); - this.Controls.Add(this.btnInspect); - this.Controls.Add(this.txtExpression); - this.Name = "VisualizerWinFormsControl"; - this.Size = new System.Drawing.Size(525, 426); - this.ResumeLayout(false); - this.PerformLayout(); - } - private System.Windows.Forms.Button btnInspect; - private System.Windows.Forms.ToolTip toolTip1; - private System.Windows.Forms.Label lblExpression; - private System.Windows.Forms.Label lblInfo; - private System.Windows.Forms.TextBox txtExpression; - } -} diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.cs deleted file mode 100644 index 09621ecf01..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Graph/VisualizerWinFormsControl.cs +++ /dev/null @@ -1,84 +0,0 @@ -// -// -// -// -// $Revision$ -// -using System; -using System.ComponentModel; -using System.Drawing; -using System.Windows.Forms; -using System.Linq; - -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Services; - -namespace Debugger.AddIn.Visualizers.Graph -{ - /// - /// Windows forms control making up the object graph visualizer user interface/ - /// - public partial class VisualizerWinFormsControl : UserControl - { - WindowsDebugger _debuggerService = null; - - public VisualizerWinFormsControl() - { - // - // The InitializeComponent() call is required for Windows Forms designer support. - // - InitializeComponent(); - - _debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger; - if (_debuggerService == null) - throw new ApplicationException("Only windows debugger is currently supported"); - - _debuggerService.IsProcessRunningChanged += new EventHandler(debuggerService_IsProcessRunningChanged); - } - - public void debuggerService_IsProcessRunningChanged(object sender, EventArgs e) - { - // on step, breakpoint hit - if (!_debuggerService.IsProcessRunning) - { - refreshGraph(); - } - } - - void BtnInspectClick(object sender, EventArgs e) - { - refreshGraph(); - } - - void refreshGraph() - { - ObjectGraphBuilder graphBuilder = new ObjectGraphBuilder(_debuggerService); - ObjectGraph graph = null; - - try - { - graph = graphBuilder.BuildGraphForExpression(txtExpression.Text); - } - catch(DebuggerVisualizerException ex) - { - guiHandleException(ex); - return; - } - catch(Debugger.GetValueException ex) - { - guiHandleException(ex); - - return; - } - - // just a simple message for checking the graph is build ok, will be replaced by graph drawing of course - //lblInfo.Text = string.Format("Done. Number of graph nodes: {0}, number of edges: {1}", graph.Nodes.Count(), graph.Edges.Count()); - } - - void guiHandleException(System.Exception ex) - { - lblInfo.Text = "< Result >"; - MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Information); - } - } -} From 485f751cc5260e4fc82694104d38f4ce0fbe295f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 12 Jun 2009 12:23:07 +0000 Subject: [PATCH 11/18] - XAML completion is now a bit less intrusive - removed code duplication from XmlFormattingStrategy - fixed bugs in XAML code completion - added AssemblyName property to IProjectContent - do not close insight and completion windows when they are still needed git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4280 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Test/Utils/MockProjectContent.cs | 6 + .../XamlBinding.Tests/UtilsTests.cs | 32 +++ .../XamlBinding/XamlBinding.Tests/XmlTests.cs | 4 + .../XamlBinding/CompletionDataHelper.cs | 245 ++++++++++++++---- .../XamlBinding/XamlBinding/Extensions.cs | 32 ++- .../XamlBinding/MarkupExtensionParser.cs | 3 + .../XamlBinding/XamlBinding/Utils.cs | 74 +++++- .../XamlBinding/XamlBinding/XamlBinding.addin | 4 + .../XamlBinding/XamlCodeCompletionBinding.cs | 54 ++-- .../XamlBinding/XamlCompletionItem.cs | 91 ++++++- .../XamlBinding/XamlCompletionItemList.cs | 33 ++- .../XamlBinding/XamlBinding/XamlContext.cs | 5 + .../AvalonEdit.AddIn/Src/CodeEditor.cs | 12 +- .../XmlEditor/Project/Src/FormatXmlCommand.cs | 10 +- .../Project/Src/XmlFormattingStrategy.cs | 35 ++- .../XmlEditor/Project/Src/XmlTreeView.cs | 4 +- .../XmlEditor/Project/Src/XmlView.cs | 26 +- .../XmlEditor/Project/XmlEditor.csproj | 5 + .../Test/Utils/MockProjectContent.cs | 6 + .../Project/Src/Gui/Dialogs/NewFileDialog.cs | 2 +- .../ParserService/ParseProjectContent.cs | 7 +- .../ProjectContent/DefaultProjectContent.cs | 7 + .../Src/ProjectContent/IProjectContent.cs | 7 + .../ReflectionProjectContent.cs | 6 + 24 files changed, 558 insertions(+), 152 deletions(-) diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs index 64eda64168..408ba9a285 100644 --- a/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs +++ b/src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs @@ -354,5 +354,11 @@ namespace PythonBinding.Tests.Utils { throw new NotImplementedException(); } + + public string AssemblyName { + get { + throw new NotImplementedException(); + } + } } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs index 8b1529bbc2..912c751015 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/UtilsTests.cs @@ -98,5 +98,37 @@ namespace ICSharpCode.XamlBinding.Tests Assert.AreEqual(expectedResult, actualResult); } + + [Test] + public void ExistingAttributesTest() + { + string xaml = " { "xmlns", "xmlns:x", "xmlns:toolkit", "xmlns:chartingToolkit" }; + + Assert.AreEqual(expected.Count, list.Length, "Wrong count!"); + Assert.AreEqual(list, expected, "Wrong elements!"); + } + + [Test] + public void ExistingAttributesWithInvalidSyntaxTest() + { + string xaml = " { "xmlns", "xmlns:x", "xmlns:toolkit", "xmlns:chartingToolkit" }; + + Assert.AreEqual(expected.Count, list.Length, "Wrong count!"); + Assert.AreEqual(list, expected, "Wrong elements!"); + } } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs index 6731151cb0..ebc98f21f9 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XmlTests.cs @@ -66,6 +66,8 @@ namespace ICSharpCode.XamlBinding.Tests int offset = "$Revision$ // -using ICSharpCode.SharpDevelop.Editor.CodeCompletion; +using ICSharpCode.SharpDevelop.Project; using System; using System.Collections.Generic; using System.Diagnostics; @@ -15,6 +15,7 @@ using System.Xml; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.XmlEditor; using LoggingService = ICSharpCode.Core.LoggingService; @@ -32,6 +33,10 @@ namespace ICSharpCode.XamlBinding static readonly List standardAttributes = new List { new DefaultCompletionItem("xmlns:") }; + + static readonly List xamlNamespaceAttributes = new List { + "Class", "ClassModifier", "FieldModifier", "Name", "Subclass", "TypeArguments", "Uid" + }; #endregion public const string XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml"; @@ -62,7 +67,7 @@ namespace ICSharpCode.XamlBinding XamlContextDescription description = XamlContextDescription.InTag; if (path == null || path.Elements.Count == 0) { - description = XamlContextDescription.AtTag; + description = XamlContextDescription.None; path = XmlParser.GetParentElementPath(text.Substring(0, offset)); } else { int ltOffset = XmlParser.GetActiveElementStartIndex(text, offset); @@ -71,7 +76,7 @@ namespace ICSharpCode.XamlBinding else { string space = text.Substring(ltOffset + 1, offset - ltOffset - 1); var last = path.Elements.LastOrDefault(); - if (last != null && last.ToString().Equals(space, StringComparison.Ordinal)) + if (last != null && last.ToString().StartsWith(space, StringComparison.Ordinal)) description = XamlContextDescription.AtTag; } } @@ -101,31 +106,96 @@ namespace ICSharpCode.XamlBinding return context; } - static List CreateListForAttributeName(ParseInformation parseInfo, XamlExpressionContext context, string[] existingItems) + static List CreateListForAttributeName(ITextEditor editor, ParseInformation parseInfo, XamlExpressionContext context, string[] existingItems) { if (context.ElementPath.Elements.Count == 0) return null; - QualifiedName lastElement = context.ElementPath.Elements[context.ElementPath.Elements.Count - 1]; + QualifiedName lastElement = context.ElementPath.Elements.LastOrDefault(); XamlCompilationUnit cu = parseInfo.BestCompilationUnit as XamlCompilationUnit; if (cu == null) return null; - IReturnType rt = cu.CreateType(lastElement.Namespace, lastElement.Name); + IReturnType rt = cu.CreateType(lastElement.Namespace, lastElement.Name.Trim('.')); if (rt == null) return null; var list = new List(); + + string xamlPrefix = Utils.GetXamlNamespacePrefix(editor.Document.Text, editor.Caret.Offset); + + foreach (string item in xamlNamespaceAttributes) { + if (!existingItems.Contains(xamlPrefix + ":" + item)) + list.Add(new XamlCompletionItem(xamlPrefix, XamlNamespace, item)); + } + foreach (IProperty p in rt.GetProperties()) { if (p.IsPublic && p.CanSet && !existingItems.Contains(p.Name)) { - list.Add(new XamlCompletionItem(p)); + list.Add(new XamlCodeCompletionItem(p)); } } foreach (IEvent e in rt.GetEvents()) { if (e.IsPublic && !existingItems.Contains(e.Name)) { - list.Add(new XamlCompletionItem(e)); + list.Add(new XamlCodeCompletionItem(e)); } } return list; } + public static IEnumerable CreateListForXmlnsCompletion(IProjectContent projectContent) + { + List list = new List(); + + foreach (IProjectContent content in projectContent.ReferencedContents) { + foreach (IAttribute att in content.GetAssemblyAttributes()) { + if (att.PositionalArguments.Count == 2 + && att.AttributeType.FullyQualifiedName == "System.Windows.Markup.XmlnsDefinitionAttribute") { + list.Add(new XmlnsCompletionItem(att.PositionalArguments[0] as string, true)); + } + } + + foreach (string @namespace in content.NamespaceNames) { + if (!string.IsNullOrEmpty(@namespace)) + list.Add(new XmlnsCompletionItem(@namespace, content.AssemblyName)); + } + } + + foreach (string @namespace in projectContent.NamespaceNames) { + if (!string.IsNullOrEmpty(@namespace)) + list.Add(new XmlnsCompletionItem(@namespace, false)); + } + + return list + .Distinct(new XmlnsEqualityComparer()) + .OrderBy(item => item, new XmlnsComparer()) + .Cast(); + } + + sealed class XmlnsEqualityComparer : IEqualityComparer { + public bool Equals(XmlnsCompletionItem x, XmlnsCompletionItem y) + { + return x.Namespace == y.Namespace && x.Assembly == y.Assembly; + } + + public int GetHashCode(XmlnsCompletionItem obj) + { + return string.IsNullOrEmpty(obj.Assembly) ? obj.Namespace.GetHashCode() : obj.Namespace.GetHashCode() ^ obj.Assembly.GetHashCode(); + } + } + + sealed class XmlnsComparer : IComparer { + public int Compare(XmlnsCompletionItem x, XmlnsCompletionItem y) + { + if (x.IsUrl && y.IsUrl) + return x.Namespace.CompareTo(y.Namespace); + if (x.IsUrl) + return -1; + if (y.IsUrl) + return 1; + if (x.Assembly == y.Assembly) + return x.Namespace.CompareTo(y.Namespace); + else + return x.Assembly.CompareTo(y.Assembly); + } + } + static bool IsReaderAtTarget(XmlTextReader r, int caretLine, int caretColumn) { if (r.LineNumber > caretLine) @@ -136,18 +206,18 @@ namespace ICSharpCode.XamlBinding return false; } - public static IList CreateListForElement(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn) + public static IList CreateListForElement(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn, bool addOpeningBrace) { var items = GetClassesFromContext(parseInfo, fileContent, caretLine, caretColumn); var result = new List(); foreach (var ns in items) { - result.AddRange(from c in ns.Value - where (c.ClassType == ClassType.Class && - !c.IsAbstract && !c.IsStatic && - !c.ClassInheritanceTree.Any(b => b.FullyQualifiedName == "System.Attribute") && - c.Methods.Any(m => m.IsConstructor && m.IsPublic)) - select (new XamlCompletionItem(c, ns.Key) as ICompletionItem) + result.AddRange((from c in ns.Value + where (c.ClassType == ClassType.Class && + !c.IsAbstract && !c.IsStatic && + !c.ClassInheritanceTree.Any(b => b.FullyQualifiedName == "System.Attribute") && + c.Methods.Any(m => m.IsConstructor && m.IsPublic)) + select (new XamlCodeCompletionItem(c, ns.Key, addOpeningBrace))).Cast() ); } @@ -156,20 +226,21 @@ namespace ICSharpCode.XamlBinding public static IList CreateListOfMarkupExtensions(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn) { - var list = CreateListForElement(parseInfo, fileContent, caretLine, caretColumn); + var list = CreateListForElement(parseInfo, fileContent, caretLine, caretColumn, false); var neededItems = list - .Where(i => ((i as XamlCompletionItem).Entity as IClass).ClassInheritanceTree + .Where(i => ((i as XamlCodeCompletionItem).Entity as IClass).ClassInheritanceTree .Any(item => item.FullyQualifiedName == "System.Windows.Markup.MarkupExtension")) .Select( selItem => { - var it = selItem as XamlCompletionItem; + var it = selItem as XamlCodeCompletionItem; string text = it.Text; if (it.Text.EndsWith("Extension", StringComparison.Ordinal)) text = text.Remove(it.Text.Length - "Extension".Length); - return new XamlCompletionItem(text, it.Entity) as ICompletionItem; + return new XamlCodeCompletionItem(it.Entity, text); } - ); + ) + .Cast(); return neededItems.ToList(); } @@ -180,13 +251,23 @@ namespace ICSharpCode.XamlBinding ParseInformation info = ParserService.GetParseInformation(editor.FileName); switch (context.Description) { + case XamlContextDescription.None: + if (context.Forced) { + list.Items.AddRange(standardElements.Select(item => new DefaultCompletionItem("<" + item.Text)).Cast()); + list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, true)); + } + break; case XamlContextDescription.AtTag: list.Items.AddRange(standardElements); - list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column)); + if (editor.Document.GetCharAt(editor.Caret.Offset - 1) == '.' || context.PressedKey == '.') { + var existing = Utils.GetListOfExistingAttributeNames(editor.Document.Text, Utils.GetParentElementStart(editor)); + list.Items.AddRange(CreateListForAttributeName(editor, info, new XamlExpressionContext(context.Path, null, false), existing).RemoveEvents()); + } else + list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, false)); break; case XamlContextDescription.InTag: - var existing = Utils.GetListOfExistingAttributeNames(editor.Document.Text, editor.Caret.Offset); - list.Items.AddRange(CreateListForAttributeName(info, new XamlExpressionContext(context.Path, null, false), existing)); + var existingAttribs = Utils.GetListOfExistingAttributeNames(editor.Document.Text, editor.Caret.Offset); + list.Items.AddRange(CreateListForAttributeName(editor, info, new XamlExpressionContext(context.Path, null, false), existingAttribs)); QualifiedName last = context.Path.Elements[context.Path.Elements.Count - 1]; @@ -194,10 +275,11 @@ namespace ICSharpCode.XamlBinding if (trr != null && trr.ResolvedType != null && trr.ResolvedType.GetUnderlyingClass() != null) { if (trr.ResolvedType.GetUnderlyingClass().ClassInheritanceTree.Any(i => i.FullyQualifiedName == "System.Windows.DependencyObject")) { - list.Items.AddRange(GetListOfAttachedProperties(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, existing)); - list.Items.AddRange(GetListOfAttachedEvents(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, existing)); + list.Items.AddRange(GetListOfAttachedProperties(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, existingAttribs)); + list.Items.AddRange(GetListOfAttachedEvents(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, existingAttribs)); } } + list.Items.AddRange(standardAttributes); break; case XamlContextDescription.InAttributeValue: @@ -210,6 +292,20 @@ namespace ICSharpCode.XamlBinding return list; } + static bool FilterCollectionAttributes(ICompletionItem item) + { + if (item is XamlCodeCompletionItem) { + var comItem = item as XamlCodeCompletionItem; + if (comItem.Entity is IProperty) { + var prop = comItem.Entity as IProperty; + var c = prop.ReturnType.GetUnderlyingClass(); + return c != null && c.ClassInheritanceTree.Any(b => b.FullyQualifiedName == "System.Collections.IEnumerable"); + } + } + + return false; + } + public static IEnumerable CreateMarkupExtensionInsight(XamlContext context, ParseInformation info, ITextEditor editor) { var markup = GetInnermostMarkup(context.AttributeValue.ExtensionValue); @@ -259,7 +355,7 @@ namespace ICSharpCode.XamlBinding { var ctors = trr.ResolvedType.GetMethods().Where(m => m.IsConstructor && m.Parameters.Count >= markup.PositionalArguments.Count); if (ctors.Any(ctor => ctor.Parameters.Count >= markup.PositionalArguments.Count)) { - list.Items.AddRange(trr.ResolvedType.GetProperties().Select(p => new XamlCompletionItem(p.Name + "=", p) as ICompletionItem)); + list.Items.AddRange(trr.ResolvedType.GetProperties().Select(p => new XamlCodeCompletionItem(p, p.Name + "=")).Cast()); } } @@ -277,7 +373,7 @@ namespace ICSharpCode.XamlBinding case "System.Windows.Markup.TypeExtension": if (context.AttributeValue.ExtensionValue.PositionalArguments.Count == 1 && context.PressedKey == ' ') break; if (context.AttributeValue.ExtensionValue.PositionalArguments.Count <= 1) { - list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column)); + list.Items.AddRange(CreateListForElement(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column, false)); AttributeValue selItem = context.AttributeValue.ExtensionValue.PositionalArguments.LastOrDefault(); if (selItem != null && selItem.IsString) { string s = selItem.StringValue; @@ -328,7 +424,7 @@ namespace ICSharpCode.XamlBinding switch (c.ClassType) { case ClassType.Enum: foreach (IField f in c.Fields) - yield return new XamlCompletionItem(f); + yield return new XamlCodeCompletionItem(f); break; case ClassType.Struct: if (c.FullyQualifiedName == "System.Boolean") { @@ -343,11 +439,18 @@ namespace ICSharpCode.XamlBinding if (path != null && path.Elements.Count > 0) { var item = path.Elements[path.Elements.Count - 1]; string attribute = XmlParser.GetAttributeNameAtIndex(editor.Document.Text, editor.Caret.Offset); - var e = ResolveAttribute(attribute, editor) as IEvent; - if (e == null) + var evt = ResolveAttribute(attribute, editor) as IEvent; + if (evt == null) break; + + string prefix = Utils.GetXamlNamespacePrefix(editor.Document.Text, editor.Caret.Offset); string name = Utils.GetAttributeValue(editor.Document.Text, editor.Caret.Offset, "name"); - yield return new NewEventCompletionItem(e, (string.IsNullOrEmpty(name)) ? item.Name : name); + if (string.IsNullOrEmpty(name)) + name = Utils.GetAttributeValue(editor.Document.Text, editor.Caret.Offset, (string.IsNullOrEmpty(prefix) ? "" : prefix + ":") + "name"); + + Debug.Print("prefix: " + prefix + " name: " + name); + + yield return new NewEventCompletionItem(evt, (string.IsNullOrEmpty(name)) ? item.Name : name); foreach (var eventItem in CompletionDataHelper.AddMatchingEventHandlers(editor, invoker)) yield return eventItem; @@ -355,6 +458,19 @@ namespace ICSharpCode.XamlBinding } break; } + + switch (c.FullyQualifiedName) { + case "System.Windows.Media.Brush": + foreach (var item in typeof(System.Windows.Media.Brushes).GetProperties()) { + yield return new DefaultCompletionItem(item.Name); + } + break; + case "System.Windows.Media.Color": + foreach (var item in typeof(System.Windows.Media.Colors).GetProperties()) { + yield return new DefaultCompletionItem(item.Name); + } + break; + } } static IEntity ResolveAttribute(string attribute, ITextEditor editor) @@ -401,7 +517,9 @@ namespace ICSharpCode.XamlBinding { var items = GetClassesFromContext(info, editor.Document.Text, editor.Caret.Line, editor.Caret.Column); foreach (var ns in items) { - list.Items.AddRange(ns.Value.Where(c => c.Fields.Any(f => f.IsStatic) || c.Properties.Any(p => p.IsStatic)).Select(c => new XamlCompletionItem(c, ns.Key) as ICompletionItem)); + list.Items.AddRange(ns.Value.Where(c => c.Fields.Any(f => f.IsStatic) || c.Properties.Any(p => p.IsStatic)) + .Select(c => new XamlCodeCompletionItem(c, ns.Key, false)) + .Cast()); } if (selItem != null && selItem.IsString) { string s = selItem.StringValue; @@ -473,7 +591,7 @@ namespace ICSharpCode.XamlBinding break; } if (equal) { - yield return new XamlCompletionItem(m); + yield return new XamlCodeCompletionItem(m); } } } @@ -491,15 +609,35 @@ namespace ICSharpCode.XamlBinding return result; } - static IDictionary> GetClassesFromContext(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn) + static XmlTextReader CreateReaderAtTarget(string fileContent, int caretLine, int caretColumn) + { + XmlTextReader r = new XmlTextReader(new StringReader(fileContent)); + + try { + r.WhitespaceHandling = WhitespaceHandling.Significant; + // move reader to correct position + while (r.Read() && !IsReaderAtTarget(r, caretLine, caretColumn)) { } + } catch (XmlException) {} + + return r; + } + + static string GetPrefixForNamespace(string @namespace, string fileContent, int caretLine, int caretColumn) { - using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) { - try { - r.WhitespaceHandling = WhitespaceHandling.Significant; - // move reader to correct position - while (r.Read() && !IsReaderAtTarget(r, caretLine, caretColumn)) { } - } catch (XmlException) {} + using (XmlTextReader r = CreateReaderAtTarget(fileContent, caretLine, caretColumn)) { + foreach (var item in r.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml)) { + if (item.Value == @namespace) { + return item.Key; + } + } + return string.Empty; + } + } + + static IDictionary> GetClassesFromContext(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn) + { + using (XmlTextReader r = CreateReaderAtTarget(fileContent, caretLine, caretColumn)) { IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent; var result = new Dictionary>(); @@ -514,15 +652,8 @@ namespace ICSharpCode.XamlBinding static List GetListOfAttachedProperties(ParseInformation parseInfo, string fileContent, int caretLine, int caretColumn, string[] existingItems) { - using (XmlTextReader r = new XmlTextReader(new StringReader(fileContent))) { - try { - r.WhitespaceHandling = WhitespaceHandling.Significant; - // move reader to correct position - while (r.Read() && !IsReaderAtTarget(r, caretLine, caretColumn)) { } - } - catch (XmlException) { - } - var result = new List(); + using (XmlTextReader r = CreateReaderAtTarget(fileContent, caretLine, caretColumn)) { + List result = new List(); IProjectContent pc = parseInfo.BestCompilationUnit.ProjectContent; foreach (var ns in r.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml)) { @@ -561,10 +692,11 @@ namespace ICSharpCode.XamlBinding string name = (!string.IsNullOrEmpty(ns.Key)) ? ns.Key + ":" : ""; string property = item.Name.Remove(item.Name.Length - "Property".Length); name += c.Name + "." + item.Name.Remove(item.Name.Length - "Property".Length); - return new XamlCompletionItem(name, new DefaultProperty(c, property) { ReturnType = GetAttachedPropertyType(item, c) } ) as ICompletionItem; + return new XamlCodeCompletionItem(new DefaultProperty(c, property) { ReturnType = GetAttachedPropertyType(item, c) }, name); } ) .Where(item => !existingItems.Any(str => str == item.Text)) + .Cast() ); } } @@ -611,14 +743,15 @@ namespace ICSharpCode.XamlBinding result.AddRange(attachedEvents .Select( - item => new XamlCompletionItem( - (string.IsNullOrEmpty(ns.Key) ? "" : ns.Key + ":") + c.Name + "." + item.Name.Remove(item.Name.Length - "Event".Length), - new DefaultEvent(c, GetEventNameFromField(item)) { - ReturnType = GetAttachedEventDelegateType(item, c) - } - ) as ICompletionItem + item => new XamlCodeCompletionItem( + new DefaultEvent(c, GetEventNameFromField(item)) { + ReturnType = GetAttachedEventDelegateType(item, c) + }, + (string.IsNullOrEmpty(ns.Key) ? "" : ns.Key + ":") + c.Name + "." + item.Name.Remove(item.Name.Length - "Event".Length) + ) ) .Where(item => !existingItems.Any(str => str == item.Text)) + .Cast() ); } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs index fcf47b117b..c419fce30e 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Extensions.cs @@ -5,10 +5,13 @@ // $Revision$ // -using ICSharpCode.SharpDevelop; using System; +using System.Collections.Generic; using System.Linq; + +using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.XmlEditor; namespace ICSharpCode.XamlBinding @@ -36,15 +39,26 @@ namespace ICSharpCode.XamlBinding return false; } - public static QualifiedName LastOrDefault(this QualifiedNameCollection collection) + public static IEnumerable RemoveEvents(this IEnumerable list) { - if (collection == null) - throw new ArgumentNullException("collection"); - - if (collection.Count > 0) - return collection[collection.Count - 1]; - - return null; + foreach (var item in list) { + if (item is XamlCodeCompletionItem) { + var comItem = item as XamlCodeCompletionItem; + if (!(comItem.Entity is IEvent)) + yield return item; + } else yield return item; + } + } + + public static IEnumerable RemoveProperties(this IEnumerable list) + { + foreach (var item in list) { + if (item is XamlCodeCompletionItem) { + var comItem = item as XamlCodeCompletionItem; + if (!(comItem.Entity is IProperty)) + yield return item; + } else yield return item; + } } } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs index 5fccb320e7..9051b4f0e8 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/MarkupExtensionParser.cs @@ -27,6 +27,9 @@ namespace ICSharpCode.XamlBinding info.ExtensionType = token.Value; break; case MarkupExtensionTokenKind.MemberName: + // if there is an open member without a value add the member name + if (argumentName != null) + info.NamedArguments.Add(argumentName, new AttributeValue(string.Empty)); argumentName = token.Value; break; case MarkupExtensionTokenKind.String: diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs index 20f9f7dc92..58ad3bb198 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/Utils.cs @@ -5,13 +5,13 @@ // $Revision$ // +using ICSharpCode.SharpDevelop.Editor; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Xml; - using ICSharpCode.Core; using ICSharpCode.XmlEditor; @@ -64,7 +64,8 @@ namespace ICSharpCode.XamlBinding if (text == null) return null; - XmlReader reader = XmlTextReader.Create(new StringReader(text)); + XmlTextReader reader = new XmlTextReader(new StringReader(text)); + reader.XmlResolver = null; try { reader.ReadToFollowing("Test"); @@ -74,13 +75,14 @@ namespace ICSharpCode.XamlBinding do { LoggingService.Debug("name: " + reader.Name + " value: " + reader.Value); - int start = reader.Name.IndexOf(':') + 1; - string plainName = reader.Name.Substring(start, reader.Name.Length - start).ToUpperInvariant(); + string plainName = reader.Name.ToUpperInvariant(); if (plainName == name.ToUpperInvariant()) return reader.Value; } while (reader.MoveToNextAttribute()); - } catch (XmlException) { } + } catch (XmlException e) { + Debug.Print(e.ToString()); + } return null; } @@ -183,7 +185,12 @@ namespace ICSharpCode.XamlBinding LoggingService.Debug("name: " + reader.Name + " value: " + reader.Value); list.Add(reader.Name); } while (reader.MoveToNextAttribute()); - } catch (XmlException) { } + } catch (XmlException e) { + Debug.Print(e.ToString()); + } + + foreach (var item in list) + Debug.Print(item); return list.ToArray(); } @@ -203,19 +210,34 @@ namespace ICSharpCode.XamlBinding return startIndex; } + + static char[] whitespace = new char[] {' ', '\t', '\n', '\r'}; static string SimplifyToSingleElement(string text, int offset, string name) { int index = XmlParser.GetActiveElementStartIndex(text, offset); if (index == -1) return null; - index = text.IndexOf(' ', index); + index = text.IndexOfAny(whitespace, index); if (index == -1) return null; - text = text.Substring(index); - int endIndex = text.IndexOfAny(new char[] { '<', '>' }); - if (endIndex == -1) return null; - text = text.Substring(0, endIndex).Trim(' ', '\t', '\n', '\r', '/'); - LoggingService.Debug("text: '" + text + "'"); - text = "<" + name + " " + text + " />"; + string newText = text.Substring(index); + int endIndex = newText.IndexOfAny(new char[] { '<', '>' }); + if (endIndex == -1) + endIndex = newText.Length; + newText = newText.Substring(0, endIndex).Trim(' ', '\t', '\n', '\r', '/'); + LoggingService.Debug("text: '" + newText + "'"); + if (!newText.EndsWith("\"") && newText.LastIndexOfAny(whitespace) > -1) { + newText = newText.Substring(0, newText.LastIndexOfAny(whitespace)); + } + + string namespaceDecls = ""; + + var list = Utils.GetXmlNamespacesForOffset(text, offset); + + foreach (var item in list) { + namespaceDecls += item.Key + "=\"" + item.Value + "\" "; + } + + text = "<" + name + " " + newText + " " + namespaceDecls + " />"; return text; } @@ -237,7 +259,7 @@ namespace ICSharpCode.XamlBinding if (offset < 0) throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + (xaml.Length - 1)); - if (offset >= xaml.Length) + if (offset >= xaml.Length && offset > 0) offset = xaml.Length - 1; string interestingPart = xaml.Substring(0, offset); @@ -247,5 +269,29 @@ namespace ICSharpCode.XamlBinding return interestingPart.LastIndexOf("