add focusing to chain; nested focus works for the most part

This commit is contained in:
🪞👃🪞 2024-06-20 22:18:08 +03:00
parent 7b568c55b8
commit 5082bf9fdf
4 changed files with 98 additions and 21 deletions

View file

@ -2,16 +2,18 @@ use crate::prelude::*;
pub struct Chain {
name: String,
devices: Vec<Box<dyn Device>>,
focused: usize,
focused: bool,
focus: usize,
items: Vec<Box<dyn Device>>,
}
impl Chain {
pub fn new (name: &str, devices: Vec<Box<dyn Device>>) -> Result<DynamicDevice<Self>, Box<dyn Error>> {
pub fn new (name: &str, items: Vec<Box<dyn Device>>) -> Result<DynamicDevice<Self>, Box<dyn Error>> {
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<bool> {
Ok(false)
impl Focus for Chain {
fn focused (&self) -> Option<&Box<dyn Device>> {
match self.focused {
true => self.items.get(self.focus),
false => None
}
}
fn focused_mut (&mut self) -> Option<&mut Box<dyn Device>> {
match self.focused {
true => self.items.get_mut(self.focus),
false => None
}
}
fn handle_focus (&mut self, event: &FocusEvent) -> Usually<bool> {
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<bool> {
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)]
}))
}

View file

@ -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<Style>) -> Rect {
if area.width < 1 || area.height < 1 {
return area
}
let style = style.unwrap_or(Style::default());
let top = format!("{}", "".repeat((area.width - 2).into()));
let bottom = format!("{}", "".repeat((area.width - 2).into()));
buffer.set_string(area.x, area.y, top, style);
for y in (area.y + 1)..(area.y + area.height - 1) {
buffer.set_string(area.x, y, format!(""), style);
buffer.set_string(area.x + area.width - 1, y, format!(""), style);
}
buffer.set_string(area.x, area.y + area.height - 1, bottom, style);
area
}
pub fn draw_box_styled_dotted (buffer: &mut Buffer, area: Rect, style: Option<Style>) -> Rect {
if area.width < 1 || area.height < 1 {
return area
}

View file

@ -6,14 +6,14 @@ pub trait Focus {
fn handle_focus (&mut self, event: &FocusEvent) -> Usually<bool>;
}
enum FocusEvent {
pub enum FocusEvent {
Forward,
Backward,
Inward,
Outward,
}
fn handle_focus <T: Device + Focus> (
pub fn handle_focus <T: Focus> (
state: &mut T,
event: &AppEvent,
keymap: &[KeyBinding<T>]
@ -156,12 +156,12 @@ impl Device for Rows {
height: area.height - h
})?;
if i == self.focus {
draw_box_styled(buf, result, Some(if true || self.focused {
Style::default().green()
if self.focused {
draw_box_styled(buf, result, Some(Style::default().green().not_dim()))
} else {
Style::default()
}));
}
draw_box_styled_dotted(buf, result, Some(Style::default().green().dim()))
};
};
w = w.max(result.width);
h = h + result.height;
}
@ -194,12 +194,12 @@ impl Device for Columns {
height: area.height
})?;
if i == self.focus {
draw_box_styled(buf, result, Some(if true || self.focused {
Style::default().green()
if self.focused {
draw_box_styled(buf, result, Some(Style::default().green().not_dim()))
} else {
Style::default()
}));
}
draw_box_styled_dotted(buf, result, Some(Style::default().green().dim()))
};
};
w = w + result.width;
h = h.max(result.height);
}

View file

@ -12,7 +12,10 @@ pub use crate::time::*;
pub use crate::layout::{
Rows,
Columns
Columns,
Focus,
FocusEvent,
handle_focus
};
pub use std::error::Error;