Skip to content

Commit 7ac2ac0

Browse files
committed
Respond to AI reviewer comments
1 parent 1be4ea9 commit 7ac2ac0

2 files changed

Lines changed: 128 additions & 14 deletions

File tree

Src/Common/Controls/DetailControls/DataTree.cs

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4536,9 +4536,39 @@ private bool EquivalentKeys(object[] newKey, object[] oldKey, bool fCheckInts)
45364536
return true;
45374537
}
45384538

4539-
private const int WM_MOUSEWHEEL = 0x020A;
45404539
private static readonly WheelRedirector s_wheelRedirector = new WheelRedirector();
45414540

4541+
internal static int GetWheelScrollPixels(DataTree dataTree, int delta)
4542+
{
4543+
if (delta == 0)
4544+
return 0;
4545+
4546+
int scrollLines = SystemInformation.MouseWheelScrollLines;
4547+
if (scrollLines == 0)
4548+
return 0;
4549+
4550+
if (scrollLines == int.MaxValue)
4551+
return Math.Sign(delta) * dataTree.ClientRectangle.Height;
4552+
4553+
double linesToScroll = (double)delta / SystemInformation.MouseWheelScrollDelta * scrollLines;
4554+
return (int)Math.Round(linesToScroll * dataTree.Font.Height, MidpointRounding.AwayFromZero);
4555+
}
4556+
4557+
internal static bool TryGetWheelScrollPosition(DataTree dataTree, int delta, out int newY)
4558+
{
4559+
int currentY = -dataTree.AutoScrollPosition.Y;
4560+
int maxScroll = Math.Max(0,
4561+
dataTree.AutoScrollMinSize.Height - dataTree.ClientRectangle.Height);
4562+
int pixelDelta = GetWheelScrollPixels(dataTree, delta);
4563+
newY = Math.Max(0, Math.Min(currentY - pixelDelta, maxScroll));
4564+
return newY != currentY;
4565+
}
4566+
4567+
internal static bool CanRedirectWheelMessage(DataTree dataTree)
4568+
{
4569+
return dataTree.IsHandleCreated && !dataTree.IsDisposed && dataTree.Visible;
4570+
}
4571+
45424572
/// <summary>
45434573
/// Application-level message filter that intercepts WM_MOUSEWHEEL messages
45444574
/// and scrolls the DataTree when the cursor is over its client area.
@@ -4549,12 +4579,13 @@ private bool EquivalentKeys(object[] newKey, object[] oldKey, bool fCheckInts)
45494579
/// </summary>
45504580
private sealed class WheelRedirector : IMessageFilter
45514581
{
4552-
private readonly List<DataTree> m_dataTrees = new List<DataTree>();
4582+
private readonly HashSet<DataTree> m_dataTrees = new HashSet<DataTree>();
45534583
private bool m_installed;
45544584

45554585
public void Register(DataTree dataTree)
45564586
{
4557-
m_dataTrees.Add(dataTree);
4587+
if (!m_dataTrees.Add(dataTree))
4588+
return;
45584589
if (!m_installed)
45594590
{
45604591
Application.AddMessageFilter(this);
@@ -4564,7 +4595,9 @@ public void Register(DataTree dataTree)
45644595

45654596
public void Unregister(DataTree dataTree)
45664597
{
4567-
m_dataTrees.Remove(dataTree);
4598+
if (!m_dataTrees.Remove(dataTree))
4599+
return;
4600+
45684601
if (m_dataTrees.Count == 0 && m_installed)
45694602
{
45704603
Application.RemoveMessageFilter(this);
@@ -4574,28 +4607,28 @@ public void Unregister(DataTree dataTree)
45744607

45754608
public bool PreFilterMessage(ref Message m)
45764609
{
4577-
if (m.Msg != WM_MOUSEWHEEL)
4610+
if (m.Msg != (int)Win32.WinMsgs.WM_MOUSEWHEEL)
45784611
return false;
45794612

45804613
Point cursor = Cursor.Position;
4581-
for (int i = 0; i < m_dataTrees.Count; i++)
4614+
foreach (var dataTree in m_dataTrees)
45824615
{
4583-
var dataTree = m_dataTrees[i];
4584-
if (!dataTree.IsHandleCreated || dataTree.IsDisposed)
4616+
if (!CanRedirectWheelMessage(dataTree))
45854617
continue;
45864618

45874619
Rectangle bounds = dataTree.RectangleToScreen(dataTree.ClientRectangle);
45884620
if (!bounds.Contains(cursor))
45894621
continue;
45904622

45914623
int delta = (short)((long)m.WParam >> 16);
4592-
int currentY = -dataTree.AutoScrollPosition.Y;
4593-
int maxScroll = Math.Max(0,
4594-
dataTree.AutoScrollMinSize.Height - dataTree.ClientRectangle.Height);
4595-
int newY = Math.Max(0, Math.Min(currentY - delta, maxScroll));
4596-
if (newY != currentY)
4624+
int newY;
4625+
if (TryGetWheelScrollPosition(dataTree, delta, out newY))
4626+
{
45974627
dataTree.AutoScrollPosition = new Point(0, newY);
4598-
return true;
4628+
return true;
4629+
}
4630+
4631+
return false;
45994632
}
46004633

46014634
return false;

Src/Common/Controls/DetailControls/DetailControlsTests/DataTreeTests.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
using System;
66
using System.Collections.Generic;
7+
using System.Drawing;
78
using System.IO;
9+
using System.Reflection;
810
using System.Windows.Forms;
911
using System.Xml;
1012
using NUnit.Framework;
@@ -275,6 +277,85 @@ public void GetGuidForJumpToTool_UsesRootObject_WhenNoCurrentSlice()
275277
}
276278
}
277279

280+
[Test]
281+
public void GetWheelScrollPixels_UsesSystemWheelSettings()
282+
{
283+
m_dtree.Bounds = new Rectangle(0, 0, 200, 100);
284+
285+
int delta = SystemInformation.MouseWheelScrollDelta;
286+
int scrollLines = SystemInformation.MouseWheelScrollLines;
287+
int expectedPixels;
288+
if (scrollLines == 0)
289+
{
290+
expectedPixels = 0;
291+
}
292+
else if (scrollLines == int.MaxValue)
293+
{
294+
expectedPixels = m_dtree.ClientRectangle.Height;
295+
}
296+
else
297+
{
298+
expectedPixels = (int)Math.Round((double)scrollLines * m_dtree.Font.Height,
299+
MidpointRounding.AwayFromZero);
300+
}
301+
302+
Assert.That(DataTree.GetWheelScrollPixels(m_dtree, delta), Is.EqualTo(expectedPixels));
303+
Assert.That(DataTree.GetWheelScrollPixels(m_dtree, -delta), Is.EqualTo(-expectedPixels));
304+
}
305+
306+
[Test]
307+
public void TryGetWheelScrollPosition_ReturnsFalse_WhenAlreadyAtTop()
308+
{
309+
m_dtree.Bounds = new Rectangle(0, 0, 200, 100);
310+
m_dtree.AutoScrollMinSize = new Size(200, 1000);
311+
m_dtree.AutoScrollPosition = new Point(0, 0);
312+
313+
int newY;
314+
bool handled = DataTree.TryGetWheelScrollPosition(m_dtree,
315+
SystemInformation.MouseWheelScrollDelta, out newY);
316+
317+
Assert.That(handled, Is.False);
318+
Assert.That(newY, Is.EqualTo(0));
319+
}
320+
321+
[Test]
322+
public void CanRedirectWheelMessage_ReturnsFalse_WhenDataTreeHidden()
323+
{
324+
m_parent.Show();
325+
m_dtree.Show();
326+
Assert.That(m_dtree.IsHandleCreated, Is.True);
327+
328+
m_dtree.Hide();
329+
330+
Assert.That(DataTree.CanRedirectWheelMessage(m_dtree), Is.False);
331+
}
332+
333+
[Test]
334+
public void Register_RegisteredTwice_AddsOneEntryAndSingleUnregisterRemovesIt()
335+
{
336+
Type wheelRedirectorType = typeof(DataTree).GetNestedType("WheelRedirector", BindingFlags.NonPublic);
337+
Assert.That(wheelRedirectorType, Is.Not.Null);
338+
339+
object redirector = Activator.CreateInstance(wheelRedirectorType, true);
340+
MethodInfo register = wheelRedirectorType.GetMethod("Register", BindingFlags.Public | BindingFlags.Instance);
341+
MethodInfo unregister = wheelRedirectorType.GetMethod("Unregister", BindingFlags.Public | BindingFlags.Instance);
342+
FieldInfo dataTreesField = wheelRedirectorType.GetField("m_dataTrees", BindingFlags.NonPublic | BindingFlags.Instance);
343+
Assert.That(register, Is.Not.Null);
344+
Assert.That(unregister, Is.Not.Null);
345+
Assert.That(dataTreesField, Is.Not.Null);
346+
347+
register.Invoke(redirector, new object[] { m_dtree });
348+
register.Invoke(redirector, new object[] { m_dtree });
349+
350+
object registrations = dataTreesField.GetValue(redirector);
351+
PropertyInfo countProperty = registrations.GetType().GetProperty("Count", BindingFlags.Public | BindingFlags.Instance);
352+
Assert.That(countProperty, Is.Not.Null);
353+
Assert.That((int)countProperty.GetValue(registrations, null), Is.EqualTo(1));
354+
355+
unregister.Invoke(redirector, new object[] { m_dtree });
356+
Assert.That((int)countProperty.GetValue(registrations, null), Is.EqualTo(0));
357+
}
358+
278359
/// <summary></summary>
279360
[Test]
280361
public void OwnedObjects()

0 commit comments

Comments
 (0)