diff --git a/src/components.rs b/src/components.rs index d06a00e..b5729c9 100644 --- a/src/components.rs +++ b/src/components.rs @@ -21,45 +21,45 @@ pub fn div() -> Component { if let Some(v) = this.binds.get(&k.kind) { match v.as_str() { "up" => { - this.active_child = closest_component( + this.set_child(closest_component( &this.children, - this.active_child, + this.child, crate::utils::Direction::Up, - ); + )); } "down" => { - this.active_child = closest_component( + this.set_child(closest_component( &this.children, - this.active_child, + this.child, crate::utils::Direction::Down, - ); + )); } "left" => { - this.active_child = closest_component( + this.set_child(closest_component( &this.children, - this.active_child, + this.child, crate::utils::Direction::Left, - ); + )); } "right" => { - this.active_child = closest_component( + this.set_child(closest_component( &this.children, - this.active_child, + this.child, crate::utils::Direction::Right, - ); + )); } _ => { - if let Some(child) = this.get_active_child() { + if let Some(child) = this.get_child() { return (child.update)(child, k); } } } } else { - if let Some(child) = this.get_active_child() { + if let Some(child) = this.get_child() { return (child.update)(child, k); } } @@ -67,16 +67,17 @@ pub fn div() -> Component { UpdateResponse::None } - fn render(s: &mut Component) -> String { - let mut frame: Vec = create_frame!(s.width, s.height); - for c in &mut s.children { + fn render(this: &mut Component) -> String { + let mut frame: Vec = create_frame!(this.width, this.height); + for (i, c) in &mut this.children.iter_mut().enumerate() { + c.style.is_active = this.style.is_active && i == this.child; render_to_frame(&mut frame, c); } frame.join("\n") } fn tick(this: &mut Component, i: usize) { - if let Some(child) = this.get_active_child() { + if let Some(child) = this.get_child() { return (child.tick)(child, i); } } @@ -106,7 +107,8 @@ pub fn text() -> Component { pub fn button() -> Component { let mut component = Component::new(); - component.style.hover_fg = crate::style::Color::Blue; + component.style.clicked_fg = crate::style::Color::Red; + component.style.hover_fg = crate::style::Color::Green; fn update(this: &mut Component, k: key::Key) -> UpdateResponse { if k.kind == KeyKind::Enter { @@ -131,7 +133,10 @@ pub fn button() -> Component { } fn render(this: &mut Component) -> String { - this.style.clone().write(&this.expr) + if this.clicked { + return this.style.write_clicked(&this.expr); + } + this.style.write(&this.expr) } component.update = update; diff --git a/src/lib.rs b/src/lib.rs index 02069f1..e303a85 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ pub struct Component { pub height: usize, pub expr: String, pub children: Vec, - pub active_child: usize, + pub child: usize, pub clicked: bool, pub toggle: bool, pub binds: HashMap, @@ -40,7 +40,7 @@ impl Component { height: 0, expr: String::new(), children: Vec::new(), - active_child: 0, + child: 0, clicked: false, toggle: false, binds: HashMap::new(), @@ -48,26 +48,19 @@ impl Component { } } - pub fn get_active_child(&mut self) -> Option<&mut Component> { - self.children.get_mut(self.active_child) + pub fn get_child(&mut self) -> Option<&mut Component> { + self.children.get_mut(self.child) } - pub fn set_active_child(&mut self, idx: usize) { - let last_active = self.active_child; - if let Some(last_child) = self.children.get_mut(last_active) { - last_child.style.is_active = false; - } + pub fn set_child(&mut self, idx: usize) { if let Some(child) = self.children.get_mut(idx) { - self.active_child = idx; + self.child = idx; if child.width == 0 { child.width = self.width; } if child.height == 0 { child.height = self.height; } - child.style.is_active = self.style.is_active; - } else if let Some(last_child) = self.children.get_mut(last_active) { - last_child.style.is_active = true; } } } diff --git a/src/style.rs b/src/style.rs index e5103f9..bb5a588 100644 --- a/src/style.rs +++ b/src/style.rs @@ -10,6 +10,11 @@ pub struct Style { pub hover_outline: Color, pub hover_font: Font, + pub clicked_bg: Color, + pub clicked_fg: Color, + pub clicked_outline: Color, + pub clicked_font: Font, + pub is_active: bool, } @@ -26,36 +31,60 @@ impl Style { hover_outline: Color::None, hover_font: Font::None, + clicked_bg: Color::None, + clicked_fg: Color::None, + clicked_outline: Color::None, + clicked_font: Font::None, + is_active: false, } } - pub fn get(self) -> String { + pub fn get(&self) -> String { if self.is_active { - String::from( - self.fg.prioritize(self.hover_fg).ansi() - + &self.bg.prioritize(self.hover_bg).ansi_bg() - + &self.font.prioritize(self.hover_font).ansi(), + format!( + "{}{}{}", + self.fg.prioritize(&self.hover_fg).ansi(), + self.bg.prioritize(&self.hover_bg).ansi_bg(), + self.font.prioritize(&self.hover_font).ansi() ) } else { - String::from(self.fg.ansi() + &self.bg.ansi_bg() + &self.font.ansi()) + format!( + "{}{}{}", + self.fg.ansi(), + self.bg.ansi_bg(), + self.font.ansi() + ) } } - pub fn get_outline(self) -> String { + pub fn get_outline(&self) -> String { if self.is_active { - self.outline.prioritize(self.hover_outline).ansi() + self.outline.prioritize(&self.hover_outline).ansi() } else { self.outline.ansi() } } - pub fn write(self, s: &str) -> String { - format!("{}{}", self.get(), s) + pub fn get_clicked(&self) -> String { + format!( + "{}{}{}", + self.fg.prioritize(&self.clicked_fg).ansi(), + self.bg.prioritize(&self.clicked_bg).ansi_bg(), + self.font.prioritize(&self.clicked_font).ansi() + ) } - pub fn write_outline(self, s: &str) -> String { - format!("{}{}", self.get_outline(), s) + pub fn write(&self, s: &str) -> String { + format!("{}{}\x1b[0m", self.get(), s) + } + + pub fn write_outline(&self, s: &str) -> String { + format!("{}{}\x1b[0m", self.get_outline(), s) + } + + pub fn write_clicked(&self, s: &str) -> String { + format!("{}{}\x1b[0m", self.get_clicked(), s) } } @@ -71,7 +100,7 @@ pub enum Font { } impl Font { - pub fn ansi(self) -> String { + pub fn ansi(&self) -> String { String::from(match self { Font::None => "", Font::Bold => "\x1b[1m", @@ -89,8 +118,8 @@ impl Font { }) } - pub fn prioritize(self, secondary: Font) -> Font { - if secondary == Font::None { + pub fn prioritize<'a>(&'a self, secondary: &'a Font) -> &Font { + if secondary == &Font::None { self } else { secondary @@ -113,7 +142,7 @@ pub enum Color { } impl Color { - pub fn ansi(self) -> String { + pub fn ansi(&self) -> String { String::from(match self { Color::None => "", Self::Rgb(r, g, b) => { @@ -130,7 +159,7 @@ impl Color { }) } - pub fn ansi_bg(self) -> String { + pub fn ansi_bg(&self) -> String { String::from(match self { Color::None => "", Self::Rgb(r, g, b) => { @@ -147,8 +176,8 @@ impl Color { }) } - pub fn prioritize(self, secondary: Color) -> Color { - if secondary == Color::None { + pub fn prioritize<'a>(&'a self, secondary: &'a Color) -> &Color { + if secondary == &Color::None { self } else { secondary diff --git a/src/utils.rs b/src/utils.rs index 4b33995..302a0b9 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -46,11 +46,15 @@ pub fn compress_string(input: &str, re: &Regex) -> (String, HashMap String { let (frame_, fm) = compress_string(frame_, &ANSI); - let (line_, lm) = compress_string(line_, &ANSI); + let (mut line_, lm) = compress_string(line_, &ANSI); + + if let Some(_) = lm.get(&line_.len()) { + line_.push('\n'); + } let mut res = String::new(); let frame: Vec = frame_.chars().collect(); - let line: Vec = line_.chars().collect(); + let line: Vec = (line_).chars().collect(); let flen = frame.len(); let llen = line.len(); @@ -60,7 +64,9 @@ fn merge_line(frame_: &str, line_: &str, x: usize) -> String { if let Some(v) = lm.get(&(i - x)) { res.push_str(v); } - res.push(line[i - x]); + if line[i - x] != '\n' { + res.push(line[i - x]); + } } else { if let Some(v) = fm.get(&i) { res.push_str(v);