Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit a07cbc7

Browse files
authored
Merge pull request #1112 from github/fixes/resizeable-peek-view
Allow inline comment peek view to resize to content.
2 parents 8432351 + efb75e2 commit a07cbc7

11 files changed

+143
-64
lines changed

src/GitHub.InlineReviews/Peek/InlineCommentPeekResultPresentation.cs

+26-2
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66

77
namespace GitHub.InlineReviews.Peek
88
{
9-
class InlineCommentPeekResultPresentation : IPeekResultPresentation
9+
class InlineCommentPeekResultPresentation : IPeekResultPresentation, IDesiredHeightProvider
1010
{
11+
const double PeekBorders = 28.0;
1112
readonly InlineCommentPeekViewModel viewModel;
13+
InlineCommentPeekView view;
14+
double desiredHeight;
1215

1316
public bool IsDirty => false;
1417
public bool IsReadOnly => true;
@@ -24,9 +27,23 @@ public double ZoomLevel
2427
set { }
2528
}
2629

30+
public double DesiredHeight
31+
{
32+
get { return desiredHeight; }
33+
private set
34+
{
35+
if (desiredHeight != value && DesiredHeightChanged != null)
36+
{
37+
desiredHeight = value;
38+
DesiredHeightChanged(this, EventArgs.Empty);
39+
}
40+
}
41+
}
42+
2743
public event EventHandler IsDirtyChanged;
2844
public event EventHandler IsReadOnlyChanged;
2945
public event EventHandler<RecreateContentEventArgs> RecreateContent;
46+
public event EventHandler<EventArgs> DesiredHeightChanged;
3047

3148
public bool CanSave(out string defaultPath)
3249
{
@@ -45,8 +62,15 @@ public void Close()
4562

4663
public UIElement Create(IPeekSession session, IPeekResultScrollState scrollState)
4764
{
48-
var view = new InlineCommentPeekView();
65+
view = new InlineCommentPeekView();
4966
view.DataContext = viewModel;
67+
68+
// Report the desired size back to the peek view. Unfortunately the peek view
69+
// helpfully assigns this desired size to the control that also contains the tab at
70+
// the top of the peek view, so we need to put in a fudge factor. Using a const
71+
// value for the moment, as there's no easy way to get the size of the control.
72+
view.DesiredHeight.Subscribe(x => DesiredHeight = x + PeekBorders);
73+
5074
return view;
5175
}
5276

src/GitHub.InlineReviews/Services/InlineCommentPeekService.cs

+13-2
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,15 @@ public ITrackingPoint Show(ITextView textView, AddInlineCommentTag tag)
9595

9696
var line = textView.TextSnapshot.GetLineFromLineNumber(tag.LineNumber);
9797
var trackingPoint = textView.TextSnapshot.CreateTrackingPoint(line.Start.Position, PointTrackingMode.Positive);
98+
var options = new PeekSessionCreationOptions(
99+
textView,
100+
InlineCommentPeekRelationship.Instance.Name,
101+
trackingPoint,
102+
defaultHeight: 0);
98103

99104
ExpandCollapsedRegions(textView, line.Extent);
100105

101-
var session = peekBroker.TriggerPeekSession(textView, trackingPoint, InlineCommentPeekRelationship.Instance.Name);
106+
var session = peekBroker.TriggerPeekSession(options);
102107
var item = session.PeekableItems.OfType<InlineCommentPeekableItem>().FirstOrDefault();
103108

104109
if (item != null)
@@ -133,8 +138,14 @@ public ITrackingPoint Show(ITextView textView, ShowInlineCommentTag tag)
133138

134139
var line = snapshot.GetLineFromLineNumber(tag.LineNumber);
135140
var trackingPoint = snapshot.CreateTrackingPoint(line.Start.Position, PointTrackingMode.Positive);
141+
var options = new PeekSessionCreationOptions(
142+
textView,
143+
InlineCommentPeekRelationship.Instance.Name,
144+
trackingPoint,
145+
defaultHeight: 0);
146+
136147
ExpandCollapsedRegions(textView, line.Extent);
137-
peekBroker.TriggerPeekSession(textView, trackingPoint, InlineCommentPeekRelationship.Instance.Name);
148+
peekBroker.TriggerPeekSession(options);
138149
return trackingPoint;
139150
}
140151

src/GitHub.InlineReviews/ViewModels/CommentViewModel.cs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.ComponentModel;
3+
using System.Linq;
34
using System.Reactive;
45
using System.Reactive.Linq;
56
using System.Threading.Tasks;

src/GitHub.InlineReviews/Views/InlineCommentPeekView.xaml

+3-2
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@
7878
</StackPanel>
7979
</Border>
8080

81-
<ScrollViewer VerticalScrollBarVisibility="Auto"
81+
<ScrollViewer Name="threadScroller"
82+
VerticalScrollBarVisibility="Auto"
8283
Background="#FFF5F5F5">
8384
<Grid>
84-
<local:CommentThreadView DataContext="{Binding Thread}"/>
85+
<local:CommentThreadView x:Name="threadView" DataContext="{Binding Thread}"/>
8586
</Grid>
8687
</ScrollViewer>
8788
</DockPanel>
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
using System.Windows;
2+
using System.Reactive.Subjects;
73
using System.Windows.Controls;
8-
using System.Windows.Data;
9-
using System.Windows.Documents;
10-
using System.Windows.Input;
11-
using System.Windows.Media;
12-
using System.Windows.Media.Imaging;
13-
using System.Windows.Navigation;
14-
using System.Windows.Shapes;
4+
using GitHub.VisualStudio.UI.Helpers;
155

166
namespace GitHub.InlineReviews.Views
177
{
188
public partial class InlineCommentPeekView : UserControl
199
{
10+
readonly Subject<double> desiredHeight;
11+
2012
public InlineCommentPeekView()
2113
{
2214
InitializeComponent();
15+
16+
desiredHeight = new Subject<double>();
17+
threadView.LayoutUpdated += ThreadViewLayoutUpdated;
18+
threadScroller.PreviewMouseWheel += ScrollViewerUtilities.FixMouseWheelScroll;
19+
}
20+
21+
public IObservable<double> DesiredHeight => desiredHeight;
22+
23+
void ThreadViewLayoutUpdated(object sender, EventArgs e)
24+
{
25+
var otherControlsHeight = ActualHeight - threadScroller.ActualHeight;
26+
var threadViewHeight = threadView.DesiredSize.Height + threadView.Margin.Top + threadView.Margin.Bottom;
27+
desiredHeight.OnNext(threadViewHeight + otherControlsHeight);
2328
}
2429
}
2530
}

src/GitHub.UI/GitHub.UI.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
<Compile Include="Helpers\ScrollViewerUtilities.cs" />
9191
<Compile Include="Helpers\SharedDictionaryManager.cs" />
9292
<Compile Include="Helpers\TreeViewExtensions.cs" />
93+
<Compile Include="Helpers\VisualTreeExtensions.cs" />
9394
<Compile Include="Resources.Designer.cs">
9495
<AutoGen>True</AutoGen>
9596
<DesignTime>True</DesignTime>

src/GitHub.UI/Helpers/ScrollViewerUtilities.cs

+22-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
using System.Windows;
1+
using System.Linq;
2+
using System.Windows;
3+
using System.Windows.Controls;
24
using System.Windows.Input;
5+
using GitHub.UI.Helpers;
36

47
namespace GitHub.VisualStudio.UI.Helpers
58
{
@@ -15,8 +18,9 @@ public static class ScrollViewerUtilities
1518
/// <param name="e">The event arguments.</param>
1619
/// <remarks>
1720
/// WPF's ScrollViewer is broken in that it doesn't pass scroll events to the parent
18-
/// control when it can't scroll any more. Add this method as an event handler to a
19-
/// control which has a ScrollViewer in its template to fix this.
21+
/// control when it can't scroll any more. Add this method as a PreviewMouseWheel event
22+
/// handler to a ScrollViewer or a control which has a ScrollViewer in its template to
23+
/// fix this.
2024
/// </remarks>
2125
public static void FixMouseWheelScroll(object sender, MouseWheelEventArgs e)
2226
{
@@ -26,15 +30,24 @@ public static void FixMouseWheelScroll(object sender, MouseWheelEventArgs e)
2630
{
2731
var control = sender as FrameworkElement;
2832
var parent = control.Parent as UIElement;
33+
var scrollViewer = control.GetSelfAndVisualDescendents()
34+
.OfType<ScrollViewer>()
35+
.FirstOrDefault();
2936

30-
if (parent != null)
37+
if (scrollViewer != null && parent != null)
3138
{
32-
e.Handled = true;
33-
parent.RaiseEvent(new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
39+
var offset = scrollViewer.ContentVerticalOffset;
40+
41+
if ((offset == scrollViewer.ScrollableHeight && e.Delta < 0) ||
42+
(offset == 0 && e.Delta > 0))
3443
{
35-
RoutedEvent = UIElement.MouseWheelEvent,
36-
Source = control,
37-
});
44+
e.Handled = true;
45+
parent.RaiseEvent(new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
46+
{
47+
RoutedEvent = UIElement.MouseWheelEvent,
48+
Source = control,
49+
});
50+
}
3851
}
3952
}
4053
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using System.Windows.Media;
4+
using GitHub.Extensions;
5+
6+
namespace GitHub.UI.Helpers
7+
{
8+
public static class VisualTreeExtensions
9+
{
10+
public static IEnumerable<Visual> GetSelfAndVisualAncestors(this Visual visual)
11+
{
12+
Guard.ArgumentNotNull(visual, nameof(visual));
13+
14+
return Enumerable.Repeat(visual, 1).Concat(GetVisualAncestors(visual));
15+
}
16+
17+
public static IEnumerable<Visual> GetVisualAncestors(this Visual visual)
18+
{
19+
Guard.ArgumentNotNull(visual, nameof(visual));
20+
21+
while (true)
22+
{
23+
visual = VisualTreeHelper.GetParent(visual) as Visual;
24+
25+
if (visual != null)
26+
yield return visual;
27+
else
28+
break;
29+
}
30+
}
31+
32+
public static IEnumerable<Visual> GetSelfAndVisualDescendents(this Visual visual)
33+
{
34+
Guard.ArgumentNotNull(visual, nameof(visual));
35+
36+
return Enumerable.Repeat(visual, 1).Concat(GetVisualDescendents(visual));
37+
}
38+
39+
public static IEnumerable<Visual> GetVisualDescendents(this Visual visual)
40+
{
41+
Guard.ArgumentNotNull(visual, nameof(visual));
42+
43+
var count = VisualTreeHelper.GetChildrenCount(visual);
44+
45+
for (var i = 0; i < count; ++i)
46+
{
47+
var child = (Visual)VisualTreeHelper.GetChild(visual, i);
48+
yield return child;
49+
50+
foreach (var descendent in child.GetVisualDescendents())
51+
{
52+
yield return descendent;
53+
}
54+
}
55+
}
56+
}
57+
}

src/GitHub.VisualStudio/GitHub.VisualStudio.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,6 @@
287287
<Link>Properties\SolutionInfo.cs</Link>
288288
</Compile>
289289
<Compile Include="AssemblyResolverPackage.cs" />
290-
<Compile Include="Helpers\VisualTreeExtensions.cs" />
291290
<Compile Include="IServiceProviderPackage.cs" />
292291
<Compile Include="Menus\BlameLink.cs" />
293292
<Compile Include="Menus\MenuBase.cs" />

src/GitHub.VisualStudio/Helpers/VisualTreeExtensions.cs

-32
This file was deleted.

src/GitHub.VisualStudio/UI/Views/PullRequestDetailView.xaml.cs

+3-4
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,21 @@
99
using System.Windows.Media;
1010
using GitHub.Exports;
1111
using GitHub.Extensions;
12+
using GitHub.InlineReviews.Commands;
1213
using GitHub.Models;
1314
using GitHub.Services;
1415
using GitHub.UI;
16+
using GitHub.UI.Helpers;
1517
using GitHub.ViewModels;
16-
using GitHub.VisualStudio.Helpers;
1718
using GitHub.VisualStudio.UI.Helpers;
18-
using Microsoft.VisualStudio.Shell;
1919
using Microsoft.VisualStudio;
2020
using Microsoft.VisualStudio.Editor;
21+
using Microsoft.VisualStudio.Shell;
2122
using Microsoft.VisualStudio.Shell.Interop;
2223
using Microsoft.VisualStudio.Text;
2324
using Microsoft.VisualStudio.Text.Editor;
2425
using ReactiveUI;
2526
using Task = System.Threading.Tasks.Task;
26-
using GitHub.InlineReviews.Commands;
27-
using GitHub.UI.Helpers;
2827

2928
namespace GitHub.VisualStudio.UI.Views
3029
{

0 commit comments

Comments
 (0)