reconstruct ccTUI, add Button component

This commit is contained in:
2025-10-10 21:43:24 +08:00
parent 61baedb606
commit 8e95fe8ad1
14 changed files with 1292 additions and 1162 deletions

100
src/lib/ccTUI/Button.ts Normal file
View File

@@ -0,0 +1,100 @@
import { UIComponent } from "./UIComponent";
import { Signal } from "./signal";
import { KeyEvent } from "../event";
/**
* Button component
*/
export class Button extends UIComponent {
private text: string;
private textColor: number;
private bgColor: number;
private pressed = false;
// Signal for when button is clicked
public onClick = new Signal<void>();
constructor(
objectName: string,
x: number,
y: number,
text: string,
textColor: number = colors.white,
bgColor: number = colors.black,
) {
// Width is based on text length plus 2 for the brackets ( [text] )
super(objectName, x, y, text.length + 2, 1);
this.text = text;
this.textColor = textColor;
this.bgColor = bgColor;
}
render(): void {
if (!this.visible) return;
const [originalX, originalY] = term.getCursorPos();
// Set colors based on state (normal, focused, or pressed)
let textColor = this.textColor;
let backgroundColor = this.bgColor;
if (this.pressed) {
textColor = this.bgColor; // Swap text and background colors when pressed
backgroundColor = this.textColor;
} else if (this.focused) {
textColor = colors.yellow; // Yellow text when focused
}
term.setTextColor(textColor);
term.setBackgroundColor(backgroundColor);
// Move cursor to position and draw button
term.setCursorPos(this.x, this.y);
term.write(`[${this.text}]`);
// Restore original cursor position
term.setCursorPos(originalX, originalY);
}
handleKeyInput(event: KeyEvent): void {
if (!this.focused) return;
this.onKeyPress.emit(event);
const key = event.key;
// Handle button activation with space or enter
if (key === keys.space || key === keys.enter) {
this.pressButton();
}
}
handleMouseClick(_event: { x: number; y: number }): void {
// Button was clicked, trigger press
this.pressButton();
}
private pressButton(): void {
// Set pressed state and render
this.pressed = true;
this.render();
// Trigger click signal
this.onClick.emit();
// Reset pressed state after a short delay to show visual feedback
this.startTimer(() => {
this.pressed = false;
this.render();
}, 100);
}
setText(newText: string): void {
this.text = newText;
this.width = newText.length + 2; // Update width based on new text
}
getText(): string {
return this.text;
}
}