use egui::{Color32, CornerRadius, Frame, InnerResponse, Margin, Ui, Visuals};
use crate::tokens::DESIGN_TOKENS;
fn panel_corner_radius() -> u8 {
DESIGN_TOKENS.rounding.sm as u8
}
fn panel_gap() -> i8 {
DESIGN_TOKENS.spacing.panel_gap as i8
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PanelPosition {
Left,
RightWidgetBar,
RightContent,
Top,
Bottom,
Chart,
}
pub struct StyledPanelFrame {
position: PanelPosition,
gap_color: Color32,
panel_bg: Color32,
}
impl StyledPanelFrame {
pub fn left(visuals: &Visuals) -> Self {
Self {
position: PanelPosition::Left,
gap_color: visuals.faint_bg_color,
panel_bg: visuals.panel_fill,
}
}
pub fn right_widget_bar(visuals: &Visuals) -> Self {
Self {
position: PanelPosition::RightWidgetBar,
gap_color: visuals.faint_bg_color,
panel_bg: visuals.panel_fill,
}
}
pub fn right_content(visuals: &Visuals) -> Self {
Self {
position: PanelPosition::RightContent,
gap_color: visuals.faint_bg_color,
panel_bg: visuals.panel_fill,
}
}
pub fn top(visuals: &Visuals) -> Self {
Self {
position: PanelPosition::Top,
gap_color: visuals.faint_bg_color,
panel_bg: visuals.panel_fill,
}
}
pub fn bottom(visuals: &Visuals) -> Self {
Self {
position: PanelPosition::Bottom,
gap_color: visuals.faint_bg_color,
panel_bg: visuals.panel_fill,
}
}
pub fn chart(visuals: &Visuals, chart_bg: Color32) -> Self {
Self {
position: PanelPosition::Chart,
gap_color: visuals.faint_bg_color,
panel_bg: chart_bg,
}
}
#[must_use]
pub fn gap_color(mut self, color: Color32) -> Self {
self.gap_color = color;
self
}
#[must_use]
pub fn panel_bg(mut self, color: Color32) -> Self {
self.panel_bg = color;
self
}
pub fn outer_frame(&self) -> Frame {
let margin = match self.position {
PanelPosition::Left => Margin {
left: 0,
right: panel_gap(),
top: 0, bottom: 0,
},
PanelPosition::RightWidgetBar => Margin {
left: panel_gap(),
right: 0,
top: 0, bottom: 0,
},
PanelPosition::RightContent => Margin {
left: panel_gap(),
right: 0,
top: 0, bottom: 0,
},
PanelPosition::Top => Margin {
left: 0,
right: 0,
top: 0,
bottom: panel_gap(),
},
PanelPosition::Bottom => Margin {
left: 0,
right: 0,
top: panel_gap(),
bottom: 0,
},
PanelPosition::Chart => Margin::ZERO,
};
Frame::new()
.fill(self.gap_color)
.corner_radius(CornerRadius::ZERO)
.inner_margin(margin)
}
pub fn inner_frame(&self) -> Frame {
let rounding = match self.position {
PanelPosition::Left => CornerRadius {
nw: 0,
ne: panel_corner_radius(),
sw: 0,
se: 0,
},
PanelPosition::RightWidgetBar | PanelPosition::RightContent => CornerRadius {
nw: panel_corner_radius(),
ne: 0,
sw: 0,
se: 0,
},
PanelPosition::Top | PanelPosition::Bottom => CornerRadius::ZERO,
PanelPosition::Chart => CornerRadius {
nw: panel_corner_radius(),
ne: panel_corner_radius(),
sw: 0,
se: 0,
},
};
Frame::new().fill(self.panel_bg).corner_radius(rounding)
}
pub fn show<R>(self, ui: &mut Ui, content: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
self.outer_frame()
.show(ui, |ui| self.inner_frame().show(ui, content).inner)
}
}
pub struct Card {
rounding: f32,
padding: f32,
}
impl Default for Card {
fn default() -> Self {
Self::new()
}
}
impl Card {
pub fn new() -> Self {
Self {
rounding: DESIGN_TOKENS.rounding.sm,
padding: DESIGN_TOKENS.spacing.sm,
}
}
#[must_use]
pub fn rounding(mut self, r: f32) -> Self {
self.rounding = r;
self
}
#[must_use]
pub fn padding(mut self, p: f32) -> Self {
self.padding = p;
self
}
pub fn show<R>(self, ui: &mut Ui, content: impl FnOnce(&mut Ui) -> R) -> InnerResponse<R> {
Frame::new()
.fill(ui.style().visuals.faint_bg_color)
.corner_radius(self.rounding)
.inner_margin(self.padding)
.show(ui, content)
}
}
pub fn modern_panel_frame(bg: Color32) -> Frame {
Frame::new()
.fill(bg)
.corner_radius(CornerRadius::ZERO)
.inner_margin(egui::Margin::ZERO)
.outer_margin(egui::Margin::ZERO)
.stroke(egui::Stroke::NONE)
}