Program.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. #nullable enable
  2. // Example demonstrating how to make ANY View runnable without implementing IRunnable
  3. using Terminal.Gui.App;
  4. using Terminal.Gui.Drawing;
  5. using Terminal.Gui.Examples;
  6. using Terminal.Gui.ViewBase;
  7. using Terminal.Gui.Views;
  8. [assembly: ExampleMetadata ("Runnable Wrapper Example", "Shows how to wrap any View to make it runnable without implementing IRunnable")]
  9. [assembly: ExampleCategory ("API Patterns")]
  10. [assembly: ExampleCategory ("Views")]
  11. [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["t", "e", "s", "t", "Esc"], Order = 1)]
  12. [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["Enter", "Esc"], DelayMs = 100, Order = 2)]
  13. [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["Enter", "Esc"], DelayMs = 100, Order = 3)]
  14. [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["Enter", "Esc"], DelayMs = 100, Order = 4)]
  15. [assembly: ExampleDemoKeyStrokes (KeyStrokes = ["Enter", "Esc"], DelayMs = 100, Order = 5)]
  16. // Check for test context to determine driver
  17. string? contextJson = Environment.GetEnvironmentVariable (ExampleContext.ENVIRONMENT_VARIABLE_NAME);
  18. string? driverName = null;
  19. var isExample = false;
  20. if (!string.IsNullOrEmpty (contextJson))
  21. {
  22. ExampleContext? context = ExampleContext.FromJson (contextJson);
  23. driverName = context?.DriverName;
  24. isExample = true;
  25. }
  26. IApplication app = Application.Create (example: isExample);
  27. app.Init (driverName);
  28. // Example 1: Use extension method with result extraction
  29. var textField = new TextField { Width = 40, Text = "Default text" };
  30. textField.Title = "Enter your name";
  31. textField.BorderStyle = LineStyle.Single;
  32. RunnableWrapper<TextField, string> textRunnable = textField.AsRunnable (tf => tf.Text);
  33. app.Run (textRunnable);
  34. if (textRunnable.Result is { } name)
  35. {
  36. MessageBox.Query (app, "Result", $"You entered: {name}", "OK");
  37. }
  38. else
  39. {
  40. MessageBox.Query (app, "Result", "Canceled", "OK");
  41. }
  42. textRunnable.Dispose ();
  43. // Example 2: Use IApplication.RunView() for one-liner
  44. Color selectedColor = app.RunView (
  45. new ColorPicker
  46. {
  47. Title = "Pick a Color",
  48. BorderStyle = LineStyle.Single
  49. },
  50. cp => cp.SelectedColor);
  51. MessageBox.Query (app, "Result", $"Selected color: {selectedColor}", "OK");
  52. // Example 3: FlagSelector with typed enum result
  53. FlagSelector<SelectorStyles> flagSelector = new()
  54. {
  55. Title = "Choose Styles",
  56. BorderStyle = LineStyle.Single
  57. };
  58. RunnableWrapper<FlagSelector<SelectorStyles>, SelectorStyles?> flagsRunnable = flagSelector.AsRunnable (fs => fs.Value);
  59. app.Run (flagsRunnable);
  60. MessageBox.Query (app, "Result", $"Selected styles: {flagsRunnable.Result}", "OK");
  61. flagsRunnable.Dispose ();
  62. // Example 4: Any View without result extraction
  63. var label = new Label
  64. {
  65. Text = "Press Esc to continue...",
  66. X = Pos.Center (),
  67. Y = Pos.Center ()
  68. };
  69. RunnableWrapper<Label, object> labelRunnable = label.AsRunnable ();
  70. app.Run (labelRunnable);
  71. // Can still access the wrapped view
  72. MessageBox.Query (app, "Result", $"Label text was: {labelRunnable.WrappedView.Text}", "OK");
  73. labelRunnable.Dispose ();
  74. // Example 5: Complex custom View made runnable
  75. View formView = CreateCustomForm ();
  76. RunnableWrapper<View, FormData> formRunnable = formView.AsRunnable (ExtractFormData);
  77. app.Run (formRunnable);
  78. if (formRunnable.Result is { } formData)
  79. {
  80. MessageBox.Query (
  81. app,
  82. "Form Results",
  83. $"Name: {formData.Name}\nAge: {formData.Age}\nAgreed: {formData.Agreed}",
  84. "OK");
  85. }
  86. formRunnable.Dispose ();
  87. app.Dispose ();
  88. // Helper method to create a custom form
  89. View CreateCustomForm ()
  90. {
  91. var form = new View
  92. {
  93. Title = "User Information",
  94. BorderStyle = LineStyle.Single,
  95. Width = 50,
  96. Height = 10
  97. };
  98. var nameField = new TextField
  99. {
  100. Id = "nameField",
  101. X = 10,
  102. Y = 1,
  103. Width = 30
  104. };
  105. var ageField = new TextField
  106. {
  107. Id = "ageField",
  108. X = 10,
  109. Y = 3,
  110. Width = 10
  111. };
  112. var agreeCheckbox = new CheckBox
  113. {
  114. Id = "agreeCheckbox",
  115. Title = "I agree to terms",
  116. X = 10,
  117. Y = 5
  118. };
  119. var okButton = new Button
  120. {
  121. Title = "OK",
  122. X = Pos.Center (),
  123. Y = 7,
  124. IsDefault = true
  125. };
  126. okButton.Accepting += (s, e) =>
  127. {
  128. form.App?.RequestStop ();
  129. e.Handled = true;
  130. };
  131. form.Add (new Label { Text = "Name:", X = 2, Y = 1 });
  132. form.Add (nameField);
  133. form.Add (new Label { Text = "Age:", X = 2, Y = 3 });
  134. form.Add (ageField);
  135. form.Add (agreeCheckbox);
  136. form.Add (okButton);
  137. return form;
  138. }
  139. // Helper method to extract data from the custom form
  140. FormData ExtractFormData (View form)
  141. {
  142. var nameField = form.SubViews.FirstOrDefault (v => v.Id == "nameField") as TextField;
  143. var ageField = form.SubViews.FirstOrDefault (v => v.Id == "ageField") as TextField;
  144. var agreeCheckbox = form.SubViews.FirstOrDefault (v => v.Id == "agreeCheckbox") as CheckBox;
  145. return new()
  146. {
  147. Name = nameField?.Text ?? string.Empty,
  148. Age = int.TryParse (ageField?.Text, out int age) ? age : 0,
  149. Agreed = agreeCheckbox?.CheckedState == CheckState.Checked
  150. };
  151. }
  152. // Result type for custom form
  153. internal record FormData
  154. {
  155. public string Name { get; init; } = string.Empty;
  156. public int Age { get; init; }
  157. public bool Agreed { get; init; }
  158. }