-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEnhancedWindowExample.cs
More file actions
312 lines (255 loc) · 11.6 KB
/
EnhancedWindowExample.cs
File metadata and controls
312 lines (255 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
using System.Drawing;
using Fallout.TerminalHacker.Components;
using Fallout.TerminalHacker.Console.Services;
using Fallout.TerminalHacker.Models;
using Fallout.TerminalHacker.Services;
namespace Fallout.TerminalHacker.Console.Examples;
public class EnhancedWindowExample
{
public static async Task DemonstrateEnhancedWindows()
{
// Create main console writer
using var consoleWriter = new ConsoleWriterService(new StyleControlHandler());
await consoleWriter.ClearAsync();
// Example 1: Simple window with border and title
await DemoBasicWindowAsync(consoleWriter);
Console.ReadKey();
// Example 2: Window with components
await DemoWindowWithComponentsAsync(consoleWriter);
Console.ReadKey();
// Example 3: Complex scrollable window
await DemoScrollableWindowAsync(consoleWriter);
Console.ReadKey();
// Example 4: Multiple windows with different configurations
await DemoMultipleWindowTypesAsync(consoleWriter);
Console.ReadKey();
}
private static async Task DemoBasicWindowAsync(IConsoleWriter mainWriter)
{
await mainWriter.ClearAsync();
// Create window with border and title
var window = new Window(mainWriter, 10, 5, 50, 15)
{
HasBorder = true,
Title = "Basic Window Demo"
};
using var windowWriter = new WindowWriter(mainWriter, window);
// Write content to the window's content area
windowWriter.CharStyle = CharStyle.Bright;
await windowWriter.WriteLineAsync("=== Window Content Area ===");
windowWriter.CharStyle = CharStyle.Normal;
windowWriter.GotoContentXY(0, 2);
await windowWriter.WriteLineAsync("This text is written in the content area.");
await windowWriter.WriteLineAsync("The border and title are automatically drawn.");
windowWriter.GotoContentXY(2, 5);
windowWriter.CharStyle = CharStyle.Warning;
await windowWriter.WriteLineAsync("Content area dimensions:");
windowWriter.CharStyle = CharStyle.Normal;
await windowWriter.WriteLineAsync($"Size: {windowWriter.ScreenSize.Width}x{windowWriter.ScreenSize.Height}");
// Show positioning info
await mainWriter.WriteLineAsync();
mainWriter.CursorPosition = new Point(0, 22);
await mainWriter.WriteLineAsync("Press any key for next demo...");
}
private static async Task DemoWindowWithComponentsAsync(IConsoleWriter mainWriter)
{
await mainWriter.ClearAsync();
// Create window with components
var window = new Window(mainWriter, 5, 3, 60, 18)
{
HasBorder = true,
Title = "Window with Components"
};
using var windowWriter = new WindowWriter(mainWriter, window);
// Add components using helper methods
var helpButton = WindowLayoutHelper.AddHelpButton(window, "F1:Help");
var statusBar = WindowLayoutHelper.AddStatusBar(window, "Ready | Components Demo");
// Add a custom button
var exitButton = new BorderButton(window.Width - 15, 1, "F10:Exit")
{
Style = CharStyle.Error,
HoverStyle = CharStyle.Bright
};
window.AddComponent(exitButton);
// Set up event handlers
helpButton.Click += (s, e) =>
{
statusBar.SetText("Help requested | F1 pressed");
_ = Task.Run(async () => await windowWriter.RefreshWindowAsync());
};
exitButton.Click += (s, e) =>
{
statusBar.SetText("Exit requested | F10 pressed");
_ = Task.Run(async () => await windowWriter.RefreshWindowAsync());
};
// Write content
await windowWriter.WriteLineAsync("This window demonstrates components:");
await windowWriter.WriteLineAsync();
await windowWriter.WriteLineAsync("• Help button in top border");
await windowWriter.WriteLineAsync("• Exit button in top border");
await windowWriter.WriteLineAsync("• Status bar in bottom border");
await windowWriter.WriteLineAsync();
await windowWriter.WriteLineAsync("Components are interactive and can handle events.");
windowWriter.GotoContentXY(0, 8);
windowWriter.CharStyle = CharStyle.Dimmed;
await windowWriter.WriteLineAsync("Note: Event handling simulation only");
await windowWriter.WriteLineAsync("(Real mouse/keyboard integration would require");
await windowWriter.WriteLineAsync("additional platform-specific code)");
// Simulate component interactions
await Task.Delay(1000);
helpButton.IsHovered = true;
await windowWriter.RefreshWindowAsync();
await Task.Delay(1000);
helpButton.IsHovered = false;
exitButton.IsHovered = true;
await windowWriter.RefreshWindowAsync();
mainWriter.CursorPosition = new Point(0, 23);
await mainWriter.WriteLineAsync("Press any key for next demo...");
}
private static async Task DemoScrollableWindowAsync(IConsoleWriter mainWriter)
{
await mainWriter.ClearAsync();
// Create scrollable window
var window = new Window(mainWriter, 8, 2, 55, 20)
{
HasBorder = true,
Title = "Scrollable Content Window"
};
using var windowWriter = new WindowWriter(mainWriter, window);
// Set up complete scrollable layout
var (scrollBar, helpButton, statusBar) = WindowLayoutHelper.SetupScrollableWindow(
window, "F1:Help", "Scrollable Demo | Use ↑↓ to scroll"
);
// Generate sample content (more than fits in window)
var sampleLines = GenerateSampleContent(30);
scrollBar.TotalItems = sampleLines.Count;
scrollBar.VisibleItems = windowWriter.ScreenSize.Height;
scrollBar.ScrollPosition = 0;
// Event handlers
helpButton.Click += (s, e) =>
{
statusBar.SetText("Help: Use ↑↓ arrows to scroll content");
_ = Task.Run(async () => await windowWriter.RefreshWindowAsync());
};
scrollBar.ScrollChanged += async (s, newPosition) =>
{
statusBar.SetText($"Scrolled to position {newPosition} of {scrollBar.TotalItems - scrollBar.VisibleItems}");
await RefreshContentAsync(windowWriter, sampleLines, newPosition);
await windowWriter.RefreshWindowAsync();
};
// Initial content display
await RefreshContentAsync(windowWriter, sampleLines, 0);
// Simulate scrolling
for (int i = 0; i < 5; i++)
{
await Task.Delay(1500);
scrollBar.ScrollPosition = Math.Min(scrollBar.ScrollPosition + 3,
Math.Max(0, scrollBar.TotalItems - scrollBar.VisibleItems));
await scrollBar.ScrollChanged.Invoke(scrollBar, scrollBar.ScrollPosition);
}
mainWriter.CursorPosition = new Point(0, 24);
await mainWriter.WriteLineAsync("Press any key for next demo...");
}
private static async Task DemoMultipleWindowTypesAsync(IConsoleWriter mainWriter)
{
await mainWriter.ClearAsync();
// Window without border
var borderlessWindow = new Window(mainWriter, 2, 2, 25, 8)
{
HasBorder = false,
Title = "Ignored" // Title ignored when no border
};
using (var writer1 = new WindowWriter(mainWriter, borderlessWindow))
{
writer1.CharStyle = CharStyle.Bright;
await writer1.WriteLineAsync("Borderless Window");
writer1.CharStyle = CharStyle.Normal;
await writer1.WriteLineAsync();
await writer1.WriteLineAsync("No border, no title");
await writer1.WriteLineAsync("Content fills entire");
await writer1.WriteLineAsync("window area.");
}
// Window with border but no title
var borderedWindow = new Window(mainWriter, 30, 2, 35, 12)
{
HasBorder = true,
Title = string.Empty
};
using (var writer2 = new WindowWriter(mainWriter, borderedWindow))
{
writer2.CharStyle = CharStyle.Warning;
await writer2.WriteLineAsync("Bordered Window (No Title)");
writer2.CharStyle = CharStyle.Normal;
await writer2.WriteLineAsync();
await writer2.WriteLineAsync("Has border but no title.");
await writer2.WriteLineAsync("Content area starts at row 1.");
// Add just a status bar
var statusBar = WindowLayoutHelper.AddStatusBar(borderedWindow, "Status: No title window");
}
// Small window with title
var smallTitledWindow = new Window(mainWriter, 10, 16, 40, 8)
{
HasBorder = true,
Title = "Small Titled Window"
};
using (var writer3 = new WindowWriter(mainWriter, smallTitledWindow))
{
await writer3.WriteLineAsync("Compact window with title.");
await writer3.WriteLineAsync("Limited content space due");
await writer3.WriteLineAsync("to title overhead.");
}
mainWriter.CursorPosition = new Point(0, 26);
await mainWriter.WriteLineAsync("Demo complete! Different window types shown above.");
}
private static List<string> GenerateSampleContent(int lineCount)
{
var content = new List<string>();
for (int i = 1; i <= lineCount; i++)
{
content.Add($"Content line {i:D2}: This is sample scrollable content that demonstrates how the scroll bar works.");
}
return content;
}
private static async Task RefreshContentAsync(WindowWriter writer, List<string> lines, int scrollPosition)
{
await writer.ClearContentAsync();
var visibleLines = Math.Min(writer.ScreenSize.Height, lines.Count - scrollPosition);
for (int i = 0; i < visibleLines; i++)
{
var lineIndex = scrollPosition + i;
if (lineIndex < lines.Count)
{
writer.GotoContentXY(0, i);
await writer.WriteLineAsync(lines[lineIndex]);
}
}
}
}
// Example of a custom component
public class ProgressComponent : BaseComponent
{
public int Value { get; set; }
public int Maximum { get; set; } = 100;
public string Label { get; set; } = "Progress";
public ProgressComponent(int left, int top, int width)
: base(left, top, width, 1)
{
}
public override async Task RenderAsync(IConsoleWriter writer, CancellationToken cancellationToken = default)
{
if (!Visible || Parent == null) return;
var absolutePos = GetAbsolutePosition();
writer.CursorPosition = absolutePos;
var percentage = Maximum > 0 ? (Value * 100) / Maximum : 0;
var progressWidth = _bounds.Width - Label.Length - 6; // Space for label and percentage
var filledWidth = (Value * progressWidth) / Math.Max(1, Maximum);
using var scope = new ColorScope(writer, CharStyle.Normal);
await writer.WriteAsync($"{Label}: ", cancellationToken);
using var progressScope = new ColorScope(writer, CharStyle.Bright);
await writer.WriteAsync(new string('█', filledWidth), cancellationToken);
using var emptyScope = new ColorScope(writer, CharStyle.Dimmed);
await writer.WriteAsync(new string('░', progressWidth - filledWidth), cancellationToken);
using var percentScope = new ColorScope(writer, CharStyle.Normal);
await writer.WriteAsync($" {percentage:D3}%", cancellationToken);
}
}