From 50240de75dba7eaf24dc19759d1a0c669bbe3e05 Mon Sep 17 00:00:00 2001
From: WMJ <wmj@live.cn>
Date: Sun, 11 Jun 2023 10:30:13 +0800
Subject: [PATCH] ! Optimized the layout and positioning of Quick Info

---
 Codist/QuickInfo/QuickInfoOverride.cs         | 17 +++---
 .../QuickInfo/QuickInfoOverrideController.cs  | 55 ++++++++++---------
 2 files changed, 38 insertions(+), 34 deletions(-)

diff --git a/Codist/QuickInfo/QuickInfoOverride.cs b/Codist/QuickInfo/QuickInfoOverride.cs
index 3091b1e9..1f9d23c0 100644
--- a/Codist/QuickInfo/QuickInfoOverride.cs
+++ b/Codist/QuickInfo/QuickInfoOverride.cs
@@ -410,7 +410,7 @@ protected override void OnVisualParentChanged(DependencyObject oldParent) {
 					if (Config.Instance.DisplayOptimizations.MatchFlags(DisplayOptimizations.CodeWindow)) {
 						WpfHelper.SetUITextRenderOptions(p, true);
 					}
-					StackPanel altSign = Config.Instance.QuickInfoOptions.MatchFlags(QuickInfoOptions.OverrideDefaultDocumentation) || _Override.ClickAndGoSymbol != null
+					Grid altSign = Config.Instance.QuickInfoOptions.MatchFlags(QuickInfoOptions.OverrideDefaultDocumentation) || _Override.ClickAndGoSymbol != null
 						? OverrideXmlDocGetSignature(p)
 						: null;
 					_Override.ErrorTags?.Clear();
@@ -488,10 +488,10 @@ void MakeTextualContentSelectableWithIcon(Panel p) {
 				bool WorkaroundForTypeScriptQuickInfo(DependencyObject c) => c is Button == false;
 			}
 
-			StackPanel OverrideXmlDocGetSignature(StackPanel infoPanel) {
+			Grid OverrideXmlDocGetSignature(StackPanel infoPanel) {
 				var titlePanel = infoPanel.GetFirstVisualChild<WrapPanel>();
 				if (titlePanel == null) {
-					StackPanel altSign = null;
+					Grid altSign = null;
 					if (_Override.ClickAndGoSymbol != null
 						&& Config.Instance.QuickInfoOptions.MatchFlags(QuickInfoOptions.AlternativeStyle)) {
 						// no built-in documentation, but Codist has it
@@ -540,7 +540,7 @@ StackPanel OverrideXmlDocGetSignature(StackPanel infoPanel) {
 				return null;
 			}
 
-			StackPanel ShowAlternativeSignature() {
+			Grid ShowAlternativeSignature() {
 				var s = _Override.ClickAndGoSymbol;
 				var icon = ThemeHelper.GetImage(s.GetImageId(), ThemeHelper.LargeIconSize)
 					.AsSymbolLink(Keyboard.Modifiers == ModifierKeys.Control ? s.OriginalDefinition : s);
@@ -549,9 +549,12 @@ StackPanel ShowAlternativeSignature() {
 				signature.MaxWidth = (Config.Instance.QuickInfo.MaxWidth >= 100
 					? Config.Instance.QuickInfo.MaxWidth
 					: WpfHelper.GetActiveScreenSize().Width / 2) - (ThemeHelper.LargeIconSize + 30);
-				return new StackPanel {
-					Orientation = Orientation.Horizontal,
-					Children = { icon, signature }
+				return new Grid {
+					ColumnDefinitions = {
+						new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) },
+						new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
+					},
+					Children = { icon, signature.SetValue(Grid.SetColumn, 1) }
 				}.Tag();
 			}
 
diff --git a/Codist/QuickInfo/QuickInfoOverrideController.cs b/Codist/QuickInfo/QuickInfoOverrideController.cs
index 682073f4..df8923e7 100644
--- a/Codist/QuickInfo/QuickInfoOverrideController.cs
+++ b/Codist/QuickInfo/QuickInfoOverrideController.cs
@@ -60,11 +60,18 @@ public QuickInfoPositioner(IAsyncQuickInfoSession session, FrameworkElement quic
 
 			// reposition the Quick Info to prevent it from hindering text selection with mouse cursor
 			public void Reposition(bool attachEventsOnDemand) {
-				if (_Session.TextView is IWpfTextView view == false || _Session.ApplicableToSpan == null) {
+				if (_Session.TextView is IWpfTextView view == false
+					|| _Session.ApplicableToSpan == null
+					|| view.VisualElement.IsVisible == false) {
 					return;
 				}
 				var viewLines = view.TextViewLines;
 				var visibleLineTop = viewLines.FirstVisibleLine.Top;
+				#region positioning fix for VS 2017
+				if (_Popup.PlacementTarget == null) {
+					_Popup.PlacementTarget = view.VisualElement;
+				}
+				#endregion
 				var mousePosition = System.Windows.Input.Mouse.GetPosition(_Popup.PlacementTarget);
 				var cursorLine = viewLines.GetTextViewLineContainingBufferPosition(_Session.GetTriggerPoint(view.TextSnapshot).Value);
 				var offsetLine = cursorLine.TextTop - view.ViewportTop;
@@ -74,44 +81,38 @@ public void Reposition(bool attachEventsOnDemand) {
 				var left = mousePosition.X - 40;
 				var zoom = view.ZoomLevel / 100;
 				var quickInfoHeight = _QuickInfo.ActualHeight / zoom;
-				double top;
-				if (offsetLine + cursorLine.TextHeight + quickInfoHeight > view.ViewportHeight) {
+				var top = view.VisualElement.PointFromScreen(new Point(0, 0)).Y;
+				var bottom = view.VisualElement.PointFromScreen(new Point(0, WpfHelper.GetActiveScreenSize().Height)).Y;
+				if (offsetLine + cursorLine.TextHeight + quickInfoHeight > bottom) {
 					// Quick Info popup is over the line with mouse cursor
-					top = offsetLine - quickInfoHeight - cursorLine.TextHeight;
-					if (view.VisualElement.PointToScreen(new Point(left, top)).Y < 0) {
-						var bottom = view.VisualElement.PointFromScreen(new Point(0, WpfHelper.GetActiveScreenSize().Height)).Y;
-						if (textBound.Bottom + quickInfoHeight >= bottom) {
-							top = view.VisualElement.PointFromScreen(new Point(0, 0)).Y;
-							// find the max vertical room to place the popup,
-							// resize if popup can go off screen
-							if (offsetLine - top < bottom - textBound.Bottom) {
-								_QuickInfo.MaxHeight = (bottom - textBound.Bottom) * zoom;
-								top = offsetLine;
-							}
-							else {
-								_QuickInfo.MaxHeight = (offsetLine - top) * zoom;
-								top = offsetLine - quickInfoHeight - cursorLine.TextHeight;
-								return;
-							}
-						}
-						else {
-							top = offsetLine;
+					if (view.VisualElement.PointToScreen(new Point(left, offsetLine - quickInfoHeight - cursorLine.TextHeight)).Y >= 0) {
+						goto SHOW_ON_TOP;
+
+					}
+					if (textBound.Bottom + quickInfoHeight >= bottom) {
+						// find the max vertical room to place the popup,
+						// resize if popup can go off screen
+						if (offsetLine - top >= bottom - textBound.Bottom) {
+							goto SHOW_ON_TOP;
 						}
 					}
 				}
-				else {
-					top = offsetLine;
-				}
-				_Popup.PlacementRectangle = new Rect(new Point(left, top), textBound.Size);
+				_QuickInfo.MaxHeight = (bottom - textBound.Bottom) * zoom;
+				_Popup.PlacementRectangle = new Rect(new Point(left, offsetLine), textBound.Size);
 				if (attachEventsOnDemand) {
 					_QuickInfo.SizeChanged += QuickInfo_SizeChanged;
 					_QuickInfo.Unloaded += QuickInfo_Unloaded;
 				}
+				return;
+				SHOW_ON_TOP:
+				_QuickInfo.MaxHeight = (offsetLine - top) * zoom;
+				_Popup.Placement = PlacementMode.Top;
+				_Popup.PlacementRectangle = new Rect(new Point(left, offsetLine), textBound.Size);
 			}
 
 			void QuickInfo_SizeChanged(object sender, SizeChangedEventArgs e) {
 				if (e.NewSize.Height != 0 && e.NewSize.Height != e.PreviousSize.Height) {
-					//Reposition(false);
+					Reposition(false);
 				}
 			}