From 5082bf9fdf697563a4f4e53212bcf9a74bf5f07a Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 20 Jun 2024 22:18:08 +0300 Subject: [PATCH] add focusing to chain; nested focus works for the most part --- src/device/chain.rs | 74 ++++++++++++++++++++++++++++++++++++++++----- src/draw.rs | 16 ++++++++++ src/layout.rs | 24 +++++++-------- src/prelude.rs | 5 ++- 4 files changed, 98 insertions(+), 21 deletions(-) diff --git a/src/device/chain.rs b/src/device/chain.rs index 295157de..94eae8b7 100644 --- a/src/device/chain.rs +++ b/src/device/chain.rs @@ -2,16 +2,18 @@ use crate::prelude::*; pub struct Chain { name: String, - devices: Vec>, - focused: usize, + focused: bool, + focus: usize, + items: Vec>, } impl Chain { - pub fn new (name: &str, devices: Vec>) -> Result, Box> { + pub fn new (name: &str, items: Vec>) -> Result, Box> { Ok(DynamicDevice::new(render, handle, process, Self { name: name.into(), - devices, - focused: 0 + focused: false, + focus: 0, + items, })) } } @@ -30,13 +32,20 @@ pub fn render (state: &Chain, buf: &mut Buffer, area: Rect) buf.set_string(area.x + area.width - 1, y, "│", Style::default().black()); buf.set_string(area.x + 2, y, "Input...", Style::default().dim()); let mut x = 0u16; - for device in state.devices.iter() { + for (i, device) in state.items.iter().enumerate() { let result = device.render(buf, Rect { x: area.x, y, width: area.width, height: 21//area.height.saturating_sub(y) })?; + if i == state.focus { + if state.focused { + draw_box_styled(buf, result, Some(Style::default().green().not_dim())) + } else { + draw_box_styled_dotted(buf, result, Some(Style::default().green().dim())) + }; + }; //let result = Rect { x: 0, y: 0, width: result.width, height: 21 }; x = x.max(result.width); y = y + result.height; @@ -57,6 +66,55 @@ pub fn render (state: &Chain, buf: &mut Buffer, area: Rect) })) } -pub fn handle (_: &mut Chain, _: &AppEvent) -> Usually { - Ok(false) +impl Focus for Chain { + fn focused (&self) -> Option<&Box> { + match self.focused { + true => self.items.get(self.focus), + false => None + } + } + fn focused_mut (&mut self) -> Option<&mut Box> { + match self.focused { + true => self.items.get_mut(self.focus), + false => None + } + } + fn handle_focus (&mut self, event: &FocusEvent) -> Usually { + match event { + FocusEvent::Backward => { + if self.focus == 0 { + self.focus = self.items.len(); + } + self.focus = self.focus - 1; + }, + FocusEvent::Forward => { + self.focus = self.focus + 1; + if self.focus >= self.items.len() { + self.focus = 0; + } + }, + FocusEvent::Inward => { + self.focused = true; + self.items[self.focus].handle(&AppEvent::Focus)?; + }, + FocusEvent::Outward => { + self.focused = false; + self.items[self.focus].handle(&AppEvent::Blur)?; + }, + }; + Ok(true) + } +} + +pub fn handle (state: &mut Chain, event: &AppEvent) -> Usually { + handle_focus(state, event, keymap!(Chain { + [Up, NONE, "focus_up", "focus row above", + |s: &mut Chain|s.handle_focus(&FocusEvent::Backward)], + [Down, NONE, "focus_down", "focus row below", + |s: &mut Chain|s.handle_focus(&FocusEvent::Forward)], + [Enter, NONE, "focus_down", "focus row below", + |s: &mut Chain|s.handle_focus(&FocusEvent::Inward)], + [Esc, NONE, "focus_down", "focus row below", + |s: &mut Chain|s.handle_focus(&FocusEvent::Outward)] + })) } diff --git a/src/draw.rs b/src/draw.rs index 5d878516..c9d8594f 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -55,6 +55,22 @@ pub fn draw_box (buffer: &mut Buffer, area: Rect) -> Rect { } pub fn draw_box_styled (buffer: &mut Buffer, area: Rect, style: Option