use crate::compositor::engine::Compositor;
use crate::compositor::plane::{Color, Styles};
use crate::input::event::{Event, MouseButton, MouseEvent, MouseEventKind};
use crate::visuals::slicer::NineSlice;
use crate::widgets::component::{Bounds, Component};
pub struct RichPanel {
pub title: String,
pub background: Option<NineSlice>,
pub border_color: Color,
}
impl RichPanel {
pub fn new(title: &str) -> Self {
Self {
title: title.to_string(),
background: None,
border_color: Color::Ansi(4), }
}
pub fn with_background(mut self, slice: NineSlice) -> Self {
self.background = Some(slice);
self
}
pub fn with_color(mut self, color: Color) -> Self {
self.border_color = color;
self
}
}
impl Component for RichPanel {
fn render(&self, compositor: &mut Compositor, bounds: Bounds) {
if let Some(ref slice) = self.background {
slice.render(
compositor,
bounds.x,
bounds.y,
bounds.w,
bounds.h,
0,
compositor.graphics_enabled,
);
}
if !self.title.is_empty() {
let title_text = format!(" {} ", self.title);
compositor.draw_text(
&title_text,
bounds.x + 2,
bounds.y,
self.border_color,
Color::Reset,
Styles::BOLD,
);
}
}
}
pub struct RichButton {
pub label: String,
pub background: NineSlice,
pub focused: bool,
pub hovered: bool,
pub on_click: Option<Box<dyn Fn() + Send + Sync>>,
}
impl RichButton {
pub fn new(label: &str, background: NineSlice) -> Self {
Self {
label: label.to_string(),
background,
focused: false,
hovered: false,
on_click: None,
}
}
pub fn set_focused(&mut self, focused: bool) {
self.focused = focused;
}
pub fn on_click<F: Fn() + Send + Sync + 'static>(mut self, f: F) -> Self {
self.on_click = Some(Box::new(f));
self
}
}
impl Component for RichButton {
fn render(&self, compositor: &mut Compositor, bounds: Bounds) {
let z = if self.focused {
3
} else if self.hovered {
2
} else {
1
};
self.background.render(
compositor,
bounds.x,
bounds.y,
bounds.w,
bounds.h,
z,
compositor.graphics_enabled,
);
let lx = bounds.x + (bounds.w.saturating_sub(self.label.len() as u16)) / 2;
let ly = bounds.y + bounds.h / 2;
let fg = if self.hovered {
Color::Rgb(255, 255, 0) } else {
Color::Rgb(255, 255, 255) };
compositor.draw_text(&self.label, lx, ly, fg, Color::Reset, Styles::BOLD);
}
fn on_event(&mut self, event: &Event, bounds: Bounds) -> bool {
match event {
Event::Mouse(MouseEvent {
kind, column, row, ..
}) => {
let inside = bounds.contains(*column, *row);
match kind {
MouseEventKind::Moved => {
self.hovered = inside;
inside }
MouseEventKind::Down(MouseButton::Left) if inside => {
if let Some(ref cb) = self.on_click {
cb();
}
true }
_ => false,
}
}
_ => false,
}
}
}