From 522bef2e3ae7ca9a3e1f70dbbc6af79c44e2ba7e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 2 Sep 2021 17:36:56 -0700 Subject: [PATCH] Add placeholder text as a feature of Editor, use it in chat panel --- gpui/src/fonts.rs | 2 +- zed/assets/themes/_base.toml | 1 + zed/src/chat_panel.rs | 9 +++++++- zed/src/editor.rs | 41 +++++++++++++++++++++++++++++++++++ zed/src/editor/display_map.rs | 4 ++++ zed/src/theme.rs | 8 +++++++ 6 files changed, 63 insertions(+), 2 deletions(-) diff --git a/gpui/src/fonts.rs b/gpui/src/fonts.rs index 450d0ac398b1c7f07d22ebb4a5b71f44a50a6bf3..3010e1ada054a0500734f78c402a81f64201a38a 100644 --- a/gpui/src/fonts.rs +++ b/gpui/src/fonts.rs @@ -26,7 +26,7 @@ pub struct TextStyle { pub font_properties: Properties, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct HighlightStyle { pub color: Color, pub font_properties: Properties, diff --git a/zed/assets/themes/_base.toml b/zed/assets/themes/_base.toml index f4b7be73d500db77b6cf45dd17fc02f8711ba738..1beab95ce749eb89a30808a12f384654da20c571 100644 --- a/zed/assets/themes/_base.toml +++ b/zed/assets/themes/_base.toml @@ -67,6 +67,7 @@ background = "$surface.0" [chat_panel.input_editor] text = "$text.1.color" +placeholder_text = "$text.2.color" background = "$surface.1" selection = "$selection.host" diff --git a/zed/src/chat_panel.rs b/zed/src/chat_panel.rs index dd2a3765108ae43a289bc468f264d7a53ab39353..8c6b85bbf1695f3de21ae3b772656eb2bffcec3a 100644 --- a/zed/src/chat_panel.rs +++ b/zed/src/chat_panel.rs @@ -156,7 +156,14 @@ impl ChatPanel { fn set_active_channel(&mut self, channel: ModelHandle, cx: &mut ViewContext) { if self.active_channel.as_ref().map(|e| &e.0) != Some(&channel) { - self.message_list.reset(channel.read(cx).message_count()); + { + let channel = channel.read(cx); + self.message_list.reset(channel.message_count()); + let placeholder = format!("Message #{}", channel.name()); + self.input_editor.update(cx, move |editor, cx| { + editor.set_placeholder_text(placeholder, cx); + }); + } let subscription = cx.subscribe(&channel, Self::channel_did_change); self.active_channel = Some((channel, subscription)); } diff --git a/zed/src/editor.rs b/zed/src/editor.rs index 148b38eb0a15ca12308bf91a61a43743727deef9..b8c9601fe26a371e63f4d2247fd9a02382d3ca86 100644 --- a/zed/src/editor.rs +++ b/zed/src/editor.rs @@ -295,15 +295,18 @@ pub struct Editor { blink_epoch: usize, blinking_paused: bool, mode: EditorMode, + placeholder_text: Option>, } pub struct Snapshot { pub display_snapshot: DisplayMapSnapshot, + pub placeholder_text: Option>, pub gutter_visible: bool, pub auto_height: bool, pub theme: Arc, pub font_family: FamilyId, pub font_size: f32, + is_focused: bool, scroll_position: Vector2F, scroll_top_anchor: Anchor, } @@ -378,6 +381,7 @@ impl Editor { blink_epoch: 0, blinking_paused: false, mode: EditorMode::Full, + placeholder_text: None, } } @@ -407,11 +411,25 @@ impl Editor { scroll_position: self.scroll_position, scroll_top_anchor: self.scroll_top_anchor.clone(), theme: settings.theme.clone(), + placeholder_text: self.placeholder_text.clone(), font_family: settings.buffer_font_family, font_size: settings.buffer_font_size, + is_focused: self + .handle + .upgrade(cx) + .map_or(false, |handle| handle.is_focused(cx)), } } + pub fn set_placeholder_text( + &mut self, + placeholder_text: impl Into>, + cx: &mut ViewContext, + ) { + self.placeholder_text = Some(placeholder_text.into()); + cx.notify(); + } + fn set_scroll_position(&mut self, mut scroll_position: Vector2F, cx: &mut ViewContext) { let map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let scroll_top_buffer_offset = @@ -2406,6 +2424,29 @@ impl Snapshot { return Ok(Vec::new()); } + // When the editor is empty and unfocused, then show the placeholder. + if self.display_snapshot.is_empty() && !self.is_focused { + let placeholder_lines = self + .placeholder_text + .as_ref() + .map_or("", AsRef::as_ref) + .split('\n') + .skip(rows.start as usize) + .take(rows.len()); + let font_id = font_cache + .select_font(self.font_family, &style.placeholder_text.font_properties)?; + return Ok(placeholder_lines + .into_iter() + .map(|line| { + layout_cache.layout_str( + line, + self.font_size, + &[(line.len(), font_id, style.placeholder_text.color)], + ) + }) + .collect()); + } + let mut prev_font_properties = FontProperties::new(); let mut prev_font_id = font_cache .select_font(self.font_family, &prev_font_properties) diff --git a/zed/src/editor/display_map.rs b/zed/src/editor/display_map.rs index 16eeba2e12ee375d852c3bccac8559c700862c07..425c4b97a5ec908f1a109b2fa6b63b27e5076b9b 100644 --- a/zed/src/editor/display_map.rs +++ b/zed/src/editor/display_map.rs @@ -108,6 +108,10 @@ impl DisplayMapSnapshot { self.folds_snapshot.fold_count() } + pub fn is_empty(&self) -> bool { + self.buffer_snapshot.len() == 0 + } + pub fn buffer_rows(&self, start_row: u32) -> BufferRows { self.wraps_snapshot.buffer_rows(start_row) } diff --git a/zed/src/theme.rs b/zed/src/theme.rs index ee39681459713d1cf7a5547a2ddc25201d6624a9..dcbec3ff2da3bdba4bbb904d4136e9e676a8544c 100644 --- a/zed/src/theme.rs +++ b/zed/src/theme.rs @@ -131,6 +131,8 @@ pub struct ContainedLabel { #[derive(Clone, Deserialize)] pub struct EditorStyle { pub text: HighlightStyle, + #[serde(default)] + pub placeholder_text: HighlightStyle, pub background: Color, pub selection: SelectionStyle, pub gutter_background: Color, @@ -143,6 +145,7 @@ pub struct EditorStyle { #[derive(Clone, Deserialize)] pub struct InputEditorStyle { pub text: HighlightStyle, + pub placeholder_text: HighlightStyle, pub background: Color, pub selection: SelectionStyle, } @@ -177,6 +180,10 @@ impl Default for EditorStyle { color: Color::from_u32(0xff0000ff), font_properties: Default::default(), }, + placeholder_text: HighlightStyle { + color: Color::from_u32(0x00ff00ff), + font_properties: Default::default(), + }, background: Default::default(), gutter_background: Default::default(), active_line_background: Default::default(), @@ -192,6 +199,7 @@ impl InputEditorStyle { pub fn as_editor(&self) -> EditorStyle { EditorStyle { text: self.text.clone(), + placeholder_text: self.placeholder_text.clone(), background: self.background, selection: self.selection, ..Default::default()