1
1
#nullable enable
2
+ using System . Collections . Generic ;
3
+
2
4
namespace Terminal . Gui ;
3
5
4
6
public abstract class Bindings < TKey , TBind > where TKey : Enum where TBind : IInputBinding , new ( )
5
7
{
6
- private readonly Dictionary < TKey , TBind > _bindings = new ( ) ;
8
+ protected readonly Dictionary < TKey , TBind > _bindings = new ( ) ;
9
+ private readonly Func < Command [ ] , TKey , TBind > _constructBinding ;
10
+
11
+ protected Bindings ( Func < Command [ ] , TKey , TBind > constructBinding )
12
+ {
13
+ _constructBinding = constructBinding ;
14
+ }
7
15
8
16
/// <summary>Adds a <see cref="MouseBinding"/> to the collection.</summary>
9
17
/// <param name="mouseEventArgs"></param>
@@ -35,37 +43,7 @@ public bool TryGet (TKey mouseEventArgs, out TBind? binding)
35
43
{
36
44
return _bindings . TryGetValue ( mouseEventArgs , out binding ) ;
37
45
}
38
- }
39
-
40
- /// <summary>
41
- /// Provides a collection of <see cref="MouseBinding"/> objects bound to a combination of <see cref="MouseFlags"/>.
42
- /// </summary>
43
- /// <seealso cref="View.MouseBindings"/>
44
- /// <seealso cref="Command"/>
45
- public class MouseBindings : Bindings < MouseFlags , MouseBinding >
46
- {
47
- /// <summary>
48
- /// Initializes a new instance. This constructor is used when the <see cref="MouseBindings"/> are not bound to a
49
- /// <see cref="View"/>. This is used for Application.MouseBindings and unit tests.
50
- /// </summary>
51
- public MouseBindings ( ) { }
52
46
53
- /// <summary>Adds a <see cref="MouseBinding"/> to the collection.</summary>
54
- /// <param name="mouseEventArgs"></param>
55
- /// <param name="binding"></param>
56
- public void Add ( MouseFlags mouseEventArgs , MouseBinding binding )
57
- {
58
- if ( TryGet ( mouseEventArgs , out MouseBinding _ ) )
59
- {
60
- throw new InvalidOperationException ( @$ "A binding for { mouseEventArgs } exists ({ binding } ).") ;
61
- }
62
-
63
- // IMPORTANT: Add a COPY of the mouseEventArgs. This is needed because ConfigurationManager.Apply uses DeepMemberWiseCopy
64
- // IMPORTANT: update the memory referenced by the key, and Dictionary uses caching for performance, and thus
65
- // IMPORTANT: Apply will update the Dictionary with the new mouseEventArgs, but the old mouseEventArgs will still be in the dictionary.
66
- // IMPORTANT: See the ConfigurationManager.Illustrate_DeepMemberWiseCopy_Breaks_Dictionary test for details.
67
- _bindings . Add ( mouseEventArgs , binding ) ;
68
- }
69
47
70
48
/// <summary>
71
49
/// <para>Adds a new mouse flag combination that will trigger the commands in <paramref name="commands"/>.</para>
@@ -85,9 +63,9 @@ public void Add (MouseFlags mouseEventArgs, MouseBinding binding)
85
63
/// will be
86
64
/// consumed if any took effect.
87
65
/// </param>
88
- public void Add ( MouseFlags mouseFlags , params Command [ ] commands )
66
+ public void Add ( TKey mouseFlags , params Command [ ] commands )
89
67
{
90
- if ( mouseFlags == MouseFlags . None )
68
+ if ( EqualityComparer < TKey > . Default . Equals ( mouseFlags , default ) )
91
69
{
92
70
throw new ArgumentException ( @"Invalid MouseFlag" , nameof ( mouseFlags ) ) ;
93
71
}
@@ -97,21 +75,19 @@ public void Add (MouseFlags mouseFlags, params Command [] commands)
97
75
throw new ArgumentException ( @"At least one command must be specified" , nameof ( commands ) ) ;
98
76
}
99
77
100
- if ( TryGet ( mouseFlags , out MouseBinding binding ) )
78
+ if ( TryGet ( mouseFlags , out var binding ) )
101
79
{
102
80
throw new InvalidOperationException ( @$ "A binding for { mouseFlags } exists ({ binding } ).") ;
103
81
}
104
82
105
- Add ( mouseFlags , new MouseBinding ( commands , mouseFlags ) ) ;
83
+ Add ( mouseFlags , _constructBinding ( commands , mouseFlags ) ) ;
106
84
}
107
85
108
- private readonly Dictionary < MouseFlags , MouseBinding > _bindings = new ( ) ;
109
-
110
86
/// <summary>
111
87
/// Gets the bindings.
112
88
/// </summary>
113
89
/// <returns></returns>
114
- public IEnumerable < KeyValuePair < MouseFlags , MouseBinding > > GetBindings ( )
90
+ public IEnumerable < KeyValuePair < TKey , TBind > > GetBindings ( )
115
91
{
116
92
return _bindings ;
117
93
}
@@ -126,11 +102,11 @@ public IEnumerable<KeyValuePair<MouseFlags, MouseBinding>> GetBindings ()
126
102
/// <param name="command"></param>
127
103
public void Clear ( params Command [ ] command )
128
104
{
129
- KeyValuePair < MouseFlags , MouseBinding > [ ] kvps = _bindings
130
- . Where ( kvp => kvp . Value . Commands . SequenceEqual ( command ) )
131
- . ToArray ( ) ;
105
+ KeyValuePair < TKey , TBind > [ ] kvps = _bindings
106
+ . Where ( kvp => kvp . Value . Commands . SequenceEqual ( command ) )
107
+ . ToArray ( ) ;
132
108
133
- foreach ( KeyValuePair < MouseFlags , MouseBinding > kvp in kvps )
109
+ foreach ( KeyValuePair < TKey , TBind > kvp in kvps )
134
110
{
135
111
Remove ( kvp . Key ) ;
136
112
}
@@ -139,16 +115,46 @@ public void Clear (params Command [] command)
139
115
/// <summary>Gets the <see cref="MouseBinding"/> for the specified combination of <see cref="MouseFlags"/>.</summary>
140
116
/// <param name="mouseEventArgs"></param>
141
117
/// <returns></returns>
142
- public MouseBinding Get ( MouseFlags mouseEventArgs )
118
+ public TBind ? Get ( TKey mouseEventArgs )
143
119
{
144
- if ( TryGet ( mouseEventArgs , out MouseBinding binding ) )
120
+ if ( TryGet ( mouseEventArgs , out var binding ) )
145
121
{
146
122
return binding ;
147
123
}
148
124
149
125
throw new InvalidOperationException ( $ "{ mouseEventArgs } is not bound.") ;
150
126
}
151
127
128
+
129
+ /// <summary>Removes a <see cref="MouseBinding"/> from the collection.</summary>
130
+ /// <param name="mouseEventArgs"></param>
131
+ public void Remove ( TKey mouseEventArgs )
132
+ {
133
+ if ( ! TryGet ( mouseEventArgs , out var _ ) )
134
+ {
135
+ return ;
136
+ }
137
+
138
+ _bindings . Remove ( mouseEventArgs ) ;
139
+ }
140
+ }
141
+
142
+ /// <summary>
143
+ /// Provides a collection of <see cref="MouseBinding"/> objects bound to a combination of <see cref="MouseFlags"/>.
144
+ /// </summary>
145
+ /// <seealso cref="View.MouseBindings"/>
146
+ /// <seealso cref="Command"/>
147
+ public class MouseBindings : Bindings < MouseFlags , MouseBinding >
148
+ {
149
+ /// <summary>
150
+ /// Initializes a new instance. This constructor is used when the <see cref="MouseBindings"/> are not bound to a
151
+ /// <see cref="View"/>. This is used for Application.MouseBindings and unit tests.
152
+ /// </summary>
153
+ public MouseBindings ( ) : base (
154
+ ( commands , flags ) => new MouseBinding ( commands , flags ) ) { }
155
+
156
+
157
+
152
158
/// <summary>
153
159
/// Gets combination of <see cref="MouseFlags"/> bound to the set of commands specified by
154
160
/// <paramref name="commands"/>.
@@ -200,17 +206,6 @@ public MouseFlags GetMouseFlagsFromCommands (params Command [] commands)
200
206
return _bindings . FirstOrDefault ( a => a . Value . Commands . SequenceEqual ( commands ) ) . Key ;
201
207
}
202
208
203
- /// <summary>Removes a <see cref="MouseBinding"/> from the collection.</summary>
204
- /// <param name="mouseEventArgs"></param>
205
- public void Remove ( MouseFlags mouseEventArgs )
206
- {
207
- if ( ! TryGet ( mouseEventArgs , out MouseBinding _ ) )
208
- {
209
- return ;
210
- }
211
-
212
- _bindings . Remove ( mouseEventArgs ) ;
213
- }
214
209
215
210
/// <summary>Replaces the commands already bound to a combination of <see cref="MouseFlags"/>.</summary>
216
211
/// <remarks>
0 commit comments