mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-18 18:08:07 +03:00
Restructure Theme with new style objects
This commit is contained in:
parent
ef0ffbe819
commit
81041d7841
@ -16,12 +16,18 @@ use crate::{
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
pub struct ContainerStyle {
|
||||
margin: Margin,
|
||||
padding: Padding,
|
||||
background_color: Option<Color>,
|
||||
border: Border,
|
||||
corner_radius: f32,
|
||||
shadow: Option<Shadow>,
|
||||
#[serde(default)]
|
||||
pub margin: Margin,
|
||||
#[serde(default)]
|
||||
pub padding: Padding,
|
||||
#[serde(rename = "background")]
|
||||
pub background_color: Option<Color>,
|
||||
#[serde(default)]
|
||||
pub border: Border,
|
||||
#[serde(default)]
|
||||
pub corner_radius: f32,
|
||||
#[serde(default)]
|
||||
pub shadow: Option<Shadow>,
|
||||
}
|
||||
|
||||
pub struct Container {
|
||||
@ -247,9 +253,13 @@ impl ToJson for ContainerStyle {
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
pub struct Margin {
|
||||
#[serde(default)]
|
||||
top: f32,
|
||||
#[serde(default)]
|
||||
left: f32,
|
||||
#[serde(default)]
|
||||
bottom: f32,
|
||||
#[serde(default)]
|
||||
right: f32,
|
||||
}
|
||||
|
||||
@ -274,9 +284,13 @@ impl ToJson for Margin {
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
pub struct Padding {
|
||||
#[serde(default)]
|
||||
top: f32,
|
||||
#[serde(default)]
|
||||
left: f32,
|
||||
#[serde(default)]
|
||||
bottom: f32,
|
||||
#[serde(default)]
|
||||
right: f32,
|
||||
}
|
||||
|
||||
@ -301,9 +315,11 @@ impl ToJson for Padding {
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
pub struct Shadow {
|
||||
#[serde(deserialize_with = "deserialize_vec2f")]
|
||||
#[serde(default, deserialize_with = "deserialize_vec2f")]
|
||||
offset: Vector2F,
|
||||
#[serde(default)]
|
||||
blur: f32,
|
||||
#[serde(default)]
|
||||
color: Color,
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,11 @@ pub struct Label {
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize)]
|
||||
pub struct LabelStyle {
|
||||
#[serde(default = "Color::black")]
|
||||
pub color: Color,
|
||||
#[serde(default)]
|
||||
pub highlight_color: Option<Color>,
|
||||
#[serde(deserialize_with = "deserialize_font_properties")]
|
||||
#[serde(default, deserialize_with = "deserialize_font_properties")]
|
||||
pub font_properties: Properties,
|
||||
#[serde(default, deserialize_with = "deserialize_option_font_properties")]
|
||||
pub highlight_font_properties: Option<Properties>,
|
||||
|
@ -59,14 +59,24 @@ pub struct Icon {
|
||||
|
||||
#[derive(Clone, Copy, Default, Debug, Deserialize)]
|
||||
pub struct Border {
|
||||
#[serde(default = "default_border_width")]
|
||||
pub width: f32,
|
||||
#[serde(default)]
|
||||
pub color: Option<Color>,
|
||||
#[serde(default)]
|
||||
pub top: bool,
|
||||
#[serde(default)]
|
||||
pub right: bool,
|
||||
#[serde(default)]
|
||||
pub bottom: bool,
|
||||
#[serde(default)]
|
||||
pub left: bool,
|
||||
}
|
||||
|
||||
fn default_border_width() -> f32 {
|
||||
1.0
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Path {
|
||||
pub bounds: RectF,
|
||||
|
@ -1,19 +1,36 @@
|
||||
[ui]
|
||||
background = "$elevation_1"
|
||||
tab_background = "$elevation_2"
|
||||
tab_background_active = "$elevation_3"
|
||||
tab_text = "$text_dull"
|
||||
tab_text_active = "$text_bright"
|
||||
tab_border = 0x000000
|
||||
tab_icon_close = 0x383839
|
||||
tab_icon_dirty = 0x556de8
|
||||
tab_icon_conflict = 0xe45349
|
||||
modal_background = "$elevation_4"
|
||||
modal_match_background = 0x424344
|
||||
modal_match_background_active = 0x094771
|
||||
modal_match_border = 0x000000
|
||||
modal_match_text = 0xcccccc
|
||||
modal_match_text_highlight = 0x18a3ff
|
||||
|
||||
[ui.tab]
|
||||
background = "$elevation_2"
|
||||
color = "$text_dull"
|
||||
border.color = 0x000000
|
||||
icon_close = 0x383839
|
||||
icon_dirty = 0x556de8
|
||||
icon_conflict = 0xe45349
|
||||
|
||||
[ui.active_tab]
|
||||
extends = ".."
|
||||
background = "$elevation_3"
|
||||
color = "$text_bright"
|
||||
|
||||
[ui.selector]
|
||||
background = "$elevation_4"
|
||||
padding = { top = 6.0, bottom = 6.0, left = 6.0, right = 6.0 }
|
||||
margin.top = 12.0
|
||||
corner_radius = 6.0
|
||||
shadow = { offset = [0.0, 0.0], blur = 12.0, color = 0x00000088 }
|
||||
|
||||
[ui.selector.item]
|
||||
background = 0x424344
|
||||
text = 0xcccccc
|
||||
highlight_text = 0x18a3ff
|
||||
highlight_font_properties = { weight = "bold" }
|
||||
border = { color = 0x000000, width = 1.0 }
|
||||
|
||||
[ui.selector.active_item]
|
||||
extends = ".."
|
||||
background = 0x094771
|
||||
|
||||
[editor]
|
||||
background = "$elevation_3"
|
||||
@ -21,7 +38,7 @@ gutter_background = "$elevation_3"
|
||||
active_line_background = "$elevation_4"
|
||||
line_number = "$text_dull"
|
||||
line_number_active = "$text_bright"
|
||||
default_text = "$text_normal"
|
||||
text = "$text_normal"
|
||||
replicas = [
|
||||
{ selection = 0x264f78, cursor = "$text_bright" },
|
||||
{ selection = 0x504f31, cursor = 0xfcf154 },
|
||||
|
@ -6,12 +6,9 @@ use crate::{
|
||||
worktree::{match_paths, PathMatch, Worktree},
|
||||
};
|
||||
use gpui::{
|
||||
color::Color,
|
||||
elements::*,
|
||||
fonts::{Properties, Weight},
|
||||
geometry::vector::vec2f,
|
||||
keymap::{self, Binding},
|
||||
AppContext, Axis, Border, Entity, MutableAppContext, RenderContext, Task, View, ViewContext,
|
||||
AppContext, Axis, Entity, MutableAppContext, RenderContext, Task, View, ViewContext,
|
||||
ViewHandle, WeakViewHandle,
|
||||
};
|
||||
use postage::watch;
|
||||
@ -78,11 +75,7 @@ impl View for FileFinder {
|
||||
.with_child(Expanded::new(1.0, self.render_matches()).boxed())
|
||||
.boxed(),
|
||||
)
|
||||
.with_margin_top(12.0)
|
||||
.with_uniform_padding(6.0)
|
||||
.with_corner_radius(6.0)
|
||||
.with_background_color(settings.theme.ui.modal_background)
|
||||
.with_shadow(vec2f(0., 4.), 12., Color::new(0, 0, 0, 128))
|
||||
.with_style(&settings.theme.ui.selector.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_max_width(600.0)
|
||||
@ -114,7 +107,7 @@ impl FileFinder {
|
||||
settings.ui_font_family,
|
||||
settings.ui_font_size,
|
||||
)
|
||||
.with_default_color(settings.theme.editor.default_text)
|
||||
.with_default_color(settings.theme.editor.text)
|
||||
.boxed(),
|
||||
)
|
||||
.with_margin_top(6.0)
|
||||
@ -152,15 +145,8 @@ impl FileFinder {
|
||||
let theme = &settings.theme.ui;
|
||||
self.labels_for_match(path_match, cx).map(
|
||||
|(file_name, file_name_positions, full_path, full_path_positions)| {
|
||||
let bold = *Properties::new().weight(Weight::BOLD);
|
||||
let selected_index = self.selected_index();
|
||||
let label_style = LabelStyle {
|
||||
color: theme.modal_match_text,
|
||||
highlight_color: Some(theme.modal_match_text_highlight),
|
||||
highlight_font_properties: Some(bold),
|
||||
..Default::default()
|
||||
};
|
||||
let mut container = Container::new(
|
||||
let container = Container::new(
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Container::new(
|
||||
@ -184,7 +170,7 @@ impl FileFinder {
|
||||
settings.ui_font_family,
|
||||
settings.ui_font_size,
|
||||
)
|
||||
.with_style(&label_style)
|
||||
.with_style(&theme.selector.label)
|
||||
.with_highlights(file_name_positions)
|
||||
.boxed(),
|
||||
)
|
||||
@ -194,7 +180,7 @@ impl FileFinder {
|
||||
settings.ui_font_family,
|
||||
settings.ui_font_size,
|
||||
)
|
||||
.with_style(&label_style)
|
||||
.with_style(&theme.selector.label)
|
||||
.with_highlights(full_path_positions)
|
||||
.boxed(),
|
||||
)
|
||||
@ -205,17 +191,12 @@ impl FileFinder {
|
||||
.boxed(),
|
||||
)
|
||||
.with_uniform_padding(6.0)
|
||||
.with_background_color(if index == selected_index {
|
||||
theme.modal_match_background_active
|
||||
.with_style(if index == selected_index {
|
||||
&theme.selector.active_item.container
|
||||
} else {
|
||||
theme.modal_match_background
|
||||
&theme.selector.item.container
|
||||
});
|
||||
|
||||
if index == selected_index || index < self.matches.len() - 1 {
|
||||
container =
|
||||
container.with_border(Border::bottom(1.0, theme.modal_match_border));
|
||||
}
|
||||
|
||||
let entry = (path_match.tree_id, path_match.path.clone());
|
||||
EventHandler::new(container.boxed())
|
||||
.on_mouse_down(move |cx| {
|
||||
|
@ -10,6 +10,7 @@ pub mod settings;
|
||||
mod sum_tree;
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub mod test;
|
||||
pub mod theme;
|
||||
pub mod theme_selector;
|
||||
mod time;
|
||||
mod util;
|
||||
|
@ -11,6 +11,9 @@ use serde::{de::value::MapDeserializer, Deserialize};
|
||||
use serde_json::Value;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use crate::theme;
|
||||
pub use theme::Theme;
|
||||
|
||||
const DEFAULT_STYLE_ID: StyleId = StyleId(u32::MAX);
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -29,13 +32,6 @@ pub struct ThemeRegistry {
|
||||
theme_data: Mutex<HashMap<String, Arc<ThemeToml>>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct Theme {
|
||||
pub ui: UiTheme,
|
||||
pub editor: EditorTheme,
|
||||
pub syntax: Vec<(String, Color, FontProperties)>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct ThemeToml {
|
||||
#[serde(default)]
|
||||
@ -50,44 +46,6 @@ struct ThemeToml {
|
||||
syntax: HashMap<String, Value>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct UiTheme {
|
||||
pub background: Color,
|
||||
pub tab_background: Color,
|
||||
pub tab_background_active: Color,
|
||||
pub tab_text: Color,
|
||||
pub tab_text_active: Color,
|
||||
pub tab_border: Color,
|
||||
pub tab_icon_close: Color,
|
||||
pub tab_icon_dirty: Color,
|
||||
pub tab_icon_conflict: Color,
|
||||
pub modal_background: Color,
|
||||
pub modal_match_background: Color,
|
||||
pub modal_match_background_active: Color,
|
||||
pub modal_match_border: Color,
|
||||
pub modal_match_text: Color,
|
||||
pub modal_match_text_highlight: Color,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct EditorTheme {
|
||||
pub background: Color,
|
||||
pub gutter_background: Color,
|
||||
pub active_line_background: Color,
|
||||
pub line_number: Color,
|
||||
pub line_number_active: Color,
|
||||
pub default_text: Color,
|
||||
pub replicas: Vec<ReplicaTheme>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Deserialize, Default)]
|
||||
pub struct ReplicaTheme {
|
||||
pub cursor: Color,
|
||||
pub selection: Color,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ThemeMap(Arc<[StyleId]>);
|
||||
|
||||
@ -169,8 +127,8 @@ impl ThemeRegistry {
|
||||
}
|
||||
|
||||
let theme = Arc::new(Theme {
|
||||
ui: UiTheme::deserialize(MapDeserializer::new(theme_toml.ui.clone().into_iter()))?,
|
||||
editor: EditorTheme::deserialize(MapDeserializer::new(
|
||||
ui: theme::Ui::deserialize(MapDeserializer::new(theme_toml.ui.clone().into_iter()))?,
|
||||
editor: theme::Editor::deserialize(MapDeserializer::new(
|
||||
theme_toml.editor.clone().into_iter(),
|
||||
))?,
|
||||
syntax,
|
||||
@ -229,7 +187,7 @@ impl Theme {
|
||||
pub fn syntax_style(&self, id: StyleId) -> (Color, FontProperties) {
|
||||
self.syntax
|
||||
.get(id.0 as usize)
|
||||
.map_or((self.editor.default_text, FontProperties::new()), |entry| {
|
||||
.map_or((self.editor.text, FontProperties::new()), |entry| {
|
||||
(entry.1, entry.2)
|
||||
})
|
||||
}
|
||||
@ -240,20 +198,6 @@ impl Theme {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for EditorTheme {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
background: Default::default(),
|
||||
gutter_background: Default::default(),
|
||||
active_line_background: Default::default(),
|
||||
line_number: Default::default(),
|
||||
line_number_active: Default::default(),
|
||||
default_text: Default::default(),
|
||||
replicas: vec![ReplicaTheme::default()],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ThemeMap {
|
||||
pub fn new(capture_names: &[String], theme: &Theme) -> Self {
|
||||
// For each capture name in the highlight query, find the longest
|
||||
@ -407,8 +351,8 @@ mod tests {
|
||||
let assets = TestAssets(&[(
|
||||
"themes/my-theme.toml",
|
||||
r#"
|
||||
[ui]
|
||||
tab_background_active = 0x100000
|
||||
[ui.tab.active]
|
||||
background = 0x100000
|
||||
|
||||
[editor]
|
||||
background = 0x00ed00
|
||||
@ -424,7 +368,10 @@ mod tests {
|
||||
let registry = ThemeRegistry::new(assets);
|
||||
let theme = registry.get("my-theme").unwrap();
|
||||
|
||||
assert_eq!(theme.ui.tab_background_active, Color::from_u32(0x100000ff));
|
||||
assert_eq!(
|
||||
theme.ui.active_tab.container.background_color,
|
||||
Some(Color::from_u32(0x100000ff))
|
||||
);
|
||||
assert_eq!(theme.editor.background, Color::from_u32(0x00ed00ff));
|
||||
assert_eq!(theme.editor.line_number, Color::from_u32(0xddddddff));
|
||||
assert_eq!(
|
||||
@ -459,9 +406,9 @@ mod tests {
|
||||
r#"
|
||||
abstract = true
|
||||
|
||||
[ui]
|
||||
tab_background = 0x111111
|
||||
tab_text = "$variable_1"
|
||||
[ui.tab]
|
||||
background = 0x111111
|
||||
text = "$variable_1"
|
||||
|
||||
[editor]
|
||||
background = 0x222222
|
||||
@ -477,8 +424,8 @@ mod tests {
|
||||
variable_1 = 0x333333
|
||||
variable_2 = 0x444444
|
||||
|
||||
[ui]
|
||||
tab_background = 0x555555
|
||||
[ui.tab]
|
||||
background = 0x555555
|
||||
|
||||
[editor]
|
||||
background = 0x666666
|
||||
@ -499,10 +446,13 @@ mod tests {
|
||||
let registry = ThemeRegistry::new(assets);
|
||||
let theme = registry.get("light").unwrap();
|
||||
|
||||
assert_eq!(theme.ui.tab_background, Color::from_u32(0x555555ff));
|
||||
assert_eq!(theme.ui.tab_text, Color::from_u32(0x333333ff));
|
||||
assert_eq!(
|
||||
theme.ui.tab.container.background_color,
|
||||
Some(Color::from_u32(0x555555ff))
|
||||
);
|
||||
assert_eq!(theme.ui.tab.label.color, Color::from_u32(0x333333ff));
|
||||
assert_eq!(theme.editor.background, Color::from_u32(0x666666ff));
|
||||
assert_eq!(theme.editor.default_text, Color::from_u32(0x444444ff));
|
||||
assert_eq!(theme.editor.text, Color::from_u32(0x444444ff));
|
||||
|
||||
assert_eq!(
|
||||
registry.list().collect::<Vec<_>>(),
|
||||
|
80
zed/src/theme.rs
Normal file
80
zed/src/theme.rs
Normal file
@ -0,0 +1,80 @@
|
||||
use gpui::color::Color;
|
||||
use gpui::elements::{ContainerStyle, LabelStyle};
|
||||
use gpui::fonts::Properties as FontProperties;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Theme {
|
||||
pub ui: Ui,
|
||||
pub editor: Editor,
|
||||
pub syntax: Vec<(String, Color, FontProperties)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct Ui {
|
||||
pub background: Color,
|
||||
pub tab: Tab,
|
||||
pub active_tab: Tab,
|
||||
pub selector: Selector,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Editor {
|
||||
pub background: Color,
|
||||
pub gutter_background: Color,
|
||||
pub active_line_background: Color,
|
||||
pub line_number: Color,
|
||||
pub line_number_active: Color,
|
||||
pub text: Color,
|
||||
pub replicas: Vec<Replica>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Deserialize)]
|
||||
pub struct Replica {
|
||||
pub cursor: Color,
|
||||
pub selection: Color,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct Tab {
|
||||
#[serde(flatten)]
|
||||
pub container: ContainerStyle,
|
||||
#[serde(flatten)]
|
||||
pub label: LabelStyle,
|
||||
pub icon_close: Color,
|
||||
pub icon_dirty: Color,
|
||||
pub icon_conflict: Color,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct Selector {
|
||||
#[serde(flatten)]
|
||||
pub container: ContainerStyle,
|
||||
#[serde(flatten)]
|
||||
pub label: LabelStyle,
|
||||
|
||||
pub item: SelectorItem,
|
||||
pub active_item: SelectorItem,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct SelectorItem {
|
||||
#[serde(flatten)]
|
||||
pub container: ContainerStyle,
|
||||
#[serde(flatten)]
|
||||
pub label: LabelStyle,
|
||||
}
|
||||
|
||||
impl Default for Editor {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
background: Default::default(),
|
||||
gutter_background: Default::default(),
|
||||
active_line_background: Default::default(),
|
||||
line_number: Default::default(),
|
||||
line_number_active: Default::default(),
|
||||
text: Default::default(),
|
||||
replicas: vec![Replica::default()],
|
||||
}
|
||||
}
|
||||
}
|
@ -9,15 +9,12 @@ use crate::{
|
||||
};
|
||||
use futures::lock::Mutex;
|
||||
use gpui::{
|
||||
color::Color,
|
||||
elements::{
|
||||
Align, ChildView, ConstrainedBox, Container, Expanded, Flex, Label, LabelStyle,
|
||||
ParentElement, UniformList, UniformListState,
|
||||
Align, ChildView, ConstrainedBox, Container, Expanded, Flex, Label, ParentElement,
|
||||
UniformList, UniformListState,
|
||||
},
|
||||
fonts::{Properties, Weight},
|
||||
geometry::vector::vec2f,
|
||||
keymap::{self, Binding},
|
||||
AppContext, Axis, Border, Element, ElementBox, Entity, MutableAppContext, RenderContext, View,
|
||||
AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, RenderContext, View,
|
||||
ViewContext, ViewHandle,
|
||||
};
|
||||
use postage::watch;
|
||||
@ -199,7 +196,7 @@ impl ThemeSelector {
|
||||
settings.ui_font_family,
|
||||
settings.ui_font_size,
|
||||
)
|
||||
.with_default_color(settings.theme.editor.default_text)
|
||||
.with_default_color(settings.theme.editor.text)
|
||||
.boxed(),
|
||||
)
|
||||
.with_margin_top(6.0)
|
||||
@ -234,32 +231,26 @@ impl ThemeSelector {
|
||||
let settings = self.settings.borrow();
|
||||
let theme = &settings.theme.ui;
|
||||
|
||||
let mut container = Container::new(
|
||||
let container = Container::new(
|
||||
Label::new(
|
||||
theme_match.string.clone(),
|
||||
settings.ui_font_family,
|
||||
settings.ui_font_size,
|
||||
)
|
||||
.with_style(&LabelStyle {
|
||||
color: theme.modal_match_text,
|
||||
highlight_color: Some(theme.modal_match_text_highlight),
|
||||
highlight_font_properties: Some(*Properties::new().weight(Weight::BOLD)),
|
||||
..Default::default()
|
||||
.with_style(if index == self.selected_index {
|
||||
&theme.selector.active_item.label
|
||||
} else {
|
||||
&theme.selector.item.label
|
||||
})
|
||||
.with_highlights(theme_match.positions.clone())
|
||||
.boxed(),
|
||||
)
|
||||
.with_uniform_padding(6.0)
|
||||
.with_background_color(if index == self.selected_index {
|
||||
theme.modal_match_background_active
|
||||
.with_style(if index == self.selected_index {
|
||||
&theme.selector.active_item.container
|
||||
} else {
|
||||
theme.modal_match_background
|
||||
&theme.selector.item.container
|
||||
});
|
||||
|
||||
if index == self.selected_index || index < self.matches.len() - 1 {
|
||||
container = container.with_border(Border::bottom(1.0, theme.modal_match_border));
|
||||
}
|
||||
|
||||
container.boxed()
|
||||
}
|
||||
}
|
||||
@ -284,11 +275,7 @@ impl View for ThemeSelector {
|
||||
.with_child(Expanded::new(1.0, self.render_matches(cx)).boxed())
|
||||
.boxed(),
|
||||
)
|
||||
.with_margin_top(12.0)
|
||||
.with_uniform_padding(6.0)
|
||||
.with_corner_radius(6.0)
|
||||
.with_background_color(settings.theme.ui.modal_background)
|
||||
.with_shadow(vec2f(0., 4.), 12., Color::new(0, 0, 0, 128))
|
||||
.with_style(&settings.theme.ui.selector.container)
|
||||
.boxed(),
|
||||
)
|
||||
.with_max_width(600.0)
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{ItemViewHandle, SplitDirection};
|
||||
use crate::settings::{Settings, UiTheme};
|
||||
use crate::{settings::Settings, theme};
|
||||
use gpui::{
|
||||
color::Color,
|
||||
elements::*,
|
||||
@ -193,6 +193,7 @@ impl Pane {
|
||||
let is_active = ix == self.active_item;
|
||||
|
||||
enum Tab {}
|
||||
let border = &theme.tab.container.border;
|
||||
|
||||
row.add_child(
|
||||
Expanded::new(
|
||||
@ -200,10 +201,10 @@ impl Pane {
|
||||
MouseEventHandler::new::<Tab, _>(item.id(), cx, |mouse_state| {
|
||||
let title = item.title(cx);
|
||||
|
||||
let mut border = Border::new(1.0, theme.tab_border);
|
||||
let mut border = border.clone();
|
||||
border.left = ix > 0;
|
||||
border.right = ix == last_item_ix;
|
||||
border.bottom = ix != self.active_item;
|
||||
border.bottom = !is_active;
|
||||
|
||||
let mut container = Container::new(
|
||||
Stack::new()
|
||||
@ -214,10 +215,10 @@ impl Pane {
|
||||
settings.ui_font_family,
|
||||
settings.ui_font_size,
|
||||
)
|
||||
.with_default_color(if is_active {
|
||||
theme.tab_text_active
|
||||
.with_style(if is_active {
|
||||
&theme.active_tab.label
|
||||
} else {
|
||||
theme.tab_text
|
||||
&theme.tab.label
|
||||
})
|
||||
.boxed(),
|
||||
)
|
||||
@ -238,15 +239,16 @@ impl Pane {
|
||||
)
|
||||
.boxed(),
|
||||
)
|
||||
.with_style(if is_active {
|
||||
&theme.active_tab.container
|
||||
} else {
|
||||
&theme.tab.container
|
||||
})
|
||||
.with_horizontal_padding(10.)
|
||||
.with_border(border);
|
||||
|
||||
if is_active {
|
||||
container = container
|
||||
.with_background_color(theme.tab_background_active)
|
||||
.with_padding_bottom(border.width);
|
||||
} else {
|
||||
container = container.with_background_color(theme.tab_background);
|
||||
container = container.with_padding_bottom(border.width);
|
||||
}
|
||||
|
||||
ConstrainedBox::new(
|
||||
@ -269,10 +271,13 @@ impl Pane {
|
||||
|
||||
// Ensure there's always a minimum amount of space after the last tab,
|
||||
// so that the tab's border doesn't abut the window's border.
|
||||
let mut border = Border::bottom(1.0, Color::default());
|
||||
border.color = theme.tab.container.border.color;
|
||||
|
||||
row.add_child(
|
||||
ConstrainedBox::new(
|
||||
Container::new(Empty::new().boxed())
|
||||
.with_border(Border::bottom(1.0, theme.tab_border))
|
||||
.with_border(border)
|
||||
.boxed(),
|
||||
)
|
||||
.with_min_width(20.)
|
||||
@ -283,7 +288,7 @@ impl Pane {
|
||||
Expanded::new(
|
||||
0.0,
|
||||
Container::new(Empty::new().boxed())
|
||||
.with_border(Border::bottom(1.0, theme.tab_border))
|
||||
.with_border(border)
|
||||
.boxed(),
|
||||
)
|
||||
.named("filler"),
|
||||
@ -300,24 +305,24 @@ impl Pane {
|
||||
tab_hovered: bool,
|
||||
is_dirty: bool,
|
||||
has_conflict: bool,
|
||||
theme: &UiTheme,
|
||||
theme: &theme::Ui,
|
||||
cx: &AppContext,
|
||||
) -> ElementBox {
|
||||
enum TabCloseButton {}
|
||||
|
||||
let mut clicked_color = theme.tab_icon_dirty;
|
||||
let mut clicked_color = theme.tab.icon_dirty;
|
||||
clicked_color.a = 180;
|
||||
|
||||
let current_color = if has_conflict {
|
||||
Some(theme.tab_icon_conflict)
|
||||
Some(theme.tab.icon_conflict)
|
||||
} else if is_dirty {
|
||||
Some(theme.tab_icon_dirty)
|
||||
Some(theme.tab.icon_dirty)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let icon = if tab_hovered {
|
||||
let close_color = current_color.unwrap_or(theme.tab_icon_close);
|
||||
let close_color = current_color.unwrap_or(theme.tab.icon_close);
|
||||
let icon = Svg::new("icons/x.svg").with_color(close_color);
|
||||
|
||||
MouseEventHandler::new::<TabCloseButton, _>(item_id, cx, |mouse_state| {
|
||||
@ -326,7 +331,7 @@ impl Pane {
|
||||
.with_background_color(if mouse_state.clicked {
|
||||
clicked_color
|
||||
} else {
|
||||
theme.tab_icon_dirty
|
||||
theme.tab.icon_dirty
|
||||
})
|
||||
.with_corner_radius(close_icon_size / 2.)
|
||||
.boxed()
|
||||
|
Loading…
Reference in New Issue
Block a user