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

MorganKryze / ConsoleAppVisuals / 7468682866

10 Jan 2024 12:37AM UTC coverage: 29.667% (+2.7%) from 26.921%
7468682866

push

github

MorganKryze
🚑 new minor fix

438 of 1490 branches covered (0.0%)

Branch coverage included in aggregate %.

4 of 4 new or added lines in 1 file covered. (100.0%)

65 existing lines in 1 file now uncovered.

757 of 2538 relevant lines covered (29.83%)

48.13 hits per line

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

52.16
/src/ConsoleAppVisuals/Window.cs
1
/*
2
    MIT License 2023 MorganKryze
3
    For full license information, please visit: https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/LICENSE
4
*/
5
namespace ConsoleAppVisuals;
6

7
/// <summary>
8
/// The major class of the library. The window is used to collect the elements of the console and draw them.
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/Program.cs">Example Project</a></description></item>
15
/// </list>
16
/// </remarks>
17
public static class Window
18
{
19
    #region Setup
20
    /// <summary>
21
    /// This method sets up the window without the need to call it.
22
    /// </summary>
23
    [ExcludeFromCodeCoverage]
24
    static Window()
25
    {
26
        Console.Clear();
27
        Console.CursorVisible = false;
28
    }
29
    #endregion
30

31
    #region Fields: s_elements
32
    private static readonly List<Element> s_elements = new();
33
    #endregion
34

35
    #region Constants: DefaultVisibility
36
    /// <summary>
37
    /// The default visibility of the elements when they are added to the window.
38
    /// </summary>
39
    public const bool DEFAULT_VISIBILITY = false;
40
    #endregion
41

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

48
    /// <summary>
49
    /// Gives the number of elements in the window.
50
    /// </summary>
51
    public static int CountElements => s_elements.Count;
15✔
52

53
    /// <summary>
54
    /// Gives the list of elements in the window.
55
    /// </summary>
56
    public static List<Element> Elements => s_elements;
6✔
57
    #endregion
58

59
    #region Basic Methods: Get, Add, Insert, Remove, RemoveAll
60
    /// <summary>
61
    /// This method returns the first element of the given type.
62
    /// </summary>
63
    /// <typeparam name="T">The type of the element.</typeparam>
64
    /// <returns>The element with the given type if it exists, null otherwise.</returns>
65
    /// <remarks>
66
    /// For more information, refer to the following resources:
67
    /// <list type="bullet">
68
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
69
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
70
    /// </list>
71
    /// </remarks>
72
    public static T? GetElement<T>()
73
        where T : Element
74
    {
75
        return s_elements.Find(element => element.GetType() == typeof(T)) as T;
36✔
76
    }
77

78
    /// <summary>
79
    /// This method returns the element with the given id.
80
    /// </summary>
81
    /// <param name="id">The id of the element.</param>
82
    /// <returns>The element with the given id if it exists, null otherwise.</returns>
83
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of range.</exception>
84
    /// <remarks>
85
    /// For more information, refer to the following resources:
86
    /// <list type="bullet">
87
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
88
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
89
    /// </list>
90
    /// </remarks>
91
    public static T? GetElement<T>(int id)
92
        where T : Element
93
    {
94
        if (id < 0 || id >= s_elements.Count)
15✔
95
        {
96
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
6✔
97
        }
98
        return (T)s_elements[id];
9✔
99
    }
100

101
    /// <summary>
102
    /// This method returns the first visible element with the given type.
103
    /// </summary>
104
    /// <typeparam name="T">The type of the element.</typeparam>
105
    /// <returns>The visible element with the given type if it exists, null otherwise.</returns>
106
    /// <remarks>
107
    /// For more information, refer to the following resources:
108
    /// <list type="bullet">
109
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
110
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
111
    /// </list>
112
    /// </remarks>
113
    public static T? GetVisibleElement<T>()
114
        where T : Element
115
    {
116
        return s_elements.Find(element => element.GetType() == typeof(T) && element.Visibility)
27✔
117
            as T;
15✔
118
    }
119

120
    /// <summary>
121
    /// This method adds an element to the window.
122
    /// </summary>
123
    /// <param name="element">The element to be added.</param>
124
    /// <remarks>
125
    /// For more information, refer to the following resources:
126
    /// <list type="bullet">
127
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
128
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
129
    /// </list>
130
    /// </remarks>
131
    public static void AddElement(Element element)
132
    {
133
        s_elements.Add(element);
126✔
134
        if (!element.IsInteractive && AllowVisibilityToggle(element.Id))
126✔
135
        {
136
            element.ToggleVisibility();
36✔
137
        }
138
    }
126✔
139

140
    /// <summary>
141
    /// This method inserts an element to the window at the given id.
142
    /// </summary>
143
    /// <param name="element">The element to be inserted.</param>
144
    /// <param name="id">The id of the element.</param>
145
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of range.</exception>
146
    /// <remarks>
147
    /// For more information, refer to the following resources:
148
    /// <list type="bullet">
149
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
150
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
151
    /// </list>
152
    /// </remarks>
153
    public static void InsertElement(Element element, int id)
154
    {
155
        if (id < 0 || id > s_elements.Count)
9✔
156
        {
157
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
6✔
158
        }
159
        s_elements.Insert(id, element);
3✔
160
    }
3✔
161

162
    /// <summary>
163
    /// This method removes the element with the given id.
164
    /// </summary>
165
    /// <param name="id">The id of the element.</param>
166
    /// <exception cref="ArgumentOutOfRangeException">Thrown when the id is out of range.</exception>
167
    /// <remarks>
168
    /// For more information, refer to the following resources:
169
    /// <list type="bullet">
170
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
171
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
172
    /// </list>
173
    /// </remarks>
174
    public static void RemoveElement(int id)
175
    {
176
        if (id < 0 || id >= s_elements.Count)
9✔
177
        {
178
            throw new ArgumentOutOfRangeException(nameof(id), "Invalid element ID.");
6✔
179
        }
180
        s_elements.RemoveAt(id);
3✔
181
        UpdateIDs();
3✔
182
    }
3✔
183

184
    /// <summary>
185
    /// This method removes the given element.
186
    /// </summary>
187
    /// <param name="element">The element to be removed.</param>
188
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
189
    /// <returns>True if the element is successfully removed, false otherwise.</returns>
190
    /// <remarks>
191
    /// For more information, refer to the following resources:
192
    /// <list type="bullet">
193
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
194
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
195
    /// </list>
196
    /// </remarks>
197
    public static bool RemoveElement(Element element)
198
    {
199
        if (!s_elements.Contains(element))
6✔
200
        {
201
            throw new ElementNotFoundException("Invalid element. Not found in the window.");
3✔
202
        }
203
        var state = s_elements.Remove(element);
3✔
204
        UpdateIDs();
3✔
205
        return state;
3✔
206
    }
207

208
    /// <summary>
209
    /// This method removes the first element with the given type.
210
    /// </summary>
211
    /// <typeparam name="T">The type of the element.</typeparam>
212
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
213
    /// <returns>True if the element is successfully removed, false otherwise.</returns>
214
    /// <remarks>
215
    /// For more information, refer to the following resources:
216
    /// <list type="bullet">
217
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
218
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
219
    /// </list>
220
    /// </remarks>
221
    public static bool RemoveElement<T>()
222
        where T : Element
223
    {
224
        var element =
6✔
225
            GetElement<T>()
6✔
226
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
6✔
227
        var state = s_elements.Remove(element);
3✔
228
        UpdateIDs();
3✔
229
        return state;
3✔
230
    }
231

232
    /// <summary>
233
    /// This method removes the first element with the given type created by the library itself.
234
    /// </summary>
235
    /// <typeparam name="T">The type of the element.</typeparam>
236
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
237
    /// <exception cref="InvalidOperationException">Thrown when the element is not created by the library.</exception>
238
    /// <returns>True if the element is successfully removed, false otherwise.</returns>
239
    /// <remarks>
240
    /// For more information, refer to the following resources:
241
    /// <list type="bullet">
242
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
243
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
244
    /// </list>
245
    /// </remarks>
246
    public static bool RemoveLibraryElement<T>()
247
        where T : Element
248
    {
249
        var element =
9✔
250
            GetElement<T>()
9✔
251
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
9✔
252
        if (element.ElementSource == Source.Library)
6✔
253
        {
254
            var state = s_elements.Remove(element);
3✔
255
            UpdateIDs();
3✔
256
            return state;
3✔
257
        }
258
        throw new InvalidOperationException("Invalid element. Not created by the library.");
3✔
259
    }
260

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

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

308
    /// <summary>
309
    /// This method attempts to activate the visibility of the first element of the given type.
310
    /// </summary>
311
    /// <param name="render">If true, the element will be rendered.</param>
312
    /// <typeparam name="T">The type of the element.</typeparam>
313
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
314
    /// <remarks>
315
    /// For more information, refer to the following resources:
316
    /// <list type="bullet">
317
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
318
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
319
    /// </list>
320
    /// </remarks>
321
    [Visual]
322
    public static void ActivateElement<T>(bool render = true)
323
        where T : Element
324
    {
325
        var element =
326
            GetElement<T>()
327
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
328
        if (!element.Visibility)
329
        {
330
            element.ToggleVisibility();
331
        }
332
        if (render)
333
        {
334
            element.RenderElement();
335
        }
336
    }
337

338
    /// <summary>
339
    /// After activating the visibility of an interactive element, this method will return the response for the user.
340
    /// </summary>
341
    /// <param name="clear">If true, the element will be cleared.</param>
342
    /// <typeparam name="T">The type of interactive element.</typeparam>
343
    /// <typeparam name="TResponse">The type of the response (int, string, float...).</typeparam>
344
    /// <returns>The response of the user.</returns>
345
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
346
    /// <remarks>
347
    /// For more information, refer to the following resources:
348
    /// <list type="bullet">
349
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
350
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
351
    /// </list>
352
    /// </remarks>
353
    [Visual]
354
    public static InteractionEventArgs<TResponse>? GetResponse<T, TResponse>(bool clear = true)
355
        where T : InteractiveElement<TResponse>
356
    {
357
        var element =
358
            GetVisibleElement<T>()
359
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
360
        DeactivateElement<T>(clear);
361
        return element.GetInteractionResponse;
362
    }
363

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

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

435
        if (element.Visibility)
6✔
436
        {
437
            element.ToggleVisibility();
6✔
438
            if (clear)
6✔
439
            {
440
                element.Clear();
3✔
441
            }
442
        }
443
    }
