• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MorganKryze / ConsoleAppVisuals / 8127311540

03 Mar 2024 02:56AM UTC coverage: 85.254%. Remained the same
8127311540

push

github

MorganKryze
🚑 Critical fix: update regex to publish

867 of 1080 branches covered (80.28%)

Branch coverage included in aggregate %.

1700 of 1931 relevant lines covered (88.04%)

272.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.74
/src/ConsoleAppVisuals/elements/interactive_elements/IntSelector.cs
1
/*
2
    GNU GPL License 2024 MorganKryze(Yann Vidamment)
3
    For full license information, please visit: https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/LICENSE
4
*/
5
namespace ConsoleAppVisuals.Elements;
6

7
/// <summary>
8
/// Defines the number selector of the console window.
9
/// </summary>
10
/// <remarks>
11
/// For more information, refer to the following resources:
12
/// <list type="bullet">
13
/// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
14
/// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
15
/// </list>
16
/// </remarks>
17
public class IntSelector : InteractiveElement<int>
18
{
19
    #region Fields
20
    private string _question;
21
    private int _minimumValue;
22
    private int _maximumValue;
23
    private int _startValue;
24
    private int _step;
25
    private bool _roundedCorners;
26
    private Placement _placement;
27
    #endregion
28

29
    #region Properties
30
    /// <summary>
31
    /// The placement of the selector on the console.
32
    /// </summary>
33
    public override Placement Placement => _placement;
21✔
34

35
    /// <summary>
36
    /// The height of the selector.
37
    /// </summary>
38
    public override int Height => 7;
3✔
39

40
    /// <summary>
41
    /// The width of the selector.
42
    /// </summary>
43
    public override int Width =>
44
        Math.Max(
3✔
45
            _question.Length,
3✔
46
            $" {Core.GetSelector.Item1} {BuildNumber(_maximumValue)} {Core.GetSelector.Item2} ".Length
3✔
47
        );
3✔
48

49
    /// <summary>
50
    /// The question to ask the user.
51
    /// </summary>
52
    public string Question => _question;
3✔
53

54
    /// <summary>
55
    /// The minimum value of the selector.
56
    /// </summary>
57
    public int Min => _minimumValue;
3✔
58

59
    /// <summary>
60
    /// The maximum value of the selector.
61
    /// </summary>
62
    public int Max => _maximumValue;
3✔
63

64
    /// <summary>
65
    /// The start value of the selector.
66
    /// </summary>
67
    public int Start => _startValue;
3✔
68

69
    /// <summary>
70
    /// The step of the selector.
71
    /// </summary>
72
    public int Step => _step;
3✔
73

74
    /// <summary>
75
    /// Whether the corners of the selector are rounded.
76
    /// </summary>
77
    public bool RoundedCorners => _roundedCorners;
3✔
78
    #endregion
79

80
    #region Constructor
81
    /// <summary>
82
    /// The constructor of the intSelector class.
83
    /// </summary>
84
    /// <param name="question">The question to ask the user.</param>
85
    /// <param name="min">The minimum value of the selector.</param>
86
    /// <param name="max">The maximum value of the selector.</param>
87
    /// <param name="start">The start value of the selector.</param>
88
    /// <param name="step">The step of the selector.</param>
89
    /// <param name="placement">The placement of the selector on the console.</param>
90
    /// <param name="roundedCorners">Whether the corners of the selector are rounded.</param>
91
    /// <remarks>
92
    /// For more information, refer to the following resources:
93
    /// <list type="bullet">
94
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
95
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
96
    /// </list>
97
    /// </remarks>
98
    public IntSelector(
45✔
99
        string question,
45✔
100
        int min,
45✔
101
        int max,
45✔
102
        int start = 0,
45✔
103
        int step = 100,
45✔
104
        Placement placement = Placement.TopCenter,
45✔
105
        bool roundedCorners = false
45✔
106
    )
45✔
107
    {
108
        _question = question;
45✔
109
        CheckMinNotHigherThanMax(min, max);
45✔
110
        _minimumValue = min;
39✔
111
        _maximumValue = max;
39✔
112
        _startValue = CheckStart(start, _minimumValue, _maximumValue);
39✔
113
        _step = CheckStep(step, _minimumValue, _maximumValue);
30✔
114
        _placement = placement;
24✔
115
        _roundedCorners = roundedCorners;
24✔
116
    }
24✔
117

118
    private static void CheckMinNotHigherThanMax(int min, int max)
119
    {
120
        if (min > max)
45✔
121
            throw new ArgumentException(
6✔
122
                "The minimum value cannot be greater than the maximum value."
6✔
123
            );
6✔
124
    }
39✔
125

126
    private static int CheckStart(int start, int min, int max)
127
    {
128
        if (start < min)
39✔
129
            throw new ArgumentException("The start value cannot be less than the minimum value.");
6✔
130
        if (start > max)
33✔
131
            throw new ArgumentException(
3✔
132
                "The start value cannot be greater than the maximum value."
3✔
133
            );
3✔
134
        return start;
30✔
135
    }
136

137
    private static int CheckStep(int step, int min, int max)
138
    {
139
        if (step > max - min)
30✔
140
            throw new ArgumentException(
3✔
141
                "The step cannot be greater than the difference between the minimum and maximum values."
3✔
142
            );
3✔
143
        if (step < 1)
27✔
144
            throw new ArgumentException("The step cannot be less than 1.");
3✔
145
        return step;
24✔
146
    }
147
    #endregion
148

149
    #region Methods
150
    /// <summary>
151
    /// This method is used to update the question of the selector.
152
    /// </summary>
153
    /// <param name="question">The question to ask the user.</param>
154
    /// <remarks>
155
    /// For more information, refer to the following resources:
156
    /// <list type="bullet">
157
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
158
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
159
    /// </list>
160
    /// </remarks>
161
    public void UpdateQuestion(string question)
162
    {
163
        _question = question;
×
164
    }
×
165

166
    /// <summary>
167
    /// This method is used to update the minimum value of the selector.
168
    /// </summary>
169
    /// <param name="min">The minimum value of the selector.</param>
170
    /// <remarks>
171
    /// For more information, refer to the following resources:
172
    /// <list type="bullet">
173
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
174
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
175
    /// </list>
176
    /// </remarks>
177
    public void UpdateMin(int min)
178
    {
179
        CheckMinNotHigherThanMax(min, _maximumValue);
×
180
        _minimumValue = min;
×
181
        _startValue = CheckStart(_startValue, _minimumValue, _maximumValue);
×
182
        _step = CheckStep(_step, _minimumValue, _maximumValue);
×
183
    }
×
184

185
    /// <summary>
186
    /// This method is used to update the maximum value of the selector.
187
    /// </summary>
188
    /// <param name="max">The maximum value of the selector.</param>
189
    /// <remarks>
190
    /// For more information, refer to the following resources:
191
    /// <list type="bullet">
192
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
193
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
194
    /// </list>
195
    /// </remarks>
196
    public void UpdateMax(int max)
197
    {
198
        CheckMinNotHigherThanMax(_minimumValue, max);
×
199
        _maximumValue = max;
×
200
        _startValue = CheckStart(_startValue, _minimumValue, _maximumValue);
×
201
        _step = CheckStep(_step, _minimumValue, _maximumValue);
×
202
    }
×
203

204
    /// <summary>
205
    /// This method is used to update the start value of the selector.
206
    /// </summary>
207
    /// <param name="start">The start value of the selector.</param>
208
    /// <remarks>
209
    /// For more information, refer to the following resources:
210
    /// <list type="bullet">
211
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
212
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
213
    /// </list>
214
    /// </remarks>
215
    public void UpdateStart(int start)
216
    {
217
        _startValue = CheckStart(start, _minimumValue, _maximumValue);
×
218
    }
×
219

220
    /// <summary>
221
    /// This method is used to update the step of the selector.
222
    /// </summary>
223
    /// <param name="step">The step of the selector.</param>
224
    /// <remarks>
225
    /// For more information, refer to the following resources:
226
    /// <list type="bullet">
227
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
228
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
229
    /// </list>
230
    /// </remarks>
231
    public void UpdateStep(int step)
232
    {
233
        _step = CheckStep(step, _minimumValue, _maximumValue);
×
234
    }
×
235

236
    /// <summary>
237
    /// This method is used to update the placement of the selector.
238
    /// </summary>
239
    /// <param name="placement">The placement of the selector on the console.</param>
240
    /// <remarks>
241
    /// For more information, refer to the following resources:
242
    /// <list type="bullet">
243
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
244
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
245
    /// </list>
246
    /// </remarks>
247
    public void UpdatePlacement(Placement placement)
248
    {
249
        _placement = placement;
×
250
    }
×
251

252
    /// <summary>
253
    /// This method is used to update the rounded corners of the selector.
254
    /// </summary>
255
    /// <param name="roundedCorners">Whether the corners of the selector are rounded.</param>
256
    /// <remarks>
257
    /// For more information, refer to the following resources:
258
    /// <list type="bullet">
259
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
260
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
261
    /// </list>
262
    /// </remarks>
263
    public void SetRoundedCorners(bool roundedCorners = true)
264
    {
265
        _roundedCorners = roundedCorners;
×
266
    }
×
267

268
    /// <summary>
269
    /// This method is used to draw the selector on the console.
270
    /// </summary>
271
    [Visual]
272
    protected override void RenderElementActions()
273
    {
274
        Core.WriteContinuousString(_question, Line, default, 1500, 50);
275
        int currentNumber = _startValue;
276
        int lineSelector = Line + 4;
277
        while (true)
278
        {
279
            DisplayChoices(lineSelector, currentNumber);
280

281
            switch (Console.ReadKey(true).Key)
282
            {
283
                case ConsoleKey.UpArrow:
284
                case ConsoleKey.Z:
285
                    currentNumber = NextNumber(Direction.Up, currentNumber);
286
                    break;
287
                case ConsoleKey.DownArrow:
288
                case ConsoleKey.S:
289
                    currentNumber = NextNumber(Direction.Down, currentNumber);
290
                    break;
291
                case ConsoleKey.Enter:
292
                    SendResponse(
293
                        this,
294
                        new InteractionEventArgs<int>(Output.Selected, currentNumber)
295
                    );
296
                    return;
297
                case ConsoleKey.Escape:
298
                    SendResponse(
299
                        this,
300
                        new InteractionEventArgs<int>(Output.Escaped, currentNumber)
301
                    );
302
                    return;
303
                default:
304
                    break;
305
            }
306
            Thread.Sleep(1);
307
        }
308
    }
309

310
    [Visual]
311
    void DisplayChoices(int lineSelector, int currentNumber)
312
    {
313
        Core.WritePositionedString(
314
            BuildLine(Direction.Up),
315
            TextAlignment.Center,
316
            false,
317
            lineSelector - 2
318
        );
319
        Core.WritePositionedString(
320
            BuildNumber(NextNumber(Direction.Up, currentNumber)),
321
            TextAlignment.Center,
322
            false,
323
            lineSelector - 1
324
        );
325
        Core.WritePositionedString(
326
            $" {Core.GetSelector.Item1} {BuildNumber(currentNumber)} {Core.GetSelector.Item2} ",
327
            TextAlignment.Center,
328
            true,
329
            lineSelector
330
        );
331
        Core.WritePositionedString(
332
            BuildNumber(NextNumber(Direction.Down, currentNumber)),
333
            TextAlignment.Center,
334
            false,
335
            lineSelector + 1
336
        );
337
        Core.WritePositionedString(
338
            BuildLine(Direction.Down),
339
            TextAlignment.Center,
340
            false,
341
            lineSelector + 2
342
        );
343
    }
344

345
    [Visual]
346
    int NextNumber(Direction direction, int currentNumber)
347
    {
348
        if (direction == Direction.Up)
349
        {
350
            if (currentNumber + _step <= _maximumValue)
351
                return currentNumber + _step;
352
            else if (currentNumber + _step > _maximumValue)
353
                return _minimumValue;
354
        }
355
        else
356
        {
357
            if (currentNumber - _step >= _minimumValue)
358
                return currentNumber - _step;
359
            else if (currentNumber - _step < _minimumValue)
360
                return _maximumValue;
361
        }
362
        return currentNumber;
363
    }
364

365
    [Visual]
366
    string BuildLine(Direction direction)
367
    {
368
        string corners = _roundedCorners ? "╭╮╰╯" : "┌┐└┘";
369
        StringBuilder line = new();
370
        for (int i = 0; i < _maximumValue.ToString().Length + 2; i++)
371
            line.Append('─');
372
        if (direction == Direction.Up)
373
            line.Insert(0, corners[0].ToString(), 1).Append(corners[1], 1);
374
        else
375
            line.Insert(0, corners[2].ToString(), 1).Append(corners[3], 1);
376
        return line.ToString();
377
    }
378

379
    string BuildNumber(int number)
380
    {
381
        StringBuilder numberStr = new();
3✔
382
        numberStr.Append("│ ");
3✔
383
        numberStr.Append(
3✔
384
            number.ToString().ResizeString(_maximumValue.ToString().Length, TextAlignment.Center)
3✔
385
        );
3✔
386
        numberStr.Append(" │");
3✔
387
        return numberStr.ToString();
3✔
388
    }
389
    #endregion
390
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc