In theme, add an InputEditorSyle for styling small editors

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Max Brunsfeld
2021-09-02 11:20:30 -07:00
co-authored by Antonio Scandurra
parent f59e02cf25
commit 1c43121ae0
12 changed files with 115 additions and 67 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ pub struct TextStyle {
pub font_properties: Properties,
}
#[derive(Clone, Debug, Default)]
#[derive(Clone, Debug)]
pub struct HighlightStyle {
pub color: Color,
pub font_properties: Properties,
+9 -7
View File
@@ -65,6 +65,11 @@ corner_radius = 6
border = { color = "#000000", width = 1 }
background = "$surface.0"
[chat_panel.input_editor]
text = "$text.1.color"
background = "$surface.1"
selection = "$selection.host"
[selector]
background = "$surface.2"
text = "$text.0"
@@ -72,6 +77,7 @@ padding = 6
margin.top = 12
corner_radius = 6
shadow = { offset = [0, 0], blur = 12, color = "#00000088" }
input_editor = "$chat_panel.input_editor"
[selector.item]
background = "#424344"
@@ -85,15 +91,11 @@ extends = "$selector.item"
background = "#094771"
[editor]
text = "$text.1.color"
background = "$surface.1"
gutter_background = "$surface.1"
active_line_background = "$surface.2"
line_number = "$text.2.color"
line_number_active = "$text.0.color"
replicas = [
{ selection = "#264f78", cursor = "$text.0.color" },
{ selection = "#504f31", cursor = "#fcf154" },
]
[syntax]
default = "$text.1.color"
selection = "$selection.host"
guest_selections = "$selection.guests"
+4
View File
@@ -11,6 +11,10 @@ base = { family = "Helvetica", size = 14.0 }
1 = { extends = "$text.base", color = "#b3b3b3" }
2 = { extends = "$text.base", color = "#7b7d80" }
[selection]
host = { selection = "#264f78", cursor = "$text.0.color" }
guests = [{ selection = "#504f31", cursor = "#fcf154" }]
[status]
good = "#4fac63"
info = "#3c5dd4"
+4
View File
@@ -12,6 +12,10 @@ base = { family = "Helvetica", size = 14.0 }
1 = { extends = "$text.base", color = "#111111" }
2 = { extends = "$text.base", color = "#333333" }
[selection]
host = { selection = "#264f78", cursor = "$text.0.color" }
guests = [{ selection = "#504f31", cursor = "#fcf154" }]
[status]
good = "#4fac63"
info = "#3c5dd4"
+6 -1
View File
@@ -46,7 +46,12 @@ impl ChatPanel {
settings: watch::Receiver<Settings>,
cx: &mut ViewContext<Self>,
) -> Self {
let input_editor = cx.add_view(|cx| Editor::auto_height(settings.clone(), cx));
let input_editor = cx.add_view(|cx| {
Editor::auto_height(settings.clone(), cx).with_style({
let settings = settings.clone();
move |_| settings.borrow().theme.chat_panel.input_editor.as_editor()
})
});
let channel_select = cx.add_view(|cx| {
let channel_list = channel_list.clone();
Select::new(0, cx, {
+6 -1
View File
@@ -2397,6 +2397,7 @@ impl Snapshot {
pub fn layout_lines(
&mut self,
mut rows: Range<u32>,
style: &EditorStyle,
font_cache: &FontCache,
layout_cache: &TextLayoutCache,
) -> Result<Vec<text_layout::Line>> {
@@ -2433,7 +2434,11 @@ impl Snapshot {
}
if !line_chunk.is_empty() && !line_exceeded_max_len {
let style = self.theme.syntax.highlight_style(style_ix);
let style = self
.theme
.syntax
.highlight_style(style_ix)
.unwrap_or(style.text.clone());
// Avoid a lookup if the font properties match the previous ones.
let font_id = if style.font_properties == prev_font_properties {
prev_font_id
+8 -14
View File
@@ -661,13 +661,10 @@ mod tests {
(function_item name: (identifier) @fn.name)"#,
)
.unwrap();
let theme = SyntaxTheme::new(
Default::default(),
vec![
("mod.body".to_string(), Color::from_u32(0xff0000ff).into()),
("fn.name".to_string(), Color::from_u32(0x00ff00ff).into()),
],
);
let theme = SyntaxTheme::new(vec![
("mod.body".to_string(), Color::from_u32(0xff0000ff).into()),
("fn.name".to_string(), Color::from_u32(0x00ff00ff).into()),
]);
let lang = Arc::new(Language {
config: LanguageConfig {
name: "Test".to_string(),
@@ -754,13 +751,10 @@ mod tests {
(function_item name: (identifier) @fn.name)"#,
)
.unwrap();
let theme = SyntaxTheme::new(
Default::default(),
vec![
("mod.body".to_string(), Color::from_u32(0xff0000ff).into()),
("fn.name".to_string(), Color::from_u32(0x00ff00ff).into()),
],
);
let theme = SyntaxTheme::new(vec![
("mod.body".to_string(), Color::from_u32(0xff0000ff).into()),
("fn.name".to_string(), Color::from_u32(0x00ff00ff).into()),
]);
let lang = Arc::new(Language {
config: LanguageConfig {
name: "Test".to_string(),
+14 -5
View File
@@ -280,7 +280,12 @@ impl EditorElement {
let content_origin = bounds.origin() + layout.text_offset;
for (replica_id, selections) in &layout.selections {
let replica_theme = theme.replicas[*replica_id as usize % theme.replicas.len()];
let style_ix = *replica_id as usize % (theme.guest_selections.len() + 1);
let style = if style_ix == 0 {
&theme.selection
} else {
&theme.guest_selections[style_ix - 1]
};
for selection in selections {
if selection.start != selection.end {
@@ -294,7 +299,7 @@ impl EditorElement {
};
let selection = Selection {
color: replica_theme.selection,
color: style.selection,
line_height: layout.line_height,
start_y: content_origin.y() + row_range.start as f32 * layout.line_height
- scroll_top,
@@ -337,7 +342,7 @@ impl EditorElement {
- scroll_left;
let y = selection.end.row() as f32 * layout.line_height - scroll_top;
cursors.push(Cursor {
color: replica_theme.cursor,
color: style.cursor,
origin: content_origin + vec2f(x, y),
line_height: layout.line_height,
});
@@ -507,8 +512,12 @@ impl Element for EditorElement {
};
let mut max_visible_line_width = 0.0;
let line_layouts = match snapshot.layout_lines(start_row..end_row, font_cache, layout_cache)
{
let line_layouts = match snapshot.layout_lines(
start_row..end_row,
&self.style,
font_cache,
layout_cache,
) {
Err(error) => {
log::error!("error laying out lines: {}", error);
return (size, None);
+14 -9
View File
@@ -30,7 +30,7 @@ pub struct FileFinder {
handle: WeakViewHandle<Self>,
settings: watch::Receiver<Settings>,
workspace: WeakViewHandle<Workspace>,
query_buffer: ViewHandle<Editor>,
query_editor: ViewHandle<Editor>,
search_count: usize,
latest_search_id: usize,
latest_search_did_cancel: bool,
@@ -86,7 +86,7 @@ impl View for FileFinder {
ConstrainedBox::new(
Container::new(
Flex::new(Axis::Vertical)
.with_child(ChildView::new(self.query_buffer.id()).boxed())
.with_child(ChildView::new(self.query_editor.id()).boxed())
.with_child(Expanded::new(1.0, self.render_matches()).boxed())
.boxed(),
)
@@ -102,7 +102,7 @@ impl View for FileFinder {
}
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
cx.focus(&self.query_buffer);
cx.focus(&self.query_editor);
}
fn keymap_context(&self, _: &AppContext) -> keymap::Context {
@@ -266,15 +266,20 @@ impl FileFinder {
) -> Self {
cx.observe(&workspace, Self::workspace_updated).detach();
let query_buffer = cx.add_view(|cx| Editor::single_line(settings.clone(), cx));
cx.subscribe(&query_buffer, Self::on_query_editor_event)
let query_editor = cx.add_view(|cx| {
Editor::single_line(settings.clone(), cx).with_style({
let settings = settings.clone();
move |_| settings.borrow().theme.selector.input_editor.as_editor()
})
});
cx.subscribe(&query_editor, Self::on_query_editor_event)
.detach();
Self {
handle: cx.handle().downgrade(),
settings,
workspace: workspace.downgrade(),
query_buffer,
query_editor,
search_count: 0,
latest_search_id: 0,
latest_search_did_cancel: false,
@@ -287,7 +292,7 @@ impl FileFinder {
}
fn workspace_updated(&mut self, _: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) {
let query = self.query_buffer.update(cx, |buffer, cx| buffer.text(cx));
let query = self.query_editor.update(cx, |buffer, cx| buffer.text(cx));
if let Some(task) = self.spawn_search(query, cx) {
task.detach();
}
@@ -301,7 +306,7 @@ impl FileFinder {
) {
match event {
editor::Event::Edited => {
let query = self.query_buffer.update(cx, |buffer, cx| buffer.text(cx));
let query = self.query_editor.update(cx, |buffer, cx| buffer.text(cx));
if query.is_empty() {
self.latest_search_id = util::post_inc(&mut self.search_count);
self.matches.clear();
@@ -460,7 +465,7 @@ mod tests {
.downcast::<FileFinder>()
.unwrap()
});
let query_buffer = cx.read(|cx| finder.read(cx).query_buffer.clone());
let query_buffer = cx.read(|cx| finder.read(cx).query_editor.clone());
let chain = vec![finder.id(), query_buffer.id()];
cx.dispatch_action(window_id, chain.clone(), Insert("b".into()));
+36 -21
View File
@@ -7,7 +7,7 @@ use gpui::{
elements::{ContainerStyle, LabelStyle},
fonts::{HighlightStyle, TextStyle},
};
use serde::{de, Deserialize};
use serde::Deserialize;
use std::collections::HashMap;
pub use highlight_map::*;
@@ -28,7 +28,6 @@ pub struct Theme {
pub struct SyntaxTheme {
highlights: Vec<(String, HighlightStyle)>,
default_style: HighlightStyle,
}
#[derive(Deserialize)]
@@ -69,6 +68,7 @@ pub struct ChatPanel {
pub container: ContainerStyle,
pub message: ChatMessage,
pub channel_select: ChannelSelect,
pub input_editor: InputEditorStyle,
}
#[derive(Deserialize)]
@@ -107,6 +107,7 @@ pub struct Selector {
#[serde(flatten)]
pub label: LabelStyle,
pub input_editor: InputEditorStyle,
pub item: ContainedLabel,
pub active_item: ContainedLabel,
}
@@ -129,33 +130,38 @@ pub struct ContainedLabel {
#[derive(Clone, Deserialize)]
pub struct EditorStyle {
pub text: HighlightStyle,
pub background: Color,
pub selection: SelectionStyle,
pub gutter_background: Color,
pub active_line_background: Color,
pub line_number: Color,
pub line_number_active: Color,
pub replicas: Vec<Replica>,
pub guest_selections: Vec<SelectionStyle>,
}
#[derive(Clone, Deserialize)]
pub struct InputEditorStyle {
pub text: HighlightStyle,
pub background: Color,
pub selection: SelectionStyle,
}
#[derive(Clone, Copy, Default, Deserialize)]
pub struct Replica {
pub struct SelectionStyle {
pub cursor: Color,
pub selection: Color,
}
impl SyntaxTheme {
pub fn new(default_style: HighlightStyle, highlights: Vec<(String, HighlightStyle)>) -> Self {
Self {
default_style,
highlights,
}
pub fn new(highlights: Vec<(String, HighlightStyle)>) -> Self {
Self { highlights }
}
pub fn highlight_style(&self, id: HighlightId) -> HighlightStyle {
pub fn highlight_style(&self, id: HighlightId) -> Option<HighlightStyle> {
self.highlights
.get(id.0 as usize)
.map(|entry| entry.1.clone())
.unwrap_or_else(|| self.default_style.clone())
}
#[cfg(test)]
@@ -167,12 +173,28 @@ impl SyntaxTheme {
impl Default for EditorStyle {
fn default() -> Self {
Self {
text: HighlightStyle {
color: Color::from_u32(0xff0000ff),
font_properties: Default::default(),
},
background: Default::default(),
gutter_background: Default::default(),
active_line_background: Default::default(),
line_number: Default::default(),
line_number_active: Default::default(),
replicas: vec![Default::default()],
selection: Default::default(),
guest_selections: Default::default(),
}
}
}
impl InputEditorStyle {
pub fn as_editor(&self) -> EditorStyle {
EditorStyle {
text: self.text.clone(),
background: self.background,
selection: self.selection,
..Default::default()
}
}
}
@@ -182,16 +204,9 @@ impl<'de> Deserialize<'de> for SyntaxTheme {
where
D: serde::Deserializer<'de>,
{
let mut syntax_data: HashMap<String, HighlightStyle> =
Deserialize::deserialize(deserializer)?;
let mut result = Self {
highlights: Vec::<(String, HighlightStyle)>::new(),
default_style: syntax_data
.remove("default")
.ok_or_else(|| de::Error::custom("must specify a default color in syntax theme"))?,
};
let syntax_data: HashMap<String, HighlightStyle> = Deserialize::deserialize(deserializer)?;
let mut result = Self::new(Vec::new());
for (key, style) in syntax_data {
match result
.highlights
-1
View File
@@ -69,7 +69,6 @@ mod tests {
#[test]
fn test_highlight_map() {
let theme = SyntaxTheme::new(
Default::default(),
[
("function", Color::from_u32(0x100000ff)),
("function.method", Color::from_u32(0x200000ff)),
+13 -7
View File
@@ -25,7 +25,7 @@ pub struct ThemeSelector {
settings: watch::Receiver<Settings>,
registry: Arc<ThemeRegistry>,
matches: Vec<StringMatch>,
query_buffer: ViewHandle<Editor>,
query_editor: ViewHandle<Editor>,
list_state: UniformListState,
selected_index: usize,
}
@@ -60,15 +60,21 @@ impl ThemeSelector {
registry: Arc<ThemeRegistry>,
cx: &mut ViewContext<Self>,
) -> Self {
let query_buffer = cx.add_view(|cx| Editor::single_line(settings.clone(), cx));
cx.subscribe(&query_buffer, Self::on_query_editor_event)
let query_editor = cx.add_view(|cx| {
Editor::single_line(settings.clone(), cx).with_style({
let settings = settings.clone();
move |_| settings.borrow().theme.selector.input_editor.as_editor()
})
});
cx.subscribe(&query_editor, Self::on_query_editor_event)
.detach();
let mut this = Self {
settings,
settings_tx,
registry,
query_buffer,
query_editor,
matches: Vec::new(),
list_state: Default::default(),
selected_index: 0,
@@ -151,7 +157,7 @@ impl ThemeSelector {
string: name,
})
.collect::<Vec<_>>();
let query = self.query_buffer.update(cx, |buffer, cx| buffer.text(cx));
let query = self.query_editor.update(cx, |buffer, cx| buffer.text(cx));
self.matches = if query.is_empty() {
candidates
@@ -276,7 +282,7 @@ impl View for ThemeSelector {
ConstrainedBox::new(
Container::new(
Flex::new(Axis::Vertical)
.with_child(ChildView::new(self.query_buffer.id()).boxed())
.with_child(ChildView::new(self.query_editor.id()).boxed())
.with_child(Expanded::new(1.0, self.render_matches(cx)).boxed())
.boxed(),
)
@@ -292,7 +298,7 @@ impl View for ThemeSelector {
}
fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
cx.focus(&self.query_buffer);
cx.focus(&self.query_editor);
}
fn keymap_context(&self, _: &AppContext) -> keymap::Context {