use egui::{ecolor::*, Margin, Rounding, Stroke};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[allow(missing_docs)]
pub enum TabAddAlign {
Left,
Right,
}
#[derive(Clone, Debug)]
#[allow(missing_docs)]
pub struct Style {
pub dock_area_padding: Option<Margin>,
pub main_surface_border_stroke: Stroke,
pub main_surface_border_rounding: Rounding,
pub buttons: ButtonsStyle,
pub separator: SeparatorStyle,
pub tab_bar: TabBarStyle,
pub tab: TabStyle,
pub overlay: OverlayStyle,
}
#[derive(Clone, Debug)]
pub struct ButtonsStyle {
pub close_tab_color: Color32,
pub close_tab_active_color: Color32,
pub close_tab_bg_fill: Color32,
pub add_tab_align: TabAddAlign,
pub add_tab_color: Color32,
pub add_tab_active_color: Color32,
pub add_tab_bg_fill: Color32,
pub add_tab_border_color: Color32,
}
#[derive(Clone, Debug)]
pub struct SeparatorStyle {
pub width: f32,
pub extra_interact_width: f32,
pub extra: f32,
pub color_idle: Color32,
pub color_hovered: Color32,
pub color_dragged: Color32,
}
#[derive(Clone, Debug)]
pub struct TabBarStyle {
pub bg_fill: Color32,
pub height: f32,
pub show_scroll_bar_on_overflow: bool,
pub rounding: Rounding,
pub hline_color: Color32,
pub fill_tab_bar: bool,
}
#[derive(Clone, Debug)]
pub struct TabStyle {
pub active: TabInteractionStyle,
pub inactive: TabInteractionStyle,
pub focused: TabInteractionStyle,
pub hovered: TabInteractionStyle,
pub tab_body: TabBodyStyle,
pub hline_below_active_tab_name: bool,
pub minimum_width: Option<f32>,
}
#[derive(Clone, Debug)]
pub struct TabInteractionStyle {
pub outline_color: Color32,
pub rounding: Rounding,
pub bg_fill: Color32,
pub text_color: Color32,
}
#[derive(Clone, Debug)]
pub struct TabBodyStyle {
pub inner_margin: Margin,
pub stroke: Stroke,
pub rounding: Rounding,
pub bg_fill: Color32,
}
#[derive(Clone, Debug)]
pub struct OverlayStyle {
pub selection_color: Color32,
pub selection_stroke_width: f32,
pub button_spacing: f32,
pub max_button_size: f32,
pub hovered_leaf_highlight: LeafHighlighting,
pub surface_fade_opacity: f32,
pub button_color: Color32,
pub button_border_stroke: Stroke,
pub overlay_type: OverlayType,
pub feel: OverlayFeel,
}
#[derive(Clone, Debug)]
pub struct OverlayFeel {
pub window_drop_coverage: f32,
pub center_drop_coverage: f32,
pub fade_hold_time: f32,
pub max_preference_time: f32,
pub interact_expansion: f32,
}
#[derive(Clone, Debug, PartialEq)]
pub enum OverlayType {
HighlightedAreas,
Widgets,
}
#[derive(Clone, Debug)]
pub struct LeafHighlighting {
pub color: Color32,
pub rounding: Rounding,
pub stroke: Stroke,
pub expansion: f32,
}
impl Default for Style {
fn default() -> Self {
Self {
dock_area_padding: None,
main_surface_border_stroke: Stroke::new(f32::default(), Color32::BLACK),
main_surface_border_rounding: Rounding::default(),
buttons: ButtonsStyle::default(),
separator: SeparatorStyle::default(),
tab_bar: TabBarStyle::default(),
tab: TabStyle::default(),
overlay: OverlayStyle::default(),
}
}
}
impl Default for ButtonsStyle {
fn default() -> Self {
Self {
close_tab_color: Color32::WHITE,
close_tab_active_color: Color32::WHITE,
close_tab_bg_fill: Color32::GRAY,
add_tab_align: TabAddAlign::Right,
add_tab_color: Color32::WHITE,
add_tab_active_color: Color32::WHITE,
add_tab_bg_fill: Color32::GRAY,
add_tab_border_color: Color32::BLACK,
}
}
}
impl Default for SeparatorStyle {
fn default() -> Self {
Self {
width: 1.0,
extra_interact_width: 2.0,
extra: 175.0,
color_idle: Color32::BLACK,
color_hovered: Color32::GRAY,
color_dragged: Color32::WHITE,
}
}
}
impl Default for TabBarStyle {
fn default() -> Self {
Self {
bg_fill: Color32::WHITE,
height: 24.0,
show_scroll_bar_on_overflow: true,
rounding: Rounding::default(),
hline_color: Color32::BLACK,
fill_tab_bar: false,
}
}
}
impl Default for TabStyle {
fn default() -> Self {
Self {
active: TabInteractionStyle::default(),
inactive: TabInteractionStyle {
text_color: Color32::DARK_GRAY,
..Default::default()
},
focused: TabInteractionStyle {
text_color: Color32::BLACK,
..Default::default()
},
hovered: TabInteractionStyle {
text_color: Color32::BLACK,
..Default::default()
},
tab_body: TabBodyStyle::default(),
hline_below_active_tab_name: false,
minimum_width: None,
}
}
}
impl Default for TabInteractionStyle {
fn default() -> Self {
Self {
bg_fill: Color32::WHITE,
outline_color: Color32::BLACK,
rounding: Rounding::default(),
text_color: Color32::DARK_GRAY,
}
}
}
impl Default for TabBodyStyle {
fn default() -> Self {
Self {
inner_margin: Margin::same(4.0),
stroke: Stroke::default(),
rounding: Rounding::default(),
bg_fill: Color32::WHITE,
}
}
}
impl Default for OverlayStyle {
fn default() -> Self {
Self {
selection_color: Color32::from_rgb(0, 191, 255).linear_multiply(0.5),
selection_stroke_width: 1.0,
button_spacing: 10.0,
max_button_size: 100.0,
surface_fade_opacity: 0.1,
hovered_leaf_highlight: Default::default(),
button_color: Color32::from_gray(140),
button_border_stroke: Stroke::new(1.0, Color32::from_gray(60)),
overlay_type: OverlayType::Widgets,
feel: Default::default(),
}
}
}
impl Default for OverlayFeel {
fn default() -> Self {
Self {
max_preference_time: 0.3,
window_drop_coverage: 0.5,
center_drop_coverage: 0.25,
fade_hold_time: 0.2,
interact_expansion: 20.0,
}
}
}
impl Default for LeafHighlighting {
fn default() -> Self {
Self {
color: Color32::TRANSPARENT,
rounding: Rounding::same(0.0),
stroke: Stroke::NONE,
expansion: 0.0,
}
}
}
impl Style {
pub(crate) const TAB_ADD_BUTTON_SIZE: f32 = 24.0;
pub(crate) const TAB_ADD_PLUS_SIZE: f32 = 12.0;
pub(crate) const TAB_CLOSE_BUTTON_SIZE: f32 = 24.0;
pub(crate) const TAB_CLOSE_X_SIZE: f32 = 9.0;
}
impl Style {
pub fn from_egui(style: &egui::Style) -> Self {
Self {
main_surface_border_stroke: Stroke::NONE,
main_surface_border_rounding: Rounding::ZERO,
buttons: ButtonsStyle::from_egui(style),
separator: SeparatorStyle::from_egui(style),
tab_bar: TabBarStyle::from_egui(style),
tab: TabStyle::from_egui(style),
overlay: OverlayStyle::from_egui(style),
..Self::default()
}
}
}
impl ButtonsStyle {
pub fn from_egui(style: &egui::Style) -> Self {
Self {
close_tab_bg_fill: style.visuals.widgets.hovered.bg_fill,
close_tab_color: style.visuals.text_color(),
close_tab_active_color: style.visuals.strong_text_color(),
add_tab_bg_fill: style.visuals.widgets.hovered.bg_fill,
add_tab_color: style.visuals.text_color(),
add_tab_active_color: style.visuals.strong_text_color(),
add_tab_border_color: style.visuals.widgets.noninteractive.bg_fill,
..ButtonsStyle::default()
}
}
}
impl SeparatorStyle {
pub fn from_egui(style: &egui::Style) -> Self {
Self {
color_idle: style.visuals.widgets.noninteractive.bg_stroke.color, color_hovered: style.visuals.widgets.hovered.fg_stroke.color, color_dragged: style.visuals.widgets.active.fg_stroke.color, ..SeparatorStyle::default()
}
}
}
impl TabBarStyle {
pub fn from_egui(style: &egui::Style) -> Self {
Self {
bg_fill: style.visuals.extreme_bg_color,
rounding: Rounding {
nw: style.visuals.widgets.inactive.rounding.nw + 2.0,
ne: style.visuals.widgets.inactive.rounding.ne + 2.0,
sw: 0.0,
se: 0.0,
},
hline_color: style.visuals.widgets.noninteractive.bg_stroke.color,
..TabBarStyle::default()
}
}
}
impl TabStyle {
pub fn from_egui(style: &egui::Style) -> TabStyle {
Self {
active: TabInteractionStyle::from_egui_active(style),
inactive: TabInteractionStyle::from_egui_inactive(style),
focused: TabInteractionStyle::from_egui_focused(style),
hovered: TabInteractionStyle::from_egui_hovered(style),
tab_body: TabBodyStyle::from_egui(style),
..Default::default()
}
}
}
impl TabInteractionStyle {
pub fn from_egui_active(style: &egui::Style) -> Self {
Self {
outline_color: style.visuals.widgets.noninteractive.bg_stroke.color,
bg_fill: style.visuals.window_fill(),
text_color: style.visuals.text_color(),
rounding: Rounding {
sw: 0.0,
se: 0.0,
..style.visuals.widgets.active.rounding
},
}
}
pub fn from_egui_inactive(style: &egui::Style) -> Self {
Self {
text_color: style.visuals.text_color(),
bg_fill: egui::ecolor::tint_color_towards(
style.visuals.window_fill,
style.visuals.extreme_bg_color,
),
outline_color: egui::ecolor::tint_color_towards(
style.visuals.widgets.noninteractive.bg_stroke.color,
style.visuals.extreme_bg_color,
),
..TabInteractionStyle::from_egui_active(style)
}
}
pub fn from_egui_focused(style: &egui::Style) -> Self {
Self {
text_color: style.visuals.strong_text_color(),
..TabInteractionStyle::from_egui_active(style)
}
}
pub fn from_egui_hovered(style: &egui::Style) -> Self {
Self {
text_color: style.visuals.strong_text_color(),
outline_color: style.visuals.widgets.hovered.bg_stroke.color,
..TabInteractionStyle::from_egui_inactive(style)
}
}
}
impl TabBodyStyle {
pub fn from_egui(style: &egui::Style) -> Self {
Self {
inner_margin: style.spacing.window_margin,
stroke: style.visuals.widgets.noninteractive.bg_stroke,
rounding: style.visuals.widgets.active.rounding,
bg_fill: style.visuals.window_fill(),
}
}
}
impl OverlayStyle {
pub fn from_egui(style: &egui::Style) -> Self {
Self {
selection_color: style.visuals.selection.bg_fill.linear_multiply(0.5),
button_spacing: style.spacing.icon_spacing,
button_color: style.visuals.widgets.noninteractive.fg_stroke.color,
button_border_stroke: style.visuals.widgets.noninteractive.bg_stroke,
..Default::default()
}
}
}