use crate::core::geometry::Rect;
use crate::core::event::{Event, EventType, KeyCode, MB_LEFT_BUTTON};
use crate::core::draw::DrawBuffer;
use crate::core::palette::colors;
use crate::core::command::CommandId;
use crate::terminal::Terminal;
use super::view::{View, write_line_to_terminal};
pub struct StatusItem {
pub text: String,
pub key_code: KeyCode,
pub command: CommandId,
}
impl StatusItem {
pub fn new(text: &str, key_code: KeyCode, command: CommandId) -> Self {
Self {
text: text.to_string(),
key_code,
command,
}
}
}
pub struct StatusLine {
bounds: Rect,
items: Vec<StatusItem>,
item_positions: Vec<(i16, i16)>, }
impl StatusLine {
pub fn new(bounds: Rect, items: Vec<StatusItem>) -> Self {
Self {
bounds,
items,
item_positions: Vec::new(),
}
}
}
impl View for StatusLine {
fn bounds(&self) -> Rect {
self.bounds
}
fn set_bounds(&mut self, bounds: Rect) {
self.bounds = bounds;
}
fn draw(&mut self, terminal: &mut Terminal) {
let width = self.bounds.width() as usize;
let mut buf = DrawBuffer::new(width);
buf.move_char(0, ' ', colors::STATUS_NORMAL, width);
self.item_positions.clear();
let mut x = 1;
for item in &self.items {
if x + item.text.len() + 2 < width {
let start_x = x as i16;
let mut chars = item.text.chars();
#[allow(clippy::while_let_on_iterator)]
while let Some(ch) = chars.next() {
if ch == '~' {
#[allow(clippy::while_let_on_iterator)]
while let Some(shortcut_ch) = chars.next() {
if shortcut_ch == '~' {
break; }
buf.put_char(x, shortcut_ch, colors::STATUS_SHORTCUT); x += 1;
}
} else {
buf.put_char(x, ch, colors::STATUS_NORMAL);
x += 1;
}
}
let end_x = x as i16;
self.item_positions.push((start_x, end_x));
buf.move_str(x, " │ ", colors::STATUS_NORMAL);
x += 3;
}
}
write_line_to_terminal(terminal, self.bounds.a.x, self.bounds.a.y, &buf);
}
fn handle_event(&mut self, event: &mut Event) {
if event.what == EventType::MouseDown {
let mouse_pos = event.mouse.pos;
if event.mouse.buttons & MB_LEFT_BUTTON != 0 {
if mouse_pos.y == self.bounds.a.y {
for (i, &(start_x, end_x)) in self.item_positions.iter().enumerate() {
if i < self.items.len() {
let absolute_start = self.bounds.a.x + start_x;
let absolute_end = self.bounds.a.x + end_x;
if mouse_pos.x >= absolute_start && mouse_pos.x < absolute_end {
let item = &self.items[i];
if item.command != 0 {
*event = Event::command(item.command);
return;
}
}
}
}
}
}
}
if event.what == EventType::Keyboard {
for item in &self.items {
if event.key_code == item.key_code {
*event = Event::command(item.command);
return;
}
}
}
}
}