Scenario.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using NStack;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using Terminal.Gui;
  6. namespace UICatalog {
  7. /// <summary>
  8. /// Base class for each demo/scenario. To define a new sceanrio simply
  9. ///
  10. /// 1) declare a class derived from Scenario,
  11. /// 2) Set Name and Description as appropriate using [ScenarioMetadata] attribute
  12. /// 3) Set one or more categories with the [ScenarioCategory] attribute
  13. /// 4) Implement Setup.
  14. /// 5) Optionally, implement Run.
  15. ///
  16. /// The Main program uses reflection to find all sceanarios and adds them to the
  17. /// ListViews. Press ENTER to run the selected sceanrio. Press CTRL-Q to exit it.
  18. /// </summary>
  19. public class Scenario : IDisposable {
  20. private bool _disposedValue;
  21. /// <summary>
  22. /// The Top level for the Scenario. This should be set to `Application.Top` in most cases.
  23. /// </summary>
  24. public Toplevel Top { get; set; }
  25. /// <summary>
  26. /// </summary>
  27. public Window Win { get; set; }
  28. /// <summary>
  29. /// Helper that provides the default Window implementation with a frame and
  30. /// label showing the name of the Scenario and logic to exit back to
  31. /// the Scenario picker UI.
  32. /// Override Init to provide any `Toplevel` behavior needed.
  33. /// </summary>
  34. /// <param name="top"></param>
  35. public virtual void Init(Toplevel top)
  36. {
  37. Top = top;
  38. Win = new Window ($"CTRL-Q to Close - Scenario: {GetName ()}") {
  39. X = 0,
  40. Y = 0,
  41. Width = Dim.Fill (),
  42. Height = Dim.Fill ()
  43. };
  44. Top.Add (Win);
  45. }
  46. [System.AttributeUsage (System.AttributeTargets.Class)]
  47. public class ScenarioMetadata : System.Attribute {
  48. /// <summary>
  49. /// Scenario Name
  50. /// </summary>
  51. public string Name { get; set; }
  52. /// <summary>
  53. /// Scenario Description
  54. /// </summary>
  55. public string Description { get; set; }
  56. public ScenarioMetadata (string Name, string Description)
  57. {
  58. this.Name = Name;
  59. this.Description = Description;
  60. }
  61. /// <summary>
  62. /// Static helper function to get the Scenario Name given a Type
  63. /// </summary>
  64. /// <param name="t"></param>
  65. /// <returns></returns>
  66. public static string GetName (Type t) => ((ScenarioMetadata)System.Attribute.GetCustomAttributes (t) [0]).Name;
  67. /// <summary>
  68. /// Static helper function to get the Scenario Description given a Type
  69. /// </summary>
  70. /// <param name="t"></param>
  71. /// <returns></returns>
  72. public static string GetDescription (Type t) => ((ScenarioMetadata)System.Attribute.GetCustomAttributes (t) [0]).Description;
  73. }
  74. /// <summary>
  75. /// Helper to get the Scenario Name
  76. /// </summary>
  77. /// <returns></returns>
  78. public string GetName () => ScenarioMetadata.GetName (this.GetType ());
  79. /// <summary>
  80. /// Helper to get the Scenario Descripiton
  81. /// </summary>
  82. /// <returns></returns>
  83. public string GetDescription () => ScenarioMetadata.GetDescription (this.GetType ());
  84. [System.AttributeUsage (System.AttributeTargets.Class, AllowMultiple = true)]
  85. public class ScenarioCategory : System.Attribute {
  86. /// <summary>
  87. /// Category Name
  88. /// </summary>
  89. public string Name { get; set; }
  90. public ScenarioCategory (string Name) => this.Name = Name;
  91. /// <summary>
  92. /// Static helper function to get the Scenario Name given a Type
  93. /// </summary>
  94. /// <param name="t"></param>
  95. /// <returns></returns>
  96. public static string GetName (Type t) => ((ScenarioCategory)System.Attribute.GetCustomAttributes (t) [0]).Name;
  97. /// <summary>
  98. /// Static helper function to get the Scenario Categories given a Type
  99. /// </summary>
  100. /// <param name="t"></param>
  101. /// <returns></returns>
  102. public static List<string> GetCategories (Type t) => System.Attribute.GetCustomAttributes (t)
  103. .ToList ()
  104. .Where (a => a is ScenarioCategory)
  105. .Select (a => ((ScenarioCategory)a).Name)
  106. .ToList ();
  107. }
  108. /// <summary>
  109. /// Helper function to get the Categories of a Scenario
  110. /// </summary>
  111. /// <returns></returns>
  112. public List<string> GetCategories () => ScenarioCategory.GetCategories (this.GetType ());
  113. public override string ToString () => $"{GetName (),-30}{GetDescription ()}";
  114. /// <summary>
  115. /// Override this to implement the Scenario setup logic (create controls, etc...).
  116. /// </summary>
  117. public virtual void Setup ()
  118. {
  119. }
  120. /// <summary>
  121. /// Runs the scenario. Override to start the scearnio using a Top level different than `Top`.
  122. /// </summary>
  123. public virtual void Run ()
  124. {
  125. Application.Run (Top);
  126. }
  127. /// <summary>
  128. /// Stops the scenario. Override to implement shutdown behavior for the Scenario.
  129. /// </summary>
  130. public virtual void RequestStop ()
  131. {
  132. Application.RequestStop ();
  133. }
  134. /// <summary>
  135. /// Returns a list of all Categories set by all of the scenarios defined in the project.
  136. /// </summary>
  137. internal static List<string> GetAllCategories ()
  138. {
  139. List<string> categories = new List<string> () { "All" };
  140. foreach (Type type in typeof (Scenario).Assembly.GetTypes ()
  141. .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (Scenario)))) {
  142. List<System.Attribute> attrs = System.Attribute.GetCustomAttributes (type).ToList ();
  143. categories = categories.Union (attrs.Where (a => a is ScenarioCategory).Select (a => ((ScenarioCategory)a).Name)).ToList ();
  144. }
  145. return categories;
  146. }
  147. /// <summary>
  148. /// Returns an instance of each Scenario defined in the project.
  149. /// https://stackoverflow.com/questions/5411694/get-all-inherited-classes-of-an-abstract-class
  150. /// </summary>
  151. internal static List<Type> GetDerivedClassesCollection ()
  152. {
  153. List<Type> objects = new List<Type> ();
  154. foreach (Type type in typeof (Scenario).Assembly.GetTypes ()
  155. .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (Scenario)))) {
  156. objects.Add (type);
  157. }
  158. return objects;
  159. }
  160. protected virtual void Dispose (bool disposing)
  161. {
  162. if (!_disposedValue) {
  163. if (disposing) {
  164. // TODO: dispose managed state (managed objects)
  165. }
  166. // TODO: free unmanaged resources (unmanaged objects) and override finalizer
  167. // TODO: set large fields to null
  168. _disposedValue = true;
  169. }
  170. }
  171. public void Dispose ()
  172. {
  173. // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
  174. Dispose (disposing: true);
  175. GC.SuppressFinalize (this);
  176. }
  177. }
  178. }