use std::any::Any;
use std::sync::{Arc, Mutex};
use super::component::Component;
use super::container::Container;
use super::tui::{OverlayHandle, OverlayOptions, TuiMode, TuiStopOptions, TUI};
use crate::terminal::Terminal;
pub struct TuiMainScreen {
terminal: Box<dyn Terminal>,
container: Container,
running: Mutex<bool>,
show_hardware_cursor: Mutex<bool>,
clear_on_shrink: Mutex<bool>,
focused: Mutex<Option<Arc<dyn Component>>>,
full_redraw_count: Mutex<usize>,
}
impl TuiMainScreen {
pub fn new(terminal: Box<dyn Terminal>, show_hardware_cursor: bool, _log_directory: Option<&str>) -> Self {
Self {
terminal,
container: Container::new(),
running: Mutex::new(false),
show_hardware_cursor: Mutex::new(show_hardware_cursor),
clear_on_shrink: Mutex::new(false),
focused: Mutex::new(None),
full_redraw_count: Mutex::new(0),
}
}
}
impl Component for TuiMainScreen {
fn render(&self, width: usize) -> Vec<String> {
self.container.render(width)
}
fn invalidate(&self) {
self.container.invalidate();
}
fn as_any(&self) -> &dyn Any {
self
}
}
impl TUI for TuiMainScreen {
fn mode(&self) -> TuiMode {
TuiMode::Regular
}
fn terminal(&self) -> &dyn Terminal {
self.terminal.as_ref()
}
fn children(&self) -> Vec<Arc<dyn Component>> {
Vec::new()
}
fn add_child(&self, component: Arc<dyn Component>) {
self.container.add_child(component);
}
fn remove_child(&self, _component: &Arc<dyn Component>) {
}
fn clear(&self) {
self.container.clear();
}
fn get_show_hardware_cursor(&self) -> bool {
self.show_hardware_cursor.lock().map(|s| *s).unwrap_or(false)
}
fn set_show_hardware_cursor(&self, enabled: bool) {
if let Ok(mut show) = self.show_hardware_cursor.lock() {
*show = enabled;
}
}
fn get_clear_on_shrink(&self) -> bool {
self.clear_on_shrink.lock().map(|s| *s).unwrap_or(false)
}
fn set_clear_on_shrink(&self, enabled: bool) {
if let Ok(mut clear) = self.clear_on_shrink.lock() {
*clear = enabled;
}
}
fn set_focus(&self, component: Option<Arc<dyn Component>>) {
if let Ok(mut focused) = self.focused.lock() {
*focused = component;
}
}
fn get_focus(&self) -> Option<Arc<dyn Component>> {
self.focused.lock().ok()?.clone()
}
fn show_overlay(&self, _component: Arc<dyn Component>, _options: Option<OverlayOptions>) -> Arc<dyn OverlayHandle> {
Arc::new(DummyOverlayHandle)
}
fn hide_overlay(&self) {
}
fn has_overlay(&self) -> bool {
false
}
fn start(&self) {
if let Ok(mut running) = self.running.lock() {
*running = true;
}
self.terminal.show_cursor();
self.request_render(false);
}
fn stop(&self, _options: TuiStopOptions) {
if let Ok(mut running) = self.running.lock() {
*running = false;
}
self.terminal.show_cursor();
self.terminal.stop();
}
fn render_now(&self, force: bool) {
if force {
if let Ok(mut count) = self.full_redraw_count.lock() {
*count += 1;
}
}
let width = self.terminal.columns();
let lines = self.render(width);
for (i, line) in lines.iter().enumerate() {
if i > 0 {
self.terminal.write("\r\n");
}
self.terminal.write(line);
}
self.terminal.flush();
}
fn request_render(&self, _force: bool) {
self.render_now(false);
}
fn full_redraws(&self) -> usize {
self.full_redraw_count.lock().map(|c| *c).unwrap_or(0)
}
}
struct DummyOverlayHandle;
impl OverlayHandle for DummyOverlayHandle {
fn hide(&self) {}
fn set_hidden(&self, _hidden: bool) {}
fn is_hidden(&self) -> bool { false }
fn focus(&self) {}
fn is_focused(&self) -> bool { false }
}