From 40e5ec6116300cc42d5ebbce9f28532a8787b416 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 23 Aug 2014 16:10:32 +0200 Subject: [PATCH] Fix #518 by re-using the insight window. --- .../Src/CodeCompletionEditorAdapter.cs | 24 +- .../Src/SharpDevelopInsightWindow.cs | 205 ++++++++++++++---- .../Src/SharpDevelopTextEditor.cs | 2 +- .../CodeCompletion/OverloadInsightWindow.cs | 2 +- 4 files changed, 181 insertions(+), 52 deletions(-) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeCompletionEditorAdapter.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeCompletionEditorAdapter.cs index 4c21ee704e..16ef070ad6 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeCompletionEditorAdapter.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeCompletionEditorAdapter.cs @@ -55,20 +55,30 @@ namespace ICSharpCode.AvalonEdit.AddIn { if (items == null) return null; - var insightWindow = new SharpDevelopInsightWindow(this.TextEditor.TextArea); - insightWindow.Items.AddRange(items); - if (insightWindow.Items.Count > 0) { - insightWindow.SelectedItem = insightWindow.Items[0]; + var insightWindow = textEditor.ActiveInsightWindow; + bool isNewWindow = false; + if (insightWindow == null) { + insightWindow = new SharpDevelopInsightWindow(this.TextEditor.TextArea); + isNewWindow = true; + } + var adapter = new SharpDevelopInsightWindowAdapter(insightWindow); + adapter.Items.AddRange(items); + if (adapter.Items.Count > 0) { + adapter.SelectedItem = adapter.Items[0]; } else { // don't open insight window when there are no items return null; } - textEditor.ShowInsightWindow(insightWindow); - return insightWindow; + insightWindow.SetActiveAdapter(adapter, isNewWindow); + if (isNewWindow) + { + textEditor.ShowInsightWindow(insightWindow); + } + return adapter; } public override IInsightWindow ActiveInsightWindow { - get { return textEditor.ActiveInsightWindow; } + get { return textEditor.ActiveInsightWindow.activeAdapter; } } public override ICompletionListWindow ActiveCompletionWindow { diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopInsightWindow.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopInsightWindow.cs index e2a26ad1d5..0bed5d79f2 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopInsightWindow.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopInsightWindow.cs @@ -22,6 +22,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Windows.Threading; using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; @@ -30,17 +31,94 @@ using ICSharpCode.SharpDevelop.Editor.CodeCompletion; namespace ICSharpCode.AvalonEdit.AddIn { + class SharpDevelopInsightWindow : OverloadInsightWindow + { + public SharpDevelopInsightWindow(TextArea textArea) : base(textArea) + { + this.Style = ICSharpCode.Core.Presentation.GlobalStyles.WindowStyle; + AttachEvents(); + } + + internal SharpDevelopInsightWindowAdapter activeAdapter; + + public void SetActiveAdapter(SharpDevelopInsightWindowAdapter adapter, bool isNewWindow) + { + if (activeAdapter != null) { + // tell the previous adapter that its window was closed, + // but actually reuse the window for the new adapter + activeAdapter.OnClosed(); + } + activeAdapter = adapter; + this.Provider = adapter.Provider; + if (!isNewWindow) { + // reset insight window to initial state + CloseAutomatically = true; + StartOffset = EndOffset = this.TextArea.Caret.Offset; + Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(SetPositionToStartOffset)); + } + } + + void SetPositionToStartOffset() + { + if (document != null && this.StartOffset != this.TextArea.Caret.Offset) { + SetPosition(new TextViewPosition(document.GetLocation(this.StartOffset))); + } else { + SetPosition(this.TextArea.Caret.Position); + } + } + + TextDocument document; + Caret caret; + + void AttachEvents() + { + document = this.TextArea.Document; + caret = this.TextArea.Caret; + if (document != null) + document.Changed += document_Changed; + if (caret != null) + caret.PositionChanged += caret_PositionChanged; + this.Closed += OnClosed; + } + + /// + protected override void DetachEvents() + { + if (document != null) + document.Changed -= document_Changed; + if (caret != null) + caret.PositionChanged -= caret_PositionChanged; + this.Closed -= OnClosed; + base.DetachEvents(); + } + + void OnClosed(object sender, EventArgs e) + { + activeAdapter.OnClosed(); + } + + void caret_PositionChanged(object sender, EventArgs e) + { + activeAdapter.OnCaretPositionChanged(e); + } + + void document_Changed(object sender, DocumentChangeEventArgs e) + { + activeAdapter.OnDocumentChanged(e); + } + } + /// /// Adapter between AvalonEdit InsightWindow and SharpDevelop IInsightWindow interface. /// - public class SharpDevelopInsightWindow : OverloadInsightWindow, IInsightWindow + class SharpDevelopInsightWindowAdapter : IInsightWindow { sealed class SDItemProvider : IOverloadProvider { - readonly SharpDevelopInsightWindow insightWindow; + readonly SharpDevelopInsightWindowAdapter insightWindow; int selectedIndex; - public SDItemProvider(SharpDevelopInsightWindow insightWindow) + public SDItemProvider(SharpDevelopInsightWindowAdapter insightWindow) { this.insightWindow = insightWindow; insightWindow.items.CollectionChanged += insightWindow_items_CollectionChanged; @@ -103,16 +181,21 @@ namespace ICSharpCode.AvalonEdit.AddIn } readonly ObservableCollection items = new ObservableCollection(); + SharpDevelopInsightWindow insightWindow; + readonly SDItemProvider provider; - public SharpDevelopInsightWindow(TextArea textArea) : base(textArea) + internal IOverloadProvider Provider { + get { return provider; } + } + + internal SharpDevelopInsightWindowAdapter(SharpDevelopInsightWindow insightWindow) { - this.Provider = new SDItemProvider(this); - this.Provider.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) { + this.insightWindow = insightWindow; + provider = new SDItemProvider(this); + provider.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "SelectedIndex") OnSelectedItemChanged(EventArgs.Empty); }; - this.Style = ICSharpCode.Core.Presentation.GlobalStyles.WindowStyle; - AttachEvents(); } public IList Items { @@ -121,55 +204,28 @@ namespace ICSharpCode.AvalonEdit.AddIn public IInsightItem SelectedItem { get { - int index = this.Provider.SelectedIndex; + int index = provider.SelectedIndex; if (index < 0 || index >= items.Count) return null; else return items[index]; } set { - this.Provider.SelectedIndex = items.IndexOf(value); + provider.SelectedIndex = items.IndexOf(value); OnSelectedItemChanged(EventArgs.Empty); } } - TextDocument document; - Caret caret; IInsightItem oldSelectedItem; - void AttachEvents() - { - document = this.TextArea.Document; - caret = this.TextArea.Caret; - if (document != null) - document.Changed += document_Changed; - if (caret != null) - caret.PositionChanged += caret_PositionChanged; - } + public event EventHandler DocumentChanged; - void caret_PositionChanged(object sender, EventArgs e) - { - OnCaretPositionChanged(e); - } - - /// - protected override void DetachEvents() - { - if (document != null) - document.Changed -= document_Changed; - if (caret != null) - caret.PositionChanged -= caret_PositionChanged; - base.DetachEvents(); - } - - void document_Changed(object sender, DocumentChangeEventArgs e) + internal void OnDocumentChanged(DocumentChangeEventArgs e) { if (DocumentChanged != null) DocumentChanged(this, e); } - public event EventHandler DocumentChanged; - public event EventHandler SelectedItemChanged; protected virtual void OnSelectedItemChanged(EventArgs e) @@ -186,8 +242,6 @@ namespace ICSharpCode.AvalonEdit.AddIn void SelectedItemPropertyChanged(object sender, PropertyChangedEventArgs e) { - var provider = Provider as SDItemProvider; - if (provider == null) return; switch (e.PropertyName) { case "Header": provider.OnPropertyChanged("CurrentHeader"); @@ -199,12 +253,77 @@ namespace ICSharpCode.AvalonEdit.AddIn } public event EventHandler CaretPositionChanged; - - protected virtual void OnCaretPositionChanged(EventArgs e) + + internal void OnCaretPositionChanged(EventArgs e) { if (CaretPositionChanged != null) { CaretPositionChanged(this, e); } } + + public event EventHandler Closed; + + internal void OnClosed() + { + if (Closed != null) + Closed(this, EventArgs.Empty); + insightWindow = null; + } + + public void Close() + { + if (insightWindow != null) + insightWindow.Close(); + } + + public double Width { + get { + return insightWindow != null ? insightWindow.Width : 0; + } + set { + if (insightWindow != null) + insightWindow.Width = value; + } + } + + public double Height { + get { + return insightWindow != null ? insightWindow.Height : 0; + } + set { + if (insightWindow != null) + insightWindow.Height = value; + } + } + + public bool CloseAutomatically { + get { + return insightWindow != null && insightWindow.CloseAutomatically; + } + set { + if (insightWindow != null) + insightWindow.CloseAutomatically = value; + } + } + + public int StartOffset { + get { + return insightWindow != null ? insightWindow.StartOffset : 0; + } + set { + if (insightWindow != null) + insightWindow.StartOffset = value; + } + } + + public int EndOffset { + get { + return insightWindow != null ? insightWindow.EndOffset : 0; + } + set { + if (insightWindow != null) + insightWindow.EndOffset = value; + } + } } } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs index ead5adfe6c..07294e8ff6 100755 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/SharpDevelopTextEditor.cs @@ -97,7 +97,7 @@ namespace ICSharpCode.AvalonEdit.AddIn get { return completionWindow; } } - public SharpDevelopInsightWindow ActiveInsightWindow { + internal SharpDevelopInsightWindow ActiveInsightWindow { get { return insightWindow; } } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/OverloadInsightWindow.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/OverloadInsightWindow.cs index ac192835b4..2ec182ce44 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/OverloadInsightWindow.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/CodeCompletion/OverloadInsightWindow.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.AvalonEdit.CodeCompletion protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); - if (!e.Handled && this.Provider.Count > 1) { + if (!e.Handled && this.Provider != null && this.Provider.Count > 1) { switch (e.Key) { case Key.Up: e.Handled = true;