run method
Initializes and runs the app.
- Reads terminal size using TerminalFunctions.
- Optionally switches the terminal into fullscreen mode if
fullScreenMode
is true, using the entire screen. - Creates a CanvasBuffer for rendering.
- Initializes input handling, focus, and interactivity.
- Measures layout and renders the component tree.
The fullScreenMode
parameter controls whether the app runs in
fullscreen or uses the current terminal viewport.
Implementation
void run({bool fullScreenMode = false}) async {
final AppInstance appInstance = createInstance() as AppInstance;
final rawTerminalWidth = TerminalFunctions.hasTerminal
? TerminalFunctions.terminalWidth
: 80;
final rawTerminalHeight = TerminalFunctions.hasTerminal
? TerminalFunctions.terminalHeight
: 20;
final LayoutEngine engine = LayoutEngine(
rootInstance: appInstance,
children: appInstance.childrenInstance,
direction: direction,
bounds: Rect(
x: 0,
y: 0,
width: rawTerminalWidth,
height: rawTerminalHeight,
),
);
final layoutHeight = engine.fitHeight();
final layoutWidth = engine.fitWidth();
final terminalWidth = min(rawTerminalWidth, layoutWidth);
final terminalHeight = min(rawTerminalHeight, layoutHeight);
final buffer = CanvasBuffer(
width: terminalWidth,
height: terminalHeight,
isFullscreen: fullScreenMode,
);
final RenderManager renderer = RenderManager(buffer: buffer);
final Context context = Context();
final InputDispatcher dispatcher = InputDispatcher(renderer: renderer);
final InputManager inputManager = InputManager(dispatcher: dispatcher);
final supportsCursor = await inputManager.isCursorSupported();
if (supportsCursor) {
Logger.trace(App._tag, "Supports cursor fetching cursor position");
final point = await inputManager.fetchCursorPosition();
buffer.setTerminalOffset(point.x + 1, point.y + 1);
context.setInitialCursorPosition(point.x, point.y);
inputManager.returnedCursorPositionX = point.x + 1;
inputManager.returnedCursorPositionY = point.y + terminalHeight + 2;
} else {
Logger.warn(
App._tag,
"Terminal doesn't support cursor. Ignore if this is a test environment",
);
}
final FocusManager focusManager = FocusManager(context: context);
final ComponentInputHandler componentInputHandler = ComponentInputHandler(
focusManager,
);
final InteractableRegistry registry = InteractableRegistry();
registry.registerInteractables(appInstance, focusManager, renderer);
final List<InputHandler> handlers = [
focusManager,
CommandModeHandler(),
componentInputHandler,
];
for (var handler in handlers) {
dispatcher.registerHandler(handler);
}
for (final handler in InputRegistry.handlers) {
Logger.trace(App._tag, 'Registering handler $handler');
dispatcher.registerHandler(handler);
}
final measuredSize = appInstance.measure(
Size(width: rawTerminalWidth, height: rawTerminalHeight),
);
final bounds = Rect(
x: 0,
y: 0,
width: measuredSize.width,
height: measuredSize.height,
);
Logger.trace(App._tag, 'Writing Components to Canvas Buffer');
appInstance.render(buffer, bounds);
Logger.trace(App._tag, 'READY');
buffer.render();
Timer.periodic(Duration(milliseconds: 16), (timer) {
if (appInstance.shouldRebuild || renderer.needsRecompute) {
appInstance.shouldRebuild = false;
appInstance._childrenInstance =
appInstance.initialChildren; // reassign to reset any tree state
buffer.clear();
focusManager.reset();
registry.registerInteractables(appInstance, focusManager, renderer);
final engine = LayoutEngine(
rootInstance: appInstance,
children: appInstance.childrenInstance,
direction: direction,
bounds: Rect(x: 0, y: 0, width: bounds.width, height: bounds.height),
);
final int termWidth = min(engine.fitWidth(), rawTerminalWidth);
final int termHeight = min(engine.fitHeight(), rawTerminalHeight);
var (x, y) = buffer.getTerminalOffset();
inputManager.returnedCursorPositionX = x + 1;
inputManager.returnedCursorPositionY = y + termWidth + 2;
buffer.updateDimensions(termWidth, termHeight);
final items = engine.compute(
Size(width: bounds.width, height: bounds.height),
);
renderer.requestRecompute(bounds);
renderer.needsRecompute = false;
appInstance._renderPositionedComponents(buffer, items);
buffer.render();
}
});
}