This commit is contained in:
2026-10-08 08:42:44 +07:00
parent 069f031af9
commit 2efb6ac5ca
24 changed files with 628 additions and 2614 deletions
+22 -192
View File
@@ -1,29 +1,21 @@
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
use gpui::{App, Pixels, px};
use gpui::{App, Global, Pixels, SharedString, Window, px};
pub mod model;
mod colors;
pub mod builtins;
mod geometry;
pub mod model;
mod notification;
mod platform_kind;
mod registry;
mod scale;
mod resolved;
mod runtime;
mod scrollbar_mode;
mod theme;
mod builtins;
pub use colors::*;
pub use geometry::*;
pub use model::*;
pub use notification::*;
pub use platform_kind::PlatformKind;
pub use registry::*;
pub use scale::*;
pub use resolved::{ResolvedAccentRoles, ResolvedColors};
pub use runtime::Theme;
pub use scrollbar_mode::*;
pub use theme::*;
/// Defines window border radius for platforms that use client side decorations.
pub const CLIENT_SIDE_DECORATION_ROUNDING: Pixels = px(10.0);
@@ -44,8 +36,6 @@ pub const TABBAR_HEIGHT: Pixels = px(36.0);
pub const SIDEBAR_WIDTH: Pixels = px(240.);
pub fn init(cx: &mut App) {
registry::init(cx);
Theme::sync_system_appearance(None, cx);
Theme::sync_scrollbar_appearance(cx);
}
@@ -68,7 +58,7 @@ pub fn sync_base(cx: &mut App) {
return;
};
let appearance = if theme.mode.is_dark() {
let appearance = if theme.appearance.is_dark() {
gpui_base::ThemeAppearance::Dark
} else {
gpui_base::ThemeAppearance::Light
@@ -79,6 +69,7 @@ pub fn sync_base(cx: &mut App) {
ScrollbarMode::Always => gpui_base::ScrollbarMode::Always,
};
let colors = theme.colors;
let accent = theme.accent;
let font_family = theme.font_family.clone();
let base = gpui_base::Theme::global_mut(cx);
@@ -89,22 +80,22 @@ pub fn sync_base(cx: &mut App) {
let tokens = &mut base.tokens.colors;
tokens.background = colors.background;
tokens.foreground = colors.text;
tokens.surface = colors.surface_background;
tokens.surface = colors.shell;
tokens.surface_foreground = colors.text;
tokens.primary = colors.element_background;
tokens.primary_foreground = colors.element_foreground;
tokens.secondary = colors.secondary_background;
tokens.secondary_foreground = colors.secondary_foreground;
tokens.muted = colors.ghost_element_background_alt;
tokens.primary = accent.primary;
tokens.primary_foreground = accent.on;
tokens.secondary = colors.raised;
tokens.secondary_foreground = colors.text;
tokens.muted = colors.hover;
tokens.muted_foreground = colors.text_muted;
tokens.accent = colors.ghost_element_hover;
tokens.accent = accent.wash;
tokens.accent_foreground = colors.text;
tokens.destructive = colors.danger_background;
tokens.destructive_foreground = colors.danger_foreground;
tokens.destructive = colors.danger;
tokens.destructive_foreground = accent.on_danger;
tokens.border = colors.border;
tokens.input = colors.border;
tokens.ring = colors.ring;
tokens.selection = colors.selection;
tokens.input = colors.input;
tokens.ring = accent.primary;
tokens.selection = accent.selection;
}
pub trait ActiveTheme {
@@ -117,164 +108,3 @@ impl ActiveTheme for App {
Theme::global(self)
}
}
#[derive(Debug, Clone)]
pub struct Theme {
/// Theme colors
pub colors: ThemeColors,
/// Theme family
pub theme: Rc<ThemeFamily>,
/// The appearance of the theme (light or dark).
pub mode: ThemeMode,
/// The font family for the application.
pub font_family: SharedString,
/// The root font size for the application, default is 15px.
pub font_size: Pixels,
/// Radius for the general elements.
pub radius: Pixels,
/// Radius for the large elements, e.g.: dialog, notification.
pub radius_lg: Pixels,
/// Enable shadow for the general elements. default is true
pub shadow: bool,
/// Show the scrollbar mode, default: scrolling
pub scrollbar_mode: ScrollbarMode,
/// Notification settings
pub notification: NotificationSettings,
}
impl Deref for Theme {
type Target = ThemeColors;
fn deref(&self) -> &Self::Target {
&self.colors
}
}
impl DerefMut for Theme {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.colors
}
}
impl Global for Theme {}
impl Theme {
/// Returns the global theme reference
pub fn global(cx: &App) -> &Theme {
cx.global::<Theme>()
}
/// Returns the global theme mutable reference
pub(crate) fn global_mut(cx: &mut App) -> &mut Theme {
cx.global_mut::<Theme>()
}
/// Returns true if the theme is dark.
pub fn is_dark(&self) -> bool {
self.mode.is_dark()
}
/// Sync the theme with the system appearance
pub fn sync_system_appearance(window: Option<&mut Window>, cx: &mut App) {
let appearance = window
.as_ref()
.map(|window| window.appearance())
.unwrap_or_else(|| cx.window_appearance());
Self::change(appearance, window, cx);
}
/// Sync the Scrollbar showing behavior with the system
pub fn sync_scrollbar_appearance(cx: &mut App) {
Theme::global_mut(cx).scrollbar_mode = if cx.should_auto_hide_scrollbars() {
ScrollbarMode::Scrolling
} else {
ScrollbarMode::Hover
};
}
/// Apply a new theme to the application.
pub fn apply_theme(new_theme: Rc<ThemeFamily>, window: Option<&mut Window>, cx: &mut App) {
let theme = cx.global_mut::<Theme>();
let mode = theme.mode;
// Update the theme
theme.theme = new_theme;
// Emit a theme change event
Self::change(mode, window, cx);
}
/// Change the app's appearance
pub fn change<M>(mode: M, window: Option<&mut Window>, cx: &mut App)
where
M: Into<ThemeMode>,
{
if !cx.has_global::<Theme>() {
let default_theme = ThemeFamily::default();
let theme = Theme::from(default_theme);
cx.set_global(theme);
}
let mode = mode.into();
let theme = cx.global_mut::<Theme>();
// Set the theme mode
theme.mode = mode;
// Set the theme colors
if mode.is_dark() {
theme.colors = *theme.theme.dark();
} else {
theme.colors = *theme.theme.light();
}
// Refresh the window if available
if let Some(window) = window {
window.refresh();
}
// Keep the base-layer projection in step with the coop palette
sync_base(cx);
}
}
impl From<ThemeFamily> for Theme {
fn from(family: ThemeFamily) -> Self {
let platform = PlatformKind::platform();
let mode = ThemeMode::default();
// Define the font family based on the platform.
let font_family = match platform {
PlatformKind::Linux => "Inter",
_ => ".SystemUIFont",
};
// Define the theme colors based on the appearance
let colors = match mode {
ThemeMode::Light => family.light(),
ThemeMode::Dark => family.dark(),
};
Theme {
font_size: px(15.),
font_family: font_family.into(),
radius: px(6.),
radius_lg: px(10.),
shadow: true,
scrollbar_mode: ScrollbarMode::default(),
notification: NotificationSettings::default(),
mode,
colors: *colors,
theme: Rc::new(family),
}
}
}