Skip to content

Commit 1a9d0c3

Browse files
authored
Merge pull request #9552 from h3xds1nz/replace-boxing-hashtable-context
Replace boxing Hashtable in AdornerPresentationContext, reduce allocations
2 parents b1ddc8a + b5dab8b commit 1a9d0c3

File tree

1 file changed

+27
-50
lines changed

1 file changed

+27
-50
lines changed

src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Component/AdornerPresentationContext.cs

Lines changed: 27 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
//
66
// Description:
7-
// AdornerPresentationContext knows that annotation comonents are wrapped
7+
// AdornerPresentationContext knows that annotation components are wrapped
88
// in an AnnotationAdorner and hosted in the AdornerLayer. Note, implementation-wise
99
// a new PresentationContext is created for every annotation component. Executing
1010
// operations on a presentation context for a different annotation component
@@ -19,17 +19,16 @@
1919
using System.Windows.Annotations;
2020
using System.Windows.Documents;
2121
using System.Windows.Media;
22-
using System.Collections;
2322

2423
namespace MS.Internal.Annotations.Component
2524
{
2625
/// <summary>
27-
/// AdornerPresentationContext knows that annotation comonents are wrapped in an AnnotationAdorner and hosted in the AdornerLayer.
26+
/// AdornerPresentationContext knows that annotation components are wrapped in an AnnotationAdorner and hosted in the AdornerLayer.
2827
/// Note, implementation-wise a new PresentationContext is created for every annotation component. Executing operations on a presentation context
2928
/// for a different annotation component (located in the same adorner layer) works, but is slower than using the presentation context stored in the
3029
/// annotation component.
3130
/// </summary>
32-
internal class AdornerPresentationContext : PresentationContext
31+
internal sealed class AdornerPresentationContext : PresentationContext
3332
{
3433
#region Constructors
3534

@@ -100,22 +99,14 @@ internal static void HostComponent(AdornerLayer adornerLayer, IAnnotationCompone
10099
/// BringToTop method. This will move the component to the top of its priority group. If there are other
101100
/// components with higher priority they will still be on top of that component. If more than
102101
/// one component type have the same ZLevel that means they all can stay on top of each other.
103-
/// Setting IAnnotationComponent.ZOrder must be invoked only by the PrezentationContext
102+
/// Setting IAnnotationComponent.ZOrder must be invoked only by the PresentationContext
104103
/// when the Z-order changes. It can not be set by application in v1.</remarks>
105104
internal static void SetTypeZLevel(Type type, int level)
106105
{
107106
Invariant.Assert(level >= 0, "level is < 0");
108-
109107
Invariant.Assert(type != null, "type is null");
110108

111-
if (_ZLevel.ContainsKey(type))
112-
{
113-
_ZLevel[type] = level;
114-
}
115-
else
116-
{
117-
_ZLevel.Add(type, level);
118-
}
109+
s_ZLevel[type] = level;
119110
}
120111

121112
/// <summary>
@@ -128,9 +119,9 @@ internal static void SetTypeZLevel(Type type, int level)
128119
/// <param name="max">max Z-order value for this level</param>
129120
internal static void SetZLevelRange(int level, int min, int max)
130121
{
131-
if (_ZRanges[level] == null)
122+
if (!s_ZRanges.ContainsKey(level))
132123
{
133-
_ZRanges.Add(level, new ZRange(min, max));
124+
s_ZRanges.Add(level, new ZRange(min, max));
134125
}
135126
}
136127

@@ -512,12 +503,9 @@ private AnnotationAdorner GetAnnotationAdorner(IAnnotationComponent component)
512503
/// <returns>ZLevel</returns>
513504
private static int GetComponentLevel(IAnnotationComponent component)
514505
{
515-
int level = 0;
516506
Type type = component.GetType();
517-
if (_ZLevel.ContainsKey(type))
518-
level = (int)_ZLevel[type];
519507

520-
return level;
508+
return s_ZLevel.TryGetValue(type, out int value) ? value : 0;
521509
}
522510

523511
/// <summary>
@@ -531,18 +519,21 @@ private static int GetComponentLevel(IAnnotationComponent component)
531519
private static int ComponentToAdorner(int zOrder, int level)
532520
{
533521
int res = zOrder;
534-
ZRange range = (ZRange)_ZRanges[level];
535-
if (range != null)
522+
523+
if (s_ZRanges.TryGetValue(level, out ZRange range))
536524
{
537525
//adjust the Z-order (shift it with the minimal value for this range)
538526
//that way the component does need to know the range for its type that is
539527
// set by the application. It always sets the z-order as it starts from 0
540528
res += range.Min;
529+
541530
if (res < range.Min)
542531
res = range.Min;
532+
543533
if (res > range.Max)
544534
res = range.Max;
545535
}
536+
546537
return res;
547538
}
548539

@@ -559,19 +550,17 @@ private static int ComponentToAdorner(int zOrder, int level)
559550
/// <summary>
560551
/// The adornerLayer which contains the annotation component. Basically what the presentation hides.
561552
/// </summary>
562-
private AdornerLayer _adornerLayer;
553+
private readonly AdornerLayer _adornerLayer;
563554

564555
/// <summary>
565-
/// The hashtable holds the priority level for each Component type as defined by the application
556+
/// The dictionary holds the priority level for each Component type as defined by the application
566557
/// </summary>
567-
private static Hashtable _ZLevel = new Hashtable();
558+
private static readonly Dictionary<Type, int> s_ZLevel = new();
568559

569560
/// <summary>
570561
/// The ZRanges for the ZLevels.
571562
/// </summary>
572-
private static Hashtable _ZRanges = new Hashtable();
573-
574-
563+
private static readonly Dictionary<int, ZRange> s_ZRanges = new();
575564

576565
#endregion Private Fields
577566

@@ -581,40 +570,28 @@ private static int ComponentToAdorner(int zOrder, int level)
581570
/// This is to control the relationships with TextSelection which lives in the same
582571
/// AdornerLayer. Will be removed when more flexible Z-ordering mechanism is available
583572
/// </summary>
584-
private class ZRange
573+
private readonly struct ZRange
585574
{
586575
public ZRange(int min, int max)
587576
{
588-
//exchange values if needed
577+
// Swap values if needed
589578
if (min > max)
590579
{
591-
int temp = min;
580+
int num = min;
592581
min = max;
593-
max = temp;
582+
max = num;
594583
}
595-
_min = min;
596-
_max = max;
597-
}
598584

599-
public int Min
600-
{
601-
get
602-
{
603-
return _min;
604-
}
605-
}
606-
public int Max
607-
{
608-
get
609-
{
610-
return _max;
611-
}
585+
Min = min;
586+
Max = max;
612587
}
613588

614-
private int _min, _max;
589+
public int Min { get; }
590+
public int Max { get; }
591+
615592
}
616593

617-
#endregion Internal classes
594+
#endregion Private classes
618595
}
619596
}
620597

0 commit comments

Comments
 (0)