OutputView.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #nullable enable
  2. using Terminal.Gui.App;
  3. using Terminal.Gui.Configuration;
  4. using Terminal.Gui.Drawing;
  5. using Terminal.Gui.ViewBase;
  6. using Terminal.Gui.Views;
  7. using Attribute = Terminal.Gui.Drawing.Attribute;
  8. // Disable all shadows and highlights
  9. ConfigurationManager.RuntimeConfig = """
  10. {
  11. "Themes": [
  12. {
  13. "Default": {
  14. "Window.DefaultShadow": "None",
  15. "CheckBox.DefaultHighlightStyle": "None",
  16. "Dialog.DefaultShadow": "None",
  17. "Button.DefaultShadow": "None",
  18. "Menuv2.DefaultBorderStyle": "Single"
  19. }
  20. }
  21. ]
  22. }
  23. """;
  24. ConfigurationManager.Enable (ConfigLocations.Runtime);
  25. // Get the view name and output file from commandline
  26. string? viewName = null;
  27. string? outputFile = null;
  28. string [] commandArgs = Environment.GetCommandLineArgs ();
  29. for (var i = 0; i < commandArgs.Length; i++)
  30. {
  31. if (commandArgs [i].StartsWith ("--view=", StringComparison.OrdinalIgnoreCase))
  32. {
  33. viewName = commandArgs [i] ["--view=".Length..];
  34. }
  35. else if (commandArgs [i] == "--view" && i + 1 < commandArgs.Length)
  36. {
  37. viewName = commandArgs [i + 1];
  38. }
  39. else if (commandArgs [i].StartsWith ("--output=", StringComparison.OrdinalIgnoreCase))
  40. {
  41. outputFile = commandArgs [i] ["--output=".Length..];
  42. }
  43. else if (commandArgs [i] == "--output" && i + 1 < commandArgs.Length)
  44. {
  45. outputFile = commandArgs [i + 1];
  46. }
  47. }
  48. if (string.IsNullOrEmpty (viewName))
  49. {
  50. Console.WriteLine (@"No view name specified. Use --view=ViewName to specify a view.");
  51. return;
  52. }
  53. ViewDemoWindow.ViewName = viewName;
  54. // Force 16 colors and end after first iteration
  55. Application.EndAfterFirstIteration = true;
  56. var demoWindow = Application.Run<ViewDemoWindow> ();
  57. string? output = demoWindow.Output?.Trim ();
  58. demoWindow.Dispose ();
  59. // Before the application exits, reset Terminal.Gui for clean shutdown
  60. Application.Shutdown ();
  61. if (output is null)
  62. {
  63. Console.WriteLine (@"No output was generated.");
  64. return;
  65. }
  66. // Write to file or console
  67. if (!string.IsNullOrEmpty (outputFile))
  68. {
  69. File.WriteAllText (outputFile, output);
  70. }
  71. else
  72. {
  73. Console.WriteLine (output);
  74. }
  75. // Defines a top-level window with border and title
  76. public class ViewDemoWindow : Window
  77. {
  78. public static string? ViewName { get; set; }
  79. public string? Output { get; set; }
  80. public ViewDemoWindow ()
  81. {
  82. // Limit the size of the window to 50x20, which works good for most views
  83. Width = 50;
  84. Height = 20;
  85. // Use only white on black
  86. SetScheme (new (new Attribute (ColorName16.White, ColorName16.Black)));
  87. BorderStyle = LineStyle.None;
  88. // Convert ViewName to type that's in the Terminal.Gui assembly:
  89. var type = Type.GetType ($"Terminal.Gui.Views.{ViewName!}, Terminal.Gui", false, true);
  90. if (type is null)
  91. {
  92. Console.WriteLine (@$"View {ViewName} type is invalid.");
  93. return;
  94. }
  95. // Create the view
  96. View? view = CreateView (type!);
  97. if (view is null)
  98. {
  99. Console.WriteLine (@$"View {ViewName} could not be created.");
  100. return;
  101. }
  102. // Initialize the view
  103. view.Initialized += ViewInitialized;
  104. base.Add (view);
  105. // In normal apps, each iteration would call Application.LayoutAndDraw()
  106. // but since we set Application.EndAfterFirstIteration = true, we need to
  107. // call it manually here and capture the output
  108. Application.Iteration += (sender, args) =>
  109. {
  110. Application.LayoutAndDraw ();
  111. Output = Application.ToString ();
  112. };
  113. }
  114. private static View? CreateView (Type type)
  115. {
  116. // If we are to create a generic Type
  117. if (type.IsGenericType)
  118. {
  119. // For each of the <T> arguments
  120. List<Type> typeArguments = new ();
  121. // use <object> or the original type if applicable
  122. foreach (Type arg in type.GetGenericArguments ())
  123. {
  124. if (arg.IsValueType && Nullable.GetUnderlyingType (arg) == null)
  125. {
  126. typeArguments.Add (arg);
  127. }
  128. else
  129. {
  130. typeArguments.Add (typeof (object));
  131. }
  132. }
  133. // And change what type we are instantiating from MyClass<T> to MyClass<object> or MyClass<T>
  134. type = type.MakeGenericType (typeArguments.ToArray ());
  135. }
  136. // Ensure the type does not contain any generic parameters
  137. if (type.ContainsGenericParameters)
  138. {
  139. Console.WriteLine (@$"Cannot create an instance of {type} because it contains generic parameters.");
  140. return null;
  141. }
  142. // Instantiate view
  143. var view = (View)Activator.CreateInstance (type)!;
  144. if (view is IDesignable designable)
  145. {
  146. var settingsEditorDemoText = "Demo Text";
  147. designable.EnableForDesign (ref settingsEditorDemoText);
  148. }
  149. else
  150. {
  151. view.Text = "Demo Text";
  152. view.Title = "_Demo Title";
  153. }
  154. return view;
  155. }
  156. private static void ViewInitialized (object? sender, EventArgs e)
  157. {
  158. if (sender is not View view)
  159. {
  160. return;
  161. }
  162. if (view.Width == Dim.Absolute (0) || view.Width is null)
  163. {
  164. view.Width = Dim.Fill ();
  165. }
  166. if (view.Height == Dim.Absolute (0) || view.Height is null)
  167. {
  168. view.Height = Dim.Fill ();
  169. }
  170. view.X = 0;
  171. view.Y = 0;
  172. }
  173. }