use gpui::{App, ElementId, Entity, Window};
use crate::theme::{ActionVariantKind, Theme};
#[derive(Clone, Debug)]
pub struct InputStyle {
pub bg: gpui::Hsla,
pub border: gpui::Hsla,
pub focus_border: gpui::Hsla,
pub text_color: gpui::Hsla,
}
pub fn compute_input_style(
theme: &Theme,
disabled: bool,
bg_color: Option<gpui::Hsla>,
border_color: Option<gpui::Hsla>,
focus_border_color: Option<gpui::Hsla>,
text_color: Option<gpui::Hsla>,
) -> InputStyle {
let bg = if disabled {
theme.surface.sunken
} else {
bg_color.unwrap_or(theme.surface.base)
};
let border = if disabled {
theme.border.muted
} else {
border_color.unwrap_or(theme.border.default)
};
let focus_border = focus_border_color.unwrap_or(theme.border.focus);
let text_color = if disabled {
theme.content.disabled
} else {
text_color.unwrap_or(theme.content.primary)
};
InputStyle {
bg,
border,
focus_border,
text_color,
}
}
pub fn resolve_controlled_state<T: Clone + Default + 'static>(
external: Option<&T>,
internal: Option<&Entity<T>>,
cx: &App,
default_value: T,
) -> T {
if let Some(value) = external {
return value.clone();
}
if let Some(internal) = internal {
return internal.read(cx).clone();
}
default_value
}
pub fn use_internal_state(has_value: bool, has_on_change: bool) -> bool {
!has_value && !has_on_change
}
pub fn use_internal_state_simple(has_on_change: bool) -> bool {
!has_on_change
}
pub fn create_internal_state<T: Clone + Default + 'static>(
window: &mut Window,
cx: &mut App,
id: &ElementId,
key: String,
default_value: T,
should_use: bool,
) -> Option<Entity<T>> {
if should_use {
Some(window.use_keyed_state((id.clone(), key), cx, |_, _| default_value))
} else {
None
}
}
pub fn update_internal_state<T: Clone + 'static>(
internal: &Option<Entity<T>>,
cx: &mut App,
new_value: T,
) {
if let Some(internal) = internal {
internal.update(cx, |state, _cx| {
*state = new_value;
_cx.notify();
});
}
}
pub fn resolve_state_value<T: Clone + Default + 'static>(
external: Option<&T>,
internal: &Option<Entity<T>>,
cx: &App,
) -> T {
if let Some(external) = external {
return external.clone();
}
if let Some(internal) = internal {
return internal.read(cx).clone();
}
T::default()
}
pub fn resolve_state_value_simple<T: Clone + 'static>(
external: T,
internal: &Option<Entity<T>>,
cx: &App,
use_internal: bool,
) -> T {
if use_internal && let Some(internal) = internal {
return internal.read(cx).clone();
}
external
}
#[derive(Clone, Debug)]
pub struct ActionStyle {
pub bg: gpui::Hsla,
pub hover_bg: gpui::Hsla,
pub fg: gpui::Hsla,
pub disabled_bg: gpui::Hsla,
pub disabled_fg: gpui::Hsla,
}
pub fn compute_action_style(
theme: &Theme,
variant: ActionVariantKind,
disabled: bool,
custom_bg: Option<gpui::Hsla>,
custom_hover_bg: Option<gpui::Hsla>,
) -> ActionStyle {
let action_variant = theme.action_variant(variant);
if disabled {
return ActionStyle {
bg: action_variant.disabled_bg,
hover_bg: action_variant.disabled_bg,
fg: action_variant.disabled_fg,
disabled_bg: action_variant.disabled_bg,
disabled_fg: action_variant.disabled_fg,
};
}
ActionStyle {
bg: custom_bg.unwrap_or(action_variant.bg),
hover_bg: custom_hover_bg.unwrap_or(action_variant.hover_bg),
fg: action_variant.fg,
disabled_bg: action_variant.disabled_bg,
disabled_fg: action_variant.disabled_fg,
}
}
#[derive(Clone, Debug)]
pub struct ToggleStyle {
pub bg: gpui::Hsla,
pub border: gpui::Hsla,
pub fg: gpui::Hsla,
pub hover_bg: gpui::Hsla,
pub disabled_opacity: f32,
}
pub fn compute_toggle_style(
theme: &Theme,
checked: bool,
disabled: bool,
custom_accent: Option<gpui::Hsla>,
) -> ToggleStyle {
let accent = custom_accent.unwrap_or(theme.action.primary.bg);
if disabled {
return ToggleStyle {
bg: theme.surface.sunken,
border: theme.border.muted,
fg: theme.content.disabled,
hover_bg: theme.surface.sunken,
disabled_opacity: 0.5,
};
}
if checked {
ToggleStyle {
bg: accent,
border: accent,
fg: theme.action.primary.fg,
hover_bg: theme.action.primary.hover_bg,
disabled_opacity: 1.0,
}
} else {
ToggleStyle {
bg: theme.surface.base,
border: theme.border.default,
fg: theme.content.primary,
hover_bg: theme.surface.hover,
disabled_opacity: 1.0,
}
}
}