From 4e45d981656d75f8f37a9bfa6541ea38b6111588 Mon Sep 17 00:00:00 2001 From: Andreas Weizel Date: Tue, 8 Jul 2014 00:15:33 +0200 Subject: [PATCH 01/11] Fix #511: Automatic code formatting grabs closing curly brackets when adding properties --- .../Project/Src/FormattingStrategy/CSharpFormatter.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs index 65bec18aca..92be04e150 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs @@ -31,11 +31,17 @@ namespace CSharpBinding.FormattingStrategy /// public static void Format(ITextEditor editor, int offset, int length, CSharpFormattingOptionsContainer optionsContainer) { + SyntaxTree syntaxTree = SyntaxTree.Parse(editor.Document); + if (syntaxTree.Errors.Count > 0) { + // Don't format files containing syntax errors! + return; + } + TextEditorOptions editorOptions = editor.ToEditorOptions(); optionsContainer.CustomizeEditorOptions(editorOptions); var formatter = new CSharpFormatter(optionsContainer.GetEffectiveOptions(), editorOptions); formatter.AddFormattingRegion(new DomRegion(editor.Document.GetLocation(offset), editor.Document.GetLocation(offset + length))); - var changes = formatter.AnalyzeFormatting(editor.Document, SyntaxTree.Parse(editor.Document)); + var changes = formatter.AnalyzeFormatting(editor.Document, syntaxTree); changes.ApplyChanges(offset, length); } } From ddd2ff1855b90932faa1d3a40952dac3249c129f Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 11 Jul 2014 23:07:20 +0200 Subject: [PATCH 02/11] Fix NullReferenceException in InsertCtorDialog.CreateCtorParams(). --- .../Src/Refactoring/InsertCtorDialog.xaml.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs index 973dbd97c7..274d3b5ed8 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs @@ -63,9 +63,14 @@ namespace CSharpBinding.Refactoring var typeResolveContext = refactoringContext.GetTypeResolveContext(); if (typeResolveContext == null) { + parameterList = EmptyList.Instance; return; } var resolvedCurrent = typeResolveContext.CurrentTypeDefinition; + if (resolvedCurrent == null) { + parameterList = EmptyList.Instance; + return; + } parameterList = CreateCtorParams(resolvedCurrent).ToList(); this.varList.ItemsSource = parameterList; @@ -74,23 +79,17 @@ namespace CSharpBinding.Refactoring Visibility = System.Windows.Visibility.Visible; } - IEnumerable CreateCtorParams(IType sourceType) + IEnumerable CreateCtorParams(ITypeDefinition sourceType) { int i = 0; - foreach (var f in sourceType.GetFields().Where(field => !field.IsConst - && field.IsStatic == sourceType.GetDefinition().IsStatic - && field.DeclaringType.FullName == sourceType.FullName - && field.ReturnType != null)) { + foreach (var f in sourceType.Fields.Where(f => !f.IsStatic)) { yield return new PropertyOrFieldWrapper(f) { Index = i }; i++; } - foreach (var p in sourceType.GetProperties().Where(prop => prop.CanSet && !prop.IsIndexer - && prop.IsAutoImplemented() - && prop.IsStatic == sourceType.GetDefinition().IsStatic - && prop.DeclaringType.FullName == sourceType.FullName - && prop.ReturnType != null)) { + foreach (var p in sourceType.Properties.Where(prop => !prop.IsStatic && prop.CanSet + && !prop.IsIndexer && prop.IsAutoImplemented())) { yield return new PropertyOrFieldWrapper(p) { Index = i }; i++; } From f1894f80f519f9788b77a9e0bcebff4d1f1662d1 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 13 Jul 2014 10:58:47 +0200 Subject: [PATCH 03/11] fix #179: "navigate to file in project browser" does not work all the times --- .../ProjectBrowser/ProjectBrowserControl.cs | 74 ++++++++++++------- .../TreeNodes/SolutionItemNode.cs | 1 + 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserControl.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserControl.cs index 012b101e55..4cd0081d21 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserControl.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/ProjectBrowserControl.cs @@ -17,8 +17,11 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.IO; +using System.Linq; using System.Windows.Forms; using ICSharpCode.Core; @@ -249,37 +252,58 @@ namespace ICSharpCode.SharpDevelop.Project try { inSelectFile = true; lastSelectionTarget = fileName; - TreeNode node = FindFileNode(fileName); - - if (node != null) { - // Expand to node - TreeNode parent = node.Parent; - while (parent != null) { - parent.Expand(); - parent = parent.Parent; - } - //node = FindFileNode(fileName); - treeView.SelectedNode = node; - } else { - // Node for this file does not exist yet (the tree view is lazy loaded) - SelectDeepestOpenNodeForPath(fileName); - } + LoadAndExpandToNode(new FileName(fileName)); } finally { inSelectFile = false; } } #region SelectDeepestOpenNode internals -// -// SolutionNode RootSolutionNode { -// get { -// if (treeView.Nodes != null && treeView.Nodes.Count>0) { -// return treeView.Nodes[0] as SolutionNode; -// } -// return null; -// } -// } -// + + void LoadAndExpandToNode(FileName fileName) + { + IProject project = null; + if (!SD.ProjectService.IsSolutionOrProjectFile(fileName)) { + project = SD.ProjectService.FindProjectContainingFile(fileName); + } + Stack itemsToExpand = new Stack(); + ISolutionItem item = project; + if (project == null) { + item = SD.ProjectService.CurrentSolution.AllItems + .OfType().FirstOrDefault(i => i.FileName.Equals(fileName)); + } + while (item != null) { + itemsToExpand.Push(item); + item = item.ParentFolder; + } + AbstractProjectBrowserTreeNode current = null; + var currentChildren = treeView.Nodes; + while (itemsToExpand.Any()) { + var currentItem = itemsToExpand.Pop(); + current = currentChildren.OfType().FirstOrDefault(n => n.Tag == currentItem); + if (current == null) break; + current.Expand(); + currentChildren = current.Nodes; + } + if (project != null) { + var fileItem = project.FindFile(fileName); + var virtualPath = fileItem.VirtualName; + if (!string.IsNullOrWhiteSpace(fileItem.DependentUpon)) { + int index = virtualPath.LastIndexOf('\\') + 1; + virtualPath = virtualPath.Insert(index, fileItem.DependentUpon + "\\"); + } + string[] relativePath = virtualPath.Split('\\'); + for (int i = 0; i < relativePath.Length; i++) { + current = currentChildren.OfType() + .FirstOrDefault(n => n.Text.Equals(relativePath[i], StringComparison.OrdinalIgnoreCase)); + if (current == null) break; + current.Expand(); + currentChildren = current.Nodes; + } + } + treeView.SelectedNode = current; + } + void SelectDeepestOpenNodeForPath(string fileName) { TreeNode node = FindDeepestOpenNodeForPath(fileName); diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionItemNode.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionItemNode.cs index 56e8359c6a..c4ec929e73 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionItemNode.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/SolutionItemNode.cs @@ -51,6 +51,7 @@ namespace ICSharpCode.SharpDevelop.Project this.solution = item.ParentSolution; this.item = item; this.Text = Path.GetFileName(FileName); + this.Tag = item; SetIcon(IconService.GetImageForFile(FileName)); } From 14dc190f94bb1ad16a4b0643bf6acaf328c1ec47 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 13 Jul 2014 12:31:34 +0200 Subject: [PATCH 04/11] Fix SymbolCollector not returning a member when it was implementing interface members. --- .../ICSharpCode.NRefactory/Analysis/SymbolCollector.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs index e63b616389..1db8836a1d 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs @@ -120,12 +120,10 @@ namespace ICSharpCode.NRefactory.Analysis case SymbolKind.Method: { var member = (IMember)m; List symbols = new List (); - if (member.ImplementedInterfaceMembers.Count > 0) { - foreach (var m2 in member.ImplementedInterfaceMembers) { - symbols.AddRange (GetRelatedSymbols (g, m2)); - } - } else { + if (!member.IsExplicitInterfaceImplementation) symbols.Add (member); + foreach (var m2 in member.ImplementedInterfaceMembers) { + symbols.AddRange (GetRelatedSymbols (g, m2)); } if (member.DeclaringType.Kind == TypeKind.Interface) { From bede4f6643887c59616ae984b76888c60f53a96a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 13 Jul 2014 12:41:14 +0200 Subject: [PATCH 05/11] Make SymbolCollector take a Lazy - it's expensive to construct and only used for some members. --- .../Project/Src/Parser/CSharpSymbolSearch.cs | 2 +- .../Analysis/SymbolCollectorTests.cs | 2 +- .../CSharp/Resolver/FindReferencesTest.cs | 2 +- .../Analysis/SymbolCollector.cs | 18 +++++++++++------- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs index fbd05adfc5..6d21e0bb23 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs @@ -87,7 +87,7 @@ namespace CSharpBinding IEnumerable GetRelatedSymbols(ISymbol entity) { - TypeGraph typeGraph = new TypeGraph(new [] { compilation.MainAssembly }); + var typeGraph = new Lazy(() => new TypeGraph(new [] { compilation.MainAssembly })); var symbolCollector = new SymbolCollector(); return symbolCollector.GetRelatedSymbols(typeGraph, entity); } diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Analysis/SymbolCollectorTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Analysis/SymbolCollectorTests.cs index 8bf4338ff8..6ca6161415 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Analysis/SymbolCollectorTests.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Analysis/SymbolCollectorTests.cs @@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.Analysis col.IncludeOverloads = includeOverloads; col.GroupForRenaming = true; - var result = col.GetRelatedSymbols (new TypeGraph (compilation.Assemblies), + var result = col.GetRelatedSymbols (new Lazy(() => new TypeGraph (compilation.Assemblies)), symbol); if (offsets.Count != result.Count()) { foreach (var a in result) diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs index e9cdc98d31..8a1470f232 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs @@ -469,7 +469,7 @@ namespace Foo { var sym = GetSymbol(compilation, fullyQualifiedName); Assert.NotNull(sym); - var graph = new TypeGraph(compilation.Assemblies); + var graph = new Lazy(() => new TypeGraph(compilation.Assemblies)); var col = new SymbolCollector(); col.IncludeOverloads = includeOverloads; col.GroupForRenaming = true; diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs index 1db8836a1d..6fa9128292 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Analysis/SymbolCollector.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.Analysis } } - static IEnumerable CollectOverloads (TypeGraph g, IMethod method) + static IEnumerable CollectOverloads (IMethod method) { return method.DeclaringType .GetMethods (m => m.Name == method.Name) @@ -85,7 +85,7 @@ namespace ICSharpCode.NRefactory.Analysis /// The related symbols. /// The type graph. /// The symbol to search - public IEnumerable GetRelatedSymbols(TypeGraph g, ISymbol m) + public IEnumerable GetRelatedSymbols(Lazy g, ISymbol m) { switch (m.SymbolKind) { case SymbolKind.TypeDefinition: @@ -103,7 +103,7 @@ namespace ICSharpCode.NRefactory.Analysis return GetRelatedSymbols (g, ((IMethod)m).DeclaringTypeDefinition); List constructorSymbols = new List (); if (IncludeOverloads) { - foreach (var m3 in CollectOverloads (g, (IMethod)m)) { + foreach (var m3 in CollectOverloads ((IMethod)m)) { constructorSymbols.Add (m3); } } @@ -122,12 +122,16 @@ namespace ICSharpCode.NRefactory.Analysis List symbols = new List (); if (!member.IsExplicitInterfaceImplementation) symbols.Add (member); - foreach (var m2 in member.ImplementedInterfaceMembers) { - symbols.AddRange (GetRelatedSymbols (g, m2)); + if (GroupForRenaming) { + foreach (var m2 in member.ImplementedInterfaceMembers) { + symbols.AddRange (GetRelatedSymbols (g, m2)); + } + } else { + symbols.AddRange(member.ImplementedInterfaceMembers); } if (member.DeclaringType.Kind == TypeKind.Interface) { - var declaringTypeNode = g.GetNode(member.DeclaringTypeDefinition); + var declaringTypeNode = g.Value.GetNode(member.DeclaringTypeDefinition); if (declaringTypeNode != null) { foreach (var derivedType in declaringTypeNode.DerivedTypes) { var mem = SearchMember (derivedType.TypeDefinition, member); @@ -141,7 +145,7 @@ namespace ICSharpCode.NRefactory.Analysis if (IncludeOverloads) { IncludeOverloads = false; if (member is IMethod) { - foreach (var m3 in CollectOverloads (g, (IMethod)member)) { + foreach (var m3 in CollectOverloads ((IMethod)member)) { symbols.AddRange (GetRelatedSymbols (g, m3)); } } else if (member.SymbolKind == SymbolKind.Indexer) { From ae692d51b7c9adea589aecfbf2c22c6c541509a8 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 13 Jul 2014 12:56:16 +0200 Subject: [PATCH 06/11] Fix #284 NotSupportedException thrown in NR CecilLoader --- .../ICSharpCode.NRefactory.Cecil/CecilLoader.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Cecil/CecilLoader.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Cecil/CecilLoader.cs index 92f642c2a9..123f810aa2 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Cecil/CecilLoader.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Cecil/CecilLoader.cs @@ -824,7 +824,13 @@ namespace ICSharpCode.NRefactory.TypeSystem void AddSecurityAttributes(SecurityDeclaration secDecl, IList targetCollection) { - var blobSecDecl = new UnresolvedSecurityDeclarationBlob((int)secDecl.Action, secDecl.GetBlob()); + byte[] blob; + try { + blob = secDecl.GetBlob(); + } catch (NotSupportedException) { + return; // https://github.com/icsharpcode/SharpDevelop/issues/284 + } + var blobSecDecl = new UnresolvedSecurityDeclarationBlob((int)secDecl.Action, blob); targetCollection.AddRange(blobSecDecl.UnresolvedAttributes); } #endregion From c92e695a20690495d2d8a5debefb2a71acfda1cb Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 13 Jul 2014 17:24:38 +0200 Subject: [PATCH 07/11] assign ParentProject of SD BuildErrors --- .../Project/Build/MSBuildEngine/MSBuildEngineWorker.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Main/SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngineWorker.cs b/src/Main/SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngineWorker.cs index 582bff0b94..15a9ef4793 100644 --- a/src/Main/SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngineWorker.cs +++ b/src/Main/SharpDevelop/Project/Build/MSBuildEngine/MSBuildEngineWorker.cs @@ -313,6 +313,7 @@ namespace ICSharpCode.SharpDevelop.Project error.IsWarning = isWarning; error.Subcategory = subcategory; error.HelpKeyword = helpKeyword; + error.ParentProject = engine.Project; engine.loggerChain.HandleError(error); } From 4ac976c1f26d32b891a9be95fe2ffbd04e9e6597 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 13 Jul 2014 17:25:34 +0200 Subject: [PATCH 08/11] fix #515: Could not find class for token exception when stepping into code --- .../Debugger/Debugger.Core/TypeSystemExtensions.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs b/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs index 8b236807be..fec6bd7158 100644 --- a/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs +++ b/src/AddIns/Debugger/Debugger.Core/TypeSystemExtensions.cs @@ -155,6 +155,12 @@ namespace Debugger string name = corModule.GetName(); if (corModule.IsDynamic() == 1 || corModule.IsInMemory() == 1) { var defaultUnresolvedAssembly = new DefaultUnresolvedAssembly(name); + var defaultUnresolvedTypeDefinition = new DefaultUnresolvedTypeDefinition("UnknownDynamicType"); + var defaultUnresolvedMethod = new DefaultUnresolvedMethod(defaultUnresolvedTypeDefinition, "UnknownMethod"); + var defaultUnresolvedField = new DefaultUnresolvedField(defaultUnresolvedTypeDefinition, "UnknownField"); + defaultUnresolvedTypeDefinition.Members.Add(defaultUnresolvedMethod); + defaultUnresolvedTypeDefinition.Members.Add(defaultUnresolvedField); + defaultUnresolvedAssembly.AddTypeDefinition(defaultUnresolvedTypeDefinition); weakTable.Add(defaultUnresolvedAssembly, new ModuleMetadataInfo(module, null)); return Task.FromResult(defaultUnresolvedAssembly); } @@ -527,6 +533,9 @@ namespace Debugger public static IMethod Import(this ICompilation compilation, ICorDebugFunction corFunction) { Module module = compilation.GetAppDomain().Process.GetModule(corFunction.GetModule()); + if (module.IsDynamic || module.IsInMemory) { + return module.Assembly.GetTypeDefinition("", "UnknownDynamicType").Methods.First(); + } var info = GetInfo(module.Assembly); uint functionToken = corFunction.GetToken(); var unresolvedMethod = info.GetMethodFromToken(functionToken); @@ -547,6 +556,9 @@ namespace Debugger public static IField ImportField(this IType declaringType, uint fieldToken) { var module = declaringType.GetDefinition().ParentAssembly.GetModule(); + if (module.IsDynamic || module.IsInMemory) { + return module.Assembly.GetTypeDefinition("", "UnknownDynamicType").Fields.First(); + } var info = GetInfo(module.Assembly); return declaringType.GetFields(f => info.GetMetadataToken(f) == fieldToken, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault(); } From 3b9b2ac5885747e672a5c350508e98bd95a54682 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 13 Jul 2014 18:16:40 +0200 Subject: [PATCH 09/11] fix #496: ContextActionBulbControl: it should always be displayed inside the editor's view port bounds --- .../AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs | 6 ++++-- src/Main/Base/Project/Editor/IEditorUIService.cs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs index 1e92947da4..2ff4906a43 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditEditorUIService.cs @@ -67,8 +67,10 @@ namespace ICSharpCode.AvalonEdit.AddIn /// public Point GetScreenPosition(int line, int column) { - var positionInPixels = textView.PointToScreen( - textView.GetVisualPosition(new TextViewPosition(line, column), VisualYPosition.LineBottom) - textView.ScrollOffset); + var visualPosition = textView.GetVisualPosition( + new TextViewPosition(line, column), VisualYPosition.LineBottom) - textView.ScrollOffset; + var positionInPixels = textView.PointToScreen(new Point(visualPosition.X.CoerceValue(0, textView.ActualWidth), + visualPosition.Y.CoerceValue(0, textView.ActualHeight))); return positionInPixels.TransformFromDevice(textView); } diff --git a/src/Main/Base/Project/Editor/IEditorUIService.cs b/src/Main/Base/Project/Editor/IEditorUIService.cs index 011dc9a206..1acf5dd07e 100644 --- a/src/Main/Base/Project/Editor/IEditorUIService.cs +++ b/src/Main/Base/Project/Editor/IEditorUIService.cs @@ -37,6 +37,8 @@ namespace ICSharpCode.SharpDevelop.Editor /// /// Gets the absolute screen position of given position in the document. + /// If the position is outside of the currently visible portion of the document, + /// the value is forced into the viewport bounds. /// Point GetScreenPosition(int line, int column); From fc284a5d164839cf2fef9228f7acfd358a724401 Mon Sep 17 00:00:00 2001 From: Andreas Weizel Date: Mon, 14 Jul 2014 00:46:02 +0200 Subject: [PATCH 10/11] Part of #234: Keyboard shortcuts now working in XmlEditor's tree view. --- .../Src/XmlTreeViewContainerControl.cs | 17 ++++-- .../Project/Src/XmlTreeViewControl.cs | 52 ++++++++++++------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs index 9ccb6a1eac..202464e075 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewContainerControl.cs @@ -667,11 +667,20 @@ namespace ICSharpCode.XmlEditor } /// - /// Deletes the selected node. + /// Handles a keyboard press event in tree view. /// - protected void XmlElementTreeViewDeleteKeyPressed(object source, EventArgs e) + protected void XmlElementTreeViewKeyPressed(object source, XmlTreeViewKeyPressedEventArgs e) { - Delete(); + if (e.KeyData == Keys.Delete) + Delete(); + else if (e.KeyData == (Keys.Control | Keys.C)) + Copy(); + else if (e.KeyData == (Keys.Control | Keys.X)) + Cut(); + else if (e.KeyData == (Keys.Control | Keys.V)) + Paste(); + else if (e.KeyData == (Keys.Control | Keys.A)) + SelectAll(); } #region Forms Designer generated code @@ -738,7 +747,7 @@ namespace ICSharpCode.XmlEditor this.xmlElementTreeView.Size = new System.Drawing.Size(185, 326); this.xmlElementTreeView.TabIndex = 0; this.xmlElementTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.XmlElementTreeViewAfterSelect); - this.xmlElementTreeView.DeleteKeyPressed += new System.EventHandler(this.XmlElementTreeViewDeleteKeyPressed); + this.xmlElementTreeView.TreeViewKeyPressed += this.XmlElementTreeViewKeyPressed; // // attributesGrid // diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewControl.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewControl.cs index 0cf244fad8..2f9840ec4b 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewControl.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlTreeViewControl.cs @@ -26,13 +26,27 @@ using ICSharpCode.SharpDevelop.Gui; namespace ICSharpCode.XmlEditor { + public class XmlTreeViewKeyPressedEventArgs : EventArgs + { + public XmlTreeViewKeyPressedEventArgs(Keys keyData) + { + KeyData = keyData; + } + + public Keys KeyData + { + get; + private set; + } + } + /// /// Displays a tree of XML elements. This is a separate control so it can /// be unit tested. It has no SharpDevelop specific parts, for example, /// the context menus are defined in the XmlTreeViewContainerControl. /// public class XmlTreeViewControl : ExtTreeView - { + { const string ViewStatePropertyName = "XmlTreeViewControl.ViewState"; XmlDocument document; @@ -43,9 +57,9 @@ namespace ICSharpCode.XmlEditor } /// - /// Raised when the delete key is pressed. + /// Raised when some key in tree view is pressed. /// - public event EventHandler DeleteKeyPressed; + public event EventHandler TreeViewKeyPressed; public XmlTreeViewControl() { @@ -98,7 +112,7 @@ namespace ICSharpCode.XmlEditor /// Gets the selected text node in the tree. /// public XmlText SelectedTextNode { - get { + get { XmlTextTreeNode xmlTextTreeNode = SelectedNode as XmlTextTreeNode; if (xmlTextTreeNode != null) { return xmlTextTreeNode.XmlText; @@ -106,12 +120,12 @@ namespace ICSharpCode.XmlEditor return null; } } - + /// /// Gets the selected comment node in the tree. /// public XmlComment SelectedComment { - get { + get { XmlCommentTreeNode commentTreeNode = SelectedNode as XmlCommentTreeNode; if (commentTreeNode != null) { return commentTreeNode.XmlComment; @@ -230,7 +244,7 @@ namespace ICSharpCode.XmlEditor } /// - /// Updates the corresponding tree node's text based on + /// Updates the corresponding tree node's text based on /// the textNode's value. /// public void UpdateTextNode(XmlText textNode) @@ -240,9 +254,9 @@ namespace ICSharpCode.XmlEditor node.Update(); } } - + /// - /// Updates the corresponding tree node's text based on + /// Updates the corresponding tree node's text based on /// the comment's value. /// public void UpdateComment(XmlComment comment) @@ -314,7 +328,7 @@ namespace ICSharpCode.XmlEditor } /// - /// If no node is selected after a mouse click then we make + /// If no node is selected after a mouse click then we make /// sure the AfterSelect event is fired. Standard behaviour is /// for the AfterSelect event not to be fired when the user /// deselects all tree nodes. @@ -332,8 +346,8 @@ namespace ICSharpCode.XmlEditor /// protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { - if (keyData == Keys.Delete && DeleteKeyPressed != null) { - DeleteKeyPressed(this, new EventArgs()); + if (/*keyData == Keys.Delete && */TreeViewKeyPressed != null) { + TreeViewKeyPressed(this, new XmlTreeViewKeyPressedEventArgs(keyData)); } return base.ProcessCmdKey(ref msg, keyData); } @@ -370,7 +384,7 @@ namespace ICSharpCode.XmlEditor } /// - /// Inserts a new element node either before or after the + /// Inserts a new element node either before or after the /// currently selected element node. /// void InsertElement(XmlElement element, InsertionMode insertionMode) @@ -388,7 +402,7 @@ namespace ICSharpCode.XmlEditor } /// - /// Inserts a new text node either before or after the + /// Inserts a new text node either before or after the /// currently selected node. /// void InsertTextNode(XmlText textNode, InsertionMode insertionMode) @@ -406,7 +420,7 @@ namespace ICSharpCode.XmlEditor } /// - /// Inserts a new comment node either before or after the + /// Inserts a new comment node either before or after the /// currently selected node. /// void InsertComment(XmlComment comment, InsertionMode insertionMode) @@ -541,7 +555,7 @@ namespace ICSharpCode.XmlEditor } /// - /// Shows the corresponding tree node with the ghosted image + /// Shows the corresponding tree node with the ghosted image /// that indicates it is being cut. /// void ShowCutElement(XmlElement element, bool showGhostImage) @@ -551,7 +565,7 @@ namespace ICSharpCode.XmlEditor } /// - /// Shows the corresponding tree node with the ghosted image + /// Shows the corresponding tree node with the ghosted image /// that indicates it is being cut. /// void ShowCutTextNode(XmlText textNode, bool showGhostImage) @@ -559,9 +573,9 @@ namespace ICSharpCode.XmlEditor XmlTextTreeNode node = FindTextNode(textNode); node.ShowGhostImage = showGhostImage; } - + /// - /// Shows the corresponding tree node with the ghosted image + /// Shows the corresponding tree node with the ghosted image /// that indicates it is being cut. /// void ShowCutComment(XmlComment comment, bool showGhostImage) From 4329ac17114eaef710dd786afab262822a18f356 Mon Sep 17 00:00:00 2001 From: Andreas Weizel Date: Mon, 14 Jul 2014 01:53:53 +0200 Subject: [PATCH 11/11] Fixed XmlEditor tests. --- .../Test/Tree/DeleteTreeNodeWithDeleteKeyTestFixture.cs | 2 +- .../Test/Utils/DerivedXmlTreeViewContainerControl.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AddIns/DisplayBindings/XmlEditor/Test/Tree/DeleteTreeNodeWithDeleteKeyTestFixture.cs b/src/AddIns/DisplayBindings/XmlEditor/Test/Tree/DeleteTreeNodeWithDeleteKeyTestFixture.cs index f4d66450ed..e729cf5e57 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Test/Tree/DeleteTreeNodeWithDeleteKeyTestFixture.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Test/Tree/DeleteTreeNodeWithDeleteKeyTestFixture.cs @@ -36,7 +36,7 @@ namespace XmlEditor.Tests.Tree public void DeleteKeyPressed() { using (DerivedXmlTreeViewControl treeView = new DerivedXmlTreeViewControl()) { - treeView.DeleteKeyPressed += TreeViewDeleteKeyPressed; + treeView.TreeViewKeyPressed += TreeViewDeleteKeyPressed; treeView.CallProcessCmdKey(Keys.Delete); } Assert.IsTrue(deleteKeyPressEventFired); diff --git a/src/AddIns/DisplayBindings/XmlEditor/Test/Utils/DerivedXmlTreeViewContainerControl.cs b/src/AddIns/DisplayBindings/XmlEditor/Test/Utils/DerivedXmlTreeViewContainerControl.cs index 2dc02aab78..bda239d255 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Test/Utils/DerivedXmlTreeViewContainerControl.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Test/Utils/DerivedXmlTreeViewContainerControl.cs @@ -81,12 +81,12 @@ namespace XmlEditor.Tests.Utils /// /// Allows us to call the XmlTreeViewContainer's - /// XmlElementTreeViewDeleteKeyPressed method to fake the user + /// XmlElementTreeViewKeyPressed method to fake the user /// pressing the delete key in the xml tree view control. /// public void CallXmlElementTreeViewDeleteKeyPressed() { - base.XmlElementTreeViewDeleteKeyPressed(this, new EventArgs()); + base.XmlElementTreeViewKeyPressed(this, new XmlTreeViewKeyPressedEventArgs(Keys.Delete)); } ///