├── .gitattributes ├── .gitignore ├── ConsoleProgressBar.sln ├── ConsoleProgressBar ├── ConsoleProgressBar.csproj ├── ConsoleProgressBar.csproj.user ├── ConsoleProgressBar.xml ├── Element.cs ├── ElementList.cs ├── Extensions │ ├── ElementExtensions.cs │ ├── StringExtensions.cs │ └── TimeSpanExtensions.cs ├── Layout.Body.cs ├── Layout.Margin.cs ├── Layout.Marquee.cs ├── Layout._.cs ├── ProgressBar.cs ├── Text.Body.cs ├── Text.Description.cs └── Text._.cs ├── ConsoleProgressBarDemo ├── ConsoleProgressBarDemo.csproj ├── DemoProgressBar.cs └── Program.cs ├── LICENSE ├── README.md └── docs ├── ConsoleProgressBar.Extensions ├── ElementExtensions.md ├── StringExtensions.md └── TimeSpanExtensions.md ├── ConsoleProgressBar └── ProgressBar.md ├── img ├── ProgressBarConsole-Default-Writing.gif ├── ProgressBarConsole-Default.gif ├── ProgressBarConsole-Demo.gif ├── ProgressBarConsole-Demo2.gif ├── ProgressBarConsole-Demo3.gif ├── ProgressBarConsole-Demo4.gif ├── ProgressBarConsole-Example01.gif ├── ProgressBarConsole-Example02.gif ├── ProgressBarConsole-Example03.gif ├── ProgressBarConsole-Example04.gif ├── ProgressBarConsole-Example05.gif ├── ProgressBarConsole-Example06.gif ├── ProgressBarConsole-Example07.gif ├── ProgressBarConsole-Example08.gif ├── ProgressBarConsole-Example09.gif ├── ProgressBarConsole-Example10.gif ├── ProgressBarConsole-Example11.gif └── ProgressBarConsole-Example_Usage1.gif └── index.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | obj 3 | bin 4 | .cr 5 | -------------------------------------------------------------------------------- /ConsoleProgressBar.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30804.86 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleProgressBar", "ConsoleProgressBar\ConsoleProgressBar.csproj", "{415D677E-01C5-46D0-B91A-4F78D06B47FE}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleProgressBarDemo", "ConsoleProgressBarDemo\ConsoleProgressBarDemo.csproj", "{C0CA7D84-1CDF-48B0-813B-48983ABACE7B}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Documentation", "Documentation", "{80ACAE36-3714-4C19-B52B-ECC2BB13F33B}" 11 | ProjectSection(SolutionItems) = preProject 12 | README.md = README.md 13 | EndProjectSection 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Release|Any CPU = Release|Any CPU 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {415D677E-01C5-46D0-B91A-4F78D06B47FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 | {415D677E-01C5-46D0-B91A-4F78D06B47FE}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 | {415D677E-01C5-46D0-B91A-4F78D06B47FE}.Release|Any CPU.ActiveCfg = Release|Any CPU 24 | {415D677E-01C5-46D0-B91A-4F78D06B47FE}.Release|Any CPU.Build.0 = Release|Any CPU 25 | {C0CA7D84-1CDF-48B0-813B-48983ABACE7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {C0CA7D84-1CDF-48B0-813B-48983ABACE7B}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {C0CA7D84-1CDF-48B0-813B-48983ABACE7B}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {C0CA7D84-1CDF-48B0-813B-48983ABACE7B}.Release|Any CPU.Build.0 = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(SolutionProperties) = preSolution 31 | HideSolutionNode = FALSE 32 | EndGlobalSection 33 | GlobalSection(ExtensibilityGlobals) = postSolution 34 | SolutionGuid = {BFD762A6-09CC-411D-B56E-B49F4A1A6F98} 35 | EndGlobalSection 36 | EndGlobal 37 | -------------------------------------------------------------------------------- /ConsoleProgressBar/ConsoleProgressBar.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.1 5 | iluvadev.$(MSBuildProjectName.Replace(" ", "_")) 6 | iluvadev.$(MSBuildProjectName) 7 | True 8 | iluvadev 9 | Copyright (c) 2021, iluvadev, and released under MIT License. 10 | Simple and versatile ProgressBar for Console Applications, written in C#, .Net Standard 2.1. Progress and/or Marquee, with estimated remaining time, custom layouts, dynamic text, colors and more. 11 | https://github.com/iluvadev/ConsoleProgressBar 12 | https://github.com/iluvadev/ConsoleProgressBar 13 | git 14 | progress-bar;console;library;netstandard 15 | 1.1.0 16 | 1.1.0 17 | MIT 18 | True 19 | $(AssemblyVersion) 20 | 21 | 22 | 23 | C:\Dev\iluvadev\projects\ConsoleProgressBar\ConsoleProgressBar\ConsoleProgressBar.xml 24 | 25 | 26 | -------------------------------------------------------------------------------- /ConsoleProgressBar/ConsoleProgressBar.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /ConsoleProgressBar/ConsoleProgressBar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iluvadev.ConsoleProgressBar 5 | 6 | 7 | 8 | 9 | An element of a ProgressBar 10 | 11 | 12 | 13 | 14 | 15 | Ctor 16 | 17 | 18 | 19 | 20 | Ctor 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Sets the ProgressBar element visible (or not) 29 | 30 | 31 | 32 | 33 | 34 | 35 | Sets the ProgressBar element visible (or not) 36 | 37 | 38 | 39 | 40 | 41 | 42 | Gets the ProgressBar element visibility 43 | 44 | 45 | 46 | 47 | 48 | 49 | Sets the Value of the ProgressBar element 50 | 51 | 52 | 53 | 54 | 55 | 56 | Sets the Value of the ProgressBar element 57 | 58 | 59 | 60 | 61 | 62 | 63 | Gets the Value of the ProgressBar element 64 | 65 | 66 | 67 | 68 | 69 | 70 | Sets the ForegroundColor of the ProgressBar element 71 | 72 | 73 | 74 | 75 | 76 | 77 | Sets the ForegroundColor of the ProgressBar element 78 | 79 | 80 | 81 | 82 | 83 | 84 | Gets the ForegroundColor of the ProgressBar element 85 | 86 | 87 | 88 | 89 | 90 | 91 | Sets the BackgroundColor of the ProgressBar element 92 | 93 | 94 | 95 | 96 | 97 | 98 | Sets the BackgroundColor of the ProgressBar element 99 | 100 | 101 | 102 | 103 | 104 | 105 | Gets the BackgroundColor of the ProgressBar element 106 | 107 | 108 | 109 | 110 | 111 | 112 | A list of Elements of a ProgressBar 113 | 114 | 115 | 116 | 117 | 118 | The List of Elements of a Progressbar 119 | 120 | 121 | 122 | 123 | Clears the List of elements of a ProgressBar 124 | 125 | 126 | 127 | 128 | 129 | Adds new Element to the List 130 | 131 | 132 | 133 | 134 | 135 | Extensions for Element 136 | 137 | 138 | 139 | 140 | Returns a list of Actions to write the element in Console 141 | 142 | 143 | 144 | Function to Transform the value before write 145 | 146 | 147 | 148 | 149 | Returns a list of Actions to write the element in Console 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | Extensions for String 159 | 160 | 161 | 162 | 163 | Returns a string that occupy all console line/s 164 | 165 | The string to write in console 166 | To allow print the string in muliple lines or only in one: 167 | True: The text can be represented in more than one Console line (fill spaces to the end of last line) 168 | False: The text must be represented in only ONE line (truncate to fit or fill spaces to the end of line) 169 | 170 | 171 | 172 | 173 | 174 | Returns a string with exactly maxChars: Truncates string value or fill with spaces to fits exact length 175 | 176 | 177 | 178 | Text appended when it is truncated. Default: "..." 179 | 180 | 181 | 182 | 183 | TimeSpan extensions 184 | 185 | 186 | 187 | 188 | Gets a textual Sumarized for remaining time: X days, or Y hours, or Z minutes, etc. 189 | 190 | 191 | 192 | 193 | 194 | 195 | Gets a textual Sumarized for remaining time: X days, or Y hours, or Z minutes, etc. 196 | 197 | 198 | 199 | 200 | 201 | 202 | Converts a TimeSpan to String, showing all hours 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | Converts a TimeSpan to String, showing all hours 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | Definition of a Layout for a ProgressBar representation 219 | 220 | 221 | 222 | 223 | Definition of the Layout used to Render the Body of the ProgressBar 224 | 225 | 226 | 227 | 228 | Element To show in Pending Section 229 | 230 | 231 | 232 | 233 | Element to show in Progress Section 234 | 235 | 236 | 237 | 238 | Layout for the Text 239 | 240 | 241 | 242 | 243 | Sets the LayoutBody value for Pending and Progress elements 244 | 245 | 246 | 247 | 248 | 249 | 250 | Sets the LayoutBody value for Pending and Progress elements 251 | 252 | 253 | 254 | 255 | 256 | 257 | Sets the ForegroundColor for Pending and Progress elements 258 | 259 | 260 | 261 | 262 | 263 | 264 | Sets the ForegroundColor for Pending and Progress elements 265 | 266 | 267 | 268 | 269 | 270 | 271 | Sets the BackgroundColor for Pending and Progress elements 272 | 273 | 274 | 275 | 276 | 277 | 278 | Sets the BackgroundColor for Pending and Progress elements 279 | 280 | 281 | 282 | 283 | 284 | 285 | Ctor 286 | 287 | 288 | 289 | 290 | Definition of the Layout used to Render the Margins of the ProgressBar 291 | 292 | 293 | 294 | 295 | Element to show at the Margin Left (Start of the ProgressBar) 296 | 297 | 298 | 299 | 300 | Element to show at the Margin Right (End of the ProgressBar) 301 | 302 | 303 | 304 | 305 | Sets the LayoutMargin value for Start and End elements 306 | 307 | 308 | 309 | 310 | 311 | 312 | Sets the LayoutMargin value for Start and End elements 313 | 314 | 315 | 316 | 317 | 318 | 319 | Sets the ForegroundColor for Start and End elements 320 | 321 | 322 | 323 | 324 | 325 | 326 | Sets the ForegroundColor for Start and End elements 327 | 328 | 329 | 330 | 331 | 332 | 333 | Sets the BackgroundColor for Start and End elements 334 | 335 | 336 | 337 | 338 | 339 | 340 | Sets the BackgroundColor for Start and End elements 341 | 342 | 343 | 344 | 345 | 346 | 347 | Sets the visibility for Start and End elements 348 | 349 | 350 | 351 | 352 | 353 | 354 | Sets the visibility for Start and End elements 355 | 356 | 357 | 358 | 359 | 360 | 361 | Return the length of Margins 362 | 363 | 364 | 365 | 366 | 367 | 368 | Ctor 369 | 370 | 371 | 372 | 373 | Definition for the Marquee 374 | The Marquee is a char that moves around the ProgressBar 375 | 376 | 377 | 378 | 379 | Marquee definition when it moves over 'Pending' section 380 | 381 | 382 | 383 | 384 | Marquee definition when it moves over 'Progress' section 385 | 386 | 387 | 388 | 389 | Sets the Marqee definition when it moves over 'Pending' or 'Progress' section 390 | 391 | 392 | 393 | 394 | 395 | 396 | Sets the Marqee definition when it moves over 'Pending' or 'Progress' section 397 | 398 | 399 | 400 | 401 | 402 | 403 | Sets the Marqee Foreground Color when it moves over 'Pending' or 'Progress' section 404 | 405 | 406 | 407 | 408 | 409 | 410 | Sets the Marqee Foreground Color when it moves over 'Pending' or 'Progress' section 411 | 412 | 413 | 414 | 415 | 416 | 417 | Sets the Marqee Background Color when it moves over 'Pending' or 'Progress' section 418 | 419 | 420 | 421 | 422 | 423 | 424 | Sets the Marqee Background Color when it moves over 'Pending' or 'Progress' section 425 | 426 | 427 | 428 | 429 | 430 | 431 | Sets the Marqee Visibility when it moves over 'Pending' or 'Progress' section 432 | 433 | 434 | 435 | 436 | 437 | 438 | Sets the Marqee Visibility when it moves over 'Pending' or 'Progress' section 439 | 440 | 441 | 442 | 443 | 444 | 445 | Ctor 446 | 447 | 448 | 449 | 450 | Layout definition for Margins 451 | 452 | 453 | 454 | 455 | Layout definition for Marquee (character moving around the ProgressBar) 456 | 457 | 458 | 459 | 460 | Layout definition for Body 461 | 462 | 463 | 464 | 465 | Width of entire ProgressBar 466 | Default = 30 467 | 468 | 469 | 470 | 471 | Gets the internal Width of the ProgressBar 472 | 473 | 474 | 475 | 476 | Returns the Actions to do in order to Render the ProgressBar with this Layout 477 | 478 | 479 | 480 | 481 | 482 | 483 | A ProgressBar for Console 484 | 485 | 486 | 487 | 488 | Layout of the ProgressBar 489 | 490 | 491 | 492 | 493 | Text definitions for the ProgressBar 494 | 495 | 496 | 497 | 498 | Tag object 499 | 500 | 501 | 502 | 503 | The Maximum value 504 | Default = 100 505 | 506 | 507 | 508 | 509 | The current Value 510 | If Value is greater than Maximum, then updates Maximum value 511 | 512 | 513 | 514 | 515 | Percentage of progress 516 | 517 | 518 | 519 | 520 | Indicates if the ProgressBar has Progress defined (Maximum defined) 521 | 522 | 523 | 524 | 525 | The amount by which to increment the ProgressBar with each call to the PerformStep() method. 526 | Default = 1 527 | 528 | 529 | 530 | 531 | The Name of the Curent Element 532 | 533 | 534 | 535 | 536 | True to Print the ProgressBar always in last Console Line 537 | False to Print the ProgressBar fixed in Console (Current position at Starting) 538 | You can Write at Console and ProgressBar will always be below your lines 539 | Default = true 540 | 541 | 542 | 543 | 544 | Delay for repaint and recalculate all ProgressBar 545 | Default = 75 546 | 547 | 548 | 549 | 550 | True if ProgressBar is Started 551 | 552 | 553 | 554 | 555 | True if ProgressBar is Paused 556 | 557 | 558 | 559 | 560 | True if ProgresBar is Done: when disposing or Progress is finished 561 | 562 | 563 | 564 | 565 | Processing time (time paused excluded) 566 | 567 | 568 | 569 | 570 | Processing time per element (median) 571 | 572 | 573 | 574 | 575 | Estimated time finish (to Value = Maximum) 576 | 577 | 578 | 579 | 580 | A Lock for Writing to Console 581 | 582 | 583 | 584 | 585 | Creates an instance of ConsoleProgressBar 586 | 587 | Initial position of the ProgressBar 588 | True if ProgressBar starts automatically 589 | 590 | 591 | 592 | Starts the ProgressBar 593 | 594 | 595 | 596 | 597 | Pauses the ProgressBar 598 | 599 | 600 | 601 | 602 | Resume the ProgresBar 603 | 604 | 605 | 606 | 607 | Assigns the current Value, and optionally current ElementName and Tag 608 | If Value is greater than Maximum, updates Maximum as Value 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | Advances the current position of the progress bar by the amount of the Step property 617 | 618 | The name of the new Element 619 | 620 | 621 | 622 | 623 | Advances the current position of the progress bar by the amount of the Step property 624 | 625 | Step to perform 626 | The name of the new Element 627 | 628 | 629 | 630 | 631 | WriteLine in Console when ProgressBar is running 632 | 633 | 634 | 635 | 636 | WriteLine in Console when ProgressBar is running 637 | 638 | 639 | 640 | 641 | 642 | WriteLine in Console when ProgressBar is running 643 | 644 | 645 | 646 | 647 | 648 | 649 | WriteLine in Console when ProgressBar is running 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | Renders in Console the ProgressBar 659 | 660 | 661 | 662 | 663 | Unrenders (remove) from Console last ProgressBar printed 664 | 665 | 666 | 667 | 668 | Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 669 | 670 | 671 | 672 | 673 | Definitions for Texts in a ProgressBar 674 | 675 | 676 | 677 | 678 | Definition for the Texts in a ProgressBar 679 | 680 | 681 | 682 | 683 | Text in Body definition when ProgressBar is "Processing" 684 | 685 | 686 | 687 | 688 | Text in Body definition when ProgressBar is "Paused" 689 | 690 | 691 | 692 | 693 | Text in Body definition when ProgressBar is "Done" 694 | 695 | 696 | 697 | 698 | Sets the Body Text visibility 699 | 700 | 701 | 702 | 703 | 704 | 705 | Sets the Body Text visibility 706 | 707 | 708 | 709 | 710 | 711 | 712 | Sets the Body Text definition in all ProgressBar states ("Processing", "Paused", "Done") 713 | 714 | 715 | 716 | 717 | 718 | 719 | Sets the Body Text definition in all ProgressBar states ("Processing", "Paused", "Done") 720 | 721 | 722 | 723 | 724 | 725 | 726 | Sets the Body Text Foreground Color 727 | 728 | 729 | 730 | 731 | 732 | 733 | Sets the Body Text Foreground Color 734 | 735 | 736 | 737 | 738 | 739 | 740 | Sets the Body Text Background Color 741 | 742 | 743 | 744 | 745 | 746 | 747 | Sets the Body Text Background Color 748 | 749 | 750 | 751 | 752 | 753 | 754 | Ctor 755 | 756 | 757 | 758 | 759 | Gets the current Text Body definition by the ProgressBar context ("Processing", "Paused" or "Done") 760 | 761 | 762 | 763 | 764 | 765 | 766 | Definition for the Description lines in a ProgressBar 767 | 768 | 769 | 770 | 771 | Description lines definition when ProgressBar is "Processing" 772 | 773 | 774 | 775 | 776 | Description lines definition when ProgressBar is "Paused" 777 | 778 | 779 | 780 | 781 | Description lines definition when ProgressBar is "Done" 782 | 783 | 784 | 785 | 786 | Indentation for Description lines 787 | 788 | 789 | 790 | 791 | Ctor 792 | 793 | 794 | 795 | 796 | Clears Description Lines 797 | 798 | 799 | 800 | 801 | 802 | Gets the current Description Lines definition by the ProgressBar context ("Processing", "Paused" or "Done") 803 | 804 | 805 | 806 | 807 | 808 | 809 | Definition of the text in the same line as ProgressBar (Body) 810 | 811 | 812 | 813 | 814 | Definition of the texts in the lines below a ProgressBar (Description) 815 | 816 | 817 | 818 | 819 | -------------------------------------------------------------------------------- /ConsoleProgressBar/Element.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using System; 10 | 11 | namespace iluvadev.ConsoleProgressBar 12 | { 13 | /// 14 | /// An element of a ProgressBar 15 | /// 16 | /// 17 | public class Element 18 | { 19 | private Func _ValueGetter; 20 | private Func _ForegroundColorGetter; 21 | private Func _BackgroundColorGetter; 22 | private Func _VisibleGetter; 23 | 24 | /// 25 | /// Ctor 26 | /// 27 | public Element() { } 28 | 29 | /// 30 | /// Ctor 31 | /// 32 | /// 33 | /// 34 | /// 35 | public Element(T value, ConsoleColor foregroundColor, ConsoleColor backgroundColor) 36 | { 37 | SetValue(value); 38 | SetForegroundColor(foregroundColor); 39 | SetBackgroundColor(backgroundColor); 40 | } 41 | 42 | /// 43 | /// Sets the ProgressBar element visible (or not) 44 | /// 45 | /// 46 | /// 47 | public Element SetVisible(bool show) 48 | => SetVisible(pb => show); 49 | 50 | /// 51 | /// Sets the ProgressBar element visible (or not) 52 | /// 53 | /// 54 | /// 55 | public Element SetVisible(Func showGetter) 56 | { 57 | _VisibleGetter = showGetter; 58 | return this; 59 | } 60 | /// 61 | /// Gets the ProgressBar element visibility 62 | /// 63 | /// 64 | /// 65 | public bool GetVisible(ProgressBar progressBar) 66 | => _VisibleGetter?.Invoke(progressBar) ?? true; 67 | 68 | /// 69 | /// Sets the Value of the ProgressBar element 70 | /// 71 | /// 72 | /// 73 | public Element SetValue(T value) => SetValue(pb => value); 74 | 75 | /// 76 | /// Sets the Value of the ProgressBar element 77 | /// 78 | /// 79 | /// 80 | public Element SetValue(Func valueGetter) 81 | { 82 | _ValueGetter = valueGetter; 83 | return this; 84 | } 85 | 86 | /// 87 | /// Gets the Value of the ProgressBar element 88 | /// 89 | /// 90 | /// 91 | public virtual T GetValue(ProgressBar progressBar) 92 | => GetVisible(progressBar) && _ValueGetter != null ? _ValueGetter.Invoke(progressBar) 93 | : default; 94 | 95 | /// 96 | /// Sets the ForegroundColor of the ProgressBar element 97 | /// 98 | /// 99 | /// 100 | public Element SetForegroundColor(ConsoleColor foregroundColor) 101 | => SetForegroundColor(pb => foregroundColor); 102 | 103 | /// 104 | /// Sets the ForegroundColor of the ProgressBar element 105 | /// 106 | /// 107 | /// 108 | public Element SetForegroundColor(Func foregroundColorGetter) 109 | { 110 | _ForegroundColorGetter = foregroundColorGetter; 111 | return this; 112 | } 113 | 114 | /// 115 | /// Gets the ForegroundColor of the ProgressBar element 116 | /// 117 | /// 118 | /// 119 | public virtual ConsoleColor? GetForegroundColor(ProgressBar progressBar) 120 | => (GetVisible(progressBar) && _ForegroundColorGetter != null) ? _ForegroundColorGetter.Invoke(progressBar) 121 | : (ConsoleColor?)null; 122 | 123 | /// 124 | /// Sets the BackgroundColor of the ProgressBar element 125 | /// 126 | /// 127 | /// 128 | public Element SetBackgroundColor(ConsoleColor backgroundColor) 129 | => SetBackgroundColor(pb => backgroundColor); 130 | 131 | /// 132 | /// Sets the BackgroundColor of the ProgressBar element 133 | /// 134 | /// 135 | /// 136 | public Element SetBackgroundColor(Func backgroundColorGetter) 137 | { 138 | _BackgroundColorGetter = backgroundColorGetter; 139 | return this; 140 | } 141 | 142 | /// 143 | /// Gets the BackgroundColor of the ProgressBar element 144 | /// 145 | /// 146 | /// 147 | public virtual ConsoleColor? GetBackgroundColor(ProgressBar progressBar) 148 | => (GetVisible(progressBar) && _BackgroundColorGetter != null) ? _BackgroundColorGetter.Invoke(progressBar) 149 | : (ConsoleColor?)null; 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /ConsoleProgressBar/ElementList.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using System.Collections.Generic; 10 | 11 | namespace iluvadev.ConsoleProgressBar 12 | { 13 | /// 14 | /// A list of Elements of a ProgressBar 15 | /// 16 | /// 17 | public class ElementList 18 | { 19 | /// 20 | /// The List of Elements of a Progressbar 21 | /// 22 | public List> List { get; } = new List>(); 23 | 24 | /// 25 | /// Clears the List of elements of a ProgressBar 26 | /// 27 | /// 28 | public ElementList Clear() 29 | { 30 | List.Clear(); 31 | return this; 32 | } 33 | 34 | /// 35 | /// Adds new Element to the List 36 | /// 37 | /// 38 | public Element AddNew() 39 | { 40 | var line = new Element(); 41 | List.Add(line); 42 | return line; 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /ConsoleProgressBar/Extensions/ElementExtensions.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using System; 10 | using System.Collections.Generic; 11 | 12 | namespace iluvadev.ConsoleProgressBar.Extensions 13 | { 14 | /// 15 | /// Extensions for Element 16 | /// 17 | public static class ElementExtensions 18 | { 19 | /// 20 | /// Returns a list of Actions to write the element in Console 21 | /// 22 | /// 23 | /// 24 | /// Function to Transform the value before write 25 | /// 26 | public static List GetRenderActions(this Element element, ProgressBar progressBar, Func valueTransformer = null) 27 | { 28 | var list = new List(); 29 | 30 | if (progressBar == null || element == null || !element.GetVisible(progressBar)) 31 | return list; 32 | 33 | var foregroundColor = element.GetForegroundColor(progressBar); 34 | if (foregroundColor.HasValue) list.Add(() => Console.ForegroundColor = foregroundColor.Value); 35 | 36 | var backgroundColor = element.GetBackgroundColor(progressBar); 37 | if (backgroundColor.HasValue) list.Add(() => Console.BackgroundColor = backgroundColor.Value); 38 | 39 | string value = element.GetValue(progressBar); 40 | if (valueTransformer != null) value = valueTransformer.Invoke(value); 41 | 42 | list.Add(() => Console.Write(value)); 43 | list.Add(() => Console.ResetColor()); 44 | 45 | return list; 46 | } 47 | 48 | /// 49 | /// Returns a list of Actions to write the element in Console 50 | /// 51 | /// 52 | /// 53 | /// 54 | /// 55 | public static List GetRenderActions(this Element element, ProgressBar progressBar, int repetition = 1) 56 | { 57 | var list = new List(); 58 | 59 | if (progressBar == null || repetition < 1 || element == null || !element.GetVisible(progressBar)) 60 | return list; 61 | 62 | var foregroundColor = element.GetForegroundColor(progressBar); 63 | if (foregroundColor.HasValue) list.Add(() => Console.ForegroundColor = foregroundColor.Value); 64 | 65 | var backgroundColor = element.GetBackgroundColor(progressBar); 66 | if (backgroundColor.HasValue) list.Add(() => Console.BackgroundColor = backgroundColor.Value); 67 | 68 | char value = element.GetValue(progressBar); 69 | list.Add(() => Console.Write(new string(value, repetition))); 70 | list.Add(() => Console.ResetColor()); 71 | 72 | return list; 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /ConsoleProgressBar/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using System; 10 | 11 | namespace iluvadev.ConsoleProgressBar.Extensions 12 | { 13 | /// 14 | /// Extensions for String 15 | /// 16 | public static class StringExtensions 17 | { 18 | /// 19 | /// Returns a string that occupy all console line/s 20 | /// 21 | /// The string to write in console 22 | /// To allow print the string in muliple lines or only in one: 23 | /// True: The text can be represented in more than one Console line (fill spaces to the end of last line) 24 | /// False: The text must be represented in only ONE line (truncate to fit or fill spaces to the end of line) 25 | /// 26 | /// 27 | public static string AdaptToConsole(this string value, bool allowMultipleLines = true) 28 | { 29 | int maxWidth = Console.BufferWidth; 30 | 31 | if (allowMultipleLines) 32 | maxWidth *= Math.DivRem(value.Length, maxWidth, out _) + 1; 33 | 34 | return AdaptToMaxWidth(value, maxWidth); 35 | } 36 | 37 | /// 38 | /// Returns a string with exactly maxChars: Truncates string value or fill with spaces to fits exact length 39 | /// 40 | /// 41 | /// 42 | /// Text appended when it is truncated. Default: "..." 43 | /// 44 | public static string AdaptToMaxWidth(this string value, int maxWidth, string append = "...") 45 | { 46 | value ??= ""; 47 | int len = value.Length; 48 | 49 | if (maxWidth <= 0) return ""; 50 | else if (len == maxWidth) return value; 51 | else if (len < maxWidth) return value.PadRight(maxWidth); 52 | else return value[..(maxWidth - append.Length)] + append; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ConsoleProgressBar/Extensions/TimeSpanExtensions.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using System; 10 | 11 | namespace iluvadev.ConsoleProgressBar.Extensions 12 | { 13 | /// 14 | /// TimeSpan extensions 15 | /// 16 | public static class TimeSpanExtensions 17 | { 18 | /// 19 | /// Gets a textual Sumarized for remaining time: X days, or Y hours, or Z minutes, etc. 20 | /// 21 | /// 22 | /// 23 | public static string ToStringAsSumarizedRemainingText(this TimeSpan? ts) 24 | => ts.HasValue ? ToStringAsSumarizedRemainingText(ts.Value) : "unknown"; 25 | 26 | /// 27 | /// Gets a textual Sumarized for remaining time: X days, or Y hours, or Z minutes, etc. 28 | /// 29 | /// 30 | /// 31 | public static string ToStringAsSumarizedRemainingText(this TimeSpan ts) 32 | { 33 | int units; 34 | if ((units = Convert.ToInt32(Math.Round(ts.TotalDays))) > 1) return $"{units} days"; 35 | else if ((Convert.ToInt32(Math.Floor(ts.TotalDays))) == 1) return $"a day"; 36 | else if ((units = Convert.ToInt32(Math.Round(ts.TotalHours))) > 1) return $"{units} hours"; 37 | else if ((Convert.ToInt32(Math.Floor(ts.TotalHours))) == 1) return $"an hour"; 38 | else if ((units = Convert.ToInt32(Math.Round(ts.TotalMinutes))) > 1) return $"{units} minutes"; 39 | else if ((Convert.ToInt32(Math.Floor(ts.TotalMinutes))) == 1) return $"a minute"; 40 | else if ((units = Convert.ToInt32(Math.Round(ts.TotalSeconds))) > 1) return $"{units} seconds"; 41 | else if ((Convert.ToInt32(Math.Floor(ts.TotalSeconds))) == 1) return $"a second"; 42 | else return "a moment"; 43 | } 44 | 45 | /// 46 | /// Converts a TimeSpan to String, showing all hours 47 | /// 48 | /// 49 | /// 50 | /// 51 | public static string ToStringWithAllHours(this TimeSpan? ts, bool includeMilliseconds = true) 52 | => ts.HasValue ? ToStringWithAllHours(ts.Value, includeMilliseconds) 53 | : "unknown"; 54 | 55 | /// 56 | /// Converts a TimeSpan to String, showing all hours 57 | /// 58 | /// 59 | /// 60 | /// 61 | public static string ToStringWithAllHours(this TimeSpan ts, bool includeMilliseconds = true) 62 | => includeMilliseconds ? $"{ts.TotalHours:F0}{ts:\\:mm\\:ss\\.fff}" 63 | : $"{ts.TotalHours:F0}{ts:\\:mm\\:ss}"; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ConsoleProgressBar/Layout.Body.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using System; 10 | 11 | namespace iluvadev.ConsoleProgressBar 12 | { 13 | public partial class Layout 14 | { 15 | /// 16 | /// Definition of the Layout used to Render the Body of the ProgressBar 17 | /// 18 | public class LayoutBody 19 | { 20 | /* Examples of ProgressBar: 21 | * - Marquee is a Character moving around the ProgressBar 22 | * 23 | * With Progress available (Maximum defined): 24 | * [■■■■■■■■■■■■········] -> Without Marquee 25 | * [■■■■■■■■■■■■····+···] -> With Marquee (in pending space) 26 | * [■■■■■■■■#■■■········] -> With Marquee (in progress space) 27 | * 28 | * Without Progress available (don't have Maximum): 29 | * [·······■············] -> Marquee is always displayed 30 | */ 31 | 32 | /// 33 | /// Element To show in Pending Section 34 | /// 35 | public Element Pending { get; } = new Element(); 36 | 37 | /// 38 | /// Element to show in Progress Section 39 | /// 40 | public Element Progress { get; } = new Element(); 41 | 42 | /// 43 | /// Layout for the Text 44 | /// 45 | public Element Text { get; } = new Element(); 46 | 47 | /// 48 | /// Sets the LayoutBody value for Pending and Progress elements 49 | /// 50 | /// 51 | /// 52 | public LayoutBody SetValue(char value) 53 | => SetValue(pb => value); 54 | /// 55 | /// Sets the LayoutBody value for Pending and Progress elements 56 | /// 57 | /// 58 | /// 59 | public LayoutBody SetValue(Func valueGetter) 60 | { 61 | Pending.SetValue(valueGetter); 62 | Progress.SetValue(valueGetter); 63 | return this; 64 | } 65 | 66 | /// 67 | /// Sets the ForegroundColor for Pending and Progress elements 68 | /// 69 | /// 70 | /// 71 | public LayoutBody SetForegroundColor(ConsoleColor foregroundColor) 72 | => SetForegroundColor(pb => foregroundColor); 73 | 74 | /// 75 | /// Sets the ForegroundColor for Pending and Progress elements 76 | /// 77 | /// 78 | /// 79 | public LayoutBody SetForegroundColor(Func foregroundColorGetter) 80 | { 81 | Pending.SetForegroundColor(foregroundColorGetter); 82 | Progress.SetForegroundColor(foregroundColorGetter); 83 | return this; 84 | } 85 | 86 | /// 87 | /// Sets the BackgroundColor for Pending and Progress elements 88 | /// 89 | /// 90 | /// 91 | public LayoutBody SetBackgroundColor(ConsoleColor backgroundColor) 92 | => SetBackgroundColor(pb => backgroundColor); 93 | /// 94 | /// Sets the BackgroundColor for Pending and Progress elements 95 | /// 96 | /// 97 | /// 98 | public LayoutBody SetBackgroundColor(Func backgroundColorGetter) 99 | { 100 | Pending.SetBackgroundColor(backgroundColorGetter); 101 | Progress.SetBackgroundColor(backgroundColorGetter); 102 | return this; 103 | } 104 | 105 | /// 106 | /// Ctor 107 | /// 108 | public LayoutBody() 109 | { 110 | Pending.SetValue('·').SetForegroundColor(ConsoleColor.DarkGray); 111 | Progress.SetValue('■').SetForegroundColor(ConsoleColor.DarkGreen); 112 | Text.SetVisible(false); 113 | } 114 | } 115 | 116 | } 117 | } -------------------------------------------------------------------------------- /ConsoleProgressBar/Layout.Margin.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using System; 10 | 11 | namespace iluvadev.ConsoleProgressBar 12 | { 13 | public partial class Layout 14 | { 15 | /// 16 | /// Definition of the Layout used to Render the Margins of the ProgressBar 17 | /// 18 | public class LayoutMargin 19 | { 20 | /* Examples of ProgressBar: 21 | * - Marquee is a Character moving around the ProgressBar 22 | * 23 | * With Progress available (Maximum defined): 24 | * [■■■■■■■■■■■■········] -> Without Marquee 25 | * [■■■■■■■■■■■■····+···] -> With Marquee (in pending space) 26 | * [■■■■■■■■#■■■········] -> With Marquee (in progress space) 27 | * 28 | * Without Progress available (don't have Maximum): 29 | * [·······■············] -> Marquee is always displayed 30 | */ 31 | 32 | /// 33 | /// Element to show at the Margin Left (Start of the ProgressBar) 34 | /// 35 | public Element Start { get; } = new Element(); 36 | 37 | /// 38 | /// Element to show at the Margin Right (End of the ProgressBar) 39 | /// 40 | public Element End { get; } = new Element(); 41 | 42 | /// 43 | /// Sets the LayoutMargin value for Start and End elements 44 | /// 45 | /// 46 | /// 47 | public LayoutMargin SetValue(string value) 48 | => SetValue(pb => value); 49 | 50 | /// 51 | /// Sets the LayoutMargin value for Start and End elements 52 | /// 53 | /// 54 | /// 55 | public LayoutMargin SetValue(Func valueGetter) 56 | { 57 | Start.SetValue(valueGetter); 58 | End.SetValue(valueGetter); 59 | return this; 60 | } 61 | 62 | /// 63 | /// Sets the ForegroundColor for Start and End elements 64 | /// 65 | /// 66 | /// 67 | public LayoutMargin SetForegroundColor(ConsoleColor foregroundColor) 68 | => SetForegroundColor(pb => foregroundColor); 69 | 70 | /// 71 | /// Sets the ForegroundColor for Start and End elements 72 | /// 73 | /// 74 | /// 75 | public LayoutMargin SetForegroundColor(Func foregroundColorGetter) 76 | { 77 | Start.SetForegroundColor(foregroundColorGetter); 78 | End.SetForegroundColor(foregroundColorGetter); 79 | return this; 80 | } 81 | 82 | /// 83 | /// Sets the BackgroundColor for Start and End elements 84 | /// 85 | /// 86 | /// 87 | public LayoutMargin SetBackgroundColor(ConsoleColor backgroundColor) 88 | => SetBackgroundColor(pb => backgroundColor); 89 | 90 | /// 91 | /// Sets the BackgroundColor for Start and End elements 92 | /// 93 | /// 94 | /// 95 | public LayoutMargin SetBackgroundColor(Func backgroundColorGetter) 96 | { 97 | Start.SetBackgroundColor(backgroundColorGetter); 98 | End.SetBackgroundColor(backgroundColorGetter); 99 | return this; 100 | } 101 | 102 | /// 103 | /// Sets the visibility for Start and End elements 104 | /// 105 | /// 106 | /// 107 | public LayoutMargin SetVisible(bool visible) 108 | => SetVisible(pb => visible); 109 | 110 | /// 111 | /// Sets the visibility for Start and End elements 112 | /// 113 | /// 114 | /// 115 | public LayoutMargin SetVisible(Func showGetter) 116 | { 117 | Start.SetVisible(showGetter); 118 | End.SetVisible(showGetter); 119 | return this; 120 | } 121 | 122 | /// 123 | /// Return the length of Margins 124 | /// 125 | /// 126 | /// 127 | public int GetLength(ProgressBar progressBar) 128 | => (Start.GetValue(progressBar)?.Length ?? 0) + (End.GetValue(progressBar)?.Length ?? 0); 129 | 130 | /// 131 | /// Ctor 132 | /// 133 | public LayoutMargin() 134 | { 135 | Start.SetValue("[").SetForegroundColor(ConsoleColor.DarkBlue); 136 | End.SetValue("]").SetForegroundColor(ConsoleColor.DarkBlue); 137 | } 138 | } 139 | 140 | } 141 | } -------------------------------------------------------------------------------- /ConsoleProgressBar/Layout.Marquee.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using System; 10 | 11 | namespace iluvadev.ConsoleProgressBar 12 | { 13 | 14 | public partial class Layout 15 | { 16 | /// 17 | /// Definition for the Marquee 18 | /// The Marquee is a char that moves around the ProgressBar 19 | /// 20 | public class LayoutMarquee 21 | { 22 | /* Examples of ProgressBar: 23 | * - Marquee is a Character moving around the ProgressBar 24 | * 25 | * With Progress available (Maximum defined): 26 | * [■■■■■■■■■■■■········] -> Without Marquee 27 | * [■■■■■■■■■■■■····+···] -> With Marquee (in pending space) 28 | * [■■■■■■■■#■■■········] -> With Marquee (in progress space) 29 | * 30 | * Without Progress available (don't have Maximum): 31 | * [·······■············] -> Marquee is always displayed 32 | */ 33 | 34 | /// 35 | /// Marquee definition when it moves over 'Pending' section 36 | /// 37 | public Element OverPending { get; } = new Element(); 38 | 39 | /// 40 | /// Marquee definition when it moves over 'Progress' section 41 | /// 42 | public Element OverProgress { get; } = new Element(); 43 | 44 | /// 45 | /// Sets the Marqee definition when it moves over 'Pending' or 'Progress' section 46 | /// 47 | /// 48 | /// 49 | public LayoutMarquee SetValue(char value) => SetValue(pb => value); 50 | 51 | /// 52 | /// Sets the Marqee definition when it moves over 'Pending' or 'Progress' section 53 | /// 54 | /// 55 | /// 56 | public LayoutMarquee SetValue(Func valueGetter) 57 | { 58 | OverPending.SetValue(valueGetter); 59 | OverProgress.SetValue(valueGetter); 60 | return this; 61 | } 62 | 63 | /// 64 | /// Sets the Marqee Foreground Color when it moves over 'Pending' or 'Progress' section 65 | /// 66 | /// 67 | /// 68 | public LayoutMarquee SetForegroundColor(ConsoleColor foregroundColor) 69 | => SetForegroundColor(pb => foregroundColor); 70 | 71 | /// 72 | /// Sets the Marqee Foreground Color when it moves over 'Pending' or 'Progress' section 73 | /// 74 | /// 75 | /// 76 | public LayoutMarquee SetForegroundColor(Func foregroundColorGetter) 77 | { 78 | OverPending.SetForegroundColor(foregroundColorGetter); 79 | OverProgress.SetForegroundColor(foregroundColorGetter); 80 | return this; 81 | } 82 | 83 | /// 84 | /// Sets the Marqee Background Color when it moves over 'Pending' or 'Progress' section 85 | /// 86 | /// 87 | /// 88 | public LayoutMarquee SetBackgroundColor(ConsoleColor backgroundColor) 89 | => SetBackgroundColor(pb => backgroundColor); 90 | 91 | /// 92 | /// Sets the Marqee Background Color when it moves over 'Pending' or 'Progress' section 93 | /// 94 | /// 95 | /// 96 | public LayoutMarquee SetBackgroundColor(Func backgroundColorGetter) 97 | { 98 | OverPending.SetBackgroundColor(backgroundColorGetter); 99 | OverProgress.SetBackgroundColor(backgroundColorGetter); 100 | return this; 101 | } 102 | 103 | /// 104 | /// Sets the Marqee Visibility when it moves over 'Pending' or 'Progress' section 105 | /// 106 | /// 107 | /// 108 | public LayoutMarquee SetVisible(bool visible) 109 | => SetVisible(pb => visible); 110 | 111 | /// 112 | /// Sets the Marqee Visibility when it moves over 'Pending' or 'Progress' section 113 | /// 114 | /// 115 | /// 116 | public LayoutMarquee SetVisible(Func showGetter) 117 | { 118 | OverPending.SetVisible(showGetter); 119 | OverProgress.SetVisible(showGetter); 120 | return this; 121 | } 122 | 123 | /// 124 | /// Ctor 125 | /// 126 | public LayoutMarquee() 127 | { 128 | OverPending.SetValue(pb => pb.HasProgress ? '+' : '■') 129 | .SetForegroundColor(pb => pb.HasProgress ? ConsoleColor.Yellow : ConsoleColor.Green); 130 | 131 | OverProgress.SetValue('■') 132 | .SetForegroundColor(ConsoleColor.Yellow); 133 | } 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /ConsoleProgressBar/Layout._.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using iluvadev.ConsoleProgressBar.Extensions; 10 | using System; 11 | using System.Collections.Generic; 12 | 13 | namespace iluvadev.ConsoleProgressBar 14 | { 15 | /// 16 | /// Definition of a Layout for a ProgressBar representation 17 | /// 18 | public partial class Layout 19 | { 20 | /* Examples of ProgressBar: 21 | * - Marquee is a Character moving around the ProgressBar 22 | * 23 | * With Progress available (Maximum defined): 24 | * [■■■■■■■■■■■■········] -> Without Marquee 25 | * [■■■■■■■■■■■■····+···] -> With Marquee (in pending space) 26 | * [■■■■■■■■#■■■········] -> With Marquee (in progress space) 27 | * 28 | * Without Progress available (don't have Maximum): 29 | * [·······■············] -> Marquee is always displayed 30 | */ 31 | 32 | /// 33 | /// Layout definition for Margins 34 | /// 35 | public LayoutMargin Margins { get; } = new LayoutMargin(); 36 | 37 | /// 38 | /// Layout definition for Marquee (character moving around the ProgressBar) 39 | /// 40 | public LayoutMarquee Marquee { get; } = new LayoutMarquee(); 41 | 42 | /// 43 | /// Layout definition for Body 44 | /// 45 | public LayoutBody Body { get; } = new LayoutBody(); 46 | 47 | 48 | /// 49 | /// Width of entire ProgressBar 50 | /// Default = 30 51 | /// 52 | public int ProgressBarWidth { get; set; } = 30; 53 | 54 | /// 55 | /// Gets the internal Width of the ProgressBar 56 | /// 57 | public int GetInnerWidth(ProgressBar progressBar) 58 | => Math.Max(ProgressBarWidth - Margins.GetLength(progressBar), 0); 59 | 60 | /// 61 | /// Returns the Actions to do in order to Render the ProgressBar with this Layout 62 | /// 63 | /// 64 | /// 65 | internal List GetRenderActions(ProgressBar progressBar) 66 | { 67 | // [■■■■■■■■■■■■········] -> Without Marquee 68 | // [■■■■■■■■■■■■····+···] -> Marquee over Pending space 69 | // [■■■■■■■■#■■■········] -> Marquee over Progress space 70 | // [·····+··············] -> Marquee withot progress 71 | var list = new List(); 72 | 73 | int innerWidth = GetInnerWidth(progressBar); 74 | int progressLenght = progressBar.HasProgress ? Convert.ToInt32(progressBar.Percentage / (100f / innerWidth)) : 0; 75 | int pendingLenght = innerWidth - progressLenght; 76 | 77 | bool marqueeInProgress = progressBar.HasProgress && 78 | progressBar.MarqueePosition >= 0 && progressBar.MarqueePosition < progressLenght && 79 | Marquee.OverProgress.GetVisible(progressBar); 80 | bool marqueeInPending = progressBar.MarqueePosition >= progressLenght && 81 | Marquee.OverPending.GetVisible(progressBar); 82 | 83 | int progressBeforeMarqueeLength = progressLenght; 84 | if (marqueeInProgress) progressBeforeMarqueeLength = progressBar.MarqueePosition; 85 | 86 | int progressAfterMarqueeLength = 0; 87 | if (marqueeInProgress) progressAfterMarqueeLength = progressLenght - progressBeforeMarqueeLength - 1; 88 | 89 | int pendingBeforeMarqueeLength = pendingLenght; 90 | if (marqueeInPending) pendingBeforeMarqueeLength = progressBar.MarqueePosition - progressLenght; 91 | 92 | int pendingAfterMarqueeLength = 0; 93 | if (marqueeInPending) pendingAfterMarqueeLength = pendingLenght - pendingBeforeMarqueeLength - 1; 94 | 95 | string innerText = ""; 96 | if (Body.Text.GetVisible(progressBar)) 97 | innerText = (Body.Text.GetValue(progressBar) ?? "").AdaptToMaxWidth(innerWidth); 98 | 99 | string textProgressBeforeMarquee = string.IsNullOrEmpty(innerText) ? 100 | new string(Body.Progress.GetValue(progressBar), progressBeforeMarqueeLength) 101 | : innerText.Substring(0, progressBeforeMarqueeLength); 102 | 103 | char? charProgressMarquee = null; 104 | if (marqueeInProgress) charProgressMarquee = string.IsNullOrEmpty(innerText) ? 105 | Marquee.OverProgress.GetValue(progressBar) 106 | : innerText[progressBar.MarqueePosition]; 107 | 108 | string textProgressAfterMarquee = string.IsNullOrEmpty(innerText) ? 109 | new string(Body.Progress.GetValue(progressBar), progressAfterMarqueeLength) 110 | : innerText.Substring(progressBar.MarqueePosition + 1, progressAfterMarqueeLength); 111 | 112 | string textPendingBeforeMarquee = string.IsNullOrEmpty(innerText) ? 113 | new string(Body.Pending.GetValue(progressBar), pendingBeforeMarqueeLength) 114 | : innerText.Substring(progressLenght, pendingBeforeMarqueeLength); 115 | 116 | char? charPendingMarquee = null; 117 | if (marqueeInPending) charPendingMarquee = string.IsNullOrEmpty(innerText) ? 118 | Marquee.OverPending.GetValue(progressBar) 119 | : innerText[progressBar.MarqueePosition]; 120 | 121 | string textPendingAfterMarquee = string.IsNullOrEmpty(innerText) ? 122 | new string(Body.Pending.GetValue(progressBar), pendingAfterMarqueeLength) 123 | : innerText.Substring(progressBar.MarqueePosition + 1, pendingAfterMarqueeLength); 124 | 125 | //Margin: Start 126 | list.AddRange(Margins.Start.GetRenderActions(progressBar)); 127 | 128 | //Body: Progress before Marquee 129 | if (!string.IsNullOrEmpty(textProgressBeforeMarquee)) 130 | { 131 | var elementProgressBeforeMarquee = new Element(textProgressBeforeMarquee, 132 | Body.Progress.GetForegroundColor(progressBar) ?? Console.ForegroundColor, 133 | Body.Progress.GetBackgroundColor(progressBar) ?? Console.BackgroundColor); 134 | list.AddRange(elementProgressBeforeMarquee.GetRenderActions(progressBar)); 135 | } 136 | 137 | //Body: Marquee in progress 138 | if (charProgressMarquee.HasValue) 139 | { 140 | var elementProgressMarquee = new Element(charProgressMarquee.Value, 141 | Marquee.OverProgress.GetForegroundColor(progressBar) ?? Console.ForegroundColor, 142 | Marquee.OverProgress.GetBackgroundColor(progressBar) ?? Console.BackgroundColor); 143 | list.AddRange(elementProgressMarquee.GetRenderActions(progressBar)); 144 | } 145 | 146 | //Body: Progress after Marquee 147 | if (!string.IsNullOrEmpty(textProgressAfterMarquee)) 148 | { 149 | var elementProgressAfterMarquee = new Element(textProgressAfterMarquee, 150 | Body.Progress.GetForegroundColor(progressBar) ?? Console.ForegroundColor, 151 | Body.Progress.GetBackgroundColor(progressBar) ?? Console.BackgroundColor); 152 | list.AddRange(elementProgressAfterMarquee.GetRenderActions(progressBar)); 153 | } 154 | 155 | //Body: Pending before Marquee 156 | if (!string.IsNullOrEmpty(textPendingBeforeMarquee)) 157 | { 158 | var elementPendingBeforeMarquee = new Element(textPendingBeforeMarquee, 159 | Body.Pending.GetForegroundColor(progressBar) ?? Console.ForegroundColor, 160 | Body.Pending.GetBackgroundColor(progressBar) ?? Console.BackgroundColor); 161 | list.AddRange(elementPendingBeforeMarquee.GetRenderActions(progressBar)); 162 | } 163 | 164 | //Body: Marquee in Pending 165 | if (charPendingMarquee.HasValue) 166 | { 167 | var elementPendingMarquee = new Element(charPendingMarquee.Value, 168 | Marquee.OverPending.GetForegroundColor(progressBar) ?? Console.ForegroundColor, 169 | Marquee.OverPending.GetBackgroundColor(progressBar) ?? Console.BackgroundColor); 170 | list.AddRange(elementPendingMarquee.GetRenderActions(progressBar)); 171 | } 172 | 173 | //Body: Pending after Marquee 174 | if (!string.IsNullOrEmpty(textPendingAfterMarquee)) 175 | { 176 | var elementPendingAfterMarquee = new Element(textPendingAfterMarquee, 177 | Body.Pending.GetForegroundColor(progressBar) ?? Console.ForegroundColor, 178 | Body.Pending.GetBackgroundColor(progressBar) ?? Console.BackgroundColor); 179 | list.AddRange(elementPendingAfterMarquee.GetRenderActions(progressBar)); 180 | } 181 | 182 | //Margin: End 183 | list.AddRange(Margins.End.GetRenderActions(progressBar)); 184 | 185 | return list; 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /ConsoleProgressBar/ProgressBar.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using iluvadev.ConsoleProgressBar.Extensions; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Diagnostics; 13 | using System.Linq; 14 | using System.Threading; 15 | using System.Threading.Tasks; 16 | 17 | namespace iluvadev.ConsoleProgressBar 18 | { 19 | /// 20 | /// A ProgressBar for Console 21 | /// 22 | public class ProgressBar : IDisposable 23 | { 24 | private Layout _Layout = null; 25 | /// 26 | /// Layout of the ProgressBar 27 | /// 28 | public Layout Layout 29 | { 30 | get => _Layout ??= new Layout(); 31 | set => _Layout = value; 32 | } 33 | 34 | private Text _Text = null; 35 | /// 36 | /// Text definitions for the ProgressBar 37 | /// 38 | public Text Text 39 | { 40 | get=> _Text ??= new Text(); 41 | set => _Text = value; 42 | } 43 | 44 | /// 45 | /// Tag object 46 | /// 47 | public object Tag { get; set; } 48 | 49 | /// 50 | /// The Maximum value 51 | /// Default = 100 52 | /// 53 | public int? Maximum { get; set; } = 100; 54 | 55 | private int _Value = 0; 56 | /// 57 | /// The current Value 58 | /// If Value is greater than Maximum, then updates Maximum value 59 | /// 60 | public int Value 61 | { 62 | get => _Value; 63 | set => SetValue(value); 64 | } 65 | 66 | /// 67 | /// Percentage of progress 68 | /// 69 | public int? Percentage => Maximum.HasValue ? (Maximum.Value != 0 ? ((Value * 100) / Maximum.Value) : 100) : (int?)null; 70 | 71 | /// 72 | /// Indicates if the ProgressBar has Progress defined (Maximum defined) 73 | /// 74 | public bool HasProgress => Maximum.HasValue; 75 | 76 | /// 77 | /// The amount by which to increment the ProgressBar with each call to the PerformStep() method. 78 | /// Default = 1 79 | /// 80 | public int Step { get; set; } = 1; 81 | 82 | /// 83 | /// The Name of the Curent Element 84 | /// 85 | public string ElementName { get; set; } 86 | 87 | 88 | private bool _FixedInBottom = false; 89 | /// 90 | /// True to Print the ProgressBar always in last Console Line 91 | /// False to Print the ProgressBar fixed in Console (Current position at Starting) 92 | /// You can Write at Console and ProgressBar will always be below your lines 93 | /// Default = true 94 | /// 95 | public bool FixedInBottom 96 | { 97 | get => _FixedInBottom; 98 | set 99 | { 100 | if (_FixedInBottom != value) 101 | { 102 | Unrender(); 103 | _FixedInBottom = value; 104 | Render(); 105 | } 106 | } 107 | } 108 | 109 | /// 110 | /// Delay for repaint and recalculate all ProgressBar 111 | /// Default = 75 112 | /// 113 | public int Delay { get; set; } = 75; 114 | 115 | 116 | /// 117 | /// True if ProgressBar is Started 118 | /// 119 | public bool IsStarted { get; private set; } 120 | 121 | /// 122 | /// True if ProgressBar is Paused 123 | /// 124 | public bool IsPaused { get; private set; } 125 | 126 | /// 127 | /// True if ProgresBar is Done: when disposing or Progress is finished 128 | /// 129 | public bool IsDone => CancelThread || (HasProgress && Value == Maximum); 130 | 131 | /// 132 | /// Processing time (time paused excluded) 133 | /// 134 | public TimeSpan TimeProcessing => ProgressStopwatch.Elapsed; 135 | 136 | /// 137 | /// Processing time per element (median) 138 | /// 139 | public TimeSpan? TimePerElement => TicksPerElement.HasValue ? new TimeSpan(TicksPerElement.Value) : (TimeSpan?)null; 140 | 141 | /// 142 | /// Estimated time finish (to Value = Maximum) 143 | /// 144 | public TimeSpan? TimeRemaining => TicksRemaining.HasValue ? new TimeSpan(TicksRemaining.Value) : (TimeSpan?)null; 145 | 146 | /// 147 | /// A Lock for Writing to Console 148 | /// 149 | public static readonly object ConsoleWriterLock = new object(); 150 | 151 | internal int MarqueePosition { get; set; } = -1; 152 | private int MarqueeIncrement { get; set; } = 1; 153 | 154 | private bool CancelThread { get; set; } 155 | 156 | private Stopwatch ProgressStopwatch { get; set; } 157 | private long? TicksCompletedElements { get; set; } 158 | private long? TicksPerElement => TicksCompletedElements.HasValue && Value > 0 ? TicksCompletedElements.Value / Value : (long?)null; 159 | private long? TicksRemaining 160 | { 161 | get 162 | { 163 | if (!Maximum.HasValue || !TicksPerElement.HasValue || !TicksCompletedElements.HasValue) return (long?)null; 164 | long currentTicks = ProgressStopwatch.ElapsedTicks; 165 | long currentElementTicks = currentTicks - TicksCompletedElements.Value; 166 | long elementTicks = (currentElementTicks <= TicksPerElement.Value) ? TicksPerElement.Value : currentTicks / (Value + 1); 167 | long totalTicks = elementTicks * Maximum.Value; 168 | return Math.Max(totalTicks - currentTicks, 0); 169 | } 170 | } 171 | 172 | private int _ConsoleRow = -1; 173 | private int _NumberLastLinesWritten = -1; 174 | 175 | /// 176 | /// Creates an instance of ConsoleProgressBar 177 | /// 178 | /// Initial position of the ProgressBar 179 | /// True if ProgressBar starts automatically 180 | public ProgressBar(int? initialPosition = null, bool autoStart = true) 181 | { 182 | ProgressStopwatch = new Stopwatch(); 183 | if (initialPosition.HasValue) _ConsoleRow = initialPosition.Value; 184 | if (autoStart) Start(); 185 | } 186 | 187 | /// 188 | /// Starts the ProgressBar 189 | /// 190 | public void Start() 191 | { 192 | if (IsStarted) Resume(); 193 | else (new Thread(ThreadAction) { IsBackground = true }).Start(); 194 | } 195 | 196 | private void ThreadAction() 197 | { 198 | ProgressStopwatch.Start(); 199 | IsStarted = true; 200 | while (!CancelThread) 201 | { 202 | if (!IsPaused) 203 | { 204 | try 205 | { 206 | UpdateMarqueePosition(); 207 | Render(); 208 | Task.Delay(Delay).Wait(); 209 | } 210 | catch { } 211 | } 212 | } 213 | } 214 | 215 | /// 216 | /// Pauses the ProgressBar 217 | /// 218 | public void Pause() 219 | { 220 | IsPaused = true; 221 | ProgressStopwatch.Stop(); 222 | Render(); 223 | } 224 | 225 | /// 226 | /// Resume the ProgresBar 227 | /// 228 | public void Resume() 229 | { 230 | ProgressStopwatch.Start(); 231 | IsPaused = false; 232 | Render(); 233 | } 234 | 235 | /// 236 | /// Assigns the current Value, and optionally current ElementName and Tag 237 | /// If Value is greater than Maximum, updates Maximum as Value 238 | /// 239 | /// 240 | /// 241 | /// 242 | public void SetValue(int value, string elementName = null, object tag = null) 243 | { 244 | if (value > Maximum) Maximum = value; 245 | _Value = value; 246 | TicksCompletedElements = value > 0 ? ProgressStopwatch.ElapsedTicks : (long?)null; 247 | 248 | if (elementName != null) ElementName = elementName; 249 | if (tag != null) Tag = tag; 250 | } 251 | 252 | /// 253 | /// Advances the current position of the progress bar by the amount of the Step property 254 | /// 255 | /// The name of the new Element 256 | /// 257 | public void PerformStep(string elementName = null, object tag = null) => PerformStep(Step, elementName, tag); 258 | 259 | /// 260 | /// Advances the current position of the progress bar by the amount of the Step property 261 | /// 262 | /// Step to perform 263 | /// The name of the new Element 264 | /// 265 | public void PerformStep(int step, string elementName = null, object tag = null) 266 | { 267 | if (elementName != null) ElementName = elementName; 268 | if (tag != null) Tag = tag; 269 | Value += step; 270 | } 271 | /// 272 | /// WriteLine in Console when ProgressBar is running 273 | /// 274 | public void WriteLine() => WriteLine("", null, null, true); 275 | /// 276 | /// WriteLine in Console when ProgressBar is running 277 | /// 278 | /// 279 | public void WriteLine(string value) => WriteLine(value, null, null, true); 280 | /// 281 | /// WriteLine in Console when ProgressBar is running 282 | /// 283 | /// 284 | /// 285 | public void WriteLine(string value, bool truncateToOneLine) => WriteLine(value, null, null, truncateToOneLine); 286 | /// 287 | /// WriteLine in Console when ProgressBar is running 288 | /// 289 | /// 290 | /// 291 | /// 292 | /// 293 | public void WriteLine(string value, ConsoleColor? foregroundColor = null, ConsoleColor? backgroundColor = null, bool truncateToOneLine = true) 294 | { 295 | var actions = new List(); 296 | 297 | if (foregroundColor.HasValue) actions.Add(() => Console.ForegroundColor = foregroundColor.Value); 298 | if (backgroundColor.HasValue) actions.Add(() => Console.BackgroundColor = backgroundColor.Value); 299 | actions.Add(() => Console.Write(value.AdaptToConsole(!truncateToOneLine) + Environment.NewLine)); 300 | 301 | lock (ConsoleWriterLock) 302 | { 303 | if (foregroundColor.HasValue) 304 | { 305 | var oldColor = Console.ForegroundColor; 306 | actions.Add(() => Console.ForegroundColor = oldColor); 307 | } 308 | if (backgroundColor.HasValue) 309 | { 310 | var oldColor = Console.BackgroundColor; 311 | actions.Add(() => Console.BackgroundColor = oldColor); 312 | } 313 | actions.ForEach(a => a.Invoke()); 314 | } 315 | 316 | //If FixedInBottom and we written over the ProgressBar -> Print it again 317 | if (FixedInBottom && _NumberLastLinesWritten > 0 && Console.CursorTop >= _ConsoleRow) 318 | Render(); 319 | } 320 | 321 | /// 322 | /// Renders in Console the ProgressBar 323 | /// 324 | public void Render() 325 | { 326 | List actionsProgressBar = GetRenderActionsForProgressBarAndText(); 327 | string emptyLine = " ".AdaptToConsole(); 328 | 329 | //Lock Write to console 330 | lock (ConsoleWriterLock) 331 | { 332 | int oldCursorLeft = Console.CursorLeft; 333 | int oldCursorTop = Console.CursorTop; 334 | bool oldCursorVisible = Console.CursorVisible; 335 | ConsoleColor oldForegroundColor = Console.ForegroundColor; 336 | ConsoleColor oldBackgroundColor = Console.BackgroundColor; 337 | 338 | //Hide Cursor 339 | Console.CursorVisible = false; 340 | 341 | //Position 342 | if (FixedInBottom) 343 | { 344 | if (_ConsoleRow < Console.WindowHeight - _NumberLastLinesWritten) 345 | { 346 | int newConsoleRow = Console.WindowHeight - _NumberLastLinesWritten; 347 | if (_NumberLastLinesWritten > 0 && _ConsoleRow >= 0) 348 | { 349 | //Clear old ProgressBar 350 | Console.SetCursorPosition(0, _ConsoleRow); 351 | for (int i = _ConsoleRow; i < newConsoleRow; i++) 352 | Console.WriteLine(emptyLine); 353 | } 354 | _ConsoleRow = newConsoleRow; 355 | } 356 | //if (oldCursorTop >= _ConsoleRow) 357 | //{ 358 | // //oldCursorTop is near or over: Keep 2 empty lines between Text and ProgressBar (avoid flickering) 359 | // Console.SetCursorPosition(0, oldCursorTop); 360 | // Console.WriteLine(emptyLine); 361 | // Console.WriteLine(emptyLine); 362 | // _ConsoleRow = oldCursorTop + 2; 363 | //} 364 | 365 | int scrollMargin = Math.Max((Console.WindowHeight - _NumberLastLinesWritten) / 3, 2); 366 | if (_ConsoleRow - oldCursorTop <= scrollMargin / 2) 367 | { 368 | //oldCursorTop is near or over: Keep a margin between Text and ProgressBar (avoid flickering) 369 | Console.SetCursorPosition(0, oldCursorTop); 370 | for (int i = oldCursorTop; i < _ConsoleRow + _NumberLastLinesWritten; i++) 371 | Console.WriteLine(emptyLine); 372 | _ConsoleRow = oldCursorTop + scrollMargin; 373 | } 374 | } 375 | else if (_ConsoleRow < 0) 376 | _ConsoleRow = oldCursorTop; 377 | Console.SetCursorPosition(0, _ConsoleRow); 378 | 379 | //ProgressBar and Text 380 | actionsProgressBar.ForEach(a => a.Invoke()); 381 | 382 | // Restore Cursor Position, Colors and Cursor visible 383 | Console.SetCursorPosition(oldCursorLeft, oldCursorTop); 384 | Console.ForegroundColor = oldForegroundColor; 385 | Console.BackgroundColor = oldBackgroundColor; 386 | if (oldCursorVisible) Console.CursorVisible = oldCursorVisible; 387 | } 388 | } 389 | 390 | /// 391 | /// Unrenders (remove) from Console last ProgressBar printed 392 | /// 393 | public void Unrender() 394 | { 395 | if (_ConsoleRow < 0 || _NumberLastLinesWritten <= 0) 396 | return; 397 | 398 | string emptyLine = " ".AdaptToConsole(); 399 | 400 | //Lock Write to console 401 | lock (ConsoleWriterLock) 402 | { 403 | int oldCursorLeft = Console.CursorLeft; 404 | int oldCursorTop = Console.CursorTop; 405 | bool oldCursorVisible = Console.CursorVisible; 406 | 407 | //Hide Cursor 408 | Console.CursorVisible = false; 409 | 410 | int initialRow = _ConsoleRow; 411 | if (FixedInBottom) 412 | initialRow = Math.Max(_ConsoleRow, oldCursorTop); 413 | 414 | //Position 415 | Console.SetCursorPosition(0, initialRow); 416 | 417 | //Remove lines 418 | for (int i = initialRow; i < _ConsoleRow + _NumberLastLinesWritten; i++) 419 | Console.WriteLine(emptyLine); 420 | 421 | // Restore Cursor Position and Cursor Visible 422 | Console.SetCursorPosition(oldCursorLeft, oldCursorTop); 423 | if (oldCursorVisible) Console.CursorVisible = oldCursorVisible; 424 | } 425 | } 426 | 427 | private List GetRenderActionsForProgressBarAndText() 428 | { 429 | int oldLinesWritten = _NumberLastLinesWritten; 430 | string emptyLine = " ".AdaptToConsole(); 431 | 432 | // ProgressBar 433 | List list = Layout.GetRenderActions(this); 434 | 435 | // Text in same line 436 | var maxTextLenght = Console.BufferWidth - Layout.ProgressBarWidth; 437 | if (maxTextLenght >= 10) //Text will be printed if there are 10 chars or more 438 | { 439 | var text = Text.Body.GetCurrentText(this); 440 | if (text != null) 441 | list.AddRange(text.GetRenderActions(this, s => (" " + s).AdaptToMaxWidth(maxTextLenght))); 442 | } 443 | list.Add(() => Console.Write(Environment.NewLine)); 444 | _NumberLastLinesWritten = 1; 445 | 446 | // Descriptions 447 | var descriptionList = Text.Description.GetCurrentDefinitionList(this)?.List?.Where(d => d != null && d.GetVisible(this)); 448 | if (descriptionList != null && descriptionList.Any()) 449 | { 450 | int indentationLen = Text.Description.Indentation.GetValue(this)?.Length ?? 0; 451 | var maxDescLenght = Console.BufferWidth - indentationLen; 452 | foreach (var description in descriptionList) 453 | { 454 | if (indentationLen > 0) list.AddRange(Text.Description.Indentation.GetRenderActions(this)); 455 | list.AddRange(description.GetRenderActions(this, s => s.AdaptToMaxWidth(maxDescLenght) + Environment.NewLine)); 456 | _NumberLastLinesWritten++; 457 | } 458 | } 459 | 460 | // Clear old lines 461 | if (oldLinesWritten > _NumberLastLinesWritten) 462 | { 463 | for (int i = 0; i < oldLinesWritten - _NumberLastLinesWritten; i++) 464 | list.Add(() => Console.WriteLine(emptyLine)); 465 | } 466 | return list; 467 | } 468 | 469 | private void UpdateMarqueePosition() 470 | { 471 | int newProgressPosition = MarqueePosition + MarqueeIncrement; 472 | if (newProgressPosition < 0 || newProgressPosition >= Layout.GetInnerWidth(this)) 473 | MarqueeIncrement *= -1; 474 | 475 | MarqueePosition += MarqueeIncrement; 476 | } 477 | 478 | /// 479 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 480 | /// 481 | public void Dispose() 482 | { 483 | CancelThread = true; 484 | Layout.Marquee.SetVisible(false); 485 | //UpdateRemainingTime(); 486 | Render(); 487 | if (FixedInBottom && _NumberLastLinesWritten > 0 && _ConsoleRow >= 0) 488 | Console.CursorTop = _ConsoleRow + _NumberLastLinesWritten; 489 | 490 | if (ProgressStopwatch.IsRunning) 491 | ProgressStopwatch.Stop(); 492 | ProgressStopwatch.Reset(); 493 | } 494 | } 495 | } 496 | -------------------------------------------------------------------------------- /ConsoleProgressBar/Text.Body.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using iluvadev.ConsoleProgressBar.Extensions; 10 | using System; 11 | 12 | namespace iluvadev.ConsoleProgressBar 13 | { 14 | public partial class Text 15 | { 16 | /// 17 | /// Definition for the Texts in a ProgressBar 18 | /// 19 | public class TextBody 20 | { 21 | /// 22 | /// Text in Body definition when ProgressBar is "Processing" 23 | /// 24 | public Element Processing { get; } = new Element(); 25 | 26 | /// 27 | /// Text in Body definition when ProgressBar is "Paused" 28 | /// 29 | public Element Paused { get; } = new Element(); 30 | 31 | /// 32 | /// Text in Body definition when ProgressBar is "Done" 33 | /// 34 | public Element Done { get; } = new Element(); 35 | 36 | /// 37 | /// Sets the Body Text visibility 38 | /// 39 | /// 40 | /// 41 | public TextBody SetVisible(bool show) 42 | => SetVisible(pb => show); 43 | 44 | /// 45 | /// Sets the Body Text visibility 46 | /// 47 | /// 48 | /// 49 | public TextBody SetVisible(Func showGetter) 50 | { 51 | Processing.SetVisible(showGetter); 52 | Paused.SetVisible(showGetter); 53 | Done.SetVisible(showGetter); 54 | return this; 55 | } 56 | 57 | /// 58 | /// Sets the Body Text definition in all ProgressBar states ("Processing", "Paused", "Done") 59 | /// 60 | /// 61 | /// 62 | public TextBody SetValue(string value) 63 | => SetValue(pb => value); 64 | 65 | /// 66 | /// Sets the Body Text definition in all ProgressBar states ("Processing", "Paused", "Done") 67 | /// 68 | /// 69 | /// 70 | public TextBody SetValue(Func valueGetter) 71 | { 72 | Processing.SetValue(valueGetter); 73 | Paused.SetValue(valueGetter); 74 | Done.SetValue(valueGetter); 75 | return this; 76 | } 77 | 78 | /// 79 | /// Sets the Body Text Foreground Color 80 | /// 81 | /// 82 | /// 83 | public TextBody SetForegroundColor(ConsoleColor foregroundColor) 84 | => SetForegroundColor(pb => foregroundColor); 85 | 86 | /// 87 | /// Sets the Body Text Foreground Color 88 | /// 89 | /// 90 | /// 91 | public TextBody SetForegroundColor(Func foregroundColorGetter) 92 | { 93 | Processing.SetForegroundColor(foregroundColorGetter); 94 | Paused.SetForegroundColor(foregroundColorGetter); 95 | Done.SetForegroundColor(foregroundColorGetter); 96 | return this; 97 | } 98 | 99 | /// 100 | /// Sets the Body Text Background Color 101 | /// 102 | /// 103 | /// 104 | public TextBody SetBackgroundColor(ConsoleColor backgroundColor) 105 | => SetBackgroundColor(pb => backgroundColor); 106 | 107 | /// 108 | /// Sets the Body Text Background Color 109 | /// 110 | /// 111 | /// 112 | public TextBody SetBackgroundColor(Func backgroundColorGetter) 113 | { 114 | Processing.SetBackgroundColor(backgroundColorGetter); 115 | Paused.SetBackgroundColor(backgroundColorGetter); 116 | Done.SetBackgroundColor(backgroundColorGetter); 117 | return this; 118 | } 119 | 120 | /// 121 | /// Ctor 122 | /// 123 | public TextBody() 124 | { 125 | Processing.SetValue(pb => pb.HasProgress ? 126 | $"{pb.Value} of {pb.Maximum} in {pb.TimeProcessing.ToStringWithAllHours()}, remaining: {pb.TimeRemaining.ToStringAsSumarizedRemainingText()}" 127 | : $"Processing... ({pb.Value} in {pb.TimeProcessing.ToStringWithAllHours()})") 128 | .SetForegroundColor(ConsoleColor.Cyan); 129 | 130 | Paused.SetValue(pb => pb.HasProgress ? 131 | $"Paused... Running time: {pb.TimeProcessing.ToStringWithAllHours()}" 132 | : $"{pb.Value} of {pb.Maximum} in {pb.TimeProcessing.ToStringWithAllHours()} (paused)") 133 | .SetForegroundColor(ConsoleColor.DarkCyan); 134 | 135 | Done.SetValue("Done!") 136 | .SetForegroundColor(ConsoleColor.DarkYellow); 137 | } 138 | 139 | /// 140 | /// Gets the current Text Body definition by the ProgressBar context ("Processing", "Paused" or "Done") 141 | /// 142 | /// 143 | /// 144 | public Element GetCurrentText(ProgressBar progressBar) 145 | { 146 | if (progressBar == null) return null; 147 | else if (progressBar.IsPaused) return Paused; 148 | else if (progressBar.IsDone) return Done; 149 | else if (progressBar.IsStarted) return Processing; 150 | else return null; 151 | } 152 | } 153 | 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /ConsoleProgressBar/Text.Description.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | using iluvadev.ConsoleProgressBar.Extensions; 10 | using System; 11 | 12 | namespace iluvadev.ConsoleProgressBar 13 | { 14 | public partial class Text 15 | { 16 | /// 17 | /// Definition for the Description lines in a ProgressBar 18 | /// 19 | public class TextDescription 20 | { 21 | /// 22 | /// Description lines definition when ProgressBar is "Processing" 23 | /// 24 | public ElementList Processing { get; } = new ElementList(); 25 | 26 | /// 27 | /// Description lines definition when ProgressBar is "Paused" 28 | /// 29 | public ElementList Paused { get; } = new ElementList(); 30 | 31 | /// 32 | /// Description lines definition when ProgressBar is "Done" 33 | /// 34 | public ElementList Done { get; } = new ElementList(); 35 | 36 | /// 37 | /// Indentation for Description lines 38 | /// 39 | public Element Indentation { get; } 40 | = new Element(); 41 | 42 | /// 43 | /// Ctor 44 | /// 45 | public TextDescription() 46 | { 47 | Processing.AddNew().SetValue(pb => pb.ElementName) 48 | .SetVisible(pb => !string.IsNullOrEmpty(pb.ElementName)) 49 | .SetForegroundColor(ConsoleColor.DarkYellow); 50 | 51 | Paused.AddNew().SetValue("[Paused]") 52 | .SetForegroundColor(ConsoleColor.DarkCyan); 53 | 54 | Done.AddNew().SetValue(pb => $"{pb.Value} in {pb.TimeProcessing.ToStringWithAllHours()} ({pb.TimePerElement.ToStringWithAllHours()} each one)") 55 | .SetForegroundColor(ConsoleColor.DarkGray); 56 | 57 | Indentation.SetValue(" -> ").SetForegroundColor(ConsoleColor.DarkBlue); 58 | } 59 | 60 | /// 61 | /// Clears Description Lines 62 | /// 63 | /// 64 | public TextDescription Clear() 65 | { 66 | Processing.Clear(); 67 | Paused.Clear(); 68 | Done.Clear(); 69 | return this; 70 | } 71 | 72 | /// 73 | /// Gets the current Description Lines definition by the ProgressBar context ("Processing", "Paused" or "Done") 74 | /// 75 | /// 76 | /// 77 | public ElementList GetCurrentDefinitionList(ProgressBar progressBar) 78 | { 79 | if (progressBar == null) return null; 80 | else if (progressBar.IsPaused) return Paused; 81 | else if (progressBar.IsDone) return Done; 82 | else if (progressBar.IsStarted) return Processing; 83 | else return null; 84 | } 85 | } 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /ConsoleProgressBar/Text._.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | namespace iluvadev.ConsoleProgressBar 10 | { 11 | /// 12 | /// Definitions for Texts in a ProgressBar 13 | /// 14 | public partial class Text 15 | { 16 | /// 17 | /// Definition of the text in the same line as ProgressBar (Body) 18 | /// 19 | public TextBody Body { get; } = new TextBody(); 20 | 21 | /// 22 | /// Definition of the texts in the lines below a ProgressBar (Description) 23 | /// 24 | public TextDescription Description { get; } = new TextDescription(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ConsoleProgressBarDemo/ConsoleProgressBarDemo.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | iluvadev.$(MSBuildProjectName) 7 | iluvadev.$(MSBuildProjectName.Replace(" ", "_")) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ConsoleProgressBarDemo/DemoProgressBar.cs: -------------------------------------------------------------------------------- 1 | using iluvadev.ConsoleProgressBar; 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace iluvadev.ConsoleProgressBarDemo 6 | { 7 | internal class DemoProgressBar 8 | { 9 | public static void Example01() 10 | { 11 | const int max = 500; 12 | 13 | //Create the ProgressBar 14 | // Maximum: The Max value in ProgressBar (Default is 100) 15 | using (var pb = new ProgressBar { Maximum = max }) 16 | { 17 | for (int i = 0; i < max; i++) 18 | { 19 | Task.Delay(10).Wait(); //Do something 20 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 21 | } 22 | } 23 | } 24 | 25 | public static void Example02() 26 | { 27 | const int max = 1000; 28 | 29 | //Create the ProgressBar 30 | // initialPosition: Console Line to put the ProgressBar (optional, last Console line is assumed) 31 | // autoStart: Optional, default true 32 | // Maximum: The Max value in ProgressBar (Default is 100) 33 | // Step: The increment when performStep (Default is 1) 34 | using (var pb = new ProgressBar(initialPosition: 3, autoStart: false) { Maximum = max, Step = 2 }) 35 | { 36 | pb.Start(); // autoStart=false -> we need start manually 37 | for (int i = 0; i < max; i += pb.Step) 38 | { 39 | Task.Delay(10).Wait(); //Do something 40 | pb.PerformStep(); //Step in ProgressBar 41 | } 42 | } 43 | } 44 | 45 | public static void Example03() 46 | { 47 | const int max = 500; 48 | 49 | //Create the ProgressBar 50 | // Maximum: The Max value in ProgressBar (Default is 100) 51 | using (var pb = new ProgressBar() { Maximum = null }) 52 | { 53 | for (int i = 0; i < max; i++) 54 | { 55 | Task.Delay(10).Wait(); //Do something 56 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 57 | } 58 | } 59 | } 60 | 61 | public static void Example04() 62 | { 63 | const int max = 500; 64 | 65 | //Create the ProgressBar 66 | using (var pb = new ProgressBar() { Maximum = max }) 67 | { 68 | //Set "Processing Text" Visible = false 69 | pb.Text.Body.Processing.SetVisible(false); 70 | 71 | for (int i = 0; i < max; i++) 72 | { 73 | Task.Delay(10).Wait(); //Do something 74 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 75 | } 76 | } 77 | } 78 | public static void Example05() 79 | { 80 | const int max = 500; 81 | 82 | //Create the ProgressBar 83 | using (var pb = new ProgressBar() { Maximum = max }) 84 | { 85 | //Setting fixed "Processing Text" 86 | pb.Text.Body.Processing.SetValue("Processing, please wait..."); 87 | 88 | //Setting "Done Text" 89 | pb.Text.Body.Done.SetValue("Well done!!"); 90 | 91 | //Clear "Description Text" 92 | pb.Text.Description.Clear(); 93 | 94 | for (int i = 0; i < max; i++) 95 | { 96 | Task.Delay(10).Wait(); //Do something 97 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 98 | } 99 | } 100 | } 101 | 102 | public static void Example06() 103 | { 104 | const int max = 500; 105 | 106 | //Create the ProgressBar 107 | using (var pb = new ProgressBar() { Maximum = max }) 108 | { 109 | //Setting "Processing Text" with context 110 | pb.Text.Body.Processing.SetValue(pb => ($"Processing {pb.ElementName}, please wait...")); 111 | 112 | //Setting "Done Text" with context 113 | pb.Text.Body.Done.SetValue(pb => $"Processed {pb.Maximum} in {pb.TimeProcessing.TotalSeconds}s."); 114 | 115 | //Clear "Description Text" 116 | pb.Text.Description.Clear(); 117 | 118 | for (int i = 0; i < max; i++) 119 | { 120 | string elementName = Guid.NewGuid().ToString(); 121 | 122 | Task.Delay(10).Wait(); //Do something 123 | pb.PerformStep(elementName); //Step in ProgressBar. Setting current ElementName 124 | } 125 | } 126 | } 127 | public static void Example07() 128 | { 129 | const int max = 500; 130 | 131 | //Create the ProgressBar 132 | using (var pb = new ProgressBar() { Maximum = max }) 133 | { 134 | //Clear "Description Text" 135 | pb.Text.Description.Clear(); 136 | 137 | //Setting "Description Text" when "Processing" 138 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"Element: {pb.ElementName}"); 139 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"Count: {pb.Value}"); 140 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"Processing time: {pb.TimeProcessing.TotalSeconds}s."); 141 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"Estimated remaining time: {pb.TimeRemaining?.TotalSeconds}s."); 142 | 143 | //Setting "Description Text" when "Done" 144 | pb.Text.Description.Done.AddNew().SetValue(pb => $"{pb.Value} elements in {pb.TimeProcessing.TotalSeconds}s."); 145 | 146 | for (int i = 0; i < max; i++) 147 | { 148 | string elementName = Guid.NewGuid().ToString(); 149 | 150 | Task.Delay(10).Wait(); //Do something 151 | pb.PerformStep(elementName); //Step in ProgressBar. Setting current ElementName 152 | } 153 | } 154 | } 155 | 156 | public static void Example08() 157 | { 158 | const int max = 150; 159 | 160 | //Create the ProgressBar 161 | using (var pb = new ProgressBar() { Maximum = max, FixedInBottom = true }) 162 | { 163 | //Clear "Description Text" 164 | pb.Text.Description.Clear(); 165 | 166 | for (int i = 0; i < max; i++) 167 | { 168 | string elementName = Guid.NewGuid().ToString(); 169 | 170 | Task.Delay(50).Wait(); //Do something 171 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 172 | 173 | //Writing on Console with ProgressBar 174 | pb.WriteLine($"> [{DateTime.Now:HH:mm:ss.fff}]: Processed {i}: {elementName}"); 175 | } 176 | } 177 | } 178 | 179 | public static void Example09() 180 | { 181 | const int max = 500; 182 | 183 | //Create the ProgressBar 184 | using (var pb = new ProgressBar(autoStart: false) { Maximum = max }) 185 | { 186 | // Hide Text 187 | pb.Text.Body.SetVisible(false); 188 | 189 | // Clear "Description Text" 190 | pb.Text.Description.Clear(); 191 | 192 | // Setting "Description Indentation", with color 193 | pb.Text.Description.Indentation.SetValue("└───> ") 194 | .SetForegroundColor(ConsoleColor.Cyan); 195 | 196 | // Setting "Description Text" when "Done", with color 197 | pb.Text.Description.Done.AddNew().SetValue(pb => $"{pb.Value} elements in {pb.TimeProcessing.TotalSeconds}s.") 198 | .SetForegroundColor(ConsoleColor.DarkBlue); 199 | 200 | // Hide "Margins" 201 | pb.Layout.Margins.SetVisible(false); 202 | 203 | // Setting "Body" layout 204 | pb.Layout.Body.SetValue('─'); 205 | pb.Layout.Body.Progress.SetForegroundColor(ConsoleColor.DarkGreen); 206 | pb.Layout.Body.Pending.SetForegroundColor(ConsoleColor.DarkRed); 207 | 208 | // Setting "Marquee" layout 209 | pb.Layout.Marquee.SetValue('─'); 210 | pb.Layout.Marquee.OverProgress.SetForegroundColor(ConsoleColor.Yellow); 211 | pb.Layout.Marquee.OverPending.SetForegroundColor(ConsoleColor.DarkYellow); 212 | 213 | // Setting ProgressBar width 214 | pb.Layout.ProgressBarWidth = Console.BufferWidth; 215 | 216 | pb.Start(); 217 | 218 | for (int i = 0; i < max; i++) 219 | { 220 | Task.Delay(10).Wait(); //Do something 221 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 222 | } 223 | } 224 | } 225 | 226 | public static void Example10() 227 | { 228 | const int max = 500; 229 | 230 | //Create the ProgressBar 231 | using (var pb = new ProgressBar(autoStart: false) { Maximum = max }) 232 | { 233 | // Hide Text 234 | pb.Text.Body.SetVisible(false); 235 | 236 | // Clear "Description Text" 237 | pb.Text.Description.Clear(); 238 | 239 | // Hide "Margins" 240 | pb.Layout.Margins.SetVisible(false); 241 | 242 | // Hide "Marquee" 243 | pb.Layout.Marquee.SetVisible(false); 244 | 245 | // Setting Body Colors 246 | pb.Layout.Body.Pending.SetForegroundColor(ConsoleColor.White).SetBackgroundColor(ConsoleColor.DarkRed); 247 | pb.Layout.Body.Progress.SetForegroundColor(ConsoleColor.Black).SetBackgroundColor(ConsoleColor.DarkGreen); 248 | 249 | // Setting Body Text (internal text), from Layout 250 | pb.Layout.Body.Text.SetVisible(true).SetValue(pb => 251 | { 252 | if (pb.IsDone) 253 | return $"{pb.Value} elements processed in {pb.TimeProcessing.TotalSeconds}s."; 254 | else 255 | return $"{pb.Percentage}%... Remaining: {pb.TimeRemaining?.TotalSeconds}s. - Current: {pb.ElementName}"; 256 | }); 257 | 258 | // Setting ProgressBar width 259 | pb.Layout.ProgressBarWidth = Console.BufferWidth; 260 | 261 | pb.Start(); 262 | 263 | for (int i = 0; i < max; i++) 264 | { 265 | string elementName = Guid.NewGuid().ToString(); 266 | 267 | Task.Delay(10).Wait(); //Do something 268 | pb.PerformStep(elementName); //Step in ProgressBar. Setting current ElementName 269 | } 270 | } 271 | } 272 | 273 | public static void Example11() 274 | { 275 | const int max = 500; 276 | 277 | //Create the ProgressBar 278 | using (var pb = new ProgressBar(autoStart: false) { Maximum = max }) 279 | { 280 | // Hide Text 281 | pb.Text.Body.SetVisible(false); 282 | 283 | // Clear "Description Text" 284 | pb.Text.Description.Clear(); 285 | 286 | // Hide "Description Indentation" 287 | pb.Text.Description.Indentation.SetVisible(false); 288 | 289 | // Setting "Description" when "Processing", with color 290 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"{pb.ElementName}...") 291 | .SetForegroundColor(ConsoleColor.DarkGray); 292 | 293 | 294 | // Hide "Margins" 295 | pb.Layout.Margins.SetVisible(false); 296 | 297 | // Set "Marquee" Color 298 | pb.Layout.Marquee.SetBackgroundColor(ConsoleColor.Black); 299 | 300 | // Setting Body Colors 301 | pb.Layout.Body.SetBackgroundColor(ConsoleColor.Black); 302 | pb.Layout.Body.Pending.SetForegroundColor(ConsoleColor.Red); 303 | pb.Layout.Body.Progress.SetForegroundColor(pb => pb.IsDone ? ConsoleColor.Cyan : ConsoleColor.Green); 304 | 305 | // Setting Body Text (internal text), from Layout 306 | string textDone = "----------------Done----------------"; 307 | string text = "-------------Processing-------------"; 308 | pb.Layout.Body.Text.SetVisible(true).SetValue(pb => pb.IsDone ? textDone : text); 309 | 310 | // Setting ProgressBar width 311 | pb.Layout.ProgressBarWidth = text.Length; 312 | 313 | pb.Start(); 314 | 315 | for (int i = 0; i < max; i++) 316 | { 317 | string elementName = Guid.NewGuid().ToString(); 318 | 319 | Task.Delay(10).Wait(); //Do something 320 | pb.PerformStep(elementName); //Step in ProgressBar. Setting current ElementName 321 | } 322 | } 323 | } 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /ConsoleProgressBarDemo/Program.cs: -------------------------------------------------------------------------------- 1 | // Description: ProgressBar for Console Applications, with advanced features. 2 | // Project site: https://github.com/iluvadev/ConsoleProgressBar 3 | // Issues: https://github.com/iluvadev/ConsoleProgressBar/issues 4 | // License (MIT): https://github.com/iluvadev/ConsoleProgressBar/blob/main/LICENSE 5 | // 6 | // Copyright (c) 2021, iluvadev, and released under MIT License. 7 | // 8 | 9 | 10 | using iluvadev.ConsoleProgressBar; 11 | using iluvadev.ConsoleProgressBar.Extensions; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Threading.Tasks; 15 | 16 | namespace iluvadev.ConsoleProgressBarDemo 17 | { 18 | class Program 19 | { 20 | static void Main(string[] args) 21 | { 22 | Console.ReadKey(); 23 | 24 | DemoProgressBar.Example11(); 25 | //Example2(); 26 | 27 | Console.ReadKey(); 28 | 29 | 30 | //Console.WriteLine(); 31 | //Console.WriteLine(); 32 | //Console.WriteLine(" ProgressBarConsole with customization: "); 33 | ////Console.ReadKey(); 34 | //ProgressBarLayout pgLayout2 = new ProgressBarLayout 35 | //{ 36 | // Start = "", 37 | // End = ">", 38 | // Pending = ' ', 39 | // Progress = '█', 40 | // MarqueeAlone = '-', 41 | // MarqueeInProgressPending = '·', 42 | // MarqueeInProgress = '▓', 43 | //}; 44 | //using (var pg = new ProgressBarConsole(pgLayout2) 45 | //{ 46 | // ProgressTextFunc = (pb) => pb.Text ?? $"Please, press any key. Time waiting: {pb.ProcessingTime.TotalSeconds}s", 47 | // Value = 0, 48 | // Maximum = 0, 49 | // InnerLength = 5, 50 | // MarqueeDelay = 100, 51 | // ShowProgress = false 52 | //}) 53 | //{ 54 | // var key = Console.ReadKey(true); 55 | // pg.Text = $"Thanks! The key is {key.KeyChar}"; 56 | //} 57 | ////Console.ReadKey(); 58 | 59 | //Console.WriteLine("All done! Press enter to exit"); 60 | //Console.ReadLine(); 61 | } 62 | 63 | 64 | private static void Example2() 65 | { 66 | Random random = new Random(Guid.NewGuid().GetHashCode()); 67 | //Randomize elementNames 68 | var elementNames = new List(); 69 | for (int i = 0; i < 1000; i++) 70 | { 71 | var randomNum = random.Next(200) + 20; 72 | string elementName = ""; 73 | for (int j = 0; j < randomNum; j++) 74 | elementName += (char)(random.Next(25) + 65); 75 | elementNames.Add(elementName); 76 | } 77 | 78 | Console.ReadKey(); 79 | Console.Clear(); 80 | Console.SetCursorPosition(0, 0); 81 | Console.Write("ProgressBar 5:"); 82 | Console.CursorVisible = false; 83 | Task taskPb1 = new Task(() => 84 | { 85 | using (var pb = new ProgressBar(1, false) { Maximum = 500 }) 86 | { 87 | pb.Text.Description.Clear(); 88 | pb.Layout.Marquee.SetVisible(false); 89 | pb.Layout.Margins.SetVisible(false); 90 | pb.Layout.Body.Pending.SetForegroundColor(ConsoleColor.White).SetBackgroundColor(ConsoleColor.DarkRed); 91 | pb.Layout.Body.Progress.SetForegroundColor(ConsoleColor.Black).SetBackgroundColor(ConsoleColor.DarkGreen); 92 | pb.Layout.ProgressBarWidth = Console.BufferWidth; 93 | 94 | pb.Layout.Body.Text.SetVisible(true).SetValue(p => 95 | { 96 | if (p.IsDone) 97 | return $"{p.Value} elements processed in {p.TimeProcessing.ToStringWithAllHours()}"; 98 | else 99 | return $"{p.Percentage}%... Remaining: {p.TimeRemaining.ToStringWithAllHours(false)} - Current: {p.ElementName}"; 100 | }); 101 | 102 | pb.Start(); 103 | for (int i = 0; i < 500; i++) 104 | { 105 | Task.Delay(10).Wait(); 106 | pb.PerformStep(elementNames[i % elementNames.Count]); 107 | } 108 | } 109 | }); 110 | taskPb1.Start(); 111 | 112 | Console.SetCursorPosition(0, 4); 113 | Console.Write("ProgressBar 6:"); 114 | Console.CursorVisible = false; 115 | Task taskPb2 = new Task(() => 116 | { 117 | using (var pb = new ProgressBar(5, false) { Maximum = 500 }) 118 | { 119 | pb.Text.Body.Done 120 | .SetValue(p => $"Progress Bar 6: {p.Value} elements processed in {p.TimeProcessing.ToStringWithAllHours()}") 121 | .SetForegroundColor(p => ConsoleColor.Green); 122 | 123 | string text = "------Processing------"; 124 | string textDone = "---------Done---------"; 125 | pb.Layout.Margins.SetVisible(false); 126 | pb.Layout.ProgressBarWidth = text.Length + pb.Layout.Margins.GetLength(pb); 127 | pb.Layout.Body.Text.SetVisible(true).SetValue(p => p.IsDone ? textDone : text); 128 | pb.Layout.Body.Progress.SetForegroundColor(ConsoleColor.Green); 129 | pb.Layout.Body.Pending.SetForegroundColor(ConsoleColor.DarkRed); 130 | pb.Layout.Body.SetBackgroundColor(ConsoleColor.Black); 131 | pb.Layout.Marquee.SetBackgroundColor(ConsoleColor.Black); 132 | pb.Text.Description.Clear(); 133 | 134 | pb.Start(); 135 | for (int i = 0; i < 500; i++) 136 | { 137 | Task.Delay(15).Wait(); 138 | pb.PerformStep(elementNames[i % elementNames.Count]); 139 | } 140 | } 141 | }); 142 | taskPb2.Start(); 143 | 144 | //Console.SetCursorPosition(0, 8); 145 | //Console.Write("ProgressBar 3:"); 146 | //Console.CursorVisible = false; 147 | //Task taskPb3 = new Task(() => 148 | //{ 149 | // using (var pb = new ProgressBar(9, false) { Maximum = 500 }) 150 | // { 151 | // pb.Layout.ProgressBarWidth = Console.BufferWidth; 152 | // pb.Layout.Body.Pending.SetValue('─'); 153 | // pb.Layout.Marquee.OverPending.SetValue('─'); 154 | 155 | // pb.Start(); 156 | // for (int i = 0; i < 500; i++) 157 | // { 158 | // Task.Delay(20).Wait(); 159 | // pb.PerformStep(elementNames[i % elementNames.Count]); 160 | // } 161 | // } 162 | //}); 163 | //taskPb3.Start(); 164 | 165 | //Console.SetCursorPosition(0, 13); 166 | //Console.Write("ProgressBar 4:"); 167 | //Console.CursorVisible = false; 168 | //Task taskPb4 = new Task(() => 169 | //{ 170 | // using (var pb = new ProgressBar(14, false) { Maximum = null }) 171 | // { 172 | // pb.Layout.ProgressBarWidth = 15; 173 | // pb.Layout.Margins.SetVisible(false); 174 | // pb.Layout.Body.Pending.SetValue('■').SetForegroundColor(ConsoleColor.Magenta); 175 | // pb.Layout.Marquee.OverPending.SetValue('■'); 176 | 177 | // pb.Description.Clear(); 178 | // pb.Description.Processing.AddNew().SetValue(p => p.Value.ToString()).SetForegroundColor(ConsoleColor.Yellow); 179 | // pb.Description.Processing.AddNew().SetValue(p => p.TimeProcessing.ToStringWithAllHours()).SetForegroundColor(ConsoleColor.Cyan); 180 | 181 | // pb.Start(); 182 | // for (int i = 0; i < 500; i++) 183 | // { 184 | // Task.Delay(25).Wait(); 185 | // pb.PerformStep(elementNames[i % elementNames.Count]); 186 | // } 187 | // } 188 | //}); 189 | //taskPb4.Start(); 190 | 191 | Task.WaitAll(taskPb1, taskPb2); 192 | } 193 | 194 | private static void Example3() 195 | { 196 | Random random = new Random(Guid.NewGuid().GetHashCode()); 197 | //Randomize elementNames 198 | var elementNames = new List(); 199 | for (int i = 0; i < 1000; i++) 200 | { 201 | var randomNum = random.Next(200) + 20; 202 | string elementName = ""; 203 | for (int j = 0; j < randomNum; j++) 204 | elementName += (char)(random.Next(25) + 65); 205 | elementNames.Add(elementName); 206 | } 207 | 208 | Console.ReadKey(); 209 | Console.Clear(); 210 | Console.SetCursorPosition(0, 0); 211 | Console.Write("ProgressBar 7:"); 212 | Console.CursorVisible = false; 213 | 214 | using (var pb = new ProgressBar() { Maximum = 500 }) 215 | { 216 | pb.WriteLine(); 217 | pb.WriteLine(); 218 | for (int i = 0; i < 500; i++) 219 | { 220 | Task.Delay(10).Wait(); 221 | pb.PerformStep(elementNames[i % elementNames.Count]); 222 | if ((i + 1) % 100 == 0) 223 | pb.WriteLine($"We can write... Element {i + 1} processed"); 224 | } 225 | } 226 | } 227 | 228 | private static void Example4() 229 | { 230 | Random random = new Random(Guid.NewGuid().GetHashCode()); 231 | //Randomize elementNames 232 | var elementNames = new List(); 233 | for (int i = 0; i < 1000; i++) 234 | { 235 | var randomNum = random.Next(200) + 20; 236 | string elementName = ""; 237 | for (int j = 0; j < randomNum; j++) 238 | elementName += (char)(random.Next(25) + 65); 239 | elementNames.Add(elementName); 240 | } 241 | 242 | Console.ReadKey(); 243 | Console.Clear(); 244 | Console.SetCursorPosition(0, 0); 245 | Console.WriteLine("ProgressBar 8:"); 246 | Console.WriteLine("============="); 247 | Console.WriteLine(); 248 | Console.CursorVisible = false; 249 | 250 | using (var pb = new ProgressBar(autoStart: false) { Maximum = 70 }) 251 | { 252 | pb.FixedInBottom = true; 253 | pb.Start(); 254 | for (int i = 0; i < 70; i++) 255 | { 256 | Task.Delay(120).Wait(); 257 | string elementName = elementNames[i % elementNames.Count].ToLowerInvariant(); 258 | pb.PerformStep(elementName); 259 | pb.WriteLine($"[Processed at {pb.TimeProcessing.ToStringWithAllHours(true)}] '{elementName}'", false); 260 | } 261 | } 262 | } 263 | 264 | private static void Example5() 265 | { 266 | Random random = new Random(Guid.NewGuid().GetHashCode()); 267 | //Randomize elementNames 268 | var elementNames = new List(); 269 | for (int i = 0; i < 1000; i++) 270 | { 271 | var randomNum = random.Next(200) + 20; 272 | string elementName = ""; 273 | for (int j = 0; j < randomNum; j++) 274 | elementName += (char)(random.Next(25) + 65); 275 | elementNames.Add(elementName); 276 | } 277 | 278 | Console.ReadKey(); 279 | Console.Clear(); 280 | Console.SetCursorPosition(0, 0); 281 | Console.Write("Dynamic layout:"); 282 | Console.CursorVisible = false; 283 | Task taskPb1 = new Task(() => 284 | { 285 | using (var pb = new ProgressBar(1, false) { Maximum = 100 }) 286 | { 287 | 288 | pb.Layout.Marquee.SetVisible(false); 289 | pb.Text.Description.Clear(); 290 | pb.Text.Body.SetValue(pb => $"{pb.Percentage} %") 291 | .SetForegroundColor(pb => 292 | { 293 | if (pb.Percentage < 20) return ConsoleColor.DarkRed; 294 | else if (pb.Percentage < 40) return ConsoleColor.Red; 295 | else if (pb.Percentage < 60) return ConsoleColor.DarkYellow; 296 | else if (pb.Percentage < 80) return ConsoleColor.DarkGreen; 297 | return ConsoleColor.Green; 298 | }); 299 | 300 | pb.Layout.Marquee.SetVisible(false); 301 | pb.Layout.Margins.SetVisible(false); 302 | pb.Layout.Body.SetForegroundColor(pb => 303 | { 304 | if (pb.Percentage < 20) return ConsoleColor.DarkRed; 305 | else if (pb.Percentage < 40) return ConsoleColor.Red; 306 | else if (pb.Percentage < 60) return ConsoleColor.DarkYellow; 307 | else if (pb.Percentage < 80) return ConsoleColor.DarkGreen; 308 | return ConsoleColor.Green; 309 | }).SetBackgroundColor(ConsoleColor.Black); 310 | pb.Layout.Body.Pending.SetValue('─').SetForegroundColor(ConsoleColor.DarkGray); 311 | pb.Layout.Body.Progress.SetValue('■'); 312 | pb.Layout.ProgressBarWidth = Console.BufferWidth / 2; 313 | 314 | pb.Start(); 315 | for (int i = 0; i < 100; i++) 316 | { 317 | Task.Delay(random.Next(100)).Wait(); 318 | pb.PerformStep(); 319 | } 320 | } 321 | }); 322 | taskPb1.Start(); 323 | 324 | Console.SetCursorPosition(0, 4); 325 | Console.Write("Dynamic descriptions:"); 326 | Console.CursorVisible = false; 327 | Task taskPb2 = new Task(() => 328 | { 329 | using (var pb = new ProgressBar(5, false) { Maximum = 500 }) 330 | { 331 | pb.Text.Body.Done 332 | .SetValue(p => $"Progress Bar 2: {p.Value} elements processed in {p.TimeProcessing.ToStringWithAllHours()}") 333 | .SetForegroundColor(p => ConsoleColor.Green); 334 | 335 | pb.Text.Description.Clear(); 336 | 337 | pb.Start(); 338 | for (int i = 0; i < 500; i++) 339 | { 340 | Task.Delay(10).Wait(); 341 | if ((i + 1) % 50 == 0) 342 | { 343 | var current = i + 1; 344 | var currentProcessing = pb.TimeProcessing; 345 | var currentRemaining = pb.TimeRemaining; 346 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"{current} elements processed in {currentProcessing.ToStringWithAllHours()}, remaining: {currentRemaining.ToStringWithAllHours()}; ({pb.TimeRemaining.ToStringWithAllHours()}) "); 347 | //.SetForegroundColor(pb => 348 | //{ 349 | // var dif = (pb.Value - current) % 78; 350 | // if (dif < 10) return ConsoleColor.White; 351 | // else if (dif < 20) return ConsoleColor.DarkBlue; 352 | // else if (dif < 30) return ConsoleColor.Yellow; 353 | // else if (dif < 40) return ConsoleColor.DarkGreen; 354 | // return ConsoleColor.Magenta; 355 | //}); 356 | pb.Text.Description.Done.AddNew().SetValue($"{i + 1} elements processed in {pb.TimeProcessing.TotalSeconds} secs."); 357 | } 358 | pb.PerformStep(elementNames[i % elementNames.Count]); 359 | } 360 | } 361 | }); 362 | taskPb2.Start(); 363 | 364 | 365 | 366 | Task.WaitAll(taskPb1, taskPb2); 367 | } 368 | 369 | private static void Example_Usage1() 370 | { 371 | const int max = 500; 372 | 373 | //Create the ProgressBar 374 | using (var pb = new ProgressBar { Maximum = max }) 375 | { 376 | for (int i = 0; i < max; i++) 377 | { 378 | Task.Delay(50).Wait(); //Do thinks 379 | pb.PerformStep(); //Step in ProgressBar 380 | } 381 | } 382 | } 383 | } 384 | } 385 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 iluvadev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/iluvadev) 2 | 3 | # ConsoleProgressBar 4 | A versatile and easy to use ProgressBar for Console applications, written in C#. 5 | 6 | Is **.Net Standard 2.1** (cross-platform ready). 7 | 8 | ## Features 9 | * Simple to use with many configuration options 10 | * Can show or hide a *Marquee*: a char that moves around the ProgressBar 11 | * Maximum is optional: If `Maximum` is `null`, no progress will be shown (but you can show Marquee) 12 | * Automatically calculates `Percentage` and *Estimated Remaining Time* (`TimeRemaining`) 13 | * Optional `Text` in the same line as ProgressBar 14 | * Optional multiple `Descriptions` under ProgressBar 15 | * Colors in all components: in ProgressBar `Layout` elements, in `Text` and `Descriptions` 16 | 17 | You can define dynamic content or values, with lambda expressions for: 18 | * Background and Foreground Colors of `Layout` elements, `Text` and `Descriptions` 19 | * Content of `Text` and `Descriptions` 20 | * Characters used in `Layout` to represent ProgressBar 21 | 22 | ### How it works 23 | ProgressBar creates an internal Thread. In this thread the component updates its representation in Console every few time. 24 | This time is configurable, modifying the ``Delay`` property (default: 75ms) 25 | 26 | 27 | 28 | ## Examples with images 29 | ### Default ProgressBar: 30 | 31 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example01.gif) 32 | #### Code: 33 | ```csharp 34 | const int max = 500; 35 | 36 | //Create the ProgressBar 37 | using (var pb = new ProgressBar { Maximum = max }) 38 | { 39 | for (int i = 0; i < max; i++) 40 | { 41 | Task.Delay(10).Wait(); //Do something 42 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 43 | } 44 | } 45 | ``` 46 | ### With params: 47 | 48 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example02.gif) 49 | #### Code: 50 | ```csharp 51 | const int max = 1000; 52 | 53 | //Create the ProgressBar 54 | // initialPosition: Console Line to put the ProgressBar (optional, last Console line is assumed) 55 | // autoStart: Optional, default true 56 | // Maximum: The Max value in ProgressBar (Default is 100) 57 | // Step: The increment when performStep (Default is 1) 58 | using (var pb = new ProgressBar(initialPosition: 3, autoStart: false) { Maximum = max, Step = 2}) 59 | { 60 | pb.Start(); // autoStart=false -> we need start manually 61 | for (int i = 0; i < max; i+=pb.Step) 62 | { 63 | Task.Delay(10).Wait(); //Do something 64 | pb.PerformStep(); //Step in ProgressBar 65 | } 66 | } 67 | ``` 68 | ### Without Maximum: 69 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example03.gif) 70 | #### Code: 71 | ```csharp 72 | const int max = 500; 73 | 74 | //Create the ProgressBar 75 | // Maximum: The Max value in ProgressBar (Default is 100) 76 | using (var pb = new ProgressBar() { Maximum = null }) 77 | { 78 | for (int i = 0; i < max; i++) 79 | { 80 | Task.Delay(10).Wait(); //Do something 81 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 82 | } 83 | } 84 | ``` 85 | ### Setting text: 86 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example05.gif) 87 | #### Code: 88 | ```csharp 89 | const int max = 500; 90 | 91 | //Create the ProgressBar 92 | using (var pb = new ProgressBar() { Maximum = max }) 93 | { 94 | //Setting fixed "Processing Text" 95 | pb.Text.Body.Processing.SetValue("Processing, please wait..."); 96 | 97 | //Setting "Done Text" 98 | pb.Text.Body.Done.SetValue("Well done!!"); 99 | 100 | //Clear "Description Text" 101 | pb.Text.Description.Clear(); 102 | 103 | for (int i = 0; i < max; i++) 104 | { 105 | Task.Delay(10).Wait(); //Do something 106 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 107 | } 108 | } 109 | ``` 110 | ### Setting contextual text: 111 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example06.gif) 112 | #### Code: 113 | ```csharp 114 | const int max = 500; 115 | 116 | //Create the ProgressBar 117 | using (var pb = new ProgressBar() { Maximum = max }) 118 | { 119 | //Setting "Processing Text" with context 120 | pb.Text.Body.Processing.SetValue(pb => ($"Processing {pb.ElementName}, please wait...")); 121 | 122 | //Setting "Done Text" with context 123 | pb.Text.Body.Done.SetValue(pb => $"Processed {pb.Maximum} in {pb.TimeProcessing.TotalSeconds}s."); 124 | 125 | //Clear "Description Text" 126 | pb.Text.Description.Clear(); 127 | 128 | for (int i = 0; i < max; i++) 129 | { 130 | string elementName = Guid.NewGuid().ToString(); 131 | 132 | Task.Delay(10).Wait(); //Do something 133 | pb.PerformStep(elementName); //Step in ProgressBar. Setting current ElementName 134 | } 135 | } 136 | ``` 137 | ### Setting descriptions: 138 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example07.gif) 139 | #### Code: 140 | ```csharp 141 | const int max = 500; 142 | 143 | //Create the ProgressBar 144 | using (var pb = new ProgressBar() { Maximum = max }) 145 | { 146 | //Clear "Description Text" 147 | pb.Text.Description.Clear(); 148 | 149 | //Setting "Description Text" when "Processing" 150 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"Element: {pb.ElementName}"); 151 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"Count: {pb.Value}"); 152 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"Processing time: {pb.TimeProcessing.TotalSeconds}s."); 153 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"Estimated remaining time: {pb.TimeRemaining?.TotalSeconds}s."); 154 | 155 | //Setting "Description Text" when "Done" 156 | pb.Text.Description.Done.AddNew().SetValue(pb => $"{pb.Value} elements in {pb.TimeProcessing.TotalSeconds}s."); 157 | 158 | for (int i = 0; i < max; i++) 159 | { 160 | string elementName = Guid.NewGuid().ToString(); 161 | 162 | Task.Delay(10).Wait(); //Do something 163 | pb.PerformStep(elementName); //Step in ProgressBar. Setting current ElementName 164 | } 165 | } 166 | ``` 167 | ### Writing on Console: 168 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example08.gif) 169 | #### Code: 170 | ```csharp 171 | const int max = 150; 172 | 173 | //Create the ProgressBar 174 | using (var pb = new ProgressBar() { Maximum = max, FixedInBottom = true }) 175 | { 176 | //Clear "Description Text" 177 | pb.Text.Description.Clear(); 178 | 179 | for (int i = 0; i < max; i++) 180 | { 181 | string elementName = Guid.NewGuid().ToString(); 182 | 183 | Task.Delay(50).Wait(); //Do something 184 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 185 | 186 | //Writing on Console with ProgressBar 187 | pb.WriteLine($"> [{DateTime.Now:HH:mm:ss.fff}]: Processed {i}: {elementName}"); 188 | } 189 | } 190 | ``` 191 | ### Styling (1): 192 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example09.gif) 193 | #### Code: 194 | ```csharp 195 | const int max = 500; 196 | 197 | //Create the ProgressBar 198 | using (var pb = new ProgressBar(autoStart: false) { Maximum = max }) 199 | { 200 | // Hide Text 201 | pb.Text.Body.SetVisible(false); 202 | 203 | // Clear "Description Text" 204 | pb.Text.Description.Clear(); 205 | 206 | // Setting "Description Indentation", with color 207 | pb.Text.Description.Indentation.SetValue("└───> ") 208 | .SetForegroundColor(ConsoleColor.Cyan); 209 | 210 | // Setting "Description Text" when "Done", with color 211 | pb.Text.Description.Done.AddNew().SetValue(pb => $"{pb.Value} elements in {pb.TimeProcessing.TotalSeconds}s.") 212 | .SetForegroundColor(ConsoleColor.DarkBlue); 213 | 214 | // Hide "Margins" 215 | pb.Layout.Margins.SetVisible(false); 216 | 217 | // Setting "Body" layout 218 | pb.Layout.Body.SetValue('─'); 219 | pb.Layout.Body.Progress.SetForegroundColor(ConsoleColor.DarkGreen); 220 | pb.Layout.Body.Pending.SetForegroundColor(ConsoleColor.DarkRed); 221 | 222 | // Setting "Marquee" layout 223 | pb.Layout.Marquee.SetValue('─'); 224 | pb.Layout.Marquee.OverProgress.SetForegroundColor(ConsoleColor.Yellow); 225 | pb.Layout.Marquee.OverPending.SetForegroundColor(ConsoleColor.DarkYellow); 226 | 227 | // Setting ProgressBar width 228 | pb.Layout.ProgressBarWidth = Console.BufferWidth; 229 | 230 | pb.Start(); 231 | 232 | for (int i = 0; i < max; i++) 233 | { 234 | Task.Delay(10).Wait(); //Do something 235 | pb.PerformStep(); //Step in ProgressBar (Default is 1) 236 | } 237 | } 238 | ``` 239 | ### Styling (2): 240 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example10.gif) 241 | #### Code: 242 | ```csharp 243 | const int max = 500; 244 | 245 | //Create the ProgressBar 246 | using (var pb = new ProgressBar(autoStart: false) { Maximum = max }) 247 | { 248 | // Hide Text 249 | pb.Text.Body.SetVisible(false); 250 | 251 | // Clear "Description Text" 252 | pb.Text.Description.Clear(); 253 | 254 | // Hide "Margins" 255 | pb.Layout.Margins.SetVisible(false); 256 | 257 | // Hide "Marquee" 258 | pb.Layout.Marquee.SetVisible(false); 259 | 260 | // Setting Body Colors 261 | pb.Layout.Body.Pending.SetForegroundColor(ConsoleColor.White) 262 | .SetBackgroundColor(ConsoleColor.DarkRed); 263 | pb.Layout.Body.Progress.SetForegroundColor(ConsoleColor.Black) 264 | .SetBackgroundColor(ConsoleColor.DarkGreen); 265 | 266 | // Setting Body Text (internal text), from Layout 267 | pb.Layout.Body.Text.SetVisible(true).SetValue(pb => 268 | { 269 | if (pb.IsDone) 270 | return $"{pb.Value} elements processed in {pb.TimeProcessing.TotalSeconds}s."; 271 | else 272 | return $"{pb.Percentage}%... Remaining: {pb.TimeRemaining?.TotalSeconds}s. - Current: {pb.ElementName}"; 273 | }); 274 | 275 | // Setting ProgressBar width 276 | pb.Layout.ProgressBarWidth = Console.BufferWidth; 277 | 278 | pb.Start(); 279 | 280 | for (int i = 0; i < max; i++) 281 | { 282 | string elementName = Guid.NewGuid().ToString(); 283 | 284 | Task.Delay(10).Wait(); //Do something 285 | pb.PerformStep(elementName); //Step in ProgressBar. Setting current ElementName 286 | } 287 | } 288 | ``` 289 | ### Styling (3): 290 | ![Output of Ussage](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Example11.gif) 291 | #### Code: 292 | ```csharp 293 | const int max = 500; 294 | 295 | //Create the ProgressBar 296 | using (var pb = new ProgressBar(autoStart: false) { Maximum = max }) 297 | { 298 | // Hide Text 299 | pb.Text.Body.SetVisible(false); 300 | 301 | // Clear "Description Text" 302 | pb.Text.Description.Clear(); 303 | 304 | // Hide "Description Indentation" 305 | pb.Text.Description.Indentation.SetVisible(false); 306 | 307 | // Setting "Description" when "Processing", with color 308 | pb.Text.Description.Processing.AddNew().SetValue(pb => $"{pb.ElementName}...") 309 | .SetForegroundColor(ConsoleColor.DarkGray); 310 | 311 | 312 | // Hide "Margins" 313 | pb.Layout.Margins.SetVisible(false); 314 | 315 | // Set "Marquee" Color 316 | pb.Layout.Marquee.SetBackgroundColor(ConsoleColor.Black); 317 | 318 | // Setting Body Colors 319 | pb.Layout.Body.SetBackgroundColor(ConsoleColor.Black); 320 | pb.Layout.Body.Pending.SetForegroundColor(ConsoleColor.Red); 321 | pb.Layout.Body.Progress.SetForegroundColor(pb => pb.IsDone ? ConsoleColor.Cyan : ConsoleColor.Green); 322 | 323 | // Setting Body Text (internal text), from Layout 324 | string textDone = "----------------Done----------------"; 325 | string text = "-------------Processing-------------"; 326 | pb.Layout.Body.Text.SetVisible(true).SetValue(pb => pb.IsDone ? textDone : text); 327 | 328 | // Setting ProgressBar width 329 | pb.Layout.ProgressBarWidth = text.Length; 330 | 331 | pb.Start(); 332 | 333 | for (int i = 0; i < max; i++) 334 | { 335 | string elementName = Guid.NewGuid().ToString(); 336 | 337 | Task.Delay(10).Wait(); //Do something 338 | pb.PerformStep(elementName); //Step in ProgressBar. Setting current ElementName 339 | } 340 | } 341 | ``` 342 | ### Other Style examples: 343 | 344 | ![Screencapture ConsoleProgressBar Demo](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Demo.gif) 345 | 346 | ![Screencapture ConsoleProgressBar Demo2](https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/main/docs/img/ProgressBarConsole-Demo2.gif) 347 | 348 | 349 | ## Install 350 | [![Nuget](https://img.shields.io/nuget/v/iluvadev.ConsoleProgressBar?style=plastic)](https://www.nuget.org/packages/iluvadev.ConsoleProgressBar/) 351 | 352 | Go to [Nuget project page](https://www.nuget.org/packages/iluvadev.ConsoleProgressBar/) to see options 353 | 354 | 355 | -------------------------------------------------------------------------------- /docs/ConsoleProgressBar.Extensions/ElementExtensions.md: -------------------------------------------------------------------------------- 1 | # ElementExtensions 2 | 3 | `Namespace: ConsoleProgressBar.Extensions` 4 | 5 | ```csharp 6 | public static class ElementExtensions 7 | ``` 8 | 9 | ## Static Methods 10 | 11 | | Type | Name | Summary | 12 | | --- | --- | --- | 13 | | `List` | GetRenderActions(this `Element` element, `ProgressBar` progressBar, `Func` valueTransformer = null) | Returns a list of Actions to write the element in Console | 14 | | `List` | GetRenderActions(this `Element` element, `ProgressBar` progressBar, `Int32` repetition = 1) | Returns a list of Actions to write the element in Console | 15 | 16 | --- 17 | 18 | [`< Back`](../) 19 | -------------------------------------------------------------------------------- /docs/ConsoleProgressBar.Extensions/StringExtensions.md: -------------------------------------------------------------------------------- 1 | # StringExtensions 2 | 3 | `Namespace: ConsoleProgressBar.Extensions` 4 | 5 | ```csharp 6 | public static class StringExtensions 7 | ``` 8 | 9 | ## Static Methods 10 | 11 | | Type | Name | Summary | 12 | | --- | --- | --- | 13 | | `String` | AdaptToConsole(this `String` value, `Boolean` allowMultipleLines = True) | Returns a string that occupy all console line/s | 14 | | `String` | AdaptToMaxWidth(this `String` value, `Int32` maxWidth, `String` append = ...) | Returns a string with exactly maxChars: Truncates string value or fill with spaces to fits exact length | 15 | 16 | --- 17 | 18 | [`< Back`](../) 19 | -------------------------------------------------------------------------------- /docs/ConsoleProgressBar.Extensions/TimeSpanExtensions.md: -------------------------------------------------------------------------------- 1 | # TimeSpanExtensions 2 | 3 | `Namespace: ConsoleProgressBar.Extensions` 4 | 5 | ```csharp 6 | public static class TimeSpanExtensions 7 | ``` 8 | 9 | ## Static Methods 10 | 11 | | Type | Name | Summary | 12 | | --- | --- | --- | 13 | | `String` | ToStringAsSumarizedRemainingText(this `Nullable` ts) | Gets a textual Sumarized for remaining time: X days, or Y hours, or Z minutes, etc. | 14 | | `String` | ToStringAsSumarizedRemainingText(this `TimeSpan` ts) | Gets a textual Sumarized for remaining time: X days, or Y hours, or Z minutes, etc. | 15 | | `String` | ToStringWithAllHours(this `Nullable` ts, `Boolean` includeMilliseconds = True) | Converts a TimeSpan to String, showing all hours | 16 | | `String` | ToStringWithAllHours(this `TimeSpan` ts, `Boolean` includeMilliseconds = True) | Converts a TimeSpan to String, showing all hours | 17 | 18 | --- 19 | 20 | [`< Back`](../) 21 | -------------------------------------------------------------------------------- /docs/ConsoleProgressBar/ProgressBar.md: -------------------------------------------------------------------------------- 1 | # ProgressBar 2 | 3 | `Namespace: ConsoleProgressBar` 4 | 5 | A ProgressBar for Console 6 | 7 | ```csharp 8 | public class ProgressBar 9 | : IDisposable 10 | ``` 11 | 12 | ## Properties 13 | 14 | | Type | Name | Summary | 15 | | --- | --- | --- | 16 | | `Int32` | Delay | Delay for repaint and recalculate all ProgressBar Default = 75 | 17 | | `DescriptionDefinition` | Description | Description of the ProgressBar | 18 | | `String` | ElementName | The Name of the Curent Element | 19 | | `Boolean` | FixedInBottom | True to Print the ProgressBar always in last Console Line False to Print the ProgressBar fixed in Console (Current position at Starting) You can Write at Console and ProgressBar will always be below your lines Default = true | 20 | | `Boolean` | HasProgress | Indicates if the ProgressBar has Progress defined (Maximum defined) | 21 | | `Boolean` | IsDone | True if ProgresBar is Done: when disposing or Progress is finished | 22 | | `Boolean` | IsPaused | True if ProgressBar is Paused | 23 | | `Boolean` | IsStarted | True if ProgressBar is Started | 24 | | `LayoutDefinition` | Layout | Layout of the ProgressBar | 25 | | `Nullable` | Maximum | The Maximum value Default = 100 | 26 | | `Nullable` | Percentage | Percentage of progress | 27 | | `Int32` | Step | The amount by which to increment the ProgressBar with each call to the PerformStep() method. Default = 1 | 28 | | `Object` | Tag | Tag object | 29 | | `TextDefinition` | Text | Text of the ProgressBar | 30 | | `Nullable` | TimePerElement | Processing time per element (median) | 31 | | `TimeSpan` | TimeProcessing | Processing time (time paused excluded) | 32 | | `Nullable` | TimeRemaining | Estimated time finish (to Value = Maximum) | 33 | | `Int32` | Value | The current Value If Value is greater than Maximum, then updates Maximum value | 34 | 35 | ## Methods 36 | 37 | | Type | Name | Summary | 38 | | --- | --- | --- | 39 | | `void` | Dispose() | Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. | 40 | | `void` | Pause() | Pauses the ProgressBar | 41 | | `void` | PerformStep(`String` elementName = null, `Object` tag = null) | Advances the current position of the progress bar by the amount of the Step property | 42 | | `void` | Print() | Prints in Console the ProgressBar | 43 | | `void` | Resume() | Resume the ProgresBar | 44 | | `void` | SetValue(`Int32` value, `String` elementName = null, `Object` tag = null) | Assigns the current Value, and optionally current ElementName and Tag If Value is greater than Maximum, updates Maximum as Value | 45 | | `void` | Start() | Starts the ProgressBar | 46 | | `void` | Unprint() | Unprints (remove) from Console last ProgressBar printed | 47 | | `void` | WriteLine(`String` value, `Boolean` truncateToOneLine = True) | | 48 | | `void` | WriteLine(`String` value, `Nullable` foregroundColor = null, `Nullable` backgroundColor = null, `Boolean` truncateToOneLine = True) | | 49 | 50 | ## Static Fields 51 | 52 | | Type | Name | Summary | 53 | | --- | --- | --- | 54 | | `Object` | ConsoleWriterLock | A Lock for Writing to Console | 55 | 56 | --- 57 | 58 | [`< Back`](../) 59 | -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Default-Writing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Default-Writing.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Default.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Default.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Demo.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Demo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Demo2.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Demo3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Demo3.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Demo4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Demo4.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example01.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example02.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example03.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example03.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example04.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example04.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example05.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example05.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example06.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example06.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example07.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example07.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example08.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example08.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example09.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example09.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example10.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example10.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example11.gif -------------------------------------------------------------------------------- /docs/img/ProgressBarConsole-Example_Usage1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iluvadev/ConsoleProgressBar/08b3d7b5b5a49f313043ef2a1cfa73f9ddea0467/docs/img/ProgressBarConsole-Example_Usage1.gif -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # ConsoleProgressBar 2 | 3 | ## `ConsoleProgressBar` 4 | 5 | - [`ProgressBar`](ConsoleProgressBar/ProgressBar) 6 | 7 | ## `ConsoleProgressBar.Extensions` 8 | 9 | - [`ElementExtensions`](ConsoleProgressBar.Extensions/ElementExtensions) 10 | - [`StringExtensions`](ConsoleProgressBar.Extensions/StringExtensions) 11 | - [`TimeSpanExtensions`](ConsoleProgressBar.Extensions/TimeSpanExtensions) 12 | --------------------------------------------------------------------------------