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

MorganKryze / ConsoleAppVisuals / 8418737641

25 Mar 2024 10:35AM UTC coverage: 93.788%. Remained the same
8418737641

push

github

MorganKryze
🚑 (TableSelector) fix render issue with first display not rendering properly

917 of 1042 branches covered (88.0%)

Branch coverage included in aggregate %.

2012 of 2081 relevant lines covered (96.68%)

252.64 hits per line

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

94.8
/src/ConsoleAppVisuals/Window.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;
6

7
/// <summary>
8
/// The Window class manages the elements that are to be displayed on the console.
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 static class Window
18
{
19
    #region Fields: s_elements
20
    private static readonly List<Element> s_elements = new();
1✔
21
    #endregion
22

23
    #region Constants: DefaultVisibility
24
    /// <summary>
25
    /// The default visibility of the elements when they are added to the window.
26
    /// </summary>
27
    /// <remarks>
28
    /// This value should not be changed.
29
    /// Each time the user adds an element to the window, it will try to toggle the visibility of the element.
30
    /// </remarks>
31
    public const bool DEFAULT_ELEMENT_VISIBILITY = false;
32

33
    /// <summary>
34
    /// Defines the interval of milliseconds between different read key of the console (used in the <see cref="Freeze"/> method).
35
    /// </summary>
36
    public const int INTERVAL_BETWEEN_READS = 10;
37
    #endregion
38

39
    #region Properties: NextId, NumberOfElements, Elements
40
    /// <summary>
41
    /// Gives the next id number each time a new element is added to the window.
42
    /// </summary>
43
    public static int NextId => s_elements.Count;
48✔
44

45
    /// <summary>
46
    /// Gives the number of elements in the window.
47
    /// </summary>
48
    public static int CountElements => s_elements.Count;
6✔
49

50
    /// <summary>
51
    /// Gives the list of elements in the window.
52
    /// </summary>
53
    public static List<Element> Elements => s_elements;
12✔
54
    #endregion
55

56
    #region Managing Methods: Get, Add, Insert, Remove, RemoveAll
57

58
    /// <summary>
59
    /// This method returns a range of elements given a start and end ids.
60
    /// </summary>
61
    /// <param name="start">The start id of the range.</param>
62
    /// <param name="end">The end id of the range.</param>
63
    /// <returns>The range of elements from the start to the end id.</returns>
64
    public static List<Element> GetRange(int start, int end)
65
    {
66
        return s_elements.GetRange(start, end);
32✔
67
    }
68

69
    /// <summary>
70
    /// This method returns the first element of the given type.
71
    /// </summary>
72
    /// <typeparam name="T">The type of the element.</typeparam>
73
    /// <returns>The element with the given type if it exists, null otherwise.</returns>
74
    /// <remarks>
75
    /// For more information, refer to the following resources:
76
    /// <list type="bullet">
77
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
78
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
79
    /// </list>
80
    /// </remarks>
81
    public static T? GetElement<T>()
82
        where T : Element
83
    {
84
        return s_elements.Find(element => element.GetType() == typeof(T)) as T;
16✔
85
    }
86

87
    /// <summary>
88
    /// This method returns the first element of the given type and id.
89
    /// </summary>
90
    /// <param name="id">The id of the element.</param>
91
    /// <returns>The element with the given id if it exists, null otherwise.</returns>
92
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of range.</exception>
93
    /// <remarks>
94
    /// For more information, refer to the following resources:
95
    /// <list type="bullet">
96
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
97
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
98
    /// </list>
99
    /// </remarks>
100
    public static T? GetElement<T>(int id)
101
        where T : Element
102
    {
103
        if (id < 0 || id >= s_elements.Count)
5✔
104
        {
105
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
2✔
106
        }
107
        return (T)s_elements[id];
3✔
108
    }
109

110
    /// <summary>
111
    /// This method returns the first visible element with the given type.
112
    /// </summary>
113
    /// <typeparam name="T">The type of the element.</typeparam>
114
    /// <returns>The visible element with the given type if it exists, null otherwise.</returns>
115
    /// <remarks>
116
    /// For more information, refer to the following resources:
117
    /// <list type="bullet">
118
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
119
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
120
    /// </list>
121
    /// </remarks>
122
    public static T? GetVisibleElement<T>()
123
        where T : Element
124
    {
125
        return s_elements.Find(element => element.GetType() == typeof(T) && element.Visibility)
10✔
126
            as T;
6✔
127
    }
128

129
    /// <summary>
130
    /// This method adds elements to the window.
131
    /// </summary>
132
    /// <param name="elements">The elements to be added.</param>
133
    /// <exception cref="ArgumentException">Thrown when no elements are provided.</exception>
134
    /// <exception cref="DuplicateElementException">Thrown when the element is already present in the window.</exception>
135
    /// <remarks>
136
    /// For more information, refer to the following resources:
137
    /// <list type="bullet">
138
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
139
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
140
    /// </list>
141
    /// </remarks>
142
    public static void AddElement(params Element[] elements)
143
    {
144
        if (elements == null || elements.Length == 0)
36✔
145
        {
146
            throw new ArgumentException("No elements provided");
2✔
147
        }
148

149
        foreach (var element in elements)
161✔
150
        {
151
            if (s_elements.Contains(element))
47✔
152
            {
153
                throw new DuplicateElementException(
1✔
154
                    $"Element with ID {element.Id} is already present in the window"
1✔
155
                );
1✔
156
            }
157

158
            element.Id = NextId;
46✔
159
            s_elements.Add(element);
46✔
160
            if (!element.IsInteractive && AllowVisibilityToggle(element.Id))
46✔
161
            {
162
                element.ToggleVisibility();
17✔
163
            }
164
        }
165
    }
33✔
166

167
    /// <summary>
168
    /// This method inserts an element to the window at the given id.
169
    /// </summary>
170
    /// <param name="element">The element to be inserted.</param>
171
    /// <param name="id">The id of the element.</param>
172
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of range.</exception>
173
    /// <remarks>
174
    /// For more information, refer to the following resources:
175
    /// <list type="bullet">
176
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
177
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
178
    /// </list>
179
    /// </remarks>
180
    public static void InsertElement(Element element, int id)
181
    {
182
        if (id < 0 || id > s_elements.Count)
3✔
183
        {
184
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
2✔
185
        }
186
        s_elements.Insert(id, element);
1✔
187
    }
1✔
188

189
    /// <summary>
190
    /// This method removes the first element with the given type.
191
    /// </summary>
192
    /// <typeparam name="T">The type of the element.</typeparam>
193
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
194
    /// <returns>True if the element is successfully removed, false otherwise.</returns>
195
    /// <remarks>
196
    /// For more information, refer to the following resources:
197
    /// <list type="bullet">
198
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
199
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
200
    /// </list>
201
    /// </remarks>
202
    public static bool RemoveElement<T>()
203
        where T : Element
204
    {
205
        var element =
4✔
206
            GetElement<T>()
4✔
207
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
4✔
208
        var state = s_elements.Remove(element);
3✔
209
        UpdateIDs();
3✔
210
        return state;
3✔
211
    }
212

213
    /// <summary>
214
    /// This method removes the element with the given id.
215
    /// </summary>
216
    /// <param name="id">The id of the element.</param>
217
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of range.</exception>
218
    /// <remarks>
219
    /// For more information, refer to the following resources:
220
    /// <list type="bullet">
221
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
222
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
223
    /// </list>
224
    /// </remarks>
225
    public static void RemoveElement(int id)
226
    {
227
        if (id < 0 || id >= s_elements.Count)
3✔
228
        {
229
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
2✔
230
        }
231
        s_elements.RemoveAt(id);
1✔
232
        UpdateIDs();
1✔
233
    }
1✔
234

235
    /// <summary>
236
    /// This method removes the given element.
237
    /// </summary>
238
    /// <param name="elements">The elements to be removed.</param>
239
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
240
    /// <returns>True if the element is successfully removed, false otherwise.</returns>
241
    /// <remarks>
242
    /// For more information, refer to the following resources:
243
    /// <list type="bullet">
244
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
245
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
246
    /// </list>
247
    /// </remarks>
248
    public static bool RemoveElement(params Element[] elements)
249
    {
250
        bool state = true;
4✔
251

252
        foreach (var element in elements)
15✔
253
        {
254
            if (!s_elements.Contains(element))
4✔
255
            {
256
                throw new ElementNotFoundException("Invalid element. Not found in the window.");
1✔
257
            }
258
            state &= s_elements.Remove(element);
3✔
259
        }
260

261
        UpdateIDs();
3✔
262
        return state;
3✔
263
    }
264

265
    /// <summary>
266
    /// This method removes all elements from the window.
267
    /// </summary>
268
    /// <remarks>
269
    /// For more information, refer to the following resources:
270
    /// <list type="bullet">
271
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
272
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
273
    /// </list>
274
    /// </remarks>
275
    public static void RemoveAllElements()
276
    {
277
        s_elements.Clear();
401✔
278
    }
401✔
279
    #endregion
280

281
    #region Visibility Methods: ActivateElement, ActivateAllElements, DeactivateElement, DeactivateAllElements
282
    /// <summary>
283
    /// This method attempts to activate the visibility of the element with the given id.
284
    /// </summary>
285
    /// <param name="id">The id of the element.</param>
286
    /// <param name="render">If true, the element will be rendered.</param>
287
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of range.</exception>
288
    /// <remarks>
289
    /// For more information, refer to the following resources:
290
    /// <list type="bullet">
291
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
292
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
293
    /// </list>
294
    /// </remarks>
295
    [Visual]
296
    public static void ActivateElement(int id, bool render = true)
297
    {
298
        if (id < 0 || id >= s_elements.Count)
299
        {
300
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
301
        }
302
        if (!s_elements[id].Visibility)
303
        {
304
            s_elements[id].ToggleVisibility();
305
        }
306
        if (render)
307
        {
308
            Render(s_elements[id]);
309
        }
310
    }
311

312
    /// <summary>
313
    /// This method attempts to activate the visibility of the given element.
314
    /// </summary>
315
    /// <param name="element">The element to be activated.</param>
316
    /// <param name="render">If true, the element will be rendered.</param>
317
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
318
    [Visual]
319
    public static void ActivateElement(Element element, bool render = true)
320
    {
321
        if (!s_elements.Contains(element))
322
        {
323
            throw new ElementNotFoundException("Invalid element. Not found in the window.");
324
        }
325
        if (!element.Visibility)
326
        {
327
            element.ToggleVisibility();
328
        }
329
        if (render)
330
        {
331
            Render(element);
332
        }
333
    }
334

335
    /// <summary>
336
    /// This method attempts to activate the visibility of the first element of the given type.
337
    /// </summary>
338
    /// <param name="render">If true, the element will be rendered.</param>
339
    /// <typeparam name="T">The type of the element.</typeparam>
340
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
341
    /// <remarks>
342
    /// For more information, refer to the following resources:
343
    /// <list type="bullet">
344
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
345
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
346
    /// </list>
347
    /// </remarks>
348
    [Visual]
349
    public static void ActivateElement<T>(bool render = true)
350
        where T : Element
351
    {
352
        var element =
353
            GetElement<T>()
354
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
355
        if (!element.Visibility)
356
        {
357
            element.ToggleVisibility();
358
        }
359
        if (render)
360
        {
361
            Render(element);
362
        }
363
    }
364

365
    /// <summary>
366
    /// This method attempts to activate the visibility of all elements.
367
    /// </summary>
368
    /// <remarks>
369
    /// For more information, refer to the following resources:
370
    /// <list type="bullet">
371
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
372
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
373
    /// </list>
374
    /// </remarks>
375
    public static void ActivateAllElements()
376
    {
377
        foreach (var element in s_elements)
8✔
378
        {
379
            if (!element.Visibility)
2✔
380
            {
381
                element.ToggleVisibility();
2✔
382
            }
383
        }
384
    }
2✔
385

386
    /// <summary>
387
    /// This method to deactivate the visibility of the element with the given id.
388
    /// </summary>
389
    /// <param name="id">The id of the element.</param>
390
    /// <param name="clear">If true, the element will be cleared from the console.</param>
391
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of range.</exception>
392
    /// <remarks>
393
    /// For more information, refer to the following resources:
394
    /// <list type="bullet">
395
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
396
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
397
    /// </list>
398
    /// </remarks>
399
    public static void DeactivateElement(int id, bool clear = true)
400
    {
401
        if (id < 0 || id >= s_elements.Count)
2✔
402
        {
403
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
1✔
404
        }
405
        if (s_elements[id].Visibility)
1✔
406
        {
407
            s_elements[id].ToggleVisibility();
1✔
408
            if (clear)
1!
409
            {
410
                s_elements[id].Clear();
×
411
            }
412
        }
413
    }
1✔
414

415
    /// <summary>
416
    /// This method deactivate the visibility of the element with the given type.
417
    /// </summary>
418
    /// <param name="element">The element to be deactivated.</param>
419
    /// <param name="clear">If true, the element will be cleared from the console.</param>
420
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
421
    /// <remarks>
422
    /// For more information, refer to the following resources:
423
    /// <list type="bullet">
424
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
425
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
426
    /// </list>
427
    /// </remarks>
428
    public static void DeactivateElement(Element element, bool clear = true)
429
    {
430
        if (!s_elements.Contains(element))
2✔
431
        {
432
            throw new ElementNotFoundException("Invalid element. Not found in the window.");
1✔
433
        }
434

435
        if (element.Visibility)
1✔
436
        {
437
            element.ToggleVisibility();
1✔
438
            if (clear)
1!
439
            {
440
                element.Clear();
×
441
            }
442
        }
443
    }
1✔
444

445
    /// <summary>
446
    /// This method deactivate the visibility of the first element with the given type.
447
    /// </summary>
448
    /// <param name="clear">If true, the element will be cleared.</param>
449
    /// <typeparam name="T">The type of the element.</typeparam>
450
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
451
    /// <remarks>
452
    /// For more information, refer to the following resources:
453
    /// <list type="bullet">
454
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
455
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
456
    /// </list>
457
    /// </remarks>
458
    public static void DeactivateElement<T>(bool clear = true)
459
        where T : Element
460
    {
461
        var element =
3✔
462
            GetVisibleElement<T>()
3✔
463
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
3✔
464
        if (element.Visibility)
2✔
465
        {
466
            element.ToggleVisibility();
2✔
467
            if (clear)
2!
468
            {
469
                element.Clear();
×
470
            }
471
        }
472
    }
2✔
473

474
    /// <summary>
475
    /// This method deactivate the visibility of all elements.
476
    /// </summary>
477
    /// <remarks>
478
    /// For more information, refer to the following resources:
479
    /// <list type="bullet">
480
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
481
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
482
    /// </list>
483
    /// </remarks>
484
    public static void DeactivateAllElements()
485
    {
486
        foreach (var element in s_elements)
4✔
487
        {
488
            if (element.Visibility)
1✔
489
            {
490
                element.ToggleVisibility();
1✔
491
            }
492
        }
493
    }
1✔
494
    #endregion
495

496
    #region Utility Methods: AllowVisibilityToggle, GetLineAvailable, Clear, StopExecution, Refresh
497
    private static void UpdateIDs()
498
    {
499
        for (int i = 0; i < s_elements.Count; i++)
16✔
500
        {
501
            s_elements[i].Id = i;
1✔
502
        }
503
    }
7✔
504

505
    /// <summary>
506
    /// This method checks if the element can be toggled to visible.
507
    /// </summary>
508
    /// <param name="id">The id of the element.</param>
509
    /// <returns>True if the element can be toggled to visible, false otherwise.</returns>
510
    public static bool AllowVisibilityToggle(int id)
511
    {
512
        if (s_elements[id].IsInteractive)
44✔
513
        {
514
            int numberOfVisibleInteractiveElements = s_elements.Count(element =>
8✔
515
                element.IsInteractive && element.Visibility
8!
516
            );
8✔
517
            return numberOfVisibleInteractiveElements == 0;
8✔
518
        }
519
        else
520
        {
521
            int numberOfVisibleElements = s_elements.Count(element =>
36✔
522
                element.GetType() == s_elements[id].GetType() && element.Visibility
70✔
523
            );
36✔
524
            return numberOfVisibleElements < s_elements[id].MaxNumberOfThisElement;
36✔
525
        }
526
    }
527

528
    /// <summary>
529
    /// This method gets the last line available to draw an element on the console from a placement.
530
    /// </summary>
531
    /// <param name="placement">The placement of the element.</param>
532
    /// <returns>The last line available to draw an element on the console from a placement.</returns>
533
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the placement is invalid.</exception>
534
    /// <remarks>
535
    /// For more information, refer to the following resources:
536
    /// <list type="bullet">
537
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
538
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
539
    /// </list>
540
    /// </remarks>
541
    public static int GetLineAvailable(Placement placement)
542
    {
543
        return placement switch
6!
544
        {
6✔
545
            Placement.TopCenterFullWidth
6✔
546
                => s_elements
1✔
547
                    .Where(e => e.Placement == Placement.TopCenterFullWidth && e.Visibility)
6✔
548
                    .Sum(e => e.Height)
2✔
549
                    + s_elements
1✔
550
                        .Where(e => e.Placement == Placement.TopCenter && e.Visibility)
6✔
551
                        .Sum(e => e.Height)
×
552
                    + s_elements
1✔
553
                        .Where(e => e.Placement == Placement.TopLeft && e.Visibility)
6✔
554
                        .Sum(e => e.Height)
×
555
                    + s_elements
1✔
556
                        .Where(e => e.Placement == Placement.TopRight && e.Visibility)
6✔
557
                        .Sum(e => e.Height),
1✔
558
            Placement.TopCenter
6✔
559
                => s_elements
1✔
560
                    .Where(e => e.Placement == Placement.TopCenterFullWidth && e.Visibility)
6✔
561
                    .Sum(e => e.Height)
2✔
562
                    + s_elements
1✔
563
                        .Where(e => e.Placement == Placement.TopCenter && e.Visibility)
6✔
564
                        .Sum(e => e.Height),
1✔
565
            Placement.TopLeft
6✔
566
                => s_elements
1✔
567
                    .Where(e => e.Placement == Placement.TopCenterFullWidth && e.Visibility)
6✔
568
                    .Sum(e => e.Height)
2✔
569
                    + s_elements
1✔
570
                        .Where(e => e.Placement == Placement.TopLeft && e.Visibility)
6✔
571
                        .Sum(e => e.Height),
1✔
572

6✔
573
            Placement.TopRight
6✔
574
                => s_elements
1✔
575
                    .Where(e => e.Placement == Placement.TopCenterFullWidth && e.Visibility)
6✔
576
                    .Sum(e => e.Height)
2✔
577
                    + s_elements
1✔
578
                        .Where(e => e.Placement == Placement.TopRight && e.Visibility)
6✔
579
                        .Sum(e => e.Height),
1✔
580
            Placement.BottomCenterFullWidth
6✔
581
                => (Console.WindowHeight == 0 ? 0 : Console.WindowHeight - 1)
2!
582
                    - s_elements
2✔
583
                        .Where(e => e.Placement == Placement.BottomCenterFullWidth && e.Visibility)
6✔
584
                        .Sum(e => e.Height),
3✔
585
            _ => throw new ArgumentOutOfRangeException(nameof(placement), "Invalid placement.")
×
586
        };
6✔
587
    }
588

589
    /// <summary>
590
    /// This method checks if the line is valid under the console constraints.
591
    /// </summary>
592
    /// <param name="line">The line to be checked.</param>
593
    /// <returns>The line if it is valid.</returns>
594
    /// <exception cref="LineOutOfConsoleException">Thrown when the line is out of range.</exception>
595
    /// <remarks>
596
    /// For more information, refer to the following resources:
597
    /// <list type="bullet">
598
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
599
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
600
    /// </list>
601
    /// </remarks>
602
    public static int? CheckLine(int? line)
603
    {
604
        int minLine = 0;
5✔
605
        int maxLine = Console.WindowHeight == 0 ? 0 : Console.WindowHeight - 1;
5!
606
        if (line is null)
5✔
607
        {
608
            return line;
3✔
609
        }
610
        if (line < minLine || line > maxLine)
2✔
611
        {
612
            throw new LineOutOfConsoleException(
1✔
613
                $"Invalid line. The line must be between 0 and {maxLine}."
1✔
614
            );
1✔
615
        }
616
        return line;
1✔
617
    }
618

619
    /// <summary>
620
    /// This method stops the execution of the program until a key is pressed.
621
    /// </summary>
622
    /// <param name="key">The key to be pressed to continue the execution.</param>
623
    /// <remarks>
624
    /// For more information, refer to the following resources:
625
    /// <list type="bullet">
626
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
627
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
628
    /// </list>
629
    /// </remarks>
630
    [Visual]
631
    public static void Freeze(ConsoleKey key = ConsoleKey.Enter)
632
    {
633
        while (Console.ReadKey(intercept: true).Key != key)
634
        {
635
            Thread.Sleep(INTERVAL_BETWEEN_READS);
636
        }
637
    }
638

639
    /// <summary>
640
    /// This method draws all visible elements of the window on the console.
641
    /// </summary>
642
    /// <remarks>
643
    /// For more information, refer to the following resources:
644
    /// <list type="bullet">
645
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
646
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
647
    /// </list>
648
    /// </remarks>
649
    [Visual]
650
    public static void Render()
651
    {
652
        Clear();
653
        Core.IsScreenUpdated();
654
        foreach (var element in s_elements)
655
        {
656
            element.RenderElement();
657
        }
658
    }
659

660
    /// <summary>
661
    /// This method draws all given visible elements of the window on the console.
662
    /// </summary>
663
    /// <param name="elements">The elements to be drawn.</param>
664
    /// <exception cref="ElementNotFoundException">Thrown when the element is not found in the window.</exception>
665
    /// <remarks>
666
    /// For more information, refer to the following resources:
667
    /// <list type="bullet">
668
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
669
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
670
    /// </list>
671
    /// </remarks>
672
    [Visual]
673
    public static void Render(params Element[] elements)
674
    {
675
        if (Core.IsScreenUpdated())
676
        {
677
            Render();
678
            return;
679
        }
680

681
        foreach (var element in elements)
682
        {
683
            if (!s_elements.Contains(element))
684
            {
685
                throw new ElementNotFoundException($"Element {element} is not in the Window.");
686
            }
687
            element.RenderElement();
688
        }
689
    }
690

691
    /// <summary>
692
    /// This method draws all the space of the visible elements of the window on the console.
693
    /// </summary>
694
    /// <param name="ignoreVisibility">If true, the space of the hidden elements will be drawn.</param>
695
    /// <returns>True if the space of the elements is successfully drawn, false otherwise.</returns>
696
    /// <remarks>
697
    /// For more information, refer to the following resources:
698
    /// <list type="bullet">
699
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
700
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
701
    /// </list>
702
    /// </remarks>
703
    [Visual]
704
    public static bool RenderElementsSpace(bool ignoreVisibility = false)
705
    {
706
        foreach (var element in s_elements)
707
        {
708
            element.RenderElementSpace(ignoreVisibility);
709
        }
710
        return true;
711
    }
712

713
    /// <summary>
714
    /// This method clears the console.
715
    /// </summary>
716
    /// <param name="continuous">If true, the window will be cleared continuously.</param>
717
    /// <param name="startLine">The start line of the window to be cleared.</param>
718
    /// <param name="length">The number of lines to be cleared.</param>
719
    /// <param name="step">The step of the window to be cleared.</param>
720
    /// <returns>True if the window is successfully cleared, false otherwise.</returns>
721
    /// <remarks>
722
    /// For more information, refer to the following resources:
723
    /// <list type="bullet">
724
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
725
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
726
    /// </list>
727
    /// </remarks>
728
    [Visual]
729
    public static bool Clear(
730
        bool continuous = false,
731
        int? startLine = null,
732
        int? length = null,
733
        int step = 1
734
    )
735
    {
736
        int stepMax = Console.WindowHeight == 0 ? 1 : Console.WindowHeight;
737
        startLine = CheckLine(startLine) ?? 0;
738
        length = CheckLine(startLine + length) ?? Console.WindowHeight;
739
        if (step < 1 || step > stepMax)
740
        {
741
            throw new ArgumentOutOfRangeException(
742
                nameof(step),
743
                "Invalid step, less than 0 or greater than the window height."
744
            );
745
        }
746

747
        for (int i = (int)startLine; i < (int)length; i += step)
748
        {
749
            if (continuous)
750
            {
751
                Core.WriteContinuousString("".PadRight(Console.WindowWidth), i, false, 100, 10);
752
            }
753
            else
754
            {
755
                Core.WritePositionedString(
756
                    "".PadRight(Console.WindowWidth),
757
                    Placement.TopCenter,
758
                    false,
759
                    i
760
                );
761
            }
762
        }
763
        return true;
764
    }
765

766
    /// <summary>
767
    /// This method "opens" the window (clears the console and hides the cursor).
768
    /// </summary>
769
    [Visual]
770
    public static void Open()
771
    {
772
        Clear();
773
        Console.CursorVisible = false;
774
    }
775

776
    /// <summary>
777
    /// This method clears the window and exit the program.
778
    /// </summary>
779
    /// <remarks>
780
    /// For more information, refer to the following resources:
781
    /// <list type="bullet">
782
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
783
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/">Example Project</a></description></item>
784
    /// </list>
785
    /// </remarks>
786
    [Visual]
787
    public static void Close()
788
    {
789
        Core.LoadTerminalColorPanel();
790
        Clear(true);
791
        Console.CursorVisible = true;
792
        Console.SetCursorPosition(0, 0);
793
        Environment.Exit(0);
794
    }
795
    #endregion
796
}
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