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

Commit 16b867e

Browse files
authored
Merge pull request #1031 from github/feature/inline-reviews-commentbubble
Show comment bubble when hovering over the current mouse line
2 parents 88821ed + 015b5c1 commit 16b867e

File tree

3 files changed

+121
-2
lines changed

3 files changed

+121
-2
lines changed

src/GitHub.InlineReviews/GitHub.InlineReviews.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
<Compile Include="InlineReviewsPackage.cs" />
8383
<Compile Include="Models\InlineCommentThreadModel.cs" />
8484
<Compile Include="Models\PullRequestSessionFile.cs" />
85+
<Compile Include="Tags\MouseEnterAndLeaveEventRouter.cs" />
8586
<Compile Include="Peek\InlineCommentPeekableItem.cs" />
8687
<Compile Include="Peek\InlineCommentPeekableItemSource.cs" />
8788
<Compile Include="Peek\InlineCommentPeekableItemSourceProvider.cs" />

src/GitHub.InlineReviews/InlineCommentMarginProvider.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Windows;
23
using System.Windows.Controls;
34
using System.ComponentModel.Composition;
45
using Microsoft.VisualStudio.Utilities;
@@ -10,7 +11,6 @@
1011
using GitHub.InlineReviews.Glyph;
1112
using GitHub.InlineReviews.Services;
1213
using GitHub.InlineReviews.Views;
13-
using GitHub.Models;
1414
using GitHub.Services;
1515

1616
namespace GitHub.InlineReviews
@@ -58,8 +58,21 @@ IWpfTextViewMargin CreateMargin<TGlyphTag>(IGlyphFactory<TGlyphTag> glyphFactory
5858
IWpfTextViewHost wpfTextViewHost, IWpfTextViewMargin parent, IEditorFormatMap editorFormatMap) where TGlyphTag : ITag
5959
{
6060
var tagAggregator = tagAggregatorFactory.CreateTagAggregator<TGlyphTag>(wpfTextViewHost.TextView);
61-
return new GlyphMargin<TGlyphTag>(wpfTextViewHost, glyphFactory, gridFactory, tagAggregator, editorFormatMap,
61+
var margin = new GlyphMargin<TGlyphTag>(wpfTextViewHost, glyphFactory, gridFactory, tagAggregator, editorFormatMap,
6262
IsMarginVisible, MarginPropertiesName, MarginName, true, 17.0);
63+
64+
TrackCommentGlyphOnDiffView(wpfTextViewHost, margin.VisualElement);
65+
return margin;
66+
}
67+
68+
void TrackCommentGlyphOnDiffView(IWpfTextViewHost host, UIElement marginElement)
69+
{
70+
var textView = host.TextView;
71+
if (textView.Roles.Contains("DIFF"))
72+
{
73+
var router = new MouseEnterAndLeaveEventRouter<AddInlineCommentGlyph>();
74+
router.Add(host.HostControl, marginElement);
75+
}
6376
}
6477

6578
bool IsMarginVisible(ITextBuffer buffer)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.Windows;
3+
using System.Windows.Controls;
4+
using System.Windows.Input;
5+
6+
namespace GitHub.InlineReviews.Tags
7+
{
8+
class MouseEnterAndLeaveEventRouter<T> where T : FrameworkElement
9+
{
10+
T previousMouseOverElement;
11+
12+
public void Add(UIElement sourceElement, UIElement targetElement)
13+
{
14+
sourceElement.MouseMove += (t, e) => MouseMove(targetElement, e);
15+
sourceElement.MouseLeave += (t, e) => MouseLeave(targetElement, e);
16+
}
17+
18+
void MouseMove(object target, MouseEventArgs e)
19+
{
20+
T mouseOverElement = null;
21+
Action<T> visitAction = element =>
22+
{
23+
mouseOverElement = element;
24+
};
25+
26+
var visitor = new Visitor(e, visitAction);
27+
visitor.Visit(target);
28+
29+
if (mouseOverElement != previousMouseOverElement)
30+
{
31+
MouseLeave(previousMouseOverElement, e);
32+
MouseEnter(mouseOverElement, e);
33+
}
34+
}
35+
36+
void MouseLeave(object target, MouseEventArgs e)
37+
{
38+
MouseLeave(previousMouseOverElement, e);
39+
}
40+
41+
void MouseEnter(T element, MouseEventArgs e)
42+
{
43+
element?.RaiseEvent(new MouseEventArgs(e.MouseDevice, e.Timestamp)
44+
{
45+
RoutedEvent = Mouse.MouseEnterEvent,
46+
});
47+
48+
previousMouseOverElement = element;
49+
}
50+
51+
void MouseLeave(T element, MouseEventArgs e)
52+
{
53+
element?.RaiseEvent(new MouseEventArgs(e.MouseDevice, e.Timestamp)
54+
{
55+
RoutedEvent = Mouse.MouseLeaveEvent,
56+
});
57+
58+
previousMouseOverElement = null;
59+
}
60+
61+
class Visitor
62+
{
63+
MouseEventArgs mouseEventArgs;
64+
Action<T> action;
65+
66+
internal Visitor(MouseEventArgs mouseEventArgs, Action<T> action)
67+
{
68+
this.mouseEventArgs = mouseEventArgs;
69+
this.action = action;
70+
}
71+
72+
internal void Visit(object obj)
73+
{
74+
if (obj is Panel)
75+
{
76+
Visit((Panel)obj);
77+
return;
78+
}
79+
80+
if (obj is T)
81+
{
82+
Visit((T)obj);
83+
return;
84+
}
85+
}
86+
87+
internal void Visit(Panel panel)
88+
{
89+
foreach (var child in panel.Children)
90+
{
91+
Visit(child);
92+
}
93+
}
94+
95+
internal void Visit(T element)
96+
{
97+
var point = mouseEventArgs.GetPosition(element);
98+
if (point.Y >= 0 && point.Y < element.ActualHeight)
99+
{
100+
action(element);
101+
}
102+
}
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)