Scenario.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 {
  20. /// <summary>
  21. /// The Top level for the Scenario. This should be set to `Application.Top` in most cases.
  22. /// </summary>
  23. public Toplevel Top { get; set; }
  24. /// <summary>
  25. /// </summary>
  26. public Window Win { get; set; }
  27. /// <summary>
  28. /// Helper that provides the default Window implementation with a frame and
  29. /// label showing the name of the Scenario and logic to exit back to
  30. /// the Scenario picker UI.
  31. /// Override Init to provide any `Toplevel` behavior needed.
  32. /// </summary>
  33. /// <param name="top"></param>
  34. public virtual void Init(Toplevel top)
  35. {
  36. Top = top;
  37. Win = new Window ($"CTRL-Q to Close - Scenario: {GetName ()}") {
  38. X = 0,
  39. Y = 0,
  40. Width = Dim.Fill (),
  41. Height = Dim.Fill ()
  42. };
  43. Top.Add (Win);
  44. }
  45. [System.AttributeUsage (System.AttributeTargets.Class)]
  46. public class ScenarioMetadata : System.Attribute {
  47. /// <summary>
  48. /// Scenario Name
  49. /// </summary>
  50. public string Name { get; set; }
  51. /// <summary>
  52. /// Scenario Description
  53. /// </summary>
  54. public string Description { get; set; }
  55. public ScenarioMetadata (string Name, string Description)
  56. {
  57. this.Name = Name;
  58. this.Description = Description;
  59. }
  60. /// <summary>
  61. /// Static helper function to get the Scenario Name given a Type
  62. /// </summary>
  63. /// <param name="t"></param>
  64. /// <returns></returns>
  65. public static string GetName (Type t) => ((ScenarioMetadata)System.Attribute.GetCustomAttributes (t) [0]).Name;
  66. /// <summary>
  67. /// Static helper function to get the Scenario Description given a Type
  68. /// </summary>
  69. /// <param name="t"></param>
  70. /// <returns></returns>
  71. public static string GetDescription (Type t) => ((ScenarioMetadata)System.Attribute.GetCustomAttributes (t) [0]).Description;
  72. }
  73. /// <summary>
  74. /// Helper to get the Scenario Name
  75. /// </summary>
  76. /// <returns></returns>
  77. public string GetName () => ScenarioMetadata.GetName (this.GetType ());
  78. /// <summary>
  79. /// Helper to get the Scenario Descripiton
  80. /// </summary>
  81. /// <returns></returns>
  82. public string GetDescription () => ScenarioMetadata.GetDescription (this.GetType ());
  83. [System.AttributeUsage (System.AttributeTargets.Class, AllowMultiple = true)]
  84. public class ScenarioCategory : System.Attribute {
  85. /// <summary>
  86. /// Category Name
  87. /// </summary>
  88. public string Name { get; set; }
  89. public ScenarioCategory (string Name) => this.Name = Name;
  90. /// <summary>
  91. /// Static helper function to get the Scenario Name given a Type
  92. /// </summary>
  93. /// <param name="t"></param>
  94. /// <returns></returns>
  95. public static string GetName (Type t) => ((ScenarioCategory)System.Attribute.GetCustomAttributes (t) [0]).Name;
  96. /// <summary>
  97. /// Static helper function to get the Scenario Categories given a Type
  98. /// </summary>
  99. /// <param name="t"></param>
  100. /// <returns></returns>
  101. public static List<string> GetCategories (Type t) => System.Attribute.GetCustomAttributes (t)
  102. .ToList ()
  103. .Where (a => a is ScenarioCategory)
  104. .Select (a => ((ScenarioCategory)a).Name)
  105. .ToList ();
  106. }
  107. /// <summary>
  108. /// Helper function to get the Categories of a Scenario
  109. /// </summary>
  110. /// <returns></returns>
  111. public List<string> GetCategories () => ScenarioCategory.GetCategories (this.GetType ());
  112. public override string ToString () => $"{GetName (),-30}{GetDescription ()}";
  113. /// <summary>
  114. /// Override this to implement the Scenario setup logic (create controls, etc...).
  115. /// </summary>
  116. public virtual void Setup ()
  117. {
  118. }
  119. /// <summary>
  120. /// Runs the scenario. Override to start the scearnio using a Top level different than `Top`.
  121. /// </summary>
  122. public virtual void Run ()
  123. {
  124. Application.Run (Top);
  125. }
  126. /// <summary>
  127. /// Stops the scenario. Override to implement shutdown behavior for the Scenario.
  128. /// </summary>
  129. public virtual void RequestStop ()
  130. {
  131. Application.RequestStop ();
  132. }
  133. /// <summary>
  134. /// Returns a list of all Categories set by all of the scenarios defined in the project.
  135. /// </summary>
  136. internal static List<string> GetAllCategories ()
  137. {
  138. List<string> categories = new List<string> () { "All" };
  139. foreach (Type type in typeof (Scenario).Assembly.GetTypes ()
  140. .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (Scenario)))) {
  141. List<System.Attribute> attrs = System.Attribute.GetCustomAttributes (type).ToList ();
  142. categories = categories.Union (attrs.Where (a => a is ScenarioCategory).Select (a => ((ScenarioCategory)a).Name)).ToList ();
  143. }
  144. return categories;
  145. }
  146. /// <summary>
  147. /// Returns an instance of each Scenario defined in the project.
  148. /// https://stackoverflow.com/questions/5411694/get-all-inherited-classes-of-an-abstract-class
  149. /// </summary>
  150. internal static List<Type> GetDerivedClassesCollection ()
  151. {
  152. List<Type> objects = new List<Type> ();
  153. foreach (Type type in typeof (Scenario).Assembly.GetTypes ()
  154. .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (Scenario)))) {
  155. objects.Add (type);
  156. }
  157. return objects;
  158. }
  159. }
  160. }