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

MorganKryze / ConsoleAppVisuals / 8520738714

02 Apr 2024 09:44AM UTC coverage: 96.257%. Remained the same
8520738714

push

github

MorganKryze
📖 (Elements options) update videos

942 of 1051 branches covered (89.63%)

Branch coverage included in aggregate %.

2118 of 2128 relevant lines covered (99.53%)

251.1 hits per line

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

94.44
/src/ConsoleAppVisuals/Window.cs
1
/*
2
    Copyright (c) 2024 Yann M. Vidamment (MorganKryze)
3
    Licensed under GNU GPL v2.0. See full license at: https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/LICENSE.md
4
*/
5
namespace ConsoleAppVisuals;
6

7
/// <summary>
8
/// The <see cref="Window"/> class is a collection of methods to manage visual elements stored in itself.
9
/// You may add, remove, or render elements in the console after adding them to the <see cref="Window"/> class.
10
/// </summary>
11
/// <remarks>
12
/// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
13
/// </remarks>
14
public static class Window
15
{
16
    #region Constants
17
    /// <summary>
18
    /// Defines the interval of milliseconds between different read key of the console (used in the <see cref="Freeze"/> method).
19
    /// </summary>
20
    public const int INTERVAL_BETWEEN_READS = 10;
21
    #endregion
22

23
    #region Fields
24
    private static readonly List<Element> s_elements = new();
1✔
25
    #endregion
26

27
    #region Properties
28
    /// <summary>
29
    /// Gets the next id number each time a new element is added to the window.
30
    /// </summary>
31
    public static int NextId => s_elements.Count;
48✔
32

33
    /// <summary>
34
    /// Gets the number of elements currently stored in the window.
35
    /// </summary>
36
    public static int CountElements => s_elements.Count;
6✔
37

38
    /// <summary>
39
    /// Gets the list of elements stored in the window.
40
    /// </summary>
41
    public static List<Element> Elements => s_elements;
12✔
42
    #endregion
43

44
    #region Managing Methods
45
    /// <summary>
46
    /// Collects a range of <see cref="Element"/> given a start id and a count.
47
    /// </summary>
48
    /// <param name="index">The start id of the range.</param>
49
    /// <param name="count">The number of elements to be collected.</param>
50
    /// <returns>The list of <see cref="Element"/> given a range of ids.</returns>
51
    /// <remarks>
52
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
53
    /// </remarks>
54
    public static List<Element> Range(int index, int count)
55
    {
56
        return s_elements.GetRange(index, count);
31✔
57
    }
58

59
    /// <summary>
60
    /// Gets the first <see cref="Element"/> of the given type present in the <see cref="Window"/>.
61
    /// </summary>
62
    /// <typeparam name="T">The type of the element.</typeparam>
63
    /// <returns>The element with the given type if it exists, null otherwise.</returns>
64
    /// <remarks>
65
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
66
    /// </remarks>
67
    public static T? GetElement<T>()
68
        where T : Element
69
    {
70
        return s_elements.Find(element => element.GetType() == typeof(T)) as T;
16✔
71
    }
72

73
    /// <summary>
74
    /// Gets the <see cref="Element"/> with the given id in the <see cref="Window"/>.
75
    /// </summary>
76
    /// <param name="id">The id of the element.</param>
77
    /// <returns>The <see cref="Element"/> with the given id if it exists, null otherwise.</returns>
78
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of the range of the <see cref="Window"/> elements.</exception>
79
    /// <remarks>
80
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
81
    /// </remarks>
82
    public static T? GetElement<T>(int id)
83
        where T : Element
84
    {
85
        if (id < 0 || id >= s_elements.Count)
5✔
86
        {
87
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
2✔
88
        }
89
        return (T)s_elements[id];
3✔
90
    }
91

92
    /// <summary>
93
    /// Gets the visible <see cref="Element"/> with the given type in the <see cref="Window"/>.
94
    /// </summary>
95
    /// <typeparam name="T">The type of the element.</typeparam>
96
    /// <returns>The visible <see cref="Element"/> with the given type if it exists, null otherwise.</returns>
97
    /// <remarks>
98
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
99
    /// </remarks>
100
    public static T? GetVisibleElement<T>()
101
        where T : Element
102
    {
103
        return s_elements.Find(element => element.GetType() == typeof(T) && element.Visibility)
10✔
104
            as T;
6✔
105
    }
106

107
    /// <summary>
108
    /// Adds one or more <see cref="Element"/> to the window.
109
    /// If the element is passive, it will try to toggle its visibility to true.
110
    /// </summary>
111
    /// <param name="elements">The <see cref="Element"/> to be added.</param>
112
    /// <exception cref="ArgumentException">Thrown when no <see cref="Element"/> are provided.</exception>
113
    /// <exception cref="DuplicateElementException">Thrown when the <see cref="Element"/> is already present in the <see cref="Window"/>.</exception>
114
    /// <remarks>
115
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
116
    /// </remarks>
117
    public static void AddElement(params Element[] elements)
118
    {
119
        if (elements == null || elements.Length == 0)
36✔
120
        {
121
            throw new ArgumentException("No elements provided");
2✔
122
        }
123

124
        foreach (var element in elements)
161✔
125
        {
126
            if (s_elements.Contains(element))
47✔
127
            {
128
                throw new DuplicateElementException(
1✔
129
                    $"Element with ID {element.Id} is already present in the window"
1✔
130
                );
1✔
131
            }
132

133
            element.Id = NextId;
46✔
134
            s_elements.Add(element);
46✔
135
            if (element.Type is ElementType.Passive && IsElementActivatable(element.Id))
46✔
136
            {
137
                element.ToggleVisibility();
17✔
138
            }
139
        }
140
    }
33✔
141

142
    /// <summary>
143
    /// Inserts an <see cref="Element"/> at the given id in the <see cref="Window"/>.
144
    /// </summary>
145
    /// <param name="element">The <see cref="Element"/> to be inserted.</param>
146
    /// <param name="id">The target id to insert the element.</param>
147
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of the range of the <see cref="Window"/> elements.</exception>
148
    /// <remarks>
149
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
150
    /// </remarks>
151
    public static void InsertElement(Element element, int id)
152
    {
153
        if (id < 0 || id > s_elements.Count)
3✔
154
        {
155
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
2✔
156
        }
157
        s_elements.Insert(id, element);
1✔
158
    }
1✔
159

160
    /// <summary>
161
    /// Removes the first <see cref="Element"/> of the given type from the <see cref="Window"/>.
162
    /// </summary>
163
    /// <typeparam name="T">The type of the element.</typeparam>
164
    /// <exception cref="ElementNotFoundException">Thrown when the <see cref="Element"/> is not found in the <see cref="Window"/>.</exception>
165
    /// <returns>True if the element is successfully removed, false otherwise.</returns>
166
    /// <remarks>
167
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
168
    /// </remarks>
169
    public static bool RemoveElement<T>()
170
        where T : Element
171
    {
172
        var element =
4✔
173
            GetElement<T>()
4✔
174
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
4✔
175
        var state = s_elements.Remove(element);
3✔
176
        UpdateIds();
3✔
177
        return state;
3✔
178
    }
179

180
    /// <summary>
181
    /// Removes the <see cref="Element"/> with the given id from the <see cref="Window"/>.
182
    /// </summary>
183
    /// <param name="id">The id of the element to be removed.</param>
184
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of the range of the <see cref="Window"/> elements.</exception>
185
    /// <remarks>
186
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
187
    /// </remarks>
188
    public static void RemoveElement(int id)
189
    {
190
        if (id < 0 || id >= s_elements.Count)
3✔
191
        {
192
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
2✔
193
        }
194
        s_elements.RemoveAt(id);
1✔
195
        UpdateIds();
1✔
196
    }
1✔
197

198
    /// <summary>
199
    /// Removes one or more <see cref="Element"/> from the <see cref="Window"/>.
200
    /// </summary>
201
    /// <param name="elements">The <see cref="Element"/> to be removed.</param>
202
    /// <exception cref="ElementNotFoundException">Thrown when the <see cref="Element"/> is not found in the <see cref="Window"/>.</exception>
203
    /// <returns>True if the element is successfully removed, false otherwise.</returns>
204
    /// <remarks>
205
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
206
    /// </remarks>
207
    public static bool RemoveElement(params Element[] elements)
208
    {
209
        bool state = true;
4✔
210

211
        foreach (var element in elements)
15✔
212
        {
213
            if (!s_elements.Contains(element))
4✔
214
            {
215
                throw new ElementNotFoundException("Invalid element. Not found in the window.");
1✔
216
            }
217
            state &= s_elements.Remove(element);
3✔
218
        }
219

220
        UpdateIds();
3✔
221
        return state;
3✔
222
    }
223

224
    /// <summary>
225
    /// Removes all <see cref="Element"/> from the window.
226
    /// </summary>
227
    /// <remarks>
228
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
229
    /// </remarks>
230
    public static void RemoveAllElements()
231
    {
232
        s_elements.Clear();
454✔
233
    }
454✔
234
    #endregion
235

236
    #region Visibility Methods
237
    /// <summary>
238
    /// Attempts to toggle the visibility of the <see cref="Element"/> with the given id if the element fits the max number constraint.
239
    /// The element will be rendered if the render parameter is true.
240
    /// </summary>
241
    /// <param name="id">The id of the <see cref="Element"/> to activate.</param>
242
    /// <param name="render">If true, the <see cref="Element"/> will be rendered.</param>
243
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of the range of the <see cref="Window"/> elements.</exception>
244
    /// <remarks>
245
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
246
    /// </remarks>
247
    [Visual]
248
    public static void ActivateElement(int id, bool render = true)
249
    {
250
        if (id < 0 || id >= s_elements.Count)
251
        {
252
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
253
        }
254
        if (!s_elements[id].Visibility)
255
        {
256
            s_elements[id].ToggleVisibility();
257
        }
258
        if (render)
259
        {
260
            Render(s_elements[id]);
261
        }
262
    }
263

264
    /// <summary>
265
    /// Attempts to toggle the visibility of the given <see cref="Element"/> if it fits the max number constraint.
266
    /// The element will be rendered if the render parameter is true.
267
    /// </summary>
268
    /// <param name="element">The <see cref="Element"/> to be activated.</param>
269
    /// <param name="render">If true, the <see cref="Element"/> will be rendered.</param>
270
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
271
    /// <remarks>
272
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
273
    /// </remarks>
274
    [Visual]
275
    public static void ActivateElement(Element element, bool render = true)
276
    {
277
        if (!s_elements.Contains(element))
278
        {
279
            throw new ElementNotFoundException("Invalid element. Not found in the window.");
280
        }
281
        if (!element.Visibility)
282
        {
283
            element.ToggleVisibility();
284
        }
285
        if (render)
286
        {
287
            Render(element);
288
        }
289
    }
290

291
    /// <summary>
292
    /// Attempts to toggle the visibility of the first <see cref="Element"/> with the given type if the element fits the max number constraint.
293
    /// </summary>
294
    /// <param name="render">If true, the element will be rendered.</param>
295
    /// <typeparam name="T">The type of the element.</typeparam>
296
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
297
    /// <remarks>
298
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
299
    /// </remarks>
300
    [Visual]
301
    public static void ActivateElement<T>(bool render = true)
302
        where T : Element
303
    {
304
        var element =
305
            GetElement<T>()
306
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
307
        if (!element.Visibility)
308
        {
309
            element.ToggleVisibility();
310
        }
311
        if (render)
312
        {
313
            Render(element);
314
        }
315
    }
316

317
    /// <summary>
318
    /// Attempts to toggle the visibility of all <see cref="Element"/> in the window if the element fits the max number constraint.
319
    /// </summary>
320
    /// <remarks>
321
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
322
    /// </remarks>
323
    public static void ActivateAllElements()
324
    {
325
        foreach (var element in s_elements)
8✔
326
        {
327
            if (!element.Visibility)
2✔
328
            {
329
                element.ToggleVisibility();
2✔
330
            }
331
        }
332
    }
2✔
333

334
    /// <summary>
335
    /// Deactivates the visibility of the <see cref="Element"/> with the given id.
336
    /// The console space taken by the element will be cleared if the clear parameter is true.
337
    /// </summary>
338
    /// <param name="id">The id of the <see cref="Element"/>.</param>
339
    /// <param name="clear">If true, the <see cref="Element"/> space will be cleared from the console.</param>
340
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of the range of the <see cref="Window"/> elements.</exception>
341
    /// <remarks>
342
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
343
    /// </remarks>
344
    public static void DeactivateElement(int id, bool clear = true)
345
    {
346
        if (id < 0 || id >= s_elements.Count)
2✔
347
        {
348
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
1✔
349
        }
350
        if (s_elements[id].Visibility)
1✔
351
        {
352
            s_elements[id].ToggleVisibility();
1✔
353
            if (clear)
1!
354
            {
355
                s_elements[id].Clear();
×
356
            }
357
        }
358
    }
1✔
359

360
    /// <summary>
361
    /// Deactivates the visibility of the given <see cref="Element"/>.
362
    /// The console space taken by the element will be cleared if the clear parameter is true.
363
    /// </summary>
364
    /// <param name="element">The <see cref="Element"/> to be deactivated.</param>
365
    /// <param name="clear">If true, the <see cref="Element"/> space will be cleared from the console.</param>
366
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
367
    /// <remarks>
368
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
369
    /// </remarks>
370
    public static void DeactivateElement(Element element, bool clear = true)
371
    {
372
        if (!s_elements.Contains(element))
3✔
373
        {
374
            throw new ElementNotFoundException("Invalid element. Not found in the window.");
1✔
375
        }
376

377
        if (element.Visibility)
2✔
378
        {
379
            element.ToggleVisibility();
2✔
380
            if (clear)
2!
381
            {
382
                element.Clear();
×
383
            }
384
        }
385
    }
2✔
386

387
    /// <summary>
388
    /// Deactivates the visibility of the first <see cref="Element"/> with the given type.
389
    /// The console space taken by the element will be cleared if the clear parameter is true.
390
    /// </summary>
391
    /// <param name="clear">If true, the element will be cleared.</param>
392
    /// <typeparam name="T">The type of the element.</typeparam>
393
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
394
    /// <remarks>
395
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
396
    /// </remarks>
397
    public static void DeactivateElement<T>(bool clear = true)
398
        where T : Element
399
    {
400
        var element =
3✔
401
            GetVisibleElement<T>()
3✔
402
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
3✔
403
        if (element.Visibility)
2✔
404
        {
405
            element.ToggleVisibility();
2✔
406
            if (clear)
2!
407
            {
408
                element.Clear();
×
409
            }
410
        }
411
    }
2✔
412

413
    /// <summary>
414
    /// This method deactivate the visibility of all <see cref="Element"/>.
415
    /// </summary>
416
    /// <remarks>
417
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
418
    /// </remarks>
419
    public static void DeactivateAllElements(bool clear = true)
420
    {
421
        foreach (var element in s_elements)
4✔
422
        {
423
            DeactivateElement(element, clear);
1✔
424
        }
425
    }
1✔
426
    #endregion
427

428
    #region Utility Methods
429
    private static void UpdateIds()
430
    {
431
        for (int i = 0; i < s_elements.Count; i++)
16✔
432
        {
433
            s_elements[i].Id = i;
1✔
434
        }
435
    }
7✔
436

437
    /// <summary>
438
    /// Tests if an <see cref="Element"/> given by an id can be activated
439
    /// </summary>
440
    /// <param name="id">The id of the <see cref="Element"/> to test.</param>
441
    /// <returns>True if the <see cref="Element"/> can be activated, false otherwise.</returns>
442
    /// <remarks>
443
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
444
    /// </remarks>
445
    public static bool IsElementActivatable(int id)
446
    {
447
        if (s_elements[id].Type is ElementType.Interactive or ElementType.Animated)
44✔
448
        {
449
            int numberOfVisibleInteractiveElements = s_elements.Count(element =>
8✔
450
                element.Type is ElementType.Interactive or ElementType.Animated
8!
451
                && element.Visibility
8✔
452
            );
8✔
453
            return numberOfVisibleInteractiveElements == 0;
8✔
454
        }
455
        else
456
        {
457
            int numberOfVisibleElements = s_elements.Count(element =>
36✔
458
                element.GetType() == s_elements[id].GetType() && element.Visibility
70✔
459
            );
36✔
460
            return numberOfVisibleElements < s_elements[id].MaxNumberOfThisElement;
36✔
461
        }
462
    }
463

464
    /// <summary>
465
    /// Gets the last line available to render an <see cref="Element"/> on the console given a placement.
466
    /// </summary>
467
    /// <param name="placement">The placement to get the line.</param>
468
    /// <returns>The last line available to render an <see cref="Element"/> on the console.</returns>
469
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the placement is invalid.</exception>
470
    /// <remarks>
471
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
472
    /// </remarks>
473
    public static int GetLineAvailable(Placement placement)
474
    {
475
        return placement switch
5!
476
        {
5✔
477
            Placement.TopCenterFullWidth
5✔
478
                => s_elements
1✔
479
                    .Where(e => e.Placement == Placement.TopCenterFullWidth && e.Visibility)
6✔
480
                    .Sum(e => e.Height)
2✔
481
                    + s_elements
1✔
482
                        .Where(e => e.Placement == Placement.TopCenter && e.Visibility)
6✔
483
                        .Sum(e => e.Height)
×
484
                    + s_elements
1✔
485
                        .Where(e => e.Placement == Placement.TopLeft && e.Visibility)
6✔
486
                        .Sum(e => e.Height)
×
487
                    + s_elements
1✔
488
                        .Where(e => e.Placement == Placement.TopRight && e.Visibility)
6✔
489
                        .Sum(e => e.Height),
1✔
490
            Placement.TopCenter
5✔
491
                => s_elements
1✔
492
                    .Where(e => e.Placement == Placement.TopCenterFullWidth && e.Visibility)
6✔
493
                    .Sum(e => e.Height)
2✔
494
                    + s_elements
1✔
495
                        .Where(e => e.Placement == Placement.TopCenter && e.Visibility)
6✔
496
                        .Sum(e => e.Height),
1✔
497
            Placement.TopLeft
5✔
498
                => s_elements
1✔
499
                    .Where(e => e.Placement == Placement.TopCenterFullWidth && e.Visibility)
6✔
500
                    .Sum(e => e.Height)
2✔
501
                    + s_elements
1✔
502
                        .Where(e => e.Placement == Placement.TopLeft && e.Visibility)
6✔
503
                        .Sum(e => e.Height),
1✔
504

5✔
505
            Placement.TopRight
5✔
506
                => s_elements
1✔
507
                    .Where(e => e.Placement == Placement.TopCenterFullWidth && e.Visibility)
6✔
508
                    .Sum(e => e.Height)
2✔
509
                    + s_elements
1✔
510
                        .Where(e => e.Placement == Placement.TopRight && e.Visibility)
6✔
511
                        .Sum(e => e.Height),
1✔
512
            Placement.BottomCenterFullWidth
5✔
513
                => (Console.WindowHeight == 0 ? 0 : Console.WindowHeight - 1)
1!
514
                    - s_elements
1✔
515
                        .Where(e => e.Placement == Placement.BottomCenterFullWidth && e.Visibility)
6✔
516
                        .Sum(e => e.Height),
2✔
517
            _ => throw new ArgumentOutOfRangeException(nameof(Placement), "Invalid placement.")
×
518
        };
5✔
519
    }
520

521
    /// <summary>
522
    /// Checks if the line is not out of the console range.
523
    /// </summary>
524
    /// <param name="line">The line to be checked.</param>
525
    /// <returns>The line if it is valid.</returns>
526
    /// <exception cref="LineOutOfConsoleException">Thrown when the line is out of the console range.</exception>
527
    /// <remarks>
528
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
529
    /// </remarks>
530
    public static int? CheckLine(int? line)
531
    {
532
        int minLine = 0;
5✔
533
        int maxLine = Console.WindowHeight == 0 ? 0 : Console.WindowHeight - 1;
5!
534
        if (line is null)
5✔
535
        {
536
            return line;
3✔
537
        }
538
        if (line < minLine || line > maxLine)
2✔
539
        {
540
            throw new LineOutOfConsoleException(
1✔
541
                $"Invalid line. The line must be between 0 and {maxLine}."
1✔
542
            );
1✔
543
        }
544
        return line;
1✔
545
    }
546

547
    /// <summary>
548
    /// Freezes the execution of the program until the given key is pressed.
549
    /// </summary>
550
    /// <param name="key">The key to be pressed to continue the execution.</param>
551
    /// <remarks>
552
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
553
    /// </remarks>
554
    [Visual]
555
    public static void Freeze(ConsoleKey key = ConsoleKey.Enter)
556
    {
557
        while (Console.ReadKey(intercept: true).Key != key)
558
        {
559
            Thread.Sleep(INTERVAL_BETWEEN_READS);
560
        }
561
    }
562

563
    /// <summary>
564
    /// Displays all the visible <see cref="Element"/> in the window.
565
    /// </summary>
566
    /// <remarks>
567
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
568
    /// </remarks>
569
    [Visual]
570
    public static void Render()
571
    {
572
        Clear();
573
        Core.IsScreenUpdated();
574
        foreach (var element in s_elements)
575
        {
576
            element.RenderElement();
577
        }
578
    }
579

580
    /// <summary>
581
    /// Displays the given <see cref="Element"/> in the window.
582
    /// </summary>
583
    /// <param name="elements">The <see cref="Element"/> to be displayed.</param>
584
    /// <exception cref="ElementNotFoundException">Thrown when the element is not found in the <see cref="Window"/>.</exception>
585
    /// <remarks>
586
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
587
    /// </remarks>
588
    [Visual]
589
    public static void Render(params Element[] elements)
590
    {
591
        if (Core.IsScreenUpdated())
592
        {
593
            Render();
594
            return;
595
        }
596

597
        foreach (var element in elements)
598
        {
599
            if (!s_elements.Contains(element))
600
            {
601
                throw new ElementNotFoundException($"Element {element} is not in the Window.");
602
            }
603
            element.RenderElement();
604
        }
605
    }
606

607
    /// <summary>
608
    /// Renders the space of all visible <see cref="Element"/> in the window.
609
    /// May ignore the visibility to display the hidden <see cref="Element"/> spaces.
610
    /// </summary>
611
    /// <param name="ignoreVisibility">If true, the space of the hidden <see cref="Element"/> will be drawn.</param>
612
    /// <returns>True if the space of the <see cref="Element"/> is successfully drawn, false otherwise.</returns>
613
    /// <remarks>
614
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
615
    /// </remarks>
616
    [Visual]
617
    public static bool RenderElementsSpace(bool ignoreVisibility = false)
618
    {
619
        foreach (var element in s_elements)
620
        {
621
            element.RenderElementSpace(ignoreVisibility);
622
        }
623
        return true;
624
    }
625

626
    /// <summary>
627
    /// Clears the console given a range of lines.
628
    /// </summary>
629
    /// <param name="continuous">If true, the window will be cleared continuously.</param>
630
    /// <param name="startLine">The start line of the window to be cleared.</param>
631
    /// <param name="length">The number of lines to be cleared.</param>
632
    /// <param name="step">The step of the window to be cleared.</param>
633
    /// <returns>True if the window is successfully cleared, false otherwise.</returns>
634
    /// <remarks>
635
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
636
    /// </remarks>
637
    [Visual]
638
    public static bool Clear(
639
        bool continuous = false,
640
        int? startLine = null,
641
        int? length = null,
642
        int step = 1
643
    )
644
    {
645
        int stepMax = Console.WindowHeight == 0 ? 1 : Console.WindowHeight;
646
        startLine = CheckLine(startLine) ?? 0;
647
        length = CheckLine(startLine + length) ?? Console.WindowHeight;
648
        if (step < 1 || step > stepMax)
649
        {
650
            throw new ArgumentOutOfRangeException(
651
                nameof(step),
652
                "Invalid step, less than 0 or greater than the window height."
653
            );
654
        }
655

656
        for (int i = (int)startLine; i < (int)length; i += step)
657
        {
658
            if (continuous)
659
            {
660
                Core.WriteContinuousString("".PadRight(Console.WindowWidth), i, false, 100, 10);
661
            }
662
            else
663
            {
664
                Core.WritePositionedString(
665
                    "".PadRight(Console.WindowWidth),
666
                    Placement.TopCenter,
667
                    false,
668
                    i
669
                );
670
            }
671
        }
672
        return true;
673
    }
674

675
    /// <summary>
676
    /// Clears the console and hide the cursor.
677
    /// </summary>
678
    /// <remarks>
679
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
680
    /// </remarks>
681
    [Visual]
682
    public static void Open()
683
    {
684
        Clear();
685
        Console.CursorVisible = false;
686
    }
687

688
    /// <summary>
689
    /// Clears the console, show the cursor, and exit the program.
690
    /// </summary>
691
    /// <remarks>
692
    /// For more information, consider visiting the documentation available <a href="https://morgankryze.github.io/ConsoleAppVisuals/">here</a>.
693
    /// </remarks>
694
    [Visual]
695
    public static void Close()
696
    {
697
        Core.LoadTerminalColorPanel();
698
        Clear(true);
699
        Console.CursorVisible = true;
700
        Console.SetCursorPosition(0, 0);
701
        Environment.Exit(0);
702
    }
703
    #endregion
704
}
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

© 2026 Coveralls, Inc