use egui::{ecolor::*, CornerRadius, Margin, 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)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[allow(missing_docs)]
pub struct Style {
pub dock_area_padding: Option<Margin>,
pub main_surface_border_stroke: Stroke,
pub main_surface_border_rounding: CornerRadius,
pub buttons: ButtonsStyle,
pub separator: SeparatorStyle,
pub tab_bar: TabBarStyle,
pub tab: TabStyle,
pub overlay: OverlayStyle,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
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,
pub close_all_tabs_color: Color32,
pub close_all_tabs_active_color: Color32,
pub close_all_tabs_bg_fill: Color32,
pub close_all_tabs_border_color: Color32,
pub close_all_tabs_disabled_color: Color32,
pub collapse_tabs_color: Color32,
pub collapse_tabs_active_color: Color32,
pub collapse_tabs_bg_fill: Color32,
pub collapse_tabs_border_color: Color32,
pub minimize_window_color: Color32,
pub minimize_window_active_color: Color32,
pub minimize_window_bg_fill: Color32,
pub minimize_window_border_color: Color32,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
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)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TabBarStyle {
pub bg_fill: Color32,
pub height: f32,
pub inner_margin: Margin,
pub show_scroll_bar_on_overflow: bool,
pub corner_radius: CornerRadius,
pub hline_color: Color32,
pub fill_tab_bar: bool,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TabStyle {
pub active: TabInteractionStyle,
pub inactive: TabInteractionStyle,
pub focused: TabInteractionStyle,
pub hovered: TabInteractionStyle,
pub inactive_with_kb_focus: TabInteractionStyle,
pub active_with_kb_focus: TabInteractionStyle,
pub focused_with_kb_focus: TabInteractionStyle,
pub tab_body: TabBodyStyle,
pub hline_below_active_tab_name: bool,
pub spacing: f32,
pub minimum_width: Option<f32>,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TabInteractionStyle {
pub outline_color: Color32,
pub corner_radius: CornerRadius,
pub bg_fill: Color32,
pub text_color: Color32,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct TabBodyStyle {
pub inner_margin: Margin,
pub stroke: Stroke,
pub corner_radius: CornerRadius,
pub bg_fill: Color32,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
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)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
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(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub enum OverlayType {
HighlightedAreas,
Widgets,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct LeafHighlighting {
pub color: Color32,
pub corner_radius: CornerRadius,
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: CornerRadius::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,
close_all_tabs_color: Color32::WHITE,
close_all_tabs_active_color: Color32::WHITE,
close_all_tabs_bg_fill: Color32::GRAY,
close_all_tabs_border_color: Color32::BLACK,
close_all_tabs_disabled_color: Color32::LIGHT_GRAY,
collapse_tabs_color: Color32::WHITE,
collapse_tabs_active_color: Color32::WHITE,
collapse_tabs_bg_fill: Color32::GRAY,
collapse_tabs_border_color: Color32::BLACK,
minimize_window_color: Color32::WHITE,
minimize_window_active_color: Color32::WHITE,
minimize_window_bg_fill: Color32::GRAY,
minimize_window_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,
inner_margin: Margin::ZERO,
show_scroll_bar_on_overflow: true,
corner_radius: CornerRadius::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()
},
active_with_kb_focus: TabInteractionStyle::default(),
inactive_with_kb_focus: TabInteractionStyle {
text_color: Color32::DARK_GRAY,
..Default::default()
},
focused_with_kb_focus: TabInteractionStyle {
text_color: Color32::BLACK,
..Default::default()
},
spacing: 0.0,
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,
corner_radius: CornerRadius::default(),
text_color: Color32::DARK_GRAY,
}
}
}
impl Default for TabBodyStyle {
fn default() -> Self {
Self {
inner_margin: Margin::same(4),
stroke: Stroke::default(),
corner_radius: CornerRadius::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,
corner_radius: CornerRadius::same(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;
pub(crate) const TAB_CLOSE_ALL_BUTTON_SIZE: f32 = 24.0;
pub(crate) const TAB_CLOSE_ALL_SIZE: f32 = 10.0;
pub(crate) const TAB_COLLAPSE_BUTTON_SIZE: f32 = 24.0;
pub(crate) const TAB_COLLAPSE_ARROW_SIZE: f32 = 10.0;
pub(crate) const TAB_EXPAND_BUTTON_SIZE: f32 = 24.0;
pub(crate) const TAB_EXPAND_ARROW_SIZE: f32 = 10.0;
}
impl Style {
pub fn from_egui(style: &egui::Style) -> Self {
Self {
main_surface_border_stroke: Stroke::NONE,
main_surface_border_rounding: CornerRadius::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,
close_all_tabs_bg_fill: style.visuals.widgets.hovered.bg_fill,
close_all_tabs_color: style.visuals.text_color(),
close_all_tabs_active_color: style.visuals.strong_text_color(),
close_all_tabs_border_color: style.visuals.widgets.noninteractive.bg_fill,
close_all_tabs_disabled_color: style.visuals.widgets.inactive.bg_fill,
collapse_tabs_bg_fill: style.visuals.widgets.hovered.bg_fill,
collapse_tabs_color: style.visuals.text_color(),
collapse_tabs_active_color: style.visuals.strong_text_color(),
collapse_tabs_border_color: style.visuals.widgets.noninteractive.bg_fill,
minimize_window_bg_fill: style.visuals.widgets.hovered.bg_fill,
minimize_window_color: style.visuals.text_color(),
minimize_window_active_color: style.visuals.strong_text_color(),
minimize_window_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,
corner_radius: CornerRadius {
nw: style.visuals.widgets.inactive.corner_radius.nw + 2,
ne: style.visuals.widgets.inactive.corner_radius.ne + 2,
sw: 0,
se: 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),
active_with_kb_focus: TabInteractionStyle::from_egui_active_with_kb_focus(style),
inactive_with_kb_focus: TabInteractionStyle::from_egui_inactive_with_kb_focus(style),
focused_with_kb_focus: TabInteractionStyle::from_egui_focused_with_kb_focus(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(),
corner_radius: CornerRadius {
sw: 0,
se: 0,
..style.visuals.widgets.active.corner_radius
},
}
}
pub fn from_egui_inactive(style: &egui::Style) -> Self {
Self {
text_color: style.visuals.text_color(),
bg_fill: tint_color_towards(style.visuals.window_fill, style.visuals.extreme_bg_color),
outline_color: 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)
}
}
pub fn from_egui_active_with_kb_focus(style: &egui::Style) -> Self {
Self {
text_color: style.visuals.strong_text_color(),
outline_color: style.visuals.widgets.hovered.bg_stroke.color,
..TabInteractionStyle::from_egui_active(style)
}
}
pub fn from_egui_inactive_with_kb_focus(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)
}
}
pub fn from_egui_focused_with_kb_focus(style: &egui::Style) -> Self {
Self {
text_color: style.visuals.strong_text_color(),
outline_color: style.visuals.widgets.hovered.bg_stroke.color,
..TabInteractionStyle::from_egui_focused(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,
corner_radius: style.visuals.widgets.active.corner_radius,
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()
}
}
}