use crossterm::event::{MouseButton, MouseEvent, MouseEventKind};
use newtui::Key;
use ratatui::layout::Rect;
use crate::modal_size::SizeKey;
use crate::prefix::{MetaAction, Sequencer, Step, BINDINGS};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Effect {
Forward(Key),
Size(SizeKey),
Redraw,
Nothing,
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct Controls {
meta: Sequencer,
prefix: Key,
resizing: bool,
dragging: bool,
help: bool,
}
impl Controls {
pub(crate) fn new(prefix: Key) -> Self {
Self {
meta: Sequencer::new(prefix),
prefix,
resizing: false,
dragging: false,
help: false,
}
}
pub(crate) fn key(&mut self, key: Key) -> Effect {
if self.resizing {
return match key {
Key::Up => Effect::Size(SizeKey::Grow),
Key::Down => Effect::Size(SizeKey::Shrink),
Key::Enter | Key::Esc => {
self.resizing = false;
Effect::Nothing
}
_ => Effect::Nothing,
};
}
self.help = false;
match self.meta.feed(key, &BINDINGS) {
Step::Pass(key) => Effect::Forward(key),
Step::Armed | Step::Cancelled => Effect::Nothing,
Step::Act(MetaAction::Zoom) => Effect::Size(SizeKey::Zoom),
Step::Act(MetaAction::Redraw) => Effect::Redraw,
Step::Act(MetaAction::Resize) => {
self.resizing = true;
Effect::Nothing
}
Step::Act(MetaAction::Help) => {
self.help = true;
Effect::Nothing
}
}
}
pub(crate) fn mouse(&mut self, event: MouseEvent, area: Rect) -> Effect {
match event.kind {
MouseEventKind::Down(MouseButton::Left) if event.row == area.y => {
self.dragging = true;
Effect::Nothing
}
MouseEventKind::Drag(MouseButton::Left) if self.dragging => {
Effect::Size(SizeKey::To(area.bottom().saturating_sub(event.row)))
}
MouseEventKind::Up(MouseButton::Left) => {
self.dragging = false;
Effect::Nothing
}
_ => Effect::Nothing,
}
}
pub(crate) fn overlay(&self) -> Option<String> {
if self.resizing {
return Some("resize: ↑ grow · ↓ shrink · Enter or Esc done".to_string());
}
(self.meta.armed() || self.help).then(|| {
format!(
"{}: {}",
crate::prefix::chord_label(self.prefix),
BINDINGS.describe()
)
})
}
}
#[cfg(test)]
#[path = "panel_controls_tests.rs"]
mod tests;