mod helpers;
mod render;
mod state;
pub mod types;
pub use types::{CollapseMode, FlattenedItem, SidebarItem, SidebarSection};
use crate::style::Color;
use crate::widget::theme::PLACEHOLDER_FG;
use crate::widget::traits::{WidgetProps, DISABLED_FG};
use crate::{impl_props_builders, impl_styled_view};
#[derive(Clone, Debug)]
pub struct Sidebar {
pub(crate) sections: Vec<SidebarSection>,
pub(crate) selected: Option<String>,
pub(crate) hovered: usize,
pub(crate) collapse_mode: CollapseMode,
pub(crate) collapse_threshold: u16,
pub(crate) expanded_width: u16,
pub(crate) collapsed_width: u16,
pub(crate) header: Option<String>,
pub(crate) footer: Option<String>,
pub(crate) scroll: usize,
pub(crate) fg: Option<Color>,
pub(crate) bg: Option<Color>,
pub(crate) selected_fg: Option<Color>,
pub(crate) selected_bg: Option<Color>,
pub(crate) hover_fg: Option<Color>,
pub(crate) hover_bg: Option<Color>,
pub(crate) disabled_fg: Option<Color>,
pub(crate) section_fg: Option<Color>,
pub(crate) badge_fg: Option<Color>,
pub(crate) badge_bg: Option<Color>,
pub(crate) border_fg: Option<Color>,
pub(crate) min_width: u16,
pub(crate) min_height: u16,
pub(crate) max_width: u16,
pub(crate) max_height: u16,
pub props: WidgetProps,
}
impl Sidebar {
pub fn new() -> Self {
Self {
sections: Vec::new(),
selected: None,
hovered: 0,
collapse_mode: CollapseMode::Expanded,
collapse_threshold: 20,
expanded_width: 24,
collapsed_width: 4,
header: None,
footer: None,
scroll: 0,
fg: None,
bg: Some(Color::rgb(30, 30, 40)),
selected_fg: Some(Color::WHITE),
selected_bg: Some(Color::BLUE),
hover_fg: Some(Color::WHITE),
hover_bg: Some(Color::rgb(50, 50, 70)),
disabled_fg: Some(DISABLED_FG),
section_fg: Some(PLACEHOLDER_FG),
badge_fg: Some(Color::WHITE),
badge_bg: Some(Color::RED),
border_fg: Some(Color::rgb(60, 60, 80)),
min_width: 0,
min_height: 0,
max_width: 0,
max_height: 0,
props: WidgetProps::new(),
}
}
pub fn section(mut self, section: SidebarSection) -> Self {
self.sections.push(section);
self
}
pub fn sections(mut self, sections: Vec<SidebarSection>) -> Self {
self.sections = sections;
self
}
pub fn items(mut self, items: Vec<SidebarItem>) -> Self {
self.sections.push(SidebarSection::new(items));
self
}
pub fn selected(mut self, id: impl Into<String>) -> Self {
self.selected = Some(id.into());
self
}
pub fn collapse_mode(mut self, mode: CollapseMode) -> Self {
self.collapse_mode = mode;
self
}
pub fn collapse_threshold(mut self, width: u16) -> Self {
self.collapse_threshold = width;
self
}
pub fn expanded_width(mut self, width: u16) -> Self {
self.expanded_width = width;
self
}
pub fn collapsed_width(mut self, width: u16) -> Self {
self.collapsed_width = width;
self
}
pub fn header(mut self, header: impl Into<String>) -> Self {
self.header = Some(header.into());
self
}
pub fn footer(mut self, footer: impl Into<String>) -> Self {
self.footer = Some(footer.into());
self
}
pub fn fg(mut self, color: Color) -> Self {
self.fg = Some(color);
self
}
pub fn bg(mut self, color: Color) -> Self {
self.bg = Some(color);
self
}
pub fn selected_style(mut self, fg: Color, bg: Color) -> Self {
self.selected_fg = Some(fg);
self.selected_bg = Some(bg);
self
}
pub fn hover_style(mut self, fg: Color, bg: Color) -> Self {
self.hover_fg = Some(fg);
self.hover_bg = Some(bg);
self
}
pub fn disabled_color(mut self, color: Color) -> Self {
self.disabled_fg = Some(color);
self
}
pub fn section_color(mut self, color: Color) -> Self {
self.section_fg = Some(color);
self
}
pub fn badge_style(mut self, fg: Color, bg: Color) -> Self {
self.badge_fg = Some(fg);
self.badge_bg = Some(bg);
self
}
pub fn border_color(mut self, color: Color) -> Self {
self.border_fg = Some(color);
self
}
pub fn toggle_collapse(&mut self) {
self.collapse_mode = match self.collapse_mode {
CollapseMode::Expanded => CollapseMode::Collapsed,
CollapseMode::Collapsed => CollapseMode::Expanded,
CollapseMode::Auto => CollapseMode::Collapsed,
};
}
pub fn min_width(mut self, width: u16) -> Self {
self.min_width = width;
self
}
pub fn min_height(mut self, height: u16) -> Self {
self.min_height = height;
self
}
pub fn max_width(mut self, width: u16) -> Self {
self.max_width = width;
self
}
pub fn max_height(mut self, height: u16) -> Self {
self.max_height = height;
self
}
pub fn min_size(self, width: u16, height: u16) -> Self {
self.min_width(width).min_height(height)
}
pub fn max_size(self, width: u16, height: u16) -> Self {
self.max_width(width).max_height(height)
}
pub fn constrain(self, min_w: u16, min_h: u16, max_w: u16, max_h: u16) -> Self {
self.min_width(min_w)
.min_height(min_h)
.max_width(max_w)
.max_height(max_h)
}
}
impl Default for Sidebar {
fn default() -> Self {
Self::new()
}
}
impl crate::widget::traits::View for Sidebar {
fn render(&self, ctx: &mut crate::widget::traits::RenderContext) {
self.render_sidebar(ctx);
}
crate::impl_view_meta!("Sidebar");
}
impl_styled_view!(Sidebar);
impl_props_builders!(Sidebar);
pub use helpers::{sidebar, sidebar_item, sidebar_section, sidebar_section_titled};
use state::SidebarState;
impl Sidebar {
pub fn selected_id(&self) -> Option<&str> {
SidebarState::selected_id(self)
}
pub fn hovered_index(&self) -> usize {
SidebarState::hovered_index(self)
}
pub fn is_collapsed(&self) -> bool {
SidebarState::is_collapsed(self)
}
pub fn current_width(&self) -> u16 {
SidebarState::current_width(self, self.expanded_width, self.collapsed_width)
}
pub fn visible_items(&self) -> Vec<FlattenedItem> {
SidebarState::visible_items(self)
}
pub fn item_count(&self) -> usize {
SidebarState::item_count(self)
}
pub fn hover_down(&mut self) {
SidebarState::hover_down(self);
}
pub fn hover_up(&mut self) {
SidebarState::hover_up(self);
}
pub fn select_hovered(&mut self) {
SidebarState::select_hovered(self);
}
pub fn toggle_hovered(&mut self) {
SidebarState::toggle_hovered(self);
}
pub fn toggle_item(&mut self, id: &str) {
SidebarState::toggle_item(self, id);
}
pub fn expand_all(&mut self) {
SidebarState::expand_all(self);
}
pub fn collapse_all(&mut self) {
SidebarState::collapse_all(self);
}
}