6✔
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/Program.cs">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 =
9✔
462
            GetVisibleElement<T>()
9✔
463
            ?? throw new ElementNotFoundException("Invalid element. Not found in the window.");
9✔
464
        if (element.Visibility)
6✔
465
        {
466
            element.ToggleVisibility();
6✔
467
            if (clear)
6✔
468
            {
469
                element.Clear();
3✔
470
            }
471
        }
472
    }
6✔
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/Program.cs">Example Project</a></description></item>
482
    /// </list>
483
    /// </remarks>
484
    public static void DeactivateAllElements()
485
    {
486
        foreach (var element in s_elements)
12✔
487
        {
488
            if (element.Visibility)
3✔
489
            {
490
                element.ToggleVisibility();
3✔
491
            }
492
        }
493
        Refresh();
3✔
494
    }
3✔
495
    #endregion
496

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

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

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

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

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

622
    /// <summary>
623
    /// This method clears the window.
624
    /// </summary>
625
    /// <param name="continuous">If true, the window will be cleared continuously.</param>
626
    /// <remarks>
627
    /// For more information, refer to the following resources:
628
    /// <list type="bullet">
629
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
630
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
631
    /// </list>
632
    /// </remarks>
633
    public static void Clear(bool continuous = false)
634
    {
635
        if (continuous)
9✔
636
        {
637
            for (int i = 0; i < Console.WindowHeight; i++)
6!
638
            {
UNCOV
639
                Core.WriteContinuousString("".PadRight(Console.WindowWidth), i, false, 100, 10);
×
640
            }
641
        }
642
        else
643
        {
644
            for (int i = 0; i < Console.WindowHeight; i++)
12!
645
            {
646
                Core.WritePositionedString(
×
647
                    "".PadRight(Console.WindowWidth),
×
648
                    TextAlignment.Center,
×
649
                    false,
×
650
                    i
×
UNCOV
651
                );
×
652
            }
653
        }
654
    }
6✔
655

656
    /// <summary>
657
    /// This method stops the execution of the program until a key is pressed.
658
    /// </summary>
659
    /// <remarks>
660
    /// For more information, refer to the following resources:
661
    /// <list type="bullet">
662
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
663
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
664
    /// </list>
665
    /// </remarks>
666
    [Visual]
667
    public static void StopExecution(ConsoleKey key = ConsoleKey.Enter)
668
    {
669
        // wait until the user presses a key
670
        while (Console.ReadKey(intercept: true).Key != key)
671
        {
672
            Thread.Sleep(10);
673
        }
674
    }
675

676
    /// <summary>
677
    /// This method draws the element with the given id on the console.
678
    /// </summary>
679
    /// <param name="id">The id of the element.</param>
680
    /// <exception cref="ElementNotFoundException">Thrown when the id is out of range.</exception>
681
    /// <returns>True if the element is successfully drawn, false otherwise.</returns>
682
    /// <remarks>
683
    /// For more information, refer to the following resources:
684
    /// <list type="bullet">
685
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
686
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
687
    /// </list>
688
    /// </remarks>
689
    public static bool RenderOneElement(int id)
690
    {
691
        if (id < 0 || id >= s_elements.Count)
6✔
692
        {
693
            throw new ElementNotFoundException("Invalid element ID.");
3✔
694
        }
695
        s_elements[id].RenderElement();
3✔
696
        return true;
3✔
697
    }
698

699
    /// <summary>
700
    /// This method draws the given element on the console.
701
    /// </summary>
702
    /// <param name="element">The element to be drawn.</param>
703
    /// <exception cref="ElementNotFoundException">Thrown when the element is invalid.</exception>
704
    /// <remarks>
705
    /// For more information, refer to the following resources:
706
    /// <list type="bullet">
707
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
708
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
709
    /// </list>
710
    /// </remarks>
711
    public static void RenderOneElement(Element element)
712
    {
UNCOV
713
        if (element == null || !s_elements.Contains(element))
×
714
        {
715
            throw new ElementNotFoundException("Invalid element. Not found in the window.");
×
716
        }
717

UNCOV
718
        element.RenderElement();
×
UNCOV
719
    }
×
720

721
    /// <summary>
722
    /// This method draws all the non interactive elements of the window on the console.
723
    /// </summary>
724
    /// <remarks>
725
    /// For more information, refer to the following resources:
726
    /// <list type="bullet">
727
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
728
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
729
    /// </list>
730
    /// </remarks>
731
    public static void Refresh()
732
    {
733
        Clear();
6✔
734
        foreach (var element in s_elements)
30✔
735
        {
736
            element.RenderElement();
9✔
737
        }
738
    }
6✔
739

740
    /// <summary>
741
    /// This method is called to refresh the window when the size of the console is changed.
742
    /// </summary>
743
    public static void OnResize()
744
    {
UNCOV
745
        if (Core.IsScreenUpdated)
×
746
        {
UNCOV
747
            Core.SetConsoleDimensions();
×
UNCOV
748
            Refresh();
×
749
        }
UNCOV
750
    }
×
751

752
    /// <summary>
753
    /// This method draws all the space of the elements of the window on the console.
754
    /// </summary>
755
    /// <remarks>
756
    /// For more information, refer to the following resources:
757
    /// <list type="bullet">
758
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
759
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
760
    /// </list>
761
    /// </remarks>
762
    public static void RenderAllElementsSpace()
763
    {
764
        foreach (var element in s_elements)
×
765
        {
UNCOV
766
            element.RenderElementSpace();
×
767
        }
UNCOV
768
    }
×
769

770
    /// <summary>
771
    /// This method closes the window and exit the program.
772
    /// </summary>
773
    /// <remarks>
774
    /// For more information, refer to the following resources:
775
    /// <list type="bullet">
776
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
777
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
778
    /// </list>
779
    /// </remarks>
780
    public static void Close()
781
    {
782
        Core.LoadTerminalColorPanel();
×
UNCOV
783
        Clear(true);
×
UNCOV
784
        Console.CursorVisible = true;
×
UNCOV
785
        Environment.Exit(0);
×
UNCOV
786
    }
×
787
    #endregion
788

789
    #region Info Methods: ListWindowElements, ListClassesInheritingElement, ListClassesInheritingInteractiveElement
790
    /// <summary>
791
    /// This method displays a list of all elements in the window and adds a table to the window.
792
    /// </summary>
793
    /// <param name="placement">The placement of the element.</param>
794
    /// <remarks>
795
    /// For more information, refer to the following resources:
796
    /// <list type="bullet">
797
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
798
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
799
    /// </list>
800
    /// </remarks>
801
    public static void AddListWindowElements(Placement placement = Placement.TopCenter)
802
    {
803
        TableView<string> table =
6✔
804
            new(
6✔
805
                "Window Elements",
6✔
806
                new List<string>
6✔
807
                {
6✔
808
                    "Id",
6✔
809
                    "Type",
6✔
810
                    "Visibility",
6✔
811
                    "Height",
6✔
812
                    "Width",
6✔
813
                    "Line",
6✔
814
                    "Placement",
6✔
815
                    "IsInteractive",
6✔
816
                    "Source"
6✔
817
                },
6✔
818
                null,
6✔
819
                placement
6✔
820
            )
6✔
821
            {
6✔
822
                ElementSource = Source.Library
6✔
823
            };
6✔
824
        AddElement(table);
6✔
825
        foreach (var element in s_elements)
24✔
826
        {
827
            table.AddLine(
6✔
828
                new List<string>
6✔
829
                {
6✔
830
                    element.Id.ToString(),
6✔
831
                    element.GetType().Name,
6✔
832
                    element.Visibility.ToString(),
6✔
833
                    element.Height.ToString(),
6✔
834
                    element.Width.ToString(),
6✔
835
                    element.Line.ToString(),
6✔
836
                    element.Placement.ToString(),
6✔
837
                    element.IsInteractive.ToString(),
6✔
838
                    element.ElementSource.ToString()
6✔
839
                }
6✔
840
            );
6✔
841
        }
842
    }
6✔
843

844
    /// <summary>
845
    /// This method is used to get a list of all the types of the elements in the window.
846
    /// </summary>
847
    /// <returns>A list of all the types of the elements in the window.</returns>
848
    /// <remarks>
849
    /// For more information, refer to the following resources:
850
    /// <list type="bullet">
851
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
852
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
853
    /// </list>
854
    /// </remarks>
855
    public static List<string>? GetListWindowElements()
856
    {
857
        TableView<string> table =
×
858
            new(
×
859
                "Window Elements",
×
860
                new List<string>
×
861
                {
×
862
                    "Id",
×
863
                    "Type",
×
864
                    "Visibility",
×
865
                    "Height",
×
866
                    "Width",
×
867
                    "Line",
×
868
                    "Placement",
×
869
                    "IsInteractive",
×
870
                    "Source"
×
871
                }
×
872
            )
×
UNCOV
873
            {
×
874
                ElementSource = Source.Library
×
875
            };
×
876
        foreach (var element in s_elements)
×
877
        {
878
            table.AddLine(
×
879
                new List<string>
×
880
                {
×
881
                    element.Id.ToString(),
×
882
                    element.GetType().Name,
×
883
                    element.Visibility.ToString(),
×
884
                    element.Height.ToString(),
×
885
                    element.Width.ToString(),
×
886
                    element.Line.ToString(),
×
887
                    element.Placement.ToString(),
×
UNCOV
888
                    element.IsInteractive.ToString(),
×
889
                    element.ElementSource.ToString()
×
UNCOV
890
                }
×
UNCOV
891
            );
×
892
        }
UNCOV
893
        return table.GetColumnData("Type");
×
894
    }
895

896
    /// <summary>
897
    /// This method gives a list of all classes inheriting from the Element (and so InteractiveElement as well) class and adds a table to the window.
898
    /// </summary>
899
    /// <param name="placement">The placement of the element.</param>
900
    /// <returns>The list of all classes inheriting from the Element class.</returns>
901
    /// <remarks>
902
    /// For more information, refer to the following resources:
903
    /// <list type="bullet">
904
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
905
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
906
    /// </list>
907
    /// </remarks>
908
    public static void AddListClassesInheritingElement(Placement placement = Placement.TopCenter)
909
    {
910
        var types = new List<Type>();
×
911
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
×
912
        {
913
            if (
×
914
                assembly.FullName != null
×
UNCOV
915
                && !assembly.FullName.StartsWith("mscorlib")
×
916
                && !assembly.FullName.StartsWith("System")
×
UNCOV
917
                && !assembly.FullName.StartsWith("Microsoft")
×
UNCOV
918
            )
×
919
            {
920
                types.AddRange(assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Element))));
×
921
            }
922
        }
UNCOV
923
        TableView<string> table =
×
924
            new("Element Classes", new List<string> { "Id", "Type", "Project" }, null, placement);
×
UNCOV
925
        var id = 0;
×
UNCOV
926
        foreach (var type in types)
×
927
        {
928
            if (type.IsAbstract)
×
929
            {
930
                continue;
931
            }
UNCOV
932
            table.AddLine(
×
933
                new List<string> { $"{id}", type.Name, type.Assembly.GetName().Name ?? "Unknown" }
×
934
            );
×
935
            id += 1;
×
936
        }
UNCOV
937
        table.ElementSource = Source.Library;
×
UNCOV
938
        AddElement(table);
×
UNCOV
939
    }
×
940

941
    /// <summary>
942
    /// This method is used to get a list of all the types of the classes inheriting from the Element class.
943
    /// </summary>
944
    /// <returns>A list of all the types of the classes inheriting from the Element class.</returns>
945
    /// <remarks>
946
    /// For more information, refer to the following resources:
947
    /// <list type="bullet">
948
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
949
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
950
    /// </list>
951
    /// </remarks>
952
    public static List<string>? GetListClassesInheritingElement()
953
    {
954
        var types = new List<Type>();
×
955
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
×
956
        {
957
            if (
×
958
                assembly.FullName != null
×
UNCOV
959
                && !assembly.FullName.StartsWith("mscorlib")
×
960
                && !assembly.FullName.StartsWith("System")
×
961
                && !assembly.FullName.StartsWith("Microsoft")
×
962
            )
×
963
            {
964
                types.AddRange(
×
965
                    assembly
×
966
                        .GetTypes()
×
967
                        .Where(
×
UNCOV
968
                            t =>
×
UNCOV
969
                                t.IsSubclassOf(typeof(Element)) && t != typeof(InteractiveElement<>)
×
970
                        )
×
971
                );
×
972
            }
973
        }
UNCOV
974
        TableView<string> table =
×
975
            new("Element Classes", new List<string> { "Id", "Type", "Project" });
×
UNCOV
976
        var id = 0;
×
UNCOV
977
        foreach (var type in types)
×
978
        {
979
            if (type.IsAbstract)
×
980
            {
981
                continue;
982
            }
UNCOV
983
            table.AddLine(
×
984
                new List<string> { $"{id}", type.Name, type.Assembly.GetName().Name ?? "Unknown" }
×
UNCOV
985
            );
×
UNCOV
986
            id += 1;
×
987
        }
UNCOV
988
        return table.GetColumnData("Type");
×
989
    }
990

991
    /// <summary>
992
    /// This method gives a list of all classes inheriting from the InteractiveElement class and adds a table to the window.
993
    /// </summary>
994
    /// <param name="placement">The placement of the element.</param>
995
    /// <returns>The list of all classes inheriting from the InteractiveElement class.</returns>
996
    public static void AddListClassesInheritingInteractiveElement(
997
        Placement placement = Placement.TopCenter
998
    )
999
    {
1000
        var types = new List<Type>();
×
1001
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
×
1002
        {
1003
            if (
×
1004
                assembly.FullName != null
×
UNCOV
1005
                && !assembly.FullName.StartsWith("mscorlib")
×
1006
                && !assembly.FullName.StartsWith("System")
×
1007
                && !assembly.FullName.StartsWith("Microsoft")
×
1008
            )
×
1009
            {
1010
                types.AddRange(
×
1011
                    assembly
×
1012
                        .GetTypes()
×
1013
                        .Where(
×
1014
                            t =>
×
1015
                                t.BaseType != null
×
1016
                                && t.BaseType.IsGenericType
×
UNCOV
1017
                                && t.BaseType.GetGenericTypeDefinition()
×
UNCOV
1018
                                    == typeof(InteractiveElement<>)
×
1019
                        )
×
1020
                );
×
1021
            }
1022
        }
1023
        TableView<string> table =
×
1024
            new(
×
1025
                "Interactive Element Classes",
×
1026
                new List<string> { "Id", "Type", "Project" },
×
1027
                null,
×
UNCOV
1028
                placement
×
1029
            );
×
1030
        var id = 0;
×
1031
        foreach (var type in types)
×
1032
        {
UNCOV
1033
            table.AddLine(
×
1034
                new List<string> { $"{id}", type.Name, type.Assembly.GetName().Name ?? "Unknown" }
×
1035
            );
×
1036
            id += 1;
×
1037
        }
UNCOV
1038
        table.ElementSource = Source.Library;
×
UNCOV
1039
        AddElement(table);
×
UNCOV
1040
    }
×
1041

1042
    /// <summary>
1043
    /// This method is used to get a list of all the types of the classes inheriting from the InteractiveElement class.
1044
    /// </summary>
1045
    /// <returns>A list of all the types of the classes inheriting from the InteractiveElement class.</returns>
1046
    /// <remarks>
1047
    /// For more information, refer to the following resources:
1048
    /// <list type="bullet">
1049
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
1050
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
1051
    /// </list>
1052
    /// </remarks>
1053
    public static List<string>? GetListClassesInheritingInteractiveElement()
1054
    {
1055
        var types = new List<Type>();
×
1056
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
×
1057
        {
1058
            if (
×
1059
                assembly.FullName != null
×
UNCOV
1060
                && !assembly.FullName.StartsWith("mscorlib")
×
1061
                && !assembly.FullName.StartsWith("System")
×
1062
                && !assembly.FullName.StartsWith("Microsoft")
×
1063
            )
×
1064
            {
1065
                types.AddRange(
×
1066
                    assembly
×
1067
                        .GetTypes()
×
1068
                        .Where(
×
1069
                            t =>
×
1070
                                t.BaseType != null
×
1071
                                && t.BaseType.IsGenericType
×
UNCOV
1072
                                && t.BaseType.GetGenericTypeDefinition()
×
UNCOV
1073
                                    == typeof(InteractiveElement<>)
×
1074
                        )
×
1075
                );
×
1076
            }
1077
        }
UNCOV
1078
        TableView<string> table =
×
1079
            new("Interactive Element Classes", new List<string> { "Id", "Type", "Project" });
×
1080
        var id = 0;
×
1081
        foreach (var type in types)
×
1082
        {
UNCOV
1083
            table.AddLine(
×
1084
                new List<string> { $"{id}", type.Name, type.Assembly.GetName().Name ?? "Unknown" }
×
UNCOV
1085
            );
×
UNCOV
1086
            id += 1;
×
1087
        }
UNCOV
1088
        return table.GetColumnData("Type");
×
1089
    }
1090

1091
    /// <summary>
1092
    /// This method displays a list of all elements in the window, a list of all classes inheriting from the Element class and a list of all classes inheriting from the InteractiveElement class.
1093
    /// </summary>
1094
    /// <remarks>
1095
    /// For more information, refer to the following resources:
1096
    /// <list type="bullet">
1097
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
1098
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
1099
    /// </list>
1100
    /// </remarks>
1101
    public static void AddDashboard()
1102
    {
UNCOV
1103
        AddListClassesInheritingElement(Placement.TopLeft);
×
UNCOV
1104
        AddListClassesInheritingInteractiveElement(Placement.TopRight);
×
UNCOV
1105
        AddListWindowElements(Placement.TopCenter);
×
UNCOV
1106
    }
×
1107

1108
    /// <summary>
1109
    /// This method removes the dashboard TableView from the window.
1110
    /// </summary>
1111
    /// <remarks>
1112
    /// For more information, refer to the following resources:
1113
    /// <list type="bullet">
1114
    /// <item><description><a href="https://morgankryze.github.io/ConsoleAppVisuals/">Documentation</a></description></item>
1115
    /// <item><description><a href="https://github.com/MorganKryze/ConsoleAppVisuals/blob/main/example/Program.cs">Example Project</a></description></item>
1116
    /// </list>
1117
    /// </remarks>
1118
    public static void RemoveDashboard()
1119
    {
UNCOV
1120
        RemoveLibraryElement<TableView<string>>();
×
UNCOV
1121
        RemoveLibraryElement<TableView<string>>();
×
UNCOV
1122
        RemoveLibraryElement<TableView<string>>();
×
UNCOV
1123
    }
×
1124
    #endregion
1125
}
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