From 24d3478ae85b629f6c1fce9675203386fe03423e Mon Sep 17 00:00:00 2001 From: WMJ Date: Wed, 31 Mar 2021 20:39:28 +0800 Subject: [PATCH] - Fixed #135 (NaviBar got broken after splitting window) --- Codist/NaviBar/CSharpBar.cs | 33 +++++++++++++++++++++----------- Codist/NaviBar/MarkdownBar.cs | 18 +++++++++++++---- Codist/NaviBar/NaviBar.cs | 5 ++++- Codist/NaviBar/NaviBarFactory.cs | 29 ++++++++++++++++------------ Codist/SmartBars/SmartBar.cs | 2 +- 5 files changed, 58 insertions(+), 29 deletions(-) diff --git a/Codist/NaviBar/CSharpBar.cs b/Codist/NaviBar/CSharpBar.cs index e2cae36d..5a369a48 100644 --- a/Codist/NaviBar/CSharpBar.cs +++ b/Codist/NaviBar/CSharpBar.cs @@ -28,7 +28,7 @@ public sealed class CSharpBar : NaviBar static string __ProjectWideSearchExpression; readonly IAdornmentLayer _SyntaxNodeRangeAdornment; - readonly SemanticContext _SemanticContext; + SemanticContext _SemanticContext; readonly RootItem _RootItem; CancellationTokenSource _cancellationSource = new CancellationTokenSource(); @@ -36,16 +36,12 @@ public sealed class CSharpBar : NaviBar SymbolList _SymbolList; ThemedImageButton _ActiveItem; - public CSharpBar(IWpfTextView textView) : base(textView) { + public CSharpBar(IWpfTextView view) : base(view) { _SyntaxNodeRangeAdornment = View.GetAdornmentLayer(SyntaxNodeRange); - _SemanticContext = SemanticContext.GetOrCreateSingetonInstance(textView); Name = nameof(CSharpBar); + BindView(view); Items.Add(_RootItem = new RootItem(this)); - View.Closed += ViewClosed; - View.TextBuffer.Changed += TextBuffer_Changed; - View.Selection.SelectionChanged += Update; ListContainer.ChildRemoved += ListContainer_MenuRemoved; - Config.Updated += Config_Updated; Update(this, EventArgs.Empty); } @@ -88,6 +84,24 @@ protected override void OnMouseMove(MouseEventArgs e) { } } + internal protected override void BindView(IWpfTextView view) { + UnbindViewEvents(); + View = view; + View.Closed += ViewClosed; + View.TextBuffer.Changed += TextBuffer_Changed; + View.Selection.SelectionChanged += Update; + Config.Updated += Config_Updated; + SyncHelper.CancelAndDispose(ref _cancellationSource, true); + _SemanticContext = SemanticContext.GetOrCreateSingetonInstance(view); + } + + protected override void UnbindViewEvents() { + View.Selection.SelectionChanged -= Update; + View.TextBuffer.Changed -= TextBuffer_Changed; + Config.Updated -= Config_Updated; + View.Closed -= ViewClosed; + } + void HighlightNodeRanges(SyntaxNode node, SnapshotSpan span) { _SyntaxNodeRangeAdornment.AddAdornment(span, null, new GeometryAdornment(ThemeHelper.MenuHoverBackgroundColor, View.TextViewLines.GetMarkerGeometry(span), 3)); var p = View.Caret.Position.BufferPosition; @@ -241,11 +255,8 @@ async Task> UpdateModelAndGetContainingNodesAsync(Can } void ViewClosed(object sender, EventArgs e) { - View.Selection.SelectionChanged -= Update; - View.TextBuffer.Changed -= TextBuffer_Changed; - Config.Updated -= Config_Updated; + UnbindViewEvents(); SyncHelper.CancelAndDispose(ref _cancellationSource, false); - View.Closed -= ViewClosed; } void Config_Updated(object sender, ConfigUpdatedEventArgs e) { diff --git a/Codist/NaviBar/MarkdownBar.cs b/Codist/NaviBar/MarkdownBar.cs index 577956d3..97d8c542 100644 --- a/Codist/NaviBar/MarkdownBar.cs +++ b/Codist/NaviBar/MarkdownBar.cs @@ -43,9 +43,7 @@ public MarkdownBar(IWpfTextView view, ITextSearchService2 textSearch) : base(vie _TextSearch = textSearch; _Tags = view.Properties.GetProperty(typeof(TaggerResult)); Name = nameof(MarkdownBar); - view.Selection.SelectionChanged += Update; - view.TextBuffer.PostChanged += Update; - view.Closed += View_Closed; + BindView(view); _ActiveTitleLabel = new ThemedToolBarText(DefaultActiveTitle); _ActiveItem = new ThemedImageButton(IconIds.Headings, _ActiveTitleLabel); _ActiveItem.Click += ShowTitleList; @@ -57,12 +55,24 @@ public MarkdownBar(IWpfTextView view, ITextSearchService2 textSearch) : base(vie //AddItem(KnownImageIds.StrikeThrough, ToggleStrikeThrough); } - void View_Closed(object sender, EventArgs e) { + protected internal override void BindView(IWpfTextView view) { + UnbindViewEvents(); + View = view; + View.Selection.SelectionChanged += Update; + View.TextBuffer.PostChanged += Update; + View.Closed += View_Closed; + } + + protected override void UnbindViewEvents() { View.Closed -= View_Closed; View.Selection.SelectionChanged -= Update; View.TextBuffer.PostChanged -= Update; } + void View_Closed(object sender, EventArgs e) { + UnbindViewEvents(); + } + void Update(object sender, EventArgs e) { HideMenu(); _ActiveTitleLabel.Text = _Tags.GetPreceedingTaggedSpan(View.GetCaretPosition().Position)?.ContentText ?? DefaultActiveTitle; diff --git a/Codist/NaviBar/NaviBar.cs b/Codist/NaviBar/NaviBar.cs index 480542c0..5db2d958 100644 --- a/Codist/NaviBar/NaviBar.cs +++ b/Codist/NaviBar/NaviBar.cs @@ -23,7 +23,10 @@ protected NaviBar(IWpfTextView textView) { public abstract void ShowActiveItemMenu(); public abstract void ShowRootItemMenu(int parameter); - protected IWpfTextView View { get; } + internal protected abstract void BindView(IWpfTextView view); + protected abstract void UnbindViewEvents(); + + protected IWpfTextView View { get; set; } internal ExternalAdornment ListContainer { get; } protected override void OnPreviewMouseRightButtonUp(MouseButtonEventArgs e) { diff --git a/Codist/NaviBar/NaviBarFactory.cs b/Codist/NaviBar/NaviBarFactory.cs index 68fb511d..ded60f45 100644 --- a/Codist/NaviBar/NaviBarFactory.cs +++ b/Codist/NaviBar/NaviBarFactory.cs @@ -89,20 +89,25 @@ public Overrider(IWpfTextView view, ITextSearchService2 textSearch) { void AddNaviBar(object sender, RoutedEventArgs e) { _View.VisualElement.Loaded -= AddNaviBar; - var view = sender as FrameworkElement; - var naviBar = view + var view = sender as IWpfTextView ?? _View; + NaviBar naviBar; + if ((naviBar = view.VisualElement?.GetParent().GetFirstVisualChild()) != null) { + naviBar.BindView(view); + return; + } + var naviBarHolder = view.VisualElement ?.GetParent(b => b.Name == "PART_ContentPanel") ?.GetFirstVisualChild(b => b.Name == "DropDownBarMargin"); - if (naviBar == null) { - var naviBarHolder = view.GetParent(b => b.GetType().Name == "WpfMultiViewHost"); - if (naviBarHolder != null) { + if (naviBarHolder == null) { + var viewHost = view.VisualElement.GetParent(b => b.GetType().Name == "WpfMultiViewHost"); + if (viewHost != null) { var b = new MarkdownBar(_View, _TextSearch); DockPanel.SetDock(b, Dock.Top); - if (naviBarHolder.Children.Count == 1) { - naviBarHolder.Children.Insert(0, b); + if (viewHost.Children.Count == 1) { + viewHost.Children.Insert(0, b); } else { - var c = naviBarHolder.Children[0] as ContentControl; + var c = viewHost.Children[0] as ContentControl; if (c != null && c.Content == null) { c.Content = b; } @@ -110,8 +115,8 @@ void AddNaviBar(object sender, RoutedEventArgs e) { } return; } - var dropDown1 = naviBar.GetFirstVisualChild(c => c.Name == "DropDown1"); - var dropDown2 = naviBar.GetFirstVisualChild(c => c.Name == "DropDown2"); + var dropDown1 = naviBarHolder.GetFirstVisualChild(c => c.Name == "DropDown1"); + var dropDown2 = naviBarHolder.GetFirstVisualChild(c => c.Name == "DropDown2"); if (dropDown1 == null || dropDown2 == null) { return; } @@ -127,7 +132,7 @@ void AddNaviBar(object sender, RoutedEventArgs e) { container.Children.Add(bar); dropDown1.Visibility = Visibility.Hidden; dropDown2.Visibility = Visibility.Hidden; - naviBar.Unloaded += ResurrectNaviBar_OnUnloaded; + naviBarHolder.Unloaded += ResurrectNaviBar_OnUnloaded; } // Fixes https://github.com/wmjordan/Codist/issues/131 @@ -142,7 +147,7 @@ async void ResurrectNaviBar_OnUnloaded(object sender, RoutedEventArgs e) { await Task.Delay(1000).ConfigureAwait(false); await Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(default); if (_View.VisualElement.IsVisible && _View.Properties.ContainsProperty(nameof(NaviBar)) == false) { - AddNaviBar(_View.VisualElement, e); + AddNaviBar(_View, e); } } } diff --git a/Codist/SmartBars/SmartBar.cs b/Codist/SmartBars/SmartBar.cs index c8fa00eb..2005ad19 100644 --- a/Codist/SmartBars/SmartBar.cs +++ b/Codist/SmartBars/SmartBar.cs @@ -249,7 +249,7 @@ async Task CreateToolBarAsync(CancellationToken cancellationToken) { while ((Mouse.LeftButton == MouseButtonState.Pressed || Keyboard.Modifiers == ModifierKeys.Shift) && cancellationToken.IsCancellationRequested == false) { // postpone the even handler until the mouse button is released - await Task.Delay(100); + await Task.Delay(100, cancellationToken); } if (View.Selection.IsEmpty || Interlocked.Exchange(ref _SelectionStatus, Working) != Selecting) { goto EXIT;