From cfc050e3fe2cd795941e50a246006834af372fc3 Mon Sep 17 00:00:00 2001 From: Julia Date: Wed, 13 Dec 2023 12:16:39 -0500 Subject: [PATCH 001/644] Fire focus handlers on draw to avoid timing with newly created item Co-Authored-By: Antonio Scandurra --- crates/gpui2/src/app.rs | 68 ++------------- crates/gpui2/src/elements/div.rs | 13 +-- crates/gpui2/src/interactive.rs | 8 +- crates/gpui2/src/key_dispatch.rs | 20 ++++- crates/gpui2/src/window.rs | 137 ++++++++++++------------------- 5 files changed, 84 insertions(+), 162 deletions(-) diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 62ce6305ea..9b9a5921e1 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -17,11 +17,10 @@ use time::UtcOffset; use crate::{ current_platform, image_cache::ImageCache, init_app_menus, Action, ActionRegistry, Any, AnyView, AnyWindowHandle, AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, - DispatchPhase, DisplayId, Entity, EventEmitter, FocusEvent, FocusHandle, FocusId, - ForegroundExecutor, KeyBinding, Keymap, Keystroke, LayoutId, Menu, PathPromptOptions, Pixels, - Platform, PlatformDisplay, Point, Render, SharedString, SubscriberSet, Subscription, - SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, ViewContext, Window, - WindowContext, WindowHandle, WindowId, + DispatchPhase, DisplayId, Entity, EventEmitter, ForegroundExecutor, KeyBinding, Keymap, + Keystroke, LayoutId, Menu, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render, + SharedString, SubscriberSet, Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, + TextSystem, View, ViewContext, Window, WindowContext, WindowHandle, WindowId, }; use anyhow::{anyhow, Result}; use collections::{FxHashMap, FxHashSet, VecDeque}; @@ -577,23 +576,21 @@ impl AppContext { Effect::Notify { emitter } => { self.apply_notify_effect(emitter); } + Effect::Emit { emitter, event_type, event, } => self.apply_emit_effect(emitter, event_type, event), - Effect::FocusChanged { - window_handle, - focused, - } => { - self.apply_focus_changed_effect(window_handle, focused); - } + Effect::Refresh => { self.apply_refresh_effect(); } + Effect::NotifyGlobalObservers { global_type } => { self.apply_notify_global_observers_effect(global_type); } + Effect::Defer { callback } => { self.apply_defer_effect(callback); } @@ -693,51 +690,6 @@ impl AppContext { }); } - fn apply_focus_changed_effect( - &mut self, - window_handle: AnyWindowHandle, - focused: Option, - ) { - window_handle - .update(self, |_, cx| { - // The window might change focus multiple times in an effect cycle. - // We only honor effects for the most recently focused handle. - if cx.window.focus == focused { - // if someone calls focus multiple times in one frame with the same handle - // the first apply_focus_changed_effect will have taken the last blur already - // and run the rest of this, so we can return. - let Some(last_blur) = cx.window.last_blur.take() else { - return; - }; - - let focused = focused - .map(|id| FocusHandle::for_id(id, &cx.window.focus_handles).unwrap()); - - let blurred = - last_blur.and_then(|id| FocusHandle::for_id(id, &cx.window.focus_handles)); - - let focus_changed = focused.is_some() || blurred.is_some(); - let event = FocusEvent { focused, blurred }; - - let mut listeners = mem::take(&mut cx.window.rendered_frame.focus_listeners); - if focus_changed { - for listener in &mut listeners { - listener(&event, cx); - } - } - cx.window.rendered_frame.focus_listeners = listeners; - - if focus_changed { - cx.window - .focus_listeners - .clone() - .retain(&(), |listener| listener(&event, cx)); - } - } - }) - .ok(); - } - fn apply_refresh_effect(&mut self) { for window in self.windows.values_mut() { if let Some(window) = window.as_mut() { @@ -1246,10 +1198,6 @@ pub(crate) enum Effect { event_type: TypeId, event: Box, }, - FocusChanged { - window_handle: AnyWindowHandle, - focused: Option, - }, Refresh, NotifyGlobalObservers { global_type: TypeId, diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index a102c71a6f..3ec0a46fcb 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1,10 +1,9 @@ use crate::{ point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext, - BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusEvent, FocusHandle, - IntoElement, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, - MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent, - SharedString, Size, StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility, - WindowContext, + BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusHandle, IntoElement, + KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, + MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, + StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility, WindowContext, }; use collections::HashMap; use refineable::Refineable; @@ -462,10 +461,6 @@ pub trait FocusableElement: InteractiveElement { } } -pub type FocusListeners = Vec; - -pub type FocusListener = Box; - pub type MouseDownListener = Box; pub type MouseUpListener = diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index 1c6955111c..58ee849aad 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -1,6 +1,5 @@ use crate::{ - div, point, Div, Element, FocusHandle, IntoElement, Keystroke, Modifiers, Pixels, Point, - Render, ViewContext, + div, point, Div, Element, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, ViewContext, }; use smallvec::SmallVec; use std::{any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf}; @@ -290,11 +289,6 @@ impl InputEvent { } } -pub struct FocusEvent { - pub blurred: Option, - pub focused: Option, -} - #[cfg(test)] mod test { use crate::{ diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index a44987aa39..ddb1f1e6ca 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -29,6 +29,7 @@ pub(crate) struct DispatchNode { pub key_listeners: Vec, pub action_listeners: Vec, pub context: Option, + focus_id: Option, parent: Option, } @@ -127,8 +128,9 @@ impl DispatchTree { } pub fn make_focusable(&mut self, focus_id: FocusId) { - self.focusable_node_ids - .insert(focus_id, self.active_node_id()); + let node_id = self.active_node_id(); + self.active_node().focus_id = Some(focus_id); + self.focusable_node_ids.insert(focus_id, node_id); } pub fn focus_contains(&self, parent: FocusId, child: FocusId) -> bool { @@ -247,6 +249,20 @@ impl DispatchTree { dispatch_path } + pub fn focus_path(&self, focus_id: FocusId) -> SmallVec<[FocusId; 8]> { + let mut focus_path: SmallVec<[FocusId; 8]> = SmallVec::new(); + let mut current_node_id = self.focusable_node_ids.get(&focus_id).copied(); + while let Some(node_id) = current_node_id { + let node = self.node(node_id); + if let Some(focus_id) = node.focus_id { + focus_path.push(focus_id); + } + current_node_id = node.parent; + } + focus_path.reverse(); // Reverse the path so it goes from the root to the focused node. + focus_path + } + pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode { &self.nodes[node_id.0] } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 77eb4e27be..d2f4891711 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -2,10 +2,10 @@ use crate::{ key_dispatch::DispatchActionListener, px, size, Action, AnyDrag, AnyView, AppContext, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, - EventEmitter, FileDropEvent, Flatten, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, - ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeystrokeEvent, LayoutId, - Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent, - Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, + EventEmitter, FileDropEvent, Flatten, FontId, GlobalElementId, GlyphId, Hsla, ImageData, + InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeystrokeEvent, LayoutId, Model, + ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent, Path, + Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, Scene, SceneBuilder, Shadow, SharedString, Size, Style, SubscriberSet, Subscription, Surface, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, @@ -74,9 +74,13 @@ impl DispatchPhase { type AnyObserver = Box bool + 'static>; type AnyMouseListener = Box; -type AnyFocusListener = Box; type AnyWindowFocusListener = Box bool + 'static>; +struct FocusEvent { + previous_focus_path: SmallVec<[FocusId; 8]>, + current_focus_path: SmallVec<[FocusId; 8]>, +} + slotmap::new_key_type! { pub struct FocusId; } impl FocusId { @@ -227,8 +231,8 @@ pub struct Window { pub(crate) rendered_frame: Frame, pub(crate) next_frame: Frame, pub(crate) focus_handles: Arc>>, - pub(crate) focus_listeners: SubscriberSet<(), AnyWindowFocusListener>, - pub(crate) blur_listeners: SubscriberSet<(), AnyObserver>, + focus_listeners: SubscriberSet<(), AnyWindowFocusListener>, + blur_listeners: SubscriberSet<(), AnyObserver>, default_prevented: bool, mouse_position: Point, requested_cursor_style: Option, @@ -238,7 +242,6 @@ pub struct Window { active: bool, pub(crate) dirty: bool, activation_observers: SubscriberSet<(), AnyObserver>, - pub(crate) last_blur: Option>, pub(crate) focus: Option, } @@ -250,10 +253,10 @@ pub(crate) struct ElementStateBox { // #[derive(Default)] pub(crate) struct Frame { + focus: Option, pub(crate) element_states: HashMap, mouse_listeners: HashMap>, pub(crate) dispatch_tree: DispatchTree, - pub(crate) focus_listeners: Vec, pub(crate) scene_builder: SceneBuilder, pub(crate) depth_map: Vec<(StackingOrder, Bounds)>, pub(crate) z_index_stack: StackingOrder, @@ -264,10 +267,10 @@ pub(crate) struct Frame { impl Frame { fn new(dispatch_tree: DispatchTree) -> Self { Frame { + focus: None, element_states: HashMap::default(), mouse_listeners: HashMap::default(), dispatch_tree, - focus_listeners: Vec::new(), scene_builder: SceneBuilder::default(), z_index_stack: StackingOrder::default(), depth_map: Default::default(), @@ -279,10 +282,15 @@ impl Frame { fn clear(&mut self) { self.element_states.clear(); self.mouse_listeners.values_mut().for_each(Vec::clear); - self.focus_listeners.clear(); self.dispatch_tree.clear(); self.depth_map.clear(); } + + fn focus_path(&self) -> SmallVec<[FocusId; 8]> { + self.focus + .map(|focus_id| self.dispatch_tree.focus_path(focus_id)) + .unwrap_or_default() + } } impl Window { @@ -372,7 +380,6 @@ impl Window { active: false, dirty: false, activation_observers: SubscriberSet::new(), - last_blur: None, focus: None, } } @@ -449,35 +456,17 @@ impl<'a> WindowContext<'a> { return; } - let focus_id = handle.id; - - if self.window.last_blur.is_none() { - self.window.last_blur = Some(self.window.focus); - } - - self.window.focus = Some(focus_id); + self.window.focus = Some(handle.id); self.window .rendered_frame .dispatch_tree .clear_pending_keystrokes(); - self.app.push_effect(Effect::FocusChanged { - window_handle: self.window.handle, - focused: Some(focus_id), - }); self.notify(); } /// Remove focus from all elements within this context's window. pub fn blur(&mut self) { - if self.window.last_blur.is_none() { - self.window.last_blur = Some(self.window.focus); - } - self.window.focus = None; - self.app.push_effect(Effect::FocusChanged { - window_handle: self.window.handle, - focused: None, - }); self.notify(); } @@ -1236,16 +1225,6 @@ impl<'a> WindowContext<'a> { /// Draw pixels to the display for this window based on the contents of its scene. pub(crate) fn draw(&mut self) -> Scene { - let window_was_focused = self - .window - .focus - .and_then(|focus_id| { - self.window - .rendered_frame - .dispatch_tree - .focusable_node_id(focus_id) - }) - .is_some(); self.text_system().start_frame(); self.window.platform_window.clear_input_handler(); self.window.layout_engine.as_mut().unwrap().clear(); @@ -1284,23 +1263,6 @@ impl<'a> WindowContext<'a> { }); } - let window_is_focused = self - .window - .focus - .and_then(|focus_id| { - self.window - .next_frame - .dispatch_tree - .focusable_node_id(focus_id) - }) - .is_some(); - if window_was_focused && !window_is_focused { - self.window - .blur_listeners - .clone() - .retain(&(), |listener| listener(self)); - } - self.window .next_frame .dispatch_tree @@ -1308,11 +1270,34 @@ impl<'a> WindowContext<'a> { &mut self.window.rendered_frame.dispatch_tree, self.window.focus, ); + self.window.next_frame.focus = self.window.focus; self.window.root_view = Some(root_view); + let previous_focus_path = self.window.rendered_frame.focus_path(); + let window = &mut self.window; mem::swap(&mut window.rendered_frame, &mut window.next_frame); + let current_focus_path = self.window.rendered_frame.focus_path(); + + if previous_focus_path != current_focus_path { + if !previous_focus_path.is_empty() && current_focus_path.is_empty() { + self.window + .blur_listeners + .clone() + .retain(&(), |listener| listener(self)); + } + + let event = FocusEvent { + previous_focus_path, + current_focus_path, + }; + self.window + .focus_listeners + .clone() + .retain(&(), |listener| listener(&event, self)); + } + let scene = self.window.rendered_frame.scene_builder.build(); // Set the cursor only if we're the active window. @@ -1699,22 +1684,6 @@ impl<'a> WindowContext<'a> { result } - /// Register a focus listener for the next frame only. It will be cleared - /// on the next frame render. You should use this method only from within elements, - /// and we may want to enforce that better via a different context type. - // todo!() Move this to `FrameContext` to emphasize its individuality? - pub fn on_focus_changed( - &mut self, - listener: impl Fn(&FocusEvent, &mut WindowContext) + 'static, - ) { - self.window - .next_frame - .focus_listeners - .push(Box::new(move |event, cx| { - listener(event, cx); - })); - } - /// Set an input handler, such as [ElementInputHandler], which interfaces with the /// platform to receive textual input with proper integration with concerns such /// as IME interactions. @@ -2389,7 +2358,9 @@ impl<'a, V: 'static> ViewContext<'a, V> { (), Box::new(move |event, cx| { view.update(cx, |view, cx| { - if event.focused.as_ref().map(|focused| focused.id) == Some(focus_id) { + if event.previous_focus_path.last() != Some(&focus_id) + && event.current_focus_path.last() == Some(&focus_id) + { listener(view, cx) } }) @@ -2414,10 +2385,8 @@ impl<'a, V: 'static> ViewContext<'a, V> { (), Box::new(move |event, cx| { view.update(cx, |view, cx| { - if event - .focused - .as_ref() - .map_or(false, |focused| focus_id.contains(focused.id, cx)) + if !event.previous_focus_path.contains(&focus_id) + && event.current_focus_path.contains(&focus_id) { listener(view, cx) } @@ -2443,7 +2412,9 @@ impl<'a, V: 'static> ViewContext<'a, V> { (), Box::new(move |event, cx| { view.update(cx, |view, cx| { - if event.blurred.as_ref().map(|blurred| blurred.id) == Some(focus_id) { + if event.previous_focus_path.last() == Some(&focus_id) + && event.current_focus_path.last() != Some(&focus_id) + { listener(view, cx) } }) @@ -2484,10 +2455,8 @@ impl<'a, V: 'static> ViewContext<'a, V> { (), Box::new(move |event, cx| { view.update(cx, |view, cx| { - if event - .blurred - .as_ref() - .map_or(false, |blurred| focus_id.contains(blurred.id, cx)) + if event.previous_focus_path.contains(&focus_id) + && !event.current_focus_path.contains(&focus_id) { listener(view, cx) } From 0e19da3107657fcdda07aa7145611a1f762dd126 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 13 Dec 2023 12:53:53 +0100 Subject: [PATCH 002/644] Bring back semantic search UI --- crates/search2/src/project_search.rs | 340 ++++++++++----------------- 1 file changed, 128 insertions(+), 212 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 34cd2b9814..875d2fe095 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -1,7 +1,8 @@ use crate::{ - history::SearchHistory, mode::SearchMode, ActivateRegexMode, ActivateTextMode, CycleMode, - NextHistoryQuery, PreviousHistoryQuery, ReplaceAll, ReplaceNext, SearchOptions, - SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleReplace, ToggleWholeWord, + history::SearchHistory, mode::SearchMode, ActivateRegexMode, ActivateSemanticMode, + ActivateTextMode, CycleMode, NextHistoryQuery, PreviousHistoryQuery, ReplaceAll, ReplaceNext, + SearchOptions, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleReplace, + ToggleWholeWord, }; use anyhow::{Context as _, Result}; use collections::HashMap; @@ -29,7 +30,7 @@ use std::{ mem, ops::{Not, Range}, path::PathBuf, - time::Duration, + time::{Duration, Instant}, }; use ui::{ @@ -283,196 +284,86 @@ impl Render for ProjectSearchView { let model = self.model.read(cx); let has_no_results = model.no_results.unwrap_or(false); let is_search_underway = model.pending_search.is_some(); - let major_text = if is_search_underway { + let mut major_text = if is_search_underway { Label::new("Searching...") } else if has_no_results { - Label::new("No results for a given query") + Label::new("No results") } else { Label::new(format!("{} search all files", self.current_mode.label())) }; + + let mut show_minor_text = true; + let semantic_status = self.semantic_state.as_ref().and_then(|semantic| { + let status = semantic.index_status; + match status { + SemanticIndexStatus::NotAuthenticated => { + major_text = Label::new("Not Authenticated"); + show_minor_text = false; + Some( + "API Key Missing: Please set 'OPENAI_API_KEY' in Environment Variables. If you authenticated using the Assistant Panel, please restart Zed to Authenticate.".to_string()) + } + SemanticIndexStatus::Indexed => Some("Indexing complete".to_string()), + SemanticIndexStatus::Indexing { + remaining_files, + rate_limit_expiry, + } => { + if remaining_files == 0 { + Some("Indexing...".to_string()) + } else { + if let Some(rate_limit_expiry) = rate_limit_expiry { + let remaining_seconds = + rate_limit_expiry.duration_since(Instant::now()); + if remaining_seconds > Duration::from_secs(0) { + Some(format!( + "Remaining files to index (rate limit resets in {}s): {}", + remaining_seconds.as_secs(), + remaining_files + )) + } else { + Some(format!("Remaining files to index: {}", remaining_files)) + } + } else { + Some(format!("Remaining files to index: {}", remaining_files)) + } + } + } + SemanticIndexStatus::NotIndexed => None, + } + }); let major_text = div().justify_center().max_w_96().child(major_text); - let middle_text = div() - .items_center() - .max_w_96() - .child(Label::new(self.landing_text_minor()).size(LabelSize::Small)); + + let minor_text: Option = if let Some(no_results) = model.no_results { + if model.pending_search.is_none() && no_results { + Some("No results found in this project for the provided query".into()) + } else { + None + } + } else { + if let Some(mut semantic_status) = semantic_status { + semantic_status.extend(self.landing_text_minor().chars()); + Some(semantic_status.into()) + } else { + Some(self.landing_text_minor()) + } + }; + let minor_text = minor_text.map(|text| { + div() + .items_center() + .max_w_96() + .child(Label::new(text).size(LabelSize::Small)) + }); v_stack().flex_1().size_full().justify_center().child( h_stack() .size_full() .justify_center() .child(h_stack().flex_1()) - .child(v_stack().child(major_text).child(middle_text)) + .child(v_stack().child(major_text).children(minor_text)) .child(h_stack().flex_1()), ) } } } -// impl Entity for ProjectSearchView { -// type Event = ViewEvent; -// } - -// impl View for ProjectSearchView { -// fn ui_name() -> &'static str { -// "ProjectSearchView" -// } - -// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { -// let model = &self.model.read(cx); -// if model.match_ranges.is_empty() { -// enum Status {} - -// let theme = theme::current(cx).clone(); - -// // If Search is Active -> Major: Searching..., Minor: None -// // If Semantic -> Major: "Search using Natural Language", Minor: {Status}/n{ex...}/n{ex...} -// // If Regex -> Major: "Search using Regex", Minor: {ex...} -// // If Text -> Major: "Text search all files and folders", Minor: {...} - -// let current_mode = self.current_mode; -// let mut major_text = if model.pending_search.is_some() { -// Cow::Borrowed("Searching...") -// } else if model.no_results.is_some_and(|v| v) { -// Cow::Borrowed("No Results") -// } else { -// match current_mode { -// SearchMode::Text => Cow::Borrowed("Text search all files and folders"), -// SearchMode::Semantic => { -// Cow::Borrowed("Search all code objects using Natural Language") -// } -// SearchMode::Regex => Cow::Borrowed("Regex search all files and folders"), -// } -// }; - -// let mut show_minor_text = true; -// let semantic_status = self.semantic_state.as_ref().and_then(|semantic| { -// let status = semantic.index_status; -// match status { -// SemanticIndexStatus::NotAuthenticated => { -// major_text = Cow::Borrowed("Not Authenticated"); -// show_minor_text = false; -// Some(vec![ -// "API Key Missing: Please set 'OPENAI_API_KEY' in Environment Variables." -// .to_string(), "If you authenticated using the Assistant Panel, please restart Zed to Authenticate.".to_string()]) -// } -// SemanticIndexStatus::Indexed => Some(vec!["Indexing complete".to_string()]), -// SemanticIndexStatus::Indexing { -// remaining_files, -// rate_limit_expiry, -// } => { -// if remaining_files == 0 { -// Some(vec![format!("Indexing...")]) -// } else { -// if let Some(rate_limit_expiry) = rate_limit_expiry { -// let remaining_seconds = -// rate_limit_expiry.duration_since(Instant::now()); -// if remaining_seconds > Duration::from_secs(0) { -// Some(vec![format!( -// "Remaining files to index (rate limit resets in {}s): {}", -// remaining_seconds.as_secs(), -// remaining_files -// )]) -// } else { -// Some(vec![format!("Remaining files to index: {}", remaining_files)]) -// } -// } else { -// Some(vec![format!("Remaining files to index: {}", remaining_files)]) -// } -// } -// } -// SemanticIndexStatus::NotIndexed => None, -// } -// }); - -// let minor_text = if let Some(no_results) = model.no_results { -// if model.pending_search.is_none() && no_results { -// vec!["No results found in this project for the provided query".to_owned()] -// } else { -// vec![] -// } -// } else { -// match current_mode { -// SearchMode::Semantic => { -// let mut minor_text: Vec = Vec::new(); -// minor_text.push("".into()); -// if let Some(semantic_status) = semantic_status { -// minor_text.extend(semantic_status); -// } -// if show_minor_text { -// minor_text -// .push("Simply explain the code you are looking to find.".into()); -// minor_text.push( -// "ex. 'prompt user for permissions to index their project'".into(), -// ); -// } -// minor_text -// } -// _ => vec![ -// "".to_owned(), -// "Include/exclude specific paths with the filter option.".to_owned(), -// "Matching exact word and/or casing is available too.".to_owned(), -// ], -// } -// }; - -// MouseEventHandler::new::(0, cx, |_, _| { -// Flex::column() -// .with_child(Flex::column().contained().flex(1., true)) -// .with_child( -// Flex::column() -// .align_children_center() -// .with_child(Label::new( -// major_text, -// theme.search.major_results_status.clone(), -// )) -// .with_children( -// minor_text.into_iter().map(|x| { -// Label::new(x, theme.search.minor_results_status.clone()) -// }), -// ) -// .aligned() -// .top() -// .contained() -// .flex(7., true), -// ) -// .contained() -// .with_background_color(theme.editor.background) -// }) -// .on_down(MouseButton::Left, |_, _, cx| { -// cx.focus_parent(); -// }) -// .into_any_named("project search view") -// } else { -// ChildView::new(&self.results_editor, cx) -// .flex(1., true) -// .into_any_named("project search view") -// } -// } - -// fn focus_in(&mut self, _: AnyView, cx: &mut ViewContext) { -// let handle = cx.weak_handle(); -// cx.update_global(|state: &mut ActiveSearches, cx| { -// state -// .0 -// .insert(self.model.read(cx).project.downgrade(), handle) -// }); - -// cx.update_global(|state: &mut ActiveSettings, cx| { -// state.0.insert( -// self.model.read(cx).project.downgrade(), -// self.current_settings(), -// ); -// }); - -// if cx.is_self_focused() { -// if self.query_editor_was_focused { -// cx.focus(&self.query_editor); -// } else { -// cx.focus(&self.results_editor); -// } -// } -// } -// } - impl FocusableView for ProjectSearchView { fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle { self.results_editor.focus_handle(cx) @@ -1256,7 +1147,7 @@ impl ProjectSearchView { fn landing_text_minor(&self) -> SharedString { match self.current_mode { SearchMode::Text | SearchMode::Regex => "Include/exclude specific paths with the filter option. Matching exact word and/or casing is available too.".into(), - SearchMode::Semantic => ".Simply explain the code you are looking to find. ex. 'prompt user for permissions to index their project'".into() + SearchMode::Semantic => "\nSimply explain the code you are looking to find. ex. 'prompt user for permissions to index their project'".into() } } } @@ -1277,8 +1168,8 @@ impl ProjectSearchBar { fn cycle_mode(&self, _: &CycleMode, cx: &mut ViewContext) { if let Some(view) = self.active_project_search.as_ref() { view.update(cx, |this, cx| { - // todo: po: 2nd argument of `next_mode` should be `SemanticIndex::enabled(cx))`, but we need to flesh out port of semantic_index first. - let new_mode = crate::mode::next_mode(&this.current_mode, false); + let new_mode = + crate::mode::next_mode(&this.current_mode, SemanticIndex::enabled(cx)); this.activate_search_mode(new_mode, cx); let editor_handle = this.query_editor.focus_handle(cx); cx.focus(&editor_handle); @@ -1548,7 +1439,7 @@ impl Render for ProjectSearchBar { }); } let search = search.read(cx); - + let semantic_is_available = SemanticIndex::enabled(cx); let query_column = v_stack() //.flex_1() .child( @@ -1578,42 +1469,51 @@ impl Render for ProjectSearchBar { .unwrap_or_default(), ), ) - .child( - IconButton::new( - "project-search-case-sensitive", - Icon::CaseSensitive, - ) - .tooltip(|cx| { - Tooltip::for_action( - "Toggle case sensitive", - &ToggleCaseSensitive, - cx, + .when(search.current_mode != SearchMode::Semantic, |this| { + this.child( + IconButton::new( + "project-search-case-sensitive", + Icon::CaseSensitive, ) - }) - .selected(self.is_option_enabled(SearchOptions::CASE_SENSITIVE, cx)) - .on_click(cx.listener( - |this, _, cx| { - this.toggle_search_option( - SearchOptions::CASE_SENSITIVE, - cx, - ); - }, - )), - ) - .child( - IconButton::new("project-search-whole-word", Icon::WholeWord) .tooltip(|cx| { Tooltip::for_action( - "Toggle whole word", - &ToggleWholeWord, + "Toggle case sensitive", + &ToggleCaseSensitive, cx, ) }) - .selected(self.is_option_enabled(SearchOptions::WHOLE_WORD, cx)) - .on_click(cx.listener(|this, _, cx| { - this.toggle_search_option(SearchOptions::WHOLE_WORD, cx); - })), - ), + .selected( + self.is_option_enabled(SearchOptions::CASE_SENSITIVE, cx), + ) + .on_click(cx.listener( + |this, _, cx| { + this.toggle_search_option( + SearchOptions::CASE_SENSITIVE, + cx, + ); + }, + )), + ) + .child( + IconButton::new("project-search-whole-word", Icon::WholeWord) + .tooltip(|cx| { + Tooltip::for_action( + "Toggle whole word", + &ToggleWholeWord, + cx, + ) + }) + .selected( + self.is_option_enabled(SearchOptions::WHOLE_WORD, cx), + ) + .on_click(cx.listener(|this, _, cx| { + this.toggle_search_option( + SearchOptions::WHOLE_WORD, + cx, + ); + })), + ) + }), ) .border_2() .bg(white()) @@ -1668,7 +1568,23 @@ impl Render for ProjectSearchBar { cx, ) }), - ), + ) + .when(semantic_is_available, |this| { + this.child( + Button::new("project-search-semantic-button", "Semantic") + .selected(search.current_mode == SearchMode::Semantic) + .on_click(cx.listener(|this, _, cx| { + this.activate_search_mode(SearchMode::Semantic, cx) + })) + .tooltip(|cx| { + Tooltip::for_action( + "Toggle semantic search", + &ActivateSemanticMode, + cx, + ) + }), + ) + }), ) .child( IconButton::new("project-search-toggle-replace", Icon::Replace) From ce1489f5dcb6471216d7a66924f880333afdddf4 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 13 Dec 2023 14:22:29 +0100 Subject: [PATCH 003/644] Add inclusion of ignored files --- crates/search2/src/project_search.rs | 75 ++++++++++++++++++---------- crates/search2/src/search.rs | 5 ++ 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 875d2fe095..f1b0c16d57 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -1,8 +1,8 @@ use crate::{ history::SearchHistory, mode::SearchMode, ActivateRegexMode, ActivateSemanticMode, ActivateTextMode, CycleMode, NextHistoryQuery, PreviousHistoryQuery, ReplaceAll, ReplaceNext, - SearchOptions, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleReplace, - ToggleWholeWord, + SearchOptions, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleIncludeIgnored, + ToggleReplace, ToggleWholeWord, }; use anyhow::{Context as _, Result}; use collections::HashMap; @@ -1530,7 +1530,22 @@ impl Render for ProjectSearchBar { .flex_1() .border_1() .mr_2() - .child(search.included_files_editor.clone()), + .child(search.included_files_editor.clone()) + .when(search.current_mode != SearchMode::Semantic, |this| { + this.child( + SearchOptions::INCLUDE_IGNORED.as_button( + search + .search_options + .contains(SearchOptions::INCLUDE_IGNORED), + cx.listener(|this, _, cx| { + this.toggle_search_option( + SearchOptions::INCLUDE_IGNORED, + cx, + ); + }), + ), + ) + }), ) .child( h_stack() @@ -1671,34 +1686,14 @@ impl Render for ProjectSearchBar { .on_action(cx.listener(|this, _: &ToggleFilters, cx| { this.toggle_filters(cx); })) - .on_action(cx.listener(|this, _: &ToggleWholeWord, cx| { - this.toggle_search_option(SearchOptions::WHOLE_WORD, cx); - })) - .on_action(cx.listener(|this, _: &ToggleCaseSensitive, cx| { - this.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx); - })) - .on_action(cx.listener(|this, action, cx| { - this.toggle_replace(action, cx); - })) .on_action(cx.listener(|this, _: &ActivateTextMode, cx| { this.activate_search_mode(SearchMode::Text, cx) })) .on_action(cx.listener(|this, _: &ActivateRegexMode, cx| { this.activate_search_mode(SearchMode::Regex, cx) })) - .on_action(cx.listener(|this, action, cx| { - if let Some(search) = this.active_project_search.as_ref() { - search.update(cx, |this, cx| { - this.replace_next(action, cx); - }) - } - })) - .on_action(cx.listener(|this, action, cx| { - if let Some(search) = this.active_project_search.as_ref() { - search.update(cx, |this, cx| { - this.replace_all(action, cx); - }) - } + .on_action(cx.listener(|this, _: &ActivateSemanticMode, cx| { + this.activate_search_mode(SearchMode::Semantic, cx) })) .on_action(cx.listener(|this, action, cx| { this.tab(action, cx); @@ -1709,6 +1704,36 @@ impl Render for ProjectSearchBar { .on_action(cx.listener(|this, action, cx| { this.cycle_mode(action, cx); })) + .when(search.current_mode != SearchMode::Semantic, |this| { + this.on_action(cx.listener(|this, action, cx| { + this.toggle_replace(action, cx); + })) + .on_action(cx.listener(|this, _: &ToggleWholeWord, cx| { + this.toggle_search_option(SearchOptions::WHOLE_WORD, cx); + })) + .on_action(cx.listener(|this, _: &ToggleCaseSensitive, cx| { + this.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx); + })) + .on_action(cx.listener(|this, action, cx| { + if let Some(search) = this.active_project_search.as_ref() { + search.update(cx, |this, cx| { + this.replace_next(action, cx); + }) + } + })) + .on_action(cx.listener(|this, action, cx| { + if let Some(search) = this.active_project_search.as_ref() { + search.update(cx, |this, cx| { + this.replace_all(action, cx); + }) + } + })) + .when(search.filters_enabled, |this| { + this.on_action(cx.listener(|this, _: &ToggleIncludeIgnored, cx| { + this.toggle_search_option(SearchOptions::INCLUDE_IGNORED, cx); + })) + }) + }) .child(query_column) .child(mode_column) .child(replace_column) diff --git a/crates/search2/src/search.rs b/crates/search2/src/search.rs index 015c126aa1..18fcc258f4 100644 --- a/crates/search2/src/search.rs +++ b/crates/search2/src/search.rs @@ -28,6 +28,7 @@ actions!( CycleMode, ToggleWholeWord, ToggleCaseSensitive, + ToggleIncludeIgnored, ToggleReplace, SelectNextMatch, SelectPrevMatch, @@ -57,6 +58,7 @@ impl SearchOptions { match *self { SearchOptions::WHOLE_WORD => "Match Whole Word", SearchOptions::CASE_SENSITIVE => "Match Case", + SearchOptions::INCLUDE_IGNORED => "Include ignored", _ => panic!("{:?} is not a named SearchOption", self), } } @@ -65,6 +67,7 @@ impl SearchOptions { match *self { SearchOptions::WHOLE_WORD => ui::Icon::WholeWord, SearchOptions::CASE_SENSITIVE => ui::Icon::CaseSensitive, + SearchOptions::INCLUDE_IGNORED => ui::Icon::FileGit, _ => panic!("{:?} is not a named SearchOption", self), } } @@ -73,6 +76,7 @@ impl SearchOptions { match *self { SearchOptions::WHOLE_WORD => Box::new(ToggleWholeWord), SearchOptions::CASE_SENSITIVE => Box::new(ToggleCaseSensitive), + SearchOptions::INCLUDE_IGNORED => Box::new(ToggleIncludeIgnored), _ => panic!("{:?} is not a named SearchOption", self), } } @@ -85,6 +89,7 @@ impl SearchOptions { let mut options = SearchOptions::NONE; options.set(SearchOptions::WHOLE_WORD, query.whole_word()); options.set(SearchOptions::CASE_SENSITIVE, query.case_sensitive()); + options.set(SearchOptions::INCLUDE_IGNORED, query.include_ignored()); options } From 85a1a8f777f4a8586d7adcd88863f6afeb086b2c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 11 Dec 2023 19:17:13 -0500 Subject: [PATCH 004/644] WIP --- docs/.gitignore | 2 + docs/book.toml | 6 + docs/src/CODE_OF_CONDUCT.md | 128 ++ docs/src/CONTRIBUTING.md | 3 + docs/src/SUMMARY.md | 18 + docs/src/configuring_zed.md | 1035 +++++++++++++++++ docs/src/configuring_zed__configuring_vim.md | 170 +++ docs/src/developing_zed__adding_languages.md | 83 ++ docs/src/developing_zed__building_zed.md | 107 ++ .../developing_zed__local_collaboration.md} | 0 docs/src/feedback.md | 29 + docs/src/getting_started.md | 15 + docs/src/system_requirements.md | 13 + docs/src/telemetry.md | 147 +++ {docs => docs_old}/backend-development.md | 0 {docs => docs_old}/building-zed.md | 0 {docs => docs_old}/company-and-vision.md | 0 {docs => docs_old}/design-tools.md | 0 {docs => docs_old}/index.md | 0 docs_old/local-collaboration.md | 22 + {docs => docs_old}/release-process.md | 0 .../theme/generating-theme-types.md | 0 {docs => docs_old}/tools.md | 0 {docs => docs_old}/zed/syntax-highlighting.md | 0 24 files changed, 1778 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/book.toml create mode 100644 docs/src/CODE_OF_CONDUCT.md create mode 100644 docs/src/CONTRIBUTING.md create mode 100644 docs/src/SUMMARY.md create mode 100644 docs/src/configuring_zed.md create mode 100644 docs/src/configuring_zed__configuring_vim.md create mode 100644 docs/src/developing_zed__adding_languages.md create mode 100644 docs/src/developing_zed__building_zed.md rename docs/{local-collaboration.md => src/developing_zed__local_collaboration.md} (100%) create mode 100644 docs/src/feedback.md create mode 100644 docs/src/getting_started.md create mode 100644 docs/src/system_requirements.md create mode 100644 docs/src/telemetry.md rename {docs => docs_old}/backend-development.md (100%) rename {docs => docs_old}/building-zed.md (100%) rename {docs => docs_old}/company-and-vision.md (100%) rename {docs => docs_old}/design-tools.md (100%) rename {docs => docs_old}/index.md (100%) create mode 100644 docs_old/local-collaboration.md rename {docs => docs_old}/release-process.md (100%) rename {docs => docs_old}/theme/generating-theme-types.md (100%) rename {docs => docs_old}/tools.md (100%) rename {docs => docs_old}/zed/syntax-highlighting.md (100%) diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000000..eed3a3e046 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +book +.vercel diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 0000000000..8062a76a42 --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,6 @@ +[book] +authors = ["Nate Butler"] +language = "en" +multilingual = false +src = "src" +title = "Zed App Docs" diff --git a/docs/src/CODE_OF_CONDUCT.md b/docs/src/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..bc1d5522a0 --- /dev/null +++ b/docs/src/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +hi@zed.dev. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/docs/src/CONTRIBUTING.md b/docs/src/CONTRIBUTING.md new file mode 100644 index 0000000000..d48c26844f --- /dev/null +++ b/docs/src/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing + +TBD diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md new file mode 100644 index 0000000000..4c6f5f9421 --- /dev/null +++ b/docs/src/SUMMARY.md @@ -0,0 +1,18 @@ +# Summary + +[Getting Started](./getting_started.md) +[Feedback](./feedback.md) + +# Configuring Zed +- [Settings](./configuring_zed.md) +- [Vim Mode](./configuring_zed__configuring_vim.md) + +# Developing Zed +- [Building from Source](./developing_zed__building_zed.md) +- [Local Collaboration](./developing_zed__local_collaboration.md) +- [Adding Languages](./developing_zed__adding_languages.md) + +# Other +- [Code of Conduct](./CODE_OF_CONDUCT.md) +- [Telemetry](./telemetry.md) +- [Contributing](./CONTRIBUTING.md) diff --git a/docs/src/configuring_zed.md b/docs/src/configuring_zed.md new file mode 100644 index 0000000000..9b9205f70c --- /dev/null +++ b/docs/src/configuring_zed.md @@ -0,0 +1,1035 @@ +# Configuring Zed + +## Folder-specific settings + +Folder-specific settings are used to override Zed's global settings for files within a specific directory in the project panel. To get started, create a `.zed` subdirectory and add a `settings.json` within it. It should be noted that folder-specific settings don't need to live only a project's root, but can be defined at multiple levels in the project hierarchy. In setups like this, Zed will find the configuration nearest to the file you are working in and apply those settings to it. In most cases, this level of flexibility won't be needed and a single configuration for all files in a project is all that is required; the `Zed > Settings > Open Local Settings` menu action is built for this case. Running this action will look for a `.zed/settings.json` file at the root of the first top-level directory in your project panel. If it does not exist, it will create it. + +The following global settings can be overriden with a folder-specific configuration: + +- `copilot` +- `enable_language_server` +- `ensure_final_newline_on_save` +- `format_on_save` +- `formatter` +- `hard_tabs` +- `language_overrides` +- `preferred_line_length` +- `remove_trailing_whitespace_on_save` +- `soft_wrap` +- `tab_size` +- `show_copilot_suggestions` +- `show_whitespaces` + +*See the Global settings section for details about these settings* + +## Global settings + +To get started with editing Zed's global settings, open `~/.config/zed/settings.json` via `cmd-,`, the command palette (`zed: open settings`), or the `Zed > Settings > Open Settings` application menu item. + +Here are all the currently available settings. + +## Active Pane Magnification + +- Description: Scale by which to zoom the active pane. When set to `1.0`, the active pane has the same size as others, but when set to a larger value, the active pane takes up more space. +- Setting: `active_pane_magnification` +- Default: `1.0` + +**Options** + +`float` values + +## Autosave + +- Description: When to automatically save edited buffers. +- Setting: `autosave` +- Default: `off` + +**Options** + +1. To disable autosave, set it to `off` + +```json +{ + "autosave": "off" +} +``` + +2. To autosave when focus changes, use `on_focus_change`: + +```json +{ + "autosave": "on_focus_change" +} +``` + +3. To autosave when the active window changes, use `on_window_change`: + +```json +{ + "autosave": "on_window_change" +} +``` + +4. To autosave after an inactivity period, use `after_delay`: + +```json +{ + "autosave": { + "after_delay": { + "milliseconds": 1000 + } + } +} +``` + +## Auto Update + +- Description: Whether or not to automatically check for updates. +- Setting: `auto_update` +- Default: `true` + +**Options** + +`boolean` values + +## Buffer Font Family + +- Description: The name of a font to use for rendering text in the editor. +- Setting: `buffer_font_family` +- Default: `Zed Mono` + +**Options** + +The name of any font family installed on the user's system + +## Buffer Font Features + +- Description: The OpenType features to enable for text in the editor. +- Setting: `buffer_font_features` +- Default: `null` + +**Options** + +Zed supports a subset of OpenType features that can be enabled or disabled for a given buffer or terminal font. The following [OpenType features](https://en.wikipedia.org/wiki/List_of_typographic_features) can be enabled or disabled too: `calt`, `case`, `cpsp`, `frac`, `liga`, `onum`, `ordn`, `pnum`, `ss01`, `ss02`, `ss03`, `ss04`, `ss05`, `ss06`, `ss07`, `ss08`, `ss09`, `ss10`, `ss11`, `ss12`, `ss13`, `ss14`, `ss15`, `ss16`, `ss17`, `ss18`, `ss19`, `ss20`, `subs`, `sups`, `swsh`, `titl`, `tnum`, `zero`. + +For example, to disable ligatures for a given font you can add the following to your settings: + +```json +{ + "buffer_font_features": { + "calt": false + } +} +``` + +## Buffer Font Size + +- Description: The default font size for text in the editor. +- Setting: `buffer_font_size` +- Default: `15` + +**Options** + +`integer` values + +## Confirm Quit + +- Description: Whether or not to prompt the user to confirm before closing the application. +- Setting: `confirm_quit` +- Default: `false` + +**Options** + +`boolean` values + +## Copilot + +- Description: Copilot-specific settings. +- Setting: `copilot` +- Default: + +```json +"copilot": { + "disabled_globs": [ + ".env" + ] +} +``` + +**Options** + +### Disabled Globs + +- Description: The set of glob patterns for which Copilot should be disabled in any matching file. +- Setting: `disabled_globs` +- Default: [".env"] + +**Options** + +List of `string` values + +## Cursor Blink + +- Description: Whether or not the cursor blinks. +- Setting: `cursor_blink` +- Default: `true` + +**Options** + +`boolean` values + +## Default Dock Anchor + +- Description: The default anchor for new docks. +- Setting: `default_dock_anchor` +- Default: `bottom` + +**Options** + +1. Position the dock attached to the bottom of the workspace: `bottom` +2. Position the dock to the right of the workspace like a side panel: `right` +3. Position the dock full screen over the entire workspace: `expanded` + +## Enable Language Server + +- Description: Whether or not to use language servers to provide code intelligence. +- Setting: `enable_language_server` +- Default: `true` + +**Options** + +`boolean` values + +## Ensure Final Newline On Save + +- Description: Whether or not to ensure there's a single newline at the end of a buffer when saving it. +- Setting: `ensure_final_newline_on_save` +- Default: `true` + +**Options** + +`boolean` values + +## LSP + +- Description: Configuration for language servers. +- Setting: `lsp` +- Default: `null` + +**Options** + +The following settings can be overridden for specific language servers: + +- `initialization_options` + +To override settings for a language, add an entry for that language server's name to the `lsp` value. Example: + +```json +"lsp": { + "rust-analyzer": { + "initialization_options": { + "checkOnSave": { + "command": "clippy" // rust-analyzer.checkOnSave.command + } + } + } +} +``` + +## Format On Save + +- Description: Whether or not to perform a buffer format before saving. +- Setting: `format_on_save` +- Default: `on` + +**Options** + +1. `on`, enables format on save obeying `formatter` setting: + +```json +{ + "format_on_save": "on" +} +``` + +2. `off`, disables format on save: + +```json +{ + "format_on_save": "off" +} +``` + +## Formatter + +- Description: How to perform a buffer format. +- Setting: `formatter` +- Default: `language_server` + +**Options** + +1. To use the current language server, use `"language_server"`: + +```json +{ + "formatter": "language_server" +} +``` + +2. Or to use an external command, use `"external"`. Specify the name of the formatting program to run, and an array of arguments to pass to the program. The buffer's text will be passed to the program on stdin, and the formatted output should be written to stdout. For example, the following command would strip trailing spaces using [`sed(1)`](https://linux.die.net/man/1/sed): + +```json +{ + "formatter": { + "external": { + "command": "sed", + "arguments": ["-e", "s/ *$//"] + } + } +} +``` + +## Git + +- Description: Configuration for git-related features. +- Setting: `git` +- Default: + +```json +"git": { + "git_gutter": "tracked_files" +}, +``` + +### Git Gutter + +- Description: Whether or not to show the git gutter. +- Setting: `git_gutter` +- Default: `tracked_files` + +**Options** + +1. Show git gutter in tracked files + +```json +{ + "git_gutter": "tracked_files" +} +``` + +2. Hide git gutter + +```json +{ + "git_gutter": "hide" +} +``` + +## Hard Tabs + +- Description: Whether to indent lines using tab characters or multiple spaces. +- Setting: `hard_tabs` +- Default: `false` + +**Options** + +`boolean` values + +## Hover Popover Enabled + +- Description: Whether or not to show the informational hover box when moving the mouse over symbols in the editor. +- Setting: `hover_popover_enabled` +- Default: `true` + +**Options** + +`boolean` values + +## Inlay hints + +- Description: Configuration for displaying extra text with hints in the editor. +- Setting: `inlay_hints` +- Default: + +```json +"inlay_hints": { + "enabled": false, + "show_type_hints": true, + "show_parameter_hints": true, + "show_other_hints": true +} +``` + +**Options** + +Inlay hints querying consists of two parts: editor (client) and LSP server. +With the inlay settings above are changed to enable the hints, editor will start to query certain types of hints and react on LSP hint refresh request from the server. +At this point, the server may or may not return hints depending on its implementation, further configuration might be needed, refer to the corresponding LSP server documentation. + +Use `lsp` section for the server configuration, below are some examples for well known servers: + +### Rust + +```json +"lsp": { + "rust-analyzer": { + "initialization_options": { + "inlayHints": { + "maxLength": null, + "lifetimeElisionHints": { + "useParameterNames": true, + "enable": "skip_trivial" + }, + "closureReturnTypeHints": { + "enable": "always" + } + } + } + } +} +``` + +### Typescript + +```json +"lsp": { + "typescript-language-server": { + "initialization_options": { + "preferences": { + "includeInlayParameterNameHints": "all", + "includeInlayParameterNameHintsWhenArgumentMatchesName": true, + "includeInlayFunctionParameterTypeHints": true, + "includeInlayVariableTypeHints": true, + "includeInlayVariableTypeHintsWhenTypeMatchesName": false, + "includeInlayPropertyDeclarationTypeHints": true, + "includeInlayFunctionLikeReturnTypeHints": true, + "includeInlayEnumMemberValueHints": true + } + } + } +} +``` + +### Go + +```json +"lsp": { + "gopls": { + "initialization_options": { + "hints": { + "assignVariableTypes": true, + "compositeLiteralFields": true, + "compositeLiteralTypes": true, + "constantValues": true, + "functionTypeParameters": true, + "parameterNames": true, + "rangeVariableTypes": true + } + } + } +} +``` + +### Svelte + +```json +{ + "lsp": { + "typescript-language-server": { + "initialization_options": { + "preferences": { + "includeInlayParameterNameHints": "all", + "includeInlayParameterNameHintsWhenArgumentMatchesName": true, + "includeInlayFunctionParameterTypeHints": true, + "includeInlayVariableTypeHints": true, + "includeInlayVariableTypeHintsWhenTypeMatchesName": false, + "includeInlayPropertyDeclarationTypeHints": true, + "includeInlayFunctionLikeReturnTypeHints": true, + "includeInlayEnumMemberValueHints": true, + "includeInlayEnumMemberDeclarationTypes": true + } + } + } + } +} +``` + +## Journal + +- Description: Configuration for the journal. +- Setting: `journal` +- Default: + +```json +"journal": { + "path": "~", + "hour_format": "hour12" +} +``` + +### Path + +- Description: The path of the directory where journal entries are stored. +- Setting: `path` +- Default: `~` + +**Options** + +`string` values + +### Hour Format + +- Description: The format to use for displaying hours in the journal. +- Setting: `hour_format` +- Default: `hour12` + +**Options** + +1. 12-hour format: + +```json +{ + "hour_format": "hour12" +} +``` + +2. 24-hour format: + +```json +{ + "hour_format": "hour24" +} +``` + +## Language Overrides + +- Description: Configuration overrides for specific languages. +- Setting: `language_overrides` +- Default: `null` + +**Options** + +To override settings for a language, add an entry for that languages name to the `language_overrides` value. Example: + +```json +"language_overrides": { + "C": { + "format_on_save": "off", + "preferred_line_length": 64, + "soft_wrap": "preferred_line_length" + }, + "JSON": { + "tab_size": 4 + } +} +``` + +The following settings can be overridden for each specific language: + +- `enable_language_server` +- `ensure_final_newline_on_save` +- `format_on_save` +- `formatter` +- `hard_tabs` +- `preferred_line_length` +- `remove_trailing_whitespace_on_save` +- `show_copilot_suggestions` +- `show_whitespaces` +- `soft_wrap` +- `tab_size` + +These values take in the same options as the root-level settings with the same name. + +## Preferred Line Length + +- Description: The column at which to soft-wrap lines, for buffers where soft-wrap is enabled. +- Setting: `preferred_line_length` +- Default: `80` + +**Options** + +`integer` values + +## Projects Online By Default + +- Description: Whether or not to show the online projects view by default. +- Setting: `projects_online_by_default` +- Default: `true` + +**Options** + +`boolean` values + +## Remove Trailing Whitespace On Save + +- Description: Whether or not to remove any trailing whitespace from lines of a buffer before saving it. +- Setting: `remove_trailing_whitespace_on_save` +- Default: `true` + +**Options** + +`boolean` values + +## Semantic Index + +- Description: Settings related to semantic index. +- Setting: `semantic_index` +- Default: + +```json +"semantic_index": { + "enabled": false +}, +``` + +### Enabled + +- Description: Whether or not to display the `Semantic` mode in project search. +- Setting: `enabled` +- Default: `true` + +**Options** + +`boolean` values + +## Show Call Status Icon + +- Description: Whether or not to show the call status icon in the status bar. +- Setting: `show_call_status_icon` +- Default: `true` + +**Options** + +`boolean` values + +## Show Completions On Input + +- Description: Whether or not to show completions as you type. +- Setting: `show_completions_on_input` +- Default: `true` + +**Options** + +`boolean` values + +## Show Completion Documentation + +- Description: Whether to display inline and alongside documentation for items in the completions menu. +- Setting: `show_completion_documentation` +- Default: `true` + +**Options** + +`boolean` values + +## Show Copilot Suggestions + +- Description: Whether or not to show Copilot suggestions as you type or wait for a `copilot::Toggle`. +- Setting: `show_copilot_suggestions` +- Default: `true` + +**Options** + +`boolean` values + +## Show Whitespaces + +- Description: Whether or not to show render whitespace characters in the editor. +- Setting: `show_whitespaces` +- Default: `selection` + +**Options** + +1. `all` +2. `selection` +3. `none` + +## Soft Wrap + +- Description: Whether or not to automatically wrap lines of text to fit editor / preferred width. +- Setting: `soft_wrap` +- Default: `none` + +**Options** + +1. `editor_width` +2. `preferred_line_length` +3. `none` + +## Tab Size + +- Description: The number of spaces to use for each tab character. +- Setting: `tab_size` +- Default: `4` + +**Options** + +`integer` values + +## Telemetry + +- Description: Control what info is collected by Zed. +- Setting: `telemetry` +- Default: + +```json +"telemetry": { + "diagnostics": true, + "metrics": true +}, +``` + +**Options** + +### Diagnostics + +- Description: Setting for sending debug-related data, such as crash reports. +- Setting: `diagnostics` +- Default: `true` + +**Options** + +`boolean` values + +### Metrics + +- Description: Setting for sending anonymized usage data, such what languages you're using Zed with. +- Setting: `metrics` +- Default: `true` + +**Options** + +`boolean` values + +## Terminal + +- Description: Configuration for the terminal. +- Setting: `terminal` +- Default: + +```json +"terminal": { + "alternate_scroll": "off", + "blinking": "terminal_controlled", + "copy_on_select": false, + "env": {}, + "font_family": null, + "font_features": null, + "font_size": null, + "option_as_meta": false, + "shell": {}, + "working_directory": "current_project_directory" +} +``` + +### Alternate Scroll + +- Description: Set whether Alternate Scroll mode (DECSET code: `?1007`) is active by default. Alternate Scroll mode converts mouse scroll events into up / down key presses when in the alternate screen (e.g. when running applications like vim or less). The terminal can still set and unset this mode with ANSI escape codes. +- Setting: `alternate_scroll` +- Default: `off` + +**Options** + +1. Default alternate scroll mode to on + +```json +{ + "alternate_scroll": "on" +} +``` + +2. Default alternate scroll mode to off + +```json +{ + "alternate_scroll": "off" +} +``` + +### Blinking + +- Description: Set the cursor blinking behavior in the terminal +- Setting: `blinking` +- Default: `terminal_controlled` + +**Options** + +1. Never blink the cursor, ignore the terminal mode + +```json +{ + "blinking": "off" +} +``` + +2. Default the cursor blink to off, but allow the terminal to turn blinking on + +```json +{ + "blinking": "terminal_controlled" +} +``` + +3. Always blink the cursor, ignore the terminal mode + +```json +"blinking": "on", +``` + +### Copy On Select + +- Description: Whether or not selecting text in the terminal will automatically copy to the system clipboard. +- Setting: `copy_on_select` +- Default: `false` + +**Options** + +`boolean` values + +### Env + +- Description: Any key-value pairs added to this object will be added to the terminal's environment. Keys must be unique, use `:` to separate multiple values in a single variable +- Setting: `env` +- Default: `{}` + +**Example** + +```json +"env": { + "ZED": "1", + "KEY": "value1:value2" +} +``` + +### Font Size + +- Description: What font size to use for the terminal. When not set defaults to matching the editor's font size +- Setting: `font_size` +- Default: `null` + +**Options** + +`integer` values + +### Font Family + +- Description: What font to use for the terminal. When not set, defaults to matching the editor's font. +- Setting: `font_family` +- Default: `null` + +**Options** + +The name of any font family installed on the user's system + +### Font Features + +- Description: What font features to use for the terminal. When not set, defaults to matching the editor's font features. +- Setting: `font_features` +- Default: `null` + +**Options** + +See Buffer Font Features + +### Option As Meta + +- Description: Re-interprets the option keys to act like a 'meta' key, like in Emacs. +- Setting: `option_as_meta` +- Default: `true` + +**Options** + +`boolean` values + +### Shell + +- Description: What shell to use when launching the terminal. +- Setting: `shell` +- Default: `system` + +**Options** + +1. Use the system's default terminal configuration (usually the `/etc/passwd` file). + +```json +{ + "shell": "system" +} +``` + +2. A program to launch: + +```json +"shell": { + "program": "sh" +} +``` + +3. A program with arguments: + +```json +"shell": { + "with_arguments": { + "program": "/bin/bash", + "args": ["--login"] + } +} +``` + +### Working Directory + +- Description: What working directory to use when launching the terminal. +- Setting: `working_directory` +- Default: `"current_project_directory"` + +**Options** + +1. Use the current file's project directory. Will Fallback to the first project directory strategy if unsuccessful + +```json +{ + "working_directory": "current_project_directory" +} +``` + +2. Use the first project in this workspace's directory. Will fallback to using this platform's home directory. + +```json +{ + "working_directory": "first_project_directory" +} +``` + +3. Always use this platform's home directory (if we can find it) + +```json +{ + "working_directory": "always_home" +} +``` + +4. Always use a specific directory. This value will be shell expanded. If this path is not a valid directory the terminal will default to this platform's home directory. + +```json +"working_directory": { + "always": { + "directory": "~/zed/projects/" + } +} +``` + +## Theme + +- Description: The name of the Zed theme to use for the UI. +- Setting: `theme` +- Default: `One Dark` + +**Options** + +Run the `theme selector: toggle` action in the command palette to see a current list of valid themes names. + +## Vim + +- Description: Whether or not to enable vim mode (work in progress). +- Setting: `vim_mode` +- Default: `false` + +## Project Panel + +- Description: Customise project panel +- Setting: `project_panel` +- Default: + +```json +"project_panel": { + "dock": "left", + "git_status": true, + "default_width": "N/A - width in pixels" +}, +``` + +### Dock + +- Description: Control the position of the dock +- Setting: `dock` +- Default: `left` + +**Options** + +1. Default dock position to left + +```json +{ + "dock": "left" +} +``` + +2. Default dock position to right + +```json +{ + "dock": "right" +} +``` + +### Git Status + +- Description: Indicates newly created and updated files +- Setting: `git_status` +- Default: `true` + +1. Default enable git status + +```json +{ + "git_status": true +} +``` + +2. Default disable git status + +```json +{ + "git_status": false +} +``` + +### Default Width +- Description: Customise default width taken by project panel +- Setting: `default_width` +- Default: N/A width in pixels (eg: 420) + +**Options** + +`boolean` values + +## An example configuration: + +```json +// ~/.config/zed/settings.json +{ + "theme": "cave-light", + "tab_size": 2, + "preferred_line_length": 80, + "soft_wrap": "none", + + "buffer_font_size": 18, + "buffer_font_family": "Zed Mono", + + "autosave": "on_focus_change", + "format_on_save": "off", + "vim_mode": false, + "projects_online_by_default": true, + "terminal": { + "font_family": "FiraCode Nerd Font Mono", + "blinking": "off" + }, + "language_overrides": { + "C": { + "format_on_save": "language_server", + "preferred_line_length": 64, + "soft_wrap": "preferred_line_length" + } + } +} +``` diff --git a/docs/src/configuring_zed__configuring_vim.md b/docs/src/configuring_zed__configuring_vim.md new file mode 100644 index 0000000000..ddef07e3c2 --- /dev/null +++ b/docs/src/configuring_zed__configuring_vim.md @@ -0,0 +1,170 @@ +# Vim Mode + +Zed includes a vim emulation layer known as “vim mode”. This document aims to describe how it works, and how to make the most out of it. + +### Philosophy +Vim mode in Zed is supposed to primarily "do what you expect": it mostly tries to copy vim exactly, but will use Zed-specific functionality when available to make things smoother. + +This means Zed will never be 100% vim compatible, but should be 100% vim familiar! We expect that our vim mode already copes with 90% of your workflow, and we'd like to keep improving it. If you find things that you can’t yet do in vim mode, but which you rely on in your current workflow, please leave feedback in the editor itself (`:feedback`), or [file an issue](https://github.com/zed-industries/community). + +### Zed-specific features +Zed is built on a modern foundation that (among other things) uses tree-sitter to understand the content of the file you're editing, and supports multiple cursors out of the box. + +Vim mode has several "core Zed" key bindings, that will help you make the most of Zed's specific feature set. +``` +# Normal mode +g d Go to definition +g D Go to type definition +c d Rename (change definition) +g A Go to All references to the current word + +g Open the current search excerpt in its own tab + +g s Find symbol in current file +g S Find symbol in entire project + +g n Add a visual selection for the next copy of the current word +g N The same, but backwards +g > Skip latest word selection, and add next. +g < The same, but backwards +g a Add a visual selection for every copy of the current word + +g h Show inline error (hover) + +# Insert mode +ctrl-x ctrl-o Open the completion menu +ctrl-x ctrl-c Request Github Copilot suggestion (if configured) +ctrl-x ctrl-a Open the inline AI assistant (if configured) +ctrl-x ctrl-l Open the LSP code actions +ctrl-x ctrl-z Hides all suggestions +``` + +Vim mode uses Zed to define concepts like "brackets" (for the `%` key) and "words" (for motions like `w` and `e`). This does lead to some differences, but they are mostly positive. For example `%` considers `|` to be a bracket in languages like Rust; and `w` considers `$` to be a word-character in languages like Javascript. + +Vim mode emulates visual block mode using Zed's multiple cursor support. This again leads to some differences, but is much more powerful. + +Finally, Vim mode's search and replace functionality is backed by Zed's. This means that the pattern syntax is slightly different, see the section on [Regex differences](#regex-differences) for details. + +### Custom key bindings +Zed does not yet have an equivalent to vim’s `map` command to convert one set of keystrokes into another, however you can bind any sequence of keys to fire any Action documented in the [Key bindings documentation](https://docs.zed.dev/configuration/key-bindings). + +You can edit your personal key bindings with `:keymap`. +For vim-specific shortcuts, you may find the following template a good place to start: + +```json +[ + { + "context": "Editor && VimControl && !VimWaiting && !menu", + "bindings": { + // put key-bindings here if you want them to work in normal & visual mode + } + }, + { + "context": "Editor && vim_mode == normal && !VimWaiting && !menu", + "bindings": { + // put key-bindings here if you want them to work only in normal mode + } + }, + { + "context": "Editor && vim_mode == visual && !VimWaiting && !menu", + "bindings": { + // visual, visual line & visual block modes + } + }, + { + "context": "Editor && vim_mode == insert && !menu", + "bindings": { + // put key-bindings here if you want them to work in insert mode + } + } +] +``` + +You can see the bindings that are enabled by default in vim mode [here](https://zed.dev/ref/vim.json). + +The details of the context are a little out of scope for this doc, but suffice to say that `menu` is true when a menu is open (e.g. the completions menu), `VimWaiting` is true after you type `f` or `t` when we’re waiting for a new key (and you probably don’t want bindings to happen). Please reach out on [Github](https://github.com/zed-industries/community) if you want help making a key bindings work. + +### Command palette + +Vim mode allows you to enable Zed’s command palette with `:`. This means that you can use vim's command palette to run any action that Zed supports. + +Additionally vim mode contains a number of aliases for popular vim commands to ensure that muscle memory works. For example `:w` will save the file. + +We do not (yet) emulate the full power of vim’s command line, in particular we special case specific patterns instead of using vim's range selection syntax, and we do not support arguments to commands yet. Please reach out on [Github](https://github.com/zed-industries/community) as you find things that are missing from the command palette. + +As mentioned above, one thing to be aware of is that the regex engine is slightly different from vim's in `:%s/a/b`. + +Currently supported vim-specific commands (as of Zed 0.106): +``` +# window management +:w[rite][!], :wq[!], :q[uit][!], :wa[ll][!], :wqa[ll][!], :qa[ll][!], :[e]x[it][!], :up[date] + to save/close tab(s) and pane(s) (no filename is supported yet) +:cq + to quit completely. +:vs[plit], :sp[lit] + to split vertically/horizontally (no filename is supported yet) +:new, :vne[w] + to create a new file in a new pane above or to the left +:tabedit, :tabnew + to create a new file in a new tab. +:tabn[ext], :tabp[rev] + to go to previous/next tabs +:tabc[lose] + to close the current tab + +# navigating diagnostics +:cn[ext], :cp[rev], :ln[ext], :lp[rev] + to go to the next/prev diagnostics +:cc, :ll + to open the errors page + +# jump to position +: + to jump to a line number +:$ + to jump to the end of the file +:/foo and :?foo + to jump to next/prev line matching foo + +# replacement +:%s/foo/bar/ + to replace instances of foo with bar (/g is always assumed, the range must always be %, and Zed uses different regex syntax to vim) + +# editing +:j[oin] + to join the current line (no range is yet supported) +:d[elete][l][p] + to delete the current line (no range is yet supported) +:s[ort] [i] + to sort the current selection (with i, case-insensitively) +``` + + +### Related settings +There are a few Zed settings that you may also enjoy if you use vim mode: +``` +{ + // disable cursor blink + "cursor_blink": false + // use relative line numbers + "relative_line_numbers": true, + // hide the scroll bar + "scrollbar": {"show": "never"}, +} +``` + +### Regex differences + +Zed uses a different regular expression engine from Vim. This means that you will have to use a different syntax for some things. + +Notably: +* Vim uses `\(` and `\)` to represent capture groups, in Zed these are `(` and `)`. +* On the flip side, `(` and `)` represent literal parentheses, but in Zed these must be escaped to `\(` and `\)`. +* When replacing, Vim uses `\0` to represent the entire match, in Zed this is `$0`, same for numbered capture groups `\1` -> `$1`. +* Vim uses `\<` and `\>` to represent word boundaries, in Zed these are both handled by `\b` +* Vim uses `/g` to indicate "all matches on one line", in Zed this is implied +* Vim uses `/i` to indicate "case-insensitive", in Zed you can either use `(?i)` at the start of the pattern or toggle case-sensitivity with `cmd-option-c`. + +To help with the transition, the command palette will fix parentheses and replace groups for you when you run `:%s//`. So `%s:/\(a\)(b)/\1/` will be converted into a search for "(a)\(b\)" and a replacement of "$1". + +For the full syntax supported by Zed's regex engine see the [regex crate documentation](https://docs.rs/regex/latest/regex/#syntax). diff --git a/docs/src/developing_zed__adding_languages.md b/docs/src/developing_zed__adding_languages.md new file mode 100644 index 0000000000..2917b08422 --- /dev/null +++ b/docs/src/developing_zed__adding_languages.md @@ -0,0 +1,83 @@ +# Adding New Languages to Zed + +## LSP + +Zed uses the [Language Server Protocol](https://microsoft.github.io/language-server-protocol/) to provide language support. This means, in theory, we can support any language that has an LSP server. + +## Syntax Highlighting + +### Defining syntax highlighting rules + +We use tree-sitter queries to match certian properties to highlight. + +#### Simple Example: + +```scheme +(property_identifier) @property +``` + +```ts +const font: FontFamily = { + weight: "normal", + underline: false, + italic: false, +} +``` + +Match a property identifier and highlight it using the identifier `@property`. In the above example, `weight`, `underline`, and `italic` would be highlighted. + +#### Complex example: + +```scheme +(_ + return_type: (type_annotation + [ + (type_identifier) @type.return + (generic_type + name: (type_identifier) @type.return) + ])) +``` + +```ts +function buildDefaultSyntax(colorScheme: Theme): Partial { + // ... +} +``` + +Match a function return type, and highlight the type using the identifier `@type.return`. In the above example, `Partial` would be highlighted. + +#### Example - Typescript + +Here is an example portion of our `highlights.scm` for TypeScript: + +```scheme +; crates/zed/src/languages/typescript/highlights.scm + +; Variables + +(identifier) @variable + +; Properties + +(property_identifier) @property + +; Function and method calls + +(call_expression + function: (identifier) @function) + +(call_expression + function: (member_expression + property: (property_identifier) @function.method)) + +; Function and method definitions + +(function + name: (identifier) @function) +(function_declaration + name: (identifier) @function) +(method_definition + name: (property_identifier) @function.method) + +; ... +``` diff --git a/docs/src/developing_zed__building_zed.md b/docs/src/developing_zed__building_zed.md new file mode 100644 index 0000000000..cb30051ffa --- /dev/null +++ b/docs/src/developing_zed__building_zed.md @@ -0,0 +1,107 @@ +# Building Zed + +🚧 TODO: +- [ ] Tidy up & update instructions +- [ ] Remove ZI-specific things +- [ ] Rework any steps that currently require a ZI-specific account + +How to build Zed from source for the first time. + +## Prerequisites + +- Be added to the GitHub organization +- Be added to the Vercel team + +## Process + +Expect this to take 30min to an hour! Some of these steps will take quite a while based on your connection speed, and how long your first build will be. + +1. Install the [GitHub CLI](https://cli.github.com/): + - `brew install gh` +1. Clone the `zed` repo + - `gh repo clone zed-industries/zed` +1. Install Xcode from the macOS App Store +1. Install Xcode command line tools + - `xcode-select --install` + - If xcode-select --print-path prints /Library/Developer/CommandLineTools… run `sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer.` +1. Install [Postgres](https://postgresapp.com) +1. Install rust/rustup + - `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` +1. Install the wasm toolchain + - `rustup target add wasm32-wasi` +1. Install Livekit & Foreman + - `brew install livekit` + - `brew install foreman` +1. Generate an GitHub API Key + - Go to https://github.com/settings/tokens and Generate new token + - GitHub currently provides two kinds of tokens: + - Classic Tokens, where only `repo` (Full control of private repositories) OAuth scope has to be selected + Unfortunately, unselecting `repo` scope and selecting every its inner scope instead does not allow the token users to read from private repositories + - (not applicable) Fine-grained Tokens, at the moment of writing, did not allow any kind of access of non-owned private repos + - Keep the token in the browser tab/editor for the next two steps +1. (Optional but reccomended) Add your GITHUB_TOKEN to your `.zshrc` or `.bashrc` like this: `export GITHUB_TOKEN=yourGithubAPIToken` +1. Ensure the Zed.dev website is checked out in a sibling directory and install it's dependencies: + ``` + cd .. + git clone https://github.com/zed-industries/zed.dev + cd zed.dev && npm install + npm install -g vercel + ``` +1. Link your zed.dev project to Vercel + - `vercel link` + - Select the `zed-industries` team. If you don't have this get someone on the team to add you to it. + - Select the `zed.dev` project +1. Run `vercel pull` to pull down the environment variables and project info from Vercel +1. Open Postgres.app +1. From `./path/to/zed/`: + - Run: + - `GITHUB_TOKEN={yourGithubAPIToken} script/bootstrap` + - Replace `{yourGithubAPIToken}` with the API token you generated above. + - You don't need to include the GITHUB_TOKEN if you exported it above. + - Consider removing the token (if it's fine for you to recreate such tokens during occasional migrations) or store this token somewhere safe (like your Zed 1Password vault). + - If you get: + - ```bash + Error: Cannot install in Homebrew on ARM processor in Intel default prefix (/usr/local)! + Please create a new installation in /opt/homebrew using one of the + "Alternative Installs" from: + https://docs.brew.sh/Installation + ``` + - In that case try: + - `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"` + - If Homebrew is not in your PATH: + - Replace `{username}` with your home folder name (usually your login name) + - `echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/{username}/.zprofile` + - `eval "$(/opt/homebrew/bin/brew shellenv)"` +1. To run the Zed app: + - If you are working on zed: + - `cargo run` + - If you are just using the latest version, but not working on zed: + - `cargo run --release` + - If you need to run the collaboration server locally: + - `script/zed-local` + +## Troubleshooting + +### `error: failed to run custom build command for gpui v0.1.0 (/Users/path/to/zed)` + +- Try `xcode-select --switch /Applications/Xcode.app/Contents/Developer` + +### `xcrun: error: unable to find utility "metal", not a developer tool or in PATH` + +### Seeding errors during `script/bootstrap` runs + +``` +seeding database... +thread 'main' panicked at 'failed to deserialize github user from 'https://api.github.com/orgs/zed-industries/teams/staff/members': reqwest::Error { kind: Decode, source: Error("invalid type: map, expected a sequence", line: 1, column: 0) }', crates/collab/src/bin/seed.rs:111:10 +``` + +Wrong permissions for `GITHUB_TOKEN` token used, the token needs to be able to read from private repos. +For Classic GitHub Tokens, that required OAuth scope `repo` (seacrh the scope name above for more details) + +Same command + +`sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer` + +### If you experience errors that mention some dependency is using unstable features + +Try `cargo clean` and `cargo build` diff --git a/docs/local-collaboration.md b/docs/src/developing_zed__local_collaboration.md similarity index 100% rename from docs/local-collaboration.md rename to docs/src/developing_zed__local_collaboration.md diff --git a/docs/src/feedback.md b/docs/src/feedback.md new file mode 100644 index 0000000000..11ae444079 --- /dev/null +++ b/docs/src/feedback.md @@ -0,0 +1,29 @@ +# Giving feedback + +### Community repository + +We track our issues at [`zed-industries/community`](https://github.com/zed-industries/community/issues). + +#### Feature requests + +Try to focus on the things that are most critical to you rather than exhaustively listing all features another editor you have used has. + +Command palette: `request feature` + +#### Bug reports + +Try to add as much detail as possible, if it is not obvious to reproduce. Let us know how severe the problem is for you; is the issue more of a minor inconvenience or something that would prevent you from using Zed? + +Command palette: `file bug report` + +### In-app feedback + +Anonymous feedback can be submitted from within Zed via the feedback editor (command palette: `give feedback`). + +### Zed forum + +Use the [community forum](https://github.com/zed-industries/community/discussions) to ask questions and learn from one another. We will be present in the forum and answering questions as well. + +### Email + +If you prefer to write up your thoughts as an email, you can send them to [hi@zed.dev](mailto:hi@zed.dev). diff --git a/docs/src/getting_started.md b/docs/src/getting_started.md new file mode 100644 index 0000000000..236249d00a --- /dev/null +++ b/docs/src/getting_started.md @@ -0,0 +1,15 @@ +# Getting Started + +Welcome to Zed! We are excited to have you. Here is a jumping-off point to getting started. + +### Download Zed + +You can obtain the release build via the [download page](https://zed.dev/download). After the first manual installation, Zed will periodically check for and install updates automatically for you. + +### Configure Zed + +Use `CMD + ,` to open your custom settings to set things like fonts, formatting settings, per-language settings and more. You can access the default configuration using the `Zed > Settings > Open Default Settings` menu item. See Configuring Zed for all available settings. + +### Set up your key bindings + +You can access the default key binding set using the `Zed > Settings > Open Default Key Bindings` menu item. Use `CMD + K`,`CMD + S` to open your custom keymap to add your own key bindings. See Key Bindings for more info., diff --git a/docs/src/system_requirements.md b/docs/src/system_requirements.md new file mode 100644 index 0000000000..debf7fa299 --- /dev/null +++ b/docs/src/system_requirements.md @@ -0,0 +1,13 @@ +# System Requirements + +## macOS + +Supported versions: Catalina (10.15) - Ventura (13.x). + +{% hint style="info" %} +The implementation of our screen sharing feature makes use of [LiveKit](https://livekit.io). The LiveKit SDK requires macOS Catalina (10.15); consequently, in v0.62.4, we dropped support for earlier macOS versions that we were initially supporting. +{% endhint %} + +## Linux, Windows, and Web + +_Not supported at this time. See our_ [_Platform Support_](https://github.com/zed-industries/community/issues/174) _issue._ diff --git a/docs/src/telemetry.md b/docs/src/telemetry.md new file mode 100644 index 0000000000..834e02770a --- /dev/null +++ b/docs/src/telemetry.md @@ -0,0 +1,147 @@ +# Telemetry in Zed + +**Up to date with v0.112.0** + +Zed collects anonymous telemetry data to help the team understand how people are using the application and to see what sort of issues they are experiencing. + +## Dataflow + +Telemetry is sent from the application to zed.dev. Data is proxied through our servers to enable us to easily switch analytics services; we never store this data. The data is then sent off to various services: + +- [Datadog](https://www.datadoghq.com): Cloud-monitoring service - stores diagnostic events +- [Clickhouse](https://clickhouse.com): Business Intelligence platform - stores both diagnostic and metric events +- [Metabase](https://www.metabase.com): Dashboards - dashboards built around data pulled from Clickhouse + +## Types of Telemetry + +### Diagnostics + +Diagnostic events include debug information (stack traces) from crash reports. Reports are sent on the first application launch after the crash occurred. We've built dashboards that allow us to visualize the frequency and severity of issues experienced by users. Having these reports sent automatically allows us to begin implementing fixes without the user needing to file a report in our issue tracker. The plots in the dashboards also give us an informal measurement of the stability of Zed. + +When a panic occurs, the following data is sent: + +#### PanicRequest + +- `panic`: The panic data +- `token`: An identifier that is used to authenticate the request on zed.dev + +#### Panic + +- `thread`: The name of the thread that panicked +- `payload`: The panic message +- `location_data`: The location of the panic + - `file` + - `line` +- `backtrace`: The backtrace of the panic +- `app_version`: Zed's app version +- `release_channel`: Zed's release channel + - `stable` + - `preview` + - `dev` +- `os_name`: The name of your operating system +- `os_version`: The version of your operating system +- `architecture`: The architecture of your CPU +- `panicked_on`: The time that the panic occurred +- `installation_id`: An identifier that is unique to each installation of Zed (this differs for stable, preview, and dev builds) +- `session_id`: An identifier that is unique to each Zed session (this differs for each time you open Zed) + +### Metrics + +Zed also collects metric information based on user actions. Metric events are reported over HTTPS, and requests are rate-limited to avoid using significant network bandwidth. All data remains anonymous, and can't be related to specific Zed users. + +The following data is sent: + +#### ClickhouseEventRequestBody + +- `token`: An identifier that is used to authenticate the request on zed.dev +- `installation_id`: An identifier that is unique to each installation of Zed (this differs for stable, preview, and dev builds) +- `session_id`: An identifier that is unique to each Zed session (this differs for each time you open Zed) +- `is_staff`: A boolean that indicates whether the user is a member of the Zed team or not +- `app_version`: Zed's app version +- `os_name`: The name of your operating system +- `os_version`: The version of your operating system +- `architecture`: The architecture of your CPU +- `release_channel`: Zed's release channel + - `stable` + - `preview` + - `dev` +- `events`: A vector of `ClickhouseEventWrapper`s + +#### ClickhouseEventWrapper + +- `signed_in`: A boolean that indicates whether the user is signed in or not +- `event`: An enum, where each variant can be one of the following `ClickhouseEvent` variants: + +#### ClickhouseEvent + +- `editor` + - `operation`: The editor operation that was performed + - `open` + - `save` + - `file_extension`: The extension of the file that was opened or saved + - `vim_mode`: A boolean that indicates whether the user is in vim mode or not + - `copilot_enabled`: A boolean that indicates whether the user has copilot enabled or not + - `copilot_enabled_for_language`: A boolean that indicates whether the user has copilot enabled for the language of the file that was opened or saved + - `milliseconds_since_first_event`: Duration of time between this event's timestamp and the timestamp of the first event in the current batch +- `copilot` + - `suggestion_id`: The ID of the suggestion + - `suggestion_accepted`: A boolean that indicates whether the suggestion was accepted or not + - `file_extension`: The file extension of the file that was opened or saved + - `milliseconds_since_first_event`: Same as above +- `call` + - `operation`: The call operation that was performed + - `accept incoming` + - `decline incoming` + - `disable microphone` + - `disable screen share` + - `enable microphone` + - `enable screen share` + - `hang up` + - `invite` + - `join channel` + - `open channel notes` + - `share project` + - `unshare project` + - `room_id`: The ID of the room + - `channel_id`: The ID of the channel + - `milliseconds_since_first_event`: Same as above +- `assistant` + - `conversation_id`: The ID of the conversation (for panel events only) + - `kind`: An enum with the following variants: + - `panel` + - `inline` + - `model`: The model that was used + - `milliseconds_since_first_event`: Same as above +- `cpu` + - `usage_as_percentage`: The CPU usage + - `core_count`: The number of cores on the CPU + - `milliseconds_since_first_event`: Same as above +- `memory` + - `memory_in_bytes`: The amount of memory used in bytes + - `virtual_memory_in_bytes`: The amount of virtual memory used in bytes + - `milliseconds_since_first_event`: Same as above +- `app` + - `operation`: The app operation that was performed + - `first open` + - `open` + - `close (only in GPUI2-powered Zed)` + - `milliseconds_since_first_event`: Same as above + +You can audit the metrics data that Zed has reported by running the command `zed: open telemetry log` from the command palette, or clicking `Help > View Telemetry Log` in the application menu. + +### Configuring Telemetry Settings + +You have full control over what data is sent out by Zed. To enable or disable some or all telemetry types, open your `settings.json` file via `zed: open settings` from the command palette. Insert and tweak the following: + +```json +"telemetry": { + "diagnostics": false, + "metrics": false +}, +``` + +The telemetry settings can also be configured via the `welcome` screen, which can be invoked via the `workspace: welcome` action in the command palette. + +### Concerns and Questions + +If you have concerns about telemetry, please feel free to open issues in our [community repository](https://github.com/zed-industries/community/issues/new/choose). diff --git a/docs/backend-development.md b/docs_old/backend-development.md similarity index 100% rename from docs/backend-development.md rename to docs_old/backend-development.md diff --git a/docs/building-zed.md b/docs_old/building-zed.md similarity index 100% rename from docs/building-zed.md rename to docs_old/building-zed.md diff --git a/docs/company-and-vision.md b/docs_old/company-and-vision.md similarity index 100% rename from docs/company-and-vision.md rename to docs_old/company-and-vision.md diff --git a/docs/design-tools.md b/docs_old/design-tools.md similarity index 100% rename from docs/design-tools.md rename to docs_old/design-tools.md diff --git a/docs/index.md b/docs_old/index.md similarity index 100% rename from docs/index.md rename to docs_old/index.md diff --git a/docs_old/local-collaboration.md b/docs_old/local-collaboration.md new file mode 100644 index 0000000000..4c059c0878 --- /dev/null +++ b/docs_old/local-collaboration.md @@ -0,0 +1,22 @@ +# Local Collaboration + +## Setting up the local collaboration server + +### Setting up for the first time? + +1. Make sure you have livekit installed (`brew install livekit`) +1. Install [Postgres](https://postgresapp.com) and run it. +1. Then, from the root of the repo, run `script/bootstrap`. + +### Have a db that is out of date? / Need to migrate? + +1. Make sure you have livekit installed (`brew install livekit`) +1. Try `cd crates/collab && cargo run -- migrate` from the root of the repo. +1. Run `script/seed-db` + +## Testing collab locally + +1. Run `foreman start` from the root of the repo. +1. In another terminal run `script/zed-local -2`. +1. Two copies of Zed will open. Add yourself as a contact in the one that is not you. +1. Start a collaboration session as normal with any open project. diff --git a/docs/release-process.md b/docs_old/release-process.md similarity index 100% rename from docs/release-process.md rename to docs_old/release-process.md diff --git a/docs/theme/generating-theme-types.md b/docs_old/theme/generating-theme-types.md similarity index 100% rename from docs/theme/generating-theme-types.md rename to docs_old/theme/generating-theme-types.md diff --git a/docs/tools.md b/docs_old/tools.md similarity index 100% rename from docs/tools.md rename to docs_old/tools.md diff --git a/docs/zed/syntax-highlighting.md b/docs_old/zed/syntax-highlighting.md similarity index 100% rename from docs/zed/syntax-highlighting.md rename to docs_old/zed/syntax-highlighting.md From 5b3b15e95cb97553377e7cc0661fec145f9dd5a3 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 12 Dec 2023 09:10:12 -0500 Subject: [PATCH 005/644] Futher outline --- docs/src/CONTRIBUTING.md | 3 --- docs/src/SUMMARY.md | 17 ++++++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) delete mode 100644 docs/src/CONTRIBUTING.md diff --git a/docs/src/CONTRIBUTING.md b/docs/src/CONTRIBUTING.md deleted file mode 100644 index d48c26844f..0000000000 --- a/docs/src/CONTRIBUTING.md +++ /dev/null @@ -1,3 +0,0 @@ -# Contributing - -TBD diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 4c6f5f9421..ad1cd6332c 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -7,12 +7,19 @@ - [Settings](./configuring_zed.md) - [Vim Mode](./configuring_zed__configuring_vim.md) -# Developing Zed +# Using Zed +- [Workflows]() +- [Collaboration]() +- [Using AI]() + +# Contributing to Zed +- [How to Contribute]() - [Building from Source](./developing_zed__building_zed.md) - [Local Collaboration](./developing_zed__local_collaboration.md) - [Adding Languages](./developing_zed__adding_languages.md) +- [Adding UI]() -# Other -- [Code of Conduct](./CODE_OF_CONDUCT.md) -- [Telemetry](./telemetry.md) -- [Contributing](./CONTRIBUTING.md) +--- + +[Telemetry](./telemetry.md) +[Code of Conduct](./CODE_OF_CONDUCT.md) From f9e7c796720834ec7c7da0622b5b8a4da34d8afe Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Wed, 13 Dec 2023 10:35:03 -0500 Subject: [PATCH 006/644] Add deploy note --- docs/how-to-deploy.md | 8 ++++++++ {docs_old => docs/old}/backend-development.md | 0 {docs_old => docs/old}/building-zed.md | 0 {docs_old => docs/old}/company-and-vision.md | 0 {docs_old => docs/old}/design-tools.md | 0 {docs_old => docs/old}/index.md | 0 {docs_old => docs/old}/local-collaboration.md | 0 {docs_old => docs/old}/release-process.md | 0 {docs_old => docs/old}/theme/generating-theme-types.md | 0 {docs_old => docs/old}/tools.md | 0 {docs_old => docs/old}/zed/syntax-highlighting.md | 0 11 files changed, 8 insertions(+) create mode 100644 docs/how-to-deploy.md rename {docs_old => docs/old}/backend-development.md (100%) rename {docs_old => docs/old}/building-zed.md (100%) rename {docs_old => docs/old}/company-and-vision.md (100%) rename {docs_old => docs/old}/design-tools.md (100%) rename {docs_old => docs/old}/index.md (100%) rename {docs_old => docs/old}/local-collaboration.md (100%) rename {docs_old => docs/old}/release-process.md (100%) rename {docs_old => docs/old}/theme/generating-theme-types.md (100%) rename {docs_old => docs/old}/tools.md (100%) rename {docs_old => docs/old}/zed/syntax-highlighting.md (100%) diff --git a/docs/how-to-deploy.md b/docs/how-to-deploy.md new file mode 100644 index 0000000000..b1222aac5c --- /dev/null +++ b/docs/how-to-deploy.md @@ -0,0 +1,8 @@ +1. `cd docs` from repo root +1. Install the vercel cli if you haven't already + - `pnpm i -g vercel` +1. `vercel` to deploy if you already have the project linked +1. Otherwise, `vercel login` and `vercel` to link + - Choose Zed Industries as the team, then `zed-app-docs` as the project + +Someone can write a script for this when they have time. diff --git a/docs_old/backend-development.md b/docs/old/backend-development.md similarity index 100% rename from docs_old/backend-development.md rename to docs/old/backend-development.md diff --git a/docs_old/building-zed.md b/docs/old/building-zed.md similarity index 100% rename from docs_old/building-zed.md rename to docs/old/building-zed.md diff --git a/docs_old/company-and-vision.md b/docs/old/company-and-vision.md similarity index 100% rename from docs_old/company-and-vision.md rename to docs/old/company-and-vision.md diff --git a/docs_old/design-tools.md b/docs/old/design-tools.md similarity index 100% rename from docs_old/design-tools.md rename to docs/old/design-tools.md diff --git a/docs_old/index.md b/docs/old/index.md similarity index 100% rename from docs_old/index.md rename to docs/old/index.md diff --git a/docs_old/local-collaboration.md b/docs/old/local-collaboration.md similarity index 100% rename from docs_old/local-collaboration.md rename to docs/old/local-collaboration.md diff --git a/docs_old/release-process.md b/docs/old/release-process.md similarity index 100% rename from docs_old/release-process.md rename to docs/old/release-process.md diff --git a/docs_old/theme/generating-theme-types.md b/docs/old/theme/generating-theme-types.md similarity index 100% rename from docs_old/theme/generating-theme-types.md rename to docs/old/theme/generating-theme-types.md diff --git a/docs_old/tools.md b/docs/old/tools.md similarity index 100% rename from docs_old/tools.md rename to docs/old/tools.md diff --git a/docs_old/zed/syntax-highlighting.md b/docs/old/zed/syntax-highlighting.md similarity index 100% rename from docs_old/zed/syntax-highlighting.md rename to docs/old/zed/syntax-highlighting.md From 70c6660ae4f7d0c2a70218022509bc4c1d77e4f1 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Wed, 13 Dec 2023 10:35:54 -0500 Subject: [PATCH 007/644] Add note --- docs/how-to-deploy.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/how-to-deploy.md b/docs/how-to-deploy.md index b1222aac5c..c32d3619a6 100644 --- a/docs/how-to-deploy.md +++ b/docs/how-to-deploy.md @@ -1,3 +1,5 @@ +These docs are intendended to replace both docs.zed.dev and introduce people to how to build Zed from source. + 1. `cd docs` from repo root 1. Install the vercel cli if you haven't already - `pnpm i -g vercel` From a874a96e76b8cced2bc0fe5e108f35b813814c7c Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 13 Dec 2023 11:44:51 -0500 Subject: [PATCH 008/644] Fix tab bar drop target sizing (#3627) This PR fixes an issue where the tab bar drop target was not receiving any size. The styling isn't 100% correct yet, as the updated background color has a gap around it. Release Notes: - N/A --- crates/workspace2/src/pane.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 2068245159..afd7e665c4 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1664,6 +1664,10 @@ impl Pane { ) .child( div() + .min_w_6() + // HACK: This empty child is currently necessary to force the drop traget to appear + // despite us setting a min width above. + .child("") .h_full() .flex_grow() .drag_over::(|bar| { From ab8d0abbc142052779a9968c4d64c2c26d335cab Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 13 Dec 2023 12:11:33 -0500 Subject: [PATCH 009/644] Wire up tooltips on tab bar actions (#3629) This PR wires up the tooltips on the actions in the tab bar. Release Notes: - N/A --- crates/workspace2/src/pane.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index afd7e665c4..bcbadc4e53 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1597,7 +1597,8 @@ impl Pane { let view = cx.view().clone(); move |_, cx| view.update(cx, Self::navigate_backward) }) - .disabled(!self.can_navigate_backward()), + .disabled(!self.can_navigate_backward()) + .tooltip(|cx| Tooltip::for_action("Go Back", &GoBack, cx)), ) .start_child( IconButton::new("navigate_forward", Icon::ArrowRight) @@ -1606,7 +1607,8 @@ impl Pane { let view = cx.view().clone(); move |_, cx| view.update(cx, Self::navigate_backward) }) - .disabled(!self.can_navigate_forward()), + .disabled(!self.can_navigate_forward()) + .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), ) .end_child( div() @@ -1625,7 +1627,8 @@ impl Pane { }) .detach(); this.new_item_menu = Some(menu); - })), + })) + .tooltip(|cx| Tooltip::text("New...", cx)), ) .when_some(self.new_item_menu.as_ref(), |el, new_item_menu| { el.child(Self::render_menu_overlay(new_item_menu)) @@ -1649,7 +1652,8 @@ impl Pane { }) .detach(); this.split_item_menu = Some(menu); - })), + })) + .tooltip(|cx| Tooltip::text("Split Pane", cx)), ) .when_some(self.split_item_menu.as_ref(), |el, split_item_menu| { el.child(Self::render_menu_overlay(split_item_menu)) From 48faa171b53e252a07e1f95c10603c9d6dd196e6 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 13 Dec 2023 12:24:10 -0500 Subject: [PATCH 010/644] v0.118.x dev --- Cargo.lock | 2 +- crates/zed/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 033ff8b69c..cc4393bffa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11882,7 +11882,7 @@ dependencies = [ [[package]] name = "zed" -version = "0.117.0" +version = "0.118.0" dependencies = [ "activity_indicator", "ai", diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index f665cc36db..0c115fb285 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] description = "The fast, collaborative code editor." edition = "2021" name = "zed" -version = "0.117.0" +version = "0.118.0" publish = false [lib] From a91a42763f8abd5426059dfb1206e0239deba099 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 13 Dec 2023 17:56:49 +0100 Subject: [PATCH 011/644] collab_ui: Wire up project picker Co-authored-by: Conrad --- crates/collab_ui2/src/collab_titlebar_item.rs | 107 ++++++++++-------- crates/picker2/src/picker2.rs | 23 ++-- .../recent_projects2/src/recent_projects.rs | 21 +++- 3 files changed, 93 insertions(+), 58 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 2b931f7085..f48a78fb1d 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -2,11 +2,13 @@ use crate::face_pile::FacePile; use call::{ActiveCall, ParticipantLocation, Room}; use client::{proto::PeerId, Client, ParticipantIndex, User, UserStore}; use gpui::{ - actions, canvas, div, point, px, rems, AppContext, Div, Element, Hsla, InteractiveElement, - IntoElement, Model, ParentElement, Path, Render, Stateful, StatefulInteractiveElement, Styled, - Subscription, ViewContext, VisualContext, WeakView, WindowBounds, + actions, canvas, div, overlay, point, px, rems, AppContext, DismissEvent, Div, Element, + FocusableView, Hsla, InteractiveElement, IntoElement, Model, Overlay, ParentElement, Path, + Render, Stateful, StatefulInteractiveElement, Styled, Subscription, ViewContext, VisualContext, + WeakView, WindowBounds, }; use project::{Project, RepositoryEntry}; +use recent_projects::RecentProjects; use std::sync::Arc; use theme::{ActiveTheme, PlayerColors}; use ui::{ @@ -14,7 +16,7 @@ use ui::{ IconButton, IconElement, KeyBinding, Tooltip, }; use util::ResultExt; -use workspace::{notifications::NotifyResultExt, Workspace}; +use workspace::{notifications::NotifyResultExt, Workspace, WORKSPACE_DB}; const MAX_PROJECT_NAME_LENGTH: usize = 40; const MAX_BRANCH_NAME_LENGTH: usize = 40; @@ -49,7 +51,7 @@ pub struct CollabTitlebarItem { client: Arc, workspace: WeakView, //branch_popover: Option>, - //project_popover: Option>, + project_popover: Option, //user_menu: ViewHandle, _subscriptions: Vec, } @@ -328,7 +330,7 @@ impl CollabTitlebarItem { // menu // }), // branch_popover: None, - // project_popover: None, + project_popover: None, _subscriptions: subscriptions, } } @@ -366,11 +368,27 @@ impl CollabTitlebarItem { let name = util::truncate_and_trailoff(name, MAX_PROJECT_NAME_LENGTH); - div().border().border_color(gpui::red()).child( - Button::new("project_name_trigger", name) - .style(ButtonStyle::Subtle) - .tooltip(move |cx| Tooltip::text("Recent Projects", cx)), - ) + div() + .border() + .border_color(gpui::red()) + .child( + Button::new("project_name_trigger", name) + .style(ButtonStyle::Subtle) + .tooltip(move |cx| Tooltip::text("Recent Projects", cx)) + .on_click(cx.listener(|this, _, cx| { + this.toggle_project_menu(&ToggleProjectMenu, cx); + })), + ) + .children(self.project_popover.as_ref().map(|popover| { + overlay().child( + div() + .min_w_56() + .on_mouse_down_out(cx.listener_for(&popover.picker, |picker, _, cx| { + picker.cancel(&Default::default(), cx) + })) + .child(popover.picker.clone()), + ) + })) } pub fn render_project_branch(&self, cx: &mut ViewContext) -> Option { @@ -611,43 +629,40 @@ impl CollabTitlebarItem { // cx.notify(); // } - // pub fn toggle_project_menu(&mut self, _: &ToggleProjectMenu, cx: &mut ViewContext) { - // let workspace = self.workspace.clone(); - // if self.project_popover.take().is_none() { - // cx.spawn(|this, mut cx| async move { - // let workspaces = WORKSPACE_DB - // .recent_workspaces_on_disk() - // .await - // .unwrap_or_default() - // .into_iter() - // .map(|(_, location)| location) - // .collect(); + pub fn toggle_project_menu(&mut self, _: &ToggleProjectMenu, cx: &mut ViewContext) { + let workspace = self.workspace.clone(); + if self.project_popover.take().is_none() { + cx.spawn(|this, mut cx| async move { + let workspaces = WORKSPACE_DB + .recent_workspaces_on_disk() + .await + .unwrap_or_default() + .into_iter() + .map(|(_, location)| location) + .collect(); - // let workspace = workspace.clone(); - // this.update(&mut cx, move |this, cx| { - // let view = cx.add_view(|cx| build_recent_projects(workspace, workspaces, cx)); + let workspace = workspace.clone(); + this.update(&mut cx, move |this, cx| { + let view = RecentProjects::open_popover(workspace, workspaces, cx); - // cx.subscribe(&view, |this, _, event, cx| { - // match event { - // PickerEvent::Dismiss => { - // this.project_popover = None; - // } - // } - - // cx.notify(); - // }) - // .detach(); - // cx.focus(&view); - // this.branch_popover.take(); - // this.project_popover = Some(view); - // cx.notify(); - // }) - // .log_err(); - // }) - // .detach(); - // } - // cx.notify(); - // } + cx.subscribe(&view.picker, |this, _, _: &DismissEvent, cx| { + this.project_popover = None; + cx.notify(); + }) + .detach(); + let focus_handle = view.focus_handle(cx); + cx.focus(&focus_handle); + // todo!() + //this.branch_popover.take(); + this.project_popover = Some(view); + cx.notify(); + }) + .log_err(); + }) + .detach(); + } + cx.notify(); + } // fn render_user_menu_button( // &self, diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 98b6ce5ff0..db5eebff53 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -1,8 +1,8 @@ use editor::Editor; use gpui::{ - div, prelude::*, rems, uniform_list, AnyElement, AppContext, Div, FocusHandle, FocusableView, - MouseButton, MouseDownEvent, Render, Task, UniformListScrollHandle, View, ViewContext, - WindowContext, + div, prelude::*, rems, uniform_list, AnyElement, AppContext, DismissEvent, Div, EventEmitter, + FocusHandle, FocusableView, MouseButton, MouseDownEvent, Render, Task, UniformListScrollHandle, + View, ViewContext, WindowContext, }; use std::{cmp, sync::Arc}; use ui::{prelude::*, v_stack, Color, Divider, Label}; @@ -113,8 +113,9 @@ impl Picker { cx.notify(); } - fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { + pub fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { self.delegate.dismissed(cx); + cx.emit(DismissEvent); } fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext) { @@ -146,9 +147,15 @@ impl Picker { event: &editor::EditorEvent, cx: &mut ViewContext, ) { - if let editor::EditorEvent::BufferEdited = event { - let query = self.editor.read(cx).text(cx); - self.update_matches(query, cx); + match event { + editor::EditorEvent::BufferEdited => { + let query = self.editor.read(cx).text(cx); + self.update_matches(query, cx); + } + editor::EditorEvent::Blurred => { + self.cancel(&menu::Cancel, cx); + } + _ => {} } } @@ -189,6 +196,8 @@ impl Picker { } } +impl EventEmitter for Picker {} + impl Render for Picker { type Element = Div; diff --git a/crates/recent_projects2/src/recent_projects.rs b/crates/recent_projects2/src/recent_projects.rs index e014783687..dff6aa12cc 100644 --- a/crates/recent_projects2/src/recent_projects.rs +++ b/crates/recent_projects2/src/recent_projects.rs @@ -23,14 +23,15 @@ pub fn init(cx: &mut AppContext) { cx.observe_new_views(RecentProjects::register).detach(); } +#[derive(Clone)] pub struct RecentProjects { - picker: View>, + pub picker: View>, } impl ModalView for RecentProjects {} impl RecentProjects { - fn new(delegate: RecentProjectsDelegate, cx: &mut ViewContext) -> Self { + fn new(delegate: RecentProjectsDelegate, cx: &mut WindowContext<'_>) -> Self { Self { picker: cx.build_view(|cx| Picker::new(delegate, cx)), } @@ -86,6 +87,16 @@ impl RecentProjects { Ok(()) })) } + pub fn open_popover( + workspace: WeakView, + workspaces: Vec, + cx: &mut WindowContext<'_>, + ) -> Self { + Self::new( + RecentProjectsDelegate::new(workspace, workspaces, false), + cx, + ) + } } impl EventEmitter for RecentProjects {} @@ -127,7 +138,7 @@ impl RecentProjectsDelegate { } } } - +impl EventEmitter for RecentProjectsDelegate {} impl PickerDelegate for RecentProjectsDelegate { type ListItem = ListItem; @@ -202,11 +213,11 @@ impl PickerDelegate for RecentProjectsDelegate { .open_workspace_for_paths(workspace_location.paths().as_ref().clone(), cx) }) .detach_and_log_err(cx); - self.dismissed(cx); + cx.emit(DismissEvent); } } - fn dismissed(&mut self, _cx: &mut ViewContext>) {} + fn dismissed(&mut self, _: &mut ViewContext>) {} fn render_match( &self, From 72eef116c965f49ead482b1cc765a580c50cd191 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 13 Dec 2023 17:58:17 +0100 Subject: [PATCH 012/644] fixup! collab_ui: Wire up project picker --- crates/collab_ui2/src/collab_titlebar_item.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index f48a78fb1d..3d8fedd06b 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -3,8 +3,8 @@ use call::{ActiveCall, ParticipantLocation, Room}; use client::{proto::PeerId, Client, ParticipantIndex, User, UserStore}; use gpui::{ actions, canvas, div, overlay, point, px, rems, AppContext, DismissEvent, Div, Element, - FocusableView, Hsla, InteractiveElement, IntoElement, Model, Overlay, ParentElement, Path, - Render, Stateful, StatefulInteractiveElement, Styled, Subscription, ViewContext, VisualContext, + FocusableView, Hsla, InteractiveElement, IntoElement, Model, ParentElement, Path, Render, + Stateful, StatefulInteractiveElement, Styled, Subscription, ViewContext, VisualContext, WeakView, WindowBounds, }; use project::{Project, RepositoryEntry}; From 3094cb749ed1691a230b4bc037bd5e9676164c18 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Wed, 13 Dec 2023 14:12:59 -0700 Subject: [PATCH 013/644] Implement user menu --- Cargo.lock | 2 + crates/collab_ui2/Cargo.toml | 4 +- crates/collab_ui2/src/collab_titlebar_item.rs | 60 ++++++++++++++----- crates/zed2/src/zed2.rs | 3 +- crates/zed_actions2/src/lib.rs | 2 +- 5 files changed, 52 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba868ebbae..a6cc38ef6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1957,6 +1957,7 @@ dependencies = [ "db2", "editor2", "feature_flags2", + "feedback2", "futures 0.3.28", "fuzzy2", "gpui2", @@ -1978,6 +1979,7 @@ dependencies = [ "settings2", "smallvec", "theme2", + "theme_selector2", "time", "tree-sitter-markdown", "ui2", diff --git a/crates/collab_ui2/Cargo.toml b/crates/collab_ui2/Cargo.toml index 65aced8e7e..88c27bc165 100644 --- a/crates/collab_ui2/Cargo.toml +++ b/crates/collab_ui2/Cargo.toml @@ -32,7 +32,7 @@ collections = { path = "../collections" } # context_menu = { path = "../context_menu" } # drag_and_drop = { path = "../drag_and_drop" } editor = { package="editor2", path = "../editor2" } -#feedback = { path = "../feedback" } +feedback = { package = "feedback2", path = "../feedback2" } fuzzy = { package = "fuzzy2", path = "../fuzzy2" } gpui = { package = "gpui2", path = "../gpui2" } language = { package = "language2", path = "../language2" } @@ -46,7 +46,7 @@ rpc = { package ="rpc2", path = "../rpc2" } settings = { package = "settings2", path = "../settings2" } feature_flags = { package = "feature_flags2", path = "../feature_flags2"} theme = { package = "theme2", path = "../theme2" } -# theme_selector = { path = "../theme_selector" } +theme_selector = { package = "theme_selector2", path = "../theme_selector2" } # vcs_menu = { path = "../vcs_menu" } ui = { package = "ui2", path = "../ui2" } util = { path = "../util" } diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 3d8fedd06b..d6de5a1565 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -1,8 +1,8 @@ use crate::face_pile::FacePile; use call::{ActiveCall, ParticipantLocation, Room}; -use client::{proto::PeerId, Client, ParticipantIndex, User, UserStore}; +use client::{proto::PeerId, Client, ParticipantIndex, SignOut, User, UserStore}; use gpui::{ - actions, canvas, div, overlay, point, px, rems, AppContext, DismissEvent, Div, Element, + actions, canvas, div, overlay, point, px, rems, Action, AppContext, DismissEvent, Div, Element, FocusableView, Hsla, InteractiveElement, IntoElement, Model, ParentElement, Path, Render, Stateful, StatefulInteractiveElement, Styled, Subscription, ViewContext, VisualContext, WeakView, WindowBounds, @@ -16,7 +16,7 @@ use ui::{ IconButton, IconElement, KeyBinding, Tooltip, }; use util::ResultExt; -use workspace::{notifications::NotifyResultExt, Workspace, WORKSPACE_DB}; +use workspace::{notifications::NotifyResultExt, Feedback, Workspace, WORKSPACE_DB}; const MAX_PROJECT_NAME_LENGTH: usize = 40; const MAX_BRANCH_NAME_LENGTH: usize = 40; @@ -239,7 +239,19 @@ impl Render for CollabTitlebarItem { this.child( popover_menu("user-menu") .menu(|cx| { - ContextMenu::build(cx, |menu, _| menu.header("ADADA")) + ContextMenu::build(cx, |menu, _| { + menu.action( + "Settings", + zed_actions::OpenSettings.boxed_clone(), + ) + .action("Theme", theme_selector::Toggle.boxed_clone()) + .separator() + .action( + "Share Feedback", + feedback::GiveFeedback.boxed_clone(), + ) + .action("Sign Out", client::SignOut.boxed_clone()) + }) }) .trigger( ButtonLike::new("user-menu") @@ -259,16 +271,6 @@ impl Render for CollabTitlebarItem { ) .anchor(gpui::AnchorCorner::TopRight), ) - // this.child( - // ButtonLike::new("user-menu") - // .child( - // h_stack().gap_0p5().child(Avatar::data(avatar)).child( - // IconElement::new(Icon::ChevronDown).color(Color::Muted), - // ), - // ) - // .style(ButtonStyle::Subtle) - // .tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)), - // ) } else { this.child(Button::new("sign_in", "Sign in").on_click(move |_, cx| { let client = client.clone(); @@ -280,6 +282,36 @@ impl Render for CollabTitlebarItem { }) .detach(); })) + .child( + popover_menu("user-menu") + .menu(|cx| { + ContextMenu::build(cx, |menu, _| { + menu.action( + "Settings", + zed_actions::OpenSettings.boxed_clone(), + ) + .action("Theme", theme_selector::Toggle.boxed_clone()) + .separator() + .action( + "Share Feedback", + feedback::GiveFeedback.boxed_clone(), + ) + }) + }) + .trigger( + ButtonLike::new("user-menu") + .child( + h_stack().gap_0p5().child( + IconElement::new(Icon::ChevronDown) + .color(Color::Muted), + ), + ) + .style(ButtonStyle::Subtle) + .tooltip(move |cx| { + Tooltip::text("Toggle User Menu", cx) + }), + ), + ) } })), ) diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index 611cf64552..45ef08fdcc 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -41,7 +41,7 @@ use workspace::{ notifications::simple_message_notification::MessageNotification, open_new, AppState, NewFile, NewWindow, Workspace, WorkspaceSettings, }; -use zed_actions::{OpenBrowser, OpenZedURL, Quit}; +use zed_actions::{OpenBrowser, OpenSettings, OpenZedURL, Quit}; actions!( zed, @@ -59,7 +59,6 @@ actions!( OpenLicenses, OpenLocalSettings, OpenLog, - OpenSettings, OpenTelemetryLog, ResetBufferFontSize, ResetDatabase, diff --git a/crates/zed_actions2/src/lib.rs b/crates/zed_actions2/src/lib.rs index fa1a4a5ea9..badf76a6e7 100644 --- a/crates/zed_actions2/src/lib.rs +++ b/crates/zed_actions2/src/lib.rs @@ -22,4 +22,4 @@ pub struct OpenZedURL { impl_actions!(zed, [OpenBrowser, OpenZedURL]); -actions!(zed, [Quit]); +actions!(zed, [OpenSettings, Quit]); From 26a31b41b96d56815c581b587d381d632e9cf85b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 13 Dec 2023 13:02:19 -0800 Subject: [PATCH 014/644] frame time --- crates/gpui2/src/window.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 77eb4e27be..a0db7d6d9e 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1236,6 +1236,8 @@ impl<'a> WindowContext<'a> { /// Draw pixels to the display for this window based on the contents of its scene. pub(crate) fn draw(&mut self) -> Scene { + let t0 = std::time::Instant::now(); + let window_was_focused = self .window .focus @@ -1326,6 +1328,7 @@ impl<'a> WindowContext<'a> { } self.window.dirty = false; + eprintln!("frame: {:?}", t0.elapsed()); scene } From 7899833367ea3971dd87b014aec4e962d3ffce23 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Wed, 13 Dec 2023 15:44:27 -0700 Subject: [PATCH 015/644] Don't hang the app when signing in offline --- Cargo.lock | 1 + crates/auto_update2/src/auto_update.rs | 4 +- crates/client2/src/client2.rs | 171 ++++---- crates/collab_ui2/Cargo.toml | 2 +- crates/collab_ui2/src/collab_titlebar_item.rs | 388 ++++++------------ crates/ui2/src/components/icon.rs | 2 + 6 files changed, 225 insertions(+), 343 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6cc38ef6a..3b0a8e57fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1949,6 +1949,7 @@ name = "collab_ui2" version = "0.1.0" dependencies = [ "anyhow", + "auto_update2", "call2", "channel2", "client2", diff --git a/crates/auto_update2/src/auto_update.rs b/crates/auto_update2/src/auto_update.rs index 31e474242a..e1e1de0da4 100644 --- a/crates/auto_update2/src/auto_update.rs +++ b/crates/auto_update2/src/auto_update.rs @@ -6,7 +6,7 @@ use db::kvp::KEY_VALUE_STORE; use db::RELEASE_CHANNEL; use gpui::{ actions, AppContext, AsyncAppContext, Context as _, Model, ModelContext, SemanticVersion, Task, - ViewContext, VisualContext, + ViewContext, VisualContext, WindowContext, }; use isahc::AsyncBody; use serde::Deserialize; @@ -125,7 +125,7 @@ pub fn init(http_client: Arc, server_url: String, cx: &mut AppCo } } -pub fn check(_: &Check, cx: &mut ViewContext) { +pub fn check(_: &Check, cx: &mut WindowContext) { if let Some(updater) = AutoUpdater::get(cx) { updater.update(cx, |updater, cx| updater.poll(cx)); } else { diff --git a/crates/client2/src/client2.rs b/crates/client2/src/client2.rs index bf8d5dda77..2c97872989 100644 --- a/crates/client2/src/client2.rs +++ b/crates/client2/src/client2.rs @@ -11,8 +11,8 @@ use async_tungstenite::tungstenite::{ http::{Request, StatusCode}, }; use futures::{ - future::LocalBoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, TryFutureExt as _, - TryStreamExt, + channel::oneshot, future::LocalBoxFuture, AsyncReadExt, FutureExt, SinkExt, StreamExt, + TryFutureExt as _, TryStreamExt, }; use gpui::{ actions, serde_json, AnyModel, AnyWeakModel, AppContext, AsyncAppContext, Model, @@ -1020,91 +1020,116 @@ impl Client { ) -> Task> { let http = self.http.clone(); cx.spawn(|cx| async move { - // Generate a pair of asymmetric encryption keys. The public key will be used by the - // zed server to encrypt the user's access token, so that it can'be intercepted by - // any other app running on the user's device. - let (public_key, private_key) = - rpc::auth::keypair().expect("failed to generate keypair for auth"); - let public_key_string = - String::try_from(public_key).expect("failed to serialize public key for auth"); + let background = cx.background_executor().clone(); - if let Some((login, token)) = IMPERSONATE_LOGIN.as_ref().zip(ADMIN_API_TOKEN.as_ref()) { - return Self::authenticate_as_admin(http, login.clone(), token.clone()).await; - } + let (open_url_tx, open_url_rx) = oneshot::channel::(); + cx.update(|cx| { + cx.spawn(move |cx| async move { + let url = open_url_rx.await?; + cx.update(|cx| cx.open_url(&url)) + }) + .detach_and_log_err(cx); + }) + .log_err(); - // Start an HTTP server to receive the redirect from Zed's sign-in page. - let server = tiny_http::Server::http("127.0.0.1:0").expect("failed to find open port"); - let port = server.server_addr().port(); + let credentials = background + .clone() + .spawn(async move { + // Generate a pair of asymmetric encryption keys. The public key will be used by the + // zed server to encrypt the user's access token, so that it can'be intercepted by + // any other app running on the user's device. + let (public_key, private_key) = + rpc::auth::keypair().expect("failed to generate keypair for auth"); + let public_key_string = String::try_from(public_key) + .expect("failed to serialize public key for auth"); - // Open the Zed sign-in page in the user's browser, with query parameters that indicate - // that the user is signing in from a Zed app running on the same device. - let mut url = format!( - "{}/native_app_signin?native_app_port={}&native_app_public_key={}", - *ZED_SERVER_URL, port, public_key_string - ); + if let Some((login, token)) = + IMPERSONATE_LOGIN.as_ref().zip(ADMIN_API_TOKEN.as_ref()) + { + return Self::authenticate_as_admin(http, login.clone(), token.clone()) + .await; + } - if let Some(impersonate_login) = IMPERSONATE_LOGIN.as_ref() { - log::info!("impersonating user @{}", impersonate_login); - write!(&mut url, "&impersonate={}", impersonate_login).unwrap(); - } + // Start an HTTP server to receive the redirect from Zed's sign-in page. + let server = + tiny_http::Server::http("127.0.0.1:0").expect("failed to find open port"); + let port = server.server_addr().port(); - cx.update(|cx| cx.open_url(&url))?; + // Open the Zed sign-in page in the user's browser, with query parameters that indicate + // that the user is signing in from a Zed app running on the same device. + let mut url = format!( + "{}/native_app_signin?native_app_port={}&native_app_public_key={}", + *ZED_SERVER_URL, port, public_key_string + ); - // Receive the HTTP request from the user's browser. Retrieve the user id and encrypted - // access token from the query params. - // - // TODO - Avoid ever starting more than one HTTP server. Maybe switch to using a - // custom URL scheme instead of this local HTTP server. - let (user_id, access_token) = cx - .spawn(|_| async move { - for _ in 0..100 { - if let Some(req) = server.recv_timeout(Duration::from_secs(1))? { - let path = req.url(); - let mut user_id = None; - let mut access_token = None; - let url = Url::parse(&format!("http://example.com{}", path)) - .context("failed to parse login notification url")?; - for (key, value) in url.query_pairs() { - if key == "access_token" { - access_token = Some(value.to_string()); - } else if key == "user_id" { - user_id = Some(value.to_string()); + if let Some(impersonate_login) = IMPERSONATE_LOGIN.as_ref() { + log::info!("impersonating user @{}", impersonate_login); + write!(&mut url, "&impersonate={}", impersonate_login).unwrap(); + } + + open_url_tx.send(url).log_err(); + + // Receive the HTTP request from the user's browser. Retrieve the user id and encrypted + // access token from the query params. + // + // TODO - Avoid ever starting more than one HTTP server. Maybe switch to using a + // custom URL scheme instead of this local HTTP server. + let (user_id, access_token) = background + .spawn(async move { + for _ in 0..100 { + if let Some(req) = server.recv_timeout(Duration::from_secs(1))? { + let path = req.url(); + let mut user_id = None; + let mut access_token = None; + let url = Url::parse(&format!("http://example.com{}", path)) + .context("failed to parse login notification url")?; + for (key, value) in url.query_pairs() { + if key == "access_token" { + access_token = Some(value.to_string()); + } else if key == "user_id" { + user_id = Some(value.to_string()); + } + } + + let post_auth_url = + format!("{}/native_app_signin_succeeded", *ZED_SERVER_URL); + req.respond( + tiny_http::Response::empty(302).with_header( + tiny_http::Header::from_bytes( + &b"Location"[..], + post_auth_url.as_bytes(), + ) + .unwrap(), + ), + ) + .context("failed to respond to login http request")?; + return Ok(( + user_id + .ok_or_else(|| anyhow!("missing user_id parameter"))?, + access_token.ok_or_else(|| { + anyhow!("missing access_token parameter") + })?, + )); } } - let post_auth_url = - format!("{}/native_app_signin_succeeded", *ZED_SERVER_URL); - req.respond( - tiny_http::Response::empty(302).with_header( - tiny_http::Header::from_bytes( - &b"Location"[..], - post_auth_url.as_bytes(), - ) - .unwrap(), - ), - ) - .context("failed to respond to login http request")?; - return Ok(( - user_id.ok_or_else(|| anyhow!("missing user_id parameter"))?, - access_token - .ok_or_else(|| anyhow!("missing access_token parameter"))?, - )); - } - } + Err(anyhow!("didn't receive login redirect")) + }) + .await?; - Err(anyhow!("didn't receive login redirect")) + let access_token = private_key + .decrypt_string(&access_token) + .context("failed to decrypt access token")?; + + Ok(Credentials { + user_id: user_id.parse()?, + access_token, + }) }) .await?; - let access_token = private_key - .decrypt_string(&access_token) - .context("failed to decrypt access token")?; cx.update(|cx| cx.activate(true))?; - - Ok(Credentials { - user_id: user_id.parse()?, - access_token, - }) + Ok(credentials) }) } diff --git a/crates/collab_ui2/Cargo.toml b/crates/collab_ui2/Cargo.toml index 88c27bc165..6249e9fdaf 100644 --- a/crates/collab_ui2/Cargo.toml +++ b/crates/collab_ui2/Cargo.toml @@ -22,7 +22,7 @@ test-support = [ ] [dependencies] -# auto_update = { path = "../auto_update" } +auto_update = { package = "auto_update2", path = "../auto_update2" } db = { package = "db2", path = "../db2" } call = { package = "call2", path = "../call2" } client = { package = "client2", path = "../client2" } diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index d6de5a1565..276455151e 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -1,10 +1,11 @@ use crate::face_pile::FacePile; +use auto_update::AutoUpdateStatus; use call::{ActiveCall, ParticipantLocation, Room}; -use client::{proto::PeerId, Client, ParticipantIndex, SignOut, User, UserStore}; +use client::{proto::PeerId, Client, ParticipantIndex, User, UserStore}; use gpui::{ - actions, canvas, div, overlay, point, px, rems, Action, AppContext, DismissEvent, Div, Element, - FocusableView, Hsla, InteractiveElement, IntoElement, Model, ParentElement, Path, Render, - Stateful, StatefulInteractiveElement, Styled, Subscription, ViewContext, VisualContext, + actions, canvas, div, overlay, point, px, rems, Action, AnyElement, AppContext, DismissEvent, + Div, Element, FocusableView, Hsla, InteractiveElement, IntoElement, Model, ParentElement, Path, + Render, Stateful, StatefulInteractiveElement, Styled, Subscription, ViewContext, VisualContext, WeakView, WindowBounds, }; use project::{Project, RepositoryEntry}; @@ -16,7 +17,7 @@ use ui::{ IconButton, IconElement, KeyBinding, Tooltip, }; use util::ResultExt; -use workspace::{notifications::NotifyResultExt, Feedback, Workspace, WORKSPACE_DB}; +use workspace::{notifications::NotifyResultExt, Workspace, WORKSPACE_DB}; const MAX_PROJECT_NAME_LENGTH: usize = 40; const MAX_BRANCH_NAME_LENGTH: usize = 40; @@ -52,7 +53,6 @@ pub struct CollabTitlebarItem { workspace: WeakView, //branch_popover: Option>, project_popover: Option, - //user_menu: ViewHandle, _subscriptions: Vec, } @@ -232,88 +232,17 @@ impl Render for CollabTitlebarItem { }), ) }) - .child(h_stack().px_1p5().map(|this| { - if let Some(user) = current_user { - // TODO: Finish implementing user menu popover - // - this.child( - popover_menu("user-menu") - .menu(|cx| { - ContextMenu::build(cx, |menu, _| { - menu.action( - "Settings", - zed_actions::OpenSettings.boxed_clone(), - ) - .action("Theme", theme_selector::Toggle.boxed_clone()) - .separator() - .action( - "Share Feedback", - feedback::GiveFeedback.boxed_clone(), - ) - .action("Sign Out", client::SignOut.boxed_clone()) - }) - }) - .trigger( - ButtonLike::new("user-menu") - .child( - h_stack() - .gap_0p5() - .child(Avatar::new(user.avatar_uri.clone())) - .child( - IconElement::new(Icon::ChevronDown) - .color(Color::Muted), - ), - ) - .style(ButtonStyle::Subtle) - .tooltip(move |cx| { - Tooltip::text("Toggle User Menu", cx) - }), - ) - .anchor(gpui::AnchorCorner::TopRight), - ) + .map(|el| { + let status = self.client.status(); + let status = &*status.borrow(); + if matches!(status, client::Status::Connected { .. }) { + el.child(self.render_user_menu_button(cx)) } else { - this.child(Button::new("sign_in", "Sign in").on_click(move |_, cx| { - let client = client.clone(); - cx.spawn(move |mut cx| async move { - client - .authenticate_and_connect(true, &cx) - .await - .notify_async_err(&mut cx); - }) - .detach(); - })) - .child( - popover_menu("user-menu") - .menu(|cx| { - ContextMenu::build(cx, |menu, _| { - menu.action( - "Settings", - zed_actions::OpenSettings.boxed_clone(), - ) - .action("Theme", theme_selector::Toggle.boxed_clone()) - .separator() - .action( - "Share Feedback", - feedback::GiveFeedback.boxed_clone(), - ) - }) - }) - .trigger( - ButtonLike::new("user-menu") - .child( - h_stack().gap_0p5().child( - IconElement::new(Icon::ChevronDown) - .color(Color::Muted), - ), - ) - .style(ButtonStyle::Subtle) - .tooltip(move |cx| { - Tooltip::text("Toggle User Menu", cx) - }), - ), - ) + el.children(self.render_connection_status(status, cx)) + .child(self.render_sign_in_button(cx)) + .child(self.render_user_menu_button(cx)) } - })), + }), ) } } @@ -355,12 +284,6 @@ impl CollabTitlebarItem { project, user_store, client, - // user_menu: cx.add_view(|cx| { - // let view_id = cx.view_id(); - // let mut menu = ContextMenu::new(view_id, cx); - // menu.set_position_mode(OverlayPositionMode::Local); - // menu - // }), // branch_popover: None, project_popover: None, _subscriptions: subscriptions, @@ -535,34 +458,6 @@ impl CollabTitlebarItem { .log_err(); } - // pub fn toggle_user_menu(&mut self, _: &ToggleUserMenu, cx: &mut ViewContext) { - // self.user_menu.update(cx, |user_menu, cx| { - // let items = if let Some(_) = self.user_store.read(cx).current_user() { - // vec![ - // ContextMenuItem::action("Settings", zed_actions::OpenSettings), - // ContextMenuItem::action("Theme", theme_selector::Toggle), - // ContextMenuItem::separator(), - // ContextMenuItem::action( - // "Share Feedback", - // feedback::feedback_editor::GiveFeedback, - // ), - // ContextMenuItem::action("Sign Out", SignOut), - // ] - // } else { - // vec![ - // ContextMenuItem::action("Settings", zed_actions::OpenSettings), - // ContextMenuItem::action("Theme", theme_selector::Toggle), - // ContextMenuItem::separator(), - // ContextMenuItem::action( - // "Share Feedback", - // feedback::feedback_editor::GiveFeedback, - // ), - // ] - // }; - // user_menu.toggle(Default::default(), AnchorCorner::TopRight, items, cx); - // }); - // } - // fn render_branches_popover_host<'a>( // &'a self, // _theme: &'a theme::Titlebar, @@ -696,154 +591,113 @@ impl CollabTitlebarItem { cx.notify(); } - // fn render_user_menu_button( - // &self, - // theme: &Theme, - // avatar: Option>, - // cx: &mut ViewContext, - // ) -> AnyElement { - // let tooltip = theme.tooltip.clone(); - // let user_menu_button_style = if avatar.is_some() { - // &theme.titlebar.user_menu.user_menu_button_online - // } else { - // &theme.titlebar.user_menu.user_menu_button_offline - // }; + fn render_connection_status( + &self, + status: &client::Status, + cx: &mut ViewContext, + ) -> Option { + match status { + client::Status::ConnectionError + | client::Status::ConnectionLost + | client::Status::Reauthenticating { .. } + | client::Status::Reconnecting { .. } + | client::Status::ReconnectionError { .. } => Some( + div() + .id("disconnected") + .bg(gpui::red()) // todo!() @nate + .child(IconElement::new(Icon::Disconnected)) + .tooltip(|cx| Tooltip::text("Disconnected", cx)) + .into_any_element(), + ), + client::Status::UpgradeRequired => { + let auto_updater = auto_update::AutoUpdater::get(cx); + let label = match auto_updater.map(|auto_update| auto_update.read(cx).status()) { + Some(AutoUpdateStatus::Updated) => "Please restart Zed to Collaborate", + Some(AutoUpdateStatus::Installing) + | Some(AutoUpdateStatus::Downloading) + | Some(AutoUpdateStatus::Checking) => "Updating...", + Some(AutoUpdateStatus::Idle) | Some(AutoUpdateStatus::Errored) | None => { + "Please update Zed to Collaborate" + } + }; - // let avatar_style = &user_menu_button_style.avatar; - // Stack::new() - // .with_child( - // MouseEventHandler::new::(0, cx, |state, _| { - // let style = user_menu_button_style - // .user_menu - // .inactive_state() - // .style_for(state); + Some( + div() + .bg(gpui::red()) // todo!() @nate + .child(Button::new("connection-status", label).on_click(|_, cx| { + if let Some(auto_updater) = auto_update::AutoUpdater::get(cx) { + if auto_updater.read(cx).status() == AutoUpdateStatus::Updated { + workspace::restart(&Default::default(), cx); + return; + } + } + auto_update::check(&Default::default(), cx); + })) + .into_any_element(), + ) + } + _ => None, + } + } - // let mut dropdown = Flex::row().align_children_center(); + pub fn render_sign_in_button(&mut self, _: &mut ViewContext) -> Button { + let client = self.client.clone(); + Button::new("sign_in", "Sign in").on_click(move |_, cx| { + let client = client.clone(); + cx.spawn(move |mut cx| async move { + client + .authenticate_and_connect(true, &cx) + .await + .notify_async_err(&mut cx); + }) + .detach(); + }) + } - // if let Some(avatar_img) = avatar { - // dropdown = dropdown.with_child(Self::render_face( - // avatar_img, - // *avatar_style, - // Color::transparent_black(), - // None, - // )); - // }; - - // dropdown - // .with_child( - // Svg::new("icons/caret_down.svg") - // .with_color(user_menu_button_style.icon.color) - // .constrained() - // .with_width(user_menu_button_style.icon.width) - // .contained() - // .into_any(), - // ) - // .aligned() - // .constrained() - // .with_height(style.width) - // .contained() - // .with_style(style.container) - // .into_any() - // }) - // .with_cursor_style(CursorStyle::PointingHand) - // .on_down(MouseButton::Left, move |_, this, cx| { - // this.user_menu.update(cx, |menu, _| menu.delay_cancel()); - // }) - // .on_click(MouseButton::Left, move |_, this, cx| { - // this.toggle_user_menu(&Default::default(), cx) - // }) - // .with_tooltip::( - // 0, - // "Toggle User Menu".to_owned(), - // Some(Box::new(ToggleUserMenu)), - // tooltip, - // cx, - // ) - // .contained(), - // ) - // .with_child( - // ChildView::new(&self.user_menu, cx) - // .aligned() - // .bottom() - // .right(), - // ) - // .into_any() - // } - - // fn render_sign_in_button(&self, theme: &Theme, cx: &mut ViewContext) -> AnyElement { - // let titlebar = &theme.titlebar; - // MouseEventHandler::new::(0, cx, |state, _| { - // let style = titlebar.sign_in_button.inactive_state().style_for(state); - // Label::new("Sign In", style.text.clone()) - // .contained() - // .with_style(style.container) - // }) - // .with_cursor_style(CursorStyle::PointingHand) - // .on_click(MouseButton::Left, move |_, this, cx| { - // let client = this.client.clone(); - // cx.app_context() - // .spawn(|cx| async move { client.authenticate_and_connect(true, &cx).await }) - // .detach_and_log_err(cx); - // }) - // .into_any() - // } - - // fn render_connection_status( - // &self, - // status: &client::Status, - // cx: &mut ViewContext, - // ) -> Option> { - // enum ConnectionStatusButton {} - - // let theme = &theme::current(cx).clone(); - // match status { - // client::Status::ConnectionError - // | client::Status::ConnectionLost - // | client::Status::Reauthenticating { .. } - // | client::Status::Reconnecting { .. } - // | client::Status::ReconnectionError { .. } => Some( - // Svg::new("icons/disconnected.svg") - // .with_color(theme.titlebar.offline_icon.color) - // .constrained() - // .with_width(theme.titlebar.offline_icon.width) - // .aligned() - // .contained() - // .with_style(theme.titlebar.offline_icon.container) - // .into_any(), - // ), - // client::Status::UpgradeRequired => { - // let auto_updater = auto_update::AutoUpdater::get(cx); - // let label = match auto_updater.map(|auto_update| auto_update.read(cx).status()) { - // Some(AutoUpdateStatus::Updated) => "Please restart Zed to Collaborate", - // Some(AutoUpdateStatus::Installing) - // | Some(AutoUpdateStatus::Downloading) - // | Some(AutoUpdateStatus::Checking) => "Updating...", - // Some(AutoUpdateStatus::Idle) | Some(AutoUpdateStatus::Errored) | None => { - // "Please update Zed to Collaborate" - // } - // }; - - // Some( - // MouseEventHandler::new::(0, cx, |_, _| { - // Label::new(label, theme.titlebar.outdated_warning.text.clone()) - // .contained() - // .with_style(theme.titlebar.outdated_warning.container) - // .aligned() - // }) - // .with_cursor_style(CursorStyle::PointingHand) - // .on_click(MouseButton::Left, |_, _, cx| { - // if let Some(auto_updater) = auto_update::AutoUpdater::get(cx) { - // if auto_updater.read(cx).status() == AutoUpdateStatus::Updated { - // workspace::restart(&Default::default(), cx); - // return; - // } - // } - // auto_update::check(&Default::default(), cx); - // }) - // .into_any(), - // ) - // } - // _ => None, - // } - // } + pub fn render_user_menu_button(&mut self, cx: &mut ViewContext) -> impl Element { + if let Some(user) = self.user_store.read(cx).current_user() { + popover_menu("user-menu") + .menu(|cx| { + ContextMenu::build(cx, |menu, _| { + menu.action("Settings", zed_actions::OpenSettings.boxed_clone()) + .action("Theme", theme_selector::Toggle.boxed_clone()) + .separator() + .action("Share Feedback", feedback::GiveFeedback.boxed_clone()) + .action("Sign Out", client::SignOut.boxed_clone()) + }) + }) + .trigger( + ButtonLike::new("user-menu") + .child( + h_stack() + .gap_0p5() + .child(Avatar::new(user.avatar_uri.clone())) + .child(IconElement::new(Icon::ChevronDown).color(Color::Muted)), + ) + .style(ButtonStyle::Subtle) + .tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)), + ) + .anchor(gpui::AnchorCorner::TopRight) + } else { + popover_menu("user-menu") + .menu(|cx| { + ContextMenu::build(cx, |menu, _| { + menu.action("Settings", zed_actions::OpenSettings.boxed_clone()) + .action("Theme", theme_selector::Toggle.boxed_clone()) + .separator() + .action("Share Feedback", feedback::GiveFeedback.boxed_clone()) + }) + }) + .trigger( + ButtonLike::new("user-menu") + .child( + h_stack() + .gap_0p5() + .child(IconElement::new(Icon::ChevronDown).color(Color::Muted)), + ) + .style(ButtonStyle::Subtle) + .tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)), + ) + } + } } diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index b68aa579c0..6876630100 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -50,6 +50,7 @@ pub enum Icon { CopilotError, CopilotDisabled, Dash, + Disconnected, Envelope, ExternalLink, ExclamationTriangle, @@ -129,6 +130,7 @@ impl Icon { Icon::CopilotError => "icons/copilot_error.svg", Icon::CopilotDisabled => "icons/copilot_disabled.svg", Icon::Dash => "icons/dash.svg", + Icon::Disconnected => "icons/disconnected.svg", Icon::Envelope => "icons/feedback.svg", Icon::ExclamationTriangle => "icons/warning.svg", Icon::ExternalLink => "icons/external_link.svg", From 1e4a7e6ef18e765fc30303e2ec7176a61a1d8b72 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 13 Dec 2023 16:01:49 -0700 Subject: [PATCH 016/644] Don't notify when drawing --- crates/gpui2/src/window.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index a0db7d6d9e..d0056617ed 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -237,6 +237,7 @@ pub struct Window { bounds_observers: SubscriberSet<(), AnyObserver>, active: bool, pub(crate) dirty: bool, + pub(crate) drawing: bool, activation_observers: SubscriberSet<(), AnyObserver>, pub(crate) last_blur: Option>, pub(crate) focus: Option, @@ -371,6 +372,7 @@ impl Window { bounds_observers: SubscriberSet::new(), active: false, dirty: false, + drawing: false, activation_observers: SubscriberSet::new(), last_blur: None, focus: None, @@ -422,7 +424,9 @@ impl<'a> WindowContext<'a> { /// Mark the window as dirty, scheduling it to be redrawn on the next frame. pub fn notify(&mut self) { - self.window.dirty = true; + if !self.window.drawing { + self.window.dirty = true; + } } /// Close this window. @@ -1237,6 +1241,8 @@ impl<'a> WindowContext<'a> { /// Draw pixels to the display for this window based on the contents of its scene. pub(crate) fn draw(&mut self) -> Scene { let t0 = std::time::Instant::now(); + self.window.dirty = false; + self.window.drawing = true; let window_was_focused = self .window @@ -1327,7 +1333,7 @@ impl<'a> WindowContext<'a> { self.platform.set_cursor_style(cursor_style); } - self.window.dirty = false; + self.window.drawing = false; eprintln!("frame: {:?}", t0.elapsed()); scene @@ -2346,10 +2352,12 @@ impl<'a, V: 'static> ViewContext<'a, V> { } pub fn notify(&mut self) { - self.window_cx.notify(); - self.window_cx.app.push_effect(Effect::Notify { - emitter: self.view.model.entity_id, - }); + if !self.window.drawing { + self.window_cx.notify(); + self.window_cx.app.push_effect(Effect::Notify { + emitter: self.view.model.entity_id, + }); + } } pub fn observe_window_bounds( From c863227dc2f84a7bd6285963d8377b3772c70322 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 13 Dec 2023 18:44:21 -0700 Subject: [PATCH 017/644] Log frame timings --- crates/gpui2/src/platform/mac/metal_renderer.rs | 6 ++++++ crates/gpui2/src/view.rs | 6 ++++++ crates/gpui2/src/window.rs | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/gpui2/src/platform/mac/metal_renderer.rs b/crates/gpui2/src/platform/mac/metal_renderer.rs index c477440df5..3210a53c63 100644 --- a/crates/gpui2/src/platform/mac/metal_renderer.rs +++ b/crates/gpui2/src/platform/mac/metal_renderer.rs @@ -187,6 +187,8 @@ impl MetalRenderer { } pub fn draw(&mut self, scene: &Scene) { + let start = std::time::Instant::now(); + let layer = self.layer.clone(); let viewport_size = layer.drawable_size(); let viewport_size: Size = size( @@ -303,6 +305,10 @@ impl MetalRenderer { command_buffer.commit(); self.sprite_atlas.clear_textures(AtlasTextureKind::Path); + + let duration_since_start = start.elapsed(); + println!("renderer draw: {:?}", duration_since_start); + command_buffer.wait_until_completed(); drawable.present(); } diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 280c52df2a..46a9086478 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -209,8 +209,14 @@ impl AnyView { ) { cx.with_absolute_element_offset(origin, |cx| { let (layout_id, rendered_element) = (self.layout)(self, cx); + let start_time = std::time::Instant::now(); cx.compute_layout(layout_id, available_space); + let duration = start_time.elapsed(); + println!("compute layout: {:?}", duration); + let start_time = std::time::Instant::now(); (self.paint)(self, rendered_element, cx); + let duration = start_time.elapsed(); + println!("paint: {:?}", duration); }) } } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index d0056617ed..4624bcf20b 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1334,7 +1334,7 @@ impl<'a> WindowContext<'a> { } self.window.drawing = false; - eprintln!("frame: {:?}", t0.elapsed()); + eprintln!("window draw: {:?}", t0.elapsed()); scene } From cd08d349a5410970b919bb0d3f0f57182ee649c2 Mon Sep 17 00:00:00 2001 From: Julia Date: Wed, 13 Dec 2023 21:48:05 -0500 Subject: [PATCH 018/644] Quick and dirty attempt to immediately apply focus change in tests Doesn't quite work yet --- crates/gpui2/src/app.rs | 4 +++- crates/gpui2/src/window.rs | 22 ++++++++++++++++++---- crates/project_panel2/src/project_panel.rs | 1 + 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 9b9a5921e1..deb03498bc 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -571,6 +571,7 @@ impl AppContext { loop { self.release_dropped_entities(); self.release_dropped_focus_handles(); + if let Some(effect) = self.pending_effects.pop_front() { match effect { Effect::Notify { emitter } => { @@ -610,7 +611,8 @@ impl AppContext { .values() .filter_map(|window| { let window = window.as_ref()?; - window.dirty.then_some(window.handle) + dbg!(window.focus_invalidated); + (window.dirty || window.focus_invalidated).then_some(window.handle) }) .collect::>() { diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index d2f4891711..895ae78862 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -243,6 +243,9 @@ pub struct Window { pub(crate) dirty: bool, activation_observers: SubscriberSet<(), AnyObserver>, pub(crate) focus: Option, + + #[cfg(any(test, feature = "test-support"))] + pub(crate) focus_invalidated: bool, } pub(crate) struct ElementStateBox { @@ -381,6 +384,9 @@ impl Window { dirty: false, activation_observers: SubscriberSet::new(), focus: None, + + #[cfg(any(test, feature = "test-support"))] + focus_invalidated: false, } } } @@ -461,6 +467,12 @@ impl<'a> WindowContext<'a> { .rendered_frame .dispatch_tree .clear_pending_keystrokes(); + + #[cfg(any(test, feature = "test-support"))] + { + self.window.focus_invalidated = true; + } + self.notify(); } @@ -1274,13 +1286,15 @@ impl<'a> WindowContext<'a> { self.window.root_view = Some(root_view); let previous_focus_path = self.window.rendered_frame.focus_path(); - - let window = &mut self.window; - mem::swap(&mut window.rendered_frame, &mut window.next_frame); - + mem::swap(&mut self.window.rendered_frame, &mut self.window.next_frame); let current_focus_path = self.window.rendered_frame.focus_path(); if previous_focus_path != current_focus_path { + #[cfg(any(test, feature = "test-support"))] + { + self.window.focus_invalidated = false; + } + if !previous_focus_path.is_empty() && current_focus_path.is_empty() { self.window .blur_listeners diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index adcd21cac6..5e71266c21 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -739,6 +739,7 @@ impl ProjectPanel { }); self.filename_editor.update(cx, |editor, cx| { editor.clear(cx); + println!("focusing"); editor.focus(cx); }); self.update_visible_entries(Some((worktree_id, NEW_ENTRY_ID)), cx); From 6f17cf73370c4482ff7a0ad63bac00ffce45d5b0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 14 Dec 2023 09:25:09 -0700 Subject: [PATCH 019/644] WIP --- crates/gpui2/src/elements/div.rs | 16 +++++++-------- crates/gpui2/src/view.rs | 5 +++++ crates/gpui2/src/window.rs | 34 ++++++++++++++++++++++++-------- debug.plist | 8 ++++++++ 4 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 debug.plist diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index a102c71a6f..5ae051644a 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -778,28 +778,28 @@ impl Interactivity { }); } - for listener in self.mouse_down_listeners.drain(..) { + for listener in self.mouse_down_listeners { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { listener(event, &*interactive_bounds, phase, cx); }) } - for listener in self.mouse_up_listeners.drain(..) { + for listener in self.mouse_up_listeners { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { listener(event, &*interactive_bounds, phase, cx); }) } - for listener in self.mouse_move_listeners.drain(..) { + for listener in self.mouse_move_listeners { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { listener(event, &*interactive_bounds, phase, cx); }) } - for listener in self.scroll_wheel_listeners.drain(..) { + for listener in self.scroll_wheel_listeners { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { listener(event, &*interactive_bounds, phase, cx); @@ -868,8 +868,8 @@ impl Interactivity { } } - let click_listeners = mem::take(&mut self.click_listeners); - let drag_listener = mem::take(&mut self.drag_listener); + let click_listeners = self.click_listeners; + let drag_listener = self.drag_listener; if !click_listeners.is_empty() || drag_listener.is_some() { let pending_mouse_down = element_state.pending_mouse_down.clone(); @@ -1086,13 +1086,13 @@ impl Interactivity { self.key_context.clone(), element_state.focus_handle.clone(), |_, cx| { - for listener in self.key_down_listeners.drain(..) { + for listener in self.key_down_listeners { cx.on_key_event(move |event: &KeyDownEvent, phase, cx| { listener(event, phase, cx); }) } - for listener in self.key_up_listeners.drain(..) { + for listener in self.key_up_listeners { cx.on_key_event(move |event: &KeyUpEvent, phase, cx| { listener(event, phase, cx); }) diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 46a9086478..d3506e93fa 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -208,11 +208,16 @@ impl AnyView { cx: &mut WindowContext, ) { cx.with_absolute_element_offset(origin, |cx| { + let start_time = std::time::Instant::now(); let (layout_id, rendered_element) = (self.layout)(self, cx); + let duration = start_time.elapsed(); + println!("request layout: {:?}", duration); + let start_time = std::time::Instant::now(); cx.compute_layout(layout_id, available_space); let duration = start_time.elapsed(); println!("compute layout: {:?}", duration); + let start_time = std::time::Instant::now(); (self.paint)(self, rendered_element, cx); let duration = start_time.elapsed(); diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 4624bcf20b..a6e738db54 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -42,8 +42,26 @@ const ACTIVE_DRAG_Z_INDEX: u32 = 1; /// A global stacking order, which is created by stacking successive z-index values. /// Each z-index will always be interpreted in the context of its parent z-index. -#[derive(Deref, DerefMut, Ord, PartialOrd, Eq, PartialEq, Clone, Default, Debug)] -pub struct StackingOrder(pub(crate) SmallVec<[u32; 16]>); +#[derive(Deref, DerefMut, Ord, PartialOrd, Eq, PartialEq, Clone, Debug)] +pub struct StackingOrder(pub(crate) Arc>); + +impl Default for StackingOrder { + fn default() -> Self { + StackingOrder(Arc::new(Vec::new())) + } +} + +impl StackingOrder { + /// Pushes a new z-index onto the stacking order. + pub fn push(&mut self, z_index: u32) { + Arc::make_mut(&mut self.0).push(z_index); + } + + /// Pops the last z-index off the stacking order. + pub fn pop(&mut self) { + Arc::make_mut(&mut self.0).pop(); + } +} /// Represents the two different phases when dispatching events. #[derive(Default, Copy, Clone, Debug, Eq, PartialEq)] @@ -2892,12 +2910,12 @@ impl AnyWindowHandle { } } -#[cfg(any(test, feature = "test-support"))] -impl From> for StackingOrder { - fn from(small_vec: SmallVec<[u32; 16]>) -> Self { - StackingOrder(small_vec) - } -} +// #[cfg(any(test, feature = "test-support"))] +// impl From> for StackingOrder { +// fn from(small_vec: SmallVec<[u32; 16]>) -> Self { +// StackingOrder(small_vec) +// } +// } #[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum ElementId { diff --git a/debug.plist b/debug.plist new file mode 100644 index 0000000000..e09573c9d1 --- /dev/null +++ b/debug.plist @@ -0,0 +1,8 @@ + + + + + com.apple.security.get-task-allow + + + From 4ace342cf0d47946b26f22c71cdbd67590856cc1 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 14 Dec 2023 11:59:24 -0500 Subject: [PATCH 020/644] Fix typo --- crates/storybook2/src/stories/text.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index ccd13cb4d8..b279e004c7 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -50,7 +50,7 @@ impl Render for TextStory { )))) // NOTE: When rendering text in a horizonal flex container, // Taffy will not pass width constraints down from the parent. - // To fix this, render text in a praent with overflow: hidden, which + // To fix this, render text in a parent with overflow: hidden .child(div().h_5()) .child(div().flex().w_96().bg(red()).child(concat!( "flex-row. width 96. The quick brown fox jumps over the lazy dog. ", From 1ae25f52a114919abe9062e3ea3506473164345f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 14 Dec 2023 10:31:45 -0700 Subject: [PATCH 021/644] WIP --- crates/collab_ui2/src/face_pile.rs | 2 +- crates/gpui2/src/elements/div.rs | 65 ++++++++++++++++++------ crates/gpui2/src/style.rs | 2 +- crates/gpui2/src/styled.rs | 2 +- crates/gpui2/src/window.rs | 24 +++++---- crates/storybook2/src/stories/z_index.rs | 4 +- crates/ui2/src/styles/elevation.rs | 12 ++--- crates/workspace2/src/modal_layer.rs | 2 +- 8 files changed, 77 insertions(+), 36 deletions(-) diff --git a/crates/collab_ui2/src/face_pile.rs b/crates/collab_ui2/src/face_pile.rs index d181509c46..fd675127e4 100644 --- a/crates/collab_ui2/src/face_pile.rs +++ b/crates/collab_ui2/src/face_pile.rs @@ -17,7 +17,7 @@ impl RenderOnce for FacePile { let isnt_last = ix < player_count - 1; div() - .z_index((player_count - ix) as u32) + .z_index((player_count - ix) as u8) .when(isnt_last, |div| div.neg_mr_1()) .child(player) }); diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 5ae051644a..cc82ff3cb0 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -646,7 +646,10 @@ pub struct DivState { impl DivState { pub fn is_active(&self) -> bool { - self.interactive_state.pending_mouse_down.borrow().is_some() + self.interactive_state + .pending_mouse_down + .as_ref() + .map_or(false, |pending| pending.borrow().is_some()) } } @@ -872,11 +875,17 @@ impl Interactivity { let drag_listener = self.drag_listener; if !click_listeners.is_empty() || drag_listener.is_some() { - let pending_mouse_down = element_state.pending_mouse_down.clone(); + let pending_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); let mouse_down = pending_mouse_down.borrow().clone(); if let Some(mouse_down) = mouse_down { if let Some(drag_listener) = drag_listener { - let active_state = element_state.clicked_state.clone(); + let active_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .clone(); let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { @@ -929,8 +938,14 @@ impl Interactivity { } if let Some(hover_listener) = self.hover_listener.take() { - let was_hovered = element_state.hover_state.clone(); - let has_mouse_down = element_state.pending_mouse_down.clone(); + let was_hovered = element_state + .hover_state + .get_or_insert_with(Default::default) + .clone(); + let has_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { @@ -951,8 +966,14 @@ impl Interactivity { } if let Some(tooltip_builder) = self.tooltip_builder.take() { - let active_tooltip = element_state.active_tooltip.clone(); - let pending_mouse_down = element_state.pending_mouse_down.clone(); + let active_tooltip = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .clone(); + let pending_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { @@ -994,19 +1015,30 @@ impl Interactivity { } }); - let active_tooltip = element_state.active_tooltip.clone(); + let active_tooltip = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .clone(); cx.on_mouse_event(move |_: &MouseDownEvent, _, _| { active_tooltip.borrow_mut().take(); }); - if let Some(active_tooltip) = element_state.active_tooltip.borrow().as_ref() { + if let Some(active_tooltip) = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .borrow() + .as_ref() + { if active_tooltip.tooltip.is_some() { cx.active_tooltip = active_tooltip.tooltip.clone() } } } - let active_state = element_state.clicked_state.clone(); + let active_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .clone(); if active_state.borrow().is_clicked() { cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| { if phase == DispatchPhase::Capture { @@ -1180,7 +1212,10 @@ impl Interactivity { } } - let clicked_state = element_state.clicked_state.borrow(); + let clicked_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .borrow(); if clicked_state.group { if let Some(group) = self.group_active_style.as_ref() { style.refine(&group.style) @@ -1235,11 +1270,11 @@ impl Default for Interactivity { #[derive(Default)] pub struct InteractiveElementState { pub focus_handle: Option, - pub clicked_state: Rc>, - pub hover_state: Rc>, - pub pending_mouse_down: Rc>>, + pub clicked_state: Option>>, + pub hover_state: Option>>, + pub pending_mouse_down: Option>>>, pub scroll_offset: Option>>>, - pub active_tooltip: Rc>>, + pub active_tooltip: Option>>>, } pub struct ActiveTooltip { diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 04f247d076..d330e73585 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -107,7 +107,7 @@ pub struct Style { /// The mouse cursor style shown when the mouse pointer is over an element. pub mouse_cursor: Option, - pub z_index: Option, + pub z_index: Option, } impl Styled for StyleRefinement { diff --git a/crates/gpui2/src/styled.rs b/crates/gpui2/src/styled.rs index a39e5f9cf9..c7312da7ac 100644 --- a/crates/gpui2/src/styled.rs +++ b/crates/gpui2/src/styled.rs @@ -12,7 +12,7 @@ pub trait Styled: Sized { gpui2_macros::style_helpers!(); - fn z_index(mut self, z_index: u32) -> Self { + fn z_index(mut self, z_index: u8) -> Self { self.style().z_index = Some(z_index); self } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index a6e738db54..31e9afc695 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -38,28 +38,34 @@ use std::{ }; use util::ResultExt; -const ACTIVE_DRAG_Z_INDEX: u32 = 1; +const ACTIVE_DRAG_Z_INDEX: u8 = 1; /// A global stacking order, which is created by stacking successive z-index values. /// Each z-index will always be interpreted in the context of its parent z-index. -#[derive(Deref, DerefMut, Ord, PartialOrd, Eq, PartialEq, Clone, Debug)] -pub struct StackingOrder(pub(crate) Arc>); +#[derive(Deref, DerefMut, Clone, Debug, Ord, PartialOrd, PartialEq, Eq)] +pub struct StackingOrder { + #[deref] + #[deref_mut] + z_indices: Arc>, +} impl Default for StackingOrder { fn default() -> Self { - StackingOrder(Arc::new(Vec::new())) + StackingOrder { + z_indices: Arc::new(SmallVec::new()), + } } } impl StackingOrder { /// Pushes a new z-index onto the stacking order. - pub fn push(&mut self, z_index: u32) { - Arc::make_mut(&mut self.0).push(z_index); + pub fn push(&mut self, z_index: u8) { + Arc::make_mut(&mut self.z_indices).push(z_index); } /// Pops the last z-index off the stacking order. pub fn pop(&mut self) { - Arc::make_mut(&mut self.0).pop(); + Arc::make_mut(&mut self.z_indices).pop(); } } @@ -905,7 +911,7 @@ impl<'a> WindowContext<'a> { /// Called during painting to invoke the given closure in a new stacking context. The given /// z-index is interpreted relative to the previous call to `stack`. - pub fn with_z_index(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R { + pub fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { self.window.next_frame.z_index_stack.push(z_index); let result = f(self); self.window.next_frame.z_index_stack.pop(); @@ -2233,7 +2239,7 @@ impl<'a, V: 'static> ViewContext<'a, V> { &mut self.window_cx } - pub fn with_z_index(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R { + pub fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { self.window.next_frame.z_index_stack.push(z_index); let result = f(self); self.window.next_frame.z_index_stack.pop(); diff --git a/crates/storybook2/src/stories/z_index.rs b/crates/storybook2/src/stories/z_index.rs index c6a4b68cc3..9579b8c7fc 100644 --- a/crates/storybook2/src/stories/z_index.rs +++ b/crates/storybook2/src/stories/z_index.rs @@ -78,7 +78,7 @@ impl Styles for Div {} #[derive(IntoElement)] struct ZIndexExample { - z_index: u32, + z_index: u8, } impl RenderOnce for ZIndexExample { @@ -170,7 +170,7 @@ impl RenderOnce for ZIndexExample { } impl ZIndexExample { - pub fn new(z_index: u32) -> Self { + pub fn new(z_index: u8) -> Self { Self { z_index } } } diff --git a/crates/ui2/src/styles/elevation.rs b/crates/ui2/src/styles/elevation.rs index 88b2ff2e56..7b3835c2e5 100644 --- a/crates/ui2/src/styles/elevation.rs +++ b/crates/ui2/src/styles/elevation.rs @@ -20,14 +20,14 @@ pub enum ElevationIndex { } impl ElevationIndex { - pub fn z_index(self) -> u32 { + pub fn z_index(self) -> u8 { match self { ElevationIndex::Background => 0, - ElevationIndex::Surface => 100, - ElevationIndex::ElevatedSurface => 200, - ElevationIndex::Wash => 250, - ElevationIndex::ModalSurface => 300, - ElevationIndex::DraggedElement => 900, + ElevationIndex::Surface => 42, + ElevationIndex::ElevatedSurface => 84, + ElevationIndex::Wash => 126, + ElevationIndex::ModalSurface => 168, + ElevationIndex::DraggedElement => 210, } } diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index a428ba3e18..e0a6395f31 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -116,7 +116,7 @@ impl Render for ModalLayer { .size_full() .top_0() .left_0() - .z_index(400) + .z_index(169) .child( v_stack() .h(px(0.0)) From 0d30b698a493f92b774ae70675f4d5e825c98d65 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 14 Dec 2023 11:28:52 -0700 Subject: [PATCH 022/644] Don't allocate interactive bounds --- crates/gpui2/src/elements/div.rs | 12 ++++++------ crates/gpui2/src/window.rs | 16 ++-------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index cc82ff3cb0..fa8ef50bbb 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -748,10 +748,10 @@ impl Interactivity { cx.with_z_index(style.z_index.unwrap_or(0), |cx| cx.add_opaque_layer(bounds)) } - let interactive_bounds = Rc::new(InteractiveBounds { + let interactive_bounds = InteractiveBounds { bounds: bounds.intersect(&cx.content_mask().bounds), stacking_order: cx.stacking_order().clone(), - }); + }; if let Some(mouse_cursor) = style.mouse_cursor { let mouse_position = &cx.mouse_position(); @@ -784,28 +784,28 @@ impl Interactivity { for listener in self.mouse_down_listeners { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { - listener(event, &*interactive_bounds, phase, cx); + listener(event, &interactive_bounds, phase, cx); }) } for listener in self.mouse_up_listeners { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { - listener(event, &*interactive_bounds, phase, cx); + listener(event, &interactive_bounds, phase, cx); }) } for listener in self.mouse_move_listeners { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - listener(event, &*interactive_bounds, phase, cx); + listener(event, &interactive_bounds, phase, cx); }) } for listener in self.scroll_wheel_listeners { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - listener(event, &*interactive_bounds, phase, cx); + listener(event, &interactive_bounds, phase, cx); }) } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 31e9afc695..d43263f815 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -46,29 +46,17 @@ const ACTIVE_DRAG_Z_INDEX: u8 = 1; pub struct StackingOrder { #[deref] #[deref_mut] - z_indices: Arc>, + z_indices: SmallVec<[u8; 32]>, } impl Default for StackingOrder { fn default() -> Self { StackingOrder { - z_indices: Arc::new(SmallVec::new()), + z_indices: SmallVec::new(), } } } -impl StackingOrder { - /// Pushes a new z-index onto the stacking order. - pub fn push(&mut self, z_index: u8) { - Arc::make_mut(&mut self.z_indices).push(z_index); - } - - /// Pops the last z-index off the stacking order. - pub fn pop(&mut self) { - Arc::make_mut(&mut self.z_indices).pop(); - } -} - /// Represents the two different phases when dispatching events. #[derive(Default, Copy, Clone, Debug, Eq, PartialEq)] pub enum DispatchPhase { From 3d1dae9a0610c4b023cd348e01c57001c04d8396 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 14 Dec 2023 11:37:48 -0700 Subject: [PATCH 023/644] Make z_indices bigger in StackingOrder --- crates/gpui2/src/window.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index d43263f815..e3b1cb4eb5 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -46,7 +46,7 @@ const ACTIVE_DRAG_Z_INDEX: u8 = 1; pub struct StackingOrder { #[deref] #[deref_mut] - z_indices: SmallVec<[u8; 32]>, + z_indices: SmallVec<[u8; 64]>, } impl Default for StackingOrder { From c041799c6ad32c046ac51b5233cdfe227958bd7c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 14 Dec 2023 15:55:17 -0500 Subject: [PATCH 024/644] Extend Story components, allow linking to story file Co-Authored-By: Marshall Bowers <1486634+maxdeviant@users.noreply.github.com> --- Cargo.lock | 2 + crates/story/Cargo.toml | 1 + crates/story/src/story.rs | 274 ++++++++++++++++++++++++-- crates/storybook2/Cargo.toml | 1 + crates/storybook2/src/stories/text.rs | 137 +++++++------ 5 files changed, 344 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4281553aff..c5ec126de5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9211,6 +9211,7 @@ name = "story" version = "0.1.0" dependencies = [ "gpui2", + "smallvec", ] [[package]] @@ -9224,6 +9225,7 @@ dependencies = [ "editor2", "fuzzy2", "gpui2", + "indoc", "itertools 0.11.0", "language2", "log", diff --git a/crates/story/Cargo.toml b/crates/story/Cargo.toml index 384447af8f..b042cbab80 100644 --- a/crates/story/Cargo.toml +++ b/crates/story/Cargo.toml @@ -8,3 +8,4 @@ publish = false [dependencies] gpui = { package = "gpui2", path = "../gpui2" } +smallvec.workspace = true diff --git a/crates/story/src/story.rs b/crates/story/src/story.rs index d95c879ce0..c656f3729d 100644 --- a/crates/story/src/story.rs +++ b/crates/story/src/story.rs @@ -1,22 +1,109 @@ -use gpui::prelude::*; -use gpui::{div, hsla, Div, SharedString}; +use gpui::{div, hsla, AnyElement, Div, ElementId, Hsla, SharedString, Stateful, WindowContext}; +use gpui::{prelude::*, px}; +use smallvec::SmallVec; + +use std::path::PathBuf; +use std::sync::atomic::{AtomicUsize, Ordering}; +use std::time::{SystemTime, UNIX_EPOCH}; + +static COUNTER: AtomicUsize = AtomicUsize::new(0); + +pub fn reasonably_unique_id() -> String { + let now = SystemTime::now(); + let timestamp = now.duration_since(UNIX_EPOCH).unwrap(); + + let cnt = COUNTER.fetch_add(1, Ordering::Relaxed); + + let id = format!("{}_{}", timestamp.as_nanos(), cnt); + + id +} + +pub struct StoryColor { + pub primary: Hsla, + pub secondary: Hsla, + pub border: Hsla, + pub background: Hsla, + pub card_background: Hsla, + pub divider: Hsla, + pub link: Hsla, +} + +impl StoryColor { + pub fn new() -> Self { + Self { + primary: hsla(216. / 360., 11. / 100., 0. / 100., 1.), + secondary: hsla(216. / 360., 11. / 100., 16. / 100., 1.), + border: hsla(216. / 360., 11. / 100., 91. / 100., 1.), + background: hsla(0. / 360., 0. / 100., 100. / 100., 1.), + card_background: hsla(0. / 360., 0. / 100., 96. / 100., 1.), + divider: hsla(216. / 360., 11. / 100., 91. / 100., 1.), + link: hsla(206. / 360., 100. / 100., 50. / 100., 1.), + } + } +} + +pub fn story_color() -> StoryColor { + StoryColor::new() +} pub struct Story {} impl Story { pub fn container() -> Div { - div().size_full().flex().flex_col().pt_2().px_4().bg(hsla( - 0. / 360., - 0. / 100., - 100. / 100., - 1., - )) + div() + .size_full() + .flex() + .flex_col() + .bg(story_color().background) + } + + // TODO: Move all stories to container2, then rename + pub fn container2(relative_path: &'static str) -> Div { + div() + .size_full() + .flex() + .flex_col() + .bg(story_color().background) + .child( + div() + .flex() + .justify_between() + .p_2() + .border_b() + .border_color(story_color().border) + .child(Story::title_for::()) + .child( + div() + .text_xs() + .text_color(story_color().primary) + .child(Story::open_story_link(relative_path)), + ), + ) + } + + pub fn open_story_link(relative_path: &'static str) -> impl Element { + let path = PathBuf::from_iter([relative_path]); + div() + .id(SharedString::from(format!("id_{}", relative_path))) + .text_xs() + .text_color(story_color().primary) + .on_click({ + let path = path.clone(); + + move |_event, _cx| { + let path = format!("{}:0:0", path.to_string_lossy()); + + std::process::Command::new("zed").arg(path).spawn().ok(); + } + }) + .child(Story::link(path.to_string_lossy().to_string())) } pub fn title(title: impl Into) -> impl Element { div() - .text_xl() - .text_color(hsla(0. / 360., 0. / 100., 0. / 100., 1.)) + .text_xs() + .text_color(story_color().primary) .child(title.into()) } @@ -24,12 +111,173 @@ impl Story { Self::title(std::any::type_name::()) } + pub fn section() -> Div { + div().mt_4().mb_2() + } + + pub fn section_title() -> Div { + div().text_lg().text_color(story_color().primary) + } + + pub fn group() -> Div { + div().my_2().bg(story_color().background) + } + + pub fn code_block(code: impl Into) -> Div { + div() + .size_full() + .p_2() + .bg(gpui::black()) + .border() + .border_color(story_color().border) + .rounded_md() + .text_sm() + .text_color(gpui::white()) + .child(code.into()) + } + + pub fn divider() -> Div { + div().my_2().h(px(1.)).bg(story_color().divider) + } + + pub fn link(link: impl Into) -> impl Element { + div() + .id(ElementId::from(SharedString::from(reasonably_unique_id()))) + .text_xs() + .text_color(story_color().link) + .cursor(gpui::CursorStyle::PointingHand) + .child(link.into()) + } + + pub fn description(description: impl Into) -> impl Element { + div() + .text_sm() + .text_color(story_color().secondary) + .min_w_96() + .child(description.into()) + } + pub fn label(label: impl Into) -> impl Element { div() - .mt_4() - .mb_2() .text_xs() - .text_color(hsla(0. / 360., 0. / 100., 0. / 100., 1.)) + .text_color(story_color().primary) .child(label.into()) } + + /// Note: Not ui::v_stack() as the story crate doesn't depend on the ui crate. + pub fn v_stack() -> Div { + div().flex().flex_col().gap_1() + } +} + +#[derive(IntoElement)] +pub struct StoryItem { + label: SharedString, + item: AnyElement, + description: Option, + usage: Option, +} + +impl StoryItem { + pub fn new(label: impl Into, item: impl IntoElement) -> Self { + Self { + label: label.into(), + item: item.into_any_element(), + description: None, + usage: None, + } + } + + pub fn description(mut self, description: impl Into) -> Self { + self.description = Some(description.into()); + self + } + + pub fn usage(mut self, code: impl Into) -> Self { + self.usage = Some(code.into()); + self + } +} + +impl RenderOnce for StoryItem { + type Rendered = Div; + + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + div() + .my_2() + .flex() + .w_full() + .child( + Story::v_stack() + .px_2() + .flex_none() + .w_1_2() + .min_h_px() + .child(Story::label(self.label)) + .child( + div() + .rounded_sm() + .bg(story_color().card_background) + .border() + .border_color(story_color().border) + .child(self.item), + ) + .when_some(self.description, |this, description| { + this.child(Story::description(description)) + }), + ) + .child( + Story::v_stack() + .px_2() + .flex_none() + .w_1_2() + .min_h_px() + .when_some(self.usage, |this, usage| { + this.child(Story::label("Usage")) + .child(Story::code_block(usage)) + }), + ) + } +} + +#[derive(IntoElement)] +pub struct StorySection { + description: Option, + children: SmallVec<[AnyElement; 2]>, +} + +impl StorySection { + pub fn new() -> Self { + Self { + description: None, + children: SmallVec::new(), + } + } + + pub fn description(mut self, description: impl Into) -> Self { + self.description = Some(description.into()); + self + } +} + +impl RenderOnce for StorySection { + type Rendered = Div; + + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + Story::section() + // Section title + .py_2() + // Section description + .when_some(self.description.clone(), |section, description| { + section.child(Story::description(description)) + }) + .child(div().flex().flex_col().gap_2().children(self.children)) + .child(Story::divider()) + } +} + +impl ParentElement for StorySection { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + &mut self.children + } } diff --git a/crates/storybook2/Cargo.toml b/crates/storybook2/Cargo.toml index 949d07b06f..672bebe20e 100644 --- a/crates/storybook2/Cargo.toml +++ b/crates/storybook2/Cargo.toml @@ -22,6 +22,7 @@ editor = { package = "editor2", path = "../editor2" } chrono = "0.4" fuzzy = { package = "fuzzy2", path = "../fuzzy2" } gpui = { package = "gpui2", path = "../gpui2" } +indoc.workspace = true itertools = "0.11.0" language = { package = "language2", path = "../language2" } log.workspace = true diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index b279e004c7..279a2dbf4d 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -1,8 +1,6 @@ -use gpui::{ - blue, div, green, red, white, Div, HighlightStyle, InteractiveText, ParentElement, Render, - Styled, StyledText, View, VisualContext, WindowContext, -}; -use ui::v_stack; +use gpui::{div, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext}; +use indoc::indoc; +use story::*; pub struct TextStory; @@ -16,59 +14,82 @@ impl Render for TextStory { type Element = Div; fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { - v_stack() - .bg(blue()) - .child( - div() - .flex() - .child(div().max_w_96().bg(white()).child(concat!( - "max-width: 96. The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", - ))), - ) - .child(div().h_5()) - .child(div().flex().flex_col().w_96().bg(white()).child(concat!( - "flex-col. width: 96; The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", - ))) - .child(div().h_5()) - .child( - div() - .flex() - .child(div().min_w_96().bg(white()).child(concat!( - "min-width: 96. The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", -)))) - .child(div().h_5()) - .child(div().flex().w_96().bg(white()).child(div().overflow_hidden().child(concat!( - "flex-row. width 96. overflow-hidden. The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", - )))) - // NOTE: When rendering text in a horizonal flex container, - // Taffy will not pass width constraints down from the parent. - // To fix this, render text in a parent with overflow: hidden - .child(div().h_5()) - .child(div().flex().w_96().bg(red()).child(concat!( - "flex-row. width 96. The quick brown fox jumps over the lazy dog. ", - "Meanwhile, the lazy dog decided it was time for a change. ", - "He started daily workout routines, ate healthier and became the fastest dog in town.", - ))).child( - InteractiveText::new( - "interactive", - StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ - (6..11, HighlightStyle { - background_color: Some(green()), - ..Default::default() - }), - ]), + // let # = "The quick brown fox jumps over the lazy dog. Meanwhile, the lazy dog decided it was time for a change. He started daily workout routines, ate healthier and became the fastest dog in town."; + + Story::container2::("crates/storybook2/src/stories/text.rs").child( + StorySection::new().child( + StoryItem::new( + "Default Text", + div().flex().child(div().max_w_96().child("foo")), ) - .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { - println!("Clicked range {range_ix}"); - }) - ) + .description("Text with a max-width. Wraps based on set max-width.") + .usage(indoc! {r##" + div().max_w_96() + .child("Some text that you want to wrap.") + "## + }), + ), + ) } } + +// impl Render for TextStory { +// type Element = Div; + +// fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { +// v_stack() +// .bg(blue()) +// .child( +// div() +// .flex() +// .child(div().max_w_96().bg(white()).child(concat!( +// "max-width: 96. The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// ))), +// ) +// .child(div().h_5()) +// .child(div().flex().flex_col().w_96().bg(white()).child(concat!( +// "flex-col. width: 96; The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// ))) +// .child(div().h_5()) +// .child( +// div() +// .flex() +// .child(div().min_w_96().bg(white()).child(concat!( +// "min-width: 96. The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// )))) +// .child(div().h_5()) +// .child(div().flex().w_96().bg(white()).child(div().overflow_hidden().child(concat!( +// "flex-row. width 96. overflow-hidden. The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// )))) +// // NOTE: When rendering text in a horizonal flex container, +// // Taffy will not pass width constraints down from the parent. +// // To fix this, render text in a parent with overflow: hidden +// .child(div().h_5()) +// .child(div().flex().w_96().bg(red()).child(concat!( +// "flex-row. width 96. The quick brown fox jumps over the lazy dog. ", +// "Meanwhile, the lazy dog decided it was time for a change. ", +// "He started daily workout routines, ate healthier and became the fastest dog in town.", +// ))).child( +// InteractiveText::new( +// "interactive", +// StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ +// (6..11, HighlightStyle { +// background_color: Some(green()), +// ..Default::default() +// }), +// ]), +// ) +// .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { +// println!("Clicked range {range_ix}"); +// }) +// ) +// } +// } From 2484a6969a96794e5ccc2c3821e20d9acf3bc341 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 14 Dec 2023 15:57:06 -0500 Subject: [PATCH 025/644] Fix toolbar flex sizing --- crates/workspace2/src/toolbar.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index b6d7b3e2cb..a6c8f9d0bf 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -109,8 +109,22 @@ impl Render for Toolbar { .child( h_stack() .justify_between() - .child(h_stack().children(self.left_items().map(|item| item.to_any()))) - .child(h_stack().children(self.right_items().map(|item| item.to_any()))), + .when(self.left_items().count() > 0, |this| { + this.child( + h_stack() + .flex_1() + .justify_start() + .children(self.left_items().map(|item| item.to_any())), + ) + }) + .when(self.right_items().count() > 0, |this| { + this.child( + h_stack() + .flex_1() + .justify_end() + .children(self.right_items().map(|item| item.to_any())), + ) + }), ) .children(secondary_item) } From c166311c06669839710e2d14e4c2506d8fc1f62d Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 14 Dec 2023 15:58:17 -0500 Subject: [PATCH 026/644] Style "Replace in project" input --- crates/search2/src/project_search.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 6e71253b1c..059003e909 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -1606,12 +1606,16 @@ impl Render for ProjectSearchBar { ); let replace_column = if search.replace_enabled { h_stack() - .p_1() .flex_1() - .border_2() + .h_full() + .gap_2() + .px_2() + .py_1() + .border_1() + .border_color(cx.theme().colors().border) .rounded_lg() .child(IconElement::new(Icon::Replace).size(ui::IconSize::Small)) - .child(search.replacement_editor.clone()) + .child(self.render_text_input(&search.replacement_editor, cx)) } else { // Fill out the space if we don't have a replacement editor. h_stack().flex_1() @@ -1674,10 +1678,10 @@ impl Render for ProjectSearchBar { ]); v_stack() .key_context(key_context) + .flex_grow() .p_1() .m_2() .gap_2() - .justify_between() .on_action(cx.listener(|this, _: &ToggleFilters, cx| { this.toggle_filters(cx); })) @@ -1731,6 +1735,7 @@ impl Render for ProjectSearchBar { }) .child( h_stack() + .justify_between() .child(query_column) .child(mode_column) .child(replace_column) From 0dd6c50a200bdc3b1cad2d48b8f38b85f9f5a458 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 14 Dec 2023 14:06:19 -0700 Subject: [PATCH 027/644] Use FxHashMap for element state --- crates/gpui2/src/window.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index e3b1cb4eb5..fc8754afef 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -12,7 +12,7 @@ use crate::{ VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, }; use anyhow::{anyhow, Context as _, Result}; -use collections::HashMap; +use collections::FxHashMap; use derive_more::{Deref, DerefMut}; use futures::{ channel::{mpsc, oneshot}, @@ -263,8 +263,8 @@ pub(crate) struct ElementStateBox { // #[derive(Default)] pub(crate) struct Frame { - pub(crate) element_states: HashMap, - mouse_listeners: HashMap>, + pub(crate) element_states: FxHashMap, + mouse_listeners: FxHashMap>, pub(crate) dispatch_tree: DispatchTree, pub(crate) focus_listeners: Vec, pub(crate) scene_builder: SceneBuilder, @@ -277,8 +277,8 @@ pub(crate) struct Frame { impl Frame { fn new(dispatch_tree: DispatchTree) -> Self { Frame { - element_states: HashMap::default(), - mouse_listeners: HashMap::default(), + element_states: FxHashMap::default(), + mouse_listeners: FxHashMap::default(), dispatch_tree, focus_listeners: Vec::new(), scene_builder: SceneBuilder::default(), From 8791f7cefccc84982c2cc4e0516ea44cca0e35a3 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Thu, 14 Dec 2023 12:03:17 -0800 Subject: [PATCH 028/644] Enable dragging from project panel to panes Rework gpui2 drag API so that receivers need not specify the dragged view type. co-authored-by: Max co-authored-by: Conrad --- crates/collab_ui2/src/collab_panel.rs | 11 +- crates/gpui2/src/app.rs | 7 +- crates/gpui2/src/elements/div.rs | 89 +++++++----- crates/gpui2/src/window.rs | 3 +- crates/project_panel2/src/project_panel.rs | 37 +++-- crates/terminal_view2/src/terminal_element.rs | 1 - crates/workspace2/src/dock.rs | 4 +- crates/workspace2/src/pane.rs | 134 +++++++++++++----- crates/workspace2/src/workspace2.rs | 4 +- 9 files changed, 190 insertions(+), 100 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 298c7682eb..65a994e6d9 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2552,12 +2552,11 @@ impl CollabPanel { .group("") .flex() .w_full() - .on_drag({ - let channel = channel.clone(); - move |cx| { - let channel = channel.clone(); - cx.build_view(|cx| DraggedChannelView { channel, width }) - } + .on_drag(channel.clone(), move |channel, cx| { + cx.build_view(|cx| DraggedChannelView { + channel: channel.clone(), + width, + }) }) .drag_over::(|style| { style.bg(cx.theme().colors().ghost_element_hover) diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index 18f688f179..bfbdc6b4a6 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -1139,8 +1139,10 @@ impl AppContext { self.active_drag.is_some() } - pub fn active_drag(&self) -> Option { - self.active_drag.as_ref().map(|drag| drag.view.clone()) + pub fn active_drag(&self) -> Option<&T> { + self.active_drag + .as_ref() + .and_then(|drag| drag.value.downcast_ref()) } } @@ -1296,6 +1298,7 @@ impl DerefMut for GlobalLease { /// within the window or by dragging into the app from the underlying platform. pub struct AnyDrag { pub view: AnyView, + pub value: Box, pub cursor_offset: Point, } diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 1954e3086c..4eed40f2eb 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -15,6 +15,7 @@ use std::{ cell::RefCell, cmp::Ordering, fmt::Debug, + marker::PhantomData, mem, rc::Rc, time::Duration, @@ -30,9 +31,18 @@ pub struct GroupStyle { pub style: Box, } -pub struct DragMoveEvent { +pub struct DragMoveEvent { pub event: MouseMoveEvent, - pub drag: View, + drag: PhantomData, +} + +impl DragMoveEvent { + pub fn drag<'b>(&self, cx: &'b AppContext) -> &'b T { + cx.active_drag + .as_ref() + .and_then(|drag| drag.value.downcast_ref::()) + .expect("DragMoveEvent is only valid when the stored active drag is of the same type.") + } } pub trait InteractiveElement: Sized { @@ -198,24 +208,27 @@ pub trait InteractiveElement: Sized { self } - fn on_drag_move( + fn on_drag_move( mut self, - listener: impl Fn(&DragMoveEvent, &mut WindowContext) + 'static, + listener: impl Fn(&DragMoveEvent, &mut WindowContext) + 'static, ) -> Self where - W: Render, + T: Render, { self.interactivity().mouse_move_listeners.push(Box::new( move |event, bounds, phase, cx| { if phase == DispatchPhase::Capture && bounds.drag_target_contains(&event.position, cx) { - if let Some(view) = cx.active_drag().and_then(|view| view.downcast::().ok()) + if cx + .active_drag + .as_ref() + .is_some_and(|drag| drag.value.type_id() == TypeId::of::()) { (listener)( &DragMoveEvent { event: event.clone(), - drag: view, + drag: PhantomData, }, cx, ); @@ -363,14 +376,11 @@ pub trait InteractiveElement: Sized { self } - fn on_drop( - mut self, - listener: impl Fn(&View, &mut WindowContext) + 'static, - ) -> Self { + fn on_drop(mut self, listener: impl Fn(&T, &mut WindowContext) + 'static) -> Self { self.interactivity().drop_listeners.push(( - TypeId::of::(), - Box::new(move |dragged_view, cx| { - listener(&dragged_view.downcast().unwrap(), cx); + TypeId::of::(), + Box::new(move |dragged_value, cx| { + listener(dragged_value.downcast_ref().unwrap(), cx); }), )); self @@ -437,19 +447,24 @@ pub trait StatefulInteractiveElement: InteractiveElement { self } - fn on_drag(mut self, constructor: impl Fn(&mut WindowContext) -> View + 'static) -> Self + fn on_drag( + mut self, + value: T, + constructor: impl Fn(&T, &mut WindowContext) -> View + 'static, + ) -> Self where Self: Sized, + T: 'static, W: 'static + Render, { debug_assert!( self.interactivity().drag_listener.is_none(), "calling on_drag more than once on the same element is not supported" ); - self.interactivity().drag_listener = Some(Box::new(move |cursor_offset, cx| AnyDrag { - view: constructor(cx).into(), - cursor_offset, - })); + self.interactivity().drag_listener = Some(( + Box::new(value), + Box::new(move |value, cx| constructor(value.downcast_ref().unwrap(), cx).into()), + )); self } @@ -513,9 +528,9 @@ pub type ScrollWheelListener = pub type ClickListener = Box; -pub type DragListener = Box, &mut WindowContext) -> AnyDrag + 'static>; +pub type DragListener = Box AnyView + 'static>; -type DropListener = dyn Fn(AnyView, &mut WindowContext) + 'static; +type DropListener = Box; pub type TooltipBuilder = Rc AnyView + 'static>; @@ -712,9 +727,9 @@ pub struct Interactivity { pub key_down_listeners: Vec, pub key_up_listeners: Vec, pub action_listeners: Vec<(TypeId, ActionListener)>, - pub drop_listeners: Vec<(TypeId, Box)>, + pub drop_listeners: Vec<(TypeId, DropListener)>, pub click_listeners: Vec, - pub drag_listener: Option, + pub drag_listener: Option<(Box, DragListener)>, pub hover_listener: Option>, pub tooltip_builder: Option, @@ -998,8 +1013,10 @@ impl Interactivity { if phase == DispatchPhase::Bubble && interactive_bounds.drag_target_contains(&event.position, cx) { - if let Some(drag_state_type) = - cx.active_drag.as_ref().map(|drag| drag.view.entity_type()) + if let Some(drag_state_type) = cx + .active_drag + .as_ref() + .map(|drag| drag.value.as_ref().type_id()) { for (drop_state_type, listener) in &drop_listeners { if *drop_state_type == drag_state_type { @@ -1008,7 +1025,7 @@ impl Interactivity { .take() .expect("checked for type drag state type above"); - listener(drag.view.clone(), cx); + listener(drag.value.as_ref(), cx); cx.notify(); cx.stop_propagation(); } @@ -1022,13 +1039,13 @@ impl Interactivity { } let click_listeners = mem::take(&mut self.click_listeners); - let drag_listener = mem::take(&mut self.drag_listener); + let mut drag_listener = mem::take(&mut self.drag_listener); if !click_listeners.is_empty() || drag_listener.is_some() { let pending_mouse_down = element_state.pending_mouse_down.clone(); let mouse_down = pending_mouse_down.borrow().clone(); if let Some(mouse_down) = mouse_down { - if let Some(drag_listener) = drag_listener { + if drag_listener.is_some() { let active_state = element_state.clicked_state.clone(); let interactive_bounds = interactive_bounds.clone(); @@ -1041,10 +1058,18 @@ impl Interactivity { && interactive_bounds.visibly_contains(&event.position, cx) && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD { + let (drag_value, drag_listener) = drag_listener + .take() + .expect("The notify below should invalidate this callback"); + *active_state.borrow_mut() = ElementClickedState::default(); let cursor_offset = event.position - bounds.origin; - let drag = drag_listener(cursor_offset, cx); - cx.active_drag = Some(drag); + let drag = (drag_listener)(drag_value.as_ref(), cx); + cx.active_drag = Some(AnyDrag { + view: drag, + value: drag_value, + cursor_offset, + }); cx.notify(); cx.stop_propagation(); } @@ -1312,7 +1337,7 @@ impl Interactivity { if let Some(drag) = cx.active_drag.take() { for (state_type, group_drag_style) in &self.group_drag_over_styles { if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { - if *state_type == drag.view.entity_type() + if *state_type == drag.value.as_ref().type_id() && group_bounds.contains(&mouse_position) { style.refine(&group_drag_style.style); @@ -1321,7 +1346,7 @@ impl Interactivity { } for (state_type, drag_over_style) in &self.drag_over_styles { - if *state_type == drag.view.entity_type() + if *state_type == drag.value.as_ref().type_id() && bounds .intersect(&cx.content_mask().bounds) .contains(&mouse_position) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 585db90c6f..fd29741986 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -806,7 +806,7 @@ impl<'a> WindowContext<'a> { /// a specific need to register a global listener. pub fn on_mouse_event( &mut self, - handler: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, + mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { let order = self.window.next_frame.z_index_stack.clone(); self.window @@ -1379,6 +1379,7 @@ impl<'a> WindowContext<'a> { self.window.mouse_position = position; if self.active_drag.is_none() { self.active_drag = Some(AnyDrag { + value: Box::new(files.clone()), view: self.build_view(|_| files).into(), cursor_offset: position, }); diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index adcd21cac6..417b351df7 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -1377,33 +1377,28 @@ impl ProjectPanel { }) .unwrap_or(theme.status().info); + let file_name = details.filename.clone(); + let icon = details.icon.clone(); + let depth = details.depth; div() .id(entry_id.to_proto() as usize) - .on_drag({ - let details = details.clone(); - move |cx| { - let details = details.clone(); - cx.build_view(|_| DraggedProjectEntryView { - details, - width, - entry_id, - }) - } + .on_drag(entry_id, move |entry_id, cx| { + cx.build_view(|_| DraggedProjectEntryView { + details: details.clone(), + width, + entry_id: *entry_id, + }) }) - .drag_over::(|style| { - style.bg(cx.theme().colors().ghost_element_hover) - }) - .on_drop(cx.listener( - move |this, dragged_view: &View, cx| { - this.move_entry(dragged_view.read(cx).entry_id, entry_id, kind.is_file(), cx); - }, - )) + .drag_over::(|style| style.bg(cx.theme().colors().ghost_element_hover)) + .on_drop(cx.listener(move |this, dragged_id: &ProjectEntryId, cx| { + this.move_entry(*dragged_id, entry_id, kind.is_file(), cx); + })) .child( ListItem::new(entry_id.to_proto() as usize) - .indent_level(details.depth) + .indent_level(depth) .indent_step_size(px(settings.indent_size)) .selected(is_selected) - .child(if let Some(icon) = &details.icon { + .child(if let Some(icon) = &icon { div().child(IconElement::from_path(icon.to_string())) } else { div() @@ -1414,7 +1409,7 @@ impl ProjectPanel { } else { div() .text_color(filename_text_color) - .child(Label::new(details.filename.clone())) + .child(Label::new(file_name)) } .ml_1(), ) diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index 7358f2e1d7..bced03e7ea 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -792,7 +792,6 @@ impl Element for TerminalElement { .on_drop::(move |external_paths, cx| { cx.focus(&terminal_focus_handle); let mut new_text = external_paths - .read(cx) .paths() .iter() .map(|path| format!(" {path:?}")) diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index f9e294763b..6a4740b6e2 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -493,7 +493,9 @@ impl Render for Dock { let handler = div() .id("resize-handle") .bg(cx.theme().colors().border) - .on_drag(move |cx| cx.build_view(|_| DraggedDock(position))) + .on_drag(DraggedDock(position), |dock, cx| { + cx.build_view(|_| dock.clone()) + }) .on_click(cx.listener(|v, e: &ClickEvent, cx| { if e.down.button == MouseButton::Left && e.down.click_count == 2 { v.resize_active_panel(None, cx) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index a55469fbad..2f6dec5bc4 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -231,6 +231,7 @@ pub struct NavigationEntry { pub timestamp: usize, } +#[derive(Clone)] struct DraggedTab { pub pane: View, pub ix: usize, @@ -1514,24 +1515,25 @@ impl Pane { .on_click(cx.listener(move |pane: &mut Self, event, cx| { pane.activate_item(ix, true, true, cx) })) - .on_drag({ - let pane = cx.view().clone(); - move |cx| { - cx.build_view(|cx| DraggedTab { - pane: pane.clone(), - detail, - item_id, - is_active, - ix, - }) - } - }) - .drag_over::(|tab| tab.bg(cx.theme().colors().tab_active_background)) - .on_drop( - cx.listener(move |this, dragged_tab: &View, cx| { - this.handle_tab_drop(dragged_tab, ix, cx) - }), + .on_drag( + DraggedTab { + pane: cx.view().clone(), + detail, + item_id, + is_active, + ix, + }, + |tab, cx| cx.build_view(|cx| tab.clone()), ) + .drag_over::(|tab| tab.bg(cx.theme().colors().tab_active_background)) + .drag_over::(|tab| tab.bg(gpui::red())) + .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { + this.handle_tab_drop(dragged_tab, ix, cx) + })) + .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { + dbg!(entry_id); + this.handle_project_entry_drop(entry_id, ix, cx) + })) .when_some(item.tab_tooltip_text(cx), |tab, text| { tab.tooltip(move |cx| Tooltip::text(text.clone(), cx)) }) @@ -1677,11 +1679,13 @@ impl Pane { .drag_over::(|bar| { bar.bg(cx.theme().colors().tab_active_background) }) - .on_drop( - cx.listener(move |this, dragged_tab: &View, cx| { - this.handle_tab_drop(dragged_tab, this.items.len(), cx) - }), - ), + .drag_over::(|bar| bar.bg(gpui::red())) + .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { + this.handle_tab_drop(dragged_tab, this.items.len(), cx) + })) + .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { + this.handle_project_entry_drop(entry_id, this.items.len(), cx) + })), ) } @@ -1743,11 +1747,10 @@ impl Pane { fn handle_tab_drop( &mut self, - dragged_tab: &View, + dragged_tab: &DraggedTab, ix: usize, cx: &mut ViewContext<'_, Pane>, ) { - let dragged_tab = dragged_tab.read(cx); let item_id = dragged_tab.item_id; let from_pane = dragged_tab.pane.clone(); let to_pane = cx.view().clone(); @@ -1760,13 +1763,37 @@ impl Pane { .log_err(); } + fn handle_project_entry_drop( + &mut self, + project_entry_id: &ProjectEntryId, + ix: usize, + cx: &mut ViewContext<'_, Pane>, + ) { + let to_pane = cx.view().downgrade(); + let project_entry_id = *project_entry_id; + self.workspace + .update(cx, |workspace, cx| { + cx.defer(move |workspace, cx| { + if let Some(path) = workspace + .project() + .read(cx) + .path_for_entry(project_entry_id, cx) + { + workspace + .open_path(path, Some(to_pane), true, cx) + .detach_and_log_err(cx); + } + }); + }) + .log_err(); + } + fn handle_split_tab_drop( &mut self, - dragged_tab: &View, + dragged_tab: &DraggedTab, split_direction: SplitDirection, cx: &mut ViewContext<'_, Pane>, ) { - let dragged_tab = dragged_tab.read(cx); let item_id = dragged_tab.item_id; let from_pane = dragged_tab.pane.clone(); let to_pane = cx.view().clone(); @@ -1780,13 +1807,40 @@ impl Pane { .map(|item| item.boxed_clone()); if let Some(item) = item { if let Some(item) = item.clone_on_split(workspace.database_id(), cx) { - workspace.split_item(split_direction, item, cx); + let pane = workspace.split_pane(to_pane, split_direction, cx); + workspace.move_item(from_pane, pane, item_id, 0, cx); } } }); }) .log_err(); } + + fn handle_split_project_entry_drop( + &mut self, + project_entry_id: &ProjectEntryId, + split_direction: SplitDirection, + cx: &mut ViewContext<'_, Pane>, + ) { + let project_entry_id = *project_entry_id; + let current_pane = cx.view().clone(); + self.workspace + .update(cx, |workspace, cx| { + cx.defer(move |workspace, cx| { + if let Some(path) = workspace + .project() + .read(cx) + .path_for_entry(project_entry_id, cx) + { + let pane = workspace.split_pane(current_pane, split_direction, cx); + workspace + .open_path(path, Some(pane.downgrade()), true, cx) + .detach_and_log_err(cx); + } + }); + }) + .log_err(); + } } impl FocusableView for Pane { @@ -1894,11 +1948,17 @@ impl Render for Pane { .full() .z_index(1) .drag_over::(|style| style.bg(drag_target_color)) - .on_drop(cx.listener( - move |this, dragged_tab: &View, cx| { - this.handle_tab_drop(dragged_tab, this.active_item_index(), cx) - }, - )), + .drag_over::(|style| style.bg(gpui::red())) + .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { + this.handle_tab_drop(dragged_tab, this.active_item_index(), cx) + })) + .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { + this.handle_project_entry_drop( + entry_id, + this.active_item_index(), + cx, + ) + })), ) .children( [ @@ -1915,9 +1975,15 @@ impl Render for Pane { .invisible() .bg(drag_target_color) .drag_over::(|style| style.visible()) + .drag_over::(|style| style.visible()) + .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { + this.handle_split_tab_drop(dragged_tab, direction, cx) + })) .on_drop(cx.listener( - move |this, dragged_tab: &View, cx| { - this.handle_split_tab_drop(dragged_tab, direction, cx) + move |this, entry_id: &ProjectEntryId, cx| { + this.handle_split_project_entry_drop( + entry_id, direction, cx, + ) }, )); match direction { diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index a07c5818a0..87083b0929 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -3580,7 +3580,7 @@ impl FocusableView for Workspace { struct WorkspaceBounds(Bounds); -#[derive(Render)] +#[derive(Clone, Render)] struct DraggedDock(DockPosition); impl Render for Workspace { @@ -3636,7 +3636,7 @@ impl Render for Workspace { ) .on_drag_move( cx.listener(|workspace, e: &DragMoveEvent, cx| { - match e.drag.read(cx).0 { + match e.drag(cx).0 { DockPosition::Left => { let size = workspace.bounds.left() + e.event.position.x; workspace.left_dock.update(cx, |left_dock, cx| { From 6b06bb4ffe924a54f939f0c6825c566c8ff540a4 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Dec 2023 13:30:11 -0800 Subject: [PATCH 029/644] Re-enable cmd- key bindings for activating panes co-authored-by: Conrad --- crates/workspace2/src/workspace2.rs | 45 +++++------------------------ 1 file changed, 7 insertions(+), 38 deletions(-) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index a07c5818a0..991a124693 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -3,13 +3,12 @@ pub mod dock; pub mod item; +mod modal_layer; pub mod notifications; pub mod pane; pub mod pane_group; mod persistence; pub mod searchable; -// todo!() -mod modal_layer; pub mod shared_screen; mod status_bar; mod toolbar; @@ -3313,42 +3312,12 @@ impl Workspace { ) .on_action(cx.listener(Workspace::open)) .on_action(cx.listener(Workspace::close_window)) - - // cx.add_action(Workspace::activate_pane_at_index); - // cx.add_action(|workspace: &mut Workspace, _: &ReopenClosedItem, cx| { - // workspace.reopen_closed_item(cx).detach(); - // }); - // cx.add_action(|workspace: &mut Workspace, _: &GoBack, cx| { - // workspace - // .go_back(workspace.active_pane().downgrade(), cx) - // .detach(); - // }); - // cx.add_action(|workspace: &mut Workspace, _: &GoForward, cx| { - // workspace - // .go_forward(workspace.active_pane().downgrade(), cx) - // .detach(); - // }); - - // cx.add_action(|_: &mut Workspace, _: &install_cli::Install, cx| { - // cx.spawn(|workspace, mut cx| async move { - // let err = install_cli::install_cli(&cx) - // .await - // .context("Failed to create CLI symlink"); - - // workspace.update(&mut cx, |workspace, cx| { - // if matches!(err, Err(_)) { - // err.notify_err(workspace, cx); - // } else { - // workspace.show_notification(1, cx, |cx| { - // cx.build_view(|_| { - // MessageNotification::new("Successfully installed the `zed` binary") - // }) - // }); - // } - // }) - // }) - // .detach(); - // }); + .on_action(cx.listener(Workspace::activate_pane_at_index)) + .on_action( + cx.listener(|workspace: &mut Workspace, _: &ReopenClosedItem, cx| { + workspace.reopen_closed_item(cx).detach(); + }), + ) } #[cfg(any(test, feature = "test-support"))] From 63c3edfb83a223c0822a160fc60e7a7de9c0d155 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 14 Dec 2023 16:52:05 -0500 Subject: [PATCH 030/644] Continue styling new story components --- Cargo.lock | 1 + crates/story/Cargo.toml | 1 + crates/story/src/story.rs | 34 +++++++++---- crates/storybook2/src/stories/text.rs | 72 +++++++++++++++++++++------ 4 files changed, 83 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c5ec126de5..1c74b49738 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9211,6 +9211,7 @@ name = "story" version = "0.1.0" dependencies = [ "gpui2", + "itertools 0.10.5", "smallvec", ] diff --git a/crates/story/Cargo.toml b/crates/story/Cargo.toml index b042cbab80..9c195f77f0 100644 --- a/crates/story/Cargo.toml +++ b/crates/story/Cargo.toml @@ -9,3 +9,4 @@ publish = false [dependencies] gpui = { package = "gpui2", path = "../gpui2" } smallvec.workspace = true +itertools = {package = "itertools", version = "0.10"} diff --git a/crates/story/src/story.rs b/crates/story/src/story.rs index c656f3729d..4985fb1961 100644 --- a/crates/story/src/story.rs +++ b/crates/story/src/story.rs @@ -1,5 +1,7 @@ -use gpui::{div, hsla, AnyElement, Div, ElementId, Hsla, SharedString, Stateful, WindowContext}; -use gpui::{prelude::*, px}; +use gpui::{ + div, hsla, prelude::*, px, rems, AnyElement, Div, ElementId, Hsla, SharedString, WindowContext, +}; +use itertools::Itertools; use smallvec::SmallVec; use std::path::PathBuf; @@ -37,7 +39,7 @@ impl StoryColor { border: hsla(216. / 360., 11. / 100., 91. / 100., 1.), background: hsla(0. / 360., 0. / 100., 100. / 100., 1.), card_background: hsla(0. / 360., 0. / 100., 96. / 100., 1.), - divider: hsla(216. / 360., 11. / 100., 91. / 100., 1.), + divider: hsla(216. / 360., 11. / 100., 86. / 100., 1.), link: hsla(206. / 360., 100. / 100., 50. / 100., 1.), } } @@ -112,7 +114,11 @@ impl Story { } pub fn section() -> Div { - div().mt_4().mb_2() + div() + .p_4() + .m_4() + .border() + .border_color(story_color().border) } pub fn section_title() -> Div { @@ -127,12 +133,12 @@ impl Story { div() .size_full() .p_2() + .max_w(rems(36.)) .bg(gpui::black()) - .border() - .border_color(story_color().border) .rounded_md() .text_sm() .text_color(gpui::white()) + .overflow_hidden() .child(code.into()) } @@ -206,20 +212,23 @@ impl RenderOnce for StoryItem { div() .my_2() .flex() + .gap_4() .w_full() .child( Story::v_stack() .px_2() - .flex_none() .w_1_2() .min_h_px() .child(Story::label(self.label)) .child( div() - .rounded_sm() + .rounded_md() .bg(story_color().card_background) .border() .border_color(story_color().border) + .py_1() + .px_2() + .overflow_hidden() .child(self.item), ) .when_some(self.description, |this, description| { @@ -233,7 +242,7 @@ impl RenderOnce for StoryItem { .w_1_2() .min_h_px() .when_some(self.usage, |this, usage| { - this.child(Story::label("Usage")) + this.child(Story::label("Example Usage")) .child(Story::code_block(usage)) }), ) @@ -264,6 +273,11 @@ impl RenderOnce for StorySection { type Rendered = Div; fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + let children: SmallVec<[AnyElement; 2]> = SmallVec::from_iter(Itertools::intersperse_with( + self.children.into_iter(), + || Story::divider().into_any_element(), + )); + Story::section() // Section title .py_2() @@ -271,7 +285,7 @@ impl RenderOnce for StorySection { .when_some(self.description.clone(), |section, description| { section.child(Story::description(description)) }) - .child(div().flex().flex_col().gap_2().children(self.children)) + .child(div().flex().flex_col().gap_2().children(children)) .child(Story::divider()) } } diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index 279a2dbf4d..b48b9dd4b5 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -1,4 +1,4 @@ -use gpui::{div, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext}; +use gpui::{div, red, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext}; use indoc::indoc; use story::*; @@ -13,22 +13,64 @@ impl TextStory { impl Render for TextStory { type Element = Div; - fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { - // let # = "The quick brown fox jumps over the lazy dog. Meanwhile, the lazy dog decided it was time for a change. He started daily workout routines, ate healthier and became the fastest dog in town."; - + fn render(&mut self, _cx: &mut gpui::ViewContext) -> Self::Element { Story::container2::("crates/storybook2/src/stories/text.rs").child( - StorySection::new().child( - StoryItem::new( - "Default Text", - div().flex().child(div().max_w_96().child("foo")), + StorySection::new() + .child( + StoryItem::new("Default", div().bg(gpui::blue()).child("Hello World!")) + .usage(indoc! {r##" + div() + .child("Hello World!") + "## + }), + ) + .child( + StoryItem::new("Wrapping Text", + div().max_w_96() + .child( + concat!( + "The quick brown fox jumps over the lazy dog. ", + "Meanwhile, the lazy dog decided it was time for a change. ", + "He started daily workout routines, ate healthier and became the fastest dog in town.", + ) + ) + ) + .description("Set a width or max-width to enable text wrapping.") + .usage(indoc! {r##" + div() + .max_w_96() + .child("Some text that you want to wrap.") + "## + }) + ) + .child( + StoryItem::new("tbd", + div().flex().w_96().child(div().overflow_hidden().child(concat!( + "flex-row. width 96. overflow-hidden. The quick brown fox jumps over the lazy dog. ", + "Meanwhile, the lazy dog decided it was time for a change. ", + "He started daily workout routines, ate healthier and became the fastest dog in town.", + ))) + ) + ) + .child( + StoryItem::new("Text in Horizontal Flex", + div().flex().w_96().bg(red()).child(concat!( + "flex-row. width 96. The quick brown fox jumps over the lazy dog. ", + "Meanwhile, the lazy dog decided it was time for a change. ", + "He started daily workout routines, ate healthier and became the fastest dog in town.", + )) + ) + .usage(indoc! {r##" + // NOTE: When rendering text in a horizonal flex container, + // Taffy will not pass width constraints down from the parent. + // To fix this, render text in a parent with overflow: hidden + + div() + .max_w_96() + .child("Some text that you want to wrap.") + "## + }) ) - .description("Text with a max-width. Wraps based on set max-width.") - .usage(indoc! {r##" - div().max_w_96() - .child("Some text that you want to wrap.") - "## - }), - ), ) } } From bbbdb9ff3e6cc90cf35c823e255cd694aa135af8 Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 14 Dec 2023 17:11:00 -0500 Subject: [PATCH 031/644] Render panel in this test to make sure it can receive focus --- crates/gpui2/src/app.rs | 1 - crates/gpui2/src/window.rs | 11 ++++++----- crates/project_panel2/src/project_panel.rs | 10 +++++++--- crates/workspace2/src/workspace2.rs | 1 + 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/crates/gpui2/src/app.rs b/crates/gpui2/src/app.rs index deb03498bc..771b561151 100644 --- a/crates/gpui2/src/app.rs +++ b/crates/gpui2/src/app.rs @@ -611,7 +611,6 @@ impl AppContext { .values() .filter_map(|window| { let window = window.as_ref()?; - dbg!(window.focus_invalidated); (window.dirty || window.focus_invalidated).then_some(window.handle) }) .collect::>() diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 895ae78862..557b2155f8 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -470,6 +470,7 @@ impl<'a> WindowContext<'a> { #[cfg(any(test, feature = "test-support"))] { + println!("invalidating focus"); self.window.focus_invalidated = true; } @@ -1237,6 +1238,11 @@ impl<'a> WindowContext<'a> { /// Draw pixels to the display for this window based on the contents of its scene. pub(crate) fn draw(&mut self) -> Scene { + #[cfg(any(test, feature = "test-support"))] + { + self.window.focus_invalidated = false; + } + self.text_system().start_frame(); self.window.platform_window.clear_input_handler(); self.window.layout_engine.as_mut().unwrap().clear(); @@ -1290,11 +1296,6 @@ impl<'a> WindowContext<'a> { let current_focus_path = self.window.rendered_frame.focus_path(); if previous_focus_path != current_focus_path { - #[cfg(any(test, feature = "test-support"))] - { - self.window.focus_invalidated = false; - } - if !previous_focus_path.is_empty() && current_focus_path.is_empty() { self.window .blur_listeners diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 5e71266c21..f7789c1a62 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -739,7 +739,6 @@ impl ProjectPanel { }); self.filename_editor.update(cx, |editor, cx| { editor.clear(cx); - println!("focusing"); editor.focus(cx); }); self.update_visible_entries(Some((worktree_id, NEW_ENTRY_ID)), cx); @@ -1672,7 +1671,7 @@ mod tests { path::{Path, PathBuf}, sync::atomic::{self, AtomicUsize}, }; - use workspace::AppState; + use workspace::{dock::PanelHandle, AppState}; #[gpui::test] async fn test_visible_list(cx: &mut gpui::TestAppContext) { @@ -2281,7 +2280,12 @@ mod tests { let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let cx = &mut VisualTestContext::from_window(*workspace, cx); let panel = workspace - .update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)) + .update(cx, |workspace, cx| { + let panel = ProjectPanel::new(workspace, cx); + workspace.add_panel(panel.clone(), cx); + workspace.toggle_dock(panel.read(cx).position(cx), cx); + panel + }) .unwrap(); select_path(&panel, "root1", cx); diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index a7dc76f41d..3cfb1f2458 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -532,6 +532,7 @@ impl Workspace { cx.notify() }) .detach(); + cx.on_blur_window(|this, cx| { let focus_handle = this.focus_handle(cx); cx.focus(&focus_handle); From d13a21c2388c6507ec66775529ccaa7ac1783e2b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 14 Dec 2023 15:15:18 -0700 Subject: [PATCH 032/644] Don't move in paint --- crates/editor2/src/element.rs | 9 +- crates/gpui2/src/element.rs | 24 +- crates/gpui2/src/elements/canvas.rs | 8 +- crates/gpui2/src/elements/div.rs | 516 +++++++++++------- crates/gpui2/src/elements/img.rs | 5 +- crates/gpui2/src/elements/list.rs | 4 +- crates/gpui2/src/elements/overlay.rs | 4 +- crates/gpui2/src/elements/svg.rs | 8 +- crates/gpui2/src/elements/text.rs | 15 +- crates/gpui2/src/elements/uniform_list.rs | 6 +- crates/gpui2/src/view.rs | 16 +- crates/terminal_view2/src/terminal_element.rs | 297 +++++----- crates/ui2/src/components/popover_menu.rs | 6 +- crates/ui2/src/components/right_click_menu.rs | 8 +- crates/workspace2/src/pane_group.rs | 4 +- 15 files changed, 537 insertions(+), 393 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 9b95e256a6..831b6cd35a 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -933,7 +933,7 @@ impl EditorElement { cx.stop_propagation(); }, )) - .draw( + .draw2( fold_bounds.origin, fold_bounds.size, cx, @@ -1199,11 +1199,10 @@ impl EditorElement { .child(mouse_context_menu.context_menu.clone()) .anchor(AnchorCorner::TopLeft) .snap_to_window(); - element.draw( + element.into_any().draw( gpui::Point::default(), size(AvailableSpace::MinContent, AvailableSpace::MinContent), cx, - |_, _| {}, ); } } @@ -1496,7 +1495,7 @@ impl EditorElement { let scroll_left = scroll_position.x * layout.position_map.em_width; let scroll_top = scroll_position.y * layout.position_map.line_height; - for block in layout.blocks.drain(..) { + for mut block in layout.blocks.drain(..) { let mut origin = bounds.origin + point( Pixels::ZERO, @@ -2781,7 +2780,7 @@ impl Element for EditorElement { } fn paint( - mut self, + &mut self, bounds: Bounds, element_state: &mut Self::State, cx: &mut gpui::WindowContext, diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index e5ecd195ba..f4bcb17f3c 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -23,7 +23,7 @@ pub trait IntoElement: Sized { self.into_element().into_any() } - fn draw( + fn draw2( self, origin: Point, available_space: Size, @@ -92,7 +92,7 @@ pub trait Element: 'static + IntoElement { cx: &mut WindowContext, ) -> (LayoutId, Self::State); - fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext); + fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext); fn into_any(self) -> AnyElement { AnyElement::new(self) @@ -150,8 +150,8 @@ impl Element for Component { } } - fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { - let element = state.rendered_element.take().unwrap(); + fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + let mut element = state.rendered_element.take().unwrap(); if let Some(element_id) = element.element_id() { cx.with_element_state(element_id, |element_state, cx| { let mut element_state = element_state.unwrap(); @@ -420,7 +420,7 @@ impl AnyElement { self.0.layout(cx) } - pub fn paint(mut self, cx: &mut WindowContext) { + pub fn paint(&mut self, cx: &mut WindowContext) { self.0.paint(cx) } @@ -435,7 +435,7 @@ impl AnyElement { /// Initializes this element and performs layout in the available space, then paints it at the given origin. pub fn draw( - mut self, + &mut self, origin: Point, available_space: Size, cx: &mut WindowContext, @@ -465,8 +465,8 @@ impl Element for AnyElement { (layout_id, ()) } - fn paint(self, _: Bounds, _: &mut Self::State, cx: &mut WindowContext) { - self.paint(cx); + fn paint(&mut self, _: Bounds, _: &mut Self::State, cx: &mut WindowContext) { + self.paint(cx) } } @@ -508,5 +508,11 @@ impl Element for () { (cx.request_layout(&crate::Style::default(), None), ()) } - fn paint(self, _bounds: Bounds, _state: &mut Self::State, _cx: &mut WindowContext) {} + fn paint( + &mut self, + _bounds: Bounds, + _state: &mut Self::State, + _cx: &mut WindowContext, + ) { + } } diff --git a/crates/gpui2/src/elements/canvas.rs b/crates/gpui2/src/elements/canvas.rs index b3afd335d4..56cfef4553 100644 --- a/crates/gpui2/src/elements/canvas.rs +++ b/crates/gpui2/src/elements/canvas.rs @@ -4,13 +4,13 @@ use crate::{Bounds, Element, IntoElement, Pixels, Style, StyleRefinement, Styled pub fn canvas(callback: impl 'static + FnOnce(&Bounds, &mut WindowContext)) -> Canvas { Canvas { - paint_callback: Box::new(callback), + paint_callback: Some(Box::new(callback)), style: StyleRefinement::default(), } } pub struct Canvas { - paint_callback: Box, &mut WindowContext)>, + paint_callback: Option, &mut WindowContext)>>, style: StyleRefinement, } @@ -40,8 +40,8 @@ impl Element for Canvas { (layout_id, ()) } - fn paint(self, bounds: Bounds, _: &mut (), cx: &mut WindowContext) { - (self.paint_callback)(&bounds, cx) + fn paint(&mut self, bounds: Bounds, _: &mut (), cx: &mut WindowContext) { + (self.paint_callback.take().unwrap())(&bounds, cx) } } diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index c24b5617d5..ff2e87e8e7 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -35,6 +35,281 @@ pub struct DragMoveEvent { pub drag: View, } +impl Interactivity { + pub fn on_mouse_down( + &mut self, + button: MouseButton, + listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, + ) { + self.mouse_down_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble + && event.button == button + && bounds.visibly_contains(&event.position, cx) + { + (listener)(event, cx) + } + })); + } + + pub fn on_any_mouse_down( + &mut self, + listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, + ) { + self.mouse_down_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { + (listener)(event, cx) + } + })); + } + + pub fn on_mouse_up( + &mut self, + button: MouseButton, + listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, + ) { + self.mouse_up_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble + && event.button == button + && bounds.visibly_contains(&event.position, cx) + { + (listener)(event, cx) + } + })); + } + + pub fn on_any_mouse_up( + &mut self, + listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, + ) { + self.mouse_up_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { + (listener)(event, cx) + } + })); + } + + pub fn on_mouse_down_out( + &mut self, + listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, + ) { + self.mouse_down_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Capture && !bounds.visibly_contains(&event.position, cx) + { + (listener)(event, cx) + } + })); + } + + pub fn on_mouse_up_out( + &mut self, + button: MouseButton, + listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, + ) { + self.mouse_up_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Capture + && event.button == button + && !bounds.visibly_contains(&event.position, cx) + { + (listener)(event, cx); + } + })); + } + + pub fn on_mouse_move( + &mut self, + listener: impl Fn(&MouseMoveEvent, &mut WindowContext) + 'static, + ) { + self.mouse_move_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { + (listener)(event, cx); + } + })); + } + + pub fn on_drag_move( + &mut self, + listener: impl Fn(&DragMoveEvent, &mut WindowContext) + 'static, + ) where + W: Render, + { + self.mouse_move_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Capture + && bounds.drag_target_contains(&event.position, cx) + { + if let Some(view) = cx.active_drag().and_then(|view| view.downcast::().ok()) + { + (listener)( + &DragMoveEvent { + event: event.clone(), + drag: view, + }, + cx, + ); + } + } + })); + } + + pub fn on_scroll_wheel( + &mut self, + listener: impl Fn(&ScrollWheelEvent, &mut WindowContext) + 'static, + ) { + self.scroll_wheel_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { + (listener)(event, cx); + } + })); + } + + pub fn capture_action( + &mut self, + listener: impl Fn(&A, &mut WindowContext) + 'static, + ) { + self.action_listeners.push(( + TypeId::of::(), + Box::new(move |action, phase, cx| { + let action = action.downcast_ref().unwrap(); + if phase == DispatchPhase::Capture { + (listener)(action, cx) + } + }), + )); + } + + pub fn on_action(&mut self, listener: impl Fn(&A, &mut WindowContext) + 'static) { + self.action_listeners.push(( + TypeId::of::(), + Box::new(move |action, phase, cx| { + let action = action.downcast_ref().unwrap(); + if phase == DispatchPhase::Bubble { + (listener)(action, cx) + } + }), + )); + } + + pub fn on_boxed_action( + &mut self, + action: &Box, + listener: impl Fn(&Box, &mut WindowContext) + 'static, + ) { + let action = action.boxed_clone(); + self.action_listeners.push(( + (*action).type_id(), + Box::new(move |_, phase, cx| { + if phase == DispatchPhase::Bubble { + (listener)(&action, cx) + } + }), + )); + } + + pub fn on_key_down(&mut self, listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static) { + self.key_down_listeners + .push(Box::new(move |event, phase, cx| { + if phase == DispatchPhase::Bubble { + (listener)(event, cx) + } + })); + } + + pub fn capture_key_down( + &mut self, + listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static, + ) { + self.key_down_listeners + .push(Box::new(move |event, phase, cx| { + if phase == DispatchPhase::Capture { + listener(event, cx) + } + })); + } + + pub fn on_key_up(&mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static) { + self.key_up_listeners + .push(Box::new(move |event, phase, cx| { + if phase == DispatchPhase::Bubble { + listener(event, cx) + } + })); + } + + pub fn capture_key_up(&mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static) { + self.key_up_listeners + .push(Box::new(move |event, phase, cx| { + if phase == DispatchPhase::Capture { + listener(event, cx) + } + })); + } + + pub fn on_drop( + &mut self, + listener: impl Fn(&View, &mut WindowContext) + 'static, + ) { + self.drop_listeners.push(( + TypeId::of::(), + Box::new(move |dragged_view, cx| { + listener(&dragged_view.downcast().unwrap(), cx); + }), + )); + } + + pub fn on_click(&mut self, listener: impl Fn(&ClickEvent, &mut WindowContext) + 'static) + where + Self: Sized, + { + self.click_listeners + .push(Box::new(move |event, cx| listener(event, cx))); + } + + pub fn on_drag(&mut self, constructor: impl Fn(&mut WindowContext) -> View + 'static) + where + Self: Sized, + W: 'static + Render, + { + debug_assert!( + self.drag_listener.is_none(), + "calling on_drag more than once on the same element is not supported" + ); + self.drag_listener = Some(Box::new(move |cursor_offset, cx| AnyDrag { + view: constructor(cx).into(), + cursor_offset, + })); + } + + pub fn on_hover(&mut self, listener: impl Fn(&bool, &mut WindowContext) + 'static) + where + Self: Sized, + { + debug_assert!( + self.hover_listener.is_none(), + "calling on_hover more than once on the same element is not supported" + ); + self.hover_listener = Some(Box::new(listener)); + } + + pub fn tooltip(&mut self, build_tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) + where + Self: Sized, + { + debug_assert!( + self.tooltip_builder.is_none(), + "calling tooltip more than once on the same element is not supported" + ); + self.tooltip_builder = Some(Rc::new(build_tooltip)); + } +} + pub trait InteractiveElement: Sized { fn interactivity(&mut self) -> &mut Interactivity; @@ -92,16 +367,7 @@ pub trait InteractiveElement: Sized { button: MouseButton, listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().mouse_down_listeners.push(Box::new( - move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble - && event.button == button - && bounds.visibly_contains(&event.position, cx) - { - (listener)(event, cx) - } - }, - )); + self.interactivity().on_mouse_down(button, listener); self } @@ -109,13 +375,7 @@ pub trait InteractiveElement: Sized { mut self, listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().mouse_down_listeners.push(Box::new( - move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { - (listener)(event, cx) - } - }, - )); + self.interactivity().on_any_mouse_down(listener); self } @@ -124,30 +384,7 @@ pub trait InteractiveElement: Sized { button: MouseButton, listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity() - .mouse_up_listeners - .push(Box::new(move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble - && event.button == button - && bounds.visibly_contains(&event.position, cx) - { - (listener)(event, cx) - } - })); - self - } - - fn on_any_mouse_up( - mut self, - listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, - ) -> Self { - self.interactivity() - .mouse_up_listeners - .push(Box::new(move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { - (listener)(event, cx) - } - })); + self.interactivity().on_mouse_up(button, listener); self } @@ -155,14 +392,7 @@ pub trait InteractiveElement: Sized { mut self, listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().mouse_down_listeners.push(Box::new( - move |event, bounds, phase, cx| { - if phase == DispatchPhase::Capture && !bounds.visibly_contains(&event.position, cx) - { - (listener)(event, cx) - } - }, - )); + self.interactivity().on_mouse_down_out(listener); self } @@ -171,16 +401,7 @@ pub trait InteractiveElement: Sized { button: MouseButton, listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity() - .mouse_up_listeners - .push(Box::new(move |event, bounds, phase, cx| { - if phase == DispatchPhase::Capture - && event.button == button - && !bounds.visibly_contains(&event.position, cx) - { - (listener)(event, cx); - } - })); + self.interactivity().on_mouse_up_out(button, listener); self } @@ -188,13 +409,7 @@ pub trait InteractiveElement: Sized { mut self, listener: impl Fn(&MouseMoveEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().mouse_move_listeners.push(Box::new( - move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { - (listener)(event, cx); - } - }, - )); + self.interactivity().on_mouse_move(listener); self } @@ -205,24 +420,7 @@ pub trait InteractiveElement: Sized { where W: Render, { - self.interactivity().mouse_move_listeners.push(Box::new( - move |event, bounds, phase, cx| { - if phase == DispatchPhase::Capture - && bounds.drag_target_contains(&event.position, cx) - { - if let Some(view) = cx.active_drag().and_then(|view| view.downcast::().ok()) - { - (listener)( - &DragMoveEvent { - event: event.clone(), - drag: view, - }, - cx, - ); - } - } - }, - )); + self.interactivity().on_drag_move(listener); self } @@ -230,13 +428,7 @@ pub trait InteractiveElement: Sized { mut self, listener: impl Fn(&ScrollWheelEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().scroll_wheel_listeners.push(Box::new( - move |event, bounds, phase, cx| { - if phase == DispatchPhase::Bubble && bounds.visibly_contains(&event.position, cx) { - (listener)(event, cx); - } - }, - )); + self.interactivity().on_scroll_wheel(listener); self } @@ -245,29 +437,13 @@ pub trait InteractiveElement: Sized { mut self, listener: impl Fn(&A, &mut WindowContext) + 'static, ) -> Self { - self.interactivity().action_listeners.push(( - TypeId::of::(), - Box::new(move |action, phase, cx| { - let action = action.downcast_ref().unwrap(); - if phase == DispatchPhase::Capture { - (listener)(action, cx) - } - }), - )); + self.interactivity().capture_action(listener); self } /// Add a listener for the given action, fires during the bubble event phase fn on_action(mut self, listener: impl Fn(&A, &mut WindowContext) + 'static) -> Self { - self.interactivity().action_listeners.push(( - TypeId::of::(), - Box::new(move |action, phase, cx| { - let action = action.downcast_ref().unwrap(); - if phase == DispatchPhase::Bubble { - (listener)(action, cx) - } - }), - )); + self.interactivity().on_action(listener); self } @@ -276,15 +452,7 @@ pub trait InteractiveElement: Sized { action: &Box, listener: impl Fn(&Box, &mut WindowContext) + 'static, ) -> Self { - let action = action.boxed_clone(); - self.interactivity().action_listeners.push(( - (*action).type_id(), - Box::new(move |_, phase, cx| { - if phase == DispatchPhase::Bubble { - (listener)(&action, cx) - } - }), - )); + self.interactivity().on_boxed_action(action, listener); self } @@ -292,13 +460,7 @@ pub trait InteractiveElement: Sized { mut self, listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity() - .key_down_listeners - .push(Box::new(move |event, phase, cx| { - if phase == DispatchPhase::Bubble { - (listener)(event, cx) - } - })); + self.interactivity().on_key_down(listener); self } @@ -306,24 +468,12 @@ pub trait InteractiveElement: Sized { mut self, listener: impl Fn(&KeyDownEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity() - .key_down_listeners - .push(Box::new(move |event, phase, cx| { - if phase == DispatchPhase::Capture { - listener(event, cx) - } - })); + self.interactivity().capture_key_down(listener); self } fn on_key_up(mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static) -> Self { - self.interactivity() - .key_up_listeners - .push(Box::new(move |event, phase, cx| { - if phase == DispatchPhase::Bubble { - listener(event, cx) - } - })); + self.interactivity().on_key_up(listener); self } @@ -331,13 +481,15 @@ pub trait InteractiveElement: Sized { mut self, listener: impl Fn(&KeyUpEvent, &mut WindowContext) + 'static, ) -> Self { - self.interactivity() - .key_up_listeners - .push(Box::new(move |event, phase, cx| { - if phase == DispatchPhase::Capture { - listener(event, cx) - } - })); + self.interactivity().capture_key_up(listener); + self + } + + fn on_drop( + mut self, + listener: impl Fn(&View, &mut WindowContext) + 'static, + ) -> Self { + self.interactivity().on_drop(listener); self } @@ -362,19 +514,6 @@ pub trait InteractiveElement: Sized { )); self } - - fn on_drop( - mut self, - listener: impl Fn(&View, &mut WindowContext) + 'static, - ) -> Self { - self.interactivity().drop_listeners.push(( - TypeId::of::(), - Box::new(move |dragged_view, cx| { - listener(&dragged_view.downcast().unwrap(), cx); - }), - )); - self - } } pub trait StatefulInteractiveElement: InteractiveElement { @@ -431,9 +570,7 @@ pub trait StatefulInteractiveElement: InteractiveElement { where Self: Sized, { - self.interactivity() - .click_listeners - .push(Box::new(move |event, cx| listener(event, cx))); + self.interactivity().on_click(listener); self } @@ -442,14 +579,7 @@ pub trait StatefulInteractiveElement: InteractiveElement { Self: Sized, W: 'static + Render, { - debug_assert!( - self.interactivity().drag_listener.is_none(), - "calling on_drag more than once on the same element is not supported" - ); - self.interactivity().drag_listener = Some(Box::new(move |cursor_offset, cx| AnyDrag { - view: constructor(cx).into(), - cursor_offset, - })); + self.interactivity().on_drag(constructor); self } @@ -457,11 +587,7 @@ pub trait StatefulInteractiveElement: InteractiveElement { where Self: Sized, { - debug_assert!( - self.interactivity().hover_listener.is_none(), - "calling on_hover more than once on the same element is not supported" - ); - self.interactivity().hover_listener = Some(Box::new(listener)); + self.interactivity().on_hover(listener); self } @@ -469,11 +595,7 @@ pub trait StatefulInteractiveElement: InteractiveElement { where Self: Sized, { - debug_assert!( - self.interactivity().tooltip_builder.is_none(), - "calling tooltip more than once on the same element is not supported" - ); - self.interactivity().tooltip_builder = Some(Rc::new(build_tooltip)); + self.interactivity().tooltip(build_tooltip); self } } @@ -529,6 +651,7 @@ pub type ActionListener = Box Div { + #[allow(unused_mut)] let mut div = Div { interactivity: Interactivity::default(), children: SmallVec::default(), @@ -598,7 +721,7 @@ impl Element for Div { } fn paint( - self, + &mut self, bounds: Bounds, element_state: &mut Self::State, cx: &mut WindowContext, @@ -649,7 +772,7 @@ impl Element for Div { cx.with_text_style(style.text_style().cloned(), |cx| { cx.with_content_mask(style.overflow_mask(bounds), |cx| { cx.with_element_offset(scroll_offset, |cx| { - for child in self.children { + for child in &mut self.children { child.paint(cx); } }) @@ -769,7 +892,7 @@ impl Interactivity { } pub fn paint( - mut self, + &mut self, bounds: Bounds, content_size: Size, element_state: &mut InteractiveElementState, @@ -788,7 +911,7 @@ impl Interactivity { && bounds.contains(&cx.mouse_position()) { const FONT_SIZE: crate::Pixels = crate::Pixels(10.); - let element_id = format!("{:?}", self.element_id.unwrap()); + let element_id = format!("{:?}", self.element_id.as_ref().unwrap()); let str_len = element_id.len(); let render_debug_text = |cx: &mut WindowContext| { @@ -934,28 +1057,28 @@ impl Interactivity { }); } - for listener in self.mouse_down_listeners { + for listener in self.mouse_down_listeners.drain(..) { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { listener(event, &interactive_bounds, phase, cx); }) } - for listener in self.mouse_up_listeners { + for listener in self.mouse_up_listeners.drain(..) { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { listener(event, &interactive_bounds, phase, cx); }) } - for listener in self.mouse_move_listeners { + for listener in self.mouse_move_listeners.drain(..) { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { listener(event, &interactive_bounds, phase, cx); }) } - for listener in self.scroll_wheel_listeners { + for listener in self.scroll_wheel_listeners.drain(..) { let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { listener(event, &interactive_bounds, phase, cx); @@ -1024,8 +1147,8 @@ impl Interactivity { } } - let click_listeners = self.click_listeners; - let drag_listener = self.drag_listener; + let click_listeners = mem::take(&mut self.click_listeners); + let drag_listener = mem::take(&mut self.drag_listener); if !click_listeners.is_empty() || drag_listener.is_some() { let pending_mouse_down = element_state @@ -1267,23 +1390,26 @@ impl Interactivity { .as_ref() .map(|scroll_offset| *scroll_offset.borrow()); + let key_down_listeners = mem::take(&mut self.key_down_listeners); + let key_up_listeners = mem::take(&mut self.key_up_listeners); + let action_listeners = mem::take(&mut self.action_listeners); cx.with_key_dispatch( self.key_context.clone(), element_state.focus_handle.clone(), |_, cx| { - for listener in self.key_down_listeners { + for listener in key_down_listeners { cx.on_key_event(move |event: &KeyDownEvent, phase, cx| { listener(event, phase, cx); }) } - for listener in self.key_up_listeners { + for listener in key_up_listeners { cx.on_key_event(move |event: &KeyUpEvent, phase, cx| { listener(event, phase, cx); }) } - for (action_type, listener) in self.action_listeners { + for (action_type, listener) in action_listeners { cx.on_action(action_type, listener) } @@ -1522,7 +1648,7 @@ where self.element.layout(state, cx) } - fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { self.element.paint(bounds, state, cx) } } @@ -1596,7 +1722,7 @@ where self.element.layout(state, cx) } - fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { self.element.paint(bounds, state, cx) } } diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index f6aae2de66..4f81f604c8 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -81,11 +81,12 @@ impl Element for Img { } fn paint( - self, + &mut self, bounds: Bounds, element_state: &mut Self::State, cx: &mut WindowContext, ) { + let source = self.source.clone(); self.interactivity.paint( bounds, bounds.size, @@ -94,7 +95,7 @@ impl Element for Img { |style, _scroll_offset, cx| { let corner_radii = style.corner_radii.to_pixels(bounds.size, cx.rem_size()); cx.with_z_index(1, |cx| { - match self.source { + match source { ImageSource::Uri(uri) => { let image_future = cx.image_cache.get(uri.clone()); if let Some(data) = image_future diff --git a/crates/gpui2/src/elements/list.rs b/crates/gpui2/src/elements/list.rs index ba479e1ea8..6818c5c7a2 100644 --- a/crates/gpui2/src/elements/list.rs +++ b/crates/gpui2/src/elements/list.rs @@ -257,7 +257,7 @@ impl Element for List { } fn paint( - self, + &mut self, bounds: crate::Bounds, _state: &mut Self::State, cx: &mut crate::WindowContext, @@ -385,7 +385,7 @@ impl Element for List { // Paint the visible items let mut item_origin = bounds.origin; item_origin.y -= scroll_top.offset_in_item; - for mut item_element in item_elements { + for item_element in &mut item_elements { let item_height = item_element.measure(available_item_space, cx).height; item_element.draw(item_origin, available_item_space, cx); item_origin.y += item_height; diff --git a/crates/gpui2/src/elements/overlay.rs b/crates/gpui2/src/elements/overlay.rs index e925d03d27..5b72019f17 100644 --- a/crates/gpui2/src/elements/overlay.rs +++ b/crates/gpui2/src/elements/overlay.rs @@ -81,7 +81,7 @@ impl Element for Overlay { } fn paint( - self, + &mut self, bounds: crate::Bounds, element_state: &mut Self::State, cx: &mut WindowContext, @@ -149,7 +149,7 @@ impl Element for Overlay { cx.with_element_offset(desired.origin - bounds.origin, |cx| { cx.break_content_mask(|cx| { - for child in self.children { + for child in &mut self.children { child.paint(cx); } }) diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index aba31686f5..9ca9baf470 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -36,8 +36,12 @@ impl Element for Svg { }) } - fn paint(self, bounds: Bounds, element_state: &mut Self::State, cx: &mut WindowContext) - where + fn paint( + &mut self, + bounds: Bounds, + element_state: &mut Self::State, + cx: &mut WindowContext, + ) where Self: Sized, { self.interactivity diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index b8fe5e6866..175a79c19a 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -6,7 +6,7 @@ use crate::{ use anyhow::anyhow; use parking_lot::{Mutex, MutexGuard}; use smallvec::SmallVec; -use std::{cell::Cell, ops::Range, rc::Rc, sync::Arc}; +use std::{cell::Cell, mem, ops::Range, rc::Rc, sync::Arc}; use util::ResultExt; impl Element for &'static str { @@ -22,7 +22,7 @@ impl Element for &'static str { (layout_id, state) } - fn paint(self, bounds: Bounds, state: &mut TextState, cx: &mut WindowContext) { + fn paint(&mut self, bounds: Bounds, state: &mut TextState, cx: &mut WindowContext) { state.paint(bounds, self, cx) } } @@ -52,7 +52,7 @@ impl Element for SharedString { (layout_id, state) } - fn paint(self, bounds: Bounds, state: &mut TextState, cx: &mut WindowContext) { + fn paint(&mut self, bounds: Bounds, state: &mut TextState, cx: &mut WindowContext) { let text_str: &str = self.as_ref(); state.paint(bounds, text_str, cx) } @@ -128,7 +128,7 @@ impl Element for StyledText { (layout_id, state) } - fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { state.paint(bounds, &self.text, cx) } } @@ -356,8 +356,8 @@ impl Element for InteractiveText { } } - fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { - if let Some(click_listener) = self.click_listener { + fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + if let Some(click_listener) = self.click_listener.take() { if let Some(ix) = state .text_state .index_for_position(bounds, cx.mouse_position()) @@ -374,13 +374,14 @@ impl Element for InteractiveText { let text_state = state.text_state.clone(); let mouse_down = state.mouse_down_index.clone(); if let Some(mouse_down_index) = mouse_down.get() { + let clickable_ranges = mem::take(&mut self.clickable_ranges); cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { if phase == DispatchPhase::Bubble { if let Some(mouse_up_index) = text_state.index_for_position(bounds, event.position) { click_listener( - &self.clickable_ranges, + &clickable_ranges, InteractiveTextClickEvent { mouse_down_index, mouse_up_index, diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index debd365c87..9fedbad41c 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -155,7 +155,7 @@ impl Element for UniformList { } fn paint( - self, + &mut self, bounds: Bounds, element_state: &mut Self::State, cx: &mut WindowContext, @@ -220,11 +220,11 @@ impl Element for UniformList { let visible_range = first_visible_element_ix ..cmp::min(last_visible_element_ix, self.item_count); - let items = (self.render_items)(visible_range.clone(), cx); + let mut items = (self.render_items)(visible_range.clone(), cx); cx.with_z_index(1, |cx| { let content_mask = ContentMask { bounds }; cx.with_content_mask(Some(content_mask), |cx| { - for (item, ix) in items.into_iter().zip(visible_range) { + for (item, ix) in items.iter_mut().zip(visible_range) { let item_origin = padded_bounds.origin + point(px(0.), item_height * ix + scroll_offset.y); let available_space = size( diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index d3506e93fa..7657ae2512 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -90,7 +90,7 @@ impl Element for View { (layout_id, Some(element)) } - fn paint(self, _: Bounds, element: &mut Self::State, cx: &mut WindowContext) { + fn paint(&mut self, _: Bounds, element: &mut Self::State, cx: &mut WindowContext) { element.take().unwrap().paint(cx); } } @@ -170,7 +170,7 @@ impl Eq for WeakView {} pub struct AnyView { model: AnyModel, layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, AnyElement), - paint: fn(&AnyView, AnyElement, &mut WindowContext), + paint: fn(&AnyView, &mut AnyElement, &mut WindowContext), } impl AnyView { @@ -209,7 +209,7 @@ impl AnyView { ) { cx.with_absolute_element_offset(origin, |cx| { let start_time = std::time::Instant::now(); - let (layout_id, rendered_element) = (self.layout)(self, cx); + let (layout_id, mut rendered_element) = (self.layout)(self, cx); let duration = start_time.elapsed(); println!("request layout: {:?}", duration); @@ -219,7 +219,7 @@ impl AnyView { println!("compute layout: {:?}", duration); let start_time = std::time::Instant::now(); - (self.paint)(self, rendered_element, cx); + (self.paint)(self, &mut rendered_element, cx); let duration = start_time.elapsed(); println!("paint: {:?}", duration); }) @@ -248,12 +248,12 @@ impl Element for AnyView { (layout_id, Some(state)) } - fn paint(self, _: Bounds, state: &mut Self::State, cx: &mut WindowContext) { + fn paint(&mut self, _: Bounds, state: &mut Self::State, cx: &mut WindowContext) { debug_assert!( state.is_some(), "state is None. Did you include an AnyView twice in the tree?" ); - (self.paint)(&self, state.take().unwrap(), cx) + (self.paint)(&self, state.as_mut().unwrap(), cx) } } @@ -284,7 +284,7 @@ impl IntoElement for AnyView { pub struct AnyWeakView { model: AnyWeakModel, layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, AnyElement), - paint: fn(&AnyView, AnyElement, &mut WindowContext), + paint: fn(&AnyView, &mut AnyElement, &mut WindowContext), } impl AnyWeakView { @@ -335,7 +335,7 @@ mod any_view { pub(crate) fn paint( _view: &AnyView, - element: AnyElement, + element: &mut AnyElement, cx: &mut WindowContext, ) { element.paint(cx); diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index 7358f2e1d7..7f221129f0 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -2,8 +2,8 @@ use editor::{Cursor, HighlightedRange, HighlightedRangeLine}; use gpui::{ black, div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, FontStyle, - FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, IntoElement, - LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, Pixels, + FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, Interactivity, + IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, Size, StatefulInteractiveElement, Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, }; @@ -145,11 +145,11 @@ pub struct TerminalElement { focused: bool, cursor_visible: bool, can_navigate_to_selected_word: bool, - interactivity: gpui::Interactivity, + interactivity: Interactivity, } impl InteractiveElement for TerminalElement { - fn interactivity(&mut self) -> &mut gpui::Interactivity { + fn interactivity(&mut self) -> &mut Interactivity { &mut self.interactivity } } @@ -605,141 +605,157 @@ impl TerminalElement { } fn register_mouse_listeners( - self, + &mut self, origin: Point, mode: TermMode, bounds: Bounds, cx: &mut WindowContext, - ) -> Self { + ) { let focus = self.focus.clone(); - let connection = self.terminal.clone(); + let terminal = self.terminal.clone(); - let mut this = self - .on_mouse_down(MouseButton::Left, { - let connection = connection.clone(); - let focus = focus.clone(); - move |e, cx| { - cx.focus(&focus); - //todo!(context menu) - // v.context_menu.update(cx, |menu, _cx| menu.delay_cancel()); - connection.update(cx, |terminal, cx| { - terminal.mouse_down(&e, origin); + self.interactivity.on_mouse_down(MouseButton::Left, { + let terminal = terminal.clone(); + let focus = focus.clone(); + move |e, cx| { + cx.focus(&focus); + //todo!(context menu) + // v.context_menu.update(cx, |menu, _cx| menu.delay_cancel()); + terminal.update(cx, |terminal, cx| { + terminal.mouse_down(&e, origin); + cx.notify(); + }) + } + }); + self.interactivity.on_mouse_move({ + let terminal = terminal.clone(); + let focus = focus.clone(); + move |e, cx| { + if e.pressed_button.is_some() && focus.is_focused(cx) && !cx.has_active_drag() { + terminal.update(cx, |terminal, cx| { + terminal.mouse_drag(e, origin, bounds); cx.notify(); }) } - }) - .on_mouse_move({ - let connection = connection.clone(); - let focus = focus.clone(); - move |e, cx| { - if e.pressed_button.is_some() && focus.is_focused(cx) && !cx.has_active_drag() { - connection.update(cx, |terminal, cx| { - terminal.mouse_drag(e, origin, bounds); - cx.notify(); - }) + } + }); + self.interactivity.on_mouse_up( + MouseButton::Left, + TerminalElement::generic_button_handler( + terminal.clone(), + origin, + focus.clone(), + move |terminal, origin, e, cx| { + terminal.mouse_up(&e, origin, cx); + }, + ), + ); + self.interactivity.on_click({ + let terminal = terminal.clone(); + move |e, cx| { + if e.down.button == MouseButton::Right { + let mouse_mode = terminal.update(cx, |terminal, _cx| { + terminal.mouse_mode(e.down.modifiers.shift) + }); + + if !mouse_mode { + //todo!(context menu) + // view.deploy_context_menu(e.position, cx); } } - }) - .on_mouse_up( - MouseButton::Left, + } + }); + + self.interactivity.on_mouse_move({ + let terminal = terminal.clone(); + let focus = focus.clone(); + move |e, cx| { + if focus.is_focused(cx) { + terminal.update(cx, |terminal, cx| { + terminal.mouse_move(&e, origin); + cx.notify(); + }) + } + } + }); + self.interactivity.on_scroll_wheel({ + let terminal = terminal.clone(); + move |e, cx| { + terminal.update(cx, |terminal, cx| { + terminal.scroll_wheel(e, origin); + cx.notify(); + }) + } + }); + + self.interactivity.on_drop::({ + let focus = focus.clone(); + let terminal = terminal.clone(); + move |external_paths, cx| { + cx.focus(&focus); + let mut new_text = external_paths + .read(cx) + .paths() + .iter() + .map(|path| format!(" {path:?}")) + .join(""); + new_text.push(' '); + terminal.update(cx, |terminal, _| { + // todo!() long paths are not displayed properly albeit the text is there + terminal.paste(&new_text); + }); + } + }); + + // Mouse mode handlers: + // All mouse modes need the extra click handlers + if mode.intersects(TermMode::MOUSE_MODE) { + self.interactivity.on_mouse_down( + MouseButton::Right, TerminalElement::generic_button_handler( - connection.clone(), + terminal.clone(), + origin, + focus.clone(), + move |terminal, origin, e, _cx| { + terminal.mouse_down(&e, origin); + }, + ), + ); + self.interactivity.on_mouse_down( + MouseButton::Middle, + TerminalElement::generic_button_handler( + terminal.clone(), + origin, + focus.clone(), + move |terminal, origin, e, _cx| { + terminal.mouse_down(&e, origin); + }, + ), + ); + self.interactivity.on_mouse_up( + MouseButton::Right, + TerminalElement::generic_button_handler( + terminal.clone(), origin, focus.clone(), move |terminal, origin, e, cx| { terminal.mouse_up(&e, origin, cx); }, ), - ) - .on_click({ - let connection = connection.clone(); - move |e, cx| { - if e.down.button == MouseButton::Right { - let mouse_mode = connection.update(cx, |terminal, _cx| { - terminal.mouse_mode(e.down.modifiers.shift) - }); - - if !mouse_mode { - //todo!(context menu) - // view.deploy_context_menu(e.position, cx); - } - } - } - }) - .on_mouse_move({ - let connection = connection.clone(); - let focus = focus.clone(); - move |e, cx| { - if focus.is_focused(cx) { - connection.update(cx, |terminal, cx| { - terminal.mouse_move(&e, origin); - cx.notify(); - }) - } - } - }) - .on_scroll_wheel({ - let connection = connection.clone(); - move |e, cx| { - connection.update(cx, |terminal, cx| { - terminal.scroll_wheel(e, origin); - cx.notify(); - }) - } - }); - - // Mouse mode handlers: - // All mouse modes need the extra click handlers - if mode.intersects(TermMode::MOUSE_MODE) { - this = this - .on_mouse_down( - MouseButton::Right, - TerminalElement::generic_button_handler( - connection.clone(), - origin, - focus.clone(), - move |terminal, origin, e, _cx| { - terminal.mouse_down(&e, origin); - }, - ), - ) - .on_mouse_down( - MouseButton::Middle, - TerminalElement::generic_button_handler( - connection.clone(), - origin, - focus.clone(), - move |terminal, origin, e, _cx| { - terminal.mouse_down(&e, origin); - }, - ), - ) - .on_mouse_up( - MouseButton::Right, - TerminalElement::generic_button_handler( - connection.clone(), - origin, - focus.clone(), - move |terminal, origin, e, cx| { - terminal.mouse_up(&e, origin, cx); - }, - ), - ) - .on_mouse_up( - MouseButton::Middle, - TerminalElement::generic_button_handler( - connection, - origin, - focus, - move |terminal, origin, e, cx| { - terminal.mouse_up(&e, origin, cx); - }, - ), - ) + ); + self.interactivity.on_mouse_up( + MouseButton::Middle, + TerminalElement::generic_button_handler( + terminal, + origin, + focus, + move |terminal, origin, e, cx| { + terminal.mouse_up(&e, origin, cx); + }, + ), + ); } - - this } } @@ -764,7 +780,12 @@ impl Element for TerminalElement { (layout_id, interactive_state) } - fn paint(self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext<'_>) { + fn paint( + &mut self, + bounds: Bounds, + state: &mut Self::State, + cx: &mut WindowContext<'_>, + ) { let mut layout = self.compute_layout(bounds, cx); let theme = cx.theme(); @@ -783,33 +804,19 @@ impl Element for TerminalElement { let terminal_focus_handle = self.focus.clone(); let terminal_handle = self.terminal.clone(); - let mut this: TerminalElement = self - .register_mouse_listeners(origin, layout.mode, bounds, cx) - .drag_over::(|style| { - // todo!() why does not it work? z-index of elements? - style.bg(cx.theme().colors().ghost_element_hover) - }) - .on_drop::(move |external_paths, cx| { - cx.focus(&terminal_focus_handle); - let mut new_text = external_paths - .read(cx) - .paths() - .iter() - .map(|path| format!(" {path:?}")) - .join(""); - new_text.push(' '); - terminal_handle.update(cx, |terminal, _| { - // todo!() long paths are not displayed properly albeit the text is there - terminal.paste(&new_text); - }); - }); + self.register_mouse_listeners(origin, layout.mode, bounds, cx); - let interactivity = mem::take(&mut this.interactivity); + // todo!(change this to work in terms of on_drag_move or some such) + // .drag_over::(|style| { + // // todo!() why does not it work? z-index of elements? + // style.bg(cx.theme().colors().ghost_element_hover) + // }) + let mut interactivity = mem::take(&mut self.interactivity); interactivity.paint(bounds, bounds.size, state, cx, |_, _, cx| { - cx.handle_input(&this.focus, terminal_input_handler); + cx.handle_input(&self.focus, terminal_input_handler); - this.register_key_listeners(cx); + self.register_key_listeners(cx); for rect in &layout.rects { rect.paint(origin, &layout, cx); @@ -840,7 +847,7 @@ impl Element for TerminalElement { } }); - if this.cursor_visible { + if self.cursor_visible { cx.with_z_index(3, |cx| { if let Some(cursor) = &layout.cursor { cursor.paint(origin, cx); @@ -848,7 +855,7 @@ impl Element for TerminalElement { }); } - if let Some(element) = layout.hyperlink_tooltip.take() { + if let Some(mut element) = layout.hyperlink_tooltip.take() { let width: AvailableSpace = bounds.size.width.into(); let height: AvailableSpace = bounds.size.height.into(); element.draw(origin, Size { width, height }, cx) diff --git a/crates/ui2/src/components/popover_menu.rs b/crates/ui2/src/components/popover_menu.rs index 4b5144e7c7..0f2fa6d23f 100644 --- a/crates/ui2/src/components/popover_menu.rs +++ b/crates/ui2/src/components/popover_menu.rs @@ -182,12 +182,12 @@ impl Element for PopoverMenu { } fn paint( - self, + &mut self, _: Bounds, element_state: &mut Self::State, cx: &mut WindowContext, ) { - if let Some(child) = element_state.child_element.take() { + if let Some(mut child) = element_state.child_element.take() { child.paint(cx); } @@ -195,7 +195,7 @@ impl Element for PopoverMenu { element_state.child_bounds = Some(cx.layout_bounds(child_layout_id)); } - if let Some(menu) = element_state.menu_element.take() { + if let Some(mut menu) = element_state.menu_element.take() { menu.paint(cx); if let Some(child_bounds) = element_state.child_bounds { diff --git a/crates/ui2/src/components/right_click_menu.rs b/crates/ui2/src/components/right_click_menu.rs index 19031b2be7..a3a454d652 100644 --- a/crates/ui2/src/components/right_click_menu.rs +++ b/crates/ui2/src/components/right_click_menu.rs @@ -112,21 +112,21 @@ impl Element for RightClickMenu { } fn paint( - self, + &mut self, bounds: Bounds, element_state: &mut Self::State, cx: &mut WindowContext, ) { - if let Some(child) = element_state.child_element.take() { + if let Some(mut child) = element_state.child_element.take() { child.paint(cx); } - if let Some(menu) = element_state.menu_element.take() { + if let Some(mut menu) = element_state.menu_element.take() { menu.paint(cx); return; } - let Some(builder) = self.menu_builder else { + let Some(builder) = self.menu_builder.take() else { return; }; let menu = element_state.menu.clone(); diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index 5f14df833d..5d79109dee 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -896,7 +896,7 @@ mod element { } fn paint( - self, + &mut self, bounds: gpui::Bounds, state: &mut Self::State, cx: &mut ui::prelude::WindowContext, @@ -912,7 +912,7 @@ mod element { let mut bounding_boxes = self.bounding_boxes.lock(); bounding_boxes.clear(); - for (ix, child) in self.children.into_iter().enumerate() { + for (ix, mut child) in self.children.iter_mut().enumerate() { //todo!(active_pane_magnification) // If usign active pane magnification, need to switch to using // 1 for all non-active panes, and then the magnification for the From 23d5f3f3e832ba68e0a191e7139c2e48a81445eb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Dec 2023 14:15:56 -0800 Subject: [PATCH 033/644] Enable all warnings in workspace, fix all warnings Bring back some workspace tests Co-authored-by: Conrad --- crates/gpui2/src/view.rs | 15 + crates/workspace2/src/dock.rs | 179 +----- crates/workspace2/src/item.rs | 6 +- crates/workspace2/src/modal_layer.rs | 6 +- crates/workspace2/src/notifications.rs | 43 +- crates/workspace2/src/pane.rs | 170 +++--- crates/workspace2/src/pane_group.rs | 416 +------------- crates/workspace2/src/searchable.rs | 4 +- crates/workspace2/src/status_bar.rs | 4 +- crates/workspace2/src/workspace2.rs | 729 ++++++++++++------------- 10 files changed, 474 insertions(+), 1098 deletions(-) diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 280c52df2a..351eb0ad06 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -7,6 +7,7 @@ use crate::{ use anyhow::{Context, Result}; use std::{ any::TypeId, + fmt, hash::{Hash, Hasher}, }; @@ -297,6 +298,20 @@ impl From> for AnyWeakView { } } +impl PartialEq for AnyWeakView { + fn eq(&self, other: &Self) -> bool { + self.model == other.model + } +} + +impl std::fmt::Debug for AnyWeakView { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("AnyWeakView") + .field("entity_id", &self.model.entity_id) + .finish_non_exhaustive() + } +} + impl Render for T where T: 'static + FnMut(&mut WindowContext) -> E, diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 6a4740b6e2..54480f0b68 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -41,7 +41,7 @@ pub trait Panel: FocusableView + EventEmitter { } pub trait PanelHandle: Send + Sync { - fn entity_id(&self) -> EntityId; + fn panel_id(&self) -> EntityId; fn persistent_name(&self) -> &'static str; fn position(&self, cx: &WindowContext) -> DockPosition; fn position_is_valid(&self, position: DockPosition, cx: &WindowContext) -> bool; @@ -62,7 +62,7 @@ impl PanelHandle for View where T: Panel, { - fn entity_id(&self) -> EntityId { + fn panel_id(&self) -> EntityId { Entity::entity_id(self) } @@ -135,7 +135,7 @@ pub struct Dock { is_open: bool, active_panel_index: usize, focus_handle: FocusHandle, - focus_subscription: Subscription, + _focus_subscription: Subscription, } impl FocusableView for Dock { @@ -187,7 +187,6 @@ struct PanelEntry { pub struct PanelButtons { dock: View, - workspace: WeakView, } impl Dock { @@ -204,7 +203,7 @@ impl Dock { active_panel_index: 0, is_open: false, focus_handle, - focus_subscription, + _focus_subscription: focus_subscription, } } @@ -261,7 +260,7 @@ impl Dock { pub fn set_panel_zoomed(&mut self, panel: &AnyView, zoomed: bool, cx: &mut ViewContext) { for entry in &mut self.panel_entries { - if entry.panel.entity_id() == panel.entity_id() { + if entry.panel.panel_id() == panel.entity_id() { if zoomed != entry.panel.is_zoomed(cx) { entry.panel.set_zoomed(zoomed, cx); } @@ -309,7 +308,7 @@ impl Dock { let was_visible = this.is_open() && this.visible_panel().map_or(false, |active_panel| { - active_panel.entity_id() == Entity::entity_id(&panel) + active_panel.panel_id() == Entity::entity_id(&panel) }); this.remove_panel(&panel, cx); @@ -351,7 +350,7 @@ impl Dock { if let Some(ix) = this .panel_entries .iter() - .position(|entry| entry.panel.entity_id() == Entity::entity_id(&panel)) + .position(|entry| entry.panel.panel_id() == Entity::entity_id(&panel)) { this.set_open(true, cx); this.activate_panel(ix, cx); @@ -361,7 +360,7 @@ impl Dock { PanelEvent::Close => { if this .visible_panel() - .map_or(false, |p| p.entity_id() == Entity::entity_id(&panel)) + .map_or(false, |p| p.panel_id() == Entity::entity_id(&panel)) { this.set_open(false, cx); } @@ -389,7 +388,7 @@ impl Dock { if let Some(panel_ix) = self .panel_entries .iter() - .position(|entry| entry.panel.entity_id() == Entity::entity_id(panel)) + .position(|entry| entry.panel.panel_id() == Entity::entity_id(panel)) { if panel_ix == self.active_panel_index { self.active_panel_index = 0; @@ -450,7 +449,7 @@ impl Dock { pub fn panel_size(&self, panel: &dyn PanelHandle, cx: &WindowContext) -> Option { self.panel_entries .iter() - .find(|entry| entry.panel.entity_id() == panel.entity_id()) + .find(|entry| entry.panel.panel_id() == panel.panel_id()) .map(|entry| entry.panel.size(cx)) } @@ -549,166 +548,12 @@ impl Render for Dock { } impl PanelButtons { - pub fn new( - dock: View, - workspace: WeakView, - cx: &mut ViewContext, - ) -> Self { + pub fn new(dock: View, cx: &mut ViewContext) -> Self { cx.observe(&dock, |_, _, cx| cx.notify()).detach(); - Self { dock, workspace } + Self { dock } } } -// impl Render for PanelButtons { -// type Element = (); - -// fn render(&mut self, cx: &mut ViewContext) -> Self::Element { -// todo!("") -// } - -// fn ui_name() -> &'static str { -// "PanelButtons" -// } - -// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { -// let theme = &settings::get::(cx).theme; -// let tooltip_style = theme.tooltip.clone(); -// let theme = &theme.workspace.status_bar.panel_buttons; -// let button_style = theme.button.clone(); -// let dock = self.dock.read(cx); -// let active_ix = dock.active_panel_index; -// let is_open = dock.is_open; -// let dock_position = dock.position; -// let group_style = match dock_position { -// DockPosition::Left => theme.group_left, -// DockPosition::Bottom => theme.group_bottom, -// DockPosition::Right => theme.group_right, -// }; -// let menu_corner = match dock_position { -// DockPosition::Left => AnchorCorner::BottomLeft, -// DockPosition::Bottom | DockPosition::Right => AnchorCorner::BottomRight, -// }; - -// let panels = dock -// .panel_entries -// .iter() -// .map(|item| (item.panel.clone(), item.context_menu.clone())) -// .collect::>(); -// Flex::row() -// .with_children(panels.into_iter().enumerate().filter_map( -// |(panel_ix, (view, context_menu))| { -// let icon_path = view.icon_path(cx)?; -// let is_active = is_open && panel_ix == active_ix; -// let (tooltip, tooltip_action) = if is_active { -// ( -// format!("Close {} dock", dock_position.to_label()), -// Some(match dock_position { -// DockPosition::Left => crate::ToggleLeftDock.boxed_clone(), -// DockPosition::Bottom => crate::ToggleBottomDock.boxed_clone(), -// DockPosition::Right => crate::ToggleRightDock.boxed_clone(), -// }), -// ) -// } else { -// view.icon_tooltip(cx) -// }; -// Some( -// Stack::new() -// .with_child( -// MouseEventHandler::new::(panel_ix, cx, |state, cx| { -// let style = button_style.in_state(is_active); - -// let style = style.style_for(state); -// Flex::row() -// .with_child( -// Svg::new(icon_path) -// .with_color(style.icon_color) -// .constrained() -// .with_width(style.icon_size) -// .aligned(), -// ) -// .with_children(if let Some(label) = view.icon_label(cx) { -// Some( -// Label::new(label, style.label.text.clone()) -// .contained() -// .with_style(style.label.container) -// .aligned(), -// ) -// } else { -// None -// }) -// .constrained() -// .with_height(style.icon_size) -// .contained() -// .with_style(style.container) -// }) -// .with_cursor_style(CursorStyle::PointingHand) -// .on_click(MouseButton::Left, { -// let tooltip_action = -// tooltip_action.as_ref().map(|action| action.boxed_clone()); -// move |_, this, cx| { -// if let Some(tooltip_action) = &tooltip_action { -// let window = cx.window(); -// let view_id = this.workspace.id(); -// let tooltip_action = tooltip_action.boxed_clone(); -// cx.spawn(|_, mut cx| async move { -// window.dispatch_action( -// view_id, -// &*tooltip_action, -// &mut cx, -// ); -// }) -// .detach(); -// } -// } -// }) -// .on_click(MouseButton::Right, { -// let view = view.clone(); -// let menu = context_menu.clone(); -// move |_, _, cx| { -// const POSITIONS: [DockPosition; 3] = [ -// DockPosition::Left, -// DockPosition::Right, -// DockPosition::Bottom, -// ]; - -// menu.update(cx, |menu, cx| { -// let items = POSITIONS -// .into_iter() -// .filter(|position| { -// *position != dock_position -// && view.position_is_valid(*position, cx) -// }) -// .map(|position| { -// let view = view.clone(); -// ContextMenuItem::handler( -// format!("Dock {}", position.to_label()), -// move |cx| view.set_position(position, cx), -// ) -// }) -// .collect(); -// menu.show(Default::default(), menu_corner, items, cx); -// }) -// } -// }) -// .with_tooltip::( -// panel_ix, -// tooltip, -// tooltip_action, -// tooltip_style.clone(), -// cx, -// ), -// ) -// .with_child(ChildView::new(&context_menu, cx)), -// ) -// }, -// )) -// .contained() -// .with_style(group_style) -// .into_any() -// } -// } - -// here be kittens impl Render for PanelButtons { type Element = Div; diff --git a/crates/workspace2/src/item.rs b/crates/workspace2/src/item.rs index c0242ffa17..43597f21a7 100644 --- a/crates/workspace2/src/item.rs +++ b/crates/workspace2/src/item.rs @@ -919,7 +919,7 @@ pub mod test { impl EventEmitter for TestItem {} impl FocusableView for TestItem { - fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle { + fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle { self.focus_handle.clone() } } @@ -941,8 +941,8 @@ pub mod test { fn tab_content( &self, detail: Option, - selected: bool, - cx: &ui::prelude::WindowContext, + _selected: bool, + _cx: &ui::prelude::WindowContext, ) -> AnyElement { self.tab_detail.set(detail); gpui::div().into_any_element() diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index a428ba3e18..8c1af48667 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -5,7 +5,7 @@ use gpui::{ use ui::{h_stack, v_stack}; pub trait ModalView: ManagedView { - fn on_before_dismiss(&mut self, cx: &mut ViewContext) -> bool { + fn on_before_dismiss(&mut self, _: &mut ViewContext) -> bool { true } } @@ -27,7 +27,7 @@ impl ModalViewHandle for View { pub struct ActiveModal { modal: Box, - subscription: Subscription, + _subscription: Subscription, previous_focus_handle: Option, focus_handle: FocusHandle, } @@ -63,7 +63,7 @@ impl ModalLayer { { self.active_modal = Some(ActiveModal { modal: Box::new(new_modal.clone()), - subscription: cx.subscribe(&new_modal, |this, modal, _: &DismissEvent, cx| { + _subscription: cx.subscribe(&new_modal, |this, _, _: &DismissEvent, cx| { this.hide_modal(cx); }), previous_focus_handle: cx.focused(), diff --git a/crates/workspace2/src/notifications.rs b/crates/workspace2/src/notifications.rs index 63475c2aba..a692388a06 100644 --- a/crates/workspace2/src/notifications.rs +++ b/crates/workspace2/src/notifications.rs @@ -104,12 +104,9 @@ impl Workspace { }) { let notification = build_notification(cx); - cx.subscribe( - ¬ification, - move |this, handle, event: &DismissEvent, cx| { - this.dismiss_notification_internal(type_id, id, cx); - }, - ) + cx.subscribe(¬ification, move |this, _, _: &DismissEvent, cx| { + this.dismiss_notification_internal(type_id, id, cx); + }) .detach(); self.notifications .push((type_id, id, Box::new(notification))); @@ -173,21 +170,15 @@ impl Workspace { pub mod simple_message_notification { use gpui::{ - div, AnyElement, AppContext, DismissEvent, Div, EventEmitter, InteractiveElement, - ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, TextStyle, - ViewContext, + div, DismissEvent, Div, EventEmitter, InteractiveElement, ParentElement, Render, + SharedString, StatefulInteractiveElement, Styled, ViewContext, }; use std::sync::Arc; use ui::prelude::*; use ui::{h_stack, v_stack, Button, Icon, IconElement, Label, StyledExt}; - enum NotificationMessage { - Text(SharedString), - Element(fn(TextStyle, &AppContext) -> AnyElement), - } - pub struct MessageNotification { - message: NotificationMessage, + message: SharedString, on_click: Option)>>, click_message: Option, } @@ -200,23 +191,12 @@ pub mod simple_message_notification { S: Into, { Self { - message: NotificationMessage::Text(message.into()), + message: message.into(), on_click: None, click_message: None, } } - // not needed I think (only for the "new panel" toast, which is outdated now) - // pub fn new_element( - // message: fn(TextStyle, &AppContext) -> AnyElement, - // ) -> MessageNotification { - // Self { - // message: NotificationMessage::Element(message), - // on_click: None, - // click_message: None, - // } - // } - pub fn with_click_message(mut self, message: S) -> Self where S: Into, @@ -248,18 +228,13 @@ pub mod simple_message_notification { .child( h_stack() .justify_between() - .child(div().max_w_80().child(match &self.message { - NotificationMessage::Text(text) => Label::new(text.clone()), - NotificationMessage::Element(element) => { - todo!() - } - })) + .child(div().max_w_80().child(Label::new(self.message.clone()))) .child( div() .id("cancel") .child(IconElement::new(Icon::Close)) .cursor_pointer() - .on_click(cx.listener(|this, event, cx| this.dismiss(cx))), + .on_click(cx.listener(|this, _, cx| this.dismiss(cx))), ), ) .children(self.click_message.iter().map(|message| { diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 2f6dec5bc4..4c436daada 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -7,7 +7,7 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ - actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyWeakView, AppContext, + actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AppContext, AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, @@ -164,11 +164,6 @@ impl fmt::Debug for Event { } } -struct FocusedView { - view: AnyWeakView, - focus_handle: FocusHandle, -} - pub struct Pane { focus_handle: FocusHandle, items: Vec>, @@ -187,7 +182,7 @@ pub struct Pane { // can_drop: Rc, &WindowContext) -> bool>, can_split: bool, // render_tab_bar_buttons: Rc) -> AnyElement>, - subscriptions: Vec, + _subscriptions: Vec, tab_bar_scroll_handle: ScrollHandle, } @@ -432,14 +427,10 @@ impl Pane { // }) // .into_any() // }), - subscriptions, + _subscriptions: subscriptions, } } - pub(crate) fn workspace(&self) -> &WeakView { - &self.workspace - } - pub fn has_focus(&self, cx: &WindowContext) -> bool { // todo!(); // inline this manually self.focus_handle.contains_focused(cx) @@ -1468,21 +1459,6 @@ impl Pane { let label = item.tab_content(Some(detail), is_active, cx); let close_side = &ItemSettings::get_global(cx).close_position; - let (text_color, tab_bg, tab_hover_bg, tab_active_bg) = match ix == self.active_item_index { - false => ( - cx.theme().colors().text_muted, - cx.theme().colors().tab_inactive_background, - cx.theme().colors().ghost_element_hover, - cx.theme().colors().ghost_element_active, - ), - true => ( - cx.theme().colors().text, - cx.theme().colors().tab_active_background, - cx.theme().colors().element_hover, - cx.theme().colors().element_active, - ), - }; - let indicator = maybe!({ let indicator_color = match (item.has_conflict(cx), item.is_dirty(cx)) { (true, _) => Color::Warning, @@ -1498,57 +1474,55 @@ impl Pane { let is_last_item = ix == self.items.len() - 1; let position_relative_to_active_item = ix.cmp(&self.active_item_index); - let tab = - Tab::new(ix) - .position(if is_first_item { - TabPosition::First - } else if is_last_item { - TabPosition::Last - } else { - TabPosition::Middle(position_relative_to_active_item) - }) - .close_side(match close_side { - ClosePosition::Left => ui::TabCloseSide::Start, - ClosePosition::Right => ui::TabCloseSide::End, - }) - .selected(is_active) - .on_click(cx.listener(move |pane: &mut Self, event, cx| { - pane.activate_item(ix, true, true, cx) - })) - .on_drag( - DraggedTab { - pane: cx.view().clone(), - detail, - item_id, - is_active, - ix, - }, - |tab, cx| cx.build_view(|cx| tab.clone()), - ) - .drag_over::(|tab| tab.bg(cx.theme().colors().tab_active_background)) - .drag_over::(|tab| tab.bg(gpui::red())) - .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { - this.handle_tab_drop(dragged_tab, ix, cx) - })) - .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { - dbg!(entry_id); - this.handle_project_entry_drop(entry_id, ix, cx) - })) - .when_some(item.tab_tooltip_text(cx), |tab, text| { - tab.tooltip(move |cx| Tooltip::text(text.clone(), cx)) - }) - .start_slot::(indicator) - .end_slot( - IconButton::new("close tab", Icon::Close) - .icon_color(Color::Muted) - .size(ButtonSize::None) - .icon_size(IconSize::XSmall) - .on_click(cx.listener(move |pane, _, cx| { - pane.close_item_by_id(item_id, SaveIntent::Close, cx) - .detach_and_log_err(cx); - })), - ) - .child(label); + let tab = Tab::new(ix) + .position(if is_first_item { + TabPosition::First + } else if is_last_item { + TabPosition::Last + } else { + TabPosition::Middle(position_relative_to_active_item) + }) + .close_side(match close_side { + ClosePosition::Left => ui::TabCloseSide::Start, + ClosePosition::Right => ui::TabCloseSide::End, + }) + .selected(is_active) + .on_click( + cx.listener(move |pane: &mut Self, _, cx| pane.activate_item(ix, true, true, cx)), + ) + .on_drag( + DraggedTab { + pane: cx.view().clone(), + detail, + item_id, + is_active, + ix, + }, + |tab, cx| cx.build_view(|_| tab.clone()), + ) + .drag_over::(|tab| tab.bg(cx.theme().colors().tab_active_background)) + .drag_over::(|tab| tab.bg(gpui::red())) + .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { + this.handle_tab_drop(dragged_tab, ix, cx) + })) + .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { + this.handle_project_entry_drop(entry_id, cx) + })) + .when_some(item.tab_tooltip_text(cx), |tab, text| { + tab.tooltip(move |cx| Tooltip::text(text.clone(), cx)) + }) + .start_slot::(indicator) + .end_slot( + IconButton::new("close tab", Icon::Close) + .icon_color(Color::Muted) + .size(ButtonSize::None) + .icon_size(IconSize::XSmall) + .on_click(cx.listener(move |pane, _, cx| { + pane.close_item_by_id(item_id, SaveIntent::Close, cx) + .detach_and_log_err(cx); + })), + ) + .child(label); let single_entry_to_resolve = { let item_entries = self.items[ix].project_entry_ids(cx); @@ -1618,12 +1592,12 @@ impl Pane { IconButton::new("plus", Icon::Plus) .icon_size(IconSize::Small) .on_click(cx.listener(|this, _, cx| { - let menu = ContextMenu::build(cx, |menu, cx| { + let menu = ContextMenu::build(cx, |menu, _| { menu.action("New File", NewFile.boxed_clone()) .action("New Terminal", NewCenterTerminal.boxed_clone()) .action("New Search", NewSearch.boxed_clone()) }); - cx.subscribe(&menu, |this, _, event: &DismissEvent, cx| { + cx.subscribe(&menu, |this, _, _: &DismissEvent, cx| { this.focus(cx); this.new_item_menu = None; }) @@ -1642,13 +1616,13 @@ impl Pane { IconButton::new("split", Icon::Split) .icon_size(IconSize::Small) .on_click(cx.listener(|this, _, cx| { - let menu = ContextMenu::build(cx, |menu, cx| { + let menu = ContextMenu::build(cx, |menu, _| { menu.action("Split Right", SplitRight.boxed_clone()) .action("Split Left", SplitLeft.boxed_clone()) .action("Split Up", SplitUp.boxed_clone()) .action("Split Down", SplitDown.boxed_clone()) }); - cx.subscribe(&menu, |this, _, event: &DismissEvent, cx| { + cx.subscribe(&menu, |this, _, _: &DismissEvent, cx| { this.focus(cx); this.split_item_menu = None; }) @@ -1684,7 +1658,7 @@ impl Pane { this.handle_tab_drop(dragged_tab, this.items.len(), cx) })) .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { - this.handle_project_entry_drop(entry_id, this.items.len(), cx) + this.handle_project_entry_drop(entry_id, cx) })), ) } @@ -1755,7 +1729,7 @@ impl Pane { let from_pane = dragged_tab.pane.clone(); let to_pane = cx.view().clone(); self.workspace - .update(cx, |workspace, cx| { + .update(cx, |_, cx| { cx.defer(move |workspace, cx| { workspace.move_item(from_pane, to_pane, item_id, ix, cx); }); @@ -1766,13 +1740,12 @@ impl Pane { fn handle_project_entry_drop( &mut self, project_entry_id: &ProjectEntryId, - ix: usize, cx: &mut ViewContext<'_, Pane>, ) { let to_pane = cx.view().downgrade(); let project_entry_id = *project_entry_id; self.workspace - .update(cx, |workspace, cx| { + .update(cx, |_, cx| { cx.defer(move |workspace, cx| { if let Some(path) = workspace .project() @@ -1798,19 +1771,10 @@ impl Pane { let from_pane = dragged_tab.pane.clone(); let to_pane = cx.view().clone(); self.workspace - .update(cx, |workspace, cx| { + .update(cx, |_, cx| { cx.defer(move |workspace, cx| { - let item = from_pane - .read(cx) - .items() - .find(|item| item.item_id() == item_id) - .map(|item| item.boxed_clone()); - if let Some(item) = item { - if let Some(item) = item.clone_on_split(workspace.database_id(), cx) { - let pane = workspace.split_pane(to_pane, split_direction, cx); - workspace.move_item(from_pane, pane, item_id, 0, cx); - } - } + let pane = workspace.split_pane(to_pane, split_direction, cx); + workspace.move_item(from_pane, pane, item_id, 0, cx); }); }) .log_err(); @@ -1825,7 +1789,7 @@ impl Pane { let project_entry_id = *project_entry_id; let current_pane = cx.view().clone(); self.workspace - .update(cx, |workspace, cx| { + .update(cx, |_, cx| { cx.defer(move |workspace, cx| { if let Some(path) = workspace .project() @@ -1853,8 +1817,6 @@ impl Render for Pane { type Element = Focusable
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - let this = cx.view().downgrade(); - v_stack() .key_context("Pane") .track_focus(&self.focus_handle) @@ -1953,11 +1915,7 @@ impl Render for Pane { this.handle_tab_drop(dragged_tab, this.active_item_index(), cx) })) .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { - this.handle_project_entry_drop( - entry_id, - this.active_item_index(), - cx, - ) + this.handle_project_entry_drop(entry_id, cx) })), ) .children( diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index 5f14df833d..72466d9ce4 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -16,7 +16,7 @@ const HANDLE_HITBOX_SIZE: f32 = 10.0; //todo!(change this back to 4) const HORIZONTAL_MIN_SIZE: f32 = 80.; const VERTICAL_MIN_SIZE: f32 = 100.; -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub struct PaneGroup { pub(crate) root: Member, } @@ -121,7 +121,7 @@ impl PaneGroup { } } -#[derive(Clone, PartialEq)] +#[derive(Clone)] pub(crate) enum Member { Axis(PaneAxis), Pane(View), @@ -426,12 +426,6 @@ pub(crate) struct PaneAxis { pub bounding_boxes: Arc>>>>, } -impl PartialEq for PaneAxis { - fn eq(&self, other: &Self) -> bool { - todo!() - } -} - impl PaneAxis { pub fn new(axis: Axis, members: Vec) -> Self { let flexes = Arc::new(Mutex::new(vec![1.; members.len()])); @@ -816,7 +810,7 @@ mod element { proposed_current_pixel_change -= current_pixel_change; } - // todo!(reserialize workspace) + // todo!(schedule serialize) // workspace.schedule_serialize(cx); cx.notify(); } @@ -851,7 +845,7 @@ mod element { cx.on_mouse_event({ let dragged_handle = dragged_handle.clone(); - move |e: &MouseDownEvent, phase, cx| { + move |e: &MouseDownEvent, phase, _cx| { if phase.bubble() && handle_bounds.contains(&e.position) { dragged_handle.replace(Some(ix)); } @@ -859,7 +853,7 @@ mod element { }); cx.on_mouse_event(move |e: &MouseMoveEvent, phase, cx| { let dragged_handle = dragged_handle.borrow(); - if *dragged_handle == Some(ix) { + if phase.bubble() && *dragged_handle == Some(ix) { Self::compute_resize(&flexes, e, ix, axis, axis_bounds, cx) } }); @@ -949,7 +943,7 @@ mod element { cx.with_z_index(1, |cx| { cx.on_mouse_event({ let state = state.clone(); - move |e: &MouseUpEvent, phase, cx| { + move |_: &MouseUpEvent, phase, _cx| { if phase.bubble() { state.replace(None); } @@ -968,402 +962,4 @@ mod element { fn flex_values_in_bounds(flexes: &[f32]) -> bool { (flexes.iter().copied().sum::() - flexes.len() as f32).abs() < 0.001 } - // // use std::{cell::RefCell, iter::from_fn, ops::Range, rc::Rc}; - - // // use gpui::{ - // // geometry::{ - // // rect::Bounds, - // // vector::{vec2f, Vector2F}, - // // }, - // // json::{self, ToJson}, - // // platform::{CursorStyle, MouseButton}, - // // scene::MouseDrag, - // // AnyElement, Axis, CursorRegion, Element, EventContext, MouseRegion, BoundsExt, - // // SizeConstraint, Vector2FExt, ViewContext, - // // }; - - // use crate::{ - // pane_group::{HANDLE_HITBOX_SIZE, HORIZONTAL_MIN_SIZE, VERTICAL_MIN_SIZE}, - // Workspace, WorkspaceSettings, - // }; - - // pub struct PaneAxisElement { - // axis: Axis, - // basis: usize, - // active_pane_ix: Option, - // flexes: Rc>>, - // children: Vec>, - // bounding_boxes: Rc>>>>, - // } - - // impl PaneAxisElement { - // pub fn new( - // axis: Axis, - // basis: usize, - // flexes: Rc>>, - // bounding_boxes: Rc>>>>, - // ) -> Self { - // Self { - // axis, - // basis, - // flexes, - // bounding_boxes, - // active_pane_ix: None, - // children: Default::default(), - // } - // } - - // pub fn set_active_pane(&mut self, active_pane_ix: Option) { - // self.active_pane_ix = active_pane_ix; - // } - - // fn layout_children( - // &mut self, - // active_pane_magnification: f32, - // constraint: SizeConstraint, - // remaining_space: &mut f32, - // remaining_flex: &mut f32, - // cross_axis_max: &mut f32, - // view: &mut Workspace, - // cx: &mut ViewContext, - // ) { - // let flexes = self.flexes.borrow(); - // let cross_axis = self.axis.invert(); - // for (ix, child) in self.children.iter_mut().enumerate() { - // let flex = if active_pane_magnification != 1. { - // if let Some(active_pane_ix) = self.active_pane_ix { - // if ix == active_pane_ix { - // active_pane_magnification - // } else { - // 1. - // } - // } else { - // 1. - // } - // } else { - // flexes[ix] - // }; - - // let child_size = if *remaining_flex == 0.0 { - // *remaining_space - // } else { - // let space_per_flex = *remaining_space / *remaining_flex; - // space_per_flex * flex - // }; - - // let child_constraint = match self.axis { - // Axis::Horizontal => SizeConstraint::new( - // vec2f(child_size, constraint.min.y()), - // vec2f(child_size, constraint.max.y()), - // ), - // Axis::Vertical => SizeConstraint::new( - // vec2f(constraint.min.x(), child_size), - // vec2f(constraint.max.x(), child_size), - // ), - // }; - // let child_size = child.layout(child_constraint, view, cx); - // *remaining_space -= child_size.along(self.axis); - // *remaining_flex -= flex; - // *cross_axis_max = cross_axis_max.max(child_size.along(cross_axis)); - // } - // } - - // fn handle_resize( - // flexes: Rc>>, - // axis: Axis, - // preceding_ix: usize, - // child_start: Vector2F, - // drag_bounds: Bounds, - // ) -> impl Fn(MouseDrag, &mut Workspace, &mut EventContext) { - // let size = move |ix, flexes: &[f32]| { - // drag_bounds.length_along(axis) * (flexes[ix] / flexes.len() as f32) - // }; - - // move |drag, workspace: &mut Workspace, cx| { - // if drag.end { - // // TODO: Clear cascading resize state - // return; - // } - // let min_size = match axis { - // Axis::Horizontal => HORIZONTAL_MIN_SIZE, - // Axis::Vertical => VERTICAL_MIN_SIZE, - // }; - // let mut flexes = flexes.borrow_mut(); - - // // Don't allow resizing to less than the minimum size, if elements are already too small - // if min_size - 1. > size(preceding_ix, flexes.as_slice()) { - // return; - // } - - // let mut proposed_current_pixel_change = (drag.position - child_start).along(axis) - // - size(preceding_ix, flexes.as_slice()); - - // let flex_changes = |pixel_dx, target_ix, next: isize, flexes: &[f32]| { - // let flex_change = pixel_dx / drag_bounds.length_along(axis); - // let current_target_flex = flexes[target_ix] + flex_change; - // let next_target_flex = - // flexes[(target_ix as isize + next) as usize] - flex_change; - // (current_target_flex, next_target_flex) - // }; - - // let mut successors = from_fn({ - // let forward = proposed_current_pixel_change > 0.; - // let mut ix_offset = 0; - // let len = flexes.len(); - // move || { - // let result = if forward { - // (preceding_ix + 1 + ix_offset < len).then(|| preceding_ix + ix_offset) - // } else { - // (preceding_ix as isize - ix_offset as isize >= 0) - // .then(|| preceding_ix - ix_offset) - // }; - - // ix_offset += 1; - - // result - // } - // }); - - // while proposed_current_pixel_change.abs() > 0. { - // let Some(current_ix) = successors.next() else { - // break; - // }; - - // let next_target_size = f32::max( - // size(current_ix + 1, flexes.as_slice()) - proposed_current_pixel_change, - // min_size, - // ); - - // let current_target_size = f32::max( - // size(current_ix, flexes.as_slice()) - // + size(current_ix + 1, flexes.as_slice()) - // - next_target_size, - // min_size, - // ); - - // let current_pixel_change = - // current_target_size - size(current_ix, flexes.as_slice()); - - // let (current_target_flex, next_target_flex) = - // flex_changes(current_pixel_change, current_ix, 1, flexes.as_slice()); - - // flexes[current_ix] = current_target_flex; - // flexes[current_ix + 1] = next_target_flex; - - // proposed_current_pixel_change -= current_pixel_change; - // } - - // workspace.schedule_serialize(cx); - // cx.notify(); - // } - // } - // } - - // impl Extend> for PaneAxisElement { - // fn extend>>(&mut self, children: T) { - // self.children.extend(children); - // } - // } - - // impl Element for PaneAxisElement { - // type LayoutState = f32; - // type PaintState = (); - - // fn layout( - // &mut self, - // constraint: SizeConstraint, - // view: &mut Workspace, - // cx: &mut ViewContext, - // ) -> (Vector2F, Self::LayoutState) { - // debug_assert!(self.children.len() == self.flexes.borrow().len()); - - // let active_pane_magnification = - // settings::get::(cx).active_pane_magnification; - - // let mut remaining_flex = 0.; - - // if active_pane_magnification != 1. { - // let active_pane_flex = self - // .active_pane_ix - // .map(|_| active_pane_magnification) - // .unwrap_or(1.); - // remaining_flex += self.children.len() as f32 - 1. + active_pane_flex; - // } else { - // for flex in self.flexes.borrow().iter() { - // remaining_flex += flex; - // } - // } - - // let mut cross_axis_max: f32 = 0.0; - // let mut remaining_space = constraint.max_along(self.axis); - - // if remaining_space.is_infinite() { - // panic!("flex contains flexible children but has an infinite constraint along the flex axis"); - // } - - // self.layout_children( - // active_pane_magnification, - // constraint, - // &mut remaining_space, - // &mut remaining_flex, - // &mut cross_axis_max, - // view, - // cx, - // ); - - // let mut size = match self.axis { - // Axis::Horizontal => vec2f(constraint.max.x() - remaining_space, cross_axis_max), - // Axis::Vertical => vec2f(cross_axis_max, constraint.max.y() - remaining_space), - // }; - - // if constraint.min.x().is_finite() { - // size.set_x(size.x().max(constraint.min.x())); - // } - // if constraint.min.y().is_finite() { - // size.set_y(size.y().max(constraint.min.y())); - // } - - // if size.x() > constraint.max.x() { - // size.set_x(constraint.max.x()); - // } - // if size.y() > constraint.max.y() { - // size.set_y(constraint.max.y()); - // } - - // (size, remaining_space) - // } - - // fn paint( - // &mut self, - // bounds: Bounds, - // visible_bounds: Bounds, - // remaining_space: &mut Self::LayoutState, - // view: &mut Workspace, - // cx: &mut ViewContext, - // ) -> Self::PaintState { - // let can_resize = settings::get::(cx).active_pane_magnification == 1.; - // let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); - - // let overflowing = *remaining_space < 0.; - // if overflowing { - // cx.scene().push_layer(Some(visible_bounds)); - // } - - // let mut child_origin = bounds.origin(); - - // let mut bounding_boxes = self.bounding_boxes.borrow_mut(); - // bounding_boxes.clear(); - - // let mut children_iter = self.children.iter_mut().enumerate().peekable(); - // while let Some((ix, child)) = children_iter.next() { - // let child_start = child_origin.clone(); - // child.paint(child_origin, visible_bounds, view, cx); - - // bounding_boxes.push(Some(Bounds::new(child_origin, child.size()))); - - // match self.axis { - // Axis::Horizontal => child_origin += vec2f(child.size().x(), 0.0), - // Axis::Vertical => child_origin += vec2f(0.0, child.size().y()), - // } - - // if can_resize && children_iter.peek().is_some() { - // cx.scene().push_stacking_context(None, None); - - // let handle_origin = match self.axis { - // Axis::Horizontal => child_origin - vec2f(HANDLE_HITBOX_SIZE / 2., 0.0), - // Axis::Vertical => child_origin - vec2f(0.0, HANDLE_HITBOX_SIZE / 2.), - // }; - - // let handle_bounds = match self.axis { - // Axis::Horizontal => Bounds::new( - // handle_origin, - // vec2f(HANDLE_HITBOX_SIZE, visible_bounds.height()), - // ), - // Axis::Vertical => Bounds::new( - // handle_origin, - // vec2f(visible_bounds.width(), HANDLE_HITBOX_SIZE), - // ), - // }; - - // let style = match self.axis { - // Axis::Horizontal => CursorStyle::ResizeLeftRight, - // Axis::Vertical => CursorStyle::ResizeUpDown, - // }; - - // cx.scene().push_cursor_region(CursorRegion { - // bounds: handle_bounds, - // style, - // }); - - // enum ResizeHandle {} - // let mut mouse_region = MouseRegion::new::( - // cx.view_id(), - // self.basis + ix, - // handle_bounds, - // ); - // mouse_region = mouse_region - // .on_drag( - // MouseButton::Left, - // Self::handle_resize( - // self.flexes.clone(), - // self.axis, - // ix, - // child_start, - // visible_bounds.clone(), - // ), - // ) - // .on_click(MouseButton::Left, { - // let flexes = self.flexes.clone(); - // move |e, v: &mut Workspace, cx| { - // if e.click_count >= 2 { - // let mut borrow = flexes.borrow_mut(); - // *borrow = vec![1.; borrow.len()]; - // v.schedule_serialize(cx); - // cx.notify(); - // } - // } - // }); - // cx.scene().push_mouse_region(mouse_region); - - // cx.scene().pop_stacking_context(); - // } - // } - - // if overflowing { - // cx.scene().pop_layer(); - // } - // } - - // fn rect_for_text_range( - // &self, - // range_utf16: Range, - // _: Bounds, - // _: Bounds, - // _: &Self::LayoutState, - // _: &Self::PaintState, - // view: &Workspace, - // cx: &ViewContext, - // ) -> Option> { - // self.children - // .iter() - // .find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx)) - // } - - // fn debug( - // &self, - // bounds: Bounds, - // _: &Self::LayoutState, - // _: &Self::PaintState, - // view: &Workspace, - // cx: &ViewContext, - // ) -> json::Value { - // serde_json::json!({ - // "type": "PaneAxis", - // "bounds": bounds.to_json(), - // "axis": self.axis.to_json(), - // "flexes": *self.flexes.borrow(), - // "children": self.children.iter().map(|child| child.debug(view, cx)).collect::>() - // }) - // } - // } } diff --git a/crates/workspace2/src/searchable.rs b/crates/workspace2/src/searchable.rs index eadd602c84..59202cbbaf 100644 --- a/crates/workspace2/src/searchable.rs +++ b/crates/workspace2/src/searchable.rs @@ -193,7 +193,7 @@ impl SearchableItemHandle for View { cx: &mut WindowContext, ) -> Task>> { let matches = self.update(cx, |this, cx| this.find_matches(query, cx)); - cx.spawn(|cx| async { + cx.spawn(|_| async { let matches = matches.await; matches .into_iter() @@ -253,7 +253,7 @@ pub trait WeakSearchableItemHandle: WeakItemHandle { } impl WeakSearchableItemHandle for WeakView { - fn upgrade(&self, cx: &AppContext) -> Option> { + fn upgrade(&self, _cx: &AppContext) -> Option> { Some(Box::new(self.upgrade()?)) } diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index c0cbd127ac..ba571d6e0a 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -51,14 +51,14 @@ impl Render for StatusBar { } impl StatusBar { - fn render_left_tools(&self, cx: &mut ViewContext) -> impl IntoElement { + fn render_left_tools(&self, _: &mut ViewContext) -> impl IntoElement { h_stack() .items_center() .gap_2() .children(self.left_items.iter().map(|item| item.to_any())) } - fn render_right_tools(&self, cx: &mut ViewContext) -> impl IntoElement { + fn render_right_tools(&self, _: &mut ViewContext) -> impl IntoElement { h_stack() .items_center() .gap_2() diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 87083b0929..8318ba3f0f 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -1,15 +1,11 @@ -#![allow(unused_variables, dead_code, unused_mut)] -// todo!() this is to make transition easier. - pub mod dock; pub mod item; +mod modal_layer; pub mod notifications; pub mod pane; pub mod pane_group; mod persistence; pub mod searchable; -// todo!() -mod modal_layer; pub mod shared_screen; mod status_bar; mod toolbar; @@ -236,14 +232,14 @@ pub fn init(app_state: Arc, cx: &mut AppContext) { cx.on_action({ let app_state = Arc::downgrade(&app_state); move |_: &Open, cx: &mut AppContext| { - let mut paths = cx.prompt_for_paths(PathPromptOptions { + let paths = cx.prompt_for_paths(PathPromptOptions { files: true, directories: true, multiple: true, }); if let Some(app_state) = app_state.upgrade() { - cx.spawn(move |mut cx| async move { + cx.spawn(move |cx| async move { if let Some(paths) = paths.await.log_err().flatten() { cx.update(|cx| { open_paths(&paths, &app_state, None, cx).detach_and_log_err(cx) @@ -458,7 +454,7 @@ pub struct Workspace { leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>, database_id: WorkspaceId, app_state: Arc, - subscriptions: Vec, + _subscriptions: Vec, _apply_leader_updates: Task>, _observe_current_user: Task>, _schedule_serialize: Option>, @@ -590,12 +586,9 @@ impl Workspace { let left_dock = cx.build_view(|cx| Dock::new(DockPosition::Left, cx)); let bottom_dock = cx.build_view(|cx| Dock::new(DockPosition::Bottom, cx)); let right_dock = cx.build_view(|cx| Dock::new(DockPosition::Right, cx)); - let left_dock_buttons = - cx.build_view(|cx| PanelButtons::new(left_dock.clone(), weak_handle.clone(), cx)); - let bottom_dock_buttons = - cx.build_view(|cx| PanelButtons::new(bottom_dock.clone(), weak_handle.clone(), cx)); - let right_dock_buttons = - cx.build_view(|cx| PanelButtons::new(right_dock.clone(), weak_handle.clone(), cx)); + let left_dock_buttons = cx.build_view(|cx| PanelButtons::new(left_dock.clone(), cx)); + let bottom_dock_buttons = cx.build_view(|cx| PanelButtons::new(bottom_dock.clone(), cx)); + let right_dock_buttons = cx.build_view(|cx| PanelButtons::new(right_dock.clone(), cx)); let status_bar = cx.build_view(|cx| { let mut status_bar = StatusBar::new(¢er_pane.clone(), cx); status_bar.add_left_item(left_dock_buttons, cx); @@ -604,8 +597,7 @@ impl Workspace { status_bar }); - let workspace_handle = cx.view().downgrade(); - let modal_layer = cx.build_view(|cx| ModalLayer::new()); + let modal_layer = cx.build_view(|_| ModalLayer::new()); // todo!() // cx.update_default_global::, _, _>(|drag_and_drop, _| { @@ -703,7 +695,7 @@ impl Workspace { _apply_leader_updates, _schedule_serialize: None, leader_updates_tx, - subscriptions, + _subscriptions: subscriptions, pane_history_timestamp, workspace_actions: Default::default(), // This data will be incorrect, but it will be overwritten by the time it needs to be used. @@ -763,7 +755,7 @@ impl Workspace { }; let window = if let Some(window) = requesting_window { - cx.update_window(window.into(), |old_workspace, cx| { + cx.update_window(window.into(), |_, cx| { cx.replace_root_view(|cx| { Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx) }); @@ -1185,8 +1177,7 @@ impl Workspace { } fn save_all(&mut self, action: &SaveAll, cx: &mut ViewContext) { - let save_all = self - .save_all_internal(action.save_intent.unwrap_or(SaveIntent::SaveAll), cx) + self.save_all_internal(action.save_intent.unwrap_or(SaveIntent::SaveAll), cx) .detach_and_log_err(cx); } @@ -1216,7 +1207,7 @@ impl Workspace { cx.spawn(|workspace, mut cx| async move { // Override save mode and display "Save all files" prompt if save_intent == SaveIntent::Close && dirty_items.len() > 1 { - let mut answer = workspace.update(&mut cx, |_, cx| { + let answer = workspace.update(&mut cx, |_, cx| { let prompt = Pane::file_names_for_prompt( &mut dirty_items.iter().map(|(_, handle)| handle), dirty_items.len(), @@ -1261,7 +1252,7 @@ impl Workspace { } pub fn open(&mut self, _: &Open, cx: &mut ViewContext) { - let mut paths = cx.prompt_for_paths(PathPromptOptions { + let paths = cx.prompt_for_paths(PathPromptOptions { files: true, directories: true, multiple: true, @@ -1390,7 +1381,7 @@ impl Workspace { } fn add_folder_to_project(&mut self, _: &AddFolderToProject, cx: &mut ViewContext) { - let mut paths = cx.prompt_for_paths(PathPromptOptions { + let paths = cx.prompt_for_paths(PathPromptOptions { files: false, directories: true, multiple: true, @@ -1670,6 +1661,8 @@ impl Workspace { None } + // todo!("implement zoom") + #[allow(unused)] fn zoom_out(&mut self, cx: &mut ViewContext) { for pane in &self.panes { pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); @@ -2574,7 +2567,7 @@ impl Workspace { // } // } - fn render_notifications(&self, cx: &ViewContext) -> Option
{ + fn render_notifications(&self, _cx: &ViewContext) -> Option
{ if self.notifications.is_empty() { None } else { @@ -3005,6 +2998,7 @@ impl Workspace { cx.notify(); } + #[allow(unused)] fn schedule_serialize(&mut self, cx: &mut ViewContext) { self._schedule_serialize = Some(cx.spawn(|this, mut cx| async move { cx.background_executor() @@ -3143,12 +3137,7 @@ impl Workspace { cx: &mut ViewContext, ) -> Task>>>> { cx.spawn(|workspace, mut cx| async move { - let (project, old_center_pane) = workspace.update(&mut cx, |workspace, _| { - ( - workspace.project().clone(), - workspace.last_active_center_pane.clone(), - ) - })?; + let project = workspace.update(&mut cx, |workspace, _| workspace.project().clone())?; let mut center_group = None; let mut center_items = None; @@ -3293,7 +3282,7 @@ impl Workspace { .on_action(cx.listener(|workspace, action: &SwapPaneInDirection, cx| { workspace.swap_pane_in_direction(action.0, cx) })) - .on_action(cx.listener(|this, e: &ToggleLeftDock, cx| { + .on_action(cx.listener(|this, _: &ToggleLeftDock, cx| { this.toggle_dock(DockPosition::Left, cx); })) .on_action( @@ -3418,7 +3407,7 @@ impl Workspace { self } - fn add_workspace_actions_listeners(&self, mut div: Div, cx: &mut ViewContext) -> Div { + fn add_workspace_actions_listeners(&self, div: Div, cx: &mut ViewContext) -> Div { let mut div = div .on_action(cx.listener(Self::close_inactive_items_and_panes)) .on_action(cx.listener(Self::close_all_items_and_panes)) @@ -3578,8 +3567,6 @@ impl FocusableView for Workspace { } } -struct WorkspaceBounds(Bounds); - #[derive(Clone, Render)] struct DraggedDock(DockPosition); @@ -3628,7 +3615,7 @@ impl Render for Workspace { .border_b() .border_color(cx.theme().colors().border) .child( - canvas(cx.listener(|workspace, bounds, cx| { + canvas(cx.listener(|workspace, bounds, _| { workspace.bounds = *bounds; })) .absolute() @@ -4056,7 +4043,7 @@ async fn join_channel_internal( active_call: &Model, cx: &mut AsyncAppContext, ) -> Result { - let (should_prompt, open_room) = active_call.read_with(cx, |active_call, cx| { + let (should_prompt, open_room) = active_call.update(cx, |active_call, cx| { let Some(room) = active_call.room().map(|room| room.read(cx)) else { return (false, None); }; @@ -4421,7 +4408,7 @@ pub fn restart(_: &Restart, cx: &mut AppContext) { } cx.spawn(|mut cx| async move { - if let Some(mut prompt) = prompt { + if let Some(prompt) = prompt { let answer = prompt.await?; if answer != 0 { return Ok(()); @@ -4460,6 +4447,8 @@ fn parse_pixel_size_env_var(value: &str) -> Option> { #[cfg(test)] mod tests { + use std::{cell::RefCell, rc::Rc}; + use super::*; use crate::item::{ test::{TestItem, TestProjectItem}, @@ -4470,7 +4459,6 @@ mod tests { use project::{Project, ProjectEntryId}; use serde_json::json; use settings::SettingsStore; - use std::{cell::RefCell, rc::Rc}; #[gpui::test] async fn test_tab_disambiguation(cx: &mut TestAppContext) { @@ -4544,7 +4532,7 @@ mod tests { let project = Project::test(fs, ["root1".as_ref()], cx).await; let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); - let worktree_id = project.read_with(cx, |project, cx| { + let worktree_id = project.update(cx, |project, cx| { project.worktrees().next().unwrap().read(cx).id() }); @@ -4557,7 +4545,7 @@ mod tests { // Add an item to an empty pane workspace.update(cx, |workspace, cx| workspace.add_item(Box::new(item1), cx)); - project.read_with(cx, |project, cx| { + project.update(cx, |project, cx| { assert_eq!( project.active_entry(), project @@ -4570,7 +4558,7 @@ mod tests { // Add a second item to a non-empty pane workspace.update(cx, |workspace, cx| workspace.add_item(Box::new(item2), cx)); assert_eq!(cx.window_title().as_deref(), Some("two.txt — root1")); - project.read_with(cx, |project, cx| { + project.update(cx, |project, cx| { assert_eq!( project.active_entry(), project @@ -4586,7 +4574,7 @@ mod tests { .await .unwrap(); assert_eq!(cx.window_title().as_deref(), Some("one.txt — root1")); - project.read_with(cx, |project, cx| { + project.update(cx, |project, cx| { assert_eq!( project.active_entry(), project @@ -4970,14 +4958,14 @@ mod tests { item.is_dirty = true; cx.blur(); }); - cx.executor().run_until_parked(); + cx.run_until_parked(); item.update(cx, |item, _| assert_eq!(item.save_count, 5)); // Ensure autosave is prevented for deleted files also when closing the buffer. let _close_items = pane.update(cx, |pane, cx| { pane.close_items(cx, SaveIntent::Close, move |id| id == item_id) }); - cx.executor().run_until_parked(); + cx.run_until_parked(); assert!(cx.has_pending_prompt()); item.update(cx, |item, _| assert_eq!(item.save_count, 5)); } @@ -5036,363 +5024,362 @@ mod tests { }); } - // #[gpui::test] - // async fn test_toggle_docks_and_panels(cx: &mut gpui::TestAppContext) { - // init_test(cx); - // let fs = FakeFs::new(cx.executor()); + // #[gpui::test] + // async fn test_toggle_docks_and_panels(cx: &mut gpui::TestAppContext) { + // init_test(cx); + // let fs = FakeFs::new(cx.executor()); - // let project = Project::test(fs, [], cx).await; - // let window = cx.add_window(|cx| Workspace::test_new(project, cx)); - // let workspace = window.root(cx); + // let project = Project::test(fs, [], cx).await; + // let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx)); - // let panel = workspace.update(cx, |workspace, cx| { - // let panel = cx.build_view(|_| TestPanel::new(DockPosition::Right)); - // workspace.add_panel(panel.clone(), cx); + // let panel = workspace.update(cx, |workspace, cx| { + // let panel = cx.build_view(|cx| TestPanel::new(DockPosition::Right, cx)); + // workspace.add_panel(panel.clone(), cx); + // workspace + // .right_dock() + // .update(cx, |right_dock, cx| right_dock.set_open(true, cx)); + + // panel + // }); + + // let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + // pane.update(cx, |pane, cx| { + // let item = cx.build_view(|cx| TestItem::new(cx)); + // pane.add_item(Box::new(item), true, true, None, cx); + // }); + + // // Transfer focus from center to panel + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_panel_focus::(cx); + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(workspace.right_dock().read(cx).is_open()); + // assert!(!panel.is_zoomed(cx)); + // assert!(panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Transfer focus from panel to center + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_panel_focus::(cx); + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(workspace.right_dock().read(cx).is_open()); + // assert!(!panel.is_zoomed(cx)); + // assert!(!panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Close the dock + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_dock(DockPosition::Right, cx); + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(!workspace.right_dock().read(cx).is_open()); + // assert!(!panel.is_zoomed(cx)); + // assert!(!panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Open the dock + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_dock(DockPosition::Right, cx); + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(workspace.right_dock().read(cx).is_open()); + // assert!(!panel.is_zoomed(cx)); + // assert!(panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Focus and zoom panel + // panel.update(cx, |panel, cx| { + // cx.focus_self(); + // panel.set_zoomed(true, cx) + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(workspace.right_dock().read(cx).is_open()); + // assert!(panel.is_zoomed(cx)); + // assert!(panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Transfer focus to the center closes the dock + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_panel_focus::(cx); + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(!workspace.right_dock().read(cx).is_open()); + // assert!(panel.is_zoomed(cx)); + // assert!(!panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Transferring focus back to the panel keeps it zoomed + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_panel_focus::(cx); + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(workspace.right_dock().read(cx).is_open()); + // assert!(panel.is_zoomed(cx)); + // assert!(panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Close the dock while it is zoomed + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_dock(DockPosition::Right, cx) + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(!workspace.right_dock().read(cx).is_open()); + // assert!(panel.is_zoomed(cx)); + // assert!(workspace.zoomed.is_none()); + // assert!(!panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Opening the dock, when it's zoomed, retains focus + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_dock(DockPosition::Right, cx) + // }); + + // workspace.update(cx, |workspace, cx| { + // assert!(workspace.right_dock().read(cx).is_open()); + // assert!(panel.is_zoomed(cx)); + // assert!(workspace.zoomed.is_some()); + // assert!(panel.read(cx).focus_handle(cx).contains_focused(cx)); + // }); + + // // Unzoom and close the panel, zoom the active pane. + // panel.update(cx, |panel, cx| panel.set_zoomed(false, cx)); + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_dock(DockPosition::Right, cx) + // }); + // pane.update(cx, |pane, cx| pane.toggle_zoom(&Default::default(), cx)); + + // // Opening a dock unzooms the pane. + // workspace.update(cx, |workspace, cx| { + // workspace.toggle_dock(DockPosition::Right, cx) + // }); + // workspace.update(cx, |workspace, cx| { + // let pane = pane.read(cx); + // assert!(!pane.is_zoomed()); + // assert!(!pane.focus_handle(cx).is_focused(cx)); + // assert!(workspace.right_dock().read(cx).is_open()); + // assert!(workspace.zoomed.is_none()); + // }); + // } + + // #[gpui::test] + // async fn test_panels(cx: &mut gpui::TestAppContext) { + // init_test(cx); + // let fs = FakeFs::new(cx.executor()); + + // let project = Project::test(fs, [], cx).await; + // let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project, cx)); + + // let (panel_1, panel_2) = workspace.update(cx, |workspace, cx| { + // // Add panel_1 on the left, panel_2 on the right. + // let panel_1 = cx.build_view(|cx| TestPanel::new(DockPosition::Left, cx)); + // workspace.add_panel(panel_1.clone(), cx); + // workspace + // .left_dock() + // .update(cx, |left_dock, cx| left_dock.set_open(true, cx)); + // let panel_2 = cx.build_view(|cx| TestPanel::new(DockPosition::Right, cx)); + // workspace.add_panel(panel_2.clone(), cx); + // workspace + // .right_dock() + // .update(cx, |right_dock, cx| right_dock.set_open(true, cx)); + + // let left_dock = workspace.left_dock(); + // assert_eq!( + // left_dock.read(cx).visible_panel().unwrap().panel_id(), + // panel_1.panel_id() + // ); + // assert_eq!( + // left_dock.read(cx).active_panel_size(cx).unwrap(), + // panel_1.size(cx) + // ); + + // left_dock.update(cx, |left_dock, cx| { + // left_dock.resize_active_panel(Some(1337.), cx) + // }); + // assert_eq!( // workspace // .right_dock() - // .update(cx, |right_dock, cx| right_dock.set_open(true, cx)); + // .read(cx) + // .visible_panel() + // .unwrap() + // .panel_id(), + // panel_2.panel_id(), + // ); - // panel - // }); + // (panel_1, panel_2) + // }); - // let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); - // pane.update(cx, |pane, cx| { - // let item = cx.build_view(|_| TestItem::new(cx)); - // pane.add_item(Box::new(item), true, true, None, cx); - // }); + // // Move panel_1 to the right + // panel_1.update(cx, |panel_1, cx| { + // panel_1.set_position(DockPosition::Right, cx) + // }); - // // Transfer focus from center to panel - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_panel_focus::(cx); - // }); + // workspace.update(cx, |workspace, cx| { + // // Since panel_1 was visible on the left, it should now be visible now that it's been moved to the right. + // // Since it was the only panel on the left, the left dock should now be closed. + // assert!(!workspace.left_dock().read(cx).is_open()); + // assert!(workspace.left_dock().read(cx).visible_panel().is_none()); + // let right_dock = workspace.right_dock(); + // assert_eq!( + // right_dock.read(cx).visible_panel().unwrap().panel_id(), + // panel_1.panel_id() + // ); + // assert_eq!(right_dock.read(cx).active_panel_size(cx).unwrap(), 1337.); - // workspace.update(cx, |workspace, cx| { - // assert!(workspace.right_dock().read(cx).is_open()); - // assert!(!panel.is_zoomed(cx)); - // assert!(panel.has_focus(cx)); - // }); + // // Now we move panel_2 to the left + // panel_2.set_position(DockPosition::Left, cx); + // }); - // // Transfer focus from panel to center - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_panel_focus::(cx); - // }); - - // workspace.update(cx, |workspace, cx| { - // assert!(workspace.right_dock().read(cx).is_open()); - // assert!(!panel.is_zoomed(cx)); - // assert!(!panel.has_focus(cx)); - // }); - - // // Close the dock - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_dock(DockPosition::Right, cx); - // }); - - // workspace.update(cx, |workspace, cx| { - // assert!(!workspace.right_dock().read(cx).is_open()); - // assert!(!panel.is_zoomed(cx)); - // assert!(!panel.has_focus(cx)); - // }); - - // // Open the dock - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_dock(DockPosition::Right, cx); - // }); - - // workspace.update(cx, |workspace, cx| { - // assert!(workspace.right_dock().read(cx).is_open()); - // assert!(!panel.is_zoomed(cx)); - // assert!(panel.has_focus(cx)); - // }); - - // // Focus and zoom panel - // panel.update(cx, |panel, cx| { - // cx.focus_self(); - // panel.set_zoomed(true, cx) - // }); - - // workspace.update(cx, |workspace, cx| { - // assert!(workspace.right_dock().read(cx).is_open()); - // assert!(panel.is_zoomed(cx)); - // assert!(panel.has_focus(cx)); - // }); - - // // Transfer focus to the center closes the dock - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_panel_focus::(cx); - // }); - - // workspace.update(cx, |workspace, cx| { - // assert!(!workspace.right_dock().read(cx).is_open()); - // assert!(panel.is_zoomed(cx)); - // assert!(!panel.has_focus(cx)); - // }); - - // // Transferring focus back to the panel keeps it zoomed - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_panel_focus::(cx); - // }); - - // workspace.update(cx, |workspace, cx| { - // assert!(workspace.right_dock().read(cx).is_open()); - // assert!(panel.is_zoomed(cx)); - // assert!(panel.has_focus(cx)); - // }); - - // // Close the dock while it is zoomed - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_dock(DockPosition::Right, cx) - // }); - - // workspace.update(cx, |workspace, cx| { - // assert!(!workspace.right_dock().read(cx).is_open()); - // assert!(panel.is_zoomed(cx)); - // assert!(workspace.zoomed.is_none()); - // assert!(!panel.has_focus(cx)); - // }); - - // // Opening the dock, when it's zoomed, retains focus - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_dock(DockPosition::Right, cx) - // }); - - // workspace.update(cx, |workspace, cx| { - // assert!(workspace.right_dock().read(cx).is_open()); - // assert!(panel.is_zoomed(cx)); - // assert!(workspace.zoomed.is_some()); - // assert!(panel.has_focus(cx)); - // }); - - // // Unzoom and close the panel, zoom the active pane. - // panel.update(cx, |panel, cx| panel.set_zoomed(false, cx)); - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_dock(DockPosition::Right, cx) - // }); - // pane.update(cx, |pane, cx| pane.toggle_zoom(&Default::default(), cx)); - - // // Opening a dock unzooms the pane. - // workspace.update(cx, |workspace, cx| { - // workspace.toggle_dock(DockPosition::Right, cx) - // }); - // workspace.update(cx, |workspace, cx| { - // let pane = pane.read(cx); - // assert!(!pane.is_zoomed()); - // assert!(!pane.has_focus()); - // assert!(workspace.right_dock().read(cx).is_open()); - // assert!(workspace.zoomed.is_none()); - // }); - // } - - // #[gpui::test] - // async fn test_panels(cx: &mut gpui::TestAppContext) { - // init_test(cx); - // let fs = FakeFs::new(cx.executor()); - - // let project = Project::test(fs, [], cx).await; - // let window = cx.add_window(|cx| Workspace::test_new(project, cx)); - // let workspace = window.root(cx); - - // let (panel_1, panel_2) = workspace.update(cx, |workspace, cx| { - // // Add panel_1 on the left, panel_2 on the right. - // let panel_1 = cx.build_view(|_| TestPanel::new(DockPosition::Left)); - // workspace.add_panel(panel_1.clone(), cx); - // workspace - // .left_dock() - // .update(cx, |left_dock, cx| left_dock.set_open(true, cx)); - // let panel_2 = cx.build_view(|_| TestPanel::new(DockPosition::Right)); - // workspace.add_panel(panel_2.clone(), cx); + // workspace.update(cx, |workspace, cx| { + // // Since panel_2 was not visible on the right, we don't open the left dock. + // assert!(!workspace.left_dock().read(cx).is_open()); + // // And the right dock is unaffected in it's displaying of panel_1 + // assert!(workspace.right_dock().read(cx).is_open()); + // assert_eq!( // workspace // .right_dock() - // .update(cx, |right_dock, cx| right_dock.set_open(true, cx)); + // .read(cx) + // .visible_panel() + // .unwrap() + // .panel_id(), + // panel_1.panel_id(), + // ); + // }); - // let left_dock = workspace.left_dock(); - // assert_eq!( - // left_dock.read(cx).visible_panel().unwrap().id(), - // panel_1.id() - // ); - // assert_eq!( - // left_dock.read(cx).active_panel_size(cx).unwrap(), - // panel_1.size(cx) - // ); + // // Move panel_1 back to the left + // panel_1.update(cx, |panel_1, cx| { + // panel_1.set_position(DockPosition::Left, cx) + // }); - // left_dock.update(cx, |left_dock, cx| { - // left_dock.resize_active_panel(Some(1337.), cx) - // }); - // assert_eq!( - // workspace - // .right_dock() - // .read(cx) - // .visible_panel() - // .unwrap() - // .id(), - // panel_2.id() - // ); + // workspace.update(cx, |workspace, cx| { + // // Since panel_1 was visible on the right, we open the left dock and make panel_1 active. + // let left_dock = workspace.left_dock(); + // assert!(left_dock.read(cx).is_open()); + // assert_eq!( + // left_dock.read(cx).visible_panel().unwrap().panel_id(), + // panel_1.panel_id() + // ); + // assert_eq!(left_dock.read(cx).active_panel_size(cx).unwrap(), 1337.); + // // And right the dock should be closed as it no longer has any panels. + // assert!(!workspace.right_dock().read(cx).is_open()); - // (panel_1, panel_2) - // }); + // // Now we move panel_1 to the bottom + // panel_1.set_position(DockPosition::Bottom, cx); + // }); - // // Move panel_1 to the right - // panel_1.update(cx, |panel_1, cx| { - // panel_1.set_position(DockPosition::Right, cx) - // }); + // workspace.update(cx, |workspace, cx| { + // // Since panel_1 was visible on the left, we close the left dock. + // assert!(!workspace.left_dock().read(cx).is_open()); + // // The bottom dock is sized based on the panel's default size, + // // since the panel orientation changed from vertical to horizontal. + // let bottom_dock = workspace.bottom_dock(); + // assert_eq!( + // bottom_dock.read(cx).active_panel_size(cx).unwrap(), + // panel_1.size(cx), + // ); + // // Close bottom dock and move panel_1 back to the left. + // bottom_dock.update(cx, |bottom_dock, cx| bottom_dock.set_open(false, cx)); + // panel_1.set_position(DockPosition::Left, cx); + // }); - // workspace.update(cx, |workspace, cx| { - // // Since panel_1 was visible on the left, it should now be visible now that it's been moved to the right. - // // Since it was the only panel on the left, the left dock should now be closed. - // assert!(!workspace.left_dock().read(cx).is_open()); - // assert!(workspace.left_dock().read(cx).visible_panel().is_none()); - // let right_dock = workspace.right_dock(); - // assert_eq!( - // right_dock.read(cx).visible_panel().unwrap().id(), - // panel_1.id() - // ); - // assert_eq!(right_dock.read(cx).active_panel_size(cx).unwrap(), 1337.); + // // Emit activated event on panel 1 + // panel_1.update(cx, |_, cx| cx.emit(PanelEvent::Activate)); - // // Now we move panel_2 to the left - // panel_2.set_position(DockPosition::Left, cx); - // }); + // // Now the left dock is open and panel_1 is active and focused. + // workspace.update(cx, |workspace, cx| { + // let left_dock = workspace.left_dock(); + // assert!(left_dock.read(cx).is_open()); + // assert_eq!( + // left_dock.read(cx).visible_panel().unwrap().panel_id(), + // panel_1.panel_id(), + // ); + // assert!(panel_1.focus_handle(cx).is_focused(cx)); + // }); - // workspace.update(cx, |workspace, cx| { - // // Since panel_2 was not visible on the right, we don't open the left dock. - // assert!(!workspace.left_dock().read(cx).is_open()); - // // And the right dock is unaffected in it's displaying of panel_1 - // assert!(workspace.right_dock().read(cx).is_open()); - // assert_eq!( - // workspace - // .right_dock() - // .read(cx) - // .visible_panel() - // .unwrap() - // .id(), - // panel_1.id() - // ); - // }); + // // Emit closed event on panel 2, which is not active + // panel_2.update(cx, |_, cx| cx.emit(PanelEvent::Close)); - // // Move panel_1 back to the left - // panel_1.update(cx, |panel_1, cx| { - // panel_1.set_position(DockPosition::Left, cx) - // }); + // // Wo don't close the left dock, because panel_2 wasn't the active panel + // workspace.update(cx, |workspace, cx| { + // let left_dock = workspace.left_dock(); + // assert!(left_dock.read(cx).is_open()); + // assert_eq!( + // left_dock.read(cx).visible_panel().unwrap().panel_id(), + // panel_1.panel_id(), + // ); + // }); - // workspace.update(cx, |workspace, cx| { - // // Since panel_1 was visible on the right, we open the left dock and make panel_1 active. - // let left_dock = workspace.left_dock(); - // assert!(left_dock.read(cx).is_open()); - // assert_eq!( - // left_dock.read(cx).visible_panel().unwrap().id(), - // panel_1.id() - // ); - // assert_eq!(left_dock.read(cx).active_panel_size(cx).unwrap(), 1337.); - // // And right the dock should be closed as it no longer has any panels. - // assert!(!workspace.right_dock().read(cx).is_open()); + // // Emitting a ZoomIn event shows the panel as zoomed. + // panel_1.update(cx, |_, cx| cx.emit(PanelEvent::ZoomIn)); + // workspace.update(cx, |workspace, _| { + // assert_eq!(workspace.zoomed, Some(panel_1.to_any().downgrade())); + // assert_eq!(workspace.zoomed_position, Some(DockPosition::Left)); + // }); - // // Now we move panel_1 to the bottom - // panel_1.set_position(DockPosition::Bottom, cx); - // }); + // // Move panel to another dock while it is zoomed + // panel_1.update(cx, |panel, cx| panel.set_position(DockPosition::Right, cx)); + // workspace.update(cx, |workspace, _| { + // assert_eq!(workspace.zoomed, Some(panel_1.to_any().downgrade())); - // workspace.update(cx, |workspace, cx| { - // // Since panel_1 was visible on the left, we close the left dock. - // assert!(!workspace.left_dock().read(cx).is_open()); - // // The bottom dock is sized based on the panel's default size, - // // since the panel orientation changed from vertical to horizontal. - // let bottom_dock = workspace.bottom_dock(); - // assert_eq!( - // bottom_dock.read(cx).active_panel_size(cx).unwrap(), - // panel_1.size(cx), - // ); - // // Close bottom dock and move panel_1 back to the left. - // bottom_dock.update(cx, |bottom_dock, cx| bottom_dock.set_open(false, cx)); - // panel_1.set_position(DockPosition::Left, cx); - // }); + // assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); + // }); - // // Emit activated event on panel 1 - // panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::Activated)); + // // If focus is transferred to another view that's not a panel or another pane, we still show + // // the panel as zoomed. + // let other_focus_handle = cx.update(|cx| cx.focus_handle()); + // cx.update(|cx| cx.focus(&other_focus_handle)); + // workspace.update(cx, |workspace, _| { + // assert_eq!(workspace.zoomed, Some(panel_1.to_any().downgrade())); + // assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); + // }); - // // Now the left dock is open and panel_1 is active and focused. - // workspace.update(cx, |workspace, cx| { - // let left_dock = workspace.left_dock(); - // assert!(left_dock.read(cx).is_open()); - // assert_eq!( - // left_dock.read(cx).visible_panel().unwrap().id(), - // panel_1.id() - // ); - // assert!(panel_1.is_focused(cx)); - // }); + // // If focus is transferred elsewhere in the workspace, the panel is no longer zoomed. + // workspace.update(cx, |_, cx| cx.focus_self()); + // workspace.update(cx, |workspace, _| { + // assert_eq!(workspace.zoomed, None); + // assert_eq!(workspace.zoomed_position, None); + // }); - // // Emit closed event on panel 2, which is not active - // panel_2.update(cx, |_, cx| cx.emit(TestPanelEvent::Closed)); + // // If focus is transferred again to another view that's not a panel or a pane, we won't + // // show the panel as zoomed because it wasn't zoomed before. + // cx.update(|cx| cx.focus(&other_focus_handle)); + // workspace.update(cx, |workspace, _| { + // assert_eq!(workspace.zoomed, None); + // assert_eq!(workspace.zoomed_position, None); + // }); - // // Wo don't close the left dock, because panel_2 wasn't the active panel - // workspace.update(cx, |workspace, cx| { - // let left_dock = workspace.left_dock(); - // assert!(left_dock.read(cx).is_open()); - // assert_eq!( - // left_dock.read(cx).visible_panel().unwrap().id(), - // panel_1.id() - // ); - // }); + // // When focus is transferred back to the panel, it is zoomed again. + // panel_1.update(cx, |_, cx| cx.focus_self()); + // workspace.update(cx, |workspace, _| { + // assert_eq!(workspace.zoomed, Some(panel_1.to_any().downgrade())); + // assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); + // }); - // // Emitting a ZoomIn event shows the panel as zoomed. - // panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomIn)); - // workspace.update(cx, |workspace, _| { - // assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); - // assert_eq!(workspace.zoomed_position, Some(DockPosition::Left)); - // }); + // // Emitting a ZoomOut event unzooms the panel. + // panel_1.update(cx, |_, cx| cx.emit(PanelEvent::ZoomOut)); + // workspace.update(cx, |workspace, _| { + // assert_eq!(workspace.zoomed, None); + // assert_eq!(workspace.zoomed_position, None); + // }); - // // Move panel to another dock while it is zoomed - // panel_1.update(cx, |panel, cx| panel.set_position(DockPosition::Right, cx)); - // workspace.update(cx, |workspace, _| { - // assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); - // assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); - // }); + // // Emit closed event on panel 1, which is active + // panel_1.update(cx, |_, cx| cx.emit(PanelEvent::Close)); - // // If focus is transferred to another view that's not a panel or another pane, we still show - // // the panel as zoomed. - // let focus_receiver = cx.build_view(|_| EmptyView); - // focus_receiver.update(cx, |_, cx| cx.focus_self()); - // workspace.update(cx, |workspace, _| { - // assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); - // assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); - // }); - - // // If focus is transferred elsewhere in the workspace, the panel is no longer zoomed. - // workspace.update(cx, |_, cx| cx.focus_self()); - // workspace.update(cx, |workspace, _| { - // assert_eq!(workspace.zoomed, None); - // assert_eq!(workspace.zoomed_position, None); - // }); - - // // If focus is transferred again to another view that's not a panel or a pane, we won't - // // show the panel as zoomed because it wasn't zoomed before. - // focus_receiver.update(cx, |_, cx| cx.focus_self()); - // workspace.update(cx, |workspace, _| { - // assert_eq!(workspace.zoomed, None); - // assert_eq!(workspace.zoomed_position, None); - // }); - - // // When focus is transferred back to the panel, it is zoomed again. - // panel_1.update(cx, |_, cx| cx.focus_self()); - // workspace.update(cx, |workspace, _| { - // assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any())); - // assert_eq!(workspace.zoomed_position, Some(DockPosition::Right)); - // }); - - // // Emitting a ZoomOut event unzooms the panel. - // panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomOut)); - // workspace.update(cx, |workspace, _| { - // assert_eq!(workspace.zoomed, None); - // assert_eq!(workspace.zoomed_position, None); - // }); - - // // Emit closed event on panel 1, which is active - // panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::Closed)); - - // // Now the left dock is closed, because panel_1 was the active panel - // workspace.update(cx, |workspace, cx| { - // let right_dock = workspace.right_dock(); - // assert!(!right_dock.read(cx).is_open()); - // }); - // } + // // Now the left dock is closed, because panel_1 was the active panel + // workspace.update(cx, |workspace, cx| { + // let right_dock = workspace.right_dock(); + // assert!(!right_dock.read(cx).is_open()); + // }); + // } pub fn init_test(cx: &mut TestAppContext) { cx.update(|cx| { From 4e7005b4f76b32da998e8b781ec2df28d81864d4 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Thu, 14 Dec 2023 17:22:13 -0500 Subject: [PATCH 034/644] Use bitflags to hold error states --- Cargo.lock | 19 ++++++++------- crates/feedback2/Cargo.toml | 6 +++-- crates/feedback2/src/feedback_modal.rs | 33 ++++++++++++++------------ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68919dffbc..7b7acd54f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -182,7 +182,7 @@ dependencies = [ "alacritty_config", "alacritty_config_derive", "base64 0.13.1", - "bitflags 2.4.0", + "bitflags 2.4.1", "home", "libc", "log", @@ -1025,9 +1025,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" dependencies = [ "serde", ] @@ -3280,6 +3280,7 @@ name = "feedback2" version = "0.1.0" dependencies = [ "anyhow", + "bitflags 2.4.1", "client2", "db2", "editor2", @@ -4026,7 +4027,7 @@ dependencies = [ "async-task", "backtrace", "bindgen 0.65.1", - "bitflags 2.4.0", + "bitflags 2.4.1", "block", "cbindgen", "cocoa", @@ -6195,7 +6196,7 @@ version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if 1.0.0", "foreign-types", "libc", @@ -7915,7 +7916,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -8031,7 +8032,7 @@ version = "0.38.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno 0.3.3", "libc", "linux-raw-sys 0.4.7", @@ -9134,7 +9135,7 @@ dependencies = [ "atoi", "base64 0.21.4", "bigdecimal", - "bitflags 2.4.0", + "bitflags 2.4.1", "byteorder", "bytes 1.5.0", "chrono", @@ -9181,7 +9182,7 @@ dependencies = [ "atoi", "base64 0.21.4", "bigdecimal", - "bitflags 2.4.0", + "bitflags 2.4.1", "byteorder", "chrono", "crc", diff --git a/crates/feedback2/Cargo.toml b/crates/feedback2/Cargo.toml index 0e34ee410b..9fe125ec57 100644 --- a/crates/feedback2/Cargo.toml +++ b/crates/feedback2/Cargo.toml @@ -18,7 +18,6 @@ gpui = { package = "gpui2", path = "../gpui2" } language = { package = "language2", path = "../language2" } menu = { package = "menu2", path = "../menu2" } project = { package = "project2", path = "../project2" } -regex.workspace = true search = { package = "search2", path = "../search2" } settings = { package = "settings2", path = "../settings2" } theme = { package = "theme2", path = "../theme2" } @@ -26,13 +25,16 @@ ui = { package = "ui2", path = "../ui2" } util = { path = "../util" } workspace = { package = "workspace2", path = "../workspace2"} +bitflags = "2.4.1" +human_bytes = "0.4.1" + anyhow.workspace = true futures.workspace = true -human_bytes = "0.4.1" isahc.workspace = true lazy_static.workspace = true log.workspace = true postage.workspace = true +regex.workspace = true serde.workspace = true serde_derive.workspace = true smallvec.workspace = true diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 3130c4bad6..22904f3a0a 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -1,6 +1,7 @@ use std::{ops::RangeInclusive, sync::Arc, time::Duration}; use anyhow::{anyhow, bail}; +use bitflags::bitflags; use client::{Client, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL}; use db::kvp::KEY_VALUE_STORE; use editor::{Editor, EditorEvent}; @@ -48,15 +49,17 @@ struct FeedbackRequestBody<'a> { token: &'a str, } -#[derive(Debug, Clone, PartialEq)] -enum InvalidStateIssue { - EmailAddress, - CharacterCount, +bitflags! { + #[derive(Debug, Clone, PartialEq)] + struct InvalidStateFlags: u8 { + const EmailAddress = 0b00000001; + const CharacterCount = 0b00000010; + } } #[derive(Debug, Clone, PartialEq)] enum CannotSubmitReason { - InvalidState { issues: Vec }, + InvalidState { flags: InvalidStateFlags }, AwaitingSubmission, } @@ -322,7 +325,7 @@ impl FeedbackModal { return; } - let mut invalid_state_issues = Vec::new(); + let mut invalid_state_flags = InvalidStateFlags::empty(); let valid_email_address = match self.email_address_editor.read(cx).text_option(cx) { Some(email_address) => Regex::new(EMAIL_REGEX).unwrap().is_match(&email_address), @@ -330,37 +333,37 @@ impl FeedbackModal { }; if !valid_email_address { - invalid_state_issues.push(InvalidStateIssue::EmailAddress); + invalid_state_flags |= InvalidStateFlags::EmailAddress; } if !FEEDBACK_CHAR_LIMIT.contains(&self.character_count) { - invalid_state_issues.push(InvalidStateIssue::CharacterCount); + invalid_state_flags |= InvalidStateFlags::CharacterCount; } - if invalid_state_issues.is_empty() { + if invalid_state_flags.is_empty() { self.submission_state = Some(SubmissionState::CanSubmit); } else { self.submission_state = Some(SubmissionState::CannotSubmit { reason: CannotSubmitReason::InvalidState { - issues: invalid_state_issues, + flags: invalid_state_flags, }, }); } } fn valid_email_address(&self) -> bool { - !self.in_invalid_state(InvalidStateIssue::EmailAddress) + !self.in_invalid_state(InvalidStateFlags::EmailAddress) } fn valid_character_count(&self) -> bool { - !self.in_invalid_state(InvalidStateIssue::CharacterCount) + !self.in_invalid_state(InvalidStateFlags::CharacterCount) } - fn in_invalid_state(&self, a: InvalidStateIssue) -> bool { + fn in_invalid_state(&self, flag: InvalidStateFlags) -> bool { match self.submission_state { Some(SubmissionState::CannotSubmit { - reason: CannotSubmitReason::InvalidState { ref issues }, - }) => issues.contains(&a), + reason: CannotSubmitReason::InvalidState { ref flags }, + }) => flags.contains(flag), _ => false, } } From 6170895932b2f3ec12911dfc4373fbcb8b4cf9de Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Dec 2023 14:27:44 -0800 Subject: [PATCH 035/644] Fix bug in Workspace::activate_pane_in_direction Co-authored-by: Conrad --- crates/workspace2/src/workspace2.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 8318ba3f0f..6d0b057083 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -2036,20 +2036,20 @@ impl Workspace { _ => bounding_box.center(), }; - let distance_to_next = 1.; //todo(pane dividers styling) + let distance_to_next = 8.; //todo(pane dividers styling) let target = match direction { SplitDirection::Left => { - Point::new(bounding_box.origin.x - distance_to_next.into(), center.y) + Point::new(bounding_box.left() - distance_to_next.into(), center.y) } SplitDirection::Right => { Point::new(bounding_box.right() + distance_to_next.into(), center.y) } SplitDirection::Up => { - Point::new(center.x, bounding_box.origin.y - distance_to_next.into()) + Point::new(center.x, bounding_box.top() - distance_to_next.into()) } SplitDirection::Down => { - Point::new(center.x, bounding_box.top() + distance_to_next.into()) + Point::new(center.x, bounding_box.bottom() + distance_to_next.into()) } }; self.center.pane_at_pixel_position(target) From 8bac4e199d656fe0179fb300c2a435a63ea727d9 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 14 Dec 2023 17:28:45 -0500 Subject: [PATCH 036/644] Emit `editor_foreground` color from theme converter --- crates/theme2/src/themes/andromeda.rs | 2 ++ crates/theme2/src/themes/ayu.rs | 3 +++ crates/theme2/src/themes/dracula.rs | 1 + crates/theme2/src/themes/gruvbox.rs | 6 +++++ crates/theme2/src/themes/night_owl.rs | 2 ++ crates/theme2/src/themes/noctis.rs | 11 ++++++++ crates/theme2/src/themes/nord.rs | 1 + crates/theme2/src/themes/palenight.rs | 3 +++ crates/theme2/src/themes/rose_pine.rs | 3 +++ crates/theme2/src/themes/solarized.rs | 2 ++ crates/theme2/src/themes/synthwave_84.rs | 1 + crates/theme_importer/src/theme_printer.rs | 1 + crates/theme_importer/src/vscode/converter.rs | 26 ++++++++++++------- 13 files changed, 52 insertions(+), 10 deletions(-) diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index 33284cdbee..32bccf172a 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -47,6 +47,7 @@ pub fn andromeda() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x3a3f4c77).into()), scrollbar_track_background: Some(rgba(0x23262eff).into()), scrollbar_track_border: Some(rgba(0x1b1d23ff).into()), + editor_foreground: Some(rgba(0xd5ced9ff).into()), editor_background: Some(rgba(0x23262eff).into()), editor_gutter_background: Some(rgba(0x23262eff).into()), editor_line_number: Some(rgba(0x746f77ff).into()), @@ -261,6 +262,7 @@ pub fn andromeda() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x3a3f4c77).into()), scrollbar_track_background: Some(rgba(0x262a33ff).into()), scrollbar_track_border: Some(rgba(0x1b1d23ff).into()), + editor_foreground: Some(rgba(0xd5ced9ff).into()), editor_background: Some(rgba(0x262a33ff).into()), editor_gutter_background: Some(rgba(0x262a33ff).into()), editor_line_number: Some(rgba(0x746f77ff).into()), diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index 0164e4786f..f7c8f8c129 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -46,6 +46,7 @@ pub fn ayu() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x8a919966).into()), scrollbar_track_background: Some(rgba(0xf8f9faff).into()), scrollbar_track_border: Some(rgba(0x6b7d8f1f).into()), + editor_foreground: Some(rgba(0x8a9199ff).into()), editor_background: Some(rgba(0xf8f9faff).into()), editor_gutter_background: Some(rgba(0xf8f9faff).into()), editor_line_number: Some(rgba(0x8a919966).into()), @@ -352,6 +353,7 @@ pub fn ayu() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x707a8c66).into()), scrollbar_track_background: Some(rgba(0x1f2430ff).into()), scrollbar_track_border: Some(rgba(0x171b24ff).into()), + editor_foreground: Some(rgba(0x707a8cff).into()), editor_background: Some(rgba(0x1f2430ff).into()), editor_gutter_background: Some(rgba(0x1f2430ff).into()), editor_line_number: Some(rgba(0x8a919966).into()), @@ -658,6 +660,7 @@ pub fn ayu() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x565b6666).into()), scrollbar_track_background: Some(rgba(0x0b0e14ff).into()), scrollbar_track_border: Some(rgba(0x1e232bff).into()), + editor_foreground: Some(rgba(0x565b66ff).into()), editor_background: Some(rgba(0x0b0e14ff).into()), editor_gutter_background: Some(rgba(0x0b0e14ff).into()), editor_line_number: Some(rgba(0x6c738099).into()), diff --git a/crates/theme2/src/themes/dracula.rs b/crates/theme2/src/themes/dracula.rs index 5933ec46ff..3fabb67ec2 100644 --- a/crates/theme2/src/themes/dracula.rs +++ b/crates/theme2/src/themes/dracula.rs @@ -43,6 +43,7 @@ pub fn dracula() -> UserThemeFamily { tab_active_background: Some(rgba(0x282a36ff).into()), scrollbar_track_background: Some(rgba(0x282a36ff).into()), scrollbar_track_border: Some(rgba(0x191a21ff).into()), + editor_foreground: Some(rgba(0xf8f8f2ff).into()), editor_background: Some(rgba(0x282a36ff).into()), editor_gutter_background: Some(rgba(0x282a36ff).into()), editor_line_number: Some(rgba(0x6272a4ff).into()), diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 4573f55ca1..2c96665534 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -46,6 +46,7 @@ pub fn gruvbox() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x50494599).into()), scrollbar_track_background: Some(rgba(0x1d2021ff).into()), scrollbar_track_border: Some(rgba(0x1d202100).into()), + editor_foreground: Some(rgba(0xebdbb2ff).into()), editor_background: Some(rgba(0x1d2021ff).into()), editor_gutter_background: Some(rgba(0x1d2021ff).into()), editor_line_number: Some(rgba(0x665c54ff).into()), @@ -338,6 +339,7 @@ pub fn gruvbox() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x50494599).into()), scrollbar_track_background: Some(rgba(0x282828ff).into()), scrollbar_track_border: Some(rgba(0x28282800).into()), + editor_foreground: Some(rgba(0xebdbb2ff).into()), editor_background: Some(rgba(0x282828ff).into()), editor_gutter_background: Some(rgba(0x282828ff).into()), editor_line_number: Some(rgba(0x665c54ff).into()), @@ -630,6 +632,7 @@ pub fn gruvbox() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x50494599).into()), scrollbar_track_background: Some(rgba(0x32302fff).into()), scrollbar_track_border: Some(rgba(0x32302f00).into()), + editor_foreground: Some(rgba(0xebdbb2ff).into()), editor_background: Some(rgba(0x32302fff).into()), editor_gutter_background: Some(rgba(0x32302fff).into()), editor_line_number: Some(rgba(0x665c54ff).into()), @@ -922,6 +925,7 @@ pub fn gruvbox() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0xd5c4a199).into()), scrollbar_track_background: Some(rgba(0xf9f5d7ff).into()), scrollbar_track_border: Some(rgba(0xf9f5d700).into()), + editor_foreground: Some(rgba(0x3c3836ff).into()), editor_background: Some(rgba(0xf9f5d7ff).into()), editor_gutter_background: Some(rgba(0xf9f5d7ff).into()), editor_line_number: Some(rgba(0xbdae93ff).into()), @@ -1214,6 +1218,7 @@ pub fn gruvbox() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0xd5c4a199).into()), scrollbar_track_background: Some(rgba(0xfbf1c7ff).into()), scrollbar_track_border: Some(rgba(0xfbf1c700).into()), + editor_foreground: Some(rgba(0x3c3836ff).into()), editor_background: Some(rgba(0xfbf1c7ff).into()), editor_gutter_background: Some(rgba(0xfbf1c7ff).into()), editor_line_number: Some(rgba(0xbdae93ff).into()), @@ -1506,6 +1511,7 @@ pub fn gruvbox() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0xd5c4a199).into()), scrollbar_track_background: Some(rgba(0xf2e5bcff).into()), scrollbar_track_border: Some(rgba(0xf2e5bc00).into()), + editor_foreground: Some(rgba(0x3c3836ff).into()), editor_background: Some(rgba(0xf2e5bcff).into()), editor_gutter_background: Some(rgba(0xf2e5bcff).into()), editor_line_number: Some(rgba(0xbdae93ff).into()), diff --git a/crates/theme2/src/themes/night_owl.rs b/crates/theme2/src/themes/night_owl.rs index 71c980e631..778dfabeb8 100644 --- a/crates/theme2/src/themes/night_owl.rs +++ b/crates/theme2/src/themes/night_owl.rs @@ -46,6 +46,7 @@ pub fn night_owl() -> UserThemeFamily { scrollbar_thumb_hover_background: Some(rgba(0x084d8180).into()), scrollbar_thumb_border: Some(rgba(0x084d8180).into()), scrollbar_track_background: Some(rgba(0x011627ff).into()), + editor_foreground: Some(rgba(0xd6deebff).into()), editor_background: Some(rgba(0x011627ff).into()), editor_gutter_background: Some(rgba(0x011627ff).into()), editor_line_number: Some(rgba(0x4b6479ff).into()), @@ -305,6 +306,7 @@ pub fn night_owl() -> UserThemeFamily { tab_inactive_background: Some(rgba(0xf0f0f0ff).into()), tab_active_background: Some(rgba(0xf6f6f6ff).into()), scrollbar_track_background: Some(rgba(0xfbfbfbff).into()), + editor_foreground: Some(rgba(0x403f53ff).into()), editor_background: Some(rgba(0xfbfbfbff).into()), editor_gutter_background: Some(rgba(0xfbfbfbff).into()), editor_line_number: Some(rgba(0x90a7b2ff).into()), diff --git a/crates/theme2/src/themes/noctis.rs b/crates/theme2/src/themes/noctis.rs index 51b442a57e..614553593d 100644 --- a/crates/theme2/src/themes/noctis.rs +++ b/crates/theme2/src/themes/noctis.rs @@ -47,6 +47,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x008ee633).into()), scrollbar_track_background: Some(rgba(0x07273bff).into()), scrollbar_track_border: Some(rgba(0x07273bff).into()), + editor_foreground: Some(rgba(0xbecfdaff).into()), editor_background: Some(rgba(0x07273bff).into()), editor_gutter_background: Some(rgba(0x07273bff).into()), editor_line_number: Some(rgba(0x4d6c80ff).into()), @@ -324,6 +325,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0xeb609133).into()), scrollbar_track_background: Some(rgba(0x322a2dff).into()), scrollbar_track_border: Some(rgba(0x322a2dff).into()), + editor_foreground: Some(rgba(0xcbbec2ff).into()), editor_background: Some(rgba(0x322a2dff).into()), editor_gutter_background: Some(rgba(0x322a2dff).into()), editor_line_number: Some(rgba(0x715b63ff).into()), @@ -601,6 +603,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), scrollbar_track_background: Some(rgba(0xf4f6f6ff).into()), scrollbar_track_border: Some(rgba(0xf4f6f6ff).into()), + editor_foreground: Some(rgba(0x005661ff).into()), editor_background: Some(rgba(0xf4f6f6ff).into()), editor_gutter_background: Some(rgba(0xf4f6f6ff).into()), editor_line_number: Some(rgba(0xa0abacff).into()), @@ -878,6 +881,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), scrollbar_track_background: Some(rgba(0xf2f1f8ff).into()), scrollbar_track_border: Some(rgba(0xf2f1f8ff).into()), + editor_foreground: Some(rgba(0x0c006bff).into()), editor_background: Some(rgba(0xf2f1f8ff).into()), editor_gutter_background: Some(rgba(0xf2f1f8ff).into()), editor_line_number: Some(rgba(0x9d9ab1ff).into()), @@ -1155,6 +1159,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), scrollbar_track_background: Some(rgba(0xfef8ecff).into()), scrollbar_track_border: Some(rgba(0xfef8ecff).into()), + editor_foreground: Some(rgba(0x005661ff).into()), editor_background: Some(rgba(0xfef8ecff).into()), editor_gutter_background: Some(rgba(0xfef8ecff).into()), editor_line_number: Some(rgba(0xa0abacff).into()), @@ -1432,6 +1437,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x3f7fa633).into()), scrollbar_track_background: Some(rgba(0x1b2932ff).into()), scrollbar_track_border: Some(rgba(0x1b2932ff).into()), + editor_foreground: Some(rgba(0xc5cdd3ff).into()), editor_background: Some(rgba(0x1b2932ff).into()), editor_gutter_background: Some(rgba(0x1b2932ff).into()), editor_line_number: Some(rgba(0x5d6e79ff).into()), @@ -1709,6 +1715,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), scrollbar_track_background: Some(rgba(0x052529ff).into()), scrollbar_track_border: Some(rgba(0x052529ff).into()), + editor_foreground: Some(rgba(0xb2cacdff).into()), editor_background: Some(rgba(0x052529ff).into()), editor_gutter_background: Some(rgba(0x052529ff).into()), editor_line_number: Some(rgba(0x4e6b6eff).into()), @@ -1986,6 +1993,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), scrollbar_track_background: Some(rgba(0x031417ff).into()), scrollbar_track_border: Some(rgba(0x031417ff).into()), + editor_foreground: Some(rgba(0xb2cacdff).into()), editor_background: Some(rgba(0x031417ff).into()), editor_gutter_background: Some(rgba(0x031417ff).into()), editor_line_number: Some(rgba(0x4e6b6eff).into()), @@ -2263,6 +2271,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), scrollbar_track_background: Some(rgba(0x031417ff).into()), scrollbar_track_border: Some(rgba(0x031417ff).into()), + editor_foreground: Some(rgba(0xb2cacdff).into()), editor_background: Some(rgba(0x031417ff).into()), editor_gutter_background: Some(rgba(0x031417ff).into()), editor_line_number: Some(rgba(0x4e6b6eff).into()), @@ -2540,6 +2549,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x7060eb33).into()), scrollbar_track_background: Some(rgba(0x292640ff).into()), scrollbar_track_border: Some(rgba(0x292640ff).into()), + editor_foreground: Some(rgba(0xc5c2d6ff).into()), editor_background: Some(rgba(0x292640ff).into()), editor_gutter_background: Some(rgba(0x292640ff).into()), editor_line_number: Some(rgba(0x5c5973ff).into()), @@ -2817,6 +2827,7 @@ pub fn noctis() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0xa660eb33).into()), scrollbar_track_background: Some(rgba(0x30243dff).into()), scrollbar_track_border: Some(rgba(0x30243dff).into()), + editor_foreground: Some(rgba(0xccbfd9ff).into()), editor_background: Some(rgba(0x30243dff).into()), editor_gutter_background: Some(rgba(0x30243dff).into()), editor_line_number: Some(rgba(0x665973ff).into()), diff --git a/crates/theme2/src/themes/nord.rs b/crates/theme2/src/themes/nord.rs index 949926c685..f3d03b3889 100644 --- a/crates/theme2/src/themes/nord.rs +++ b/crates/theme2/src/themes/nord.rs @@ -46,6 +46,7 @@ pub fn nord() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x434c5e99).into()), scrollbar_track_background: Some(rgba(0x2e3440ff).into()), scrollbar_track_border: Some(rgba(0x3b4252ff).into()), + editor_foreground: Some(rgba(0xd8dee9ff).into()), editor_background: Some(rgba(0x2e3440ff).into()), editor_gutter_background: Some(rgba(0x2e3440ff).into()), editor_line_number: Some(rgba(0x4c566aff).into()), diff --git a/crates/theme2/src/themes/palenight.rs b/crates/theme2/src/themes/palenight.rs index ab47cc1046..028d326229 100644 --- a/crates/theme2/src/themes/palenight.rs +++ b/crates/theme2/src/themes/palenight.rs @@ -46,6 +46,7 @@ pub fn palenight() -> UserThemeFamily { scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), scrollbar_thumb_border: Some(rgba(0x694ca466).into()), scrollbar_track_background: Some(rgba(0x292d3eff).into()), + editor_foreground: Some(rgba(0xffffffff).into()), editor_background: Some(rgba(0x292d3eff).into()), editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), @@ -331,6 +332,7 @@ pub fn palenight() -> UserThemeFamily { scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), scrollbar_thumb_border: Some(rgba(0x694ca466).into()), scrollbar_track_background: Some(rgba(0x292d3eff).into()), + editor_foreground: Some(rgba(0xffffffff).into()), editor_background: Some(rgba(0x292d3eff).into()), editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), @@ -616,6 +618,7 @@ pub fn palenight() -> UserThemeFamily { scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), scrollbar_thumb_border: Some(rgba(0x694ca466).into()), scrollbar_track_background: Some(rgba(0x292d3eff).into()), + editor_foreground: Some(rgba(0xffffffff).into()), editor_background: Some(rgba(0x292d3eff).into()), editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index d9091df347..a09364405f 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -47,6 +47,7 @@ pub fn rose_pine() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x6e6a8633).into()), scrollbar_track_background: Some(rgba(0x191724ff).into()), scrollbar_track_border: Some(rgba(0x6e6a8666).into()), + editor_foreground: Some(rgba(0xe0def4ff).into()), editor_background: Some(rgba(0x191724ff).into()), editor_gutter_background: Some(rgba(0x191724ff).into()), editor_line_number: Some(rgba(0x908caaff).into()), @@ -306,6 +307,7 @@ pub fn rose_pine() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x817c9c26).into()), scrollbar_track_background: Some(rgba(0x232136ff).into()), scrollbar_track_border: Some(rgba(0x817c9c4d).into()), + editor_foreground: Some(rgba(0xe0def4ff).into()), editor_background: Some(rgba(0x232136ff).into()), editor_gutter_background: Some(rgba(0x232136ff).into()), editor_line_number: Some(rgba(0x908caaff).into()), @@ -565,6 +567,7 @@ pub fn rose_pine() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x6e6a8614).into()), scrollbar_track_background: Some(rgba(0xfaf4edff).into()), scrollbar_track_border: Some(rgba(0x6e6a8626).into()), + editor_foreground: Some(rgba(0x575279ff).into()), editor_background: Some(rgba(0xfaf4edff).into()), editor_gutter_background: Some(rgba(0xfaf4edff).into()), editor_line_number: Some(rgba(0x797593ff).into()), diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index 25799bea28..9807a6cd3d 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -42,6 +42,7 @@ pub fn solarized() -> UserThemeFamily { tab_inactive_background: Some(rgba(0x004052ff).into()), tab_active_background: Some(rgba(0x002b37ff).into()), scrollbar_track_background: Some(rgba(0x002b36ff).into()), + editor_foreground: Some(rgba(0xbbbbbbff).into()), editor_background: Some(rgba(0x002b36ff).into()), editor_gutter_background: Some(rgba(0x002b36ff).into()), editor_line_number: Some(rgba(0x566c74ff).into()), @@ -307,6 +308,7 @@ pub fn solarized() -> UserThemeFamily { tab_inactive_background: Some(rgba(0xd3cbb7ff).into()), tab_active_background: Some(rgba(0xfdf6e3ff).into()), scrollbar_track_background: Some(rgba(0xfdf6e3ff).into()), + editor_foreground: Some(rgba(0x333333ff).into()), editor_background: Some(rgba(0xfdf6e3ff).into()), editor_gutter_background: Some(rgba(0xfdf6e3ff).into()), editor_line_number: Some(rgba(0x9ca8a6ff).into()), diff --git a/crates/theme2/src/themes/synthwave_84.rs b/crates/theme2/src/themes/synthwave_84.rs index 4f62732d7f..defc73ae56 100644 --- a/crates/theme2/src/themes/synthwave_84.rs +++ b/crates/theme2/src/themes/synthwave_84.rs @@ -39,6 +39,7 @@ pub fn synthwave_84() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x9d8bca30).into()), scrollbar_track_background: Some(rgba(0x262335ff).into()), scrollbar_track_border: Some(rgba(0x34294fb3).into()), + editor_foreground: Some(rgba(0xffffffff).into()), editor_background: Some(rgba(0x262335ff).into()), editor_gutter_background: Some(rgba(0x262335ff).into()), editor_line_number: Some(rgba(0xffffff73).into()), diff --git a/crates/theme_importer/src/theme_printer.rs b/crates/theme_importer/src/theme_printer.rs index 78c8719105..4726c90c6d 100644 --- a/crates/theme_importer/src/theme_printer.rs +++ b/crates/theme_importer/src/theme_printer.rs @@ -201,6 +201,7 @@ impl<'a> Debug for ThemeColorsRefinementPrinter<'a> { self.0.scrollbar_track_background, ), ("scrollbar_track_border", self.0.scrollbar_track_border), + ("editor_foreground", self.0.editor_foreground), ("editor_background", self.0.editor_background), ("editor_gutter_background", self.0.editor_gutter_background), ( diff --git a/crates/theme_importer/src/vscode/converter.rs b/crates/theme_importer/src/vscode/converter.rs index c9a07a1f7f..e4c95d6cf2 100644 --- a/crates/theme_importer/src/vscode/converter.rs +++ b/crates/theme_importer/src/vscode/converter.rs @@ -142,6 +142,16 @@ impl VsCodeThemeConverter { .as_ref() .traverse(|color| try_parse_color(&color))?; + let vscode_token_colors_foreground = self + .theme + .token_colors + .iter() + .find(|token_color| token_color.scope.is_none()) + .and_then(|token_color| token_color.settings.foreground.as_ref()) + .traverse(|color| try_parse_color(&color)) + .ok() + .flatten(); + Ok(ThemeColorsRefinement { border: vscode_panel_border, border_variant: vscode_panel_border, @@ -197,16 +207,7 @@ impl VsCodeThemeConverter { .foreground .as_ref() .traverse(|color| try_parse_color(&color))? - .or_else(|| { - self.theme - .token_colors - .iter() - .find(|token_color| token_color.scope.is_none()) - .and_then(|token_color| token_color.settings.foreground.as_ref()) - .traverse(|color| try_parse_color(&color)) - .ok() - .flatten() - }), + .or(vscode_token_colors_foreground), text_muted: vscode_colors .tab_inactive_foreground .as_ref() @@ -226,6 +227,11 @@ impl VsCodeThemeConverter { .as_ref() .traverse(|color| try_parse_color(&color))? .or(vscode_editor_background), + editor_foreground: vscode_colors + .foreground + .as_ref() + .traverse(|color| try_parse_color(&color))? + .or(vscode_token_colors_foreground), editor_background: vscode_editor_background, editor_gutter_background: vscode_editor_background, editor_line_number: vscode_colors From 292fac37bbe9109e4297d1e288c92c8784b9001d Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 14 Dec 2023 17:30:37 -0500 Subject: [PATCH 037/644] Use `editor.foreground` from VS Code for the editor foreground --- crates/theme2/src/themes/ayu.rs | 6 +++--- crates/theme2/src/themes/palenight.rs | 6 +++--- crates/theme2/src/themes/synthwave_84.rs | 1 - crates/theme_importer/src/vscode/converter.rs | 11 ++++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index f7c8f8c129..4c5d951230 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -46,7 +46,7 @@ pub fn ayu() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x8a919966).into()), scrollbar_track_background: Some(rgba(0xf8f9faff).into()), scrollbar_track_border: Some(rgba(0x6b7d8f1f).into()), - editor_foreground: Some(rgba(0x8a9199ff).into()), + editor_foreground: Some(rgba(0x5c6166ff).into()), editor_background: Some(rgba(0xf8f9faff).into()), editor_gutter_background: Some(rgba(0xf8f9faff).into()), editor_line_number: Some(rgba(0x8a919966).into()), @@ -353,7 +353,7 @@ pub fn ayu() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x707a8c66).into()), scrollbar_track_background: Some(rgba(0x1f2430ff).into()), scrollbar_track_border: Some(rgba(0x171b24ff).into()), - editor_foreground: Some(rgba(0x707a8cff).into()), + editor_foreground: Some(rgba(0xcccac2ff).into()), editor_background: Some(rgba(0x1f2430ff).into()), editor_gutter_background: Some(rgba(0x1f2430ff).into()), editor_line_number: Some(rgba(0x8a919966).into()), @@ -660,7 +660,7 @@ pub fn ayu() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x565b6666).into()), scrollbar_track_background: Some(rgba(0x0b0e14ff).into()), scrollbar_track_border: Some(rgba(0x1e232bff).into()), - editor_foreground: Some(rgba(0x565b66ff).into()), + editor_foreground: Some(rgba(0xbfbdb6ff).into()), editor_background: Some(rgba(0x0b0e14ff).into()), editor_gutter_background: Some(rgba(0x0b0e14ff).into()), editor_line_number: Some(rgba(0x6c738099).into()), diff --git a/crates/theme2/src/themes/palenight.rs b/crates/theme2/src/themes/palenight.rs index 028d326229..501a678577 100644 --- a/crates/theme2/src/themes/palenight.rs +++ b/crates/theme2/src/themes/palenight.rs @@ -46,7 +46,7 @@ pub fn palenight() -> UserThemeFamily { scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), scrollbar_thumb_border: Some(rgba(0x694ca466).into()), scrollbar_track_background: Some(rgba(0x292d3eff).into()), - editor_foreground: Some(rgba(0xffffffff).into()), + editor_foreground: Some(rgba(0xbfc7d5ff).into()), editor_background: Some(rgba(0x292d3eff).into()), editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), @@ -332,7 +332,7 @@ pub fn palenight() -> UserThemeFamily { scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), scrollbar_thumb_border: Some(rgba(0x694ca466).into()), scrollbar_track_background: Some(rgba(0x292d3eff).into()), - editor_foreground: Some(rgba(0xffffffff).into()), + editor_foreground: Some(rgba(0xbfc7d5ff).into()), editor_background: Some(rgba(0x292d3eff).into()), editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), @@ -618,7 +618,7 @@ pub fn palenight() -> UserThemeFamily { scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), scrollbar_thumb_border: Some(rgba(0x694ca466).into()), scrollbar_track_background: Some(rgba(0x292d3eff).into()), - editor_foreground: Some(rgba(0xffffffff).into()), + editor_foreground: Some(rgba(0xbfc7d5ff).into()), editor_background: Some(rgba(0x292d3eff).into()), editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), diff --git a/crates/theme2/src/themes/synthwave_84.rs b/crates/theme2/src/themes/synthwave_84.rs index defc73ae56..4f62732d7f 100644 --- a/crates/theme2/src/themes/synthwave_84.rs +++ b/crates/theme2/src/themes/synthwave_84.rs @@ -39,7 +39,6 @@ pub fn synthwave_84() -> UserThemeFamily { scrollbar_thumb_border: Some(rgba(0x9d8bca30).into()), scrollbar_track_background: Some(rgba(0x262335ff).into()), scrollbar_track_border: Some(rgba(0x34294fb3).into()), - editor_foreground: Some(rgba(0xffffffff).into()), editor_background: Some(rgba(0x262335ff).into()), editor_gutter_background: Some(rgba(0x262335ff).into()), editor_line_number: Some(rgba(0xffffff73).into()), diff --git a/crates/theme_importer/src/vscode/converter.rs b/crates/theme_importer/src/vscode/converter.rs index e4c95d6cf2..46d9c3d086 100644 --- a/crates/theme_importer/src/vscode/converter.rs +++ b/crates/theme_importer/src/vscode/converter.rs @@ -132,6 +132,11 @@ impl VsCodeThemeConverter { .as_ref() .traverse(|color| try_parse_color(&color))?; + let vscode_editor_foreground = vscode_colors + .editor_foreground + .as_ref() + .traverse(|color| try_parse_color(&color))?; + let vscode_editor_background = vscode_colors .editor_background .as_ref() @@ -227,11 +232,7 @@ impl VsCodeThemeConverter { .as_ref() .traverse(|color| try_parse_color(&color))? .or(vscode_editor_background), - editor_foreground: vscode_colors - .foreground - .as_ref() - .traverse(|color| try_parse_color(&color))? - .or(vscode_token_colors_foreground), + editor_foreground: vscode_editor_foreground.or(vscode_token_colors_foreground), editor_background: vscode_editor_background, editor_gutter_background: vscode_editor_background, editor_line_number: vscode_colors From 2b278e69f73589c9bb277ab5c63f5d86453452c7 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 14 Dec 2023 17:34:07 -0500 Subject: [PATCH 038/644] Use `editor_foreground` color in editor --- crates/editor2/src/editor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 89b5fd2efb..e58aa1000d 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -9297,7 +9297,7 @@ impl Render for Editor { let settings = ThemeSettings::get_global(cx); let text_style = match self.mode { EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle { - color: cx.theme().colors().text, + color: cx.theme().colors().editor_foreground, font_family: settings.ui_font.family.clone(), font_features: settings.ui_font.features, font_size: rems(0.875).into(), @@ -9310,7 +9310,7 @@ impl Render for Editor { }, EditorMode::Full => TextStyle { - color: cx.theme().colors().text, + color: cx.theme().colors().editor_foreground, font_family: settings.buffer_font.family.clone(), font_features: settings.buffer_font.features, font_size: settings.buffer_font_size(cx).into(), From 3cf003763e3af497351f6294b10259cce081348c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 14 Dec 2023 17:38:22 -0500 Subject: [PATCH 039/644] Use updated story container in Text story --- crates/story/src/story.rs | 118 ++++++++++++++++++++++---- crates/storybook2/src/stories/text.rs | 50 +++++++++-- 2 files changed, 148 insertions(+), 20 deletions(-) diff --git a/crates/story/src/story.rs b/crates/story/src/story.rs index 4985fb1961..3419af95b0 100644 --- a/crates/story/src/story.rs +++ b/crates/story/src/story.rs @@ -1,5 +1,6 @@ use gpui::{ - div, hsla, prelude::*, px, rems, AnyElement, Div, ElementId, Hsla, SharedString, WindowContext, + div, hsla, prelude::*, px, rems, AnyElement, Div, ElementId, Hsla, SharedString, Stateful, + WindowContext, }; use itertools::Itertools; use smallvec::SmallVec; @@ -49,47 +50,134 @@ pub fn story_color() -> StoryColor { StoryColor::new() } -pub struct Story {} +#[derive(IntoElement)] +pub struct StoryContainer { + title: SharedString, + relative_path: &'static str, + children: SmallVec<[AnyElement; 2]>, +} -impl Story { - pub fn container() -> Div { - div() - .size_full() - .flex() - .flex_col() - .bg(story_color().background) +impl StoryContainer { + pub fn new(title: impl Into, relative_path: &'static str) -> Self { + Self { + title: title.into(), + relative_path, + children: SmallVec::new(), + } } +} - // TODO: Move all stories to container2, then rename - pub fn container2(relative_path: &'static str) -> Div { +impl ParentElement for StoryContainer { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]> { + &mut self.children + } +} + +impl RenderOnce for StoryContainer { + type Rendered = Stateful
; + + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { div() .size_full() .flex() .flex_col() + .id("story_container") .bg(story_color().background) .child( div() .flex() + .flex_none() + .w_full() .justify_between() .p_2() + .bg(story_color().background) .border_b() .border_color(story_color().border) - .child(Story::title_for::()) + .child(Story::title(self.title)) .child( div() .text_xs() .text_color(story_color().primary) - .child(Story::open_story_link(relative_path)), + .child(Story::open_story_link(self.relative_path)), ), ) + .child( + div() + .w_full() + .h_px() + .flex_1() + .id("story_body") + .overflow_hidden_x() + .overflow_y_scroll() + .flex() + .flex_col() + .pb_4() + .children(self.children), + ) + } +} + +pub struct Story {} + +impl Story { + pub fn container() -> Div { + div().size_full().overflow_hidden().child( + div() + .id("story_container") + .overflow_y_scroll() + .w_full() + .min_h_full() + .flex() + .flex_col() + .bg(story_color().background), + ) + } + + // TODO: Move all stories to container2, then rename + pub fn container2(relative_path: &'static str) -> Div { + div().size_full().child( + div() + .size_full() + .id("story_container") + .overflow_y_scroll() + .flex() + .flex_col() + .flex_none() + .child( + div() + .flex() + .justify_between() + .p_2() + .border_b() + .border_color(story_color().border) + .child(Story::title_for::()) + .child( + div() + .text_xs() + .text_color(story_color().primary) + .child(Story::open_story_link(relative_path)), + ), + ) + .child( + div() + .w_full() + .min_h_full() + .flex() + .flex_col() + .bg(story_color().background), + ), + ) } pub fn open_story_link(relative_path: &'static str) -> impl Element { let path = PathBuf::from_iter([relative_path]); + div() - .id(SharedString::from(format!("id_{}", relative_path))) + .flex() + .gap_2() .text_xs() .text_color(story_color().primary) + .id(SharedString::from(format!("id_{}", relative_path))) .on_click({ let path = path.clone(); @@ -99,7 +187,7 @@ impl Story { std::process::Command::new("zed").arg(path).spawn().ok(); } }) - .child(Story::link(path.to_string_lossy().to_string())) + .children(vec![div().child(Story::link("Open in Zed →"))]) } pub fn title(title: impl Into) -> impl Element { diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index b48b9dd4b5..7c1d29a269 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -1,4 +1,7 @@ -use gpui::{div, red, Div, ParentElement, Render, Styled, View, VisualContext, WindowContext}; +use gpui::{ + div, green, red, Component, Div, HighlightStyle, InteractiveText, IntoElement, ParentElement, + Render, Styled, StyledText, View, VisualContext, WindowContext, +}; use indoc::indoc; use story::*; @@ -11,10 +14,13 @@ impl TextStory { } impl Render for TextStory { - type Element = Div; + type Element = Component; + + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { + StoryContainer::new("Text Story", "crates/storybook2/src/stories/text.rs") + .children( + vec![ - fn render(&mut self, _cx: &mut gpui::ViewContext) -> Self::Element { - Story::container2::("crates/storybook2/src/stories/text.rs").child( StorySection::new() .child( StoryItem::new("Default", div().bg(gpui::blue()).child("Hello World!")) @@ -71,10 +77,44 @@ impl Render for TextStory { "## }) ) - ) + .child( + StoryItem::new("Interactive Text", + InteractiveText::new( + "interactive", + StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ + (6..11, HighlightStyle { + background_color: Some(green()), + ..Default::default() + }), + ]), + ) + .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { + println!("Clicked range {range_ix}"); + }) + ) + .usage(indoc! {r##" + InteractiveText::new( + "interactive", + StyledText::new("Hello world, how is it going?").with_highlights(&cx.text_style(), [ + (6..11, HighlightStyle { + background_color: Some(green()), + ..Default::default() + }), + ]), + ) + .on_click(vec![2..4, 1..3, 7..9], |range_ix, _cx| { + println!("Clicked range {range_ix}"); + }) + "## + }) + ) + ] + ).into_element() } } +// TODO: Check all were updated to new style and remove + // impl Render for TextStory { // type Element = Div; From 936c78be941cbf6948b93c81e6e9ca07def9f4f2 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 14 Dec 2023 17:51:08 -0500 Subject: [PATCH 040/644] WIP IconButton story --- crates/storybook2/src/stories/text.rs | 2 +- .../ui2/src/components/stories/icon_button.rs | 214 +++++++++++++----- 2 files changed, 163 insertions(+), 53 deletions(-) diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index 7c1d29a269..99d722988d 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -1,5 +1,5 @@ use gpui::{ - div, green, red, Component, Div, HighlightStyle, InteractiveText, IntoElement, ParentElement, + div, green, red, Component, HighlightStyle, InteractiveText, IntoElement, ParentElement, Render, Styled, StyledText, View, VisualContext, WindowContext, }; use indoc::indoc; diff --git a/crates/ui2/src/components/stories/icon_button.rs b/crates/ui2/src/components/stories/icon_button.rs index 583f453d18..5391f0ac18 100644 --- a/crates/ui2/src/components/stories/icon_button.rs +++ b/crates/ui2/src/components/stories/icon_button.rs @@ -1,5 +1,5 @@ -use gpui::{Div, Render}; -use story::Story; +use gpui::{Component, Div, Render}; +use story::{Story, StoryContainer, StoryItem, StorySection}; use crate::{prelude::*, Tooltip}; use crate::{Icon, IconButton}; @@ -7,57 +7,167 @@ use crate::{Icon, IconButton}; pub struct IconButtonStory; impl Render for IconButtonStory { - type Element = Div; + type Element = Component; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - Story::container() - .child(Story::title_for::()) - .child(Story::label("Default")) - .child(div().w_8().child(IconButton::new("icon_a", Icon::Hash))) - .child(Story::label("Selected")) - .child( - div() - .w_8() - .child(IconButton::new("icon_a", Icon::Hash).selected(true)), - ) - .child(Story::label("Selected with `selected_icon`")) - .child( - div().w_8().child( - IconButton::new("icon_a", Icon::AudioOn) - .selected(true) - .selected_icon(Icon::AudioOff), - ), - ) - .child(Story::label("Disabled")) - .child( - div() - .w_8() - .child(IconButton::new("icon_a", Icon::Hash).disabled(true)), - ) - .child(Story::label("With `on_click`")) - .child( - div() - .w_8() - .child( - IconButton::new("with_on_click", Icon::Ai).on_click(|_event, _cx| { - println!("Clicked!"); - }), - ), - ) - .child(Story::label("With `tooltip`")) - .child( - div().w_8().child( - IconButton::new("with_tooltip", Icon::MessageBubbles) - .tooltip(|cx| Tooltip::text("Open messages", cx)), - ), - ) - .child(Story::label("Selected with `tooltip`")) - .child( - div().w_8().child( - IconButton::new("selected_with_tooltip", Icon::InlayHint) - .selected(true) - .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)), - ), - ) + let default_button = StoryItem::new( + "Default", + IconButton::new("default_icon_button", Icon::Hash), + ) + .description("Displays an icon button.") + .usage( + r#" + IconButton::new("default_icon_button", Icon::Hash) + "#, + ); + + let selected_button = StoryItem::new( + "Selected", + IconButton::new("selected_icon_button", Icon::Hash).selected(true), + ) + .description("Displays an icon button that is selected.") + .usage( + r#" + IconButton::new("selected_icon_button", Icon::Hash).selected(true) + "#, + ); + + let selected_with_selected_icon = StoryItem::new( + "Selected with `selected_icon`", + IconButton::new("selected_with_selected_icon_button", Icon::AudioOn) + .selected(true) + .selected_icon(Icon::AudioOff), + ) + .description( + "Displays an icon button that is selected and shows a different icon when selected.", + ) + .usage( + r#" + IconButton::new("selected_with_selected_icon_button", Icon::AudioOn) + .selected(true) + .selected_icon(Icon::AudioOff) + "#, + ); + + let disabled_button = StoryItem::new( + "Disabled", + IconButton::new("disabled_icon_button", Icon::Hash).disabled(true), + ) + .description("Displays an icon button that is disabled.") + .usage( + r#" + IconButton::new("disabled_icon_button", Icon::Hash).disabled(true) + "#, + ); + + let with_on_click_button = StoryItem::new( + "With `on_click`", + IconButton::new("with_on_click_button", Icon::Ai).on_click(|_event, _cx| { + println!("Clicked!"); + }), + ) + .description("Displays an icon button which triggers an event on click.") + .usage( + r#" + IconButton::new("with_on_click_button", Icon::Ai).on_click(|_event, _cx| { + println!("Clicked!"); + }) + "#, + ); + + let with_tooltip_button = StoryItem::new( + "With `tooltip`", + IconButton::new("with_tooltip_button", Icon::MessageBubbles) + .tooltip(|cx| Tooltip::text("Open messages", cx)), + ) + .description("Displays an icon button that has a tooltip when hovered.") + .usage( + r#" + IconButton::new("with_tooltip_button", Icon::MessageBubbles) + .tooltip(|cx| Tooltip::text("Open messages", cx)) + "#, + ); + + let selected_with_tooltip_button = StoryItem::new( + "Selected with `tooltip`", + IconButton::new("selected_with_tooltip_button", Icon::InlayHint) + .selected(true) + .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)), + ) + .description("Displays a selected icon button with tooltip.") + .usage( + r#" + IconButton::new("selected_with_tooltip_button", Icon::InlayHint) + .selected(true) + .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)) + "#, + ); + + let buttons = vec![ + default_button, + selected_button, + selected_with_selected_icon, + disabled_button, + with_on_click_button, + with_tooltip_button, + selected_with_tooltip_button, + ]; + + StoryContainer::new( + "Icon Button", + "crates/ui2/src/components/stories/icon_button.rs", + ) + .children(vec![StorySection::new().children(buttons)]) + .into_element() + + // Story::container() + // .child(Story::title_for::()) + // .child(Story::label("Default")) + // .child(div().w_8().child(IconButton::new("icon_a", Icon::Hash))) + // .child(Story::label("Selected")) + // .child( + // div() + // .w_8() + // .child(IconButton::new("icon_a", Icon::Hash).selected(true)), + // ) + // .child(Story::label("Selected with `selected_icon`")) + // .child( + // div().w_8().child( + // IconButton::new("icon_a", Icon::AudioOn) + // .selected(true) + // .selected_icon(Icon::AudioOff), + // ), + // ) + // .child(Story::label("Disabled")) + // .child( + // div() + // .w_8() + // .child(IconButton::new("icon_a", Icon::Hash).disabled(true)), + // ) + // .child(Story::label("With `on_click`")) + // .child( + // div() + // .w_8() + // .child( + // IconButton::new("with_on_click", Icon::Ai).on_click(|_event, _cx| { + // println!("Clicked!"); + // }), + // ), + // ) + // .child(Story::label("With `tooltip`")) + // .child( + // div().w_8().child( + // IconButton::new("with_tooltip", Icon::MessageBubbles) + // .tooltip(|cx| Tooltip::text("Open messages", cx)), + // ), + // ) + // .child(Story::label("Selected with `tooltip`")) + // .child( + // div().w_8().child( + // IconButton::new("selected_with_tooltip", Icon::InlayHint) + // .selected(true) + // .tooltip(|cx| Tooltip::text("Toggle inlay hints", cx)), + // ), + // ) } } From e4f9bddbab32140f23840037a3d8989bc665aecc Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 14 Dec 2023 17:56:42 -0500 Subject: [PATCH 041/644] Remove unused imports --- crates/ui2/src/components/stories/icon_button.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ui2/src/components/stories/icon_button.rs b/crates/ui2/src/components/stories/icon_button.rs index 5391f0ac18..0d219efbc2 100644 --- a/crates/ui2/src/components/stories/icon_button.rs +++ b/crates/ui2/src/components/stories/icon_button.rs @@ -1,5 +1,5 @@ -use gpui::{Component, Div, Render}; -use story::{Story, StoryContainer, StoryItem, StorySection}; +use gpui::{Component, Render}; +use story::{StoryContainer, StoryItem, StorySection}; use crate::{prelude::*, Tooltip}; use crate::{Icon, IconButton}; From 4c63c74f920d11cff2ecefabd9e09fb001d076d1 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Thu, 14 Dec 2023 15:23:24 -0800 Subject: [PATCH 042/644] Fix bug in drag move dispatch co-authored-by: conrad --- crates/gpui2/src/elements/div.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 395afdcc88..1019e5f5e6 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -213,7 +213,7 @@ pub trait InteractiveElement: Sized { listener: impl Fn(&DragMoveEvent, &mut WindowContext) + 'static, ) -> Self where - T: Render, + T: 'static, { self.interactivity().mouse_move_listeners.push(Box::new( move |event, bounds, phase, cx| { @@ -223,7 +223,7 @@ pub trait InteractiveElement: Sized { if cx .active_drag .as_ref() - .is_some_and(|drag| drag.value.type_id() == TypeId::of::()) + .is_some_and(|drag| (*drag.value).type_id() == TypeId::of::()) { (listener)( &DragMoveEvent { From bc3e6649f87ab468e0a564857dbeb23915cf0ef4 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 14 Dec 2023 18:52:14 -0500 Subject: [PATCH 043/644] Fix warning in release mode (#3662) This PR fixes a warning that was present in release mode, which was preventing the nightly builds from running: ``` error: variable does not need to be mutable --> crates/gpui2/src/elements/div.rs:547:9 | 547 | let mut div = Div { | ----^^^ | | | help: remove this `mut` | = note: `-D unused-mut` implied by `-D warnings` ``` Release Notes: - N/A --- crates/gpui2/src/elements/div.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 395afdcc88..257ba64b8c 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -544,17 +544,20 @@ pub type ActionListener = Box Div { - let mut div = Div { - interactivity: Interactivity::default(), - children: SmallVec::default(), + #[cfg(debug_assertions)] + let interactivity = { + let mut interactivity = Interactivity::default(); + interactivity.location = Some(*core::panic::Location::caller()); + interactivity }; - #[cfg(debug_assertions)] - { - div.interactivity.location = Some(*core::panic::Location::caller()); - } + #[cfg(not(debug_assertions))] + let interactivity = Interactivity::default(); - div + Div { + interactivity, + children: SmallVec::default(), + } } pub struct Div { From 8b4cf383798fd288f2e0c189b0f3af69b50775e3 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Thu, 14 Dec 2023 15:53:06 -0800 Subject: [PATCH 044/644] Fix dock resize handles co-authored-by: conrad --- crates/gpui2/src/elements/canvas.rs | 8 +++--- crates/workspace2/src/dock.rs | 39 ++++++++++++++++++----------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/crates/gpui2/src/elements/canvas.rs b/crates/gpui2/src/elements/canvas.rs index b3afd335d4..6a7d68e831 100644 --- a/crates/gpui2/src/elements/canvas.rs +++ b/crates/gpui2/src/elements/canvas.rs @@ -27,7 +27,7 @@ impl IntoElement for Canvas { } impl Element for Canvas { - type State = (); + type State = Style; fn layout( &mut self, @@ -37,11 +37,11 @@ impl Element for Canvas { let mut style = Style::default(); style.refine(&self.style); let layout_id = cx.request_layout(&style, []); - (layout_id, ()) + (layout_id, style) } - fn paint(self, bounds: Bounds, _: &mut (), cx: &mut WindowContext) { - (self.paint_callback)(&bounds, cx) + fn paint(self, bounds: Bounds, style: &mut Style, cx: &mut WindowContext) { + style.paint(bounds, cx, |cx| (self.paint_callback)(&bounds, cx)); } } diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 54480f0b68..f76bb82177 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -486,12 +486,9 @@ impl Render for Dock { if let Some(entry) = self.visible_entry() { let size = entry.panel.size(cx); - let mut pre_resize_handle = None; - let mut post_resize_handle = None; let position = self.position; - let handler = div() + let mut handle = div() .id("resize-handle") - .bg(cx.theme().colors().border) .on_drag(DraggedDock(position), |dock, cx| { cx.build_view(|_| dock.clone()) }) @@ -506,16 +503,31 @@ impl Render for Dock { match self.position() { DockPosition::Left => { - post_resize_handle = - Some(handler.min_w(HANDLE_SIZE).h_full().cursor_col_resize()) + handle = handle + .absolute() + .right(px(0.)) + .top(px(0.)) + .h_full() + .w(HANDLE_SIZE) + .cursor_col_resize(); } DockPosition::Bottom => { - pre_resize_handle = - Some(handler.w_full().min_h(HANDLE_SIZE).cursor_row_resize()) + handle = handle + .absolute() + .top(px(0.)) + .left(px(0.)) + .w_full() + .h(HANDLE_SIZE) + .cursor_row_resize(); } DockPosition::Right => { - pre_resize_handle = - Some(handler.min_w(HANDLE_SIZE).h_full().cursor_col_resize()) + handle = handle + .absolute() + .top(px(0.)) + .left(px(0.)) + .w_full() + .h(HANDLE_SIZE) + .cursor_col_resize(); } } @@ -531,16 +543,15 @@ impl Render for Dock { DockPosition::Right => this.border_l(), DockPosition::Bottom => this.border_t(), }) - .children(pre_resize_handle) .child( div() .map(|this| match self.position().axis() { - Axis::Horizontal => this.min_w(px(size) - HANDLE_SIZE).h_full(), - Axis::Vertical => this.min_h(px(size) - HANDLE_SIZE).w_full(), + Axis::Horizontal => this.min_w(px(size)).h_full(), + Axis::Vertical => this.min_h(px(size)).w_full(), }) .child(entry.panel.to_any()), ) - .children(post_resize_handle) + .child(handle) } else { div() } From ad8165ae797d48db42689424429bc5f2e195edf7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 14 Dec 2023 17:20:27 -0700 Subject: [PATCH 045/644] Rename draw2 -> draw_and_update_state --- crates/editor2/src/element.rs | 2 +- crates/gpui2/src/element.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 831b6cd35a..0f1b565b9d 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -933,7 +933,7 @@ impl EditorElement { cx.stop_propagation(); }, )) - .draw2( + .draw_and_update_state( fold_bounds.origin, fold_bounds.size, cx, diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index f4bcb17f3c..b446c2fe86 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -23,7 +23,7 @@ pub trait IntoElement: Sized { self.into_element().into_any() } - fn draw2( + fn draw_and_update_state( self, origin: Point, available_space: Size, From d6383ab0c629e09bc5f8177e0db0fcc6e7dcfd06 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Dec 2023 16:20:19 -0800 Subject: [PATCH 046/644] Fix stickiness of main pane drag target Reimplement the pane drag targets using on_drag_move --- crates/gpui2/src/elements/div.rs | 6 +- crates/workspace2/src/pane.rs | 196 ++++++++++++++----------------- 2 files changed, 90 insertions(+), 112 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index aa77480944..fb730a0700 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -33,6 +33,7 @@ pub struct GroupStyle { pub struct DragMoveEvent { pub event: MouseMoveEvent, + pub bounds: Bounds, drag: PhantomData, } @@ -208,7 +209,7 @@ pub trait InteractiveElement: Sized { self } - fn on_drag_move( + fn on_drag_move( mut self, listener: impl Fn(&DragMoveEvent, &mut WindowContext) + 'static, ) -> Self @@ -223,11 +224,12 @@ pub trait InteractiveElement: Sized { if cx .active_drag .as_ref() - .is_some_and(|drag| (*drag.value).type_id() == TypeId::of::()) + .is_some_and(|drag| drag.value.as_ref().type_id() == TypeId::of::()) { (listener)( &DragMoveEvent { event: event.clone(), + bounds: bounds.bounds, drag: PhantomData, }, cx, diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 4c436daada..712e447905 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -8,9 +8,10 @@ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AppContext, - AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, Focusable, - FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, - ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, + AsyncWindowContext, DismissEvent, Div, DragMoveEvent, EntityId, EventEmitter, FocusHandle, + Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, + Render, ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView, + WindowContext, }; use parking_lot::Mutex; use project::{Project, ProjectEntryId, ProjectPath}; @@ -28,8 +29,8 @@ use std::{ use theme::ThemeSettings; use ui::{ - h_stack, prelude::*, right_click_menu, ButtonSize, Color, Icon, IconButton, IconSize, - Indicator, Label, Tab, TabBar, TabPosition, Tooltip, + prelude::*, right_click_menu, ButtonSize, Color, Icon, IconButton, IconSize, Indicator, Label, + Tab, TabBar, TabPosition, Tooltip, }; use ui::{v_stack, ContextMenu}; use util::{maybe, truncate_and_remove_front, ResultExt}; @@ -179,6 +180,7 @@ pub struct Pane { // tab_context_menu: ViewHandle, workspace: WeakView, project: Model, + drag_split_direction: Option, // can_drop: Rc, &WindowContext) -> bool>, can_split: bool, // render_tab_bar_buttons: Rc) -> AnyElement>, @@ -361,6 +363,7 @@ impl Pane { new_item_menu: None, split_item_menu: None, tab_bar_scroll_handle: ScrollHandle::new(), + drag_split_direction: None, // tab_bar_context_menu: TabBarContextMenu { // kind: TabBarContextMenuKind::New, // handle: context_menu, @@ -1503,9 +1506,11 @@ impl Pane { .drag_over::(|tab| tab.bg(cx.theme().colors().tab_active_background)) .drag_over::(|tab| tab.bg(gpui::red())) .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { + this.drag_split_direction = None; this.handle_tab_drop(dragged_tab, ix, cx) })) .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { + this.drag_split_direction = None; this.handle_project_entry_drop(entry_id, cx) })) .when_some(item.tab_tooltip_text(cx), |tab, text| { @@ -1655,9 +1660,11 @@ impl Pane { }) .drag_over::(|bar| bar.bg(gpui::red())) .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { + this.drag_split_direction = None; this.handle_tab_drop(dragged_tab, this.items.len(), cx) })) .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { + this.drag_split_direction = None; this.handle_project_entry_drop(entry_id, cx) })), ) @@ -1719,18 +1726,42 @@ impl Pane { self.zoomed } + fn handle_drag_move(&mut self, event: &DragMoveEvent, cx: &mut ViewContext) { + let edge_width = cx.rem_size() * 8; + let cursor = event.event.position; + let direction = if cursor.x < event.bounds.left() + edge_width { + Some(SplitDirection::Left) + } else if cursor.x > event.bounds.right() - edge_width { + Some(SplitDirection::Right) + } else if cursor.y < event.bounds.top() + edge_width { + Some(SplitDirection::Up) + } else if cursor.y > event.bounds.bottom() - edge_width { + Some(SplitDirection::Down) + } else { + None + }; + if direction != self.drag_split_direction { + self.drag_split_direction = direction; + cx.notify(); + } + } + fn handle_tab_drop( &mut self, dragged_tab: &DraggedTab, ix: usize, cx: &mut ViewContext<'_, Pane>, ) { + let mut to_pane = cx.view().clone(); + let split_direction = self.drag_split_direction; let item_id = dragged_tab.item_id; let from_pane = dragged_tab.pane.clone(); - let to_pane = cx.view().clone(); self.workspace .update(cx, |_, cx| { cx.defer(move |workspace, cx| { + if let Some(split_direction) = split_direction { + to_pane = workspace.split_pane(to_pane, split_direction, cx); + } workspace.move_item(from_pane, to_pane, item_id, ix, cx); }); }) @@ -1742,7 +1773,8 @@ impl Pane { project_entry_id: &ProjectEntryId, cx: &mut ViewContext<'_, Pane>, ) { - let to_pane = cx.view().downgrade(); + let mut to_pane = cx.view().clone(); + let split_direction = self.drag_split_direction; let project_entry_id = *project_entry_id; self.workspace .update(cx, |_, cx| { @@ -1752,53 +1784,11 @@ impl Pane { .read(cx) .path_for_entry(project_entry_id, cx) { + if let Some(split_direction) = split_direction { + to_pane = workspace.split_pane(to_pane, split_direction, cx); + } workspace - .open_path(path, Some(to_pane), true, cx) - .detach_and_log_err(cx); - } - }); - }) - .log_err(); - } - - fn handle_split_tab_drop( - &mut self, - dragged_tab: &DraggedTab, - split_direction: SplitDirection, - cx: &mut ViewContext<'_, Pane>, - ) { - let item_id = dragged_tab.item_id; - let from_pane = dragged_tab.pane.clone(); - let to_pane = cx.view().clone(); - self.workspace - .update(cx, |_, cx| { - cx.defer(move |workspace, cx| { - let pane = workspace.split_pane(to_pane, split_direction, cx); - workspace.move_item(from_pane, pane, item_id, 0, cx); - }); - }) - .log_err(); - } - - fn handle_split_project_entry_drop( - &mut self, - project_entry_id: &ProjectEntryId, - split_direction: SplitDirection, - cx: &mut ViewContext<'_, Pane>, - ) { - let project_entry_id = *project_entry_id; - let current_pane = cx.view().clone(); - self.workspace - .update(cx, |_, cx| { - cx.defer(move |workspace, cx| { - if let Some(path) = workspace - .project() - .read(cx) - .path_for_entry(project_entry_id, cx) - { - let pane = workspace.split_pane(current_pane, split_direction, cx); - workspace - .open_path(path, Some(pane.downgrade()), true, cx) + .open_path(path, Some(to_pane.downgrade()), true, cx) .detach_and_log_err(cx); } }); @@ -1817,6 +1807,9 @@ impl Render for Pane { type Element = Focusable
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + let mut drag_target_color = cx.theme().colors().text; + drag_target_color.a = 0.5; + v_stack() .key_context("Pane") .track_focus(&self.focus_handle) @@ -1894,71 +1887,54 @@ impl Render for Pane { }), ) .child(self.render_tab_bar(cx)) - .child(self.toolbar.clone()) - .child(if let Some(item) = self.active_item() { - let mut drag_target_color = cx.theme().colors().text; - drag_target_color.a = 0.5; - - div() - .flex() + .child( + // main content + v_stack() .flex_1() .relative() - .child(item.to_any()) + .group("") + .on_drag_move::(cx.listener(Self::handle_drag_move)) + .on_drag_move::(cx.listener(Self::handle_drag_move)) + .child(self.toolbar.clone()) + .map(|div| { + if let Some(item) = self.active_item() { + div.child(item.to_any()) + } else { + div.items_center().size_full().justify_center().child( + Label::new("Open a file or project to get started.") + .color(Color::Muted), + ) + } + }) .child( + // drag target div() + .invisible() .absolute() - .full() - .z_index(1) - .drag_over::(|style| style.bg(drag_target_color)) - .drag_over::(|style| style.bg(gpui::red())) - .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { + .bg(drag_target_color) + .group_drag_over::("", |style| style.visible()) + .group_drag_over::("", |style| style.visible()) + .on_drop(cx.listener(move |this, dragged_tab, cx| { this.handle_tab_drop(dragged_tab, this.active_item_index(), cx) })) - .on_drop(cx.listener(move |this, entry_id: &ProjectEntryId, cx| { + .on_drop(cx.listener(move |this, entry_id, cx| { this.handle_project_entry_drop(entry_id, cx) - })), - ) - .children( - [ - (SplitDirection::Up, 2), - (SplitDirection::Down, 2), - (SplitDirection::Left, 3), - (SplitDirection::Right, 3), - ] - .into_iter() - .map(|(direction, z_index)| { - let div = div() - .absolute() - .z_index(z_index) - .invisible() - .bg(drag_target_color) - .drag_over::(|style| style.visible()) - .drag_over::(|style| style.visible()) - .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { - this.handle_split_tab_drop(dragged_tab, direction, cx) - })) - .on_drop(cx.listener( - move |this, entry_id: &ProjectEntryId, cx| { - this.handle_split_project_entry_drop( - entry_id, direction, cx, - ) - }, - )); - match direction { - SplitDirection::Up => div.top_0().left_0().right_0().h_32(), - SplitDirection::Down => div.left_0().bottom_0().right_0().h_32(), - SplitDirection::Left => div.top_0().left_0().bottom_0().w_32(), - SplitDirection::Right => div.top_0().bottom_0().right_0().w_32(), - } - }), - ) - } else { - h_stack() - .items_center() - .size_full() - .justify_center() - .child(Label::new("Open a file or project to get started.").color(Color::Muted)) - }) + })) + .map(|div| match self.drag_split_direction { + None => div.full(), + Some(SplitDirection::Up) => div.top_0().left_0().right_0().h_32(), + Some(SplitDirection::Down) => { + div.left_0().bottom_0().right_0().h_32() + } + Some(SplitDirection::Left) => { + div.top_0().left_0().bottom_0().w_32() + } + Some(SplitDirection::Right) => { + div.top_0().bottom_0().right_0().w_32() + } + }), + ), + ) .on_mouse_down( MouseButton::Navigate(NavigationDirection::Back), cx.listener(|pane, _, cx| { From 842f15c65b76d73701a10e4404ee51b4dabb2563 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Dec 2023 16:35:58 -0800 Subject: [PATCH 047/644] Fix centering of empty pane text --- crates/workspace2/src/pane.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 712e447905..6b5a131ea0 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1889,21 +1889,27 @@ impl Render for Pane { .child(self.render_tab_bar(cx)) .child( // main content - v_stack() + div() .flex_1() .relative() .group("") .on_drag_move::(cx.listener(Self::handle_drag_move)) .on_drag_move::(cx.listener(Self::handle_drag_move)) - .child(self.toolbar.clone()) .map(|div| { if let Some(item) = self.active_item() { - div.child(item.to_any()) + div.flex_col() + .child(self.toolbar.clone()) + .child(item.to_any()) } else { - div.items_center().size_full().justify_center().child( - Label::new("Open a file or project to get started.") - .color(Color::Muted), - ) + div.flex() + .flex_row() + .items_center() + .size_full() + .justify_center() + .child( + Label::new("Open a file or project to get started.") + .color(Color::Muted), + ) } }) .child( From 52b9fc303b6393712ec06f5113ce2c1c59e5dad3 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Dec 2023 16:52:03 -0800 Subject: [PATCH 048/644] Fix overlay rendering when dragging onto the center of a pane --- crates/workspace2/src/pane.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 6b5a131ea0..11588212ef 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1927,7 +1927,7 @@ impl Render for Pane { this.handle_project_entry_drop(entry_id, cx) })) .map(|div| match self.drag_split_direction { - None => div.full(), + None => div.top_0().left_0().right_0().bottom_0(), Some(SplitDirection::Up) => div.top_0().left_0().right_0().h_32(), Some(SplitDirection::Down) => { div.left_0().bottom_0().right_0().h_32() From ead52067412636f9ad09663313a894d3f5635ad4 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Thu, 14 Dec 2023 17:00:07 -0800 Subject: [PATCH 049/644] Fix todos in auto-update --- crates/auto_update2/src/auto_update.rs | 19 ++++++------------- .../auto_update2/src/update_notification.rs | 6 ++++-- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/crates/auto_update2/src/auto_update.rs b/crates/auto_update2/src/auto_update.rs index 31e474242a..4bf2bca063 100644 --- a/crates/auto_update2/src/auto_update.rs +++ b/crates/auto_update2/src/auto_update.rs @@ -9,12 +9,14 @@ use gpui::{ ViewContext, VisualContext, }; use isahc::AsyncBody; + use serde::Deserialize; use serde_derive::Serialize; use smol::io::AsyncReadExt; use settings::{Settings, SettingsStore}; use smol::{fs::File, process::Command}; + use std::{ffi::OsString, sync::Arc, time::Duration}; use update_notification::UpdateNotification; use util::channel::{AppCommitSha, ReleaseChannel}; @@ -24,16 +26,7 @@ use workspace::Workspace; const SHOULD_SHOW_UPDATE_NOTIFICATION_KEY: &str = "auto-updater-should-show-updated-notification"; const POLL_INTERVAL: Duration = Duration::from_secs(60 * 60); -//todo!(remove CheckThatAutoUpdaterWorks) -actions!( - auto_update, - [ - Check, - DismissErrorMessage, - ViewReleaseNotes, - CheckThatAutoUpdaterWorks - ] -); +actions!(auto_update, [Check, DismissErrorMessage, ViewReleaseNotes]); #[derive(Serialize)] struct UpdateRequestBody { @@ -90,7 +83,10 @@ pub fn init(http_client: Arc, server_url: String, cx: &mut AppCo cx.observe_new_views(|workspace: &mut Workspace, _cx| { workspace.register_action(|_, action: &Check, cx| check(action, cx)); + workspace.register_action(|_, action, cx| view_release_notes(action, cx)); + // @nate - code to trigger update notification on launch + // todo!("remove this when Nate is done") // workspace.show_notification(0, _cx, |cx| { // cx.build_view(|_| UpdateNotification::new(SemanticVersion::from_str("1.1.1").unwrap())) // }); @@ -119,9 +115,6 @@ pub fn init(http_client: Arc, server_url: String, cx: &mut AppCo updater }); cx.set_global(Some(auto_updater)); - //todo!(action) - // cx.add_global_action(view_release_notes); - // cx.add_action(UpdateNotification::dismiss); } } diff --git a/crates/auto_update2/src/update_notification.rs b/crates/auto_update2/src/update_notification.rs index 4a2efcf807..8bb08912b0 100644 --- a/crates/auto_update2/src/update_notification.rs +++ b/crates/auto_update2/src/update_notification.rs @@ -2,6 +2,7 @@ use gpui::{ div, DismissEvent, Div, EventEmitter, InteractiveElement, ParentElement, Render, SemanticVersion, StatefulInteractiveElement, Styled, ViewContext, }; +use menu::Cancel; use util::channel::ReleaseChannel; use workspace::ui::{h_stack, v_stack, Icon, IconElement, Label, StyledExt}; @@ -18,6 +19,7 @@ impl Render for UpdateNotification { let app_name = cx.global::().display_name(); v_stack() + .on_action(cx.listener(UpdateNotification::dismiss)) .elevation_3(cx) .p_4() .child( @@ -32,7 +34,7 @@ impl Render for UpdateNotification { .id("cancel") .child(IconElement::new(Icon::Close)) .cursor_pointer() - .on_click(cx.listener(|this, _, cx| this.dismiss(cx))), + .on_click(cx.listener(|this, _, cx| this.dismiss(&menu::Cancel, cx))), ), ) .child( @@ -50,7 +52,7 @@ impl UpdateNotification { Self { version } } - pub fn dismiss(&mut self, cx: &mut ViewContext) { + pub fn dismiss(&mut self, _: &Cancel, cx: &mut ViewContext) { cx.emit(DismissEvent); } } From 6973b1b592cb77954c7324bf1b1216084cf6e8b5 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Thu, 14 Dec 2023 17:48:49 -0800 Subject: [PATCH 050/644] Add several red outlines --- crates/collab_ui2/src/collab_panel.rs | 23 +++- .../src/collab_panel/contact_finder.rs | 39 +------ crates/collab_ui2/src/collab_titlebar_item.rs | 106 ++++++++++-------- 3 files changed, 79 insertions(+), 89 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 65a994e6d9..4edf5ef35b 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2142,7 +2142,7 @@ impl CollabPanel { } fn render_signed_out(&mut self, cx: &mut ViewContext) -> Div { - v_stack().child( + v_stack().border_1().border_color(gpui::red()).child( Button::new("sign_in", "Sign in to collaborate").on_click(cx.listener( |this, _, cx| { let client = this.client.clone(); @@ -2301,9 +2301,14 @@ impl CollabPanel { .into_any_element() }), Section::Contacts => Some( - IconButton::new("add-contact", Icon::Plus) - .on_click(cx.listener(|this, _, cx| this.toggle_contact_finder(cx))) - .tooltip(|cx| Tooltip::text("Search for new contact", cx)) + div() + .border_1() + .border_color(gpui::red()) + .child( + IconButton::new("add-contact", Icon::Plus) + .on_click(cx.listener(|this, _, cx| this.toggle_contact_finder(cx))) + .tooltip(|cx| Tooltip::text("Search for new contact", cx)), + ) .into_any_element(), ), Section::Channels => Some( @@ -2323,7 +2328,7 @@ impl CollabPanel { | Section::Offline => true, }; - h_stack() + let mut row = h_stack() .w_full() .group("section-header") .child( @@ -2350,7 +2355,13 @@ impl CollabPanel { .detach_and_log_err(cx) }, )) - }) + }); + + if section == Section::Offline { + row = div().border_1().border_color(gpui::red()).child(row); + } + + row } fn render_contact( diff --git a/crates/collab_ui2/src/collab_panel/contact_finder.rs b/crates/collab_ui2/src/collab_panel/contact_finder.rs index bd0c5d4b07..3087e6812f 100644 --- a/crates/collab_ui2/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui2/src/collab_panel/contact_finder.rs @@ -11,14 +11,8 @@ use ui::{prelude::*, Avatar}; use util::{ResultExt as _, TryFutureExt}; use workspace::ModalView; -pub fn init(cx: &mut AppContext) { - //Picker::::init(cx); - //cx.add_action(ContactFinder::dismiss) -} - pub struct ContactFinder { picker: View>, - has_focus: bool, } impl ContactFinder { @@ -31,16 +25,12 @@ impl ContactFinder { }; let picker = cx.build_view(|cx| Picker::new(delegate, cx)); - Self { - picker, - has_focus: false, - } + Self { picker } } pub fn set_query(&mut self, query: String, cx: &mut ViewContext) { self.picker.update(cx, |picker, cx| { - // todo!() - // picker.set_query(query, cx); + picker.set_query(query, cx); }); } } @@ -62,32 +52,9 @@ impl Render for ContactFinder { .w(rems(34.)) } - // fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext) { - // self.has_focus = true; - // if cx.is_self_focused() { - // cx.focus(&self.picker) - // } - // } - - // fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext) { - // self.has_focus = false; - // } - type Element = Div; } -// impl Modal for ContactFinder { -// fn has_focus(&self) -> bool { -// self.has_focus -// } - -// fn dismiss_on_event(event: &Self::Event) -> bool { -// match event { -// PickerEvent::Dismiss => true, -// } -// } -// } - pub struct ContactFinderDelegate { parent: WeakView, potential_contacts: Arc<[Arc]>, @@ -161,7 +128,6 @@ impl PickerDelegate for ContactFinderDelegate { } fn dismissed(&mut self, cx: &mut ViewContext>) { - //cx.emit(PickerEvent::Dismiss); self.parent .update(cx, |_, cx| cx.emit(DismissEvent)) .log_err(); @@ -191,6 +157,7 @@ impl PickerDelegate for ContactFinderDelegate { .child(Label::new(user.github_login.clone())) .children(icon_path.map(|icon_path| svg().path(icon_path))), ) + // todo!() // Flex::row() // .with_children(user.avatar.clone().map(|avatar| { // Image::from_data(avatar) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 5b3d4c0942..2c48a66a1d 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -233,56 +233,68 @@ impl Render for CollabTitlebarItem { }), ) }) - .child(h_stack().px_1p5().map(|this| { - if let Some(user) = current_user { - // TODO: Finish implementing user menu popover - // - this.child( - popover_menu("user-menu") - .menu(|cx| { - ContextMenu::build(cx, |menu, _| menu.header("ADADA")) - }) - .trigger( - ButtonLike::new("user-menu") - .child( - h_stack() - .gap_0p5() - .child(Avatar::new(user.avatar_uri.clone())) + .child( + h_stack() + .border_color(gpui::red()) + .border_1() + .px_1p5() + .map(|this| { + if let Some(user) = current_user { + // TODO: Finish implementing user menu popover + // + this.child( + popover_menu("user-menu") + .menu(|cx| { + ContextMenu::build(cx, |menu, _| { + menu.header("ADADA") + }) + }) + .trigger( + ButtonLike::new("user-menu") .child( - IconElement::new(Icon::ChevronDown) - .color(Color::Muted), - ), + h_stack() + .gap_0p5() + .child(Avatar::new( + user.avatar_uri.clone(), + )) + .child( + IconElement::new(Icon::ChevronDown) + .color(Color::Muted), + ), + ) + .style(ButtonStyle::Subtle) + .tooltip(move |cx| { + Tooltip::text("Toggle User Menu", cx) + }), ) - .style(ButtonStyle::Subtle) - .tooltip(move |cx| { - Tooltip::text("Toggle User Menu", cx) - }), + .anchor(gpui::AnchorCorner::TopRight), ) - .anchor(gpui::AnchorCorner::TopRight), - ) - // this.child( - // ButtonLike::new("user-menu") - // .child( - // h_stack().gap_0p5().child(Avatar::data(avatar)).child( - // IconElement::new(Icon::ChevronDown).color(Color::Muted), - // ), - // ) - // .style(ButtonStyle::Subtle) - // .tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)), - // ) - } else { - this.child(Button::new("sign_in", "Sign in").on_click(move |_, cx| { - let client = client.clone(); - cx.spawn(move |mut cx| async move { - client - .authenticate_and_connect(true, &cx) - .await - .notify_async_err(&mut cx); - }) - .detach(); - })) - } - })), + // this.child( + // ButtonLike::new("user-menu") + // .child( + // h_stack().gap_0p5().child(Avatar::data(avatar)).child( + // IconElement::new(Icon::ChevronDown).color(Color::Muted), + // ), + // ) + // .style(ButtonStyle::Subtle) + // .tooltip(move |cx| Tooltip::text("Toggle User Menu", cx)), + // ) + } else { + this.child(Button::new("sign_in", "Sign in").on_click( + move |_, cx| { + let client = client.clone(); + cx.spawn(move |mut cx| async move { + client + .authenticate_and_connect(true, &cx) + .await + .notify_async_err(&mut cx); + }) + .detach(); + }, + )) + } + }), + ), ) } } From fbcaf96ab5bbdb1b47f301206ad91257dcdd2aed Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 14 Dec 2023 20:58:59 -0500 Subject: [PATCH 051/644] Track focus on TestItem --- crates/project_panel2/src/project_panel.rs | 2 +- crates/workspace2/src/item.rs | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index f7789c1a62..51d04e0468 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -1671,7 +1671,7 @@ mod tests { path::{Path, PathBuf}, sync::atomic::{self, AtomicUsize}, }; - use workspace::{dock::PanelHandle, AppState}; + use workspace::AppState; #[gpui::test] async fn test_visible_list(cx: &mut gpui::TestAppContext) { diff --git a/crates/workspace2/src/item.rs b/crates/workspace2/src/item.rs index c0242ffa17..30410550fc 100644 --- a/crates/workspace2/src/item.rs +++ b/crates/workspace2/src/item.rs @@ -760,8 +760,9 @@ pub mod test { use super::{Item, ItemEvent}; use crate::{ItemId, ItemNavHistory, Pane, Workspace, WorkspaceId}; use gpui::{ - AnyElement, AppContext, Context as _, Div, EntityId, EventEmitter, FocusableView, - IntoElement, Model, Render, SharedString, Task, View, ViewContext, VisualContext, WeakView, + AnyElement, AppContext, Context as _, Div, EntityId, EventEmitter, Focusable, + FocusableView, InteractiveElement, IntoElement, Model, Render, SharedString, Task, View, + ViewContext, VisualContext, WeakView, }; use project::{Project, ProjectEntryId, ProjectPath, WorktreeId}; use std::{any::Any, cell::Cell, path::Path}; @@ -909,10 +910,10 @@ pub mod test { } impl Render for TestItem { - type Element = Div; + type Element = Focusable
; fn render(&mut self, _: &mut ViewContext) -> Self::Element { - gpui::div() + gpui::div().track_focus(&self.focus_handle) } } From ff4da878f9d0026f4cfc78c39b2cfdf8433394fa Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 14 Dec 2023 21:33:11 -0500 Subject: [PATCH 052/644] Render panel in these tests --- crates/project_panel2/src/project_panel.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 51d04e0468..21989dd3ff 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -1927,7 +1927,12 @@ mod tests { let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let cx = &mut VisualTestContext::from_window(*workspace, cx); let panel = workspace - .update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)) + .update(cx, |workspace, cx| { + let panel = ProjectPanel::new(workspace, cx); + workspace.add_panel(panel.clone(), cx); + workspace.toggle_dock(panel.read(cx).position(cx), cx); + panel + }) .unwrap(); select_path(&panel, "root1", cx); @@ -2556,7 +2561,12 @@ mod tests { let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let cx = &mut VisualTestContext::from_window(*workspace, cx); let panel = workspace - .update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)) + .update(cx, |workspace, cx| { + let panel = ProjectPanel::new(workspace, cx); + workspace.add_panel(panel.clone(), cx); + workspace.toggle_dock(panel.read(cx).position(cx), cx); + panel + }) .unwrap(); select_path(&panel, "src/", cx); From d4e09230cc103b8366ba58e3c493b1f34857016b Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 14 Dec 2023 22:29:33 -0500 Subject: [PATCH 053/644] Give result-less project search a focus handle --- crates/search2/src/project_search.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index f1b0c16d57..25a44c4da2 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -273,13 +273,15 @@ pub enum ViewEvent { impl EventEmitter for ProjectSearchView {} impl Render for ProjectSearchView { - type Element = Div; + type Element = AnyElement; + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { if self.has_matches() { div() .flex_1() .size_full() .child(self.results_editor.clone()) + .into_any() } else { let model = self.model.read(cx); let has_no_results = model.no_results.unwrap_or(false); @@ -352,14 +354,20 @@ impl Render for ProjectSearchView { .max_w_96() .child(Label::new(text).size(LabelSize::Small)) }); - v_stack().flex_1().size_full().justify_center().child( - h_stack() - .size_full() - .justify_center() - .child(h_stack().flex_1()) - .child(v_stack().child(major_text).children(minor_text)) - .child(h_stack().flex_1()), - ) + v_stack() + .track_focus(&self.query_editor.focus_handle(cx)) + .flex_1() + .size_full() + .justify_center() + .child( + h_stack() + .size_full() + .justify_center() + .child(h_stack().flex_1()) + .child(v_stack().child(major_text).children(minor_text)) + .child(h_stack().flex_1()), + ) + .into_any() } } } From de523c2d8063610034e94ed803317107154a8977 Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 14 Dec 2023 23:49:44 -0500 Subject: [PATCH 054/644] Give correct focus handle when project search has no matches --- crates/gpui2/src/window.rs | 1 - crates/search2/src/project_search.rs | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index e2f53f7347..1c0849785b 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -489,7 +489,6 @@ impl<'a> WindowContext<'a> { #[cfg(any(test, feature = "test-support"))] { - println!("invalidating focus"); self.window.focus_invalidated = true; } diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index da48625b42..167c6fece2 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -378,7 +378,11 @@ impl Render for ProjectSearchView { impl FocusableView for ProjectSearchView { fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle { - self.results_editor.focus_handle(cx) + if self.has_matches() { + self.results_editor.focus_handle(cx) + } else { + self.query_editor.focus_handle(cx) + } } } From a6403aad1a246a5ca1013cac8c5c37407eada436 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 11:28:48 +0200 Subject: [PATCH 055/644] Remove extra nits, do not panic on clicking the buffer separator --- crates/editor2/src/element.rs | 4 ++-- crates/gpui2/src/platform/mac/metal_renderer.rs | 5 ----- crates/gpui2/src/view.rs | 11 ----------- crates/gpui2/src/window.rs | 2 -- 4 files changed, 2 insertions(+), 20 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 0f1b565b9d..a6d4bc20b1 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2284,8 +2284,8 @@ impl EditorElement { .cursor_pointer() .hover(|style| style.bg(cx.theme().colors().element_hover)) .on_click(cx.listener(|_editor, _event, _cx| { - // TODO: Implement collapsing path headers - todo!("Clicking path header") + // todo!() Implement collapsing path headers + // todo!("Clicking path header") })) .child( h_stack() diff --git a/crates/gpui2/src/platform/mac/metal_renderer.rs b/crates/gpui2/src/platform/mac/metal_renderer.rs index 3210a53c63..68768521ee 100644 --- a/crates/gpui2/src/platform/mac/metal_renderer.rs +++ b/crates/gpui2/src/platform/mac/metal_renderer.rs @@ -187,8 +187,6 @@ impl MetalRenderer { } pub fn draw(&mut self, scene: &Scene) { - let start = std::time::Instant::now(); - let layer = self.layer.clone(); let viewport_size = layer.drawable_size(); let viewport_size: Size = size( @@ -306,9 +304,6 @@ impl MetalRenderer { command_buffer.commit(); self.sprite_atlas.clear_textures(AtlasTextureKind::Path); - let duration_since_start = start.elapsed(); - println!("renderer draw: {:?}", duration_since_start); - command_buffer.wait_until_completed(); drawable.present(); } diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index fb61190731..1b4c2b6346 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -209,20 +209,9 @@ impl AnyView { cx: &mut WindowContext, ) { cx.with_absolute_element_offset(origin, |cx| { - let start_time = std::time::Instant::now(); let (layout_id, mut rendered_element) = (self.layout)(self, cx); - let duration = start_time.elapsed(); - println!("request layout: {:?}", duration); - - let start_time = std::time::Instant::now(); cx.compute_layout(layout_id, available_space); - let duration = start_time.elapsed(); - println!("compute layout: {:?}", duration); - - let start_time = std::time::Instant::now(); (self.paint)(self, &mut rendered_element, cx); - let duration = start_time.elapsed(); - println!("paint: {:?}", duration); }) } } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 1c0849785b..74c7204048 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1255,7 +1255,6 @@ impl<'a> WindowContext<'a> { /// Draw pixels to the display for this window based on the contents of its scene. pub(crate) fn draw(&mut self) -> Scene { - let t0 = std::time::Instant::now(); self.window.dirty = false; self.window.drawing = true; @@ -1347,7 +1346,6 @@ impl<'a> WindowContext<'a> { } self.window.drawing = false; - eprintln!("window draw: {:?}", t0.elapsed()); scene } From 31ff7d40ed67ac55d19f1d4b051d27003765e86f Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 11:34:00 +0200 Subject: [PATCH 056/644] Adjust copy/paste buffer only on the copy error action trigger --- crates/editor2/src/editor.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index e58aa1000d..664d1d7380 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -9739,12 +9739,8 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend }; highlighted_lines.push(line); } - let message = diagnostic.message; Arc::new(move |cx: &mut BlockContext| { - let message = message.clone(); let copy_id: SharedString = format!("copy-{}", cx.block_id.clone()).to_string().into(); - let write_to_clipboard = cx.write_to_clipboard(ClipboardItem::new(message.clone())); - // TODO: Nate: We should tint the background of the block with the severity color // We need to extend the theme before we can do this v_stack() @@ -9754,7 +9750,6 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend .bg(gpui::red()) .children(highlighted_lines.iter().map(|(line, highlights)| { let group_id = cx.block_id.to_string(); - h_stack() .group(group_id.clone()) .gap_2() @@ -9769,7 +9764,12 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend .size(ButtonSize::Compact) .style(ButtonStyle::Transparent) .visible_on_hover(group_id) - .on_click(cx.listener(move |_, _, cx| write_to_clipboard)) + .on_click(cx.listener({ + let message = diagnostic.message.clone(); + move |_, _, cx| { + cx.write_to_clipboard(ClipboardItem::new(message.clone())) + } + })) .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)), ), ) From 4bfe46f53a6eaacb02a748e8c33ed6ed24e4929c Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 12:15:20 +0200 Subject: [PATCH 057/644] Restore zed1 behavior for buffer search deploy --- crates/search2/src/buffer_search.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index 45495e5027..5db7aff736 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -338,7 +338,9 @@ impl BufferSearchBar { pane.update(cx, |this, cx| { this.toolbar().update(cx, |this, cx| { if let Some(search_bar) = this.item_of_type::() { - search_bar.update(cx, |this, cx| this.toggle(deploy, cx)); + search_bar.update(cx, |this, cx| { + this.deploy(deploy, cx); + }); return; } let view = cx.build_view(|cx| BufferSearchBar::new(cx)); @@ -1483,9 +1485,9 @@ mod tests { search_bar.select_all_matches(&SelectAllMatches, cx); }); assert!( - editor.update(cx, |this, cx| !this.is_focused(cx.window_context())), - "Should not switch focus to editor if SelectAllMatches does not find any matches" - ); + editor.update(cx, |this, cx| !this.is_focused(cx.window_context())), + "Should not switch focus to editor if SelectAllMatches does not find any matches" + ); search_bar.update(cx, |search_bar, cx| { let all_selections = editor.update(cx, |editor, cx| editor.selections.display_ranges(cx)); @@ -1651,6 +1653,7 @@ mod tests { assert_eq!(search_bar.search_options, SearchOptions::NONE); }); } + #[gpui::test] async fn test_replace_simple(cx: &mut TestAppContext) { let (editor, search_bar, cx) = init_test(cx); From 2b3d9deabe66e601e8b984a07188ade678e2689d Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 15 Dec 2023 12:07:25 +0100 Subject: [PATCH 058/644] Dismiss Recent Projects & VCS modals on ESC (#3671) Release Notes: - N/A --- crates/recent_projects2/src/recent_projects.rs | 5 ++++- crates/vcs_menu2/src/lib.rs | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/recent_projects2/src/recent_projects.rs b/crates/recent_projects2/src/recent_projects.rs index dff6aa12cc..3ecf1180af 100644 --- a/crates/recent_projects2/src/recent_projects.rs +++ b/crates/recent_projects2/src/recent_projects.rs @@ -76,7 +76,10 @@ impl RecentProjects { let delegate = RecentProjectsDelegate::new(weak_workspace, workspace_locations, true); - RecentProjects::new(delegate, cx) + let modal = RecentProjects::new(delegate, cx); + cx.subscribe(&modal.picker, |_, _, _, cx| cx.emit(DismissEvent)) + .detach(); + modal }); } else { workspace.show_notification(0, cx, |cx| { diff --git a/crates/vcs_menu2/src/lib.rs b/crates/vcs_menu2/src/lib.rs index e867e04dcd..ca3b685aa6 100644 --- a/crates/vcs_menu2/src/lib.rs +++ b/crates/vcs_menu2/src/lib.rs @@ -65,8 +65,13 @@ impl ModalBranchList { ) -> Result<()> { // Modal branch picker has a longer trailoff than a popover one. let delegate = BranchListDelegate::new(workspace, cx.view().clone(), 70, cx)?; - workspace.toggle_modal(cx, |cx| ModalBranchList { - picker: cx.build_view(|cx| Picker::new(delegate, cx)), + workspace.toggle_modal(cx, |cx| { + let modal = ModalBranchList { + picker: cx.build_view(|cx| Picker::new(delegate, cx)), + }; + cx.subscribe(&modal.picker, |_, _, _, cx| cx.emit(DismissEvent)) + .detach(); + modal }); Ok(()) From ff3f4f3027d7c4d03c8c163bac1158829e1af976 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 15 Dec 2023 12:20:54 +0100 Subject: [PATCH 059/644] search: Reintroduce whole word switch (#3672) It seems to have been lost in the recent styling pass. Release Notes: - N/A --- crates/search2/src/project_search.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 167c6fece2..7bd60891ce 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -1536,13 +1536,30 @@ impl Render for ProjectSearchBar { cx, ) }) - .selected(self.is_option_enabled(SearchOptions::WHOLE_WORD, cx)) + .selected(self.is_option_enabled(SearchOptions::CASE_SENSITIVE, cx)) .on_click(cx.listener( |this, _, cx| { - this.toggle_search_option(SearchOptions::WHOLE_WORD, cx); + this.toggle_search_option( + SearchOptions::CASE_SENSITIVE, + cx, + ); }, )), ) + .child( + IconButton::new("project-search-whole-word", Icon::WholeWord) + .tooltip(|cx| { + Tooltip::for_action( + "Toggle whole word", + &ToggleWholeWord, + cx, + ) + }) + .selected(self.is_option_enabled(SearchOptions::WHOLE_WORD, cx)) + .on_click(cx.listener(|this, _, cx| { + this.toggle_search_option(SearchOptions::WHOLE_WORD, cx); + })), + ) }), ), ); From e1ca8e81bb83c4a45b0f9b2fc7b5adf089697f9f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 15 Dec 2023 15:13:32 +0100 Subject: [PATCH 060/644] Use an Arena to reuse allocations for listeners --- crates/gpui2/src/arena.rs | 124 +++++++++++++++++++++++++++++++ crates/gpui2/src/gpui2.rs | 1 + crates/gpui2/src/key_dispatch.rs | 10 +-- crates/gpui2/src/window.rs | 105 +++++++++++++++----------- 4 files changed, 191 insertions(+), 49 deletions(-) create mode 100644 crates/gpui2/src/arena.rs diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs new file mode 100644 index 0000000000..cf6b877ba3 --- /dev/null +++ b/crates/gpui2/src/arena.rs @@ -0,0 +1,124 @@ +use std::{ + alloc, + ptr::{self, NonNull}, +}; + +pub struct Arena { + start: NonNull, + offset: usize, + elements: Vec, +} + +impl Default for Arena { + fn default() -> Self { + unsafe { + let layout = alloc::Layout::from_size_align(16 * 1024 * 1024, 1).unwrap(); + let ptr = alloc::alloc(layout); + Self { + start: NonNull::new_unchecked(ptr), + offset: 0, + elements: Vec::new(), + } + } + } +} + +struct ArenaElement { + value: NonNull, + drop: unsafe fn(NonNull), +} + +impl Arena { + pub fn clear(&mut self) { + for element in self.elements.drain(..) { + unsafe { + (element.drop)(element.value); + } + } + self.offset = 0; + } + + #[inline(always)] + pub fn alloc(&mut self, value: T) -> ArenaRef { + unsafe fn drop(ptr: NonNull) { + std::ptr::drop_in_place(ptr.cast::().as_ptr()); + } + + unsafe { + let layout = alloc::Layout::for_value(&value).pad_to_align(); + let value_ptr = self.start.as_ptr().add(self.offset).cast::(); + ptr::write(value_ptr, value); + + let value = NonNull::new_unchecked(value_ptr); + self.elements.push(ArenaElement { + value: value.cast(), + drop: drop::, + }); + self.offset += layout.size(); + ArenaRef(value) + } + } +} + +pub struct ArenaRef(NonNull); + +impl Copy for ArenaRef {} + +impl Clone for ArenaRef { + fn clone(&self) -> Self { + Self(self.0) + } +} + +impl ArenaRef { + pub unsafe fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef { + let u = f(self.get_mut()); + ArenaRef(NonNull::new_unchecked(u)) + } + + pub unsafe fn get_mut(&mut self) -> &mut T { + self.0.as_mut() + } +} + +#[cfg(test)] +mod tests { + use std::{cell::Cell, rc::Rc}; + + use super::*; + + #[test] + fn test_arena() { + let mut arena = Arena::default(); + let mut a = arena.alloc(1u64); + let mut b = arena.alloc(2u32); + let mut c = arena.alloc(3u16); + let mut d = arena.alloc(4u8); + assert_eq!(unsafe { *a.get_mut() }, 1); + assert_eq!(unsafe { *b.get_mut() }, 2); + assert_eq!(unsafe { *c.get_mut() }, 3); + assert_eq!(unsafe { *d.get_mut() }, 4); + + arena.clear(); + let mut a = arena.alloc(5u64); + let mut b = arena.alloc(6u32); + let mut c = arena.alloc(7u16); + let mut d = arena.alloc(8u8); + assert_eq!(unsafe { *a.get_mut() }, 5); + assert_eq!(unsafe { *b.get_mut() }, 6); + assert_eq!(unsafe { *c.get_mut() }, 7); + assert_eq!(unsafe { *d.get_mut() }, 8); + + // Ensure drop gets called. + let dropped = Rc::new(Cell::new(false)); + struct DropGuard(Rc>); + impl Drop for DropGuard { + fn drop(&mut self) { + self.0.set(true); + } + } + arena.alloc(DropGuard(dropped.clone())); + arena.clear(); + assert!(dropped.get()); + } +} diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index c711d1f5a2..322ca20608 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -2,6 +2,7 @@ mod action; mod app; +mod arena; mod assets; mod color; mod element; diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index ddb1f1e6ca..a9d717ea1a 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -1,6 +1,6 @@ use crate::{ - Action, ActionRegistry, DispatchPhase, FocusId, KeyBinding, KeyContext, KeyMatch, Keymap, - Keystroke, KeystrokeMatcher, WindowContext, + arena::ArenaRef, Action, ActionRegistry, DispatchPhase, FocusId, KeyBinding, KeyContext, + KeyMatch, Keymap, Keystroke, KeystrokeMatcher, WindowContext, }; use collections::HashMap; use parking_lot::Mutex; @@ -33,12 +33,12 @@ pub(crate) struct DispatchNode { parent: Option, } -type KeyListener = Rc; +type KeyListener = ArenaRef; #[derive(Clone)] pub(crate) struct DispatchActionListener { pub(crate) action_type: TypeId, - pub(crate) listener: Rc, + pub(crate) listener: ArenaRef, } impl DispatchTree { @@ -117,7 +117,7 @@ impl DispatchTree { pub fn on_action( &mut self, action_type: TypeId, - listener: Rc, + listener: ArenaRef, ) { self.active_node() .action_listeners diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 1c0849785b..202489ef0e 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1,15 +1,17 @@ use crate::{ - key_dispatch::DispatchActionListener, px, size, transparent_black, Action, AnyDrag, AnyView, - AppContext, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, - CursorStyle, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, - EntityId, EventEmitter, FileDropEvent, Flatten, FontId, GlobalElementId, GlyphId, Hsla, - ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeystrokeEvent, LayoutId, - Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent, - Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, - PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams, - RenderSvgParams, ScaledPixels, Scene, SceneBuilder, Shadow, SharedString, Size, Style, - SubscriberSet, Subscription, Surface, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, - VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, + arena::{Arena, ArenaRef}, + key_dispatch::DispatchActionListener, + px, size, transparent_black, Action, AnyDrag, AnyView, AppContext, AsyncWindowContext, + AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, + DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, + FontId, GlobalElementId, GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyBinding, KeyContext, + KeyDownEvent, KeystrokeEvent, LayoutId, Model, ModelContext, Modifiers, MonochromeSprite, + MouseButton, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, + PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, + RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, Scene, SceneBuilder, + Shadow, SharedString, Size, Style, SubscriberSet, Subscription, Surface, TaffyLayoutEngine, + Task, Underline, UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions, + SUBPIXEL_VARIANTS, }; use anyhow::{anyhow, Context as _, Result}; use collections::FxHashMap; @@ -85,7 +87,7 @@ impl DispatchPhase { } type AnyObserver = Box bool + 'static>; -type AnyMouseListener = Box; +type AnyMouseListener = ArenaRef; type AnyWindowFocusListener = Box bool + 'static>; struct FocusEvent { @@ -268,9 +270,9 @@ pub(crate) struct ElementStateBox { type_name: &'static str, } -// #[derive(Default)] pub(crate) struct Frame { focus: Option, + arena: Arena, pub(crate) element_states: FxHashMap, mouse_listeners: FxHashMap>, pub(crate) dispatch_tree: DispatchTree, @@ -285,6 +287,7 @@ impl Frame { fn new(dispatch_tree: DispatchTree) -> Self { Frame { focus: None, + arena: Arena::default(), element_states: FxHashMap::default(), mouse_listeners: FxHashMap::default(), dispatch_tree, @@ -299,6 +302,7 @@ impl Frame { fn clear(&mut self) { self.element_states.clear(); self.mouse_listeners.values_mut().for_each(Vec::clear); + self.arena.clear(); self.dispatch_tree.clear(); self.depth_map.clear(); } @@ -818,25 +822,23 @@ impl<'a> WindowContext<'a> { /// Register a mouse event listener on the window for the next frame. The type of event /// is determined by the first parameter of the given listener. When the next frame is rendered /// the listener will be cleared. - /// - /// This is a fairly low-level method, so prefer using event handlers on elements unless you have - /// a specific need to register a global listener. pub fn on_mouse_event( &mut self, mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { let order = self.window.next_frame.z_index_stack.clone(); + let handler = self.window.next_frame.arena.alloc( + move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { + handler(event.downcast_ref().unwrap(), phase, cx) + }, + ); + let handler = unsafe { handler.map(|handler| handler as _) }; self.window .next_frame .mouse_listeners .entry(TypeId::of::()) .or_default() - .push(( - order, - Box::new(move |event: &dyn Any, phase, cx| { - handler(event.downcast_ref().unwrap(), phase, cx) - }), - )) + .push((order, handler)) } /// Register a key event listener on the window for the next frame. The type of event @@ -847,16 +849,17 @@ impl<'a> WindowContext<'a> { /// a specific need to register a global listener. pub fn on_key_event( &mut self, - handler: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, + listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { - self.window - .next_frame - .dispatch_tree - .on_key_event(Rc::new(move |event, phase, cx| { + let listener = self.window.next_frame.arena.alloc( + move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { if let Some(event) = event.downcast_ref::() { - handler(event, phase, cx) + listener(event, phase, cx) } - })); + }, + ); + let listener = unsafe { listener.map(|handler| handler as _) }; + self.window.next_frame.dispatch_tree.on_key_event(listener); } /// Register an action listener on the window for the next frame. The type of action @@ -868,12 +871,14 @@ impl<'a> WindowContext<'a> { pub fn on_action( &mut self, action_type: TypeId, - handler: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static, + listener: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static, ) { - self.window.next_frame.dispatch_tree.on_action( - action_type, - Rc::new(move |action, phase, cx| handler(action, phase, cx)), - ); + let listener = self.window.next_frame.arena.alloc(listener); + let listener = unsafe { listener.map(|handler| handler as _) }; + self.window + .next_frame + .dispatch_tree + .on_action(action_type, listener); } pub fn is_action_available(&self, action: &dyn Action) -> bool { @@ -1274,10 +1279,16 @@ impl<'a> WindowContext<'a> { cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| { for (action_type, action_listeners) in &cx.app.global_action_listeners { for action_listener in action_listeners.iter().cloned() { - cx.window.next_frame.dispatch_tree.on_action( - *action_type, - Rc::new(move |action, phase, cx| action_listener(action, phase, cx)), - ) + let listener = cx.window.next_frame.arena.alloc( + move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { + action_listener(action, phase, cx) + }, + ); + let listener = unsafe { listener.map(|listener| listener as _) }; + cx.window + .next_frame + .dispatch_tree + .on_action(*action_type, listener) } } @@ -1460,6 +1471,7 @@ impl<'a> WindowContext<'a> { // Capture phase, events bubble from back to front. Handlers for this phase are used for // special purposes, such as detecting events outside of a given Bounds. for (_, handler) in &mut handlers { + let handler = unsafe { handler.get_mut() }; handler(event, DispatchPhase::Capture, self); if !self.app.propagate_event { break; @@ -1469,6 +1481,7 @@ impl<'a> WindowContext<'a> { // Bubble phase, where most normal handlers do their work. if self.app.propagate_event { for (_, handler) in handlers.iter_mut().rev() { + let handler = unsafe { handler.get_mut() }; handler(event, DispatchPhase::Bubble, self); if !self.app.propagate_event { break; @@ -1518,7 +1531,8 @@ impl<'a> WindowContext<'a> { context_stack.push(context); } - for key_listener in node.key_listeners.clone() { + for mut key_listener in node.key_listeners.clone() { + let key_listener = unsafe { key_listener.get_mut() }; key_listener(event, DispatchPhase::Capture, self); if !self.propagate_event { return; @@ -1530,7 +1544,8 @@ impl<'a> WindowContext<'a> { for node_id in dispatch_path.iter().rev() { // Handle low level key events let node = self.window.rendered_frame.dispatch_tree.node(*node_id); - for key_listener in node.key_listeners.clone() { + for mut key_listener in node.key_listeners.clone() { + let key_listener = unsafe { key_listener.get_mut() }; key_listener(event, DispatchPhase::Bubble, self); if !self.propagate_event { return; @@ -1582,11 +1597,12 @@ impl<'a> WindowContext<'a> { let node = self.window.rendered_frame.dispatch_tree.node(*node_id); for DispatchActionListener { action_type, - listener, + mut listener, } in node.action_listeners.clone() { let any_action = action.as_any(); if action_type == any_action.type_id() { + let listener = unsafe { listener.get_mut() }; listener(any_action, DispatchPhase::Capture, self); if !self.propagate_event { return; @@ -1599,12 +1615,13 @@ impl<'a> WindowContext<'a> { let node = self.window.rendered_frame.dispatch_tree.node(*node_id); for DispatchActionListener { action_type, - listener, + mut listener, } in node.action_listeners.clone() { let any_action = action.as_any(); if action_type == any_action.type_id() { self.propagate_event = false; // Actions stop propagation by default during the bubble phase + let listener = unsafe { listener.get_mut() }; listener(any_action, DispatchPhase::Bubble, self); if !self.propagate_event { return; @@ -2593,13 +2610,13 @@ impl<'a, V: 'static> ViewContext<'a, V> { pub fn on_action( &mut self, action_type: TypeId, - handler: impl Fn(&mut V, &dyn Any, DispatchPhase, &mut ViewContext) + 'static, + listener: impl Fn(&mut V, &dyn Any, DispatchPhase, &mut ViewContext) + 'static, ) { let handle = self.view().clone(); self.window_cx .on_action(action_type, move |action, phase, cx| { handle.update(cx, |view, cx| { - handler(view, action, phase, cx); + listener(view, action, phase, cx); }) }); } From be73dd852d2bf1b709bffd971fa2e92d871727fc Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 15 Dec 2023 16:18:05 +0100 Subject: [PATCH 061/644] Move `Arena` to a thread-local and use it to allocate `AnyElement` --- crates/gpui2/src/arena.rs | 4 ++++ crates/gpui2/src/element.rs | 30 ++++++++++++++------------ crates/gpui2/src/window.rs | 43 +++++++++++++++++++++---------------- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index cf6b877ba3..0e01c392b7 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -76,6 +76,10 @@ impl ArenaRef { ArenaRef(NonNull::new_unchecked(u)) } + pub unsafe fn get(&self) -> &T { + self.0.as_ref() + } + pub unsafe fn get_mut(&mut self) -> &mut T { self.0.as_mut() } diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index b446c2fe86..dcb103b61e 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -1,6 +1,6 @@ use crate::{ - AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, ViewContext, - WindowContext, + arena::ArenaRef, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, + Size, ViewContext, WindowContext, FRAME_ARENA, }; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; @@ -405,7 +405,7 @@ where } } -pub struct AnyElement(Box); +pub struct AnyElement(ArenaRef); impl AnyElement { pub fn new(element: E) -> Self @@ -413,15 +413,18 @@ impl AnyElement { E: 'static + Element, E::State: Any, { - AnyElement(Box::new(Some(DrawableElement::new(element))) as Box) + let element = + FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(Some(DrawableElement::new(element)))); + let element = unsafe { element.map(|element| element as &mut dyn ElementObject) }; + AnyElement(element) } pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId { - self.0.layout(cx) + unsafe { self.0.get_mut() }.layout(cx) } pub fn paint(&mut self, cx: &mut WindowContext) { - self.0.paint(cx) + unsafe { self.0.get_mut() }.paint(cx) } /// Initializes this element and performs layout within the given available space to determine its size. @@ -430,7 +433,7 @@ impl AnyElement { available_space: Size, cx: &mut WindowContext, ) -> Size { - self.0.measure(available_space, cx) + unsafe { self.0.get_mut() }.measure(available_space, cx) } /// Initializes this element and performs layout in the available space, then paints it at the given origin. @@ -440,16 +443,11 @@ impl AnyElement { available_space: Size, cx: &mut WindowContext, ) { - self.0.draw(origin, available_space, cx) - } - - /// Converts this `AnyElement` into a trait object that can be stored and manipulated. - pub fn into_any(self) -> AnyElement { - AnyElement::new(self) + unsafe { self.0.get_mut() }.draw(origin, available_space, cx) } pub fn inner_id(&self) -> Option { - self.0.element_id() + unsafe { self.0.get() }.element_id() } } @@ -480,6 +478,10 @@ impl IntoElement for AnyElement { fn into_element(self) -> Self::Element { self } + + fn into_any_element(self) -> AnyElement { + self + } } /// The empty element, which renders nothing. diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 202489ef0e..74b67503d5 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -27,6 +27,7 @@ use smallvec::SmallVec; use std::{ any::{Any, TypeId}, borrow::{Borrow, BorrowMut, Cow}, + cell::RefCell, fmt::Debug, future::Future, hash::{Hash, Hasher}, @@ -97,6 +98,10 @@ struct FocusEvent { slotmap::new_key_type! { pub struct FocusId; } +thread_local! { + pub static FRAME_ARENA: RefCell = RefCell::new(Arena::default()); +} + impl FocusId { /// Obtains whether the element associated with this handle is currently focused. pub fn is_focused(&self, cx: &WindowContext) -> bool { @@ -272,7 +277,6 @@ pub(crate) struct ElementStateBox { pub(crate) struct Frame { focus: Option, - arena: Arena, pub(crate) element_states: FxHashMap, mouse_listeners: FxHashMap>, pub(crate) dispatch_tree: DispatchTree, @@ -287,7 +291,6 @@ impl Frame { fn new(dispatch_tree: DispatchTree) -> Self { Frame { focus: None, - arena: Arena::default(), element_states: FxHashMap::default(), mouse_listeners: FxHashMap::default(), dispatch_tree, @@ -302,7 +305,6 @@ impl Frame { fn clear(&mut self) { self.element_states.clear(); self.mouse_listeners.values_mut().for_each(Vec::clear); - self.arena.clear(); self.dispatch_tree.clear(); self.depth_map.clear(); } @@ -827,11 +829,13 @@ impl<'a> WindowContext<'a> { mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { let order = self.window.next_frame.z_index_stack.clone(); - let handler = self.window.next_frame.arena.alloc( - move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { - handler(event.downcast_ref().unwrap(), phase, cx) - }, - ); + let handler = FRAME_ARENA.with_borrow_mut(|arena| { + arena.alloc( + move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { + handler(event.downcast_ref().unwrap(), phase, cx) + }, + ) + }); let handler = unsafe { handler.map(|handler| handler as _) }; self.window .next_frame @@ -851,13 +855,13 @@ impl<'a> WindowContext<'a> { &mut self, listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = self.window.next_frame.arena.alloc( - move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { + let listener = FRAME_ARENA.with_borrow_mut(|arena| { + arena.alloc(move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { if let Some(event) = event.downcast_ref::() { listener(event, phase, cx) } - }, - ); + }) + }); let listener = unsafe { listener.map(|handler| handler as _) }; self.window.next_frame.dispatch_tree.on_key_event(listener); } @@ -873,7 +877,7 @@ impl<'a> WindowContext<'a> { action_type: TypeId, listener: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = self.window.next_frame.arena.alloc(listener); + let listener = FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(listener)); let listener = unsafe { listener.map(|handler| handler as _) }; self.window .next_frame @@ -1273,17 +1277,20 @@ impl<'a> WindowContext<'a> { self.window.platform_window.clear_input_handler(); self.window.layout_engine.as_mut().unwrap().clear(); self.window.next_frame.clear(); + FRAME_ARENA.with_borrow_mut(|arena| arena.clear()); let root_view = self.window.root_view.take().unwrap(); self.with_z_index(0, |cx| { cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| { for (action_type, action_listeners) in &cx.app.global_action_listeners { for action_listener in action_listeners.iter().cloned() { - let listener = cx.window.next_frame.arena.alloc( - move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { - action_listener(action, phase, cx) - }, - ); + let listener = FRAME_ARENA.with_borrow_mut(|arena| { + arena.alloc( + move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { + action_listener(action, phase, cx) + }, + ) + }); let listener = unsafe { listener.map(|listener| listener as _) }; cx.window .next_frame From 3d9e051b07d20ca5009da8d363dea7307dad1d05 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 10:25:07 -0500 Subject: [PATCH 062/644] Update storybook2.rs --- crates/storybook2/src/bin/storybook2.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/storybook2/src/bin/storybook2.rs b/crates/storybook2/src/bin/storybook2.rs index 43f91db1a4..b77bbcb066 100644 --- a/crates/storybook2/src/bin/storybook2.rs +++ b/crates/storybook2/src/bin/storybook2.rs @@ -11,6 +11,7 @@ use simplelog::SimpleLogger; use theme2::{ThemeRegistry, ThemeSettings}; use ui::prelude::*; +pub use indoc::indoc; use storybook2::assets::Assets; pub use storybook2::story_selector::*; // pub use crate::story_selector::{ComponentStory, StorySelector}; From f459fc5e27c5e905f6be516be134edeca1aa911c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 10:33:27 -0500 Subject: [PATCH 063/644] Fix import --- crates/storybook2/src/storybook2.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/storybook2/src/storybook2.rs b/crates/storybook2/src/storybook2.rs index 13d9a75e24..523e93cf52 100644 --- a/crates/storybook2/src/storybook2.rs +++ b/crates/storybook2/src/storybook2.rs @@ -17,10 +17,9 @@ use strum::IntoEnumIterator; use theme2::{ThemeRegistry, ThemeSettings}; use ui::prelude::*; -pub use indoc::indoc; -use storybook2::assets::Assets; use crate::assets::Assets; use crate::story_selector::{ComponentStory, StorySelector}; +pub use indoc::indoc; // gpui::actions! { // storybook, From 50a44dd8ba1d04bc9a69d9292b662e6d1e10d8e7 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 11:07:17 -0500 Subject: [PATCH 064/644] Improve tooltip with keybinding styling --- crates/ui2/src/components/tooltip.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ui2/src/components/tooltip.rs b/crates/ui2/src/components/tooltip.rs index 7c502ac5cb..0a8eb8d6be 100644 --- a/crates/ui2/src/components/tooltip.rs +++ b/crates/ui2/src/components/tooltip.rs @@ -78,13 +78,13 @@ impl Render for Tooltip { v_stack() .elevation_2(cx) .font(ui_font) - .text_ui_sm() + .text_ui() .text_color(cx.theme().colors().text) .py_1() .px_2() .child( h_stack() - .gap_2() + .gap_4() .child(self.title.clone()) .when_some(self.key_binding.clone(), |this, key_binding| { this.justify_between().child(key_binding) From 47eaf1abd88863767233df4a843219d65944d2a8 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 11:07:40 -0500 Subject: [PATCH 065/644] Remove red borders, improve left side padding --- crates/collab_ui2/src/collab_titlebar_item.rs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index b127708fa6..7ce3502c7d 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -74,12 +74,16 @@ impl Render for CollabTitlebarItem { // Set a non-scaling min-height here to ensure the titlebar is // always at least the height of the traffic lights. .min_h(px(32.)) - .when( - !matches!(cx.window_bounds(), WindowBounds::Fullscreen), - // Use pixels here instead of a rem-based size because the macOS traffic - // lights are a static size, and don't scale with the rest of the UI. - |s| s.pl(px(68.)), - ) + .pl_2() + .map(|this| { + if matches!(cx.window_bounds(), WindowBounds::Fullscreen) { + this.pl_2() + } else { + // Use pixels here instead of a rem-based size because the macOS traffic + // lights are a static size, and don't scale with the rest of the UI. + this.pl(px(72.)) + } + }) .bg(cx.theme().colors().title_bar_background) .on_click(|event, cx| { if event.up.click_count == 2 { @@ -325,8 +329,6 @@ impl CollabTitlebarItem { let name = util::truncate_and_trailoff(name, MAX_PROJECT_NAME_LENGTH); div() - .border() - .border_color(gpui::red()) .child( Button::new("project_name_trigger", name) .style(ButtonStyle::Subtle) @@ -365,10 +367,9 @@ impl CollabTitlebarItem { Some( div() - .border() - .border_color(gpui::red()) .child( Button::new("project_branch_trigger", branch_name) + .color(Color::Muted) .style(ButtonStyle::Subtle) .tooltip(move |cx| { Tooltip::with_meta( From d099d359488c9ffd890857c44dd986c052ca8d87 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 11:20:56 -0500 Subject: [PATCH 066/644] Reduce intensity of project panel icons --- crates/project_panel2/src/project_panel.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 2d18d2a6c7..d8b5c1551f 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -1389,7 +1389,9 @@ impl ProjectPanel { entry_id: *entry_id, }) }) - .drag_over::(|style| style.bg(cx.theme().colors().ghost_element_hover)) + .drag_over::(|style| { + style.bg(cx.theme().colors().drop_target_background) + }) .on_drop(cx.listener(move |this, dragged_id: &ProjectEntryId, cx| { this.move_entry(*dragged_id, entry_id, kind.is_file(), cx); })) @@ -1399,7 +1401,7 @@ impl ProjectPanel { .indent_step_size(px(settings.indent_size)) .selected(is_selected) .child(if let Some(icon) = &icon { - div().child(IconElement::from_path(icon.to_string())) + div().child(IconElement::from_path(icon.to_string()).color(Color::Muted)) } else { div() }) From 6345e6d4d2857a182d98875c24ea7daf4587b9ac Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 11:25:24 -0500 Subject: [PATCH 067/644] Add some right side padding in titlebar. --- crates/collab_ui2/src/collab_titlebar_item.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 7ce3502c7d..706749b28d 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -169,6 +169,7 @@ impl Render for CollabTitlebarItem { .child( h_stack() .gap_1() + .pr_1() .when_some(room, |this, room| { let room = room.read(cx); let is_shared = self.project.read(cx).is_shared(); From 6c10ff8548ccadd6749ab6b5680402942fed4187 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 11:56:03 -0500 Subject: [PATCH 068/644] Render the collab panel using a `gpui::list` --- crates/collab_ui2/src/collab_panel.rs | 287 ++++++++------------------ 1 file changed, 87 insertions(+), 200 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 4edf5ef35b..3a35c81286 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -175,12 +175,12 @@ use editor::Editor; use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt}; use fuzzy::{match_strings, StringMatchCandidate}; use gpui::{ - actions, canvas, div, fill, img, impl_actions, overlay, point, prelude::*, px, rems, + actions, canvas, div, fill, img, impl_actions, list, overlay, point, prelude::*, px, rems, serde_json, size, Action, AnyElement, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle, Focusable, FocusableView, Hsla, - InteractiveElement, IntoElement, Length, Model, MouseDownEvent, ParentElement, Pixels, Point, - PromptLevel, Quad, Render, RenderOnce, ScrollHandle, SharedString, Size, Stateful, Styled, - Subscription, Task, View, ViewContext, VisualContext, WeakView, + InteractiveElement, IntoElement, Length, ListState, Model, MouseDownEvent, ParentElement, + Pixels, Point, PromptLevel, Quad, Render, RenderOnce, ScrollHandle, SharedString, Size, + Stateful, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, }; use project::{Fs, Project}; use serde_derive::{Deserialize, Serialize}; @@ -303,6 +303,7 @@ pub struct CollabPanel { channel_clipboard: Option, pending_serialization: Task>, context_menu: Option<(View, Point, Subscription)>, + list_state: ListState, filter_editor: View, channel_name_editor: View, channel_editing_state: Option, @@ -398,7 +399,7 @@ enum ListEntry { impl CollabPanel { pub fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> View { cx.build_view(|cx| { - // let view_id = cx.view_id(); + let view = cx.view().clone(); let filter_editor = cx.build_view(|cx| { let mut editor = Editor::single_line(cx); @@ -445,136 +446,10 @@ impl CollabPanel { }) .detach(); - // let list_state = - // ListState::::new(0, Orientation::Top, 1000., move |this, ix, cx| { - // let theme = theme::current(cx).clone(); - // let is_selected = this.selection == Some(ix); - // let current_project_id = this.project.read(cx).remote_id(); - - // match &this.entries[ix] { - // ListEntry::Header(section) => { - // let is_collapsed = this.collapsed_sections.contains(section); - // this.render_header(*section, &theme, is_selected, is_collapsed, cx) - // } - // ListEntry::CallParticipant { - // user, - // peer_id, - // is_pending, - // } => Self::render_call_participant( - // user, - // *peer_id, - // this.user_store.clone(), - // *is_pending, - // is_selected, - // &theme, - // cx, - // ), - // ListEntry::ParticipantProject { - // project_id, - // worktree_root_names, - // host_user_id, - // is_last, - // } => Self::render_participant_project( - // *project_id, - // worktree_root_names, - // *host_user_id, - // Some(*project_id) == current_project_id, - // *is_last, - // is_selected, - // &theme, - // cx, - // ), - // ListEntry::ParticipantScreen { peer_id, is_last } => { - // Self::render_participant_screen( - // *peer_id, - // *is_last, - // is_selected, - // &theme.collab_panel, - // cx, - // ) - // } - // ListEntry::Channel { - // channel, - // depth, - // has_children, - // } => { - // let channel_row = this.render_channel( - // &*channel, - // *depth, - // &theme, - // is_selected, - // *has_children, - // ix, - // cx, - // ); - - // if is_selected && this.context_menu_on_selected { - // Stack::new() - // .with_child(channel_row) - // .with_child( - // ChildView::new(&this.context_menu, cx) - // .aligned() - // .bottom() - // .right(), - // ) - // .into_any() - // } else { - // return channel_row; - // } - // } - // ListEntry::ChannelNotes { channel_id } => this.render_channel_notes( - // *channel_id, - // &theme.collab_panel, - // is_selected, - // ix, - // cx, - // ), - // ListEntry::ChannelChat { channel_id } => this.render_channel_chat( - // *channel_id, - // &theme.collab_panel, - // is_selected, - // ix, - // cx, - // ), - // ListEntry::ChannelInvite(channel) => Self::render_channel_invite( - // channel.clone(), - // this.channel_store.clone(), - // &theme.collab_panel, - // is_selected, - // cx, - // ), - // ListEntry::IncomingRequest(user) => Self::render_contact_request( - // user.clone(), - // this.user_store.clone(), - // &theme.collab_panel, - // true, - // is_selected, - // cx, - // ), - // ListEntry::OutgoingRequest(user) => Self::render_contact_request( - // user.clone(), - // this.user_store.clone(), - // &theme.collab_panel, - // false, - // is_selected, - // cx, - // ), - // ListEntry::Contact { contact, calling } => Self::render_contact( - // contact, - // *calling, - // &this.project, - // &theme, - // is_selected, - // cx, - // ), - // ListEntry::ChannelEditor { depth } => { - // this.render_channel_editor(&theme, *depth, cx) - // } - // ListEntry::ContactPlaceholder => { - // this.render_contact_placeholder(&theme.collab_panel, is_selected, cx) - // } - // } - // }); + let list_state = + ListState::new(0, gpui::ListAlignment::Top, px(1000.), move |ix, cx| { + view.update(cx, |view, cx| view.render_list_entry(ix, cx)) + }); let mut this = Self { width: None, @@ -583,6 +458,7 @@ impl CollabPanel { fs: workspace.app_state().fs.clone(), pending_serialization: Task::ready(None), context_menu: None, + list_state, channel_name_editor, filter_editor, entries: Vec::default(), @@ -1084,6 +960,8 @@ impl CollabPanel { self.entries.push(ListEntry::ContactPlaceholder); } + self.list_state.reset(self.entries.len()); + if select_same_item { if let Some(prev_selected_entry) = prev_selected_entry { self.selection.take(); @@ -2158,77 +2036,86 @@ impl CollabPanel { ) } + fn render_list_entry( + &mut self, + // entry: &ListEntry, + ix: usize, + cx: &mut ViewContext, + ) -> AnyElement { + let entry = &self.entries[ix]; + + let is_selected = self.selection == Some(ix); + match entry { + ListEntry::Header(section) => { + let is_collapsed = self.collapsed_sections.contains(section); + self.render_header(*section, is_selected, is_collapsed, cx) + .into_any_element() + } + ListEntry::Contact { contact, calling } => self + .render_contact(contact, *calling, is_selected, cx) + .into_any_element(), + ListEntry::ContactPlaceholder => self + .render_contact_placeholder(is_selected, cx) + .into_any_element(), + ListEntry::IncomingRequest(user) => self + .render_contact_request(user, true, is_selected, cx) + .into_any_element(), + ListEntry::OutgoingRequest(user) => self + .render_contact_request(user, false, is_selected, cx) + .into_any_element(), + ListEntry::Channel { + channel, + depth, + has_children, + } => self + .render_channel(channel, *depth, *has_children, is_selected, ix, cx) + .into_any_element(), + ListEntry::ChannelEditor { depth } => { + self.render_channel_editor(*depth, cx).into_any_element() + } + ListEntry::CallParticipant { + user, + peer_id, + is_pending, + } => self + .render_call_participant(user, *peer_id, *is_pending, cx) + .into_any_element(), + ListEntry::ParticipantProject { + project_id, + worktree_root_names, + host_user_id, + is_last, + } => self + .render_participant_project( + *project_id, + &worktree_root_names, + *host_user_id, + *is_last, + cx, + ) + .into_any_element(), + ListEntry::ParticipantScreen { peer_id, is_last } => self + .render_participant_screen(*peer_id, *is_last, cx) + .into_any_element(), + ListEntry::ChannelNotes { channel_id } => self + .render_channel_notes(*channel_id, cx) + .into_any_element(), + ListEntry::ChannelChat { channel_id } => { + self.render_channel_chat(*channel_id, cx).into_any_element() + } + } + } + fn render_signed_in(&mut self, cx: &mut ViewContext) -> Div { v_stack() .size_full() .child( v_stack() .size_full() - .id("scroll") - .overflow_y_scroll() - .track_scroll(&self.scroll_handle) - .children(self.entries.iter().enumerate().map(|(ix, entry)| { - let is_selected = self.selection == Some(ix); - match entry { - ListEntry::Header(section) => { - let is_collapsed = self.collapsed_sections.contains(section); - self.render_header(*section, is_selected, is_collapsed, cx) - .into_any_element() - } - ListEntry::Contact { contact, calling } => self - .render_contact(contact, *calling, is_selected, cx) - .into_any_element(), - ListEntry::ContactPlaceholder => self - .render_contact_placeholder(is_selected, cx) - .into_any_element(), - ListEntry::IncomingRequest(user) => self - .render_contact_request(user, true, is_selected, cx) - .into_any_element(), - ListEntry::OutgoingRequest(user) => self - .render_contact_request(user, false, is_selected, cx) - .into_any_element(), - ListEntry::Channel { - channel, - depth, - has_children, - } => self - .render_channel(channel, *depth, *has_children, is_selected, ix, cx) - .into_any_element(), - ListEntry::ChannelEditor { depth } => { - self.render_channel_editor(*depth, cx).into_any_element() - } - ListEntry::CallParticipant { - user, - peer_id, - is_pending, - } => self - .render_call_participant(user, *peer_id, *is_pending, cx) - .into_any_element(), - ListEntry::ParticipantProject { - project_id, - worktree_root_names, - host_user_id, - is_last, - } => self - .render_participant_project( - *project_id, - &worktree_root_names, - *host_user_id, - *is_last, - cx, - ) - .into_any_element(), - ListEntry::ParticipantScreen { peer_id, is_last } => self - .render_participant_screen(*peer_id, *is_last, cx) - .into_any_element(), - ListEntry::ChannelNotes { channel_id } => self - .render_channel_notes(*channel_id, cx) - .into_any_element(), - ListEntry::ChannelChat { channel_id } => { - self.render_channel_chat(*channel_id, cx).into_any_element() - } - } - })), + // .id("scroll") + // .overflow_y_scroll() + // .track_scroll(&self.scroll_handle) + .child(list(self.list_state.clone()).full().into_any_element()), ) .child( div().p_2().child( From d13c1486dab44094ac29e47a4ff9e1cb74bedc9e Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 12:09:06 -0500 Subject: [PATCH 069/644] Update fold_indicator render --- crates/editor2/src/editor.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 664d1d7380..3dd703bcba 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -4260,11 +4260,7 @@ impl Editor { fold_data .map(|(fold_status, buffer_row, active)| { (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| { - let icon = match fold_status { - FoldStatus::Folded => ui::Icon::ChevronRight, - FoldStatus::Foldable => ui::Icon::ChevronDown, - }; - IconButton::new(ix as usize, icon) + IconButton::new(ix as usize, ui::Icon::ChevronDown) .on_click(cx.listener(move |editor, e, cx| match fold_status { FoldStatus::Folded => { editor.unfold_at(&UnfoldAt { buffer_row }, cx); @@ -4274,6 +4270,10 @@ impl Editor { } })) .icon_color(ui::Color::Muted) + .icon_size(ui::IconSize::Small) + .selected(fold_status == FoldStatus::Folded) + .selected_icon(ui::Icon::ChevronRight) + .size(ui::ButtonSize::None) }) }) .flatten() From b478a4c4d5676f1d7e07961d29f41e24cf5e7602 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 12:10:40 -0500 Subject: [PATCH 070/644] Perform scroll interactions through the `ListState` --- crates/collab_ui2/src/collab_panel.rs | 53 ++++++++++++++++----------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 3a35c81286..31b1ef0237 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -178,9 +178,10 @@ use gpui::{ actions, canvas, div, fill, img, impl_actions, list, overlay, point, prelude::*, px, rems, serde_json, size, Action, AnyElement, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter, FocusHandle, Focusable, FocusableView, Hsla, - InteractiveElement, IntoElement, Length, ListState, Model, MouseDownEvent, ParentElement, - Pixels, Point, PromptLevel, Quad, Render, RenderOnce, ScrollHandle, SharedString, Size, - Stateful, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, + InteractiveElement, IntoElement, Length, ListOffset, ListState, Model, MouseDownEvent, + ParentElement, Pixels, Point, PromptLevel, Quad, Render, RenderOnce, ScrollHandle, + SharedString, Size, Stateful, Styled, Subscription, Task, View, ViewContext, VisualContext, + WeakView, }; use project::{Fs, Project}; use serde_derive::{Deserialize, Serialize}; @@ -314,7 +315,6 @@ pub struct CollabPanel { client: Arc, project: Model, match_candidates: Vec, - scroll_handle: ScrollHandle, subscriptions: Vec, collapsed_sections: Vec
, collapsed_channels: Vec, @@ -469,7 +469,6 @@ impl CollabPanel { project: workspace.project().clone(), subscriptions: Vec::default(), match_candidates: Vec::default(), - scroll_handle: ScrollHandle::new(), collapsed_sections: vec![Section::Offline], collapsed_channels: Vec::default(), workspace: workspace.weak_handle(), @@ -585,6 +584,13 @@ impl CollabPanel { ); } + fn scroll_to_item(&mut self, ix: usize) { + self.list_state.scroll_to(ListOffset { + item_ix: ix, + offset_in_item: px(0.), + }) + } + fn update_entries(&mut self, select_same_item: bool, cx: &mut ViewContext) { let channel_store = self.channel_store.read(cx); let user_store = self.user_store.read(cx); @@ -968,7 +974,7 @@ impl CollabPanel { for (ix, entry) in self.entries.iter().enumerate() { if *entry == prev_selected_entry { self.selection = Some(ix); - self.scroll_handle.scroll_to_item(ix); + self.scroll_to_item(ix); break; } } @@ -979,16 +985,19 @@ impl CollabPanel { None } else { let ix = prev_selection.min(self.entries.len() - 1); - self.scroll_handle.scroll_to_item(ix); + self.scroll_to_item(ix); Some(ix) } }); } if scroll_to_top { - self.scroll_handle.scroll_to_item(0) + self.scroll_to_item(0) } else { - let (old_index, old_offset) = self.scroll_handle.logical_scroll_top(); + let ListOffset { + item_ix: old_index, + offset_in_item: old_offset, + } = self.list_state.logical_scroll_top(); // Attempt to maintain the same scroll position. if let Some(old_top_entry) = old_entries.get(old_index) { let (new_index, new_offset) = self @@ -1014,8 +1023,9 @@ impl CollabPanel { }) .unwrap_or_else(|| (old_index, old_offset)); - self.scroll_handle - .set_logical_scroll_top(new_index, new_offset); + // TODO: How to handle this with `list`? + // self.scroll_handle + // .set_logical_scroll_top(new_index, new_offset); } } @@ -1506,7 +1516,7 @@ impl CollabPanel { } if let Some(ix) = self.selection { - self.scroll_handle.scroll_to_item(ix) + self.scroll_to_item(ix) } cx.notify(); } @@ -1518,7 +1528,7 @@ impl CollabPanel { } if let Some(ix) = self.selection { - self.scroll_handle.scroll_to_item(ix) + self.scroll_to_item(ix) } cx.notify(); } @@ -1841,14 +1851,15 @@ impl CollabPanel { let Some(channel) = self.selected_channel() else { return; }; - let Some(bounds) = self - .selection - .and_then(|ix| self.scroll_handle.bounds_for_item(ix)) - else { - return; - }; - - self.deploy_channel_context_menu(bounds.center(), channel.id, self.selection.unwrap(), cx); + // TODO: How to handle now that we're using `list`? + // let Some(bounds) = self + // .selection + // .and_then(|ix| self.scroll_handle.bounds_for_item(ix)) + // else { + // return; + // }; + // + // self.deploy_channel_context_menu(bounds.center(), channel.id, self.selection.unwrap(), cx); cx.stop_propagation(); } From 83525bf142eebf5af1f69a4a02946475d5796090 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 12:22:33 -0500 Subject: [PATCH 071/644] Revert change to single line editor height --- crates/editor2/src/editor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 3dd703bcba..fc03150fb6 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -9303,7 +9303,7 @@ impl Render for Editor { font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, - line_height: relative(1.).into(), + line_height: relative(settings.buffer_line_height.value()), background_color: None, underline: None, white_space: WhiteSpace::Normal, From 4cb0f60779d5deb53ff782ea929e1b0b16d123e4 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 12:29:33 -0500 Subject: [PATCH 072/644] Update size of code action indicator and show when active --- crates/editor2/src/editor.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index fc03150fb6..e1e4c7e0ad 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -4228,16 +4228,18 @@ impl Editor { ) -> Option { if self.available_code_actions.is_some() { Some( - IconButton::new("code_actions_indicator", ui::Icon::Bolt).on_click(cx.listener( - |editor, e, cx| { + IconButton::new("code_actions_indicator", ui::Icon::Bolt) + .icon_size(IconSize::Small) + .icon_color(Color::Muted) + .selected(is_active) + .on_click(cx.listener(|editor, e, cx| { editor.toggle_code_actions( &ToggleCodeActions { deployed_from_indicator: true, }, cx, ); - }, - )), + })), ) } else { None From 0a57171066400c64aa282d9350a80220e5cf485e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 15 Dec 2023 18:30:32 +0100 Subject: [PATCH 073/644] Use a safe API for Arena --- crates/gpui2/src/arena.rs | 150 ++++++++++++++++++++++-------------- crates/gpui2/src/element.rs | 12 +-- crates/gpui2/src/window.rs | 70 ++++++++--------- 3 files changed, 134 insertions(+), 98 deletions(-) diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index 0e01c392b7..a362c720a2 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -1,40 +1,49 @@ use std::{ alloc, + cell::Cell, + ops::{Deref, DerefMut}, ptr::{self, NonNull}, + rc::Rc, }; -pub struct Arena { - start: NonNull, - offset: usize, - elements: Vec, -} - -impl Default for Arena { - fn default() -> Self { - unsafe { - let layout = alloc::Layout::from_size_align(16 * 1024 * 1024, 1).unwrap(); - let ptr = alloc::alloc(layout); - Self { - start: NonNull::new_unchecked(ptr), - offset: 0, - elements: Vec::new(), - } - } - } -} - struct ArenaElement { value: NonNull, drop: unsafe fn(NonNull), } +impl Drop for ArenaElement { + fn drop(&mut self) { + unsafe { + (self.drop)(self.value); + } + } +} + +pub struct Arena { + start: NonNull, + offset: usize, + elements: Vec, + valid: Rc>, +} + impl Arena { - pub fn clear(&mut self) { - for element in self.elements.drain(..) { - unsafe { - (element.drop)(element.value); + pub fn new(size_in_bytes: usize) -> Self { + unsafe { + let layout = alloc::Layout::from_size_align(size_in_bytes, 1).unwrap(); + let ptr = alloc::alloc(layout); + Self { + start: NonNull::new_unchecked(ptr), + offset: 0, + elements: Vec::new(), + valid: Rc::new(Cell::new(true)), } } + } + + pub fn clear(&mut self) { + self.valid.set(false); + self.valid = Rc::new(Cell::new(true)); + self.elements.clear(); self.offset = 0; } @@ -46,42 +55,71 @@ impl Arena { unsafe { let layout = alloc::Layout::for_value(&value).pad_to_align(); - let value_ptr = self.start.as_ptr().add(self.offset).cast::(); - ptr::write(value_ptr, value); + let ptr = NonNull::new_unchecked(self.start.as_ptr().add(self.offset).cast::()); + ptr::write(ptr.as_ptr(), value); - let value = NonNull::new_unchecked(value_ptr); self.elements.push(ArenaElement { - value: value.cast(), + value: ptr.cast(), drop: drop::, }); self.offset += layout.size(); - ArenaRef(value) + ArenaRef { + ptr, + valid: self.valid.clone(), + } } } } -pub struct ArenaRef(NonNull); +impl Drop for Arena { + fn drop(&mut self) { + self.clear(); + } +} -impl Copy for ArenaRef {} +pub struct ArenaRef { + ptr: NonNull, + valid: Rc>, +} impl Clone for ArenaRef { fn clone(&self) -> Self { - Self(self.0) + Self { + ptr: self.ptr, + valid: self.valid.clone(), + } } } impl ArenaRef { - pub unsafe fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef { - let u = f(self.get_mut()); - ArenaRef(NonNull::new_unchecked(u)) + pub fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef { + ArenaRef { + ptr: unsafe { NonNull::new_unchecked(f(&mut *self)) }, + valid: self.valid, + } } - pub unsafe fn get(&self) -> &T { - self.0.as_ref() + fn validate(&self) { + assert!( + self.valid.get(), + "attempted to dereference an ArenaRef after its Arena was cleared" + ); } +} - pub unsafe fn get_mut(&mut self) -> &mut T { - self.0.as_mut() +impl Deref for ArenaRef { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.validate(); + unsafe { self.ptr.as_ref() } + } +} + +impl DerefMut for ArenaRef { + fn deref_mut(&mut self) -> &mut Self::Target { + self.validate(); + unsafe { self.ptr.as_mut() } } } @@ -93,25 +131,25 @@ mod tests { #[test] fn test_arena() { - let mut arena = Arena::default(); - let mut a = arena.alloc(1u64); - let mut b = arena.alloc(2u32); - let mut c = arena.alloc(3u16); - let mut d = arena.alloc(4u8); - assert_eq!(unsafe { *a.get_mut() }, 1); - assert_eq!(unsafe { *b.get_mut() }, 2); - assert_eq!(unsafe { *c.get_mut() }, 3); - assert_eq!(unsafe { *d.get_mut() }, 4); + let mut arena = Arena::new(1024); + let a = arena.alloc(1u64); + let b = arena.alloc(2u32); + let c = arena.alloc(3u16); + let d = arena.alloc(4u8); + assert_eq!(*a, 1); + assert_eq!(*b, 2); + assert_eq!(*c, 3); + assert_eq!(*d, 4); arena.clear(); - let mut a = arena.alloc(5u64); - let mut b = arena.alloc(6u32); - let mut c = arena.alloc(7u16); - let mut d = arena.alloc(8u8); - assert_eq!(unsafe { *a.get_mut() }, 5); - assert_eq!(unsafe { *b.get_mut() }, 6); - assert_eq!(unsafe { *c.get_mut() }, 7); - assert_eq!(unsafe { *d.get_mut() }, 8); + let a = arena.alloc(5u64); + let b = arena.alloc(6u32); + let c = arena.alloc(7u16); + let d = arena.alloc(8u8); + assert_eq!(*a, 5); + assert_eq!(*b, 6); + assert_eq!(*c, 7); + assert_eq!(*d, 8); // Ensure drop gets called. let dropped = Rc::new(Cell::new(false)); diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index dcb103b61e..d54d1c245d 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -415,16 +415,16 @@ impl AnyElement { { let element = FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(Some(DrawableElement::new(element)))); - let element = unsafe { element.map(|element| element as &mut dyn ElementObject) }; + let element = element.map(|element| element as &mut dyn ElementObject); AnyElement(element) } pub fn layout(&mut self, cx: &mut WindowContext) -> LayoutId { - unsafe { self.0.get_mut() }.layout(cx) + self.0.layout(cx) } pub fn paint(&mut self, cx: &mut WindowContext) { - unsafe { self.0.get_mut() }.paint(cx) + self.0.paint(cx) } /// Initializes this element and performs layout within the given available space to determine its size. @@ -433,7 +433,7 @@ impl AnyElement { available_space: Size, cx: &mut WindowContext, ) -> Size { - unsafe { self.0.get_mut() }.measure(available_space, cx) + self.0.measure(available_space, cx) } /// Initializes this element and performs layout in the available space, then paints it at the given origin. @@ -443,11 +443,11 @@ impl AnyElement { available_space: Size, cx: &mut WindowContext, ) { - unsafe { self.0.get_mut() }.draw(origin, available_space, cx) + self.0.draw(origin, available_space, cx) } pub fn inner_id(&self) -> Option { - unsafe { self.0.get() }.element_id() + self.0.element_id() } } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 74b67503d5..76fa36c68b 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -99,7 +99,7 @@ struct FocusEvent { slotmap::new_key_type! { pub struct FocusId; } thread_local! { - pub static FRAME_ARENA: RefCell = RefCell::new(Arena::default()); + pub static FRAME_ARENA: RefCell = RefCell::new(Arena::new(16 * 1024 * 1024)); } impl FocusId { @@ -829,14 +829,15 @@ impl<'a> WindowContext<'a> { mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { let order = self.window.next_frame.z_index_stack.clone(); - let handler = FRAME_ARENA.with_borrow_mut(|arena| { - arena.alloc( - move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { - handler(event.downcast_ref().unwrap(), phase, cx) - }, - ) - }); - let handler = unsafe { handler.map(|handler| handler as _) }; + let handler = FRAME_ARENA + .with_borrow_mut(|arena| { + arena.alloc( + move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { + handler(event.downcast_ref().unwrap(), phase, cx) + }, + ) + }) + .map(|handler| handler as _); self.window .next_frame .mouse_listeners @@ -855,14 +856,15 @@ impl<'a> WindowContext<'a> { &mut self, listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = FRAME_ARENA.with_borrow_mut(|arena| { - arena.alloc(move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { - if let Some(event) = event.downcast_ref::() { - listener(event, phase, cx) - } + let listener = FRAME_ARENA + .with_borrow_mut(|arena| { + arena.alloc(move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { + if let Some(event) = event.downcast_ref::() { + listener(event, phase, cx) + } + }) }) - }); - let listener = unsafe { listener.map(|handler| handler as _) }; + .map(|handler| handler as _); self.window.next_frame.dispatch_tree.on_key_event(listener); } @@ -877,8 +879,9 @@ impl<'a> WindowContext<'a> { action_type: TypeId, listener: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(listener)); - let listener = unsafe { listener.map(|handler| handler as _) }; + let listener = FRAME_ARENA + .with_borrow_mut(|arena| arena.alloc(listener)) + .map(|handler| handler as _); self.window .next_frame .dispatch_tree @@ -1284,14 +1287,15 @@ impl<'a> WindowContext<'a> { cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| { for (action_type, action_listeners) in &cx.app.global_action_listeners { for action_listener in action_listeners.iter().cloned() { - let listener = FRAME_ARENA.with_borrow_mut(|arena| { - arena.alloc( - move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { - action_listener(action, phase, cx) - }, - ) - }); - let listener = unsafe { listener.map(|listener| listener as _) }; + let listener = FRAME_ARENA + .with_borrow_mut(|arena| { + arena.alloc( + move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { + action_listener(action, phase, cx) + }, + ) + }) + .map(|listener| listener as _); cx.window .next_frame .dispatch_tree @@ -1478,7 +1482,6 @@ impl<'a> WindowContext<'a> { // Capture phase, events bubble from back to front. Handlers for this phase are used for // special purposes, such as detecting events outside of a given Bounds. for (_, handler) in &mut handlers { - let handler = unsafe { handler.get_mut() }; handler(event, DispatchPhase::Capture, self); if !self.app.propagate_event { break; @@ -1488,7 +1491,6 @@ impl<'a> WindowContext<'a> { // Bubble phase, where most normal handlers do their work. if self.app.propagate_event { for (_, handler) in handlers.iter_mut().rev() { - let handler = unsafe { handler.get_mut() }; handler(event, DispatchPhase::Bubble, self); if !self.app.propagate_event { break; @@ -1538,8 +1540,7 @@ impl<'a> WindowContext<'a> { context_stack.push(context); } - for mut key_listener in node.key_listeners.clone() { - let key_listener = unsafe { key_listener.get_mut() }; + for key_listener in node.key_listeners.clone() { key_listener(event, DispatchPhase::Capture, self); if !self.propagate_event { return; @@ -1551,8 +1552,7 @@ impl<'a> WindowContext<'a> { for node_id in dispatch_path.iter().rev() { // Handle low level key events let node = self.window.rendered_frame.dispatch_tree.node(*node_id); - for mut key_listener in node.key_listeners.clone() { - let key_listener = unsafe { key_listener.get_mut() }; + for key_listener in node.key_listeners.clone() { key_listener(event, DispatchPhase::Bubble, self); if !self.propagate_event { return; @@ -1604,12 +1604,11 @@ impl<'a> WindowContext<'a> { let node = self.window.rendered_frame.dispatch_tree.node(*node_id); for DispatchActionListener { action_type, - mut listener, + listener, } in node.action_listeners.clone() { let any_action = action.as_any(); if action_type == any_action.type_id() { - let listener = unsafe { listener.get_mut() }; listener(any_action, DispatchPhase::Capture, self); if !self.propagate_event { return; @@ -1622,13 +1621,12 @@ impl<'a> WindowContext<'a> { let node = self.window.rendered_frame.dispatch_tree.node(*node_id); for DispatchActionListener { action_type, - mut listener, + listener, } in node.action_listeners.clone() { let any_action = action.as_any(); if action_type == any_action.type_id() { self.propagate_event = false; // Actions stop propagation by default during the bubble phase - let listener = unsafe { listener.get_mut() }; listener(any_action, DispatchPhase::Bubble, self); if !self.propagate_event { return; From a2852e36ce8df6d1bc86a8cc2a59b31af60b2e22 Mon Sep 17 00:00:00 2001 From: Mikayla Date: Fri, 15 Dec 2023 10:07:10 -0800 Subject: [PATCH 074/644] Fix pane resizing --- crates/workspace2/src/pane_group.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index 966e2c6341..d35c138d5c 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -693,7 +693,8 @@ mod element { use gpui::{ px, relative, Along, AnyElement, Axis, Bounds, CursorStyle, Element, IntoElement, - MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Style, WindowContext, + MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Size, Style, + WindowContext, }; use parking_lot::Mutex; use smallvec::SmallVec; @@ -736,7 +737,8 @@ mod element { e: &MouseMoveEvent, ix: usize, axis: Axis, - axis_bounds: Bounds, + child_start: Point, + container_size: Size, cx: &mut WindowContext, ) { let min_size = match axis { @@ -747,7 +749,7 @@ mod element { debug_assert!(flex_values_in_bounds(flexes.as_slice())); let size = move |ix, flexes: &[f32]| { - axis_bounds.size.along(axis) * (flexes[ix] / flexes.len() as f32) + container_size.along(axis) * (flexes[ix] / flexes.len() as f32) }; // Don't allow resizing to less than the minimum size, if elements are already too small @@ -756,10 +758,10 @@ mod element { } let mut proposed_current_pixel_change = - (e.position - axis_bounds.origin).along(axis) - size(ix, flexes.as_slice()); + (e.position - child_start).along(axis) - size(ix, flexes.as_slice()); let flex_changes = |pixel_dx, target_ix, next: isize, flexes: &[f32]| { - let flex_change = pixel_dx / axis_bounds.size.along(axis); + let flex_change = pixel_dx / container_size.along(axis); let current_target_flex = flexes[target_ix] + flex_change; let next_target_flex = flexes[(target_ix as isize + next) as usize] - flex_change; (current_target_flex, next_target_flex) @@ -854,7 +856,15 @@ mod element { cx.on_mouse_event(move |e: &MouseMoveEvent, phase, cx| { let dragged_handle = dragged_handle.borrow(); if phase.bubble() && *dragged_handle == Some(ix) { - Self::compute_resize(&flexes, e, ix, axis, axis_bounds, cx) + Self::compute_resize( + &flexes, + e, + ix, + axis, + pane_bounds.origin, + axis_bounds.size, + cx, + ) } }); }); From 47fc03ab98536b3ba2cbd75cf169ff516a5eb07f Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 13:24:30 -0500 Subject: [PATCH 075/644] Fix positioning of the inline context menu Added a new `bounds_for_item` for `ListState`. Co-authored-by: Max --- crates/collab_ui2/src/collab_panel.rs | 55 ++++++++++----------------- crates/gpui2/src/elements/list.rs | 46 ++++++++++++++++++---- 2 files changed, 60 insertions(+), 41 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 31b1ef0237..6f21649dd6 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -165,7 +165,7 @@ struct ChannelMoveClipboard { const COLLABORATION_PANEL_KEY: &'static str = "CollaborationPanel"; -use std::{iter::once, mem, sync::Arc}; +use std::{mem, sync::Arc}; use call::ActiveCall; use channel::{Channel, ChannelEvent, ChannelId, ChannelStore}; @@ -175,12 +175,11 @@ use editor::Editor; use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt}; use fuzzy::{match_strings, StringMatchCandidate}; use gpui::{ - actions, canvas, div, fill, img, impl_actions, list, overlay, point, prelude::*, px, rems, - serde_json, size, Action, AnyElement, AppContext, AsyncWindowContext, Bounds, ClipboardItem, - DismissEvent, Div, EventEmitter, FocusHandle, Focusable, FocusableView, Hsla, - InteractiveElement, IntoElement, Length, ListOffset, ListState, Model, MouseDownEvent, - ParentElement, Pixels, Point, PromptLevel, Quad, Render, RenderOnce, ScrollHandle, - SharedString, Size, Stateful, Styled, Subscription, Task, View, ViewContext, VisualContext, + actions, canvas, div, fill, impl_actions, list, overlay, point, prelude::*, px, serde_json, + AnyElement, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, + EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement, IntoElement, + ListOffset, ListState, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, + Render, RenderOnce, SharedString, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, }; use project::{Fs, Project}; @@ -189,7 +188,7 @@ use settings::{Settings, SettingsStore}; use ui::prelude::*; use ui::{ h_stack, v_stack, Avatar, Button, Color, ContextMenu, Icon, IconButton, IconElement, IconSize, - Label, List, ListHeader, ListItem, Tooltip, + Label, ListHeader, ListItem, Tooltip, }; use util::{maybe, ResultExt, TryFutureExt}; use workspace::{ @@ -1023,9 +1022,10 @@ impl CollabPanel { }) .unwrap_or_else(|| (old_index, old_offset)); - // TODO: How to handle this with `list`? - // self.scroll_handle - // .set_logical_scroll_top(new_index, new_offset); + self.list_state.scroll_to(ListOffset { + item_ix: new_index, + offset_in_item: new_offset, + }); } } @@ -1851,15 +1851,14 @@ impl CollabPanel { let Some(channel) = self.selected_channel() else { return; }; - // TODO: How to handle now that we're using `list`? - // let Some(bounds) = self - // .selection - // .and_then(|ix| self.scroll_handle.bounds_for_item(ix)) - // else { - // return; - // }; - // - // self.deploy_channel_context_menu(bounds.center(), channel.id, self.selection.unwrap(), cx); + let Some(bounds) = self + .selection + .and_then(|ix| self.list_state.bounds_for_item(ix)) + else { + return; + }; + + self.deploy_channel_context_menu(bounds.center(), channel.id, self.selection.unwrap(), cx); cx.stop_propagation(); } @@ -2047,12 +2046,7 @@ impl CollabPanel { ) } - fn render_list_entry( - &mut self, - // entry: &ListEntry, - ix: usize, - cx: &mut ViewContext, - ) -> AnyElement { + fn render_list_entry(&mut self, ix: usize, cx: &mut ViewContext) -> AnyElement { let entry = &self.entries[ix]; let is_selected = self.selection == Some(ix); @@ -2120,14 +2114,7 @@ impl CollabPanel { fn render_signed_in(&mut self, cx: &mut ViewContext) -> Div { v_stack() .size_full() - .child( - v_stack() - .size_full() - // .id("scroll") - // .overflow_y_scroll() - // .track_scroll(&self.scroll_handle) - .child(list(self.list_state.clone()).full().into_any_element()), - ) + .child(list(self.list_state.clone()).full()) .child( div().p_2().child( div() diff --git a/crates/gpui2/src/elements/list.rs b/crates/gpui2/src/elements/list.rs index 6818c5c7a2..108703370c 100644 --- a/crates/gpui2/src/elements/list.rs +++ b/crates/gpui2/src/elements/list.rs @@ -1,6 +1,7 @@ use crate::{ - px, AnyElement, AvailableSpace, BorrowAppContext, DispatchPhase, Element, IntoElement, Pixels, - Point, ScrollWheelEvent, Size, Style, StyleRefinement, Styled, WindowContext, + point, px, AnyElement, AvailableSpace, BorrowAppContext, Bounds, DispatchPhase, Element, + IntoElement, Pixels, Point, ScrollWheelEvent, Size, Style, StyleRefinement, Styled, + WindowContext, }; use collections::VecDeque; use refineable::Refineable as _; @@ -23,7 +24,7 @@ pub struct List { pub struct ListState(Rc>); struct StateInner { - last_layout_width: Option, + last_layout_bounds: Option>, render_item: Box AnyElement>, items: SumTree, logical_scroll_top: Option, @@ -83,7 +84,7 @@ impl ListState { let mut items = SumTree::new(); items.extend((0..element_count).map(|_| ListItem::Unrendered), &()); Self(Rc::new(RefCell::new(StateInner { - last_layout_width: None, + last_layout_bounds: None, render_item: Box::new(render_item), items, logical_scroll_top: None, @@ -152,6 +153,35 @@ impl ListState { } state.logical_scroll_top = Some(scroll_top); } + + /// Get the bounds for the given item in window coordinates. + pub fn bounds_for_item(&self, ix: usize) -> Option> { + let state = &*self.0.borrow(); + let bounds = state.last_layout_bounds.unwrap_or_default(); + let scroll_top = state.logical_scroll_top.unwrap_or_default(); + + if ix < scroll_top.item_ix { + return None; + } + + let mut cursor = state.items.cursor::<(Count, Height)>(); + cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &()); + + let scroll_top = cursor.start().1 .0 + scroll_top.offset_in_item; + + cursor.seek_forward(&Count(ix), Bias::Right, &()); + if let Some(&ListItem::Rendered { height }) = cursor.item() { + let &(Count(count), Height(top)) = cursor.start(); + if count == ix { + let top = bounds.top() + top - scroll_top; + return Some(Bounds::from_corners( + point(bounds.left(), top), + point(bounds.right(), top + height), + )); + } + } + None + } } impl StateInner { @@ -234,7 +264,7 @@ impl std::fmt::Debug for ListItem { } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct ListOffset { pub item_ix: usize, pub offset_in_item: Pixels, @@ -265,7 +295,9 @@ impl Element for List { let state = &mut *self.state.0.borrow_mut(); // If the width of the list has changed, invalidate all cached item heights - if state.last_layout_width != Some(bounds.size.width) { + if state.last_layout_bounds.map_or(true, |last_bounds| { + last_bounds.size.width != bounds.size.width + }) { state.items = SumTree::from_iter( (0..state.items.summary().count).map(|_| ListItem::Unrendered), &(), @@ -392,7 +424,7 @@ impl Element for List { } state.items = new_items; - state.last_layout_width = Some(bounds.size.width); + state.last_layout_bounds = Some(bounds); let list_state = self.state.clone(); let height = bounds.size.height; From b4135dd2f1aa7f1da9daa3245f29d6b963ef0d6b Mon Sep 17 00:00:00 2001 From: Mikayla Date: Fri, 15 Dec 2023 10:26:41 -0800 Subject: [PATCH 076/644] Fix editor mouse event dispatch --- crates/editor2/src/editor.rs | 2 +- crates/editor2/src/element.rs | 110 ++++++++++++++++++---------------- 2 files changed, 59 insertions(+), 53 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 664d1d7380..c6d83ef24e 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -9758,7 +9758,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend .px_1p5() .child(HighlightedLabel::new(line.clone(), highlights.clone())) .child( - div().border().border_color(gpui::red()).child( + div().z_index(1).child( IconButton::new(copy_id.clone(), Icon::Copy) .icon_color(Color::Muted) .size(ButtonSize::Compact) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index a6d4bc20b1..a04af377b4 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2447,13 +2447,13 @@ impl EditorElement { let interactive_bounds = interactive_bounds.clone(); move |event: &ScrollWheelEvent, phase, cx| { - if phase != DispatchPhase::Bubble { - return; + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { + editor.update(cx, |editor, cx| { + Self::scroll(editor, event, &position_map, &interactive_bounds, cx) + }); } - - editor.update(cx, |editor, cx| { - Self::scroll(editor, event, &position_map, &interactive_bounds, cx) - }); } }); @@ -2461,48 +2461,54 @@ impl EditorElement { let position_map = layout.position_map.clone(); let editor = self.editor.clone(); let stacking_order = cx.stacking_order().clone(); + let interactive_bounds = interactive_bounds.clone(); move |event: &MouseDownEvent, phase, cx| { - if phase != DispatchPhase::Bubble { - return; + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { + match event.button { + MouseButton::Left => editor.update(cx, |editor, cx| { + Self::mouse_left_down( + editor, + event, + &position_map, + text_bounds, + gutter_bounds, + &stacking_order, + cx, + ); + }), + MouseButton::Right => editor.update(cx, |editor, cx| { + Self::mouse_right_down(editor, event, &position_map, text_bounds, cx); + }), + _ => {} + }; } + } + }); - match event.button { - MouseButton::Left => editor.update(cx, |editor, cx| { - Self::mouse_left_down( + cx.on_mouse_event({ + let position_map = layout.position_map.clone(); + let editor = self.editor.clone(); + let stacking_order = cx.stacking_order().clone(); + let interactive_bounds = interactive_bounds.clone(); + + move |event: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { + editor.update(cx, |editor, cx| { + Self::mouse_up( editor, event, &position_map, text_bounds, - gutter_bounds, &stacking_order, cx, - ); - }), - MouseButton::Right => editor.update(cx, |editor, cx| { - Self::mouse_right_down(editor, event, &position_map, text_bounds, cx); - }), - _ => {} - }; - } - }); - - cx.on_mouse_event({ - let position_map = layout.position_map.clone(); - let editor = self.editor.clone(); - let stacking_order = cx.stacking_order().clone(); - - move |event: &MouseUpEvent, phase, cx| { - editor.update(cx, |editor, cx| { - Self::mouse_up( - editor, - event, - &position_map, - text_bounds, - &stacking_order, - cx, - ) - }); + ) + }); + } } }); cx.on_mouse_event({ @@ -2511,21 +2517,21 @@ impl EditorElement { let stacking_order = cx.stacking_order().clone(); move |event: &MouseMoveEvent, phase, cx| { - if phase != DispatchPhase::Bubble { - return; + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { + editor.update(cx, |editor, cx| { + Self::mouse_moved( + editor, + event, + &position_map, + text_bounds, + gutter_bounds, + &stacking_order, + cx, + ) + }); } - - editor.update(cx, |editor, cx| { - Self::mouse_moved( - editor, - event, - &position_map, - text_bounds, - gutter_bounds, - &stacking_order, - cx, - ) - }); } }); } From a40f04b71fd72e3818d3b9f23c4e31c30c4d47b6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 13:50:51 -0500 Subject: [PATCH 077/644] Only scroll enough to reveal the next channel if it isn't visible Co-authored-by: Max --- crates/collab_ui2/src/collab_panel.rs | 5 +--- crates/gpui2/src/elements/list.rs | 33 +++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 6f21649dd6..1ca6101c54 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -584,10 +584,7 @@ impl CollabPanel { } fn scroll_to_item(&mut self, ix: usize) { - self.list_state.scroll_to(ListOffset { - item_ix: ix, - offset_in_item: px(0.), - }) + self.list_state.scroll_to_reveal_item(ix) } fn update_entries(&mut self, select_same_item: bool, cx: &mut ViewContext) { diff --git a/crates/gpui2/src/elements/list.rs b/crates/gpui2/src/elements/list.rs index 108703370c..415a3b7368 100644 --- a/crates/gpui2/src/elements/list.rs +++ b/crates/gpui2/src/elements/list.rs @@ -154,11 +154,40 @@ impl ListState { state.logical_scroll_top = Some(scroll_top); } + pub fn scroll_to_reveal_item(&self, ix: usize) { + let state = &mut *self.0.borrow_mut(); + let mut scroll_top = state.logical_scroll_top(); + let height = state + .last_layout_bounds + .map_or(px(0.), |bounds| bounds.size.height); + + if ix <= scroll_top.item_ix { + scroll_top.item_ix = ix; + scroll_top.offset_in_item = px(0.); + } else { + let mut cursor = state.items.cursor::(); + cursor.seek(&Count(ix + 1), Bias::Right, &()); + let bottom = cursor.start().height; + let goal_top = px(0.).max(bottom - height); + + cursor.seek(&Height(goal_top), Bias::Left, &()); + let start_ix = cursor.start().count; + let start_item_top = cursor.start().height; + + if start_ix >= scroll_top.item_ix { + scroll_top.item_ix = start_ix; + scroll_top.offset_in_item = goal_top - start_item_top; + } + } + + state.logical_scroll_top = Some(scroll_top); + } + /// Get the bounds for the given item in window coordinates. pub fn bounds_for_item(&self, ix: usize) -> Option> { let state = &*self.0.borrow(); let bounds = state.last_layout_bounds.unwrap_or_default(); - let scroll_top = state.logical_scroll_top.unwrap_or_default(); + let scroll_top = state.logical_scroll_top(); if ix < scroll_top.item_ix { return None; @@ -264,7 +293,7 @@ impl std::fmt::Debug for ListItem { } } -#[derive(Debug, Clone, Copy, Default)] +#[derive(Debug, Clone, Copy)] pub struct ListOffset { pub item_ix: usize, pub offset_in_item: Pixels, From d0dbf8e1e269ae46ae456cf2485b70011134b8b7 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 15 Dec 2023 11:59:06 -0700 Subject: [PATCH 078/644] Fix bug where vim commands were copied on each update_matches In zed1, the array of commands was recalculated on every update_matches, In zed2 it's cached before we change the focus. --- crates/command_palette2/src/command_palette.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 393fb16f81..04efe1df53 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -101,6 +101,7 @@ pub struct CommandInterceptResult { pub struct CommandPaletteDelegate { command_palette: WeakView, + all_commands: Vec, commands: Vec, matches: Vec, selected_ix: usize, @@ -135,6 +136,7 @@ impl CommandPaletteDelegate { ) -> Self { Self { command_palette, + all_commands: commands.clone(), matches: vec![], commands, selected_ix: 0, @@ -167,7 +169,7 @@ impl PickerDelegate for CommandPaletteDelegate { query: String, cx: &mut ViewContext>, ) -> gpui::Task<()> { - let mut commands = self.commands.clone(); + let mut commands = self.all_commands.clone(); cx.spawn(move |picker, mut cx| async move { cx.read_global::(|hit_counts, _| { From 541712790295a6950afbf610a44d755b4c9ae143 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 14:01:24 -0500 Subject: [PATCH 079/644] Fix channel drag and drop Also add the ability to unnest a channel by dragging it to the "Channels" header. This is currently not working due to a collab server issue. Co-authored-by: Max --- crates/collab_ui2/src/collab_panel.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 1ca6101c54..c2da29ba9f 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2225,14 +2225,14 @@ impl CollabPanel { .selected(is_selected), ) .when(section == Section::Channels, |el| { - el.drag_over::(|style| { + el.drag_over::(|style| { style.bg(cx.theme().colors().ghost_element_hover) }) .on_drop(cx.listener( - move |this, view: &View, cx| { + move |this, dragged_channel: &Channel, cx| { this.channel_store .update(cx, |channel_store, cx| { - channel_store.move_channel(view.read(cx).channel.id, None, cx) + channel_store.move_channel(dragged_channel.id, None, cx) }) .detach_and_log_err(cx) }, @@ -2451,15 +2451,15 @@ impl CollabPanel { width, }) }) - .drag_over::(|style| { + .drag_over::(|style| { style.bg(cx.theme().colors().ghost_element_hover) }) .on_drop( - cx.listener(move |this, view: &View, cx| { + cx.listener(move |this, dragged_channel: &Channel, cx| { this.channel_store .update(cx, |channel_store, cx| { channel_store.move_channel( - view.read(cx).channel.id, + dragged_channel.id, Some(channel_id), cx, ) From 5c060ceb1c2e3ae85503f89c57da34ac8e4446ad Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 14:03:49 -0500 Subject: [PATCH 080/644] Format code --- crates/collab_ui2/src/collab_panel.rs | 34 +++++++++------------------ 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index c2da29ba9f..ec723df25d 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2225,18 +2225,14 @@ impl CollabPanel { .selected(is_selected), ) .when(section == Section::Channels, |el| { - el.drag_over::(|style| { - style.bg(cx.theme().colors().ghost_element_hover) - }) - .on_drop(cx.listener( - move |this, dragged_channel: &Channel, cx| { + el.drag_over::(|style| style.bg(cx.theme().colors().ghost_element_hover)) + .on_drop(cx.listener(move |this, dragged_channel: &Channel, cx| { this.channel_store .update(cx, |channel_store, cx| { channel_store.move_channel(dragged_channel.id, None, cx) }) .detach_and_log_err(cx) - }, - )) + })) }); if section == Section::Offline { @@ -2451,22 +2447,14 @@ impl CollabPanel { width, }) }) - .drag_over::(|style| { - style.bg(cx.theme().colors().ghost_element_hover) - }) - .on_drop( - cx.listener(move |this, dragged_channel: &Channel, cx| { - this.channel_store - .update(cx, |channel_store, cx| { - channel_store.move_channel( - dragged_channel.id, - Some(channel_id), - cx, - ) - }) - .detach_and_log_err(cx) - }), - ) + .drag_over::(|style| style.bg(cx.theme().colors().ghost_element_hover)) + .on_drop(cx.listener(move |this, dragged_channel: &Channel, cx| { + this.channel_store + .update(cx, |channel_store, cx| { + channel_store.move_channel(dragged_channel.id, Some(channel_id), cx) + }) + .detach_and_log_err(cx) + })) .child( ListItem::new(channel_id as usize) // Offset the indent depth by one to give us room to show the disclosure. From 793381f4552378b5d8d65e8f73d8243acd372322 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 14 Dec 2023 17:41:29 -0800 Subject: [PATCH 081/644] Render zoomed item in the workspace --- crates/workspace2/src/workspace2.rs | 49 ++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index a789809537..f2482d034c 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -3556,6 +3556,8 @@ impl Render for Workspace { ) }; + let theme = cx.theme().clone(); + let colors = theme.colors(); cx.set_rem_size(ui_font_size); self.actions(div(), cx) @@ -3568,10 +3570,10 @@ impl Render for Workspace { .gap_0() .justify_start() .items_start() - .text_color(cx.theme().colors().text) - .bg(cx.theme().colors().background) + .text_color(colors.text) + .bg(colors.background) .border() - .border_color(cx.theme().colors().border) + .border_color(colors.border) .children(self.titlebar_item.clone()) .child( div() @@ -3584,7 +3586,7 @@ impl Render for Workspace { .overflow_hidden() .border_t() .border_b() - .border_color(cx.theme().colors().border) + .border_color(colors.border) .child( canvas(cx.listener(|workspace, bounds, _| { workspace.bounds = *bounds; @@ -3623,13 +3625,17 @@ impl Render for Workspace { .flex_row() .h_full() // Left Dock - .child( - div() - .flex() - .flex_none() - .overflow_hidden() - .child(self.left_dock.clone()), - ) + .children(if self.zoomed_position == Some(DockPosition::Left) { + None + } else { + Some( + div() + .flex() + .flex_none() + .overflow_hidden() + .child(self.left_dock.clone()), + ) + }) // Panes .child( div() @@ -3657,7 +3663,26 @@ impl Render for Workspace { .child(self.right_dock.clone()), ), ) - .children(self.render_notifications(cx)), + .children(self.render_notifications(cx)) + .children(self.zoomed.as_ref().and_then(|view| { + let zoomed_view = view.upgrade()?; + let div = div() + .z_index(1) + .absolute() + .overflow_hidden() + .border_color(colors.border) + .bg(colors.background) + .child(zoomed_view) + .inset_0() + .shadow_lg(); + + Some(match self.zoomed_position { + Some(DockPosition::Left) => div.right_2().border_r(), + Some(DockPosition::Right) => div.left_2().border_l(), + Some(DockPosition::Bottom) => div.top_2().border_t(), + None => div.top_2().bottom_2().left_2().right_2().border(), + }) + })), ) .child(self.status_bar.clone()) } From b1a61ca21e9fd4b2b615f9c61012d54b9895832b Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 14:44:29 -0500 Subject: [PATCH 082/644] Fix toolbar width (#3681) This PR fixes an issue with the toolbar width introduced in #3666. The lack of a flex container was making the toolbar contents not take up the full width, and thus not positions items correctly along its main axis. Release Notes: - N/A --- crates/workspace2/src/pane.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 11588212ef..65e7f2a106 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1897,19 +1897,14 @@ impl Render for Pane { .on_drag_move::(cx.listener(Self::handle_drag_move)) .map(|div| { if let Some(item) = self.active_item() { - div.flex_col() + div.v_flex() .child(self.toolbar.clone()) .child(item.to_any()) } else { - div.flex() - .flex_row() - .items_center() - .size_full() - .justify_center() - .child( - Label::new("Open a file or project to get started.") - .color(Color::Muted), - ) + div.h_flex().size_full().justify_center().child( + Label::new("Open a file or project to get started.") + .color(Color::Muted), + ) } }) .child( From a4c123bb1103d1953b6bbdee6ef001845069bee0 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Dec 2023 11:47:01 -0800 Subject: [PATCH 083/644] Fix logic for activating panel when re-docking it --- crates/workspace2/src/dock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index f76bb82177..e44471a871 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -317,7 +317,7 @@ impl Dock { new_dock.add_panel(panel.clone(), workspace.clone(), cx); if was_visible { new_dock.set_open(true, cx); - new_dock.activate_panel(this.panels_len() - 1, cx); + new_dock.activate_panel(new_dock.panels_len() - 1, cx); } }); } From 9a8225c8553e7d6208fd1a962fc182f5f3eb3c89 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Dec 2023 11:48:25 -0800 Subject: [PATCH 084/644] When a dock is zoomed, don't render it in its normal place --- crates/workspace2/src/workspace2.rs | 165 ++++------------------------ 1 file changed, 19 insertions(+), 146 deletions(-) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index f2482d034c..866762e7d5 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -3625,17 +3625,15 @@ impl Render for Workspace { .flex_row() .h_full() // Left Dock - .children(if self.zoomed_position == Some(DockPosition::Left) { - None - } else { - Some( + .children(self.zoomed_position.ne(&Some(DockPosition::Left)).then( + || { div() .flex() .flex_none() .overflow_hidden() - .child(self.left_dock.clone()), - ) - }) + .child(self.left_dock.clone()) + }, + )) // Panes .child( div() @@ -3652,16 +3650,22 @@ impl Render for Workspace { &self.app_state, cx, )) - .child(self.bottom_dock.clone()), + .children( + self.zoomed_position + .ne(&Some(DockPosition::Bottom)) + .then(|| self.bottom_dock.clone()), + ), ) // Right Dock - .child( - div() - .flex() - .flex_none() - .overflow_hidden() - .child(self.right_dock.clone()), - ), + .children(self.zoomed_position.ne(&Some(DockPosition::Right)).then( + || { + div() + .flex() + .flex_none() + .overflow_hidden() + .child(self.right_dock.clone()) + }, + )), ) .children(self.render_notifications(cx)) .children(self.zoomed.as_ref().and_then(|view| { @@ -3688,137 +3692,6 @@ impl Render for Workspace { } } -// impl View for Workspace { - -// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { -// let theme = theme::current(cx).clone(); -// Stack::new() -// .with_child( -// Flex::column() -// .with_child(self.render_titlebar(&theme, cx)) -// .with_child( -// Stack::new() -// .with_child({ -// let project = self.project.clone(); -// Flex::row() -// .with_children(self.render_dock(DockPosition::Left, cx)) -// .with_child( -// Flex::column() -// .with_child( -// FlexItem::new( -// self.center.render( -// &project, -// &theme, -// &self.follower_states, -// self.active_call(), -// self.active_pane(), -// self.zoomed -// .as_ref() -// .and_then(|zoomed| zoomed.upgrade(cx)) -// .as_ref(), -// &self.app_state, -// cx, -// ), -// ) -// .flex(1., true), -// ) -// .with_children( -// self.render_dock(DockPosition::Bottom, cx), -// ) -// .flex(1., true), -// ) -// .with_children(self.render_dock(DockPosition::Right, cx)) -// }) -// .with_child(Overlay::new( -// Stack::new() -// .with_children(self.zoomed.as_ref().and_then(|zoomed| { -// enum ZoomBackground {} -// let zoomed = zoomed.upgrade(cx)?; - -// let mut foreground_style = -// theme.workspace.zoomed_pane_foreground; -// if let Some(zoomed_dock_position) = self.zoomed_position { -// foreground_style = -// theme.workspace.zoomed_panel_foreground; -// let margin = foreground_style.margin.top; -// let border = foreground_style.border.top; - -// // Only include a margin and border on the opposite side. -// foreground_style.margin.top = 0.; -// foreground_style.margin.left = 0.; -// foreground_style.margin.bottom = 0.; -// foreground_style.margin.right = 0.; -// foreground_style.border.top = false; -// foreground_style.border.left = false; -// foreground_style.border.bottom = false; -// foreground_style.border.right = false; -// match zoomed_dock_position { -// DockPosition::Left => { -// foreground_style.margin.right = margin; -// foreground_style.border.right = border; -// } -// DockPosition::Right => { -// foreground_style.margin.left = margin; -// foreground_style.border.left = border; -// } -// DockPosition::Bottom => { -// foreground_style.margin.top = margin; -// foreground_style.border.top = border; -// } -// } -// } - -// Some( -// ChildView::new(&zoomed, cx) -// .contained() -// .with_style(foreground_style) -// .aligned() -// .contained() -// .with_style(theme.workspace.zoomed_background) -// .mouse::(0) -// .capture_all() -// .on_down( -// MouseButton::Left, -// |_, this: &mut Self, cx| { -// this.zoom_out(cx); -// }, -// ), -// ) -// })) -// .with_children(self.modal.as_ref().map(|modal| { -// // Prevent clicks within the modal from falling -// // through to the rest of the workspace. -// enum ModalBackground {} -// MouseEventHandler::new::( -// 0, -// cx, -// |_, cx| ChildView::new(modal.view.as_any(), cx), -// ) -// .on_click(MouseButton::Left, |_, _, _| {}) -// .contained() -// .with_style(theme.workspace.modal) -// .aligned() -// .top() -// })) -// .with_children(self.render_notifications(&theme.workspace, cx)), -// )) -// .provide_resize_bounds::() -// .flex(1.0, true), -// ) -// .with_child(ChildView::new(&self.status_bar, cx)) -// .contained() -// .with_background_color(theme.workspace.background), -// ) -// .with_children(DragAndDrop::render(cx)) -// .with_children(self.render_disconnected_overlay(cx)) -// .into_any_named("workspace") -// } - -// fn modifiers_changed(&mut self, e: &ModifiersChangedEvent, cx: &mut ViewContext) -> bool { -// DragAndDrop::::update_modifiers(e.modifiers, cx) -// } -// } - impl WorkspaceStore { pub fn new(client: Arc, cx: &mut ModelContext) -> Self { Self { From a35fdf45fc9de57b7696c4deacbc62c49b26a516 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 15 Dec 2023 12:54:12 -0700 Subject: [PATCH 085/644] Don't scroll beyond end of uniform list --- crates/gpui2/src/elements/uniform_list.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 9fedbad41c..27499b93a6 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -191,7 +191,7 @@ impl Element for UniformList { content_size, &mut element_state.interactive, cx, - |style, scroll_offset, cx| { + |style, mut scroll_offset, cx| { let border = style.border_widths.to_pixels(cx.rem_size()); let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size()); @@ -204,6 +204,13 @@ impl Element for UniformList { cx.with_z_index(style.z_index.unwrap_or(0), |cx| { style.paint(bounds, cx, |cx| { if self.item_count > 0 { + let min_scroll_offset = + padded_bounds.size.height - (item_height * self.item_count); + if scroll_offset.y < min_scroll_offset { + shared_scroll_offset.borrow_mut().y = min_scroll_offset; + scroll_offset.y = min_scroll_offset; + } + if let Some(scroll_handle) = self.scroll_handle.clone() { scroll_handle.0.borrow_mut().replace(ScrollHandleState { item_height, From 4c3ec0a8e553dbe7afd5779e805a75283ced0597 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Dec 2023 12:00:58 -0800 Subject: [PATCH 086/644] Enable pane tests --- crates/workspace2/src/pane.rs | 1213 +++++++++++++++------------------ 1 file changed, 548 insertions(+), 665 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 11588212ef..e5b4125447 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -177,7 +177,7 @@ pub struct Pane { toolbar: View, new_item_menu: Option>, split_item_menu: Option>, - // tab_context_menu: ViewHandle, + // tab_context_menu: View, workspace: WeakView, project: Model, drag_split_direction: Option, @@ -256,11 +256,11 @@ struct DraggedTab { // struct TabBarContextMenu { // kind: TabBarContextMenuKind, -// handle: ViewHandle, +// handle: View, // } // impl TabBarContextMenu { -// fn handle_if_kind(&self, kind: TabBarContextMenuKind) -> Option> { +// fn handle_if_kind(&self, kind: TabBarContextMenuKind) -> Option> { // if self.kind == kind { // return Some(self.handle.clone()); // } @@ -329,7 +329,7 @@ impl Pane { ) -> Self { // todo!("context menu") // let pane_view_id = cx.view_id(); - // let context_menu = cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)); + // let context_menu = cx.build_view(|cx| ContextMenu::new(pane_view_id, cx)); // context_menu.update(cx, |menu, _| { // menu.set_position_mode(OverlayPositionMode::Local) // }); @@ -368,7 +368,7 @@ impl Pane { // kind: TabBarContextMenuKind::New, // handle: context_menu, // }, - // tab_context_menu: cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)), + // tab_context_menu: cx.build_view(|_| ContextMenu::new(pane_view_id, cx)), workspace, project, // can_drop: Rc::new(|_, _| true), @@ -1968,52 +1968,6 @@ impl Render for Pane { }), ) } - - // fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext) { - // if !self.has_focus { - // self.has_focus = true; - // cx.emit(Event::Focus); - // cx.notify(); - // } - - // self.toolbar.update(cx, |toolbar, cx| { - // toolbar.focus_changed(true, cx); - // }); - - // if let Some(active_item) = self.active_item() { - // if cx.is_self_focused() { - // // Pane was focused directly. We need to either focus a view inside the active item, - // // or focus the active item itself - // if let Some(weak_last_focused_view) = - // self.last_focused_view_by_item.get(&active_item.id()) - // { - // if let Some(last_focused_view) = weak_last_focused_view.upgrade(cx) { - // cx.focus(&last_focused_view); - // return; - // } else { - // self.last_focused_view_by_item.remove(&active_item.id()); - // } - // } - - // cx.focus(active_item.as_any()); - // } else if focused != self.tab_bar_context_menu.handle { - // self.last_focused_view_by_item - // .insert(active_item.id(), focused.downgrade()); - // } - // } - // } - - // fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - // self.has_focus = false; - // self.toolbar.update(cx, |toolbar, cx| { - // toolbar.focus_changed(false, cx); - // }); - // cx.notify(); - // } - - // fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) { - // Self::reset_to_default_keymap_context(keymap); - // } } impl ItemNavHistory { @@ -2171,98 +2125,6 @@ impl NavHistoryState { } } -// pub struct PaneBackdrop { -// child_view: usize, -// child: AnyElement, -// } - -// impl PaneBackdrop { -// pub fn new(pane_item_view: usize, child: AnyElement) -> Self { -// PaneBackdrop { -// child, -// child_view: pane_item_view, -// } -// } -// } - -// impl Element for PaneBackdrop { -// type LayoutState = (); - -// type PaintState = (); - -// fn layout( -// &mut self, -// constraint: gpui::SizeConstraint, -// view: &mut V, -// cx: &mut ViewContext, -// ) -> (Vector2F, Self::LayoutState) { -// let size = self.child.layout(constraint, view, cx); -// (size, ()) -// } - -// fn paint( -// &mut self, -// bounds: RectF, -// visible_bounds: RectF, -// _: &mut Self::LayoutState, -// view: &mut V, -// cx: &mut ViewContext, -// ) -> Self::PaintState { -// let background = theme::current(cx).editor.background; - -// let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default(); - -// cx.scene().push_quad(gpui::Quad { -// bounds: RectF::new(bounds.origin(), bounds.size()), -// background: Some(background), -// ..Default::default() -// }); - -// let child_view_id = self.child_view; -// cx.scene().push_mouse_region( -// MouseRegion::new::(child_view_id, 0, visible_bounds).on_down( -// gpui::platform::MouseButton::Left, -// move |_, _: &mut V, cx| { -// let window = cx.window(); -// cx.app_context().focus(window, Some(child_view_id)) -// }, -// ), -// ); - -// cx.scene().push_layer(Some(bounds)); -// self.child.paint(bounds.origin(), visible_bounds, view, cx); -// cx.scene().pop_layer(); -// } - -// fn rect_for_text_range( -// &self, -// range_utf16: std::ops::Range, -// _bounds: RectF, -// _visible_bounds: RectF, -// _layout: &Self::LayoutState, -// _paint: &Self::PaintState, -// view: &V, -// cx: &gpui::ViewContext, -// ) -> Option { -// self.child.rect_for_text_range(range_utf16, view, cx) -// } - -// fn debug( -// &self, -// _bounds: RectF, -// _layout: &Self::LayoutState, -// _paint: &Self::PaintState, -// view: &V, -// cx: &gpui::ViewContext, -// ) -> serde_json::Value { -// gpui::json::json!({ -// "type": "Pane Back Drop", -// "view": self.child_view, -// "child": self.child.debug(view, cx), -// }) -// } -// } - fn dirty_message_for(buffer_path: Option) -> String { let path = buffer_path .as_ref() @@ -2272,528 +2134,549 @@ fn dirty_message_for(buffer_path: Option) -> String { format!("{path} contains unsaved edits. Do you want to save it?") } -// todo!("uncomment tests") -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::item::test::{TestItem, TestProjectItem}; -// use gpui::TestAppContext; -// use project::FakeFs; -// use settings::SettingsStore; - -// #[gpui::test] -// async fn test_remove_active_empty(cx: &mut TestAppContext) { -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// pane.update(cx, |pane, cx| { -// assert!(pane -// .close_active_item(&CloseActiveItem { save_intent: None }, cx) -// .is_none()) -// }); -// } - -// #[gpui::test] -// async fn test_add_item_with_new_item(cx: &mut TestAppContext) { -// cx.foreground().forbid_parking(); -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// // 1. Add with a destination index -// // a. Add before the active item -// set_labeled_items(&pane, ["A", "B*", "C"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item( -// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), -// false, -// false, -// Some(0), -// cx, -// ); -// }); -// assert_item_labels(&pane, ["D*", "A", "B", "C"], cx); - -// // b. Add after the active item -// set_labeled_items(&pane, ["A", "B*", "C"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item( -// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), -// false, -// false, -// Some(2), -// cx, -// ); -// }); -// assert_item_labels(&pane, ["A", "B", "D*", "C"], cx); - -// // c. Add at the end of the item list (including off the length) -// set_labeled_items(&pane, ["A", "B*", "C"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item( -// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), -// false, -// false, -// Some(5), -// cx, -// ); -// }); -// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); - -// // 2. Add without a destination index -// // a. Add with active item at the start of the item list -// set_labeled_items(&pane, ["A*", "B", "C"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item( -// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), -// false, -// false, -// None, -// cx, -// ); -// }); -// set_labeled_items(&pane, ["A", "D*", "B", "C"], cx); - -// // b. Add with active item at the end of the item list -// set_labeled_items(&pane, ["A", "B", "C*"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item( -// Box::new(cx.add_view(|_| TestItem::new().with_label("D"))), -// false, -// false, -// None, -// cx, -// ); -// }); -// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); -// } - -// #[gpui::test] -// async fn test_add_item_with_existing_item(cx: &mut TestAppContext) { -// cx.foreground().forbid_parking(); -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// // 1. Add with a destination index -// // 1a. Add before the active item -// let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(d, false, false, Some(0), cx); -// }); -// assert_item_labels(&pane, ["D*", "A", "B", "C"], cx); - -// // 1b. Add after the active item -// let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(d, false, false, Some(2), cx); -// }); -// assert_item_labels(&pane, ["A", "B", "D*", "C"], cx); - -// // 1c. Add at the end of the item list (including off the length) -// let [a, _, _, _] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(a, false, false, Some(5), cx); -// }); -// assert_item_labels(&pane, ["B", "C", "D", "A*"], cx); - -// // 1d. Add same item to active index -// let [_, b, _] = set_labeled_items(&pane, ["A", "B*", "C"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(b, false, false, Some(1), cx); -// }); -// assert_item_labels(&pane, ["A", "B*", "C"], cx); - -// // 1e. Add item to index after same item in last position -// let [_, _, c] = set_labeled_items(&pane, ["A", "B*", "C"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(c, false, false, Some(2), cx); -// }); -// assert_item_labels(&pane, ["A", "B", "C*"], cx); - -// // 2. Add without a destination index -// // 2a. Add with active item at the start of the item list -// let [_, _, _, d] = set_labeled_items(&pane, ["A*", "B", "C", "D"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(d, false, false, None, cx); -// }); -// assert_item_labels(&pane, ["A", "D*", "B", "C"], cx); - -// // 2b. Add with active item at the end of the item list -// let [a, _, _, _] = set_labeled_items(&pane, ["A", "B", "C", "D*"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(a, false, false, None, cx); -// }); -// assert_item_labels(&pane, ["B", "C", "D", "A*"], cx); - -// // 2c. Add active item to active item at end of list -// let [_, _, c] = set_labeled_items(&pane, ["A", "B", "C*"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(c, false, false, None, cx); -// }); -// assert_item_labels(&pane, ["A", "B", "C*"], cx); - -// // 2d. Add active item to active item at start of list -// let [a, _, _] = set_labeled_items(&pane, ["A*", "B", "C"], cx); -// pane.update(cx, |pane, cx| { -// pane.add_item(a, false, false, None, cx); -// }); -// assert_item_labels(&pane, ["A*", "B", "C"], cx); -// } - -// #[gpui::test] -// async fn test_add_item_with_same_project_entries(cx: &mut TestAppContext) { -// cx.foreground().forbid_parking(); -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// // singleton view -// pane.update(cx, |pane, cx| { -// let item = TestItem::new() -// .with_singleton(true) -// .with_label("buffer 1") -// .with_project_items(&[TestProjectItem::new(1, "one.txt", cx)]); - -// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); -// }); -// assert_item_labels(&pane, ["buffer 1*"], cx); - -// // new singleton view with the same project entry -// pane.update(cx, |pane, cx| { -// let item = TestItem::new() -// .with_singleton(true) -// .with_label("buffer 1") -// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]); - -// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); -// }); -// assert_item_labels(&pane, ["buffer 1*"], cx); - -// // new singleton view with different project entry -// pane.update(cx, |pane, cx| { -// let item = TestItem::new() -// .with_singleton(true) -// .with_label("buffer 2") -// .with_project_items(&[TestProjectItem::new(2, "2.txt", cx)]); -// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); -// }); -// assert_item_labels(&pane, ["buffer 1", "buffer 2*"], cx); - -// // new multibuffer view with the same project entry -// pane.update(cx, |pane, cx| { -// let item = TestItem::new() -// .with_singleton(false) -// .with_label("multibuffer 1") -// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]); - -// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); -// }); -// assert_item_labels(&pane, ["buffer 1", "buffer 2", "multibuffer 1*"], cx); - -// // another multibuffer view with the same project entry -// pane.update(cx, |pane, cx| { -// let item = TestItem::new() -// .with_singleton(false) -// .with_label("multibuffer 1b") -// .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]); - -// pane.add_item(Box::new(cx.add_view(|_| item)), false, false, None, cx); -// }); -// assert_item_labels( -// &pane, -// ["buffer 1", "buffer 2", "multibuffer 1", "multibuffer 1b*"], -// cx, -// ); -// } - -// #[gpui::test] -// async fn test_remove_item_ordering(cx: &mut TestAppContext) { -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// add_labeled_item(&pane, "A", false, cx); -// add_labeled_item(&pane, "B", false, cx); -// add_labeled_item(&pane, "C", false, cx); -// add_labeled_item(&pane, "D", false, cx); -// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); - -// pane.update(cx, |pane, cx| pane.activate_item(1, false, false, cx)); -// add_labeled_item(&pane, "1", false, cx); -// assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx); - -// pane.update(cx, |pane, cx| { -// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) -// }) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, ["A", "B*", "C", "D"], cx); - -// pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx)); -// assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); - -// pane.update(cx, |pane, cx| { -// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) -// }) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, ["A", "B*", "C"], cx); - -// pane.update(cx, |pane, cx| { -// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) -// }) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, ["A", "C*"], cx); - -// pane.update(cx, |pane, cx| { -// pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) -// }) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, ["A*"], cx); -// } - -// #[gpui::test] -// async fn test_close_inactive_items(cx: &mut TestAppContext) { -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); - -// pane.update(cx, |pane, cx| { -// pane.close_inactive_items(&CloseInactiveItems, cx) -// }) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, ["C*"], cx); -// } - -// #[gpui::test] -// async fn test_close_clean_items(cx: &mut TestAppContext) { -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// add_labeled_item(&pane, "A", true, cx); -// add_labeled_item(&pane, "B", false, cx); -// add_labeled_item(&pane, "C", true, cx); -// add_labeled_item(&pane, "D", false, cx); -// add_labeled_item(&pane, "E", false, cx); -// assert_item_labels(&pane, ["A^", "B", "C^", "D", "E*"], cx); - -// pane.update(cx, |pane, cx| pane.close_clean_items(&CloseCleanItems, cx)) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, ["A^", "C*^"], cx); -// } - -// #[gpui::test] -// async fn test_close_items_to_the_left(cx: &mut TestAppContext) { -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); - -// pane.update(cx, |pane, cx| { -// pane.close_items_to_the_left(&CloseItemsToTheLeft, cx) -// }) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, ["C*", "D", "E"], cx); -// } - -// #[gpui::test] -// async fn test_close_items_to_the_right(cx: &mut TestAppContext) { -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); - -// pane.update(cx, |pane, cx| { -// pane.close_items_to_the_right(&CloseItemsToTheRight, cx) -// }) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, ["A", "B", "C*"], cx); -// } - -// #[gpui::test] -// async fn test_close_all_items(cx: &mut TestAppContext) { -// init_test(cx); -// let fs = FakeFs::new(cx.background()); - -// let project = Project::test(fs, None, cx).await; -// let window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); -// let workspace = window.root(cx); -// let pane = workspace.read_with(cx, |workspace, _| workspace.active_pane().clone()); - -// add_labeled_item(&pane, "A", false, cx); -// add_labeled_item(&pane, "B", false, cx); -// add_labeled_item(&pane, "C", false, cx); -// assert_item_labels(&pane, ["A", "B", "C*"], cx); - -// pane.update(cx, |pane, cx| { -// pane.close_all_items(&CloseAllItems { save_intent: None }, cx) -// }) -// .unwrap() -// .await -// .unwrap(); -// assert_item_labels(&pane, [], cx); - -// add_labeled_item(&pane, "A", true, cx); -// add_labeled_item(&pane, "B", true, cx); -// add_labeled_item(&pane, "C", true, cx); -// assert_item_labels(&pane, ["A^", "B^", "C*^"], cx); - -// let save = pane -// .update(cx, |pane, cx| { -// pane.close_all_items(&CloseAllItems { save_intent: None }, cx) -// }) -// .unwrap(); - -// cx.foreground().run_until_parked(); -// window.simulate_prompt_answer(2, cx); -// save.await.unwrap(); -// assert_item_labels(&pane, [], cx); -// } - -// fn init_test(cx: &mut TestAppContext) { -// cx.update(|cx| { -// cx.set_global(SettingsStore::test(cx)); -// theme::init((), cx); -// crate::init_settings(cx); -// Project::init_settings(cx); -// }); -// } - -// fn add_labeled_item( -// pane: &ViewHandle, -// label: &str, -// is_dirty: bool, -// cx: &mut TestAppContext, -// ) -> Box> { -// pane.update(cx, |pane, cx| { -// let labeled_item = -// Box::new(cx.add_view(|_| TestItem::new().with_label(label).with_dirty(is_dirty))); -// pane.add_item(labeled_item.clone(), false, false, None, cx); -// labeled_item -// }) -// } - -// fn set_labeled_items( -// pane: &ViewHandle, -// labels: [&str; COUNT], -// cx: &mut TestAppContext, -// ) -> [Box>; COUNT] { -// pane.update(cx, |pane, cx| { -// pane.items.clear(); -// let mut active_item_index = 0; - -// let mut index = 0; -// let items = labels.map(|mut label| { -// if label.ends_with("*") { -// label = label.trim_end_matches("*"); -// active_item_index = index; -// } - -// let labeled_item = Box::new(cx.add_view(|_| TestItem::new().with_label(label))); -// pane.add_item(labeled_item.clone(), false, false, None, cx); -// index += 1; -// labeled_item -// }); - -// pane.activate_item(active_item_index, false, false, cx); - -// items -// }) -// } - -// // Assert the item label, with the active item label suffixed with a '*' -// fn assert_item_labels( -// pane: &ViewHandle, -// expected_states: [&str; COUNT], -// cx: &mut TestAppContext, -// ) { -// pane.read_with(cx, |pane, cx| { -// let actual_states = pane -// .items -// .iter() -// .enumerate() -// .map(|(ix, item)| { -// let mut state = item -// .as_any() -// .downcast_ref::() -// .unwrap() -// .read(cx) -// .label -// .clone(); -// if ix == pane.active_item_index { -// state.push('*'); -// } -// if item.is_dirty(cx) { -// state.push('^'); -// } -// state -// }) -// .collect::>(); - -// assert_eq!( -// actual_states, expected_states, -// "pane items do not match expectation" -// ); -// }) -// } -// } +#[cfg(test)] +mod tests { + use super::*; + use crate::item::test::{TestItem, TestProjectItem}; + use gpui::{TestAppContext, VisualTestContext}; + use project::FakeFs; + use settings::SettingsStore; + use theme::LoadThemes; + + #[gpui::test] + async fn test_remove_active_empty(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + pane.update(cx, |pane, cx| { + assert!(pane + .close_active_item(&CloseActiveItem { save_intent: None }, cx) + .is_none()) + }); + } + + #[gpui::test] + async fn test_add_item_with_new_item(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + // 1. Add with a destination index + // a. Add before the active item + set_labeled_items(&pane, ["A", "B*", "C"], cx); + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), + false, + false, + Some(0), + cx, + ); + }); + assert_item_labels(&pane, ["D*", "A", "B", "C"], cx); + + // b. Add after the active item + set_labeled_items(&pane, ["A", "B*", "C"], cx); + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), + false, + false, + Some(2), + cx, + ); + }); + assert_item_labels(&pane, ["A", "B", "D*", "C"], cx); + + // c. Add at the end of the item list (including off the length) + set_labeled_items(&pane, ["A", "B*", "C"], cx); + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), + false, + false, + Some(5), + cx, + ); + }); + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); + + // 2. Add without a destination index + // a. Add with active item at the start of the item list + set_labeled_items(&pane, ["A*", "B", "C"], cx); + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), + false, + false, + None, + cx, + ); + }); + set_labeled_items(&pane, ["A", "D*", "B", "C"], cx); + + // b. Add with active item at the end of the item list + set_labeled_items(&pane, ["A", "B", "C*"], cx); + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label("D"))), + false, + false, + None, + cx, + ); + }); + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); + } + + #[gpui::test] + async fn test_add_item_with_existing_item(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + // 1. Add with a destination index + // 1a. Add before the active item + let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(d, false, false, Some(0), cx); + }); + assert_item_labels(&pane, ["D*", "A", "B", "C"], cx); + + // 1b. Add after the active item + let [_, _, _, d] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(d, false, false, Some(2), cx); + }); + assert_item_labels(&pane, ["A", "B", "D*", "C"], cx); + + // 1c. Add at the end of the item list (including off the length) + let [a, _, _, _] = set_labeled_items(&pane, ["A", "B*", "C", "D"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(a, false, false, Some(5), cx); + }); + assert_item_labels(&pane, ["B", "C", "D", "A*"], cx); + + // 1d. Add same item to active index + let [_, b, _] = set_labeled_items(&pane, ["A", "B*", "C"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(b, false, false, Some(1), cx); + }); + assert_item_labels(&pane, ["A", "B*", "C"], cx); + + // 1e. Add item to index after same item in last position + let [_, _, c] = set_labeled_items(&pane, ["A", "B*", "C"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(c, false, false, Some(2), cx); + }); + assert_item_labels(&pane, ["A", "B", "C*"], cx); + + // 2. Add without a destination index + // 2a. Add with active item at the start of the item list + let [_, _, _, d] = set_labeled_items(&pane, ["A*", "B", "C", "D"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(d, false, false, None, cx); + }); + assert_item_labels(&pane, ["A", "D*", "B", "C"], cx); + + // 2b. Add with active item at the end of the item list + let [a, _, _, _] = set_labeled_items(&pane, ["A", "B", "C", "D*"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(a, false, false, None, cx); + }); + assert_item_labels(&pane, ["B", "C", "D", "A*"], cx); + + // 2c. Add active item to active item at end of list + let [_, _, c] = set_labeled_items(&pane, ["A", "B", "C*"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(c, false, false, None, cx); + }); + assert_item_labels(&pane, ["A", "B", "C*"], cx); + + // 2d. Add active item to active item at start of list + let [a, _, _] = set_labeled_items(&pane, ["A*", "B", "C"], cx); + pane.update(cx, |pane, cx| { + pane.add_item(a, false, false, None, cx); + }); + assert_item_labels(&pane, ["A*", "B", "C"], cx); + } + + #[gpui::test] + async fn test_add_item_with_same_project_entries(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + // singleton view + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| { + TestItem::new(cx) + .with_singleton(true) + .with_label("buffer 1") + .with_project_items(&[TestProjectItem::new(1, "one.txt", cx)]) + })), + false, + false, + None, + cx, + ); + }); + assert_item_labels(&pane, ["buffer 1*"], cx); + + // new singleton view with the same project entry + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| { + TestItem::new(cx) + .with_singleton(true) + .with_label("buffer 1") + .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]) + })), + false, + false, + None, + cx, + ); + }); + assert_item_labels(&pane, ["buffer 1*"], cx); + + // new singleton view with different project entry + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| { + TestItem::new(cx) + .with_singleton(true) + .with_label("buffer 2") + .with_project_items(&[TestProjectItem::new(2, "2.txt", cx)]) + })), + false, + false, + None, + cx, + ); + }); + assert_item_labels(&pane, ["buffer 1", "buffer 2*"], cx); + + // new multibuffer view with the same project entry + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| { + TestItem::new(cx) + .with_singleton(false) + .with_label("multibuffer 1") + .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]) + })), + false, + false, + None, + cx, + ); + }); + assert_item_labels(&pane, ["buffer 1", "buffer 2", "multibuffer 1*"], cx); + + // another multibuffer view with the same project entry + pane.update(cx, |pane, cx| { + pane.add_item( + Box::new(cx.build_view(|cx| { + TestItem::new(cx) + .with_singleton(false) + .with_label("multibuffer 1b") + .with_project_items(&[TestProjectItem::new(1, "1.txt", cx)]) + })), + false, + false, + None, + cx, + ); + }); + assert_item_labels( + &pane, + ["buffer 1", "buffer 2", "multibuffer 1", "multibuffer 1b*"], + cx, + ); + } + + #[gpui::test] + async fn test_remove_item_ordering(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + add_labeled_item(&pane, "A", false, cx); + add_labeled_item(&pane, "B", false, cx); + add_labeled_item(&pane, "C", false, cx); + add_labeled_item(&pane, "D", false, cx); + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); + + pane.update(cx, |pane, cx| pane.activate_item(1, false, false, cx)); + add_labeled_item(&pane, "1", false, cx); + assert_item_labels(&pane, ["A", "B", "1*", "C", "D"], cx); + + pane.update(cx, |pane, cx| { + pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) + }) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, ["A", "B*", "C", "D"], cx); + + pane.update(cx, |pane, cx| pane.activate_item(3, false, false, cx)); + assert_item_labels(&pane, ["A", "B", "C", "D*"], cx); + + pane.update(cx, |pane, cx| { + pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) + }) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, ["A", "B*", "C"], cx); + + pane.update(cx, |pane, cx| { + pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) + }) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, ["A", "C*"], cx); + + pane.update(cx, |pane, cx| { + pane.close_active_item(&CloseActiveItem { save_intent: None }, cx) + }) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, ["A*"], cx); + } + + #[gpui::test] + async fn test_close_inactive_items(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); + + pane.update(cx, |pane, cx| { + pane.close_inactive_items(&CloseInactiveItems, cx) + }) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, ["C*"], cx); + } + + #[gpui::test] + async fn test_close_clean_items(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + add_labeled_item(&pane, "A", true, cx); + add_labeled_item(&pane, "B", false, cx); + add_labeled_item(&pane, "C", true, cx); + add_labeled_item(&pane, "D", false, cx); + add_labeled_item(&pane, "E", false, cx); + assert_item_labels(&pane, ["A^", "B", "C^", "D", "E*"], cx); + + pane.update(cx, |pane, cx| pane.close_clean_items(&CloseCleanItems, cx)) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, ["A^", "C*^"], cx); + } + + #[gpui::test] + async fn test_close_items_to_the_left(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); + + pane.update(cx, |pane, cx| { + pane.close_items_to_the_left(&CloseItemsToTheLeft, cx) + }) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, ["C*", "D", "E"], cx); + } + + #[gpui::test] + async fn test_close_items_to_the_right(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + set_labeled_items(&pane, ["A", "B", "C*", "D", "E"], cx); + + pane.update(cx, |pane, cx| { + pane.close_items_to_the_right(&CloseItemsToTheRight, cx) + }) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, ["A", "B", "C*"], cx); + } + + #[gpui::test] + async fn test_close_all_items(cx: &mut TestAppContext) { + init_test(cx); + let fs = FakeFs::new(cx.executor()); + + let project = Project::test(fs, None, cx).await; + let (workspace, cx) = cx.add_window_view(|cx| Workspace::test_new(project.clone(), cx)); + let pane = workspace.update(cx, |workspace, _| workspace.active_pane().clone()); + + add_labeled_item(&pane, "A", false, cx); + add_labeled_item(&pane, "B", false, cx); + add_labeled_item(&pane, "C", false, cx); + assert_item_labels(&pane, ["A", "B", "C*"], cx); + + pane.update(cx, |pane, cx| { + pane.close_all_items(&CloseAllItems { save_intent: None }, cx) + }) + .unwrap() + .await + .unwrap(); + assert_item_labels(&pane, [], cx); + + add_labeled_item(&pane, "A", true, cx); + add_labeled_item(&pane, "B", true, cx); + add_labeled_item(&pane, "C", true, cx); + assert_item_labels(&pane, ["A^", "B^", "C*^"], cx); + + let save = pane + .update(cx, |pane, cx| { + pane.close_all_items(&CloseAllItems { save_intent: None }, cx) + }) + .unwrap(); + + cx.executor().run_until_parked(); + cx.simulate_prompt_answer(2); + save.await.unwrap(); + assert_item_labels(&pane, [], cx); + } + + fn init_test(cx: &mut TestAppContext) { + cx.update(|cx| { + let settings_store = SettingsStore::test(cx); + cx.set_global(settings_store); + theme::init(LoadThemes::JustBase, cx); + crate::init_settings(cx); + Project::init_settings(cx); + }); + } + + fn add_labeled_item( + pane: &View, + label: &str, + is_dirty: bool, + cx: &mut VisualTestContext, + ) -> Box> { + pane.update(cx, |pane, cx| { + let labeled_item = Box::new( + cx.build_view(|cx| TestItem::new(cx).with_label(label).with_dirty(is_dirty)), + ); + pane.add_item(labeled_item.clone(), false, false, None, cx); + labeled_item + }) + } + + fn set_labeled_items( + pane: &View, + labels: [&str; COUNT], + cx: &mut VisualTestContext, + ) -> [Box>; COUNT] { + pane.update(cx, |pane, cx| { + pane.items.clear(); + let mut active_item_index = 0; + + let mut index = 0; + let items = labels.map(|mut label| { + if label.ends_with("*") { + label = label.trim_end_matches("*"); + active_item_index = index; + } + + let labeled_item = + Box::new(cx.build_view(|cx| TestItem::new(cx).with_label(label))); + pane.add_item(labeled_item.clone(), false, false, None, cx); + index += 1; + labeled_item + }); + + pane.activate_item(active_item_index, false, false, cx); + + items + }) + } + + // Assert the item label, with the active item label suffixed with a '*' + fn assert_item_labels( + pane: &View, + expected_states: [&str; COUNT], + cx: &mut VisualTestContext, + ) { + pane.update(cx, |pane, cx| { + let actual_states = pane + .items + .iter() + .enumerate() + .map(|(ix, item)| { + let mut state = item + .to_any() + .downcast::() + .unwrap() + .read(cx) + .label + .clone(); + if ix == pane.active_item_index { + state.push('*'); + } + if item.is_dirty(cx) { + state.push('^'); + } + state + }) + .collect::>(); + + assert_eq!( + actual_states, expected_states, + "pane items do not match expectation" + ); + }) + } +} impl Render for DraggedTab { type Element = ::Rendered; From 2fe9a1df218009e078e8a885b512346adde3c9aa Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Fri, 15 Dec 2023 13:18:51 -0700 Subject: [PATCH 087/644] Restore position of uniform_list padding It should be inside the scrollable area. --- crates/gpui2/src/elements/uniform_list.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 27499b93a6..866bd4a1d0 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -196,16 +196,16 @@ impl Element for UniformList { let padding = style.padding.to_pixels(bounds.size.into(), cx.rem_size()); let padded_bounds = Bounds::from_corners( - bounds.origin + point(border.left + padding.left, border.top + padding.top), - bounds.lower_right() - - point(border.right + padding.right, border.bottom + padding.bottom), + bounds.origin + point(border.left + padding.left, border.top), + bounds.lower_right() - point(border.right + padding.right, border.bottom), ); cx.with_z_index(style.z_index.unwrap_or(0), |cx| { style.paint(bounds, cx, |cx| { if self.item_count > 0 { - let min_scroll_offset = - padded_bounds.size.height - (item_height * self.item_count); + let content_height = + item_height * self.item_count + padding.top + padding.bottom; + let min_scroll_offset = padded_bounds.size.height - content_height; if scroll_offset.y < min_scroll_offset { shared_scroll_offset.borrow_mut().y = min_scroll_offset; scroll_offset.y = min_scroll_offset; @@ -220,7 +220,7 @@ impl Element for UniformList { } let first_visible_element_ix = - (-scroll_offset.y / item_height).floor() as usize; + (-(scroll_offset.y + padding.top) / item_height).floor() as usize; let last_visible_element_ix = ((-scroll_offset.y + padded_bounds.size.height) / item_height) .ceil() as usize; @@ -233,7 +233,10 @@ impl Element for UniformList { cx.with_content_mask(Some(content_mask), |cx| { for (item, ix) in items.iter_mut().zip(visible_range) { let item_origin = padded_bounds.origin - + point(px(0.), item_height * ix + scroll_offset.y); + + point( + px(0.), + item_height * ix + scroll_offset.y + padding.top, + ); let available_space = size( AvailableSpace::Definite(padded_bounds.size.width), AvailableSpace::Definite(item_height), From e71f2b49e8a97dd269a045cdf66d9aae5eef2f5e Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Fri, 15 Dec 2023 15:41:53 -0500 Subject: [PATCH 088/644] Style fold control --- crates/editor2/src/element.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index a6d4bc20b1..20012ae41d 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -939,11 +939,11 @@ impl EditorElement { cx, |fold_element_state, cx| { if fold_element_state.is_active() { - gpui::blue() + cx.theme().colors().ghost_element_active } else if fold_bounds.contains(&cx.mouse_position()) { - gpui::black() + cx.theme().colors().ghost_element_hover } else { - gpui::red() + cx.theme().colors().ghost_element_background } }, ) From e3e988c150e1ad656d91bdc87039f4da6312c67f Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Dec 2023 13:26:36 -0800 Subject: [PATCH 089/644] Always render panes via pane_group::Member::render Remove distinct code path for rendering panes in a PaneAxis, as this dropped the logic for rendering the leader border and info box. --- crates/workspace2/src/pane_group.rs | 160 +++------------------------- 1 file changed, 14 insertions(+), 146 deletions(-) diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index d35c138d5c..4f29f08ef2 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -270,6 +270,7 @@ impl Member { project, basis + 1, follower_states, + active_call, active_pane, zoomed, app_state, @@ -277,133 +278,6 @@ impl Member { ) .into_any(), } - - // enum FollowIntoExternalProject {} - - // match self { - // Member::Pane(pane) => { - // let pane_element = if Some(&**pane) == zoomed { - // Empty::new().into_any() - // } else { - // ChildView::new(pane, cx).into_any() - // }; - - // let leader = follower_states.get(pane).and_then(|state| { - // let room = active_call?.read(cx).room()?.read(cx); - // room.remote_participant_for_peer_id(state.leader_id) - // }); - - // let mut leader_border = Border::default(); - // let mut leader_status_box = None; - // if let Some(leader) = &leader { - // let leader_color = theme - // .editor - // .selection_style_for_room_participant(leader.participant_index.0) - // .cursor; - // leader_border = Border::all(theme.workspace.leader_border_width, leader_color); - // leader_border - // .color - // .fade_out(1. - theme.workspace.leader_border_opacity); - // leader_border.overlay = true; - - // leader_status_box = match leader.location { - // ParticipantLocation::SharedProject { - // project_id: leader_project_id, - // } => { - // if Some(leader_project_id) == project.read(cx).remote_id() { - // None - // } else { - // let leader_user = leader.user.clone(); - // let leader_user_id = leader.user.id; - // Some( - // MouseEventHandler::new::( - // pane.id(), - // cx, - // |_, _| { - // Label::new( - // format!( - // "Follow {} to their active project", - // leader_user.github_login, - // ), - // theme - // .workspace - // .external_location_message - // .text - // .clone(), - // ) - // .contained() - // .with_style( - // theme.workspace.external_location_message.container, - // ) - // }, - // ) - // .with_cursor_style(CursorStyle::PointingHand) - // .on_click(MouseButton::Left, move |_, this, cx| { - // crate::join_remote_project( - // leader_project_id, - // leader_user_id, - // this.app_state().clone(), - // cx, - // ) - // .detach_and_log_err(cx); - // }) - // .aligned() - // .bottom() - // .right() - // .into_any(), - // ) - // } - // } - // ParticipantLocation::UnsharedProject => Some( - // Label::new( - // format!( - // "{} is viewing an unshared Zed project", - // leader.user.github_login - // ), - // theme.workspace.external_location_message.text.clone(), - // ) - // .contained() - // .with_style(theme.workspace.external_location_message.container) - // .aligned() - // .bottom() - // .right() - // .into_any(), - // ), - // ParticipantLocation::External => Some( - // Label::new( - // format!( - // "{} is viewing a window outside of Zed", - // leader.user.github_login - // ), - // theme.workspace.external_location_message.text.clone(), - // ) - // .contained() - // .with_style(theme.workspace.external_location_message.container) - // .aligned() - // .bottom() - // .right() - // .into_any(), - // ), - // }; - // } - - // Stack::new() - // .with_child(pane_element.contained().with_border(leader_border)) - // .with_children(leader_status_box) - // .into_any() - // } - // Member::Axis(axis) => axis.render( - // project, - // basis + 1, - // theme, - // follower_states, - // active_call, - // active_pane, - // zoomed, - // app_state, - // cx, - // ), - // } } fn collect_panes<'a>(&'a self, panes: &mut Vec<&'a View>) { @@ -586,6 +460,7 @@ impl PaneAxis { project: &Model, basis: usize, follower_states: &HashMap, FollowerState>, + active_call: Option<&Model>, active_pane: &View, zoomed: Option<&AnyWeakView>, app_state: &Arc, @@ -604,25 +479,18 @@ impl PaneAxis { if member.contains(active_pane) { active_pane_ix = Some(ix); } - - match member { - Member::Axis(axis) => axis - .render( - project, - (basis + ix) * 10, - follower_states, - active_pane, - zoomed, - app_state, - cx, - ) - .into_any_element(), - Member::Pane(pane) => div() - .size_full() - .border() - .child(pane.clone()) - .into_any_element(), - } + member + .render( + project, + (basis + ix) * 10, + follower_states, + active_call, + active_pane, + zoomed, + app_state, + cx, + ) + .into_any_element() })) .with_active_pane(active_pane_ix) .into_any_element() From a5e037befa7067501089928947d51e49c07f9ffe Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Dec 2023 13:26:48 -0800 Subject: [PATCH 090/644] Avoid duplicate render of a pane when it is zoomed --- crates/workspace2/src/pane_group.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index 4f29f08ef2..b52cec2b18 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -172,6 +172,10 @@ impl Member { ) -> impl IntoElement { match self { Member::Pane(pane) => { + if zoomed == Some(&pane.downgrade().into()) { + return div().into_any(); + } + let leader = follower_states.get(pane).and_then(|state| { let room = active_call?.read(cx).room()?.read(cx); room.remote_participant_for_peer_id(state.leader_id) From 0ea59d6466e064decc45767b0eb0792ad8f1fcd3 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 16:27:58 -0500 Subject: [PATCH 091/644] Format `zed-local` script --- script/zed-local | 97 ++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 53 deletions(-) diff --git a/script/zed-local b/script/zed-local index 20f0d22ea1..6fef809985 100755 --- a/script/zed-local +++ b/script/zed-local @@ -1,95 +1,86 @@ #!/usr/bin/env node -const {spawn, execFileSync} = require('child_process') +const { spawn, execFileSync } = require("child_process"); -const RESOLUTION_REGEX = /(\d+) x (\d+)/ -const DIGIT_FLAG_REGEX = /^--?(\d+)$/ -const ZED_2_MODE = "--zed2" +const RESOLUTION_REGEX = /(\d+) x (\d+)/; +const DIGIT_FLAG_REGEX = /^--?(\d+)$/; +const ZED_2_MODE = "--zed2"; -const args = process.argv.slice(2) +const args = process.argv.slice(2); // Parse the number of Zed instances to spawn. -let instanceCount = 1 -const digitMatch = args[0]?.match(DIGIT_FLAG_REGEX) +let instanceCount = 1; +const digitMatch = args[0]?.match(DIGIT_FLAG_REGEX); if (digitMatch) { - instanceCount = parseInt(digitMatch[1]) - args.shift() + instanceCount = parseInt(digitMatch[1]); + args.shift(); } -const isZed2 = args.some(arg => arg === ZED_2_MODE); +const isZed2 = args.some((arg) => arg === ZED_2_MODE); if (instanceCount > 4) { - throw new Error('Cannot spawn more than 4 instances') + throw new Error("Cannot spawn more than 4 instances"); } // Parse the resolution of the main screen const displayInfo = JSON.parse( - execFileSync( - 'system_profiler', - ['SPDisplaysDataType', '-json'], - {encoding: 'utf8'} - ) -) -const mainDisplayResolution = displayInfo - ?.SPDisplaysDataType[0] - ?.spdisplays_ndrvs - ?.find(entry => entry.spdisplays_main === "spdisplays_yes") - ?._spdisplays_resolution - ?.match(RESOLUTION_REGEX) + execFileSync("system_profiler", ["SPDisplaysDataType", "-json"], { + encoding: "utf8", + }), +); +const mainDisplayResolution = + displayInfo?.SPDisplaysDataType[0]?.spdisplays_ndrvs + ?.find((entry) => entry.spdisplays_main === "spdisplays_yes") + ?._spdisplays_resolution?.match(RESOLUTION_REGEX); if (!mainDisplayResolution) { - throw new Error('Could not parse screen resolution') + throw new Error("Could not parse screen resolution"); } -const screenWidth = parseInt(mainDisplayResolution[1]) -const screenHeight = parseInt(mainDisplayResolution[2]) +const screenWidth = parseInt(mainDisplayResolution[1]); +const screenHeight = parseInt(mainDisplayResolution[2]); // Determine the window size for each instance -let instanceWidth = screenWidth -let instanceHeight = screenHeight +let instanceWidth = screenWidth; +let instanceHeight = screenHeight; if (instanceCount > 1) { - instanceWidth = Math.floor(screenWidth / 2) + instanceWidth = Math.floor(screenWidth / 2); if (instanceCount > 2) { - instanceHeight = Math.floor(screenHeight / 2) + instanceHeight = Math.floor(screenHeight / 2); } } -let users = [ - 'nathansobo', - 'as-cii', - 'maxbrunsfeld', - 'iamnbutler' -] +let users = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler"]; -const RUST_LOG = process.env.RUST_LOG || 'info' +const RUST_LOG = process.env.RUST_LOG || "info"; // If a user is specified, make sure it's first in the list -const user = process.env.ZED_IMPERSONATE +const user = process.env.ZED_IMPERSONATE; if (user) { - users = [user].concat(users.filter(u => u !== user)) + users = [user].concat(users.filter((u) => u !== user)); } const positions = [ - '0,0', + "0,0", `${instanceWidth},0`, `0,${instanceHeight}`, - `${instanceWidth},${instanceHeight}` -] + `${instanceWidth},${instanceHeight}`, +]; -const buildArgs = isZed2 ? ["build", "-p", "zed2"] : ["build"] -const zedBinary = isZed2 ? "target/debug/Zed2" : "target/debug/Zed" -execFileSync('cargo', buildArgs, { stdio: 'inherit' }) +const buildArgs = isZed2 ? ["build", "-p", "zed2"] : ["build"]; +const zedBinary = isZed2 ? "target/debug/Zed2" : "target/debug/Zed"; +execFileSync("cargo", buildArgs, { stdio: "inherit" }); setTimeout(() => { for (let i = 0; i < instanceCount; i++) { spawn(zedBinary, i == 0 ? args : [], { - stdio: 'inherit', + stdio: "inherit", env: { ZED_IMPERSONATE: users[i], ZED_WINDOW_POSITION: positions[i], - ZED_STATELESS: '1', - ZED_ALWAYS_ACTIVE: '1', - ZED_SERVER_URL: 'http://localhost:8080', - ZED_ADMIN_API_TOKEN: 'secret', + ZED_STATELESS: "1", + ZED_ALWAYS_ACTIVE: "1", + ZED_SERVER_URL: "http://localhost:8080", + ZED_ADMIN_API_TOKEN: "secret", ZED_WINDOW_SIZE: `${instanceWidth},${instanceHeight}`, PATH: process.env.PATH, RUST_LOG, - } - }) + }, + }); } -}, 0.1) +}, 0.1); From 170e3324170797dd38898a2f98cb70c7d9f2ad81 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 16:28:23 -0500 Subject: [PATCH 092/644] Add support for `--release` flag to `zed-local` script --- script/zed-local | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/script/zed-local b/script/zed-local index 6fef809985..bb0f1bd5da 100755 --- a/script/zed-local +++ b/script/zed-local @@ -5,6 +5,7 @@ const { spawn, execFileSync } = require("child_process"); const RESOLUTION_REGEX = /(\d+) x (\d+)/; const DIGIT_FLAG_REGEX = /^--?(\d+)$/; const ZED_2_MODE = "--zed2"; +const RELEASE_MODE = "--release"; const args = process.argv.slice(2); @@ -16,6 +17,7 @@ if (digitMatch) { args.shift(); } const isZed2 = args.some((arg) => arg === ZED_2_MODE); +const isReleaseMode = args.some((arg) => arg === RELEASE_MODE); if (instanceCount > 4) { throw new Error("Cannot spawn more than 4 instances"); } @@ -63,8 +65,25 @@ const positions = [ `${instanceWidth},${instanceHeight}`, ]; -const buildArgs = isZed2 ? ["build", "-p", "zed2"] : ["build"]; -const zedBinary = isZed2 ? "target/debug/Zed2" : "target/debug/Zed"; +const buildArgs = (() => { + const buildArgs = ["build"]; + if (isReleaseMode) { + buildArgs.push("--release"); + } + + if (isZed2) { + buildArgs.push("-p", "zed2"); + } + + return buildArgs; +})(); +const zedBinary = (() => { + const target = isReleaseMode ? "release" : "debug"; + const binary = isZed2 ? "Zed2" : "Zed"; + + return `target/${target}/${binary}`; +})(); + execFileSync("cargo", buildArgs, { stdio: "inherit" }); setTimeout(() => { for (let i = 0; i < instanceCount; i++) { From 149a718d65c6df6a71acdc0a45e8fe5c6907b933 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Dec 2023 13:38:49 -0800 Subject: [PATCH 093/644] Don't scroll List on scroll wheel events outside of its bounds --- crates/gpui2/src/elements/list.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/gpui2/src/elements/list.rs b/crates/gpui2/src/elements/list.rs index 415a3b7368..73bd319afc 100644 --- a/crates/gpui2/src/elements/list.rs +++ b/crates/gpui2/src/elements/list.rs @@ -458,7 +458,10 @@ impl Element for List { let list_state = self.state.clone(); let height = bounds.size.height; cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - if phase == DispatchPhase::Bubble { + if phase == DispatchPhase::Bubble + && bounds.contains(&event.position) + && cx.was_top_layer(&event.position, cx.stacking_order()) + { list_state.0.borrow_mut().scroll( &scroll_top, height, From 5447c6d5eeadb6e97ec6e344101ff9ff6b52c10e Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 17:03:59 -0500 Subject: [PATCH 094/644] Fix channel filter input (#3686) This PR fixes the channel filter in the collab panel not showing up. Release Notes: - N/A --- crates/collab_ui2/src/collab_panel.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index ec723df25d..5f01d49878 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2113,8 +2113,8 @@ impl CollabPanel { .size_full() .child(list(self.list_state.clone()).full()) .child( - div().p_2().child( - div() + v_stack().p_2().child( + v_stack() .border_primary(cx) .border_t() .child(self.filter_editor.clone()), From 54eb4521442d0edaf82cfa1104fb8947620ac0a5 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 15 Dec 2023 17:53:10 -0500 Subject: [PATCH 095/644] Only apply scroll correction in `uniform_list` when already scrolled (#3687) This PR fixes an issue where the scroll correction added to the uniform list in a35fdf45fc9de57b7696c4deacbc62c49b26a516 was being applied even if the list wasn't scrolled at all. This manifested in the project panel starting with an incorrect scroll offset that would disappear once scrolled. It seems like we should only need to apply this scroll correction when the list is already scrolled. Release Notes: - N/A --- crates/gpui2/src/elements/uniform_list.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 866bd4a1d0..26b1df4cda 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -206,7 +206,9 @@ impl Element for UniformList { let content_height = item_height * self.item_count + padding.top + padding.bottom; let min_scroll_offset = padded_bounds.size.height - content_height; - if scroll_offset.y < min_scroll_offset { + let is_scrolled = scroll_offset.y != px(0.); + + if is_scrolled && scroll_offset.y < min_scroll_offset { shared_scroll_offset.borrow_mut().y = min_scroll_offset; scroll_offset.y = min_scroll_offset; } From a4cdf365be1c696679ad4be35e648367515a7bc8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Dec 2023 16:15:31 -0800 Subject: [PATCH 096/644] Fix accidental drop of following task. Add back FollowNextCollaborator --- .../collab2/src/tests/channel_buffer_tests.rs | 4 +- crates/workspace2/src/workspace2.rs | 128 +++++++----------- 2 files changed, 55 insertions(+), 77 deletions(-) diff --git a/crates/collab2/src/tests/channel_buffer_tests.rs b/crates/collab2/src/tests/channel_buffer_tests.rs index b0af360fd5..19411ed892 100644 --- a/crates/collab2/src/tests/channel_buffer_tests.rs +++ b/crates/collab2/src/tests/channel_buffer_tests.rs @@ -685,7 +685,9 @@ async fn test_following_to_channel_notes_without_a_shared_project( // Client B follows client A. workspace_b .update(cx_b, |workspace, cx| { - workspace.follow(client_a.peer_id().unwrap(), cx).unwrap() + workspace + .start_following(client_a.peer_id().unwrap(), cx) + .unwrap() }) .await .unwrap(); diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 866762e7d5..8cb8c3dc9a 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -2292,7 +2292,7 @@ impl Workspace { cx.notify(); } - fn start_following( + pub fn start_following( &mut self, leader_id: PeerId, cx: &mut ViewContext, @@ -2347,57 +2347,55 @@ impl Workspace { })) } - // pub fn follow_next_collaborator( - // &mut self, - // _: &FollowNextCollaborator, - // cx: &mut ViewContext, - // ) { - // let collaborators = self.project.read(cx).collaborators(); - // let next_leader_id = if let Some(leader_id) = self.leader_for_pane(&self.active_pane) { - // let mut collaborators = collaborators.keys().copied(); - // for peer_id in collaborators.by_ref() { - // if peer_id == leader_id { - // break; - // } - // } - // collaborators.next() - // } else if let Some(last_leader_id) = - // self.last_leaders_by_pane.get(&self.active_pane.downgrade()) - // { - // if collaborators.contains_key(last_leader_id) { - // Some(*last_leader_id) - // } else { - // None - // } - // } else { - // None - // }; - - // let pane = self.active_pane.clone(); - // let Some(leader_id) = next_leader_id.or_else(|| collaborators.keys().copied().next()) - // else { - // return; - // }; - // if Some(leader_id) == self.unfollow(&pane, cx) { - // return; - // } - // if let Some(task) = self.follow(leader_id, cx) { - // task.detach(); - // } - // } - - pub fn follow( + pub fn follow_next_collaborator( &mut self, - leader_id: PeerId, + _: &FollowNextCollaborator, cx: &mut ViewContext, - ) -> Option>> { - let room = ActiveCall::global(cx).read(cx).room()?.read(cx); - let project = self.project.read(cx); - - let Some(remote_participant) = room.remote_participant_for_peer_id(leader_id) else { - return None; + ) { + let collaborators = self.project.read(cx).collaborators(); + let next_leader_id = if let Some(leader_id) = self.leader_for_pane(&self.active_pane) { + let mut collaborators = collaborators.keys().copied(); + for peer_id in collaborators.by_ref() { + if peer_id == leader_id { + break; + } + } + collaborators.next() + } else if let Some(last_leader_id) = + self.last_leaders_by_pane.get(&self.active_pane.downgrade()) + { + if collaborators.contains_key(last_leader_id) { + Some(*last_leader_id) + } else { + None + } + } else { + None }; + let pane = self.active_pane.clone(); + let Some(leader_id) = next_leader_id.or_else(|| collaborators.keys().copied().next()) + else { + return; + }; + if Some(leader_id) == self.unfollow(&pane, cx) { + return; + } + self.start_following(leader_id, cx) + .map(|task| task.detach_and_log_err(cx)); + } + + pub fn follow(&mut self, leader_id: PeerId, cx: &mut ViewContext) { + let Some(room) = ActiveCall::global(cx).read(cx).room() else { + return; + }; + let room = room.read(cx); + let Some(remote_participant) = room.remote_participant_for_peer_id(leader_id) else { + return; + }; + + let project = self.project.read(cx); + let other_project_id = match remote_participant.location { call::ParticipantLocation::External => None, call::ParticipantLocation::UnsharedProject => None, @@ -2413,38 +2411,23 @@ impl Workspace { // if they are active in another project, follow there. if let Some(project_id) = other_project_id { let app_state = self.app_state.clone(); - return Some(crate::join_remote_project( - project_id, - remote_participant.user.id, - app_state, - cx, - )); + crate::join_remote_project(project_id, remote_participant.user.id, app_state, cx) + .detach_and_log_err(cx); } // if you're already following, find the right pane and focus it. for (pane, state) in &self.follower_states { if leader_id == state.leader_id { cx.focus_view(pane); - return None; + return; } } // Otherwise, follow. self.start_following(leader_id, cx) + .map(|task| task.detach_and_log_err(cx)); } - // // if you're already following, find the right pane and focus it. - // for (pane, state) in &self.follower_states { - // if leader_id == state.leader_id { - // cx.focus(pane); - // return None; - // } - // } - - // // Otherwise, follow. - // self.start_following(leader_id, cx) - // } - pub fn unfollow(&mut self, pane: &View, cx: &mut ViewContext) -> Option { let state = self.follower_states.remove(pane)?; let leader_id = state.leader_id; @@ -2855,12 +2838,6 @@ impl Workspace { if leader_in_this_project || !item.is_project_item(cx) { items_to_activate.push((pane.clone(), item.boxed_clone())); } - } else { - log::warn!( - "unknown view id {:?} for leader {:?}", - active_view_id, - leader_id - ); } continue; } @@ -3255,6 +3232,7 @@ impl Workspace { .on_action(cx.listener(Self::close_all_items_and_panes)) .on_action(cx.listener(Self::save_all)) .on_action(cx.listener(Self::add_folder_to_project)) + .on_action(cx.listener(Self::follow_next_collaborator)) .on_action(cx.listener(|workspace, _: &Unfollow, cx| { let pane = workspace.active_pane().clone(); workspace.unfollow(&pane, cx); @@ -4240,9 +4218,7 @@ pub fn join_remote_project( }); if let Some(follow_peer_id) = follow_peer_id { - workspace - .follow(follow_peer_id, cx) - .map(|follow| follow.detach_and_log_err(cx)); + workspace.follow(follow_peer_id, cx); } } })?; From b5ae2f060b420371076a75bc7c94d899e7fb767e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 15 Dec 2023 16:26:56 -0800 Subject: [PATCH 097/644] Remove div around all avatars in titlebar facepile --- crates/collab_ui2/src/collab_titlebar_item.rs | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 706749b28d..023b77ab8f 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -401,33 +401,30 @@ impl CollabTitlebarItem { ) -> Option { let followers = project_id.map_or(&[] as &[_], |id| room.followers_for(peer_id, id)); - let pile = FacePile::default().child( - div() - .child( - Avatar::new(user.avatar_uri.clone()) - .grayscale(!is_present) - .border_color(if is_speaking { - gpui::blue() - } else if is_muted { - gpui::red() - } else { - Hsla::default() - }), - ) - .children(followers.iter().filter_map(|follower_peer_id| { - let follower = room - .remote_participants() - .values() - .find_map(|p| (p.peer_id == *follower_peer_id).then_some(&p.user)) - .or_else(|| { - (self.client.peer_id() == Some(*follower_peer_id)) - .then_some(current_user) - })? - .clone(); + let pile = FacePile::default() + .child( + Avatar::new(user.avatar_uri.clone()) + .grayscale(!is_present) + .border_color(if is_speaking { + gpui::blue() + } else if is_muted { + gpui::red() + } else { + Hsla::default() + }), + ) + .children(followers.iter().filter_map(|follower_peer_id| { + let follower = room + .remote_participants() + .values() + .find_map(|p| (p.peer_id == *follower_peer_id).then_some(&p.user)) + .or_else(|| { + (self.client.peer_id() == Some(*follower_peer_id)).then_some(current_user) + })? + .clone(); - Some(div().child(Avatar::new(follower.avatar_uri.clone()))) - })), - ); + Some(Avatar::new(follower.avatar_uri.clone())) + })); Some(pile) } From 5a4e2e6b90900fe685ce69ff230da5163f370a76 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 18 Dec 2023 10:41:20 +0100 Subject: [PATCH 098/644] Use a closure to allocate structs onto the `Arena` This is a trick borrowed from Bumpalo that helps LLVM understand it should instantiate the object directly on the heap, as opposed to doing so on the stack and then moving it. --- crates/gpui2/src/arena.rs | 36 ++++++++++++++++-------- crates/gpui2/src/element.rs | 9 +++--- crates/gpui2/src/gpui2.rs | 1 + crates/gpui2/src/window.rs | 56 +++++++++++++++++-------------------- 4 files changed, 55 insertions(+), 47 deletions(-) diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index a362c720a2..c99f09d29f 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -12,6 +12,7 @@ struct ArenaElement { } impl Drop for ArenaElement { + #[inline(always)] fn drop(&mut self) { unsafe { (self.drop)(self.value); @@ -48,15 +49,23 @@ impl Arena { } #[inline(always)] - pub fn alloc(&mut self, value: T) -> ArenaRef { + pub fn alloc(&mut self, f: impl FnOnce() -> T) -> ArenaRef { + #[inline(always)] + unsafe fn inner_writer(ptr: *mut T, f: F) + where + F: FnOnce() -> T, + { + ptr::write(ptr, f()); + } + unsafe fn drop(ptr: NonNull) { std::ptr::drop_in_place(ptr.cast::().as_ptr()); } unsafe { - let layout = alloc::Layout::for_value(&value).pad_to_align(); + let layout = alloc::Layout::new::().pad_to_align(); let ptr = NonNull::new_unchecked(self.start.as_ptr().add(self.offset).cast::()); - ptr::write(ptr.as_ptr(), value); + inner_writer(ptr.as_ptr(), f); self.elements.push(ArenaElement { value: ptr.cast(), @@ -92,6 +101,7 @@ impl Clone for ArenaRef { } impl ArenaRef { + #[inline(always)] pub fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef { ArenaRef { ptr: unsafe { NonNull::new_unchecked(f(&mut *self)) }, @@ -110,6 +120,7 @@ impl ArenaRef { impl Deref for ArenaRef { type Target = T; + #[inline(always)] fn deref(&self) -> &Self::Target { self.validate(); unsafe { self.ptr.as_ref() } @@ -117,6 +128,7 @@ impl Deref for ArenaRef { } impl DerefMut for ArenaRef { + #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { self.validate(); unsafe { self.ptr.as_mut() } @@ -132,20 +144,20 @@ mod tests { #[test] fn test_arena() { let mut arena = Arena::new(1024); - let a = arena.alloc(1u64); - let b = arena.alloc(2u32); - let c = arena.alloc(3u16); - let d = arena.alloc(4u8); + let a = arena.alloc(|| 1u64); + let b = arena.alloc(|| 2u32); + let c = arena.alloc(|| 3u16); + let d = arena.alloc(|| 4u8); assert_eq!(*a, 1); assert_eq!(*b, 2); assert_eq!(*c, 3); assert_eq!(*d, 4); arena.clear(); - let a = arena.alloc(5u64); - let b = arena.alloc(6u32); - let c = arena.alloc(7u16); - let d = arena.alloc(8u8); + let a = arena.alloc(|| 5u64); + let b = arena.alloc(|| 6u32); + let c = arena.alloc(|| 7u16); + let d = arena.alloc(|| 8u8); assert_eq!(*a, 5); assert_eq!(*b, 6); assert_eq!(*c, 7); @@ -159,7 +171,7 @@ mod tests { self.0.set(true); } } - arena.alloc(DropGuard(dropped.clone())); + arena.alloc(|| DropGuard(dropped.clone())); arena.clear(); assert!(dropped.get()); } diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index d54d1c245d..6f739d8e33 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -1,6 +1,6 @@ use crate::{ - arena::ArenaRef, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, - Size, ViewContext, WindowContext, FRAME_ARENA, + frame_alloc, ArenaRef, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, + Point, Size, ViewContext, WindowContext, }; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; @@ -413,9 +413,8 @@ impl AnyElement { E: 'static + Element, E::State: Any, { - let element = - FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(Some(DrawableElement::new(element)))); - let element = element.map(|element| element as &mut dyn ElementObject); + let element = frame_alloc(|| Some(DrawableElement::new(element))) + .map(|element| element as &mut dyn ElementObject); AnyElement(element) } diff --git a/crates/gpui2/src/gpui2.rs b/crates/gpui2/src/gpui2.rs index 322ca20608..6af274ef5d 100644 --- a/crates/gpui2/src/gpui2.rs +++ b/crates/gpui2/src/gpui2.rs @@ -39,6 +39,7 @@ mod private { pub use action::*; pub use anyhow::Result; pub use app::*; +pub(crate) use arena::*; pub use assets::*; pub use color::*; pub use ctor::ctor; diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 56c5466b63..337f61272f 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -102,6 +102,11 @@ thread_local! { pub static FRAME_ARENA: RefCell = RefCell::new(Arena::new(16 * 1024 * 1024)); } +#[inline(always)] +pub(crate) fn frame_alloc(f: impl FnOnce() -> T) -> ArenaRef { + FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(f)) +} + impl FocusId { /// Obtains whether the element associated with this handle is currently focused. pub fn is_focused(&self, cx: &WindowContext) -> bool { @@ -829,15 +834,12 @@ impl<'a> WindowContext<'a> { mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { let order = self.window.next_frame.z_index_stack.clone(); - let handler = FRAME_ARENA - .with_borrow_mut(|arena| { - arena.alloc( - move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { - handler(event.downcast_ref().unwrap(), phase, cx) - }, - ) - }) - .map(|handler| handler as _); + let handler = frame_alloc(|| { + move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { + handler(event.downcast_ref().unwrap(), phase, cx) + } + }) + .map(|handler| handler as _); self.window .next_frame .mouse_listeners @@ -856,15 +858,14 @@ impl<'a> WindowContext<'a> { &mut self, listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = FRAME_ARENA - .with_borrow_mut(|arena| { - arena.alloc(move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { - if let Some(event) = event.downcast_ref::() { - listener(event, phase, cx) - } - }) - }) - .map(|handler| handler as _); + let listener = frame_alloc(|| { + move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { + if let Some(event) = event.downcast_ref::() { + listener(event, phase, cx) + } + } + }) + .map(|handler| handler as _); self.window.next_frame.dispatch_tree.on_key_event(listener); } @@ -879,9 +880,7 @@ impl<'a> WindowContext<'a> { action_type: TypeId, listener: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = FRAME_ARENA - .with_borrow_mut(|arena| arena.alloc(listener)) - .map(|handler| handler as _); + let listener = frame_alloc(|| listener).map(|handler| handler as _); self.window .next_frame .dispatch_tree @@ -1286,15 +1285,12 @@ impl<'a> WindowContext<'a> { cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| { for (action_type, action_listeners) in &cx.app.global_action_listeners { for action_listener in action_listeners.iter().cloned() { - let listener = FRAME_ARENA - .with_borrow_mut(|arena| { - arena.alloc( - move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { - action_listener(action, phase, cx) - }, - ) - }) - .map(|listener| listener as _); + let listener = frame_alloc(|| { + move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { + action_listener(action, phase, cx) + } + }) + .map(|listener| listener as _); cx.window .next_frame .dispatch_tree From 7e21e0f0eb43ed57e8b2371f7c05b2e6a8c93e34 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 18 Dec 2023 13:05:25 +0200 Subject: [PATCH 099/644] Do not panic on non-worktree file indexing --- crates/project/src/worktree.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index c721d127ad..8b9fdd2c65 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -963,12 +963,19 @@ impl LocalWorktree { let mut index_task = None; let snapshot = this.read_with(&cx, |this, _| this.as_local().unwrap().snapshot()); if let Some(repo) = snapshot.repository_for_path(&path) { - let repo_path = repo.work_directory.relativize(&snapshot, &path).unwrap(); - if let Some(repo) = snapshot.git_repositories.get(&*repo.work_directory) { - let repo = repo.repo_ptr.clone(); - index_task = Some( - cx.background() - .spawn(async move { repo.lock().load_index_text(&repo_path) }), + if let Some(repo_path) = repo.work_directory.relativize(&snapshot, &path) { + if let Some(repo) = snapshot.git_repositories.get(&*repo.work_directory) { + let repo = repo.repo_ptr.clone(); + index_task = Some( + cx.background() + .spawn(async move { repo.lock().load_index_text(&repo_path) }), + ); + } + } else { + log::warn!( + "Skipping loading index text from path {:?} is not in repository {:?}", + path, + repo.work_directory, ); } } From b4042feccd22a9343ccd0c57f5f24edf45c99110 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 18 Dec 2023 10:44:34 -0500 Subject: [PATCH 100/644] Unbork project search focus --- crates/search2/src/project_search.rs | 131 ++++++++++++++++++--------- crates/workspace2/src/workspace2.rs | 89 +++++++----------- 2 files changed, 117 insertions(+), 103 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 7bd60891ce..284875c7f5 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -13,9 +13,9 @@ use editor::{ use editor::{EditorElement, EditorStyle}; use gpui::{ actions, div, AnyElement, AnyView, AppContext, Context as _, Div, Element, EntityId, - EventEmitter, FocusableView, FontStyle, FontWeight, InteractiveElement, IntoElement, - KeyContext, Model, ModelContext, ParentElement, PromptLevel, Render, SharedString, Styled, - Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakModel, WeakView, + EventEmitter, FocusHandle, FocusableView, FontStyle, FontWeight, InteractiveElement, + IntoElement, KeyContext, Model, ModelContext, ParentElement, PromptLevel, Render, SharedString, + Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakModel, WeakView, WhiteSpace, WindowContext, }; use menu::Confirm; @@ -91,6 +91,7 @@ enum InputPanel { } pub struct ProjectSearchView { + focus_handle: FocusHandle, model: Model, query_editor: View, replacement_editor: View, @@ -107,6 +108,7 @@ pub struct ProjectSearchView { filters_enabled: bool, replace_enabled: bool, current_mode: SearchMode, + _subscriptions: Vec, } struct SemanticState { @@ -284,6 +286,7 @@ impl Render for ProjectSearchView { div() .flex_1() .size_full() + .track_focus(&self.focus_handle) .child(self.results_editor.clone()) .into_any() } else { @@ -359,10 +362,10 @@ impl Render for ProjectSearchView { .child(Label::new(text).size(LabelSize::Small)) }); v_stack() - .track_focus(&self.query_editor.focus_handle(cx)) .flex_1() .size_full() .justify_center() + .track_focus(&self.focus_handle) .child( h_stack() .size_full() @@ -377,12 +380,8 @@ impl Render for ProjectSearchView { } impl FocusableView for ProjectSearchView { - fn focus_handle(&self, cx: &AppContext) -> gpui::FocusHandle { - if self.has_matches() { - self.results_editor.focus_handle(cx) - } else { - self.query_editor.focus_handle(cx) - } + fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle { + self.focus_handle.clone() } } @@ -783,6 +782,7 @@ impl ProjectSearchView { let excerpts; let mut replacement_text = None; let mut query_text = String::new(); + let mut subscriptions = Vec::new(); // Read in settings if available let (mut options, current_mode, filters_enabled) = if let Some(settings) = settings { @@ -805,8 +805,7 @@ impl ProjectSearchView { options = SearchOptions::from_query(active_query); } } - cx.observe(&model, |this, _, cx| this.model_changed(cx)) - .detach(); + subscriptions.push(cx.observe(&model, |this, _, cx| this.model_changed(cx))); let query_editor = cx.build_view(|cx| { let mut editor = Editor::single_line(cx); @@ -815,10 +814,11 @@ impl ProjectSearchView { editor }); // Subscribe to query_editor in order to reraise editor events for workspace item activation purposes - cx.subscribe(&query_editor, |_, _, event: &EditorEvent, cx| { - cx.emit(ViewEvent::EditorEvent(event.clone())) - }) - .detach(); + subscriptions.push( + cx.subscribe(&query_editor, |_, _, event: &EditorEvent, cx| { + cx.emit(ViewEvent::EditorEvent(event.clone())) + }), + ); let replacement_editor = cx.build_view(|cx| { let mut editor = Editor::single_line(cx); editor.set_placeholder_text("Replace in project..", cx); @@ -832,17 +832,17 @@ impl ProjectSearchView { editor.set_searchable(false); editor }); - cx.observe(&results_editor, |_, _, cx| cx.emit(ViewEvent::UpdateTab)) - .detach(); + subscriptions.push(cx.observe(&results_editor, |_, _, cx| cx.emit(ViewEvent::UpdateTab))); - cx.subscribe(&results_editor, |this, _, event: &EditorEvent, cx| { - if matches!(event, editor::EditorEvent::SelectionsChanged { .. }) { - this.update_match_index(cx); - } - // Reraise editor events for workspace item activation purposes - cx.emit(ViewEvent::EditorEvent(event.clone())); - }) - .detach(); + subscriptions.push( + cx.subscribe(&results_editor, |this, _, event: &EditorEvent, cx| { + if matches!(event, editor::EditorEvent::SelectionsChanged { .. }) { + this.update_match_index(cx); + } + // Reraise editor events for workspace item activation purposes + cx.emit(ViewEvent::EditorEvent(event.clone())); + }), + ); let included_files_editor = cx.build_view(|cx| { let mut editor = Editor::single_line(cx); @@ -851,10 +851,11 @@ impl ProjectSearchView { editor }); // Subscribe to include_files_editor in order to reraise editor events for workspace item activation purposes - cx.subscribe(&included_files_editor, |_, _, event: &EditorEvent, cx| { - cx.emit(ViewEvent::EditorEvent(event.clone())) - }) - .detach(); + subscriptions.push( + cx.subscribe(&included_files_editor, |_, _, event: &EditorEvent, cx| { + cx.emit(ViewEvent::EditorEvent(event.clone())) + }), + ); let excluded_files_editor = cx.build_view(|cx| { let mut editor = Editor::single_line(cx); @@ -863,13 +864,26 @@ impl ProjectSearchView { editor }); // Subscribe to excluded_files_editor in order to reraise editor events for workspace item activation purposes - cx.subscribe(&excluded_files_editor, |_, _, event: &EditorEvent, cx| { - cx.emit(ViewEvent::EditorEvent(event.clone())) - }) - .detach(); + subscriptions.push( + cx.subscribe(&excluded_files_editor, |_, _, event: &EditorEvent, cx| { + cx.emit(ViewEvent::EditorEvent(event.clone())) + }), + ); + + let focus_handle = cx.focus_handle(); + subscriptions.push(cx.on_focus_in(&focus_handle, |this, cx| { + if this.focus_handle.is_focused(cx) { + if this.has_matches() { + this.results_editor.focus_handle(cx).focus(cx); + } else { + this.query_editor.focus_handle(cx).focus(cx); + } + } + })); // Check if Worktrees have all been previously indexed let mut this = ProjectSearchView { + focus_handle, replacement_editor, search_id: model.read(cx).search_id, model, @@ -886,6 +900,7 @@ impl ProjectSearchView { filters_enabled, current_mode, replace_enabled: false, + _subscriptions: subscriptions, }; this.model_changed(cx); this @@ -1186,6 +1201,7 @@ impl ProjectSearchBar { subscription: Default::default(), } } + fn cycle_mode(&self, _: &CycleMode, cx: &mut ViewContext) { if let Some(view) = self.active_project_search.as_ref() { view.update(cx, |this, cx| { @@ -1197,6 +1213,7 @@ impl ProjectSearchBar { }); } } + fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext) { if let Some(search_view) = self.active_project_search.as_ref() { search_view.update(cx, |search_view, cx| { @@ -1307,6 +1324,7 @@ impl ProjectSearchBar { false } } + fn toggle_replace(&mut self, _: &ToggleReplace, cx: &mut ViewContext) { if let Some(search) = &self.active_project_search { search.update(cx, |this, cx| { @@ -1400,6 +1418,7 @@ impl ProjectSearchBar { }); } } + fn new_placeholder_text(&self, cx: &mut ViewContext) -> Option { let previous_query_keystrokes = cx .bindings_for_action(&PreviousHistoryQuery {}) @@ -2305,6 +2324,7 @@ pub mod tests { let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.clone(); + let search_bar = window.build_view(cx, |_| ProjectSearchBar::new()); let active_item = cx.read(|cx| { workspace @@ -2320,8 +2340,14 @@ pub mod tests { "Expected no search panel to be active" ); - workspace - .update(cx, |workspace, cx| { + window + .update(cx, move |workspace, cx| { + assert_eq!(workspace.panes().len(), 1); + workspace.panes()[0].update(cx, move |pane, cx| { + pane.toolbar() + .update(cx, |toolbar, cx| toolbar.add_item(search_bar, cx)) + }); + ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx) }) .unwrap(); @@ -2600,6 +2626,7 @@ pub mod tests { }); let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx).unwrap(); + let search_bar = window.build_view(cx, |_| ProjectSearchBar::new()); let active_item = cx.read(|cx| { workspace @@ -2614,6 +2641,16 @@ pub mod tests { "Expected no search panel to be active" ); + window + .update(cx, move |workspace, cx| { + assert_eq!(workspace.panes().len(), 1); + workspace.panes()[0].update(cx, move |pane, cx| { + pane.toolbar() + .update(cx, |toolbar, cx| toolbar.add_item(search_bar, cx)) + }); + }) + .unwrap(); + let one_file_entry = cx.update(|cx| { workspace .read(cx) @@ -2734,9 +2771,20 @@ pub mod tests { let project = Project::test(fs.clone(), ["/dir".as_ref()], cx).await; let window = cx.add_window(|cx| Workspace::test_new(project, cx)); let workspace = window.root(cx).unwrap(); + let search_bar = window.build_view(cx, |_| ProjectSearchBar::new()); + window - .update(cx, |workspace, cx| { - ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx) + .update(cx, { + let search_bar = search_bar.clone(); + move |workspace, cx| { + assert_eq!(workspace.panes().len(), 1); + workspace.panes()[0].update(cx, move |pane, cx| { + pane.toolbar() + .update(cx, |toolbar, cx| toolbar.add_item(search_bar, cx)) + }); + + ProjectSearchView::deploy(workspace, &workspace::NewSearch, cx) + } }) .unwrap(); @@ -2750,13 +2798,6 @@ pub mod tests { .expect("Search view expected to appear after new search event trigger") }); - let search_bar = window.build_view(cx, |cx| { - let mut search_bar = ProjectSearchBar::new(); - search_bar.set_active_pane_item(Some(&search_view), cx); - // search_bar.show(cx); - search_bar - }); - // Add 3 search items into the history + another unsubmitted one. window .update(cx, |_, cx| { diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 866762e7d5..061a6aed3f 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -3556,8 +3556,6 @@ impl Render for Workspace { ) }; - let theme = cx.theme().clone(); - let colors = theme.colors(); cx.set_rem_size(ui_font_size); self.actions(div(), cx) @@ -3570,10 +3568,10 @@ impl Render for Workspace { .gap_0() .justify_start() .items_start() - .text_color(colors.text) - .bg(colors.background) + .text_color(cx.theme().colors().text) + .bg(cx.theme().colors().background) .border() - .border_color(colors.border) + .border_color(cx.theme().colors().border) .children(self.titlebar_item.clone()) .child( div() @@ -3586,7 +3584,7 @@ impl Render for Workspace { .overflow_hidden() .border_t() .border_b() - .border_color(colors.border) + .border_color(cx.theme().colors().border) .child( canvas(cx.listener(|workspace, bounds, _| { workspace.bounds = *bounds; @@ -3625,15 +3623,13 @@ impl Render for Workspace { .flex_row() .h_full() // Left Dock - .children(self.zoomed_position.ne(&Some(DockPosition::Left)).then( - || { - div() - .flex() - .flex_none() - .overflow_hidden() - .child(self.left_dock.clone()) - }, - )) + .child( + div() + .flex() + .flex_none() + .overflow_hidden() + .child(self.left_dock.clone()), + ) // Panes .child( div() @@ -3641,52 +3637,29 @@ impl Render for Workspace { .flex_col() .flex_1() .overflow_hidden() - .child(self.center.render( - &self.project, - &self.follower_states, - self.active_call(), - &self.active_pane, - self.zoomed.as_ref(), - &self.app_state, - cx, - )) - .children( - self.zoomed_position - .ne(&Some(DockPosition::Bottom)) - .then(|| self.bottom_dock.clone()), - ), + .child({ + self.center.render( + &self.project, + &self.follower_states, + self.active_call(), + &self.active_pane, + self.zoomed.as_ref(), + &self.app_state, + cx, + ) + }) + .child(self.bottom_dock.clone()), ) // Right Dock - .children(self.zoomed_position.ne(&Some(DockPosition::Right)).then( - || { - div() - .flex() - .flex_none() - .overflow_hidden() - .child(self.right_dock.clone()) - }, - )), + .child( + div() + .flex() + .flex_none() + .overflow_hidden() + .child(self.right_dock.clone()), + ), ) - .children(self.render_notifications(cx)) - .children(self.zoomed.as_ref().and_then(|view| { - let zoomed_view = view.upgrade()?; - let div = div() - .z_index(1) - .absolute() - .overflow_hidden() - .border_color(colors.border) - .bg(colors.background) - .child(zoomed_view) - .inset_0() - .shadow_lg(); - - Some(match self.zoomed_position { - Some(DockPosition::Left) => div.right_2().border_r(), - Some(DockPosition::Right) => div.left_2().border_l(), - Some(DockPosition::Bottom) => div.top_2().border_t(), - None => div.top_2().bottom_2().left_2().right_2().border(), - }) - })), + .children(self.render_notifications(cx)), ) .child(self.status_bar.clone()) } From 02bcc7bbeb484bb9715a1936cfd380e22edd63c6 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 18 Dec 2023 11:09:54 -0500 Subject: [PATCH 101/644] Add release channel to zed2 collab server --- crates/collab2/src/api.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/collab2/src/api.rs b/crates/collab2/src/api.rs index a84fcf328b..8d286388cf 100644 --- a/crates/collab2/src/api.rs +++ b/crates/collab2/src/api.rs @@ -116,12 +116,13 @@ struct CreateUserResponse { #[derive(Debug, Deserialize)] struct Panic { version: String, + release_channel: String, text: String, } #[instrument(skip(panic))] async fn trace_panic(panic: Json) -> Result<()> { - tracing::error!(version = %panic.version, text = %panic.text, "panic report"); + tracing::error!(version = %panic.version, release_channel = %panic.release_channel, text = %panic.text, "panic report"); Ok(()) } From 7cd6825eee83af355699096436e40b3531d98a30 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 18 Dec 2023 11:12:23 -0500 Subject: [PATCH 102/644] Add backtrace hash to collab server panic api --- crates/collab/src/api.rs | 3 ++- crates/collab2/src/api.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/collab/src/api.rs b/crates/collab/src/api.rs index 8d286388cf..a28aeac9ab 100644 --- a/crates/collab/src/api.rs +++ b/crates/collab/src/api.rs @@ -117,12 +117,13 @@ struct CreateUserResponse { struct Panic { version: String, release_channel: String, + backtrace_hash: String, text: String, } #[instrument(skip(panic))] async fn trace_panic(panic: Json) -> Result<()> { - tracing::error!(version = %panic.version, release_channel = %panic.release_channel, text = %panic.text, "panic report"); + tracing::error!(version = %panic.version, release_channel = %panic.release_channel, backtrace_hash = %panic.backtrace_hash, text = %panic.text, "panic report"); Ok(()) } diff --git a/crates/collab2/src/api.rs b/crates/collab2/src/api.rs index 8d286388cf..a28aeac9ab 100644 --- a/crates/collab2/src/api.rs +++ b/crates/collab2/src/api.rs @@ -117,12 +117,13 @@ struct CreateUserResponse { struct Panic { version: String, release_channel: String, + backtrace_hash: String, text: String, } #[instrument(skip(panic))] async fn trace_panic(panic: Json) -> Result<()> { - tracing::error!(version = %panic.version, release_channel = %panic.release_channel, text = %panic.text, "panic report"); + tracing::error!(version = %panic.version, release_channel = %panic.release_channel, backtrace_hash = %panic.backtrace_hash, text = %panic.text, "panic report"); Ok(()) } From b46f5be490f35132bd38cce235bd731f6cef2562 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 11:16:00 -0500 Subject: [PATCH 103/644] Style One Dark wrap guides --- crates/theme2/src/one_themes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/theme2/src/one_themes.rs b/crates/theme2/src/one_themes.rs index 23b3ff5089..72411dc40c 100644 --- a/crates/theme2/src/one_themes.rs +++ b/crates/theme2/src/one_themes.rs @@ -86,8 +86,8 @@ pub(crate) fn one_dark() -> Theme { editor_line_number: hsla(222.0 / 360., 11.5 / 100., 34.1 / 100., 1.0), editor_active_line_number: hsla(216.0 / 360., 5.9 / 100., 49.6 / 100., 1.0), editor_invisible: hsla(222.0 / 360., 11.5 / 100., 34.1 / 100., 1.0), - editor_wrap_guide: gpui::black(), - editor_active_wrap_guide: gpui::red(), + editor_wrap_guide: hsla(228. / 360., 8. / 100., 25. / 100., 1.), + editor_active_wrap_guide: hsla(228. / 360., 8. / 100., 25. / 100., 1.), editor_document_highlight_read_background: hsla( 207.8 / 360., 81. / 100., From da7628cc1e644b2c376943e6330a616a0d0120ef Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 11:16:22 -0500 Subject: [PATCH 104/644] Style wrap guides for imported themes --- crates/theme2/src/themes/andromeda.rs | 4 ++++ crates/theme2/src/themes/ayu.rs | 6 +++++ crates/theme2/src/themes/dracula.rs | 2 ++ crates/theme2/src/themes/gruvbox.rs | 12 ++++++++++ crates/theme2/src/themes/night_owl.rs | 4 ++++ crates/theme2/src/themes/noctis.rs | 22 +++++++++++++++++++ crates/theme2/src/themes/nord.rs | 2 ++ crates/theme2/src/themes/palenight.rs | 6 +++++ crates/theme2/src/themes/rose_pine.rs | 6 +++++ crates/theme2/src/themes/solarized.rs | 4 ++++ crates/theme_importer/src/vscode/converter.rs | 2 ++ script/import-themes | 3 +++ 12 files changed, 73 insertions(+) create mode 100755 script/import-themes diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index 32bccf172a..513b6f0212 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -52,6 +52,8 @@ pub fn andromeda() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x23262eff).into()), editor_line_number: Some(rgba(0x746f77ff).into()), editor_active_line_number: Some(rgba(0xd5ced9ff).into()), + editor_wrap_guide: Some(rgba(0x1b1d23ff).into()), + editor_active_wrap_guide: Some(rgba(0x1b1d23ff).into()), terminal_ansi_bright_red: Some(rgba(0xee5d43ff).into()), terminal_ansi_bright_green: Some(rgba(0x96e072ff).into()), terminal_ansi_bright_yellow: Some(rgba(0xffe66dff).into()), @@ -267,6 +269,8 @@ pub fn andromeda() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x262a33ff).into()), editor_line_number: Some(rgba(0x746f77ff).into()), editor_active_line_number: Some(rgba(0xd5ced9ff).into()), + editor_wrap_guide: Some(rgba(0x1b1d23ff).into()), + editor_active_wrap_guide: Some(rgba(0x1b1d23ff).into()), terminal_ansi_bright_red: Some(rgba(0xee5d43ff).into()), terminal_ansi_bright_green: Some(rgba(0x96e072ff).into()), terminal_ansi_bright_yellow: Some(rgba(0xffe66dff).into()), diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index 4c5d951230..79aed9e1b5 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -51,6 +51,8 @@ pub fn ayu() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xf8f9faff).into()), editor_line_number: Some(rgba(0x8a919966).into()), editor_active_line_number: Some(rgba(0x5c6166ff).into()), + editor_wrap_guide: Some(rgba(0x6b7d8f1f).into()), + editor_active_wrap_guide: Some(rgba(0x6b7d8f1f).into()), terminal_background: Some(rgba(0xf8f9faff).into()), terminal_ansi_bright_black: Some(rgba(0x686868ff).into()), terminal_ansi_bright_red: Some(rgba(0xf07171ff).into()), @@ -358,6 +360,8 @@ pub fn ayu() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x1f2430ff).into()), editor_line_number: Some(rgba(0x8a919966).into()), editor_active_line_number: Some(rgba(0xcccac2ff).into()), + editor_wrap_guide: Some(rgba(0x171b24ff).into()), + editor_active_wrap_guide: Some(rgba(0x171b24ff).into()), terminal_background: Some(rgba(0x1f2430ff).into()), terminal_ansi_bright_black: Some(rgba(0x686868ff).into()), terminal_ansi_bright_red: Some(rgba(0xf28779ff).into()), @@ -665,6 +669,8 @@ pub fn ayu() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x0b0e14ff).into()), editor_line_number: Some(rgba(0x6c738099).into()), editor_active_line_number: Some(rgba(0xbfbdb6ff).into()), + editor_wrap_guide: Some(rgba(0x1e232bff).into()), + editor_active_wrap_guide: Some(rgba(0x1e232bff).into()), terminal_background: Some(rgba(0x0b0e14ff).into()), terminal_ansi_bright_black: Some(rgba(0x686868ff).into()), terminal_ansi_bright_red: Some(rgba(0xf07178ff).into()), diff --git a/crates/theme2/src/themes/dracula.rs b/crates/theme2/src/themes/dracula.rs index 3fabb67ec2..9d9da27eed 100644 --- a/crates/theme2/src/themes/dracula.rs +++ b/crates/theme2/src/themes/dracula.rs @@ -48,6 +48,8 @@ pub fn dracula() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x282a36ff).into()), editor_line_number: Some(rgba(0x6272a4ff).into()), editor_active_line_number: Some(rgba(0xf8f8f2ff).into()), + editor_wrap_guide: Some(rgba(0xbd93f9ff).into()), + editor_active_wrap_guide: Some(rgba(0xbd93f9ff).into()), terminal_background: Some(rgba(0x282a36ff).into()), terminal_ansi_bright_black: Some(rgba(0x6272a4ff).into()), terminal_ansi_bright_red: Some(rgba(0xff6e6eff).into()), diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 2c96665534..35f5b31aa2 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -51,6 +51,8 @@ pub fn gruvbox() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x1d2021ff).into()), editor_line_number: Some(rgba(0x665c54ff).into()), editor_active_line_number: Some(rgba(0xebdbb2ff).into()), + editor_wrap_guide: Some(rgba(0x3c3836ff).into()), + editor_active_wrap_guide: Some(rgba(0x3c3836ff).into()), terminal_background: Some(rgba(0x1d2021ff).into()), terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), terminal_ansi_bright_red: Some(rgba(0xfb4934ff).into()), @@ -344,6 +346,8 @@ pub fn gruvbox() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x282828ff).into()), editor_line_number: Some(rgba(0x665c54ff).into()), editor_active_line_number: Some(rgba(0xebdbb2ff).into()), + editor_wrap_guide: Some(rgba(0x3c3836ff).into()), + editor_active_wrap_guide: Some(rgba(0x3c3836ff).into()), terminal_background: Some(rgba(0x282828ff).into()), terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), terminal_ansi_bright_red: Some(rgba(0xfb4934ff).into()), @@ -637,6 +641,8 @@ pub fn gruvbox() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x32302fff).into()), editor_line_number: Some(rgba(0x665c54ff).into()), editor_active_line_number: Some(rgba(0xebdbb2ff).into()), + editor_wrap_guide: Some(rgba(0x3c3836ff).into()), + editor_active_wrap_guide: Some(rgba(0x3c3836ff).into()), terminal_background: Some(rgba(0x32302fff).into()), terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), terminal_ansi_bright_red: Some(rgba(0xfb4934ff).into()), @@ -930,6 +936,8 @@ pub fn gruvbox() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xf9f5d7ff).into()), editor_line_number: Some(rgba(0xbdae93ff).into()), editor_active_line_number: Some(rgba(0x3c3836ff).into()), + editor_wrap_guide: Some(rgba(0xebdbb2ff).into()), + editor_active_wrap_guide: Some(rgba(0xebdbb2ff).into()), terminal_background: Some(rgba(0xf9f5d7ff).into()), terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), terminal_ansi_bright_red: Some(rgba(0x9d0006ff).into()), @@ -1223,6 +1231,8 @@ pub fn gruvbox() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xfbf1c7ff).into()), editor_line_number: Some(rgba(0xbdae93ff).into()), editor_active_line_number: Some(rgba(0x3c3836ff).into()), + editor_wrap_guide: Some(rgba(0xebdbb2ff).into()), + editor_active_wrap_guide: Some(rgba(0xebdbb2ff).into()), terminal_background: Some(rgba(0xfbf1c7ff).into()), terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), terminal_ansi_bright_red: Some(rgba(0x9d0006ff).into()), @@ -1516,6 +1526,8 @@ pub fn gruvbox() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xf2e5bcff).into()), editor_line_number: Some(rgba(0xbdae93ff).into()), editor_active_line_number: Some(rgba(0x3c3836ff).into()), + editor_wrap_guide: Some(rgba(0xebdbb2ff).into()), + editor_active_wrap_guide: Some(rgba(0xebdbb2ff).into()), terminal_background: Some(rgba(0xf2e5bcff).into()), terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), terminal_ansi_bright_red: Some(rgba(0x9d0006ff).into()), diff --git a/crates/theme2/src/themes/night_owl.rs b/crates/theme2/src/themes/night_owl.rs index 778dfabeb8..437f79d4c7 100644 --- a/crates/theme2/src/themes/night_owl.rs +++ b/crates/theme2/src/themes/night_owl.rs @@ -51,6 +51,8 @@ pub fn night_owl() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x011627ff).into()), editor_line_number: Some(rgba(0x4b6479ff).into()), editor_active_line_number: Some(rgba(0xd6deebff).into()), + editor_wrap_guide: Some(rgba(0x5f7e97ff).into()), + editor_active_wrap_guide: Some(rgba(0x5f7e97ff).into()), terminal_ansi_bright_black: Some(rgba(0x575656ff).into()), terminal_ansi_bright_red: Some(rgba(0xef5350ff).into()), terminal_ansi_bright_green: Some(rgba(0x22da6eff).into()), @@ -311,6 +313,8 @@ pub fn night_owl() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xfbfbfbff).into()), editor_line_number: Some(rgba(0x90a7b2ff).into()), editor_active_line_number: Some(rgba(0x403f53ff).into()), + editor_wrap_guide: Some(rgba(0xd9d9d9ff).into()), + editor_active_wrap_guide: Some(rgba(0xd9d9d9ff).into()), terminal_background: Some(rgba(0xf6f6f6ff).into()), terminal_ansi_bright_black: Some(rgba(0x403f53ff).into()), terminal_ansi_bright_red: Some(rgba(0xde3d3bff).into()), diff --git a/crates/theme2/src/themes/noctis.rs b/crates/theme2/src/themes/noctis.rs index 614553593d..273b52a34a 100644 --- a/crates/theme2/src/themes/noctis.rs +++ b/crates/theme2/src/themes/noctis.rs @@ -52,6 +52,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x07273bff).into()), editor_line_number: Some(rgba(0x4d6c80ff).into()), editor_active_line_number: Some(rgba(0xbecfdaff).into()), + editor_wrap_guide: Some(rgba(0x1679b6ff).into()), + editor_active_wrap_guide: Some(rgba(0x1679b6ff).into()), terminal_background: Some(rgba(0x051b29ff).into()), terminal_ansi_bright_black: Some(rgba(0x475e6cff).into()), terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), @@ -330,6 +332,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x322a2dff).into()), editor_line_number: Some(rgba(0x715b63ff).into()), editor_active_line_number: Some(rgba(0xcbbec2ff).into()), + editor_wrap_guide: Some(rgba(0x997582ff).into()), + editor_active_wrap_guide: Some(rgba(0x997582ff).into()), terminal_background: Some(rgba(0x272022ff).into()), terminal_ansi_bright_black: Some(rgba(0x69545bff).into()), terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), @@ -608,6 +612,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xf4f6f6ff).into()), editor_line_number: Some(rgba(0xa0abacff).into()), editor_active_line_number: Some(rgba(0x005661ff).into()), + editor_wrap_guide: Some(rgba(0x00c6e0ff).into()), + editor_active_wrap_guide: Some(rgba(0x00c6e0ff).into()), terminal_background: Some(rgba(0xe1eeefff).into()), terminal_ansi_bright_black: Some(rgba(0x004d57ff).into()), terminal_ansi_bright_red: Some(rgba(0xff4000ff).into()), @@ -886,6 +892,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xf2f1f8ff).into()), editor_line_number: Some(rgba(0x9d9ab1ff).into()), editor_active_line_number: Some(rgba(0x0c006bff).into()), + editor_wrap_guide: Some(rgba(0xaea4f4ff).into()), + editor_active_wrap_guide: Some(rgba(0xaea4f4ff).into()), terminal_background: Some(rgba(0xe9e7f3ff).into()), terminal_ansi_bright_black: Some(rgba(0x0f0080ff).into()), terminal_ansi_bright_red: Some(rgba(0xff4000ff).into()), @@ -1164,6 +1172,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xfef8ecff).into()), editor_line_number: Some(rgba(0xa0abacff).into()), editor_active_line_number: Some(rgba(0x005661ff).into()), + editor_wrap_guide: Some(rgba(0x00c6e0ff).into()), + editor_active_wrap_guide: Some(rgba(0x00c6e0ff).into()), terminal_background: Some(rgba(0xf6eddaff).into()), terminal_ansi_bright_black: Some(rgba(0x004d57ff).into()), terminal_ansi_bright_red: Some(rgba(0xff4000ff).into()), @@ -1442,6 +1452,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x1b2932ff).into()), editor_line_number: Some(rgba(0x5d6e79ff).into()), editor_active_line_number: Some(rgba(0xc5cdd3ff).into()), + editor_wrap_guide: Some(rgba(0x496d83ff).into()), + editor_active_wrap_guide: Some(rgba(0x496d83ff).into()), terminal_background: Some(rgba(0x0e1920ff).into()), terminal_ansi_bright_black: Some(rgba(0x425866ff).into()), terminal_ansi_bright_red: Some(rgba(0xca8468ff).into()), @@ -1720,6 +1732,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x052529ff).into()), editor_line_number: Some(rgba(0x4e6b6eff).into()), editor_active_line_number: Some(rgba(0xb2cacdff).into()), + editor_wrap_guide: Some(rgba(0x0e6671ff).into()), + editor_active_wrap_guide: Some(rgba(0x0e6671ff).into()), terminal_background: Some(rgba(0x03191bff).into()), terminal_ansi_bright_black: Some(rgba(0x47686cff).into()), terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), @@ -1998,6 +2012,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x031417ff).into()), editor_line_number: Some(rgba(0x4e6b6eff).into()), editor_active_line_number: Some(rgba(0xb2cacdff).into()), + editor_wrap_guide: Some(rgba(0x0e6671ff).into()), + editor_active_wrap_guide: Some(rgba(0x0e6671ff).into()), terminal_background: Some(rgba(0x020c0eff).into()), terminal_ansi_bright_black: Some(rgba(0x47686cff).into()), terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), @@ -2276,6 +2292,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x031417ff).into()), editor_line_number: Some(rgba(0x4e6b6eff).into()), editor_active_line_number: Some(rgba(0xb2cacdff).into()), + editor_wrap_guide: Some(rgba(0x0e6671ff).into()), + editor_active_wrap_guide: Some(rgba(0x0e6671ff).into()), terminal_background: Some(rgba(0x020c0eff).into()), terminal_ansi_bright_black: Some(rgba(0x47686cff).into()), terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), @@ -2554,6 +2572,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x292640ff).into()), editor_line_number: Some(rgba(0x5c5973ff).into()), editor_active_line_number: Some(rgba(0xc5c2d6ff).into()), + editor_wrap_guide: Some(rgba(0x6e67a8ff).into()), + editor_active_wrap_guide: Some(rgba(0x6e67a8ff).into()), terminal_background: Some(rgba(0x1f1d30ff).into()), terminal_ansi_bright_black: Some(rgba(0x504e65ff).into()), terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), @@ -2832,6 +2852,8 @@ pub fn noctis() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x30243dff).into()), editor_line_number: Some(rgba(0x665973ff).into()), editor_active_line_number: Some(rgba(0xccbfd9ff).into()), + editor_wrap_guide: Some(rgba(0x8767a8ff).into()), + editor_active_wrap_guide: Some(rgba(0x8767a8ff).into()), terminal_background: Some(rgba(0x291d35ff).into()), terminal_ansi_bright_black: Some(rgba(0x594e65ff).into()), terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), diff --git a/crates/theme2/src/themes/nord.rs b/crates/theme2/src/themes/nord.rs index f3d03b3889..83fafa7a87 100644 --- a/crates/theme2/src/themes/nord.rs +++ b/crates/theme2/src/themes/nord.rs @@ -51,6 +51,8 @@ pub fn nord() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x2e3440ff).into()), editor_line_number: Some(rgba(0x4c566aff).into()), editor_active_line_number: Some(rgba(0xd8dee9ff).into()), + editor_wrap_guide: Some(rgba(0x3b4252ff).into()), + editor_active_wrap_guide: Some(rgba(0x3b4252ff).into()), terminal_background: Some(rgba(0x2e3440ff).into()), terminal_ansi_bright_black: Some(rgba(0x4c566aff).into()), terminal_ansi_bright_red: Some(rgba(0xbf616aff).into()), diff --git a/crates/theme2/src/themes/palenight.rs b/crates/theme2/src/themes/palenight.rs index 501a678577..2fceb8055e 100644 --- a/crates/theme2/src/themes/palenight.rs +++ b/crates/theme2/src/themes/palenight.rs @@ -51,6 +51,8 @@ pub fn palenight() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), editor_active_line_number: Some(rgba(0xbfc7d5ff).into()), + editor_wrap_guide: Some(rgba(0x282b3cff).into()), + editor_active_wrap_guide: Some(rgba(0x282b3cff).into()), terminal_ansi_bright_black: Some(rgba(0x676e95ff).into()), terminal_ansi_bright_red: Some(rgba(0xff5572ff).into()), terminal_ansi_bright_green: Some(rgba(0xc3e88dff).into()), @@ -337,6 +339,8 @@ pub fn palenight() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), editor_active_line_number: Some(rgba(0xbfc7d5ff).into()), + editor_wrap_guide: Some(rgba(0x282b3cff).into()), + editor_active_wrap_guide: Some(rgba(0x282b3cff).into()), terminal_ansi_bright_black: Some(rgba(0x676e95ff).into()), terminal_ansi_bright_red: Some(rgba(0xff5572ff).into()), terminal_ansi_bright_green: Some(rgba(0xc3e88dff).into()), @@ -623,6 +627,8 @@ pub fn palenight() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x292d3eff).into()), editor_line_number: Some(rgba(0x4c5374ff).into()), editor_active_line_number: Some(rgba(0xbfc7d5ff).into()), + editor_wrap_guide: Some(rgba(0x2c2f40ff).into()), + editor_active_wrap_guide: Some(rgba(0x2c2f40ff).into()), terminal_ansi_bright_black: Some(rgba(0x676e95ff).into()), terminal_ansi_bright_red: Some(rgba(0xff5572ff).into()), terminal_ansi_bright_green: Some(rgba(0xc3e88dff).into()), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index a09364405f..51e3a2451c 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -52,6 +52,8 @@ pub fn rose_pine() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x191724ff).into()), editor_line_number: Some(rgba(0x908caaff).into()), editor_active_line_number: Some(rgba(0xe0def4ff).into()), + editor_wrap_guide: Some(rgba(0x00000000).into()), + editor_active_wrap_guide: Some(rgba(0x00000000).into()), terminal_ansi_bright_black: Some(rgba(0x908caaff).into()), terminal_ansi_bright_red: Some(rgba(0xeb6f92ff).into()), terminal_ansi_bright_green: Some(rgba(0x31748fff).into()), @@ -312,6 +314,8 @@ pub fn rose_pine() -> UserThemeFamily { editor_gutter_background: Some(rgba(0x232136ff).into()), editor_line_number: Some(rgba(0x908caaff).into()), editor_active_line_number: Some(rgba(0xe0def4ff).into()), + editor_wrap_guide: Some(rgba(0x00000000).into()), + editor_active_wrap_guide: Some(rgba(0x00000000).into()), terminal_ansi_bright_black: Some(rgba(0x908caaff).into()), terminal_ansi_bright_red: Some(rgba(0xeb6f92ff).into()), terminal_ansi_bright_green: Some(rgba(0x3e8fb0ff).into()), @@ -572,6 +576,8 @@ pub fn rose_pine() -> UserThemeFamily { editor_gutter_background: Some(rgba(0xfaf4edff).into()), editor_line_number: Some(rgba(0x797593ff).into()), editor_active_line_number: Some(rgba(0x575279ff).into()), + editor_wrap_guide: Some(rgba(0x00000000).into()), + editor_active_wrap_guide: Some(rgba(0x00000000).into()), terminal_ansi_bright_black: Some(rgba(0x797593ff).into()), terminal_ansi_bright_red: Some(rgba(0xb4637aff).into()), terminal_ansi_bright_green: Some(rgba(0x286983ff).into()), diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index 9807a6cd3d..8a5bf96c16 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -46,6 +46,8 @@ pub fn solarized() -> UserThemeFamily { editor_background: Some(rgba(0x002b36ff).into()), editor_gutter_background: Some(rgba(0x002b36ff).into()), editor_line_number: Some(rgba(0x566c74ff).into()), + editor_wrap_guide: Some(rgba(0x003847ff).into()), + editor_active_wrap_guide: Some(rgba(0x003847ff).into()), terminal_ansi_bright_black: Some(rgba(0x586e75ff).into()), terminal_ansi_bright_red: Some(rgba(0xcb4b16ff).into()), terminal_ansi_bright_green: Some(rgba(0x859900ff).into()), @@ -312,6 +314,8 @@ pub fn solarized() -> UserThemeFamily { editor_background: Some(rgba(0xfdf6e3ff).into()), editor_gutter_background: Some(rgba(0xfdf6e3ff).into()), editor_line_number: Some(rgba(0x9ca8a6ff).into()), + editor_wrap_guide: Some(rgba(0xddd6c1ff).into()), + editor_active_wrap_guide: Some(rgba(0xddd6c1ff).into()), terminal_ansi_bright_black: Some(rgba(0x657b83ff).into()), terminal_ansi_bright_red: Some(rgba(0xcb4b16ff).into()), terminal_ansi_bright_green: Some(rgba(0x859900ff).into()), diff --git a/crates/theme_importer/src/vscode/converter.rs b/crates/theme_importer/src/vscode/converter.rs index 46d9c3d086..f5a606b329 100644 --- a/crates/theme_importer/src/vscode/converter.rs +++ b/crates/theme_importer/src/vscode/converter.rs @@ -243,6 +243,8 @@ impl VsCodeThemeConverter { .editor_foreground .as_ref() .traverse(|color| try_parse_color(&color))?, + editor_wrap_guide: vscode_panel_border, + editor_active_wrap_guide: vscode_panel_border, scrollbar_track_background: vscode_editor_background, scrollbar_track_border: vscode_colors .editor_overview_ruler_border diff --git a/script/import-themes b/script/import-themes new file mode 100755 index 0000000000..ce9ce9ef12 --- /dev/null +++ b/script/import-themes @@ -0,0 +1,3 @@ +#!/bin/bash + +cargo run -p theme_importer From 4707248714ac29b9c5adee694d67f11c163a8a3c Mon Sep 17 00:00:00 2001 From: Julia <30666851+ForLoveOfCats@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:32:06 -0500 Subject: [PATCH 105/644] Revert accidental merge of old version of workspace2 render function (#3694) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Something happened with my local diff and https://github.com/zed-industries/zed/pull/3691 somehow contained an old version of workspace2's render function. Perhaps I rebased at some point and borked it? Not sure 🤷‍♀️ Release Notes: - N/A --- crates/workspace2/src/workspace2.rs | 89 +++++++++++++++++++---------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 617b5c51bf..8cb8c3dc9a 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -3534,6 +3534,8 @@ impl Render for Workspace { ) }; + let theme = cx.theme().clone(); + let colors = theme.colors(); cx.set_rem_size(ui_font_size); self.actions(div(), cx) @@ -3546,10 +3548,10 @@ impl Render for Workspace { .gap_0() .justify_start() .items_start() - .text_color(cx.theme().colors().text) - .bg(cx.theme().colors().background) + .text_color(colors.text) + .bg(colors.background) .border() - .border_color(cx.theme().colors().border) + .border_color(colors.border) .children(self.titlebar_item.clone()) .child( div() @@ -3562,7 +3564,7 @@ impl Render for Workspace { .overflow_hidden() .border_t() .border_b() - .border_color(cx.theme().colors().border) + .border_color(colors.border) .child( canvas(cx.listener(|workspace, bounds, _| { workspace.bounds = *bounds; @@ -3601,13 +3603,15 @@ impl Render for Workspace { .flex_row() .h_full() // Left Dock - .child( - div() - .flex() - .flex_none() - .overflow_hidden() - .child(self.left_dock.clone()), - ) + .children(self.zoomed_position.ne(&Some(DockPosition::Left)).then( + || { + div() + .flex() + .flex_none() + .overflow_hidden() + .child(self.left_dock.clone()) + }, + )) // Panes .child( div() @@ -3615,29 +3619,52 @@ impl Render for Workspace { .flex_col() .flex_1() .overflow_hidden() - .child({ - self.center.render( - &self.project, - &self.follower_states, - self.active_call(), - &self.active_pane, - self.zoomed.as_ref(), - &self.app_state, - cx, - ) - }) - .child(self.bottom_dock.clone()), + .child(self.center.render( + &self.project, + &self.follower_states, + self.active_call(), + &self.active_pane, + self.zoomed.as_ref(), + &self.app_state, + cx, + )) + .children( + self.zoomed_position + .ne(&Some(DockPosition::Bottom)) + .then(|| self.bottom_dock.clone()), + ), ) // Right Dock - .child( - div() - .flex() - .flex_none() - .overflow_hidden() - .child(self.right_dock.clone()), - ), + .children(self.zoomed_position.ne(&Some(DockPosition::Right)).then( + || { + div() + .flex() + .flex_none() + .overflow_hidden() + .child(self.right_dock.clone()) + }, + )), ) - .children(self.render_notifications(cx)), + .children(self.render_notifications(cx)) + .children(self.zoomed.as_ref().and_then(|view| { + let zoomed_view = view.upgrade()?; + let div = div() + .z_index(1) + .absolute() + .overflow_hidden() + .border_color(colors.border) + .bg(colors.background) + .child(zoomed_view) + .inset_0() + .shadow_lg(); + + Some(match self.zoomed_position { + Some(DockPosition::Left) => div.right_2().border_r(), + Some(DockPosition::Right) => div.left_2().border_l(), + Some(DockPosition::Bottom) => div.top_2().border_t(), + None => div.top_2().bottom_2().left_2().right_2().border(), + }) + })), ) .child(self.status_bar.clone()) } From 196df1c37889f3b220a41da4e5fd6f8024183b35 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 11:33:37 -0500 Subject: [PATCH 106/644] Start on collab panel empty state --- crates/collab_ui2/src/collab_panel.rs | 41 ++++++++++++++++++--------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 5f01d49878..a845e117d5 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2027,20 +2027,33 @@ impl CollabPanel { } fn render_signed_out(&mut self, cx: &mut ViewContext) -> Div { - v_stack().border_1().border_color(gpui::red()).child( - Button::new("sign_in", "Sign in to collaborate").on_click(cx.listener( - |this, _, cx| { - let client = this.client.clone(); - cx.spawn(|_, mut cx| async move { - client - .authenticate_and_connect(true, &cx) - .await - .notify_async_err(&mut cx); - }) - .detach() - }, - )), - ) + v_stack() + .justify_center() + .items_center() + .child(v_stack().gap_1().p_4() + .child( + Label::new("Work with your team with realtive collaborative editing, voice, shared notes and more.") + ) + .child( + Label::new("Sign in to enable collaboration.") + ) + .child( + Button::new("sign_in", "Sign in") + .style(ButtonStyle::Filled) + .full_width() + .on_click(cx.listener( + |this, _, cx| { + let client = this.client.clone(); + cx.spawn(|_, mut cx| async move { + client + .authenticate_and_connect(true, &cx) + .await + .notify_async_err(&mut cx); + }) + .detach() + }, + )), + )) } fn render_list_entry(&mut self, ix: usize, cx: &mut ViewContext) -> AnyElement { From 5900b815e1565325a7c79f1621e6e24a2fc0ac9f Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 12:53:08 -0500 Subject: [PATCH 107/644] Remove unimplemented toggling for project search entries (#3695) This PR removes the unimplemented toggling of search results in the project search. This is new functionality that didn't exist in Zed1, and it's likely that we won't be adding it before launch, so removing it for now. Release Notes: - N/A --- crates/editor2/src/element.rs | 41 ++++++++++------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 3af6281121..328f2f08ba 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2283,36 +2283,19 @@ impl EditorElement { .justify_between() .cursor_pointer() .hover(|style| style.bg(cx.theme().colors().element_hover)) - .on_click(cx.listener(|_editor, _event, _cx| { - // todo!() Implement collapsing path headers - // todo!("Clicking path header") - })) .child( - h_stack() - .gap_3() - // TODO: Add open/close state and toggle action - .child( - div().border().border_color(gpui::red()).child( - ButtonLike::new("path-header-disclosure-control") - .style(ButtonStyle::Subtle) - .child(IconElement::new(match is_open { - true => Icon::ChevronDown, - false => Icon::ChevronRight, - })), - ), - ) - .child( - h_stack() - .gap_2() - .child(Label::new( - filename - .map(SharedString::from) - .unwrap_or_else(|| "untitled".into()), - )) - .when_some(parent_path, |then, path| { - then.child(Label::new(path).color(Color::Muted)) - }), - ), + h_stack().gap_3().child( + h_stack() + .gap_2() + .child(Label::new( + filename + .map(SharedString::from) + .unwrap_or_else(|| "untitled".into()), + )) + .when_some(parent_path, |then, path| { + then.child(Label::new(path).color(Color::Muted)) + }), + ), ) .children(jump_handler.map(|jump_handler| { IconButton::new(block_id, Icon::ArrowUpRight) From d72cd3795aba48be2f4a0c37821eef12dc4a34d7 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 12:56:50 -0500 Subject: [PATCH 108/644] Fix implementation of full_width and icon_position in button --- crates/ui2/src/components/button/button.rs | 33 +++++++++++-------- .../ui2/src/components/button/button_like.rs | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/crates/ui2/src/components/button/button.rs b/crates/ui2/src/components/button/button.rs index fc7ca2c128..014a2f5362 100644 --- a/crates/ui2/src/components/button/button.rs +++ b/crates/ui2/src/components/button/button.rs @@ -151,26 +151,31 @@ impl RenderOnce for Button { self.base.child( h_stack() .gap_1() - .map(|this| { - if self.icon_position == Some(IconPosition::End) { - this.flex_row_reverse() - } else { - this - } + .when(self.icon_position.is_some(), |this| { + this.children(self.icon.map(|icon| { + ButtonIcon::new(icon) + .disabled(is_disabled) + .selected(is_selected) + .selected_icon(self.selected_icon) + .size(self.icon_size) + .color(self.icon_color) + })) }) .child( Label::new(label) .color(label_color) .line_height_style(LineHeightStyle::UILabel), ) - .children(self.icon.map(|icon| { - ButtonIcon::new(icon) - .disabled(is_disabled) - .selected(is_selected) - .selected_icon(self.selected_icon) - .size(self.icon_size) - .color(self.icon_color) - })), + .when(!self.icon_position.is_some(), |this| { + this.children(self.icon.map(|icon| { + ButtonIcon::new(icon) + .disabled(is_disabled) + .selected(is_selected) + .selected_icon(self.selected_icon) + .size(self.icon_size) + .color(self.icon_color) + })) + }), ) } } diff --git a/crates/ui2/src/components/button/button_like.rs b/crates/ui2/src/components/button/button_like.rs index 8255490476..54f2a0e9ea 100644 --- a/crates/ui2/src/components/button/button_like.rs +++ b/crates/ui2/src/components/button/button_like.rs @@ -355,7 +355,7 @@ impl RenderOnce for ButtonLike { .group("") .flex_none() .h(self.size.height()) - .when_some(self.width, |this, width| this.w(width)) + .when_some(self.width, |this, width| this.w(width).justify_center()) .rounded_md() .gap_1() .map(|this| match self.size { From eeaa1e5cf9a6ea0369bf237705439b392f9ad382 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 12:56:57 -0500 Subject: [PATCH 109/644] Add github icon --- assets/icons/github.svg | 1 + crates/ui2/src/components/icon.rs | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 assets/icons/github.svg diff --git a/assets/icons/github.svg b/assets/icons/github.svg new file mode 100644 index 0000000000..28148b9894 --- /dev/null +++ b/assets/icons/github.svg @@ -0,0 +1 @@ + diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index 6876630100..6216acac48 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -67,6 +67,7 @@ pub enum Icon { Folder, FolderOpen, FolderX, + Github, Hash, InlayHint, Link, @@ -147,6 +148,7 @@ impl Icon { Icon::Folder => "icons/file_icons/folder.svg", Icon::FolderOpen => "icons/file_icons/folder_open.svg", Icon::FolderX => "icons/stop_sharing.svg", + Icon::Github => "icons/github.svg", Icon::Hash => "icons/hash.svg", Icon::InlayHint => "icons/inlay_hint.svg", Icon::Link => "icons/link.svg", From cef9aa359079f74dd8ae44accf3e6a162a76b162 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 18 Dec 2023 18:58:40 +0100 Subject: [PATCH 110/644] Use a different frame arena for each window Co-Authored-By: Max Brunsfeld Co-Authored-By: Nathan Sobo --- crates/gpui2/src/window.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 337f61272f..e00c707de3 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -99,12 +99,12 @@ struct FocusEvent { slotmap::new_key_type! { pub struct FocusId; } thread_local! { - pub static FRAME_ARENA: RefCell = RefCell::new(Arena::new(16 * 1024 * 1024)); + pub static FRAME_ARENA: RefCell> = RefCell::new(None); } #[inline(always)] pub(crate) fn frame_alloc(f: impl FnOnce() -> T) -> ArenaRef { - FRAME_ARENA.with_borrow_mut(|arena| arena.alloc(f)) + FRAME_ARENA.with_borrow_mut(|arena| arena.as_mut().unwrap().alloc(f)) } impl FocusId { @@ -254,6 +254,7 @@ pub struct Window { pub(crate) element_id_stack: GlobalElementId, pub(crate) rendered_frame: Frame, pub(crate) next_frame: Frame, + frame_arena: Option, pub(crate) focus_handles: Arc>>, focus_listeners: SubscriberSet<(), AnyWindowFocusListener>, blur_listeners: SubscriberSet<(), AnyObserver>, @@ -397,6 +398,7 @@ impl Window { element_id_stack: GlobalElementId::default(), rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())), next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())), + frame_arena: Some(Arena::new(16 * 1024 * 1024)), focus_handles: Arc::new(RwLock::new(SlotMap::with_key())), focus_listeners: SubscriberSet::new(), blur_listeners: SubscriberSet::new(), @@ -1278,7 +1280,9 @@ impl<'a> WindowContext<'a> { self.window.platform_window.clear_input_handler(); self.window.layout_engine.as_mut().unwrap().clear(); self.window.next_frame.clear(); - FRAME_ARENA.with_borrow_mut(|arena| arena.clear()); + let mut frame_arena = self.window.frame_arena.take().unwrap(); + frame_arena.clear(); + FRAME_ARENA.replace(Some(frame_arena)); let root_view = self.window.root_view.take().unwrap(); self.with_z_index(0, |cx| { @@ -1364,6 +1368,7 @@ impl<'a> WindowContext<'a> { } self.window.drawing = false; + self.window.frame_arena = Some(FRAME_ARENA.take().unwrap()); scene } From 89b231afebe71e270025ba4556d66d08aa58e1b8 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 13:09:46 -0500 Subject: [PATCH 111/644] Update collab panel signed out state --- crates/collab_ui2/src/collab_panel.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index a845e117d5..18d9916bb3 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2028,17 +2028,20 @@ impl CollabPanel { fn render_signed_out(&mut self, cx: &mut ViewContext) -> Div { v_stack() - .justify_center() + // .flex_1() + // .justify_center() .items_center() - .child(v_stack().gap_1().p_4() + .child(v_stack().gap_6().p_4() .child( - Label::new("Work with your team with realtive collaborative editing, voice, shared notes and more.") - ) - .child( - Label::new("Sign in to enable collaboration.") + Label::new("Work with your team in realtime with collaborative editing, voice, shared notes and more.") ) + .child(v_stack().gap_2() + .child( Button::new("sign_in", "Sign in") + .icon_color(Color::Muted) + .icon(Icon::Github) + .icon_position(IconPosition::Start) .style(ButtonStyle::Filled) .full_width() .on_click(cx.listener( @@ -2052,6 +2055,12 @@ impl CollabPanel { }) .detach() }, + ))) + .child( + div().flex().w_full().items_center().child( + Label::new("Sign in to enable collaboration.") + .color(Color::Muted) + .size(LabelSize::Small) )), )) } From 9d014b0f9a886e308b3ad80aa1f7318a541c5a89 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 13:11:51 -0500 Subject: [PATCH 112/644] Remove comment --- crates/collab_ui2/src/collab_panel.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 18d9916bb3..5fc0c77d0c 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2028,8 +2028,6 @@ impl CollabPanel { fn render_signed_out(&mut self, cx: &mut ViewContext) -> Div { v_stack() - // .flex_1() - // .justify_center() .items_center() .child(v_stack().gap_6().p_4() .child( From 0aa690f915067ada7de8ab9902cf3f1b8acc681d Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 13:27:47 -0500 Subject: [PATCH 113/644] Always show channel toggle when collapsed (#3698) This PR makes the channel toggle disclosure always visible when a channel tree is collapsed, as opposed to just being visible on hover. This makes it possible to visually identify collapsed channel trees without having to hover over each entry. Release Notes: - N/A --- crates/ui2/src/components/list/list_item.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index 481d96d242..a8ca45d1d7 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -192,7 +192,7 @@ impl RenderOnce for ListItem { .flex() .absolute() .left(rems(-1.)) - .visible_on_hover("") + .when(is_open, |this| this.visible_on_hover("")) .child(Disclosure::new(is_open).on_toggle(self.on_toggle)) })) .child( From 98f5a3d544a661a05184c6286c992ed61cf273c3 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 13:35:05 -0500 Subject: [PATCH 114/644] Center text on welcome screen (#3699) This PR centers the text "Code at the speed of thought" on the welcome screen. Release Notes: - N/A --- crates/welcome2/src/welcome.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/welcome2/src/welcome.rs b/crates/welcome2/src/welcome.rs index c553a04fc7..91620595ce 100644 --- a/crates/welcome2/src/welcome.rs +++ b/crates/welcome2/src/welcome.rs @@ -74,7 +74,11 @@ impl Render for WelcomePage { .h(px(96.)) .mx_auto(), ) - .child(Label::new("Code at the speed of thought")) + .child( + h_stack() + .justify_center() + .child(Label::new("Code at the speed of thought")), + ) .child( v_stack() .gap_2() From 37efe82c5e5f98978b386df85b3be61ccc83b078 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 18 Dec 2023 19:35:17 +0100 Subject: [PATCH 115/644] Use a different frame arena for all elements Co-Authored-By: Nathan Sobo Co-Authored-By: Max Brunsfeld --- crates/gpui2/src/arena.rs | 4 +++ crates/gpui2/src/element.rs | 7 ++-- crates/gpui2/src/window.rs | 70 ++++++++++++++++++++----------------- 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index c99f09d29f..24434153fb 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -78,6 +78,10 @@ impl Arena { } } } + + pub fn size(&self) -> usize { + self.offset + } } impl Drop for Arena { diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 6f739d8e33..d0ed50a3d5 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -1,6 +1,6 @@ use crate::{ - frame_alloc, ArenaRef, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, - Point, Size, ViewContext, WindowContext, + ArenaRef, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, + ViewContext, WindowContext, ELEMENT_ARENA, }; use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; @@ -413,7 +413,8 @@ impl AnyElement { E: 'static + Element, E::State: Any, { - let element = frame_alloc(|| Some(DrawableElement::new(element))) + let element = ELEMENT_ARENA + .with_borrow_mut(|arena| arena.alloc(|| Some(DrawableElement::new(element)))) .map(|element| element as &mut dyn ElementObject); AnyElement(element) } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index e00c707de3..0cef164460 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -99,12 +99,7 @@ struct FocusEvent { slotmap::new_key_type! { pub struct FocusId; } thread_local! { - pub static FRAME_ARENA: RefCell> = RefCell::new(None); -} - -#[inline(always)] -pub(crate) fn frame_alloc(f: impl FnOnce() -> T) -> ArenaRef { - FRAME_ARENA.with_borrow_mut(|arena| arena.as_mut().unwrap().alloc(f)) + pub(crate) static ELEMENT_ARENA: RefCell = RefCell::new(Arena::new(4 * 1024 * 1024)); } impl FocusId { @@ -254,7 +249,7 @@ pub struct Window { pub(crate) element_id_stack: GlobalElementId, pub(crate) rendered_frame: Frame, pub(crate) next_frame: Frame, - frame_arena: Option, + frame_arena: Arena, pub(crate) focus_handles: Arc>>, focus_listeners: SubscriberSet<(), AnyWindowFocusListener>, blur_listeners: SubscriberSet<(), AnyObserver>, @@ -398,7 +393,7 @@ impl Window { element_id_stack: GlobalElementId::default(), rendered_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())), next_frame: Frame::new(DispatchTree::new(cx.keymap.clone(), cx.actions.clone())), - frame_arena: Some(Arena::new(16 * 1024 * 1024)), + frame_arena: Arena::new(1 * 1024 * 1024), focus_handles: Arc::new(RwLock::new(SlotMap::with_key())), focus_listeners: SubscriberSet::new(), blur_listeners: SubscriberSet::new(), @@ -836,12 +831,15 @@ impl<'a> WindowContext<'a> { mut handler: impl FnMut(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { let order = self.window.next_frame.z_index_stack.clone(); - let handler = frame_alloc(|| { - move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { - handler(event.downcast_ref().unwrap(), phase, cx) - } - }) - .map(|handler| handler as _); + let handler = self + .window + .frame_arena + .alloc(|| { + move |event: &dyn Any, phase: DispatchPhase, cx: &mut WindowContext<'_>| { + handler(event.downcast_ref().unwrap(), phase, cx) + } + }) + .map(|handler| handler as _); self.window .next_frame .mouse_listeners @@ -860,14 +858,17 @@ impl<'a> WindowContext<'a> { &mut self, listener: impl Fn(&Event, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = frame_alloc(|| { - move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { - if let Some(event) = event.downcast_ref::() { - listener(event, phase, cx) + let listener = self + .window + .frame_arena + .alloc(|| { + move |event: &dyn Any, phase, cx: &mut WindowContext<'_>| { + if let Some(event) = event.downcast_ref::() { + listener(event, phase, cx) + } } - } - }) - .map(|handler| handler as _); + }) + .map(|handler| handler as _); self.window.next_frame.dispatch_tree.on_key_event(listener); } @@ -882,7 +883,11 @@ impl<'a> WindowContext<'a> { action_type: TypeId, listener: impl Fn(&dyn Any, DispatchPhase, &mut WindowContext) + 'static, ) { - let listener = frame_alloc(|| listener).map(|handler| handler as _); + let listener = self + .window + .frame_arena + .alloc(|| listener) + .map(|handler| handler as _); self.window .next_frame .dispatch_tree @@ -1280,21 +1285,22 @@ impl<'a> WindowContext<'a> { self.window.platform_window.clear_input_handler(); self.window.layout_engine.as_mut().unwrap().clear(); self.window.next_frame.clear(); - let mut frame_arena = self.window.frame_arena.take().unwrap(); - frame_arena.clear(); - FRAME_ARENA.replace(Some(frame_arena)); + self.window.frame_arena.clear(); let root_view = self.window.root_view.take().unwrap(); self.with_z_index(0, |cx| { cx.with_key_dispatch(Some(KeyContext::default()), None, |_, cx| { for (action_type, action_listeners) in &cx.app.global_action_listeners { for action_listener in action_listeners.iter().cloned() { - let listener = frame_alloc(|| { - move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { - action_listener(action, phase, cx) - } - }) - .map(|listener| listener as _); + let listener = cx + .window + .frame_arena + .alloc(|| { + move |action: &dyn Any, phase, cx: &mut WindowContext<'_>| { + action_listener(action, phase, cx) + } + }) + .map(|listener| listener as _); cx.window .next_frame .dispatch_tree @@ -1368,7 +1374,7 @@ impl<'a> WindowContext<'a> { } self.window.drawing = false; - self.window.frame_arena = Some(FRAME_ARENA.take().unwrap()); + ELEMENT_ARENA.with_borrow_mut(|element_arena| element_arena.clear()); scene } From 0000e6831094c38bf3455acc0617922ced877516 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 18 Dec 2023 10:41:02 -0800 Subject: [PATCH 116/644] Remove unused Arena::sized method --- crates/gpui2/src/arena.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index 24434153fb..c99f09d29f 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -78,10 +78,6 @@ impl Arena { } } } - - pub fn size(&self) -> usize { - self.offset - } } impl Drop for Arena { From c9893ce2fd87f349cbb5f92d2ba8eb86889494f8 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 13:51:04 -0500 Subject: [PATCH 117/644] Use flex_1 div instead of justify_center in toolbar --- crates/workspace2/src/toolbar.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index a6c8f9d0bf..c9bcc9346e 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -108,7 +108,6 @@ impl Render for Toolbar { .bg(cx.theme().colors().toolbar_background) .child( h_stack() - .justify_between() .when(self.left_items().count() > 0, |this| { this.child( h_stack() @@ -117,6 +116,11 @@ impl Render for Toolbar { .children(self.left_items().map(|item| item.to_any())), ) }) + // Render an empty div that takes up the space between + // the left and right sides. This won't cause items to + // be centered like justify_center() will if left or + // right is missing. + .child(div().flex_1()) .when(self.right_items().count() > 0, |this| { this.child( h_stack() From 4fdf6a867ad085308ed89524ee4649e4b9b6d1a8 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 13:54:11 -0500 Subject: [PATCH 118/644] Wire up offline contact list (#3700) This PR wires up the offline contact list. Also enables toggling both the online and offline contact lists. Release Notes: - N/A --- crates/collab_ui2/src/collab_panel.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 5fc0c77d0c..ab82310094 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2230,15 +2230,17 @@ impl CollabPanel { | Section::Offline => true, }; - let mut row = h_stack() + h_stack() .w_full() .group("section-header") .child( ListHeader::new(text) - .toggle(if can_collapse { - Some(!is_collapsed) - } else { - None + .when(can_collapse, |header| { + header.toggle(Some(!is_collapsed)).on_toggle(cx.listener( + move |this, event, cx| { + this.toggle_section_expanded(section, cx); + }, + )) }) .inset(true) .end_slot::(button) @@ -2253,13 +2255,7 @@ impl CollabPanel { }) .detach_and_log_err(cx) })) - }); - - if section == Section::Offline { - row = div().border_1().border_color(gpui::red()).child(row); - } - - row + }) } fn render_contact( From 2ae39b70c8dcef9d8a0459a07887b678a3e2e9f7 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 13:55:30 -0500 Subject: [PATCH 119/644] Add left side padding --- crates/workspace2/src/toolbar.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index c9bcc9346e..ef8595ae09 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -111,6 +111,7 @@ impl Render for Toolbar { .when(self.left_items().count() > 0, |this| { this.child( h_stack() + .p_1() .flex_1() .justify_start() .children(self.left_items().map(|item| item.to_any())), From 9cd8e99a9a39e346d3a31dd491039496a1fb6f51 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 14:10:12 -0500 Subject: [PATCH 120/644] Update toolbar.rs --- crates/workspace2/src/toolbar.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index ef8595ae09..df19ca4451 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -117,11 +117,6 @@ impl Render for Toolbar { .children(self.left_items().map(|item| item.to_any())), ) }) - // Render an empty div that takes up the space between - // the left and right sides. This won't cause items to - // be centered like justify_center() will if left or - // right is missing. - .child(div().flex_1()) .when(self.right_items().count() > 0, |this| { this.child( h_stack() From 9785481abadbe740f6e731c5bb26ac77eab5e0b1 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 15:21:04 -0500 Subject: [PATCH 121/644] Make `Disclosure` accept an ID (#3701) This PR makes the `Disclosure` component accept an ID rather than using a static ID for all disclosures. Release Notes: - N/A --- crates/ui2/src/components/disclosure.rs | 6 +- crates/ui2/src/components/list/list_header.rs | 87 ++++++++++--------- crates/ui2/src/components/list/list_item.rs | 2 +- .../ui2/src/components/stories/disclosure.rs | 4 +- 4 files changed, 53 insertions(+), 46 deletions(-) diff --git a/crates/ui2/src/components/disclosure.rs b/crates/ui2/src/components/disclosure.rs index 7d0f911d96..729023986d 100644 --- a/crates/ui2/src/components/disclosure.rs +++ b/crates/ui2/src/components/disclosure.rs @@ -4,13 +4,15 @@ use crate::{prelude::*, Color, Icon, IconButton, IconSize}; #[derive(IntoElement)] pub struct Disclosure { + id: ElementId, is_open: bool, on_toggle: Option>, } impl Disclosure { - pub fn new(is_open: bool) -> Self { + pub fn new(id: impl Into, is_open: bool) -> Self { Self { + id: id.into(), is_open, on_toggle: None, } @@ -30,7 +32,7 @@ impl RenderOnce for Disclosure { fn render(self, _cx: &mut WindowContext) -> Self::Rendered { IconButton::new( - "toggle", + self.id, match self.is_open { true => Icon::ChevronDown, false => Icon::ChevronRight, diff --git a/crates/ui2/src/components/list/list_header.rs b/crates/ui2/src/components/list/list_header.rs index d082574a92..0c07867c6d 100644 --- a/crates/ui2/src/components/list/list_header.rs +++ b/crates/ui2/src/components/list/list_header.rs @@ -1,5 +1,6 @@ +use gpui::{AnyElement, ClickEvent, Div, Stateful}; + use crate::{h_stack, prelude::*, Disclosure, Label}; -use gpui::{AnyElement, ClickEvent, Div}; #[derive(IntoElement)] pub struct ListHeader { @@ -75,48 +76,52 @@ impl Selectable for ListHeader { } impl RenderOnce for ListHeader { - type Rendered = Div; + type Rendered = Stateful
; fn render(self, cx: &mut WindowContext) -> Self::Rendered { - h_stack().w_full().relative().group("list_header").child( - div() - .h_7() - .when(self.inset, |this| this.px_2()) - .when(self.selected, |this| { - this.bg(cx.theme().colors().ghost_element_selected) - }) - .flex() - .flex_1() - .items_center() - .justify_between() - .w_full() - .gap_1() - .child( - h_stack() - .gap_1() - .children( - self.toggle - .map(|is_open| Disclosure::new(is_open).on_toggle(self.on_toggle)), - ) - .child( - div() - .flex() - .gap_1() - .items_center() - .children(self.start_slot) - .child(Label::new(self.label.clone()).color(Color::Muted)), - ), - ) - .child(h_stack().children(self.end_slot)) - .when_some(self.end_hover_slot, |this, end_hover_slot| { - this.child( - div() - .absolute() - .right_0() - .visible_on_hover("list_header") - .child(end_hover_slot), + h_stack() + .id(self.label.clone()) + .w_full() + .relative() + .group("list_header") + .child( + div() + .h_7() + .when(self.inset, |this| this.px_2()) + .when(self.selected, |this| { + this.bg(cx.theme().colors().ghost_element_selected) + }) + .flex() + .flex_1() + .items_center() + .justify_between() + .w_full() + .gap_1() + .child( + h_stack() + .gap_1() + .children(self.toggle.map(|is_open| { + Disclosure::new("toggle", is_open).on_toggle(self.on_toggle) + })) + .child( + div() + .flex() + .gap_1() + .items_center() + .children(self.start_slot) + .child(Label::new(self.label.clone()).color(Color::Muted)), + ), ) - }), - ) + .child(h_stack().children(self.end_slot)) + .when_some(self.end_hover_slot, |this, end_hover_slot| { + this.child( + div() + .absolute() + .right_0() + .visible_on_hover("list_header") + .child(end_hover_slot), + ) + }), + ) } } diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index a8ca45d1d7..bdb5c2b854 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -193,7 +193,7 @@ impl RenderOnce for ListItem { .absolute() .left(rems(-1.)) .when(is_open, |this| this.visible_on_hover("")) - .child(Disclosure::new(is_open).on_toggle(self.on_toggle)) + .child(Disclosure::new("toggle", is_open).on_toggle(self.on_toggle)) })) .child( h_stack() diff --git a/crates/ui2/src/components/stories/disclosure.rs b/crates/ui2/src/components/stories/disclosure.rs index 7a2c419456..cf2491b387 100644 --- a/crates/ui2/src/components/stories/disclosure.rs +++ b/crates/ui2/src/components/stories/disclosure.rs @@ -13,8 +13,8 @@ impl Render for DisclosureStory { Story::container() .child(Story::title_for::()) .child(Story::label("Toggled")) - .child(Disclosure::new(true)) + .child(Disclosure::new("toggled", true)) .child(Story::label("Not Toggled")) - .child(Disclosure::new(false)) + .child(Disclosure::new("not_toggled", false)) } } From a286ec46504093365f52abf5ad9f9c3838683d24 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Mon, 18 Dec 2023 16:10:13 -0500 Subject: [PATCH 122/644] Update toolbar.rs --- crates/workspace2/src/toolbar.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index df19ca4451..1c60b8967f 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -108,6 +108,7 @@ impl Render for Toolbar { .bg(cx.theme().colors().toolbar_background) .child( h_stack() + .justify_between() .when(self.left_items().count() > 0, |this| { this.child( h_stack() From 64ceb61aa32727f31f54bcc1ef61966394fc69f6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 16:32:51 -0500 Subject: [PATCH 123/644] Add pane dividers (#3703) This PR adds dividers between panes in a split. Release Notes: - N/A --- crates/workspace2/src/pane_group.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index b52cec2b18..7416b72331 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -570,9 +570,12 @@ mod element { }; use parking_lot::Mutex; use smallvec::SmallVec; + use ui::prelude::*; use super::{HANDLE_HITBOX_SIZE, HORIZONTAL_MIN_SIZE, VERTICAL_MIN_SIZE}; + const DIVIDER_SIZE: f32 = 1.0; + pub fn pane_axis( axis: Axis, basis: usize, @@ -699,12 +702,18 @@ mod element { cx: &mut WindowContext, ) { let handle_bounds = Bounds { - origin: pane_bounds.origin.apply_along(axis, |o| { - o + pane_bounds.size.along(axis) - Pixels(HANDLE_HITBOX_SIZE / 2.) + origin: pane_bounds.origin.apply_along(axis, |origin| { + origin + pane_bounds.size.along(axis) - px(HANDLE_HITBOX_SIZE / 2.) }), size: pane_bounds .size - .apply_along(axis, |_| Pixels(HANDLE_HITBOX_SIZE)), + .apply_along(axis, |_| px(HANDLE_HITBOX_SIZE)), + }; + let divider_bounds = Bounds { + origin: pane_bounds + .origin + .apply_along(axis, |origin| origin + pane_bounds.size.along(axis)), + size: pane_bounds.size.apply_along(axis, |_| px(DIVIDER_SIZE)), }; cx.with_z_index(3, |cx| { @@ -716,6 +725,7 @@ mod element { } cx.add_opaque_layer(handle_bounds); + cx.paint_quad(gpui::fill(divider_bounds, cx.theme().colors().border)); cx.on_mouse_event({ let dragged_handle = dragged_handle.clone(); @@ -790,7 +800,7 @@ mod element { for (ix, child) in self.children.iter_mut().enumerate() { //todo!(active_pane_magnification) - // If usign active pane magnification, need to switch to using + // If using active pane magnification, need to switch to using // 1 for all non-active panes, and then the magnification for the // active pane. let child_size = bounds From 734bbfa66f268220c849455568f467427884eed7 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 16:56:44 -0500 Subject: [PATCH 124/644] Use status colors for contact availability indicators (#3704) This PR updates the availability indicators in the contact list to use the status colors from the theme. Release Notes: - N/A --- crates/ui2/src/components/avatar.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/ui2/src/components/avatar.rs b/crates/ui2/src/components/avatar.rs index 33c8d71625..0ab6ce2d85 100644 --- a/crates/ui2/src/components/avatar.rs +++ b/crates/ui2/src/components/avatar.rs @@ -47,7 +47,11 @@ impl RenderOnce for Avatar { div() .absolute() .z_index(1) - .bg(if is_free { gpui::green() } else { gpui::red() }) + .bg(if is_free { + cx.theme().status().created + } else { + cx.theme().status().deleted + }) .size(indicator_size) .rounded(indicator_size) .bottom_0() From 912f7e6c1a149d62b5f36f50304ff63ed0201840 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 17:18:49 -0500 Subject: [PATCH 125/644] Add ability to warn on missing theme values (#3705) This PR adds the ability to warn in the `theme_importer` when a theme is missing values. Providing the `--warn-on-missing` flag to the `theme_importer` will print a warning for missing theme value when printing the theme. ```sh cargo run -p theme_importer -- --warn-on-missing ``` Release Notes: - N/A --- Cargo.lock | 1 + crates/theme_importer/Cargo.toml | 1 + crates/theme_importer/src/main.rs | 31 +++++++++++++++++----- crates/theme_importer/src/theme_printer.rs | 2 ++ 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a4801524e..cb0d54022f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9813,6 +9813,7 @@ name = "theme_importer" version = "0.1.0" dependencies = [ "anyhow", + "clap 4.4.4", "convert_case 0.6.0", "gpui2", "indexmap 1.9.3", diff --git a/crates/theme_importer/Cargo.toml b/crates/theme_importer/Cargo.toml index 82ab18d48d..4b8641faa4 100644 --- a/crates/theme_importer/Cargo.toml +++ b/crates/theme_importer/Cargo.toml @@ -8,6 +8,7 @@ publish = false [dependencies] anyhow.workspace = true +clap = { version = "4.4", features = ["derive"] } convert_case = "0.6.0" gpui = { package = "gpui2", path = "../gpui2" } indexmap = { version = "1.6.2", features = ["serde"] } diff --git a/crates/theme_importer/src/main.rs b/crates/theme_importer/src/main.rs index 0005d932d4..a02b1ca114 100644 --- a/crates/theme_importer/src/main.rs +++ b/crates/theme_importer/src/main.rs @@ -10,6 +10,7 @@ use std::process::Command; use std::str::FromStr; use anyhow::{anyhow, Context, Result}; +use clap::Parser; use convert_case::{Case, Casing}; use gpui::serde_json; use indexmap::IndexMap; @@ -61,16 +62,34 @@ pub struct ThemeMetadata { pub appearance: ThemeAppearanceJson, } +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Whether to warn when values are missing from the theme. + #[arg(long)] + warn_on_missing: bool, +} + fn main() -> Result<()> { const SOURCE_PATH: &str = "assets/themes/src/vscode"; const OUT_PATH: &str = "crates/theme2/src/themes"; - let log_config = simplelog::ConfigBuilder::new() - .set_level_color(log::Level::Trace, simplelog::Color::Cyan) - .set_level_color(log::Level::Info, simplelog::Color::Blue) - .set_level_color(log::Level::Warn, simplelog::Color::Yellow) - .set_level_color(log::Level::Error, simplelog::Color::Red) - .build(); + let args = Args::parse(); + + let log_config = { + let mut config = simplelog::ConfigBuilder::new(); + config + .set_level_color(log::Level::Trace, simplelog::Color::Cyan) + .set_level_color(log::Level::Info, simplelog::Color::Blue) + .set_level_color(log::Level::Warn, simplelog::Color::Yellow) + .set_level_color(log::Level::Error, simplelog::Color::Red); + + if !args.warn_on_missing { + config.add_filter_ignore_str("theme_printer"); + } + + config.build() + }; TermLogger::init(LevelFilter::Trace, log_config, TerminalMode::Mixed) .expect("could not initialize logger"); diff --git a/crates/theme_importer/src/theme_printer.rs b/crates/theme_importer/src/theme_printer.rs index 4726c90c6d..13123d854f 100644 --- a/crates/theme_importer/src/theme_printer.rs +++ b/crates/theme_importer/src/theme_printer.rs @@ -282,6 +282,8 @@ impl<'a> Debug for ThemeColorsRefinementPrinter<'a> { HslaPrinter(color).fmt(f)?; f.write_str(")")?; f.write_str(",")?; + } else { + log::warn!(target: "theme_printer", "No value for '{}' in theme", color_name); } } From 91f1be213bd182c28cf4555a52b955ca82136c49 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 18 Dec 2023 18:13:09 -0500 Subject: [PATCH 126/644] Style project share notification (#3706) This PR styles the project share notification, so we're not staring a red rectangle. Screenshot 2023-12-18 at 6 06 14 PM Release Notes: - N/A --- .../project_shared_notification.rs | 111 ++++++++++-------- 1 file changed, 63 insertions(+), 48 deletions(-) diff --git a/crates/collab_ui2/src/notifications/project_shared_notification.rs b/crates/collab_ui2/src/notifications/project_shared_notification.rs index e130f09b16..2dc0dee6f4 100644 --- a/crates/collab_ui2/src/notifications/project_shared_notification.rs +++ b/crates/collab_ui2/src/notifications/project_shared_notification.rs @@ -3,11 +3,12 @@ use call::{room, ActiveCall}; use client::User; use collections::HashMap; use gpui::{ - px, AppContext, Div, Element, ParentElement, Render, RenderOnce, Size, Styled, ViewContext, - VisualContext, + img, px, AppContext, Div, ParentElement, Render, Size, Styled, ViewContext, VisualContext, }; +use settings::Settings; use std::sync::{Arc, Weak}; -use ui::{h_stack, v_stack, Avatar, Button, Clickable, Label}; +use theme::ThemeSettings; +use ui::{h_stack, prelude::*, v_stack, Button, Label}; use workspace::AppState; pub fn init(app_state: &Arc, cx: &mut AppContext) { @@ -21,8 +22,8 @@ pub fn init(app_state: &Arc, cx: &mut AppContext) { worktree_root_names, } => { let window_size = Size { - width: px(380.), - height: px(64.), + width: px(400.), + height: px(96.), }; for screen in cx.displays() { @@ -116,56 +117,70 @@ impl ProjectSharedNotification { }); } } - - fn render_owner(&self) -> impl Element { - h_stack() - .child(Avatar::new(self.owner.avatar_uri.clone())) - .child( - v_stack() - .child(Label::new(self.owner.github_login.clone())) - .child(Label::new(format!( - "is sharing a project in Zed{}", - if self.worktree_root_names.is_empty() { - "" - } else { - ":" - } - ))) - .children(if self.worktree_root_names.is_empty() { - None - } else { - Some(Label::new(self.worktree_root_names.join(", "))) - }), - ) - } - - fn render_buttons(&self, cx: &mut ViewContext) -> impl Element { - let this = cx.view().clone(); - v_stack() - .child(Button::new("open", "Open").render(cx).on_click({ - let this = this.clone(); - move |_, cx| { - this.update(cx, |this, cx| this.join(cx)); - } - })) - .child( - Button::new("dismiss", "Dismiss") - .render(cx) - .on_click(move |_, cx| { - this.update(cx, |this, cx| this.dismiss(cx)); - }), - ) - } } impl Render for ProjectSharedNotification { type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + // TODO: Is there a better place for us to initialize the font? + let (ui_font, ui_font_size) = { + let theme_settings = ThemeSettings::get_global(cx); + ( + theme_settings.ui_font.family.clone(), + theme_settings.ui_font_size.clone(), + ) + }; + + cx.set_rem_size(ui_font_size); + h_stack() + .font(ui_font) + .text_ui() + .justify_between() .size_full() - .bg(gpui::red()) - .child(self.render_owner()) - .child(self.render_buttons(cx)) + .elevation_3(cx) + .p_2() + .gap_2() + .child( + h_stack() + .gap_2() + .child( + img(self.owner.avatar_uri.clone()) + .w_16() + .h_16() + .rounded_full(), + ) + .child( + v_stack() + .child(Label::new(self.owner.github_login.clone())) + .child(Label::new(format!( + "is sharing a project in Zed{}", + if self.worktree_root_names.is_empty() { + "" + } else { + ":" + } + ))) + .children(if self.worktree_root_names.is_empty() { + None + } else { + Some(Label::new(self.worktree_root_names.join(", "))) + }), + ), + ) + .child( + v_stack() + .child(Button::new("open", "Open").on_click(cx.listener( + move |this, _event, cx| { + this.join(cx); + }, + ))) + .child(Button::new("dismiss", "Dismiss").on_click(cx.listener( + move |this, _event, cx| { + this.dismiss(cx); + }, + ))), + ) } } From e6f3731efd6983818dd188bf5d817eac16500e81 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 18 Dec 2023 13:51:23 -0800 Subject: [PATCH 127/644] Fix position of right dock handle Co-authored-by: Nathan Sobo --- crates/workspace2/src/dock.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index e44471a871..3997b8f9b0 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -490,6 +490,7 @@ impl Render for Dock { let mut handle = div() .id("resize-handle") .on_drag(DraggedDock(position), |dock, cx| { + cx.stop_propagation(); cx.build_view(|_| dock.clone()) }) .on_click(cx.listener(|v, e: &ClickEvent, cx| { @@ -525,8 +526,8 @@ impl Render for Dock { .absolute() .top(px(0.)) .left(px(0.)) - .w_full() - .h(HANDLE_SIZE) + .h_full() + .w(HANDLE_SIZE) .cursor_col_resize(); } } From ee8e1454fcb2edb90fa1ceb10b1f9dd508756327 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 18 Dec 2023 13:51:23 -0800 Subject: [PATCH 128/644] Fix drag and drop logic in div's mouse handling * Attach mouse up and mouse move listeners immediately, not just when there is already a drag in progress, because when starting a drag, these other events may fire before the next frame. * Remove bounds checks for handling mouse move and mouse events, since a dragged object may be moved outside of its original container. Co-authored-by: Nathan Sobo --- crates/gpui2/src/elements/div.rs | 161 ++++++++++++++++--------------- 1 file changed, 85 insertions(+), 76 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 1f56f44900..f6dd2fa09e 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -151,9 +151,7 @@ impl Interactivity { { self.mouse_move_listeners .push(Box::new(move |event, bounds, phase, cx| { - if phase == DispatchPhase::Capture - && bounds.drag_target_contains(&event.position, cx) - { + if phase == DispatchPhase::Capture { if cx .active_drag .as_ref() @@ -1131,19 +1129,19 @@ impl Interactivity { }); } - if cx.active_drag.is_some() { - let drop_listeners = mem::take(&mut self.drop_listeners); - let interactive_bounds = interactive_bounds.clone(); - if !drop_listeners.is_empty() { - cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && interactive_bounds.drag_target_contains(&event.position, cx) - { - if let Some(drag_state_type) = cx - .active_drag - .as_ref() - .map(|drag| drag.value.as_ref().type_id()) + let mut drag_listener = mem::take(&mut self.drag_listener); + let drop_listeners = mem::take(&mut self.drop_listeners); + let click_listeners = mem::take(&mut self.click_listeners); + + if !drop_listeners.is_empty() { + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + move |event: &MouseUpEvent, phase, cx| { + if let Some(drag) = &cx.active_drag { + if phase == DispatchPhase::Bubble + && interactive_bounds.drag_target_contains(&event.position, cx) { + let drag_state_type = drag.value.as_ref().type_id(); for (drop_state_type, listener) in &drop_listeners { if *drop_state_type == drag_state_type { let drag = cx @@ -1156,77 +1154,27 @@ impl Interactivity { cx.stop_propagation(); } } - } else { - cx.active_drag = None; } } - }); - } + } + }); } - let click_listeners = mem::take(&mut self.click_listeners); - let mut drag_listener = mem::take(&mut self.drag_listener); - if !click_listeners.is_empty() || drag_listener.is_some() { let pending_mouse_down = element_state .pending_mouse_down .get_or_insert_with(Default::default) .clone(); - let mouse_down = pending_mouse_down.borrow().clone(); - if let Some(mouse_down) = mouse_down { - if drag_listener.is_some() { - let active_state = element_state - .clicked_state - .get_or_insert_with(Default::default) - .clone(); - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - if cx.active_drag.is_some() { - if phase == DispatchPhase::Capture { - cx.notify(); - } - } else if phase == DispatchPhase::Bubble - && interactive_bounds.visibly_contains(&event.position, cx) - && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD - { - let (drag_value, drag_listener) = drag_listener - .take() - .expect("The notify below should invalidate this callback"); - - *active_state.borrow_mut() = ElementClickedState::default(); - let cursor_offset = event.position - bounds.origin; - let drag = (drag_listener)(drag_value.as_ref(), cx); - cx.active_drag = Some(AnyDrag { - view: drag, - value: drag_value, - cursor_offset, - }); - cx.notify(); - cx.stop_propagation(); - } - }); - } + let active_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .clone(); + cx.on_mouse_event({ let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && interactive_bounds.visibly_contains(&event.position, cx) - { - let mouse_click = ClickEvent { - down: mouse_down.clone(), - up: event.clone(), - }; - for listener in &click_listeners { - listener(&mouse_click, cx); - } - } - *pending_mouse_down.borrow_mut() = None; - cx.notify(); - }); - } else { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { + let pending_mouse_down = pending_mouse_down.clone(); + move |event: &MouseDownEvent, phase, cx| { if phase == DispatchPhase::Bubble && event.button == MouseButton::Left && interactive_bounds.visibly_contains(&event.position, cx) @@ -1234,8 +1182,69 @@ impl Interactivity { *pending_mouse_down.borrow_mut() = Some(event.clone()); cx.notify(); } - }); - } + } + }); + + cx.on_mouse_event({ + let pending_mouse_down = pending_mouse_down.clone(); + move |event: &MouseMoveEvent, phase, cx| { + let mut pending_mouse_down = pending_mouse_down.borrow_mut(); + if let Some(mouse_down) = pending_mouse_down.clone() { + if cx.active_drag.is_some() { + if phase == DispatchPhase::Capture { + cx.notify(); + } + } else if phase == DispatchPhase::Bubble + && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD + { + if let Some((drag_value, drag_listener)) = drag_listener.take() { + *active_state.borrow_mut() = ElementClickedState::default(); + let cursor_offset = event.position - bounds.origin; + let drag = (drag_listener)(drag_value.as_ref(), cx); + cx.active_drag = Some(AnyDrag { + view: drag, + value: drag_value, + cursor_offset, + }); + pending_mouse_down.take(); + cx.notify(); + cx.stop_propagation(); + } + } + } + } + }); + + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + let mut captured_mouse_down = None; + move |event: &MouseUpEvent, phase, cx| match phase { + // Clear the pending mouse down during the capture phase, + // so that it happens even if another event handler stops + // propagation. + DispatchPhase::Capture => { + let mut pending_mouse_down = pending_mouse_down.borrow_mut(); + if pending_mouse_down.is_some() { + captured_mouse_down = pending_mouse_down.take(); + cx.notify(); + } + } + // Fire click handlers during the bubble phase. + DispatchPhase::Bubble => { + if let Some(mouse_down) = captured_mouse_down.take() { + if interactive_bounds.visibly_contains(&event.position, cx) { + let mouse_click = ClickEvent { + down: mouse_down, + up: event.clone(), + }; + for listener in &click_listeners { + listener(&mouse_click, cx); + } + } + } + } + } + }); } if let Some(hover_listener) = self.hover_listener.take() { From b88370d5ade5d6954c6db989ec89942c91151b9c Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 18 Dec 2023 18:02:19 -0800 Subject: [PATCH 129/644] Respect a div's own z-index when adding its event listeners --- crates/gpui2/src/elements/div.rs | 987 +++++++++++----------- crates/gpui2/src/elements/uniform_list.rs | 92 +- 2 files changed, 539 insertions(+), 540 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index f6dd2fa09e..02b9d08b40 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -778,20 +778,16 @@ impl Element for Div { &mut element_state.interactive_state, cx, |style, scroll_offset, cx| { - let z_index = style.z_index.unwrap_or(0); - - cx.with_z_index(z_index, |cx| { - style.paint(bounds, cx, |cx| { - cx.with_text_style(style.text_style().cloned(), |cx| { - cx.with_content_mask(style.overflow_mask(bounds), |cx| { - cx.with_element_offset(scroll_offset, |cx| { - for child in &mut self.children { - child.paint(cx); - } - }) + style.paint(bounds, cx, |cx| { + cx.with_text_style(style.text_style().cloned(), |cx| { + cx.with_content_mask(style.overflow_mask(bounds), |cx| { + cx.with_element_offset(scroll_offset, |cx| { + for child in &mut self.children { + child.paint(cx); + } }) }) - }); + }) }) }, ); @@ -918,542 +914,547 @@ impl Interactivity { return; } - #[cfg(debug_assertions)] - if self.element_id.is_some() - && (style.debug || style.debug_below || cx.has_global::()) - && bounds.contains(&cx.mouse_position()) - { - const FONT_SIZE: crate::Pixels = crate::Pixels(10.); - let element_id = format!("{:?}", self.element_id.as_ref().unwrap()); - let str_len = element_id.len(); + let z_index = style.z_index.unwrap_or(0); + cx.with_z_index(z_index, |cx| { + #[cfg(debug_assertions)] + if self.element_id.is_some() + && (style.debug || style.debug_below || cx.has_global::()) + && bounds.contains(&cx.mouse_position()) + { + const FONT_SIZE: crate::Pixels = crate::Pixels(10.); + let element_id = format!("{:?}", self.element_id.as_ref().unwrap()); + let str_len = element_id.len(); - let render_debug_text = |cx: &mut WindowContext| { - if let Some(text) = cx - .text_system() - .shape_text( - &element_id, - FONT_SIZE, - &[cx.text_style().to_run(str_len)], - None, - ) - .ok() - .map(|mut text| text.pop()) - .flatten() - { - text.paint(bounds.origin, FONT_SIZE, cx).ok(); - - let text_bounds = crate::Bounds { - origin: bounds.origin, - size: text.size(FONT_SIZE), - }; - if self.location.is_some() - && text_bounds.contains(&cx.mouse_position()) - && cx.modifiers().command + let render_debug_text = |cx: &mut WindowContext| { + if let Some(text) = cx + .text_system() + .shape_text( + &element_id, + FONT_SIZE, + &[cx.text_style().to_run(str_len)], + None, + ) + .ok() + .map(|mut text| text.pop()) + .flatten() { - let command_held = cx.modifiers().command; - cx.on_key_event({ - let text_bounds = text_bounds.clone(); - move |e: &crate::ModifiersChangedEvent, _phase, cx| { - if e.modifiers.command != command_held - && text_bounds.contains(&cx.mouse_position()) - { - cx.notify(); + text.paint(bounds.origin, FONT_SIZE, cx).ok(); + + let text_bounds = crate::Bounds { + origin: bounds.origin, + size: text.size(FONT_SIZE), + }; + if self.location.is_some() + && text_bounds.contains(&cx.mouse_position()) + && cx.modifiers().command + { + let command_held = cx.modifiers().command; + cx.on_key_event({ + let text_bounds = text_bounds.clone(); + move |e: &crate::ModifiersChangedEvent, _phase, cx| { + if e.modifiers.command != command_held + && text_bounds.contains(&cx.mouse_position()) + { + cx.notify(); + } } - } - }); + }); - let hovered = bounds.contains(&cx.mouse_position()); - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Capture { - if bounds.contains(&event.position) != hovered { - cx.notify(); + let hovered = bounds.contains(&cx.mouse_position()); + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if bounds.contains(&event.position) != hovered { + cx.notify(); + } } - } - }); + }); - cx.on_mouse_event({ - let location = self.location.clone().unwrap(); - let text_bounds = text_bounds.clone(); - move |e: &crate::MouseDownEvent, phase, cx| { - if text_bounds.contains(&e.position) && phase.capture() { - cx.stop_propagation(); - let Ok(dir) = std::env::current_dir() else { - return; - }; + cx.on_mouse_event({ + let location = self.location.clone().unwrap(); + let text_bounds = text_bounds.clone(); + move |e: &crate::MouseDownEvent, phase, cx| { + if text_bounds.contains(&e.position) && phase.capture() { + cx.stop_propagation(); + let Ok(dir) = std::env::current_dir() else { + return; + }; - eprintln!( - "This element is created at:\n{}:{}:{}", - location.file(), - location.line(), - location.column() - ); - - std::process::Command::new("zed") - .arg(format!( - "{}/{}:{}:{}", - dir.to_string_lossy(), + eprintln!( + "This element is created at:\n{}:{}:{}", location.file(), location.line(), location.column() - )) - .spawn() - .ok(); + ); + + std::process::Command::new("zed") + .arg(format!( + "{}/{}:{}:{}", + dir.to_string_lossy(), + location.file(), + location.line(), + location.column() + )) + .spawn() + .ok(); + } } - } - }); - cx.paint_quad(crate::outline( - crate::Bounds { - origin: bounds.origin - + crate::point(crate::px(0.), FONT_SIZE - px(2.)), - size: crate::Size { - width: text_bounds.size.width, - height: crate::px(1.), + }); + cx.paint_quad(crate::outline( + crate::Bounds { + origin: bounds.origin + + crate::point(crate::px(0.), FONT_SIZE - px(2.)), + size: crate::Size { + width: text_bounds.size.width, + height: crate::px(1.), + }, }, - }, - crate::red(), - )) + crate::red(), + )) + } } - } + }; + + cx.with_z_index(1, |cx| { + cx.with_text_style( + Some(crate::TextStyleRefinement { + color: Some(crate::red()), + line_height: Some(FONT_SIZE.into()), + background_color: Some(crate::white()), + ..Default::default() + }), + render_debug_text, + ) + }); + } + + if style + .background + .as_ref() + .is_some_and(|fill| fill.color().is_some_and(|color| !color.is_transparent())) + { + cx.add_opaque_layer(bounds) + } + + let interactive_bounds = InteractiveBounds { + bounds: bounds.intersect(&cx.content_mask().bounds), + stacking_order: cx.stacking_order().clone(), }; - cx.with_z_index(1, |cx| { - cx.with_text_style( - Some(crate::TextStyleRefinement { - color: Some(crate::red()), - line_height: Some(FONT_SIZE.into()), - background_color: Some(crate::white()), - ..Default::default() - }), - render_debug_text, - ) - }); - } - - if style - .background - .as_ref() - .is_some_and(|fill| fill.color().is_some_and(|color| !color.is_transparent())) - { - cx.with_z_index(style.z_index.unwrap_or(0), |cx| cx.add_opaque_layer(bounds)) - } - - let interactive_bounds = InteractiveBounds { - bounds: bounds.intersect(&cx.content_mask().bounds), - stacking_order: cx.stacking_order().clone(), - }; - - if let Some(mouse_cursor) = style.mouse_cursor { - let mouse_position = &cx.mouse_position(); - let hovered = interactive_bounds.visibly_contains(mouse_position, cx); - if hovered { - cx.set_cursor_style(mouse_cursor); + if let Some(mouse_cursor) = style.mouse_cursor { + let mouse_position = &cx.mouse_position(); + let hovered = interactive_bounds.visibly_contains(mouse_position, cx); + if hovered { + cx.set_cursor_style(mouse_cursor); + } } - } - // If this element can be focused, register a mouse down listener - // that will automatically transfer focus when hitting the element. - // This behavior can be suppressed by using `cx.prevent_default()`. - if let Some(focus_handle) = element_state.focus_handle.clone() { - cx.on_mouse_event({ - let interactive_bounds = interactive_bounds.clone(); - move |event: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && !cx.default_prevented() - && interactive_bounds.visibly_contains(&event.position, cx) - { - cx.focus(&focus_handle); - // If there is a parent that is also focusable, prevent it - // from trasferring focus because we already did so. - cx.prevent_default(); - } - } - }); - } - - for listener in self.mouse_down_listeners.drain(..) { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { - listener(event, &interactive_bounds, phase, cx); - }) - } - - for listener in self.mouse_up_listeners.drain(..) { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { - listener(event, &interactive_bounds, phase, cx); - }) - } - - for listener in self.mouse_move_listeners.drain(..) { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - listener(event, &interactive_bounds, phase, cx); - }) - } - - for listener in self.scroll_wheel_listeners.drain(..) { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - listener(event, &interactive_bounds, phase, cx); - }) - } - - let hover_group_bounds = self - .group_hover_style - .as_ref() - .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx)); - - if let Some(group_bounds) = hover_group_bounds { - let hovered = group_bounds.contains(&cx.mouse_position()); - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Capture { - if group_bounds.contains(&event.position) != hovered { - cx.notify(); - } - } - }); - } - - if self.hover_style.is_some() - || self.base_style.mouse_cursor.is_some() - || cx.active_drag.is_some() && !self.drag_over_styles.is_empty() - { - let bounds = bounds.intersect(&cx.content_mask().bounds); - let hovered = bounds.contains(&cx.mouse_position()); - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Capture { - if bounds.contains(&event.position) != hovered { - cx.notify(); - } - } - }); - } - - let mut drag_listener = mem::take(&mut self.drag_listener); - let drop_listeners = mem::take(&mut self.drop_listeners); - let click_listeners = mem::take(&mut self.click_listeners); - - if !drop_listeners.is_empty() { - cx.on_mouse_event({ - let interactive_bounds = interactive_bounds.clone(); - move |event: &MouseUpEvent, phase, cx| { - if let Some(drag) = &cx.active_drag { + // If this element can be focused, register a mouse down listener + // that will automatically transfer focus when hitting the element. + // This behavior can be suppressed by using `cx.prevent_default()`. + if let Some(focus_handle) = element_state.focus_handle.clone() { + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + move |event: &MouseDownEvent, phase, cx| { if phase == DispatchPhase::Bubble - && interactive_bounds.drag_target_contains(&event.position, cx) + && !cx.default_prevented() + && interactive_bounds.visibly_contains(&event.position, cx) { - let drag_state_type = drag.value.as_ref().type_id(); - for (drop_state_type, listener) in &drop_listeners { - if *drop_state_type == drag_state_type { - let drag = cx - .active_drag - .take() - .expect("checked for type drag state type above"); + cx.focus(&focus_handle); + // If there is a parent that is also focusable, prevent it + // from trasferring focus because we already did so. + cx.prevent_default(); + } + } + }); + } - listener(drag.value.as_ref(), cx); + for listener in self.mouse_down_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { + listener(event, &interactive_bounds, phase, cx); + }) + } + + for listener in self.mouse_up_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { + listener(event, &interactive_bounds, phase, cx); + }) + } + + for listener in self.mouse_move_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + listener(event, &interactive_bounds, phase, cx); + }) + } + + for listener in self.scroll_wheel_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { + listener(event, &interactive_bounds, phase, cx); + }) + } + + let hover_group_bounds = self + .group_hover_style + .as_ref() + .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx)); + + if let Some(group_bounds) = hover_group_bounds { + let hovered = group_bounds.contains(&cx.mouse_position()); + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if group_bounds.contains(&event.position) != hovered { + cx.notify(); + } + } + }); + } + + if self.hover_style.is_some() + || self.base_style.mouse_cursor.is_some() + || cx.active_drag.is_some() && !self.drag_over_styles.is_empty() + { + let bounds = bounds.intersect(&cx.content_mask().bounds); + let hovered = bounds.contains(&cx.mouse_position()); + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if bounds.contains(&event.position) != hovered { + cx.notify(); + } + } + }); + } + + let mut drag_listener = mem::take(&mut self.drag_listener); + let drop_listeners = mem::take(&mut self.drop_listeners); + let click_listeners = mem::take(&mut self.click_listeners); + + if !drop_listeners.is_empty() { + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + move |event: &MouseUpEvent, phase, cx| { + if let Some(drag) = &cx.active_drag { + if phase == DispatchPhase::Bubble + && interactive_bounds.drag_target_contains(&event.position, cx) + { + let drag_state_type = drag.value.as_ref().type_id(); + for (drop_state_type, listener) in &drop_listeners { + if *drop_state_type == drag_state_type { + let drag = cx + .active_drag + .take() + .expect("checked for type drag state type above"); + + listener(drag.value.as_ref(), cx); + cx.notify(); + cx.stop_propagation(); + } + } + } + } + } + }); + } + + if !click_listeners.is_empty() || drag_listener.is_some() { + let pending_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); + + let active_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .clone(); + + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + let pending_mouse_down = pending_mouse_down.clone(); + move |event: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Bubble + && event.button == MouseButton::Left + && interactive_bounds.visibly_contains(&event.position, cx) + { + *pending_mouse_down.borrow_mut() = Some(event.clone()); + cx.notify(); + } + } + }); + + cx.on_mouse_event({ + let pending_mouse_down = pending_mouse_down.clone(); + move |event: &MouseMoveEvent, phase, cx| { + let mut pending_mouse_down = pending_mouse_down.borrow_mut(); + + if let Some(mouse_down) = pending_mouse_down.clone() { + if cx.active_drag.is_some() { + if phase == DispatchPhase::Capture { + cx.notify(); + } + } else if phase == DispatchPhase::Bubble + && (event.position - mouse_down.position).magnitude() + > DRAG_THRESHOLD + { + if let Some((drag_value, drag_listener)) = drag_listener.take() { + *active_state.borrow_mut() = ElementClickedState::default(); + let cursor_offset = event.position - bounds.origin; + let drag = (drag_listener)(drag_value.as_ref(), cx); + cx.active_drag = Some(AnyDrag { + view: drag, + value: drag_value, + cursor_offset, + }); + pending_mouse_down.take(); cx.notify(); cx.stop_propagation(); } } } } - } - }); - } + }); - if !click_listeners.is_empty() || drag_listener.is_some() { - let pending_mouse_down = element_state - .pending_mouse_down - .get_or_insert_with(Default::default) - .clone(); + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + let mut captured_mouse_down = None; + move |event: &MouseUpEvent, phase, cx| match phase { + // Clear the pending mouse down during the capture phase, + // so that it happens even if another event handler stops + // propagation. + DispatchPhase::Capture => { + let mut pending_mouse_down = pending_mouse_down.borrow_mut(); + if pending_mouse_down.is_some() { + captured_mouse_down = pending_mouse_down.take(); + cx.notify(); + } + } + // Fire click handlers during the bubble phase. + DispatchPhase::Bubble => { + if let Some(mouse_down) = captured_mouse_down.take() { + if interactive_bounds.visibly_contains(&event.position, cx) { + let mouse_click = ClickEvent { + down: mouse_down, + up: event.clone(), + }; + for listener in &click_listeners { + listener(&mouse_click, cx); + } + } + } + } + } + }); + } + + if let Some(hover_listener) = self.hover_listener.take() { + let was_hovered = element_state + .hover_state + .get_or_insert_with(Default::default) + .clone(); + let has_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); + let interactive_bounds = interactive_bounds.clone(); + + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + if phase != DispatchPhase::Bubble { + return; + } + let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) + && has_mouse_down.borrow().is_none(); + let mut was_hovered = was_hovered.borrow_mut(); + + if is_hovered != was_hovered.clone() { + *was_hovered = is_hovered; + drop(was_hovered); + + hover_listener(&is_hovered, cx); + } + }); + } + + if let Some(tooltip_builder) = self.tooltip_builder.take() { + let active_tooltip = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .clone(); + let pending_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); + let interactive_bounds = interactive_bounds.clone(); + + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) + && pending_mouse_down.borrow().is_none(); + if !is_hovered { + active_tooltip.borrow_mut().take(); + return; + } + + if phase != DispatchPhase::Bubble { + return; + } + + if active_tooltip.borrow().is_none() { + let task = cx.spawn({ + let active_tooltip = active_tooltip.clone(); + let tooltip_builder = tooltip_builder.clone(); + + move |mut cx| async move { + cx.background_executor().timer(TOOLTIP_DELAY).await; + cx.update(|_, cx| { + active_tooltip.borrow_mut().replace(ActiveTooltip { + tooltip: Some(AnyTooltip { + view: tooltip_builder(cx), + cursor_offset: cx.mouse_position(), + }), + _task: None, + }); + cx.notify(); + }) + .ok(); + } + }); + active_tooltip.borrow_mut().replace(ActiveTooltip { + tooltip: None, + _task: Some(task), + }); + } + }); + + let active_tooltip = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .clone(); + cx.on_mouse_event(move |_: &MouseDownEvent, _, _| { + active_tooltip.borrow_mut().take(); + }); + + if let Some(active_tooltip) = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .borrow() + .as_ref() + { + if active_tooltip.tooltip.is_some() { + cx.active_tooltip = active_tooltip.tooltip.clone() + } + } + } let active_state = element_state .clicked_state .get_or_insert_with(Default::default) .clone(); - - cx.on_mouse_event({ - let interactive_bounds = interactive_bounds.clone(); - let pending_mouse_down = pending_mouse_down.clone(); - move |event: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && event.button == MouseButton::Left - && interactive_bounds.visibly_contains(&event.position, cx) - { - *pending_mouse_down.borrow_mut() = Some(event.clone()); + if active_state.borrow().is_clicked() { + cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Capture { + *active_state.borrow_mut() = ElementClickedState::default(); cx.notify(); } - } - }); - - cx.on_mouse_event({ - let pending_mouse_down = pending_mouse_down.clone(); - move |event: &MouseMoveEvent, phase, cx| { - let mut pending_mouse_down = pending_mouse_down.borrow_mut(); - if let Some(mouse_down) = pending_mouse_down.clone() { - if cx.active_drag.is_some() { - if phase == DispatchPhase::Capture { - cx.notify(); - } - } else if phase == DispatchPhase::Bubble - && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD - { - if let Some((drag_value, drag_listener)) = drag_listener.take() { - *active_state.borrow_mut() = ElementClickedState::default(); - let cursor_offset = event.position - bounds.origin; - let drag = (drag_listener)(drag_value.as_ref(), cx); - cx.active_drag = Some(AnyDrag { - view: drag, - value: drag_value, - cursor_offset, - }); - pending_mouse_down.take(); - cx.notify(); - cx.stop_propagation(); - } - } - } - } - }); - - cx.on_mouse_event({ + }); + } else { + let active_group_bounds = self + .group_active_style + .as_ref() + .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); let interactive_bounds = interactive_bounds.clone(); - let mut captured_mouse_down = None; - move |event: &MouseUpEvent, phase, cx| match phase { - // Clear the pending mouse down during the capture phase, - // so that it happens even if another event handler stops - // propagation. - DispatchPhase::Capture => { - let mut pending_mouse_down = pending_mouse_down.borrow_mut(); - if pending_mouse_down.is_some() { - captured_mouse_down = pending_mouse_down.take(); + cx.on_mouse_event(move |down: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Bubble && !cx.default_prevented() { + let group = active_group_bounds + .map_or(false, |bounds| bounds.contains(&down.position)); + let element = interactive_bounds.visibly_contains(&down.position, cx); + if group || element { + *active_state.borrow_mut() = ElementClickedState { group, element }; cx.notify(); } } - // Fire click handlers during the bubble phase. - DispatchPhase::Bubble => { - if let Some(mouse_down) = captured_mouse_down.take() { - if interactive_bounds.visibly_contains(&event.position, cx) { - let mouse_click = ClickEvent { - down: mouse_down, - up: event.clone(), - }; - for listener in &click_listeners { - listener(&mouse_click, cx); - } - } - } - } - } - }); - } - - if let Some(hover_listener) = self.hover_listener.take() { - let was_hovered = element_state - .hover_state - .get_or_insert_with(Default::default) - .clone(); - let has_mouse_down = element_state - .pending_mouse_down - .get_or_insert_with(Default::default) - .clone(); - let interactive_bounds = interactive_bounds.clone(); - - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - if phase != DispatchPhase::Bubble { - return; - } - let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) - && has_mouse_down.borrow().is_none(); - let mut was_hovered = was_hovered.borrow_mut(); - - if is_hovered != was_hovered.clone() { - *was_hovered = is_hovered; - drop(was_hovered); - - hover_listener(&is_hovered, cx); - } - }); - } - - if let Some(tooltip_builder) = self.tooltip_builder.take() { - let active_tooltip = element_state - .active_tooltip - .get_or_insert_with(Default::default) - .clone(); - let pending_mouse_down = element_state - .pending_mouse_down - .get_or_insert_with(Default::default) - .clone(); - let interactive_bounds = interactive_bounds.clone(); - - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) - && pending_mouse_down.borrow().is_none(); - if !is_hovered { - active_tooltip.borrow_mut().take(); - return; - } - - if phase != DispatchPhase::Bubble { - return; - } - - if active_tooltip.borrow().is_none() { - let task = cx.spawn({ - let active_tooltip = active_tooltip.clone(); - let tooltip_builder = tooltip_builder.clone(); - - move |mut cx| async move { - cx.background_executor().timer(TOOLTIP_DELAY).await; - cx.update(|_, cx| { - active_tooltip.borrow_mut().replace(ActiveTooltip { - tooltip: Some(AnyTooltip { - view: tooltip_builder(cx), - cursor_offset: cx.mouse_position(), - }), - _task: None, - }); - cx.notify(); - }) - .ok(); - } - }); - active_tooltip.borrow_mut().replace(ActiveTooltip { - tooltip: None, - _task: Some(task), - }); - } - }); - - let active_tooltip = element_state - .active_tooltip - .get_or_insert_with(Default::default) - .clone(); - cx.on_mouse_event(move |_: &MouseDownEvent, _, _| { - active_tooltip.borrow_mut().take(); - }); - - if let Some(active_tooltip) = element_state - .active_tooltip - .get_or_insert_with(Default::default) - .borrow() - .as_ref() - { - if active_tooltip.tooltip.is_some() { - cx.active_tooltip = active_tooltip.tooltip.clone() - } + }); } - } - let active_state = element_state - .clicked_state - .get_or_insert_with(Default::default) - .clone(); - if active_state.borrow().is_clicked() { - cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Capture { - *active_state.borrow_mut() = ElementClickedState::default(); - cx.notify(); + let overflow = style.overflow; + if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll { + if let Some(scroll_handle) = &self.scroll_handle { + scroll_handle.0.borrow_mut().overflow = overflow; } - }); - } else { - let active_group_bounds = self - .group_active_style - .as_ref() - .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |down: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble && !cx.default_prevented() { - let group = - active_group_bounds.map_or(false, |bounds| bounds.contains(&down.position)); - let element = interactive_bounds.visibly_contains(&down.position, cx); - if group || element { - *active_state.borrow_mut() = ElementClickedState { group, element }; - cx.notify(); + + let scroll_offset = element_state + .scroll_offset + .get_or_insert_with(Rc::default) + .clone(); + let line_height = cx.line_height(); + let scroll_max = (content_size - bounds.size).max(&Size::default()); + let interactive_bounds = interactive_bounds.clone(); + + cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { + let mut scroll_offset = scroll_offset.borrow_mut(); + let old_scroll_offset = *scroll_offset; + let delta = event.delta.pixel_delta(line_height); + + if overflow.x == Overflow::Scroll { + scroll_offset.x = + (scroll_offset.x + delta.x).clamp(-scroll_max.width, px(0.)); + } + + if overflow.y == Overflow::Scroll { + scroll_offset.y = + (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); + } + + if *scroll_offset != old_scroll_offset { + cx.notify(); + cx.stop_propagation(); + } } - } - }); - } + }); + } - let overflow = style.overflow; - if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll { - if let Some(scroll_handle) = &self.scroll_handle { - scroll_handle.0.borrow_mut().overflow = overflow; + if let Some(group) = self.group.clone() { + GroupBounds::push(group, bounds, cx); } let scroll_offset = element_state .scroll_offset - .get_or_insert_with(Rc::default) - .clone(); - let line_height = cx.line_height(); - let scroll_max = (content_size - bounds.size).max(&Size::default()); - let interactive_bounds = interactive_bounds.clone(); + .as_ref() + .map(|scroll_offset| *scroll_offset.borrow()); - cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && interactive_bounds.visibly_contains(&event.position, cx) - { - let mut scroll_offset = scroll_offset.borrow_mut(); - let old_scroll_offset = *scroll_offset; - let delta = event.delta.pixel_delta(line_height); - - if overflow.x == Overflow::Scroll { - scroll_offset.x = - (scroll_offset.x + delta.x).clamp(-scroll_max.width, px(0.)); + let key_down_listeners = mem::take(&mut self.key_down_listeners); + let key_up_listeners = mem::take(&mut self.key_up_listeners); + let action_listeners = mem::take(&mut self.action_listeners); + cx.with_key_dispatch( + self.key_context.clone(), + element_state.focus_handle.clone(), + |_, cx| { + for listener in key_down_listeners { + cx.on_key_event(move |event: &KeyDownEvent, phase, cx| { + listener(event, phase, cx); + }) } - if overflow.y == Overflow::Scroll { - scroll_offset.y = - (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); + for listener in key_up_listeners { + cx.on_key_event(move |event: &KeyUpEvent, phase, cx| { + listener(event, phase, cx); + }) } - if *scroll_offset != old_scroll_offset { - cx.notify(); - cx.stop_propagation(); + for (action_type, listener) in action_listeners { + cx.on_action(action_type, listener) } - } - }); - } - if let Some(group) = self.group.clone() { - GroupBounds::push(group, bounds, cx); - } + f(style, scroll_offset.unwrap_or_default(), cx) + }, + ); - let scroll_offset = element_state - .scroll_offset - .as_ref() - .map(|scroll_offset| *scroll_offset.borrow()); - - let key_down_listeners = mem::take(&mut self.key_down_listeners); - let key_up_listeners = mem::take(&mut self.key_up_listeners); - let action_listeners = mem::take(&mut self.action_listeners); - cx.with_key_dispatch( - self.key_context.clone(), - element_state.focus_handle.clone(), - |_, cx| { - for listener in key_down_listeners { - cx.on_key_event(move |event: &KeyDownEvent, phase, cx| { - listener(event, phase, cx); - }) - } - - for listener in key_up_listeners { - cx.on_key_event(move |event: &KeyUpEvent, phase, cx| { - listener(event, phase, cx); - }) - } - - for (action_type, listener) in action_listeners { - cx.on_action(action_type, listener) - } - - f(style, scroll_offset.unwrap_or_default(), cx) - }, - ); - - if let Some(group) = self.group.as_ref() { - GroupBounds::pop(group, cx); - } + if let Some(group) = self.group.as_ref() { + GroupBounds::pop(group, cx); + } + }); } pub fn compute_style( diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 26b1df4cda..7fba7ef477 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -200,58 +200,56 @@ impl Element for UniformList { bounds.lower_right() - point(border.right + padding.right, border.bottom), ); - cx.with_z_index(style.z_index.unwrap_or(0), |cx| { - style.paint(bounds, cx, |cx| { - if self.item_count > 0 { - let content_height = - item_height * self.item_count + padding.top + padding.bottom; - let min_scroll_offset = padded_bounds.size.height - content_height; - let is_scrolled = scroll_offset.y != px(0.); + style.paint(bounds, cx, |cx| { + if self.item_count > 0 { + let content_height = + item_height * self.item_count + padding.top + padding.bottom; + let min_scroll_offset = padded_bounds.size.height - content_height; + let is_scrolled = scroll_offset.y != px(0.); - if is_scrolled && scroll_offset.y < min_scroll_offset { - shared_scroll_offset.borrow_mut().y = min_scroll_offset; - scroll_offset.y = min_scroll_offset; - } + if is_scrolled && scroll_offset.y < min_scroll_offset { + shared_scroll_offset.borrow_mut().y = min_scroll_offset; + scroll_offset.y = min_scroll_offset; + } - if let Some(scroll_handle) = self.scroll_handle.clone() { - scroll_handle.0.borrow_mut().replace(ScrollHandleState { - item_height, - list_height: padded_bounds.size.height, - scroll_offset: shared_scroll_offset, - }); - } - - let first_visible_element_ix = - (-(scroll_offset.y + padding.top) / item_height).floor() as usize; - let last_visible_element_ix = - ((-scroll_offset.y + padded_bounds.size.height) / item_height) - .ceil() as usize; - let visible_range = first_visible_element_ix - ..cmp::min(last_visible_element_ix, self.item_count); - - let mut items = (self.render_items)(visible_range.clone(), cx); - cx.with_z_index(1, |cx| { - let content_mask = ContentMask { bounds }; - cx.with_content_mask(Some(content_mask), |cx| { - for (item, ix) in items.iter_mut().zip(visible_range) { - let item_origin = padded_bounds.origin - + point( - px(0.), - item_height * ix + scroll_offset.y + padding.top, - ); - let available_space = size( - AvailableSpace::Definite(padded_bounds.size.width), - AvailableSpace::Definite(item_height), - ); - item.draw(item_origin, available_space, cx); - } - }); + if let Some(scroll_handle) = self.scroll_handle.clone() { + scroll_handle.0.borrow_mut().replace(ScrollHandleState { + item_height, + list_height: padded_bounds.size.height, + scroll_offset: shared_scroll_offset, }); } - }); - }) + + let first_visible_element_ix = + (-(scroll_offset.y + padding.top) / item_height).floor() as usize; + let last_visible_element_ix = + ((-scroll_offset.y + padded_bounds.size.height) / item_height).ceil() + as usize; + let visible_range = first_visible_element_ix + ..cmp::min(last_visible_element_ix, self.item_count); + + let mut items = (self.render_items)(visible_range.clone(), cx); + cx.with_z_index(1, |cx| { + let content_mask = ContentMask { bounds }; + cx.with_content_mask(Some(content_mask), |cx| { + for (item, ix) in items.iter_mut().zip(visible_range) { + let item_origin = padded_bounds.origin + + point( + px(0.), + item_height * ix + scroll_offset.y + padding.top, + ); + let available_space = size( + AvailableSpace::Definite(padded_bounds.size.width), + AvailableSpace::Definite(item_height), + ); + item.draw(item_origin, available_space, cx); + } + }); + }); + } + }); }, - ); + ) } } From 2979eb9da96c2b5940e94af863dd8fa966518aeb Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 18 Dec 2023 18:32:03 -0800 Subject: [PATCH 130/644] Allow transparent divs to be considered "top layers" This changes the meaning of `was_top_layer` so that it is checking that nothing opaque is on top of the given layer. The layer in question need not be opaque. --- crates/gpui2/src/window.rs | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 0cef164460..ccfdb6a273 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -942,16 +942,20 @@ impl<'a> WindowContext<'a> { } } - /// Returns true if the top-most opaque layer painted over this point was part of the - /// same layer as the given stacking order. + /// Returns true if there is no opaque layer containing the given point + /// on top of the given level. Layers whose level is an extension of the + /// level are not considered to be on top of the level. pub fn was_top_layer(&self, point: &Point, level: &StackingOrder) -> bool { - for (stack, bounds) in self.window.rendered_frame.depth_map.iter() { - if bounds.contains(point) { - return level.starts_with(stack) || stack.starts_with(level); + for (opaque_level, bounds) in self.window.rendered_frame.depth_map.iter() { + if level >= opaque_level { + break; + } + + if bounds.contains(point) && !opaque_level.starts_with(level) { + return false; } } - - false + true } pub fn was_top_layer_under_active_drag( @@ -959,16 +963,19 @@ impl<'a> WindowContext<'a> { point: &Point, level: &StackingOrder, ) -> bool { - for (stack, bounds) in self.window.rendered_frame.depth_map.iter() { - if stack.starts_with(&[ACTIVE_DRAG_Z_INDEX]) { + for (opaque_level, bounds) in self.window.rendered_frame.depth_map.iter() { + if level >= opaque_level { + break; + } + if opaque_level.starts_with(&[ACTIVE_DRAG_Z_INDEX]) { continue; } - if bounds.contains(point) { - return level.starts_with(stack) || stack.starts_with(level); + + if bounds.contains(point) && !opaque_level.starts_with(level) { + return false; } } - - false + true } /// Called during painting to get the current stacking order. From 4b74f30d0a24afde4e6f118504f5778137cccdae Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 19 Dec 2023 06:44:26 +0200 Subject: [PATCH 131/644] Properly restore termina current dir when deserializing the project --- crates/terminal_view2/src/terminal_view.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/terminal_view2/src/terminal_view.rs b/crates/terminal_view2/src/terminal_view.rs index 1ac5ba8ab5..f82a43959b 100644 --- a/crates/terminal_view2/src/terminal_view.rs +++ b/crates/terminal_view2/src/terminal_view.rs @@ -752,8 +752,7 @@ impl Item for TerminalView { ) -> Task>> { let window = cx.window_handle(); cx.spawn(|pane, mut cx| async move { - let cwd = None; - TERMINAL_DB + let cwd = TERMINAL_DB .get_working_directory(item_id, workspace_id) .log_err() .flatten() From ba0d7e35bb74cf09833828542fbe0e0094287812 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Dec 2023 10:26:06 +0100 Subject: [PATCH 132/644] Set window edited --- crates/gpui2/src/window.rs | 4 ++++ crates/workspace2/src/workspace2.rs | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 0cef164460..ca91a806ad 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -773,6 +773,10 @@ impl<'a> WindowContext<'a> { self.window.platform_window.set_title(title); } + pub fn set_window_edited(&mut self, edited: bool) { + self.window.platform_window.set_edited(edited); + } + pub fn display(&self) -> Option> { self.platform .displays() diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 8cb8c3dc9a..4f911d1073 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -2520,8 +2520,7 @@ impl Workspace { .any(|item| item.has_conflict(cx) || item.is_dirty(cx)); if is_edited != self.window_edited { self.window_edited = is_edited; - // todo!() - // cx.set_window_edited(self.window_edited) + cx.set_window_edited(self.window_edited) } } From ae32706cfed3b5e51f4f7a4990b8e8fc0b22399b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Dec 2023 11:04:32 +0100 Subject: [PATCH 133/644] Fix tests --- crates/gpui2/src/app/test_context.rs | 7 +------ crates/gpui2/src/platform/test/window.rs | 12 +++++++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index 9f0c7e6aca..c77ec29bdf 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -567,12 +567,7 @@ impl<'a> VisualTestContext<'a> { pub fn window_title(&mut self) -> Option { self.cx .update_window(self.window, |_, cx| { - cx.window - .platform_window - .as_test() - .unwrap() - .window_title - .clone() + cx.window.platform_window.as_test().unwrap().title.clone() }) .unwrap() } diff --git a/crates/gpui2/src/platform/test/window.rs b/crates/gpui2/src/platform/test/window.rs index 0f981d4478..9df513d1f7 100644 --- a/crates/gpui2/src/platform/test/window.rs +++ b/crates/gpui2/src/platform/test/window.rs @@ -21,7 +21,8 @@ pub(crate) struct TestWindowHandlers { pub struct TestWindow { pub(crate) bounds: WindowBounds, display: Rc, - pub(crate) window_title: Option, + pub(crate) title: Option, + pub(crate) edited: bool, pub(crate) input_handler: Option>>>, pub(crate) handlers: Arc>, platform: Weak, @@ -41,7 +42,8 @@ impl TestWindow { input_handler: None, sprite_atlas: Arc::new(TestAtlas::new()), handlers: Default::default(), - window_title: Default::default(), + title: Default::default(), + edited: false, } } } @@ -109,11 +111,11 @@ impl PlatformWindow for TestWindow { } fn set_title(&mut self, title: &str) { - self.window_title = Some(title.to_owned()); + self.title = Some(title.to_owned()); } - fn set_edited(&mut self, _edited: bool) { - unimplemented!() + fn set_edited(&mut self, edited: bool) { + self.edited = edited; } fn show_character_palette(&self) { From 02e53025f30efbd56b7b03f53d1aaf4237742ba1 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Dec 2023 14:26:30 +0100 Subject: [PATCH 134/644] Track caller on h_stack and v_stack --- crates/gpui2/src/elements/div.rs | 2 +- crates/ui2/src/components/stack.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 1f56f44900..631ffc43c6 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1065,7 +1065,7 @@ impl Interactivity { { cx.focus(&focus_handle); // If there is a parent that is also focusable, prevent it - // from trasferring focus because we already did so. + // from transferring focus because we already did so. cx.prevent_default(); } } diff --git a/crates/ui2/src/components/stack.rs b/crates/ui2/src/components/stack.rs index 6ae88cb1a2..a6321b93d7 100644 --- a/crates/ui2/src/components/stack.rs +++ b/crates/ui2/src/components/stack.rs @@ -5,6 +5,7 @@ use crate::StyledExt; /// Horizontally stacks elements. /// /// Sets `flex()`, `flex_row()`, `items_center()` +#[track_caller] pub fn h_stack() -> Div { div().h_flex() } @@ -12,6 +13,7 @@ pub fn h_stack() -> Div { /// Vertically stacks elements. /// /// Sets `flex()`, `flex_col()` +#[track_caller] pub fn v_stack() -> Div { div().v_flex() } From afbc61a344856ed43c7397533c706db5727e7cfa Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Dec 2023 14:26:44 +0100 Subject: [PATCH 135/644] Prevent default when mousing down on a button that responds to clicks This ensures that ancestors that track focus don't accidentally steal it on mouse down, which was preventing the editor from deploying the code actions menu. --- crates/ui2/src/components/button/button_like.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/ui2/src/components/button/button_like.rs b/crates/ui2/src/components/button/button_like.rs index 54f2a0e9ea..bd4e9cd523 100644 --- a/crates/ui2/src/components/button/button_like.rs +++ b/crates/ui2/src/components/button/button_like.rs @@ -1,4 +1,4 @@ -use gpui::{relative, DefiniteLength}; +use gpui::{relative, DefiniteLength, MouseButton}; use gpui::{rems, transparent_black, AnyElement, AnyView, ClickEvent, Div, Hsla, Rems, Stateful}; use smallvec::SmallVec; @@ -372,10 +372,11 @@ impl RenderOnce for ButtonLike { .when_some( self.on_click.filter(|_| !self.disabled), |this, on_click| { - this.on_click(move |event, cx| { - cx.stop_propagation(); - (on_click)(event, cx) - }) + this.on_mouse_down(MouseButton::Left, |_, cx| cx.prevent_default()) + .on_click(move |event, cx| { + cx.stop_propagation(); + (on_click)(event, cx) + }) }, ) .when_some(self.tooltip, |this, tooltip| { From b30fd3f5743863b8fc566ecb479f97c8f57ab30f Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Dec 2023 15:29:05 +0100 Subject: [PATCH 136/644] Fix janky editor scrollbar dragging We can receive multiple events before computing the next frame, and in that case we want to compute a drag delta between the position for the previous mouse event and the current one. --- crates/editor2/src/element.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 328f2f08ba..cf34863ba6 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -1351,7 +1351,7 @@ impl EditorElement { )); } - let mouse_position = cx.mouse_position(); + let mut mouse_position = cx.mouse_position(); if track_bounds.contains(&mouse_position) { cx.set_cursor_style(CursorStyle::Arrow); } @@ -1377,6 +1377,8 @@ impl EditorElement { } editor.set_scroll_position(position, cx); } + + mouse_position = event.position; cx.stop_propagation(); } else { editor.scroll_manager.set_is_dragging_scrollbar(false, cx); @@ -1392,6 +1394,10 @@ impl EditorElement { cx.on_mouse_event({ let editor = self.editor.clone(); move |event: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Capture { + return; + } + editor.update(cx, |editor, cx| { editor.scroll_manager.set_is_dragging_scrollbar(false, cx); cx.stop_propagation(); @@ -1402,6 +1408,10 @@ impl EditorElement { cx.on_mouse_event({ let editor = self.editor.clone(); move |event: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Capture { + return; + } + editor.update(cx, |editor, cx| { if track_bounds.contains(&event.position) { editor.scroll_manager.set_is_dragging_scrollbar(true, cx); From 49502af4d3a645187b8c2c844c88864ccd7474dc Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 09:56:29 -0500 Subject: [PATCH 137/644] Update conversation item rendering --- crates/assistant2/src/assistant_panel.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 79ebb6602d..4c1abbe4b8 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -1020,10 +1020,18 @@ impl AssistantPanel { this.open_conversation(path.clone(), cx) .detach_and_log_err(cx) })) - .child(Label::new( - conversation.mtime.format("%F %I:%M%p").to_string(), - )) - .child(Label::new(conversation.title.clone())) + .child( + div() + .flex() + .flex_1() + .gap_2() + .child( + Label::new(conversation.mtime.format("%F %I:%M%p").to_string()) + .color(Color::Muted) + .size(LabelSize::Small), + ) + .child(Label::new(conversation.title.clone()).size(LabelSize::Small)), + ) } fn open_conversation(&mut self, path: PathBuf, cx: &mut ViewContext) -> Task> { From 2c402f9b5deab38e331248fe8d8d87dab5ab2926 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 10:03:26 -0500 Subject: [PATCH 138/644] Ensure conversation items fill the container --- crates/assistant2/src/assistant_panel.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 4c1abbe4b8..ec2fa4fba0 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -1020,10 +1020,11 @@ impl AssistantPanel { this.open_conversation(path.clone(), cx) .detach_and_log_err(cx) })) + .full_width() .child( div() .flex() - .flex_1() + .w_full() .gap_2() .child( Label::new(conversation.mtime.format("%F %I:%M%p").to_string()) From 42a02e4fb6c0b76457b1bcff2117b2ec2a6fd12c Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 10:03:59 -0500 Subject: [PATCH 139/644] Remove red border --- crates/assistant2/src/assistant_panel.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index ec2fa4fba0..0cac69661a 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -1174,8 +1174,6 @@ impl Render for AssistantPanel { .into_any_element() }), ) - .border() - .border_color(gpui::red()) } } } From dd84993d76b9ba0e9ab8a760ae8eba0fd61bec2d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 19 Dec 2023 16:06:00 +0100 Subject: [PATCH 140/644] Maintain scroll position in CollabPanel after updating entries Co-Authored-By: Julia --- crates/collab_ui2/src/collab_panel.rs | 49 ++++++++++++++------------- crates/gpui2/src/elements/list.rs | 2 +- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index ab82310094..2179d82cf3 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -962,15 +962,12 @@ impl CollabPanel { self.entries.push(ListEntry::ContactPlaceholder); } - self.list_state.reset(self.entries.len()); - if select_same_item { if let Some(prev_selected_entry) = prev_selected_entry { self.selection.take(); for (ix, entry) in self.entries.iter().enumerate() { if *entry == prev_selected_entry { self.selection = Some(ix); - self.scroll_to_item(ix); break; } } @@ -980,49 +977,53 @@ impl CollabPanel { if self.entries.is_empty() { None } else { - let ix = prev_selection.min(self.entries.len() - 1); - self.scroll_to_item(ix); - Some(ix) + Some(prev_selection.min(self.entries.len() - 1)) } }); } + let old_scroll_top = self.list_state.logical_scroll_top(); + self.list_state.reset(self.entries.len()); + if scroll_to_top { - self.scroll_to_item(0) + self.list_state.scroll_to(ListOffset::default()); } else { - let ListOffset { - item_ix: old_index, - offset_in_item: old_offset, - } = self.list_state.logical_scroll_top(); // Attempt to maintain the same scroll position. - if let Some(old_top_entry) = old_entries.get(old_index) { - let (new_index, new_offset) = self + if let Some(old_top_entry) = old_entries.get(old_scroll_top.item_ix) { + let new_scroll_top = self .entries .iter() .position(|entry| entry == old_top_entry) - .map(|item_ix| (item_ix, old_offset)) + .map(|item_ix| ListOffset { + item_ix, + offset_in_item: old_scroll_top.offset_in_item, + }) .or_else(|| { - let entry_after_old_top = old_entries.get(old_index + 1)?; + let entry_after_old_top = old_entries.get(old_scroll_top.item_ix + 1)?; let item_ix = self .entries .iter() .position(|entry| entry == entry_after_old_top)?; - Some((item_ix, px(0.))) + Some(ListOffset { + item_ix, + offset_in_item: Pixels::ZERO, + }) }) .or_else(|| { - let entry_before_old_top = old_entries.get(old_index.saturating_sub(1))?; + let entry_before_old_top = + old_entries.get(old_scroll_top.item_ix.saturating_sub(1))?; let item_ix = self .entries .iter() .position(|entry| entry == entry_before_old_top)?; - Some((item_ix, px(0.))) - }) - .unwrap_or_else(|| (old_index, old_offset)); + Some(ListOffset { + item_ix, + offset_in_item: Pixels::ZERO, + }) + }); - self.list_state.scroll_to(ListOffset { - item_ix: new_index, - offset_in_item: new_offset, - }); + self.list_state + .scroll_to(new_scroll_top.unwrap_or(old_scroll_top)); } } diff --git a/crates/gpui2/src/elements/list.rs b/crates/gpui2/src/elements/list.rs index 73bd319afc..a0467aaaa3 100644 --- a/crates/gpui2/src/elements/list.rs +++ b/crates/gpui2/src/elements/list.rs @@ -293,7 +293,7 @@ impl std::fmt::Debug for ListItem { } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct ListOffset { pub item_ix: usize, pub offset_in_item: Pixels, From 57efaa92cf6bb43330e1be225a151ecd1eab41ae Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 10:30:46 -0500 Subject: [PATCH 141/644] Style assistant header, update icons --- assets/icons/maximize.svg | 5 +- assets/icons/menu.svg | 4 +- assets/icons/minimize.svg | 5 +- assets/icons/quote.svg | 9 +--- assets/icons/snip.svg | 1 + assets/icons/split_message.svg | 1 - crates/assistant2/src/assistant_panel.rs | 58 ++++++++++++++++++------ crates/ui2/src/components/icon.rs | 6 ++- 8 files changed, 54 insertions(+), 35 deletions(-) create mode 100644 assets/icons/snip.svg delete mode 100644 assets/icons/split_message.svg diff --git a/assets/icons/maximize.svg b/assets/icons/maximize.svg index f37f6a2087..b3504b5701 100644 --- a/assets/icons/maximize.svg +++ b/assets/icons/maximize.svg @@ -1,4 +1 @@ - - - - + diff --git a/assets/icons/menu.svg b/assets/icons/menu.svg index 060caeecbf..6598697ff8 100644 --- a/assets/icons/menu.svg +++ b/assets/icons/menu.svg @@ -1,3 +1 @@ - - - + diff --git a/assets/icons/minimize.svg b/assets/icons/minimize.svg index ec78f152e1..0451233cc9 100644 --- a/assets/icons/minimize.svg +++ b/assets/icons/minimize.svg @@ -1,4 +1 @@ - - - - + diff --git a/assets/icons/quote.svg b/assets/icons/quote.svg index 50205479c3..b970db1430 100644 --- a/assets/icons/quote.svg +++ b/assets/icons/quote.svg @@ -1,8 +1 @@ - - - + diff --git a/assets/icons/snip.svg b/assets/icons/snip.svg new file mode 100644 index 0000000000..03ae4ce039 --- /dev/null +++ b/assets/icons/snip.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/split_message.svg b/assets/icons/split_message.svg deleted file mode 100644 index 54d9e81224..0000000000 --- a/assets/icons/split_message.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 0cac69661a..17a020fb9c 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -54,7 +54,8 @@ use std::{ }; use theme::ThemeSettings; use ui::{ - h_stack, prelude::*, v_stack, Button, ButtonLike, Icon, IconButton, IconElement, Label, Tooltip, + h_stack, prelude::*, v_stack, Button, ButtonLike, Icon, IconButton, IconElement, Label, TabBar, + Tooltip, }; use util::{paths::CONVERSATIONS_DIR, post_inc, ResultExt, TryFutureExt}; use uuid::Uuid; @@ -939,7 +940,7 @@ impl AssistantPanel { this.set_active_editor_index(this.prev_active_editor_index, cx); } })) - .tooltip(|cx| Tooltip::text("History", cx)) + .tooltip(|cx| Tooltip::text("Conversation History", cx)) } fn render_editor_tools(&self, cx: &mut ViewContext) -> Vec { @@ -955,12 +956,13 @@ impl AssistantPanel { } fn render_split_button(cx: &mut ViewContext) -> impl IntoElement { - IconButton::new("split_button", Icon::SplitMessage) + IconButton::new("split_button", Icon::Snip) .on_click(cx.listener(|this, _event, cx| { if let Some(active_editor) = this.active_editor() { active_editor.update(cx, |editor, cx| editor.split(&Default::default(), cx)); } })) + .icon_size(IconSize::Small) .tooltip(|cx| Tooltip::for_action("Split Message", &Split, cx)) } @@ -971,6 +973,7 @@ impl AssistantPanel { active_editor.update(cx, |editor, cx| editor.assist(&Default::default(), cx)); } })) + .icon_size(IconSize::Small) .tooltip(|cx| Tooltip::for_action("Assist", &Assist, cx)) } @@ -985,6 +988,7 @@ impl AssistantPanel { }); } })) + .icon_size(IconSize::Small) .tooltip(|cx| Tooltip::for_action("Quote Seleciton", &QuoteSelection, cx)) } @@ -993,15 +997,19 @@ impl AssistantPanel { .on_click(cx.listener(|this, _event, cx| { this.new_conversation(cx); })) + .icon_size(IconSize::Small) .tooltip(|cx| Tooltip::for_action("New Conversation", &NewConversation, cx)) } fn render_zoom_button(&self, cx: &mut ViewContext) -> impl IntoElement { let zoomed = self.zoomed; - IconButton::new("zoom_button", Icon::MagnifyingGlass) + IconButton::new("zoom_button", Icon::Maximize) .on_click(cx.listener(|this, _event, cx| { this.toggle_zoom(&ToggleZoom, cx); })) + .selected(zoomed) + .selected_icon(Icon::Minimize) + .icon_size(IconSize::Small) .tooltip(move |cx| { Tooltip::for_action(if zoomed { "Zoom Out" } else { "Zoom In" }, &ToggleZoom, cx) }) @@ -1125,16 +1133,40 @@ impl Render for AssistantPanel { .active_editor() .map(|editor| Label::new(editor.read(cx).title(cx))); - let mut header = h_stack() - .child(Self::render_hamburger_button(cx)) - .children(title); + // let mut header = h_stack() + // .p_1() + // .border_b() + // .border_color(cx.theme().colors().border_variant) + // .bg(cx.theme().colors().toolbar_background) + // .child(div().flex_1()); - if self.focus_handle.contains_focused(cx) { - header = header - .children(self.render_editor_tools(cx)) - .child(Self::render_plus_button(cx)) - .child(self.render_zoom_button(cx)); - } + let header = TabBar::new("assistant_header") + .start_child( + h_stack() + .gap_1() + .child(Self::render_hamburger_button(cx)) + .children(title), + ) + .end_child(if self.focus_handle.contains_focused(cx) { + h_stack() + .gap_1() + .children(self.render_editor_tools(cx)) + .child(Self::render_plus_button(cx)) + .child(self.render_zoom_button(cx)) + } else { + div() + }); + + // if self.focus_handle.contains_focused(cx) { + // header = header.child( + // div() + // .flex() + // .gap_1() + // .children(self.render_editor_tools(cx)) + // .child(Self::render_plus_button(cx)) + // .child(self.render_zoom_button(cx)), + // ); + // } v_stack() .size_full() diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index 6216acac48..ca50cae7f8 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -75,6 +75,7 @@ pub enum Icon { MagnifyingGlass, MailOpen, Maximize, + Minimize, Menu, MessageBubbles, Mic, @@ -88,7 +89,7 @@ pub enum Icon { Screen, SelectAll, Split, - SplitMessage, + Snip, Terminal, WholeWord, XCircle, @@ -156,6 +157,7 @@ impl Icon { Icon::MagnifyingGlass => "icons/magnifying_glass.svg", Icon::MailOpen => "icons/mail-open.svg", Icon::Maximize => "icons/maximize.svg", + Icon::Minimize => "icons/minimize.svg", Icon::Menu => "icons/menu.svg", Icon::MessageBubbles => "icons/conversations.svg", Icon::Mic => "icons/mic.svg", @@ -169,7 +171,7 @@ impl Icon { Icon::Screen => "icons/desktop.svg", Icon::SelectAll => "icons/select-all.svg", Icon::Split => "icons/split.svg", - Icon::SplitMessage => "icons/split_message.svg", + Icon::Snip => "icons/snip.svg", Icon::Terminal => "icons/terminal.svg", Icon::WholeWord => "icons/word_search.svg", Icon::XCircle => "icons/error.svg", From 286f654517ad64bd2a342951de14358573ae554e Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 10:57:36 -0500 Subject: [PATCH 142/644] Update assistant header --- crates/assistant2/src/assistant_panel.rs | 53 ++++++++++-------------- crates/ui2/src/components/divider.rs | 28 ++++++++++++- crates/ui2/src/components/tab.rs | 6 +-- 3 files changed, 51 insertions(+), 36 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 17a020fb9c..b0b1378dbd 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -55,7 +55,7 @@ use std::{ use theme::ThemeSettings; use ui::{ h_stack, prelude::*, v_stack, Button, ButtonLike, Icon, IconButton, IconElement, Label, TabBar, - Tooltip, + Tooltip, TAB_HEIGHT_IN_REMS, }; use util::{paths::CONVERSATIONS_DIR, post_inc, ResultExt, TryFutureExt}; use uuid::Uuid; @@ -1129,45 +1129,36 @@ impl Render for AssistantPanel { .border() .border_color(gpui::red()) } else { - let title = self - .active_editor() - .map(|editor| Label::new(editor.read(cx).title(cx))); - - // let mut header = h_stack() - // .p_1() - // .border_b() - // .border_color(cx.theme().colors().border_variant) - // .bg(cx.theme().colors().toolbar_background) - // .child(div().flex_1()); - let header = TabBar::new("assistant_header") .start_child( - h_stack() - .gap_1() - .child(Self::render_hamburger_button(cx)) - .children(title), + h_stack().gap_1().child(Self::render_hamburger_button(cx)), // .children(title), ) + .children(self.active_editor().map(|editor| { + h_stack() + .h(rems(TAB_HEIGHT_IN_REMS)) + .flex_1() + .px_2() + .child(Label::new(editor.read(cx).title(cx)).into_element()) + })) .end_child(if self.focus_handle.contains_focused(cx) { h_stack() - .gap_1() - .children(self.render_editor_tools(cx)) - .child(Self::render_plus_button(cx)) - .child(self.render_zoom_button(cx)) + .gap_2() + .child(h_stack().gap_1().children(self.render_editor_tools(cx))) + .child( + ui::Divider::vertical() + .inset() + .color(ui::DividerColor::Border), + ) + .child( + h_stack() + .gap_1() + .child(Self::render_plus_button(cx)) + .child(self.render_zoom_button(cx)), + ) } else { div() }); - // if self.focus_handle.contains_focused(cx) { - // header = header.child( - // div() - // .flex() - // .gap_1() - // .children(self.render_editor_tools(cx)) - // .child(Self::render_plus_button(cx)) - // .child(self.render_zoom_button(cx)), - // ); - // } - v_stack() .size_full() .on_action(cx.listener(|this, _: &workspace::NewFile, cx| { diff --git a/crates/ui2/src/components/divider.rs b/crates/ui2/src/components/divider.rs index cb48ce00ae..20744d6c48 100644 --- a/crates/ui2/src/components/divider.rs +++ b/crates/ui2/src/components/divider.rs @@ -1,4 +1,4 @@ -use gpui::{Div, IntoElement}; +use gpui::{Div, Hsla, IntoElement}; use crate::prelude::*; @@ -7,9 +7,26 @@ enum DividerDirection { Vertical, } +#[derive(Default)] +pub enum DividerColor { + Border, + #[default] + BorderVariant, +} + +impl DividerColor { + pub fn hsla(self, cx: &WindowContext) -> Hsla { + match self { + DividerColor::Border => cx.theme().colors().border, + DividerColor::BorderVariant => cx.theme().colors().border_variant, + } + } +} + #[derive(IntoElement)] pub struct Divider { direction: DividerDirection, + color: DividerColor, inset: bool, } @@ -26,7 +43,7 @@ impl RenderOnce for Divider { this.w_px().h_full().when(self.inset, |this| this.my_1p5()) } }) - .bg(cx.theme().colors().border_variant) + .bg(self.color.hsla(cx)) } } @@ -34,6 +51,7 @@ impl Divider { pub fn horizontal() -> Self { Self { direction: DividerDirection::Horizontal, + color: DividerColor::default(), inset: false, } } @@ -41,6 +59,7 @@ impl Divider { pub fn vertical() -> Self { Self { direction: DividerDirection::Vertical, + color: DividerColor::default(), inset: false, } } @@ -49,4 +68,9 @@ impl Divider { self.inset = true; self } + + pub fn color(mut self, color: DividerColor) -> Self { + self.color = color; + self + } } diff --git a/crates/ui2/src/components/tab.rs b/crates/ui2/src/components/tab.rs index 8114a322e3..7f20a92329 100644 --- a/crates/ui2/src/components/tab.rs +++ b/crates/ui2/src/components/tab.rs @@ -3,6 +3,8 @@ use gpui::{AnyElement, IntoElement, Stateful}; use smallvec::SmallVec; use std::cmp::Ordering; +pub const TAB_HEIGHT_IN_REMS: f32 = 30. / 16.; + /// The position of a [`Tab`] within a list of tabs. #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum TabPosition { @@ -94,8 +96,6 @@ impl RenderOnce for Tab { type Rendered = Stateful
; fn render(self, cx: &mut WindowContext) -> Self::Rendered { - const HEIGHT_IN_REMS: f32 = 30. / 16.; - let (text_color, tab_bg, _tab_hover_bg, _tab_active_bg) = match self.selected { false => ( cx.theme().colors().text_muted, @@ -112,7 +112,7 @@ impl RenderOnce for Tab { }; self.div - .h(rems(HEIGHT_IN_REMS)) + .h(rems(TAB_HEIGHT_IN_REMS)) .bg(tab_bg) .border_color(cx.theme().colors().border) .map(|this| match self.position { From 30b01b9bc0699763f2ea72dcd273dfe4d9da30d8 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 11:03:08 -0500 Subject: [PATCH 143/644] Update imports, tab height const --- crates/assistant2/src/assistant_panel.rs | 9 +++------ crates/ui2/src/components/tab.rs | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index b0b1378dbd..94be39f924 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -53,10 +53,7 @@ use std::{ time::{Duration, Instant}, }; use theme::ThemeSettings; -use ui::{ - h_stack, prelude::*, v_stack, Button, ButtonLike, Icon, IconButton, IconElement, Label, TabBar, - Tooltip, TAB_HEIGHT_IN_REMS, -}; +use ui::{prelude::*, Tab, TabBar, Tooltip}; use util::{paths::CONVERSATIONS_DIR, post_inc, ResultExt, TryFutureExt}; use uuid::Uuid; use workspace::{ @@ -1129,13 +1126,13 @@ impl Render for AssistantPanel { .border() .border_color(gpui::red()) } else { - let header = TabBar::new("assistant_header") + let header = ui::TabBar::new("assistant_header") .start_child( h_stack().gap_1().child(Self::render_hamburger_button(cx)), // .children(title), ) .children(self.active_editor().map(|editor| { h_stack() - .h(rems(TAB_HEIGHT_IN_REMS)) + .h(rems(ui::Tab::HEIGHT_IN_REMS)) .flex_1() .px_2() .child(Label::new(editor.read(cx).title(cx)).into_element()) diff --git a/crates/ui2/src/components/tab.rs b/crates/ui2/src/components/tab.rs index 7f20a92329..eddfab8119 100644 --- a/crates/ui2/src/components/tab.rs +++ b/crates/ui2/src/components/tab.rs @@ -3,8 +3,6 @@ use gpui::{AnyElement, IntoElement, Stateful}; use smallvec::SmallVec; use std::cmp::Ordering; -pub const TAB_HEIGHT_IN_REMS: f32 = 30. / 16.; - /// The position of a [`Tab`] within a list of tabs. #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum TabPosition { @@ -50,6 +48,8 @@ impl Tab { } } + pub const HEIGHT_IN_REMS: f32 = 30. / 16.; + pub fn position(mut self, position: TabPosition) -> Self { self.position = position; self @@ -112,7 +112,7 @@ impl RenderOnce for Tab { }; self.div - .h(rems(TAB_HEIGHT_IN_REMS)) + .h(rems(Self::HEIGHT_IN_REMS)) .bg(tab_bg) .border_color(cx.theme().colors().border) .map(|this| match self.position { From ae313ff83075474d1eed8de1ac840a2eafd59710 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 11:16:59 -0500 Subject: [PATCH 144/644] Allow format_distance to take a DateTimeType --- crates/ui2/src/utils/format_distance.rs | 65 +++++++++++++++++-------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/crates/ui2/src/utils/format_distance.rs b/crates/ui2/src/utils/format_distance.rs index d157d30bbe..f13e92bbe9 100644 --- a/crates/ui2/src/utils/format_distance.rs +++ b/crates/ui2/src/utils/format_distance.rs @@ -1,4 +1,23 @@ -use chrono::NaiveDateTime; +use chrono::{DateTime, Local, NaiveDateTime}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum DateTimeType { + Naive(NaiveDateTime), + Local(DateTime), +} + +impl DateTimeType { + /// Converts the DateTimeType to a NaiveDateTime. + /// + /// If the DateTimeType is already a NaiveDateTime, it will be returned as is. + /// If the DateTimeType is a DateTime, it will be converted to a NaiveDateTime. + pub fn to_naive(&self) -> NaiveDateTime { + match self { + DateTimeType::Naive(naive) => *naive, + DateTimeType::Local(local) => local.naive_local(), + } + } +} /// Calculates the distance in seconds between two NaiveDateTime objects. /// It returns a signed integer denoting the difference. If `date` is earlier than `base_date`, the returned value will be negative. @@ -108,13 +127,13 @@ fn distance_string(distance: i64, include_seconds: bool, add_suffix: bool) -> St /// ``` /// /// Output: `"There was about 3 years between the first and last crewed moon landings."` -pub fn naive_format_distance( - date: NaiveDateTime, +pub fn format_distance( + date: DateTimeType, base_date: NaiveDateTime, include_seconds: bool, add_suffix: bool, ) -> String { - let distance = distance_in_seconds(date, base_date); + let distance = distance_in_seconds(date.to_naive(), base_date); distance_string(distance, include_seconds, add_suffix) } @@ -142,14 +161,14 @@ pub fn naive_format_distance( /// ``` /// /// Output: `It's been over 54 years since Apollo 11 first landed on the moon.` -pub fn naive_format_distance_from_now( - datetime: NaiveDateTime, +pub fn format_distance_from_now( + datetime: DateTimeType, include_seconds: bool, add_suffix: bool, ) -> String { let now = chrono::offset::Local::now().naive_local(); - naive_format_distance(datetime, now, include_seconds, add_suffix) + format_distance(datetime, now, include_seconds, add_suffix) } #[cfg(test)] @@ -159,38 +178,44 @@ mod tests { #[test] fn test_naive_format_distance() { - let date = - NaiveDateTime::from_timestamp_opt(9600, 0).expect("Invalid NaiveDateTime for date"); - let base_date = - NaiveDateTime::from_timestamp_opt(0, 0).expect("Invalid NaiveDateTime for base_date"); + let date = DateTimeType::Naive( + NaiveDateTime::from_timestamp_opt(9600, 0).expect("Invalid NaiveDateTime for date"), + ); + let base_date = DateTimeType::Naive( + NaiveDateTime::from_timestamp_opt(0, 0).expect("Invalid NaiveDateTime for base_date"), + ); assert_eq!( "about 2 hours", - naive_format_distance(date, base_date, false, false) + format_distance(date, base_date.to_naive(), false, false) ); } #[test] fn test_naive_format_distance_with_suffix() { - let date = - NaiveDateTime::from_timestamp_opt(9600, 0).expect("Invalid NaiveDateTime for date"); - let base_date = - NaiveDateTime::from_timestamp_opt(0, 0).expect("Invalid NaiveDateTime for base_date"); + let date = DateTimeType::Naive( + NaiveDateTime::from_timestamp_opt(9600, 0).expect("Invalid NaiveDateTime for date"), + ); + let base_date = DateTimeType::Naive( + NaiveDateTime::from_timestamp_opt(0, 0).expect("Invalid NaiveDateTime for base_date"), + ); assert_eq!( "about 2 hours from now", - naive_format_distance(date, base_date, false, true) + format_distance(date, base_date.to_naive(), false, true) ); } #[test] fn test_naive_format_distance_from_now() { - let date = NaiveDateTime::parse_from_str("1969-07-20T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ") - .expect("Invalid NaiveDateTime for date"); + let date = DateTimeType::Naive( + NaiveDateTime::parse_from_str("1969-07-20T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ") + .expect("Invalid NaiveDateTime for date"), + ); assert_eq!( "over 54 years ago", - naive_format_distance_from_now(date, false, true) + format_distance_from_now(date, false, true) ); } From 79653d2175ed1ac8a037fb843465012203af0aa0 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 11:19:18 -0500 Subject: [PATCH 145/644] Rename format distance test names --- crates/ui2/src/utils/format_distance.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/ui2/src/utils/format_distance.rs b/crates/ui2/src/utils/format_distance.rs index f13e92bbe9..ec9a8ad5d8 100644 --- a/crates/ui2/src/utils/format_distance.rs +++ b/crates/ui2/src/utils/format_distance.rs @@ -177,7 +177,7 @@ mod tests { use chrono::NaiveDateTime; #[test] - fn test_naive_format_distance() { + fn test_format_distance() { let date = DateTimeType::Naive( NaiveDateTime::from_timestamp_opt(9600, 0).expect("Invalid NaiveDateTime for date"), ); @@ -192,7 +192,7 @@ mod tests { } #[test] - fn test_naive_format_distance_with_suffix() { + fn test_format_distance_with_suffix() { let date = DateTimeType::Naive( NaiveDateTime::from_timestamp_opt(9600, 0).expect("Invalid NaiveDateTime for date"), ); @@ -207,7 +207,7 @@ mod tests { } #[test] - fn test_naive_format_distance_from_now() { + fn test_format_distance_from_now() { let date = DateTimeType::Naive( NaiveDateTime::parse_from_str("1969-07-20T00:00:00Z", "%Y-%m-%dT%H:%M:%SZ") .expect("Invalid NaiveDateTime for date"), @@ -220,7 +220,7 @@ mod tests { } #[test] - fn test_naive_format_distance_string() { + fn test_format_distance_string() { assert_eq!(distance_string(3, false, false), "less than a minute"); assert_eq!(distance_string(7, false, false), "less than a minute"); assert_eq!(distance_string(13, false, false), "less than a minute"); @@ -244,7 +244,7 @@ mod tests { } #[test] - fn test_naive_format_distance_string_include_seconds() { + fn test_format_distance_string_include_seconds() { assert_eq!(distance_string(3, true, false), "less than 5 seconds"); assert_eq!(distance_string(7, true, false), "less than 10 seconds"); assert_eq!(distance_string(13, true, false), "less than 20 seconds"); From 3e6b84a726d25df9dbcb8f298e2403b40b894771 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 11:26:55 -0500 Subject: [PATCH 146/644] Wire up the middle mouse button to close tabs (#3714) This PR wires up the middle mouse button to close tabs. Right now we're doing this using `on_mouse_down`, but we need a way in GPUI2 to have an `on_click` for a mouse button other than the left one. Release Notes: - N/A --- crates/workspace2/src/pane.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 65e34c9fa5..e1bb006c11 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1493,6 +1493,14 @@ impl Pane { .on_click( cx.listener(move |pane: &mut Self, _, cx| pane.activate_item(ix, true, true, cx)), ) + // TODO: This should be a click listener with the middle mouse button instead of a mouse down listener. + .on_mouse_down( + MouseButton::Middle, + cx.listener(move |pane, _event, cx| { + pane.close_item_by_id(item_id, SaveIntent::Close, cx) + .detach_and_log_err(cx); + }), + ) .on_drag( DraggedTab { pane: cx.view().clone(), From d8a8feb45c35f910c199c94f2ae96f5ea2ecc39a Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 11:41:14 -0500 Subject: [PATCH 147/644] Add FormatDistance struct, add hide_prefix option --- crates/ui2/src/utils/format_distance.rs | 265 +++++++++++++++++++----- 1 file changed, 217 insertions(+), 48 deletions(-) diff --git a/crates/ui2/src/utils/format_distance.rs b/crates/ui2/src/utils/format_distance.rs index ec9a8ad5d8..1586a6e155 100644 --- a/crates/ui2/src/utils/format_distance.rs +++ b/crates/ui2/src/utils/format_distance.rs @@ -19,6 +19,45 @@ impl DateTimeType { } } +pub struct FormatDistance { + date: DateTimeType, + base_date: DateTimeType, + include_seconds: bool, + add_suffix: bool, + hide_prefix: bool, +} + +impl FormatDistance { + pub fn new(date: DateTimeType, base_date: DateTimeType) -> Self { + Self { + date, + base_date, + include_seconds: false, + add_suffix: false, + hide_prefix: false, + } + } + + pub fn from_now(date: DateTimeType) -> Self { + Self::new(date, DateTimeType::Local(Local::now())) + } + + pub fn include_seconds(mut self, include_seconds: bool) -> Self { + self.include_seconds = include_seconds; + self + } + + pub fn add_suffix(mut self, add_suffix: bool) -> Self { + self.add_suffix = add_suffix; + self + } + + pub fn hide_prefix(mut self, hide_prefix: bool) -> Self { + self.hide_prefix = hide_prefix; + self + } +} + /// Calculates the distance in seconds between two NaiveDateTime objects. /// It returns a signed integer denoting the difference. If `date` is earlier than `base_date`, the returned value will be negative. /// @@ -32,7 +71,12 @@ fn distance_in_seconds(date: NaiveDateTime, base_date: NaiveDateTime) -> i64 { } /// Generates a string describing the time distance between two dates in a human-readable way. -fn distance_string(distance: i64, include_seconds: bool, add_suffix: bool) -> String { +fn distance_string( + distance: i64, + include_seconds: bool, + add_suffix: bool, + hide_prefix: bool, +) -> String { let suffix = if distance < 0 { " from now" } else { " ago" }; let distance = distance.abs(); @@ -43,53 +87,128 @@ fn distance_string(distance: i64, include_seconds: bool, add_suffix: bool) -> St let months = distance / 2_592_000; let string = if distance < 5 && include_seconds { - "less than 5 seconds".to_string() + if hide_prefix { + "5 seconds" + } else { + "less than 5 seconds" + } + .to_string() } else if distance < 10 && include_seconds { - "less than 10 seconds".to_string() + if hide_prefix { + "10 seconds" + } else { + "less than 10 seconds" + } + .to_string() } else if distance < 20 && include_seconds { - "less than 20 seconds".to_string() + if hide_prefix { + "20 seconds" + } else { + "less than 20 seconds" + } + .to_string() } else if distance < 40 && include_seconds { - "half a minute".to_string() + if hide_prefix { + "half a minute" + } else { + "half a minute" + } + .to_string() } else if distance < 60 && include_seconds { - "less than a minute".to_string() + if hide_prefix { + "a minute" + } else { + "less than a minute" + } + .to_string() } else if distance < 90 && include_seconds { "1 minute".to_string() } else if distance < 30 { - "less than a minute".to_string() + if hide_prefix { + "a minute" + } else { + "less than a minute" + } + .to_string() } else if distance < 90 { "1 minute".to_string() } else if distance < 2_700 { format!("{} minutes", minutes) } else if distance < 5_400 { - "about 1 hour".to_string() + if hide_prefix { + "1 hour" + } else { + "about 1 hour" + } + .to_string() } else if distance < 86_400 { - format!("about {} hours", hours) + if hide_prefix { + format!("{} hours", hours) + } else { + format!("about {} hours", hours) + } + .to_string() } else if distance < 172_800 { "1 day".to_string() } else if distance < 2_592_000 { format!("{} days", days) } else if distance < 5_184_000 { - "about 1 month".to_string() + if hide_prefix { + "1 month" + } else { + "about 1 month" + } + .to_string() } else if distance < 7_776_000 { - "about 2 months".to_string() + if hide_prefix { + "2 months" + } else { + "about 2 months" + } + .to_string() } else if distance < 31_540_000 { format!("{} months", months) } else if distance < 39_425_000 { - "about 1 year".to_string() + if hide_prefix { + "1 year" + } else { + "about 1 year" + } + .to_string() } else if distance < 55_195_000 { - "over 1 year".to_string() + if hide_prefix { "1 year" } else { "over 1 year" }.to_string() } else if distance < 63_080_000 { - "almost 2 years".to_string() + if hide_prefix { + "2 years" + } else { + "almost 2 years" + } + .to_string() } else { let years = distance / 31_536_000; let remaining_months = (distance % 31_536_000) / 2_592_000; if remaining_months < 3 { - format!("about {} years", years) + if hide_prefix { + format!("{} years", years) + } else { + format!("about {} years", years) + } + .to_string() } else if remaining_months < 9 { - format!("over {} years", years) + if hide_prefix { + format!("{} years", years) + } else { + format!("over {} years", years) + } + .to_string() } else { - format!("almost {} years", years + 1) + if hide_prefix { + format!("{} years", years + 1) + } else { + format!("almost {} years", years + 1) + } + .to_string() } }; @@ -132,10 +251,11 @@ pub fn format_distance( base_date: NaiveDateTime, include_seconds: bool, add_suffix: bool, + hide_prefix: bool, ) -> String { let distance = distance_in_seconds(date.to_naive(), base_date); - distance_string(distance, include_seconds, add_suffix) + distance_string(distance, include_seconds, add_suffix, hide_prefix) } /// Get the time difference between a date and now as relative human readable string. @@ -165,10 +285,11 @@ pub fn format_distance_from_now( datetime: DateTimeType, include_seconds: bool, add_suffix: bool, + hide_prefix: bool, ) -> String { let now = chrono::offset::Local::now().naive_local(); - format_distance(datetime, now, include_seconds, add_suffix) + format_distance(datetime, now, include_seconds, add_suffix, hide_prefix) } #[cfg(test)] @@ -187,7 +308,7 @@ mod tests { assert_eq!( "about 2 hours", - format_distance(date, base_date.to_naive(), false, false) + format_distance(date, base_date.to_naive(), false, false, false) ); } @@ -202,7 +323,7 @@ mod tests { assert_eq!( "about 2 hours from now", - format_distance(date, base_date.to_naive(), false, true) + format_distance(date, base_date.to_naive(), false, true, false) ); } @@ -215,41 +336,89 @@ mod tests { assert_eq!( "over 54 years ago", - format_distance_from_now(date, false, true) + format_distance_from_now(date, false, true, false) ); } #[test] fn test_format_distance_string() { - assert_eq!(distance_string(3, false, false), "less than a minute"); - assert_eq!(distance_string(7, false, false), "less than a minute"); - assert_eq!(distance_string(13, false, false), "less than a minute"); - assert_eq!(distance_string(21, false, false), "less than a minute"); - assert_eq!(distance_string(45, false, false), "1 minute"); - assert_eq!(distance_string(61, false, false), "1 minute"); - assert_eq!(distance_string(1920, false, false), "32 minutes"); - assert_eq!(distance_string(3902, false, false), "about 1 hour"); - assert_eq!(distance_string(18002, false, false), "about 5 hours"); - assert_eq!(distance_string(86470, false, false), "1 day"); - assert_eq!(distance_string(345880, false, false), "4 days"); - assert_eq!(distance_string(2764800, false, false), "about 1 month"); - assert_eq!(distance_string(5184000, false, false), "about 2 months"); - assert_eq!(distance_string(10368000, false, false), "4 months"); - assert_eq!(distance_string(34694000, false, false), "about 1 year"); - assert_eq!(distance_string(47310000, false, false), "over 1 year"); - assert_eq!(distance_string(61503000, false, false), "almost 2 years"); - assert_eq!(distance_string(160854000, false, false), "about 5 years"); - assert_eq!(distance_string(236550000, false, false), "over 7 years"); - assert_eq!(distance_string(249166000, false, false), "almost 8 years"); + assert_eq!( + distance_string(3, false, false, false), + "less than a minute" + ); + assert_eq!( + distance_string(7, false, false, false), + "less than a minute" + ); + assert_eq!( + distance_string(13, false, false, false), + "less than a minute" + ); + assert_eq!( + distance_string(21, false, false, false), + "less than a minute" + ); + assert_eq!(distance_string(45, false, false, false), "1 minute"); + assert_eq!(distance_string(61, false, false, false), "1 minute"); + assert_eq!(distance_string(1920, false, false, false), "32 minutes"); + assert_eq!(distance_string(3902, false, false, false), "about 1 hour"); + assert_eq!(distance_string(18002, false, false, false), "about 5 hours"); + assert_eq!(distance_string(86470, false, false, false), "1 day"); + assert_eq!(distance_string(345880, false, false, false), "4 days"); + assert_eq!( + distance_string(2764800, false, false, false), + "about 1 month" + ); + assert_eq!( + distance_string(5184000, false, false, false), + "about 2 months" + ); + assert_eq!(distance_string(10368000, false, false, false), "4 months"); + assert_eq!( + distance_string(34694000, false, false, false), + "about 1 year" + ); + assert_eq!( + distance_string(47310000, false, false, false), + "over 1 year" + ); + assert_eq!( + distance_string(61503000, false, false, false), + "almost 2 years" + ); + assert_eq!( + distance_string(160854000, false, false, false), + "about 5 years" + ); + assert_eq!( + distance_string(236550000, false, false, false), + "over 7 years" + ); + assert_eq!( + distance_string(249166000, false, false, false), + "almost 8 years" + ); } #[test] fn test_format_distance_string_include_seconds() { - assert_eq!(distance_string(3, true, false), "less than 5 seconds"); - assert_eq!(distance_string(7, true, false), "less than 10 seconds"); - assert_eq!(distance_string(13, true, false), "less than 20 seconds"); - assert_eq!(distance_string(21, true, false), "half a minute"); - assert_eq!(distance_string(45, true, false), "less than a minute"); - assert_eq!(distance_string(61, true, false), "1 minute"); + assert_eq!( + distance_string(3, true, false, false), + "less than 5 seconds" + ); + assert_eq!( + distance_string(7, true, false, false), + "less than 10 seconds" + ); + assert_eq!( + distance_string(13, true, false, false), + "less than 20 seconds" + ); + assert_eq!(distance_string(21, true, false, false), "half a minute"); + assert_eq!( + distance_string(45, true, false, false), + "less than a minute" + ); + assert_eq!(distance_string(61, true, false, false), "1 minute"); } } From a1085184a1432a52b2cec43e8567d47df477b3ec Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 11:57:57 -0500 Subject: [PATCH 148/644] use `to_string` to return the format distance string from FormatDistance --- crates/ui2/src/utils/format_distance.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/ui2/src/utils/format_distance.rs b/crates/ui2/src/utils/format_distance.rs index 1586a6e155..b0fce184ce 100644 --- a/crates/ui2/src/utils/format_distance.rs +++ b/crates/ui2/src/utils/format_distance.rs @@ -42,6 +42,16 @@ impl FormatDistance { Self::new(date, DateTimeType::Local(Local::now())) } + pub fn to_string(self) -> String { + format_distance( + self.date, + self.base_date.to_naive(), + self.include_seconds, + self.add_suffix, + self.hide_prefix, + ) + } + pub fn include_seconds(mut self, include_seconds: bool) -> Self { self.include_seconds = include_seconds; self From d8eea949eff72581f9e154667533443e2368b499 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 11:58:20 -0500 Subject: [PATCH 149/644] Update assistant panel message header, model switcher --- crates/assistant2/src/assistant_panel.rs | 45 +++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 94be39f924..ca9e0ddade 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -53,7 +53,11 @@ use std::{ time::{Duration, Instant}, }; use theme::ThemeSettings; -use ui::{prelude::*, Tab, TabBar, Tooltip}; +use ui::{ + prelude::*, + utils::{DateTimeType, FormatDistance}, + ButtonLike, Tab, TabBar, Tooltip, +}; use util::{paths::CONVERSATIONS_DIR, post_inc, ResultExt, TryFutureExt}; use uuid::Uuid; use workspace::{ @@ -1126,13 +1130,13 @@ impl Render for AssistantPanel { .border() .border_color(gpui::red()) } else { - let header = ui::TabBar::new("assistant_header") + let header = TabBar::new("assistant_header") .start_child( h_stack().gap_1().child(Self::render_hamburger_button(cx)), // .children(title), ) .children(self.active_editor().map(|editor| { h_stack() - .h(rems(ui::Tab::HEIGHT_IN_REMS)) + .h(rems(Tab::HEIGHT_IN_REMS)) .flex_1() .px_2() .child(Label::new(editor.read(cx).title(cx)).into_element()) @@ -2278,6 +2282,14 @@ impl ConversationEditor { } Role::System => Label::new("System").color(Color::Warning), }) + .tooltip(|cx| { + Tooltip::with_meta( + "Toggle message role", + None, + "Available roles: You (User), Assistant, System", + cx, + ) + }) .on_click({ let conversation = conversation.clone(); move |_, cx| { @@ -2292,10 +2304,23 @@ impl ConversationEditor { h_stack() .id(("message_header", message_id.0)) - .border() - .border_color(gpui::red()) + .h_12() + .gap_1() + .p_1() + .debug_bg_cyan() .child(sender) - .child(Label::new(message.sent_at.format("%I:%M%P").to_string())) + // TODO: Only show this if the message if the message has been sent + .child( + Label::new( + FormatDistance::from_now(DateTimeType::Local( + message.sent_at, + )) + .hide_prefix(true) + .add_suffix(true) + .to_string(), + ) + .color(Color::Muted), + ) .children( if let MessageStatus::Error(error) = message.status.clone() { Some( @@ -2456,6 +2481,7 @@ impl ConversationEditor { "current_model", self.conversation.read(cx).model.short_name(), ) + .style(ButtonStyle::Filled) .tooltip(move |cx| Tooltip::text("Change Model", cx)) .on_click(cx.listener(|this, _, cx| this.cycle_model(cx))) } @@ -2469,12 +2495,7 @@ impl ConversationEditor { } else { Color::Default }; - Some( - div() - .border() - .border_color(gpui::red()) - .child(Label::new(remaining_tokens.to_string()).color(remaining_tokens_color)), - ) + Some(Label::new(remaining_tokens.to_string()).color(remaining_tokens_color)) } } From e655d2434a88d6b8d2c598e492b8ae5af169aae5 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 09:02:25 -0800 Subject: [PATCH 150/644] Don't stop propagation on mouse move over editor gutter --- crates/editor2/src/element.rs | 2 -- crates/workspace2/src/dock.rs | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index cf34863ba6..8ccae59172 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -564,8 +564,6 @@ impl EditorElement { ); } } - - cx.stop_propagation(); } else { update_go_to_definition_link(editor, None, modifiers.command, modifiers.shift, cx); hover_at(editor, None, cx); diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 3997b8f9b0..d0aba998b9 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -495,7 +495,8 @@ impl Render for Dock { }) .on_click(cx.listener(|v, e: &ClickEvent, cx| { if e.down.button == MouseButton::Left && e.down.click_count == 2 { - v.resize_active_panel(None, cx) + v.resize_active_panel(None, cx); + cx.stop_propagation(); } })) .z_index(1); From 5d95e13cc809ba872969d19998c371214ec07fb9 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Tue, 19 Dec 2023 12:04:01 -0500 Subject: [PATCH 151/644] Update assistant editor --- crates/assistant2/src/assistant_panel.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index ca9e0ddade..ec67d684da 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -2304,10 +2304,9 @@ impl ConversationEditor { h_stack() .id(("message_header", message_id.0)) - .h_12() + .h_11() .gap_1() .p_1() - .debug_bg_cyan() .child(sender) // TODO: Only show this if the message if the message has been sent .child( @@ -2507,15 +2506,21 @@ impl Render for ConversationEditor { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { div() .key_context("ConversationEditor") - .size_full() - .relative() .capture_action(cx.listener(ConversationEditor::cancel_last_assist)) .capture_action(cx.listener(ConversationEditor::save)) .capture_action(cx.listener(ConversationEditor::copy)) .capture_action(cx.listener(ConversationEditor::cycle_message_role)) .on_action(cx.listener(ConversationEditor::assist)) .on_action(cx.listener(ConversationEditor::split)) - .child(self.editor.clone()) + .size_full() + .relative() + .child( + div() + .size_full() + .pl_2() + .bg(cx.theme().colors().editor_background) + .child(self.editor.clone()), + ) .child( h_stack() .absolute() From 616ea131af6447b4818f1e085537fd01e29098b3 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 12:11:06 -0500 Subject: [PATCH 152/644] Style buffer search input (#3713) This PR styles the text input for the buffer search. Release Notes: - N/A --- crates/search2/src/buffer_search.rs | 58 +++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index 5db7aff736..17dc13feaa 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -7,18 +7,21 @@ use crate::{ ToggleCaseSensitive, ToggleReplace, ToggleWholeWord, }; use collections::HashMap; -use editor::Editor; +use editor::{Editor, EditorElement, EditorStyle}; use futures::channel::oneshot; use gpui::{ - actions, div, impl_actions, red, Action, AppContext, ClickEvent, Div, EventEmitter, - FocusableView, InteractiveElement as _, IntoElement, KeyContext, ParentElement as _, Render, - Styled, Subscription, Task, View, ViewContext, VisualContext as _, WindowContext, + actions, div, impl_actions, Action, AppContext, ClickEvent, Div, EventEmitter, FocusableView, + FontStyle, FontWeight, InteractiveElement as _, IntoElement, KeyContext, ParentElement as _, + Render, Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext as _, + WhiteSpace, WindowContext, }; use project::search::SearchQuery; use serde::Deserialize; +use settings::Settings; use std::{any::Any, sync::Arc}; +use theme::ThemeSettings; -use ui::{h_stack, ButtonCommon, Clickable, Icon, IconButton, IconElement, Tooltip}; +use ui::{h_stack, prelude::*, Icon, IconButton, IconElement, Tooltip}; use util::ResultExt; use workspace::{ item::ItemHandle, @@ -63,6 +66,38 @@ pub struct BufferSearchBar { replace_enabled: bool, } +impl BufferSearchBar { + fn render_text_input(&self, editor: &View, cx: &ViewContext) -> impl IntoElement { + let settings = ThemeSettings::get_global(cx); + let text_style = TextStyle { + color: if editor.read(cx).read_only() { + cx.theme().colors().text_disabled + } else { + cx.theme().colors().text + }, + font_family: settings.ui_font.family.clone(), + font_features: settings.ui_font.features, + font_size: rems(0.875).into(), + font_weight: FontWeight::NORMAL, + font_style: FontStyle::Normal, + line_height: relative(1.3).into(), + background_color: None, + underline: None, + white_space: WhiteSpace::Normal, + }; + + EditorElement::new( + &editor, + EditorStyle { + background: cx.theme().colors().editor_background, + local_player: cx.theme().players().local(), + text: text_style, + ..Default::default() + }, + ) + } +} + impl EventEmitter for BufferSearchBar {} impl EventEmitter for BufferSearchBar {} impl Render for BufferSearchBar { @@ -207,15 +242,16 @@ impl Render for BufferSearchBar { .w_full() .p_1() .child( - div() - .flex() + h_stack() .flex_1() + .px_2() + .py_1() + .gap_2() .border_1() - .border_color(red()) - .rounded_md() - .items_center() + .border_color(cx.theme().colors().border) + .rounded_lg() .child(IconElement::new(Icon::MagnifyingGlass)) - .child(self.query_editor.clone()) + .child(self.render_text_input(&self.query_editor, cx)) .children(supported_options.case.then(|| { self.render_search_option_button( SearchOptions::CASE_SENSITIVE, From 51396344a3f549571eff54e59cd4bcf31f4abc46 Mon Sep 17 00:00:00 2001 From: Julia Date: Tue, 19 Dec 2023 12:50:06 -0500 Subject: [PATCH 153/644] Match zed1 scrollbar drag behavior Still not ideal, but we need to ship and this is more than reasonable Co-Authored-By: Antonio Scandurra --- crates/editor2/src/element.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index cf34863ba6..0c9d0b46a8 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -1369,7 +1369,7 @@ impl EditorElement { { let y = mouse_position.y; let new_y = event.position.y; - if thumb_top < y && y < thumb_bottom { + if (track_bounds.top()..track_bounds.bottom()).contains(&y) { let mut position = editor.scroll_position(cx); position.y += (new_y - y) * (max_row as f32) / height; if position.y < 0.0 { From e08fc0bbc026e093543b3681380598ea27fa9aa3 Mon Sep 17 00:00:00 2001 From: Julia Date: Tue, 19 Dec 2023 13:00:21 -0500 Subject: [PATCH 154/644] Allow editor mouse drag selection outside interactive bounds Co-Authored-By: Antonio Scandurra --- crates/editor2/src/element.rs | 118 +++++++++++++++++++++------------- 1 file changed, 72 insertions(+), 46 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index cf34863ba6..e98c50d9ed 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -488,6 +488,52 @@ impl EditorElement { } } + fn mouse_dragged( + editor: &mut Editor, + event: &MouseMoveEvent, + position_map: &PositionMap, + text_bounds: Bounds, + gutter_bounds: Bounds, + stacking_order: &StackingOrder, + cx: &mut ViewContext, + ) { + if !editor.has_pending_selection() { + return; + } + + let point_for_position = position_map.point_for_position(text_bounds, event.position); + let mut scroll_delta = gpui::Point::::default(); + let vertical_margin = position_map.line_height.min(text_bounds.size.height / 3.0); + let top = text_bounds.origin.y + vertical_margin; + let bottom = text_bounds.lower_left().y - vertical_margin; + if event.position.y < top { + scroll_delta.y = -scale_vertical_mouse_autoscroll_delta(top - event.position.y); + } + if event.position.y > bottom { + scroll_delta.y = scale_vertical_mouse_autoscroll_delta(event.position.y - bottom); + } + + let horizontal_margin = position_map.line_height.min(text_bounds.size.width / 3.0); + let left = text_bounds.origin.x + horizontal_margin; + let right = text_bounds.upper_right().x - horizontal_margin; + if event.position.x < left { + scroll_delta.x = -scale_horizontal_mouse_autoscroll_delta(left - event.position.x); + } + if event.position.x > right { + scroll_delta.x = scale_horizontal_mouse_autoscroll_delta(event.position.x - right); + } + + editor.select( + SelectPhase::Update { + position: point_for_position.previous_valid, + goal_column: point_for_position.exact_unclipped.column(), + scroll_position: (position_map.snapshot.scroll_position() + scroll_delta) + .clamp(&gpui::Point::default(), &position_map.scroll_max), + }, + cx, + ); + } + fn mouse_moved( editor: &mut Editor, event: &MouseMoveEvent, @@ -498,40 +544,6 @@ impl EditorElement { cx: &mut ViewContext, ) { let modifiers = event.modifiers; - if editor.has_pending_selection() && event.pressed_button == Some(MouseButton::Left) { - let point_for_position = position_map.point_for_position(text_bounds, event.position); - let mut scroll_delta = gpui::Point::::default(); - let vertical_margin = position_map.line_height.min(text_bounds.size.height / 3.0); - let top = text_bounds.origin.y + vertical_margin; - let bottom = text_bounds.lower_left().y - vertical_margin; - if event.position.y < top { - scroll_delta.y = -scale_vertical_mouse_autoscroll_delta(top - event.position.y); - } - if event.position.y > bottom { - scroll_delta.y = scale_vertical_mouse_autoscroll_delta(event.position.y - bottom); - } - - let horizontal_margin = position_map.line_height.min(text_bounds.size.width / 3.0); - let left = text_bounds.origin.x + horizontal_margin; - let right = text_bounds.upper_right().x - horizontal_margin; - if event.position.x < left { - scroll_delta.x = -scale_horizontal_mouse_autoscroll_delta(left - event.position.x); - } - if event.position.x > right { - scroll_delta.x = scale_horizontal_mouse_autoscroll_delta(event.position.x - right); - } - - editor.select( - SelectPhase::Update { - position: point_for_position.previous_valid, - goal_column: point_for_position.exact_unclipped.column(), - scroll_position: (position_map.snapshot.scroll_position() + scroll_delta) - .clamp(&gpui::Point::default(), &position_map.scroll_max), - }, - cx, - ); - } - let text_hovered = text_bounds.contains(&event.position); let gutter_hovered = gutter_bounds.contains(&event.position); let was_top = cx.was_top_layer(&event.position, stacking_order); @@ -2510,19 +2522,33 @@ impl EditorElement { let stacking_order = cx.stacking_order().clone(); move |event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && interactive_bounds.visibly_contains(&event.position, cx) - { + // if editor.has_pending_selection() && event.pressed_button == Some(MouseButton::Left) { + + if phase == DispatchPhase::Bubble { editor.update(cx, |editor, cx| { - Self::mouse_moved( - editor, - event, - &position_map, - text_bounds, - gutter_bounds, - &stacking_order, - cx, - ) + if event.pressed_button == Some(MouseButton::Left) { + Self::mouse_dragged( + editor, + event, + &position_map, + text_bounds, + gutter_bounds, + &stacking_order, + cx, + ) + } + + if interactive_bounds.visibly_contains(&event.position, cx) { + Self::mouse_moved( + editor, + event, + &position_map, + text_bounds, + gutter_bounds, + &stacking_order, + cx, + ) + } }); } } From a3bab25792aa1e4cef69786e78ca0962ab08325c Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 13:16:14 -0500 Subject: [PATCH 155/644] Style contact finder (#3717) This PR styles the contact finder. Screenshot 2023-12-19 at 12 59 00 PM Release Notes: - N/A --- crates/collab_ui2/src/collab_panel.rs | 11 +--- .../src/collab_panel/contact_finder.rs | 66 +++++-------------- crates/picker2/src/picker2.rs | 42 ++++++------ 3 files changed, 40 insertions(+), 79 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 2179d82cf3..cbae076304 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2204,14 +2204,9 @@ impl CollabPanel { .into_any_element() }), Section::Contacts => Some( - div() - .border_1() - .border_color(gpui::red()) - .child( - IconButton::new("add-contact", Icon::Plus) - .on_click(cx.listener(|this, _, cx| this.toggle_contact_finder(cx))) - .tooltip(|cx| Tooltip::text("Search for new contact", cx)), - ) + IconButton::new("add-contact", Icon::Plus) + .on_click(cx.listener(|this, _, cx| this.toggle_contact_finder(cx))) + .tooltip(|cx| Tooltip::text("Search for new contact", cx)) .into_any_element(), ), Section::Channels => Some( diff --git a/crates/collab_ui2/src/collab_panel/contact_finder.rs b/crates/collab_ui2/src/collab_panel/contact_finder.rs index 3087e6812f..ff7e02a909 100644 --- a/crates/collab_ui2/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui2/src/collab_panel/contact_finder.rs @@ -7,7 +7,7 @@ use gpui::{ use picker::{Picker, PickerDelegate}; use std::sync::Arc; use theme::ActiveTheme as _; -use ui::{prelude::*, Avatar}; +use ui::{prelude::*, Avatar, ListItem}; use util::{ResultExt as _, TryFutureExt}; use workspace::ModalView; @@ -23,7 +23,7 @@ impl ContactFinder { potential_contacts: Arc::from([]), selected_index: 0, }; - let picker = cx.build_view(|cx| Picker::new(delegate, cx)); + let picker = cx.build_view(|cx| Picker::new(delegate, cx).modal(false)); Self { picker } } @@ -37,16 +37,17 @@ impl ContactFinder { impl Render for ContactFinder { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - fn render_mode_button(text: &'static str) -> AnyElement { - Label::new(text).into_any_element() - } - v_stack() + .elevation_3(cx) .child( v_stack() + .px_2() + .py_1() + .bg(cx.theme().colors().element_background) + // HACK: Prevent the background color from overflowing the parent container. + .rounded_t(px(8.)) .child(Label::new("Contacts")) - .child(h_stack().children([render_mode_button("Invite new contacts")])) - .bg(cx.theme().colors().element_background), + .child(h_stack().child(Label::new("Invite new contacts"))), ) .child(self.picker.clone()) .w(rems(34.)) @@ -72,7 +73,8 @@ impl FocusableView for ContactFinder { } impl PickerDelegate for ContactFinderDelegate { - type ListItem = Div; + type ListItem = ListItem; + fn match_count(&self) -> usize { self.potential_contacts.len() } @@ -150,46 +152,14 @@ impl PickerDelegate for ContactFinderDelegate { ContactRequestStatus::RequestAccepted => None, }; Some( - div() - .flex_1() - .justify_between() - .child(Avatar::new(user.avatar_uri.clone())) + ListItem::new(ix) + .inset(true) + .selected(selected) + .start_slot(Avatar::new(user.avatar_uri.clone())) .child(Label::new(user.github_login.clone())) - .children(icon_path.map(|icon_path| svg().path(icon_path))), + .end_slot::( + icon_path.map(|icon_path| IconElement::from_path(icon_path)), + ), ) - // todo!() - // Flex::row() - // .with_children(user.avatar.clone().map(|avatar| { - // Image::from_data(avatar) - // .with_style(theme.contact_avatar) - // .aligned() - // .left() - // })) - // .with_child( - // Label::new(user.github_login.clone(), style.label.clone()) - // .contained() - // .with_style(theme.contact_username) - // .aligned() - // .left(), - // ) - // .with_children(icon_path.map(|icon_path| { - // Svg::new(icon_path) - // .with_color(button_style.color) - // .constrained() - // .with_width(button_style.icon_width) - // .aligned() - // .contained() - // .with_style(button_style.container) - // .constrained() - // .with_width(button_style.button_width) - // .with_height(button_style.button_width) - // .aligned() - // .flex_float() - // })) - // .contained() - // .with_style(style.container) - // .constrained() - // .with_height(tabbed_modal.row_height) - // .into_any() } } diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index f7911094b5..70180112f9 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -1,8 +1,8 @@ use editor::Editor; use gpui::{ - div, prelude::*, rems, uniform_list, AnyElement, AppContext, DismissEvent, Div, EventEmitter, - FocusHandle, FocusableView, Length, MouseButton, MouseDownEvent, Render, Task, - UniformListScrollHandle, View, ViewContext, WindowContext, + div, prelude::*, rems, uniform_list, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, + FocusableView, Length, MouseButton, MouseDownEvent, Render, Task, UniformListScrollHandle, + View, ViewContext, WindowContext, }; use std::{cmp, sync::Arc}; use ui::{prelude::*, v_stack, Color, Divider, Label}; @@ -15,6 +15,11 @@ pub struct Picker { pending_update_matches: Option>, confirm_on_update: Option, width: Option, + + /// Whether the `Picker` is rendered as a self-contained modal. + /// + /// Set this to `false` when rendering the `Picker` as part of a larger modal. + is_modal: bool, } pub trait PickerDelegate: Sized + 'static { @@ -58,6 +63,7 @@ impl Picker { pending_update_matches: None, confirm_on_update: None, width: None, + is_modal: true, }; this.update_matches("".to_string(), cx); this @@ -68,6 +74,11 @@ impl Picker { self } + pub fn modal(mut self, modal: bool) -> Self { + self.is_modal = modal; + self + } + pub fn focus(&self, cx: &mut WindowContext) { self.editor.update(cx, |editor, cx| editor.focus(cx)); } @@ -234,7 +245,11 @@ impl Render for Picker { el.w(width) }) .overflow_hidden() - .elevation_3(cx) + // This is a bit of a hack to remove the modal styling when we're rendering the `Picker` + // as a part of a modal rather than the entire modal. + // + // We should revisit how the `Picker` is styled to make it more composable. + .when(self.is_modal, |this| this.elevation_3(cx)) .on_action(cx.listener(Self::select_next)) .on_action(cx.listener(Self::select_prev)) .on_action(cx.listener(Self::select_first)) @@ -295,22 +310,3 @@ impl Render for Picker { }) } } - -pub fn simple_picker_match( - selected: bool, - cx: &mut WindowContext, - children: impl FnOnce(&mut WindowContext) -> AnyElement, -) -> AnyElement { - let colors = cx.theme().colors(); - - div() - .px_1() - .text_color(colors.text) - .text_ui() - .bg(colors.ghost_element_background) - .rounded_md() - .when(selected, |this| this.bg(colors.ghost_element_selected)) - .hover(|this| this.bg(colors.ghost_element_hover)) - .child((children)(cx)) - .into_any() -} From a4bfd0147dd30aa12003beaa9f0938e3540196bd Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 09:48:45 -0800 Subject: [PATCH 156/644] Render channel invites in collab panel, fix unused warnings --- crates/collab_ui2/src/collab_panel.rs | 837 +++--------------- .../src/collab_panel/channel_modal.rs | 1 + .../src/collab_panel/contact_finder.rs | 1 + 3 files changed, 142 insertions(+), 697 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index cbae076304..c58d7c47bc 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -1,4 +1,3 @@ -#![allow(unused)] mod channel_modal; mod contact_finder; @@ -317,18 +316,10 @@ pub struct CollabPanel { subscriptions: Vec, collapsed_sections: Vec
, collapsed_channels: Vec, - drag_target_channel: ChannelDragTarget, workspace: WeakView, // context_menu_on_selected: bool, } -#[derive(PartialEq, Eq)] -enum ChannelDragTarget { - None, - Root, - Channel(ChannelId), -} - #[derive(Serialize, Deserialize)] struct SerializedCollabPanel { width: Option, @@ -373,7 +364,7 @@ enum ListEntry { }, IncomingRequest(Arc), OutgoingRequest(Arc), - // ChannelInvite(Arc), + ChannelInvite(Arc), Channel { channel: Arc, depth: usize, @@ -472,8 +463,6 @@ impl CollabPanel { collapsed_channels: Vec::default(), workspace: workspace.weak_handle(), client: workspace.app_state().client.clone(), - // context_menu_on_selected: true, - drag_target_channel: ChannelDragTarget::None, }; this.update_entries(false, cx); @@ -529,9 +518,6 @@ impl CollabPanel { }) } - fn contacts(&self, cx: &AppContext) -> Option>> { - Some(self.user_store.read(cx).contacts().to_owned()) - } pub async fn load( workspace: WeakView, mut cx: AsyncWindowContext, @@ -808,37 +794,37 @@ impl CollabPanel { } } - // let channel_invites = channel_store.channel_invitations(); - // if !channel_invites.is_empty() { - // self.match_candidates.clear(); - // self.match_candidates - // .extend(channel_invites.iter().enumerate().map(|(ix, channel)| { - // StringMatchCandidate { - // id: ix, - // string: channel.name.clone(), - // char_bag: channel.name.chars().collect(), - // } - // })); - // let matches = executor.block(match_strings( - // &self.match_candidates, - // &query, - // true, - // usize::MAX, - // &Default::default(), - // executor.clone(), - // )); - // request_entries.extend(matches.iter().map(|mat| { - // ListEntry::ChannelInvite(channel_invites[mat.candidate_id].clone()) - // })); + let channel_invites = channel_store.channel_invitations(); + if !channel_invites.is_empty() { + self.match_candidates.clear(); + self.match_candidates + .extend(channel_invites.iter().enumerate().map(|(ix, channel)| { + StringMatchCandidate { + id: ix, + string: channel.name.clone().into(), + char_bag: channel.name.chars().collect(), + } + })); + let matches = executor.block(match_strings( + &self.match_candidates, + &query, + true, + usize::MAX, + &Default::default(), + executor.clone(), + )); + request_entries.extend(matches.iter().map(|mat| { + ListEntry::ChannelInvite(channel_invites[mat.candidate_id].clone()) + })); - // if !request_entries.is_empty() { - // self.entries - // .push(ListEntry::Header(Section::ChannelInvites)); - // if !self.collapsed_sections.contains(&Section::ChannelInvites) { - // self.entries.append(&mut request_entries); - // } - // } - // } + if !request_entries.is_empty() { + self.entries + .push(ListEntry::Header(Section::ChannelInvites)); + if !self.collapsed_sections.contains(&Section::ChannelInvites) { + self.entries.append(&mut request_entries); + } + } + } } self.entries.push(ListEntry::Header(Section::Contacts)); @@ -1049,9 +1035,7 @@ impl CollabPanel { } else if is_current_user { IconButton::new("leave-call", Icon::Exit) .style(ButtonStyle::Subtle) - .on_click(cx.listener(move |this, _, cx| { - Self::leave_call(cx); - })) + .on_click(move |_, cx| Self::leave_call(cx)) .tooltip(|cx| Tooltip::text("Leave Call", cx)) .into_any_element() } else { @@ -1061,7 +1045,8 @@ impl CollabPanel { this.tooltip(move |cx| Tooltip::text(tooltip.clone(), cx)) .on_click(cx.listener(move |this, _, cx| { this.workspace - .update(cx, |workspace, cx| workspace.follow(peer_id, cx)); + .update(cx, |workspace, cx| workspace.follow(peer_id, cx)) + .ok(); })) }) } @@ -1073,7 +1058,7 @@ impl CollabPanel { host_user_id: u64, // is_current: bool, is_last: bool, - // is_selected: bool, + is_selected: bool, // theme: &theme::Theme, cx: &mut ViewContext, ) -> impl IntoElement { @@ -1084,15 +1069,16 @@ impl CollabPanel { } .into(); - let theme = cx.theme(); - ListItem::new(project_id as usize) + .selected(is_selected) .on_click(cx.listener(move |this, _, cx| { - this.workspace.update(cx, |workspace, cx| { - let app_state = workspace.app_state().clone(); - workspace::join_remote_project(project_id, host_user_id, app_state, cx) - .detach_and_log_err(cx); - }); + this.workspace + .update(cx, |workspace, cx| { + let app_state = workspace.app_state().clone(); + workspace::join_remote_project(project_id, host_user_id, app_state, cx) + .detach_and_log_err(cx); + }) + .ok(); })) .start_slot( h_stack() @@ -1102,95 +1088,19 @@ impl CollabPanel { ) .child(Label::new(project_name.clone())) .tooltip(move |cx| Tooltip::text(format!("Open {}", project_name), cx)) - - // enum JoinProject {} - // enum JoinProjectTooltip {} - - // let collab_theme = &theme.collab_panel; - // let host_avatar_width = collab_theme - // .contact_avatar - // .width - // .or(collab_theme.contact_avatar.height) - // .unwrap_or(0.); - // let tree_branch = collab_theme.tree_branch; - - // let content = - // MouseEventHandler::new::(project_id as usize, cx, |mouse_state, cx| { - // let tree_branch = *tree_branch.in_state(is_selected).style_for(mouse_state); - // let row = if is_current { - // collab_theme - // .project_row - // .in_state(true) - // .style_for(&mut Default::default()) - // } else { - // collab_theme - // .project_row - // .in_state(is_selected) - // .style_for(mouse_state) - // }; - - // Flex::row() - // .with_child(render_tree_branch( - // tree_branch, - // &row.name.text, - // is_last, - // vec2f(host_avatar_width, collab_theme.row_height), - // cx.font_cache(), - // )) - // .with_child( - // Svg::new("icons/file_icons/folder.svg") - // .with_color(collab_theme.channel_hash.color) - // .constrained() - // .with_width(collab_theme.channel_hash.width) - // .aligned() - // .left(), - // ) - // .with_child( - // Label::new(project_name.clone(), row.name.text.clone()) - // .aligned() - // .left() - // .contained() - // .with_style(row.name.container) - // .flex(1., false), - // ) - // .constrained() - // .with_height(collab_theme.row_height) - // .contained() - // .with_style(row.container) - // }); - - // if is_current { - // return content.into_any(); - // } - - // content - // .with_cursor_style(CursorStyle::PointingHand) - // .on_click(MouseButton::Left, move |_, this, cx| { - // if let Some(workspace) = this.workspace.upgrade(cx) { - // let app_state = workspace.read(cx).app_state().clone(); - // workspace::join_remote_project(project_id, host_user_id, app_state, cx) - // .detach_and_log_err(cx); - // } - // }) - // .with_tooltip::( - // project_id as usize, - // format!("Open {}", project_name), - // None, - // theme.tooltip.clone(), - // cx, - // ) - // .into_any() } fn render_participant_screen( &self, peer_id: Option, is_last: bool, + is_selected: bool, cx: &mut ViewContext, ) -> impl IntoElement { let id = peer_id.map_or(usize::MAX, |id| id.as_u64() as usize); ListItem::new(("screen", id)) + .selected(is_selected) .start_slot( h_stack() .gap_1() @@ -1200,9 +1110,11 @@ impl CollabPanel { .child(Label::new("Screen")) .when_some(peer_id, |this, _| { this.on_click(cx.listener(move |this, _, cx| { - this.workspace.update(cx, |workspace, cx| { - workspace.open_shared_screen(peer_id.unwrap(), cx) - }); + this.workspace + .update(cx, |workspace, cx| { + workspace.open_shared_screen(peer_id.unwrap(), cx) + }) + .ok(); })) .tooltip(move |cx| Tooltip::text(format!("Open shared screen"), cx)) }) @@ -1291,86 +1203,6 @@ impl CollabPanel { .tooltip(move |cx| Tooltip::text("Open Chat", cx)) } - // fn render_channel_invite( - // channel: Arc, - // channel_store: ModelHandle, - // theme: &theme::CollabPanel, - // is_selected: bool, - // cx: &mut ViewContext, - // ) -> AnyElement { - // enum Decline {} - // enum Accept {} - - // let channel_id = channel.id; - // let is_invite_pending = channel_store - // .read(cx) - // .has_pending_channel_invite_response(&channel); - // let button_spacing = theme.contact_button_spacing; - - // Flex::row() - // .with_child( - // Svg::new("icons/hash.svg") - // .with_color(theme.channel_hash.color) - // .constrained() - // .with_width(theme.channel_hash.width) - // .aligned() - // .left(), - // ) - // .with_child( - // Label::new(channel.name.clone(), theme.contact_username.text.clone()) - // .contained() - // .with_style(theme.contact_username.container) - // .aligned() - // .left() - // .flex(1., true), - // ) - // .with_child( - // MouseEventHandler::new::(channel.id as usize, cx, |mouse_state, _| { - // let button_style = if is_invite_pending { - // &theme.disabled_button - // } else { - // theme.contact_button.style_for(mouse_state) - // }; - // render_icon_button(button_style, "icons/x.svg").aligned() - // }) - // .with_cursor_style(CursorStyle::PointingHand) - // .on_click(MouseButton::Left, move |_, this, cx| { - // this.respond_to_channel_invite(channel_id, false, cx); - // }) - // .contained() - // .with_margin_right(button_spacing), - // ) - // .with_child( - // MouseEventHandler::new::(channel.id as usize, cx, |mouse_state, _| { - // let button_style = if is_invite_pending { - // &theme.disabled_button - // } else { - // theme.contact_button.style_for(mouse_state) - // }; - // render_icon_button(button_style, "icons/check.svg") - // .aligned() - // .flex_float() - // }) - // .with_cursor_style(CursorStyle::PointingHand) - // .on_click(MouseButton::Left, move |_, this, cx| { - // this.respond_to_channel_invite(channel_id, true, cx); - // }), - // ) - // .constrained() - // .with_height(theme.row_height) - // .contained() - // .with_style( - // *theme - // .contact_row - // .in_state(is_selected) - // .style_for(&mut Default::default()), - // ) - // .with_padding_left( - // theme.contact_row.default_style().padding.left + theme.channel_indent, - // ) - // .into_any() - // } - fn has_subchannels(&self, ix: usize) -> bool { self.entries.get(ix).map_or(false, |entry| { if let ListEntry::Channel { has_children, .. } = entry { @@ -1724,7 +1556,7 @@ impl CollabPanel { self.collapsed_channels.binary_search(&channel_id).is_ok() } - fn leave_call(cx: &mut ViewContext) { + fn leave_call(cx: &mut WindowContext) { ActiveCall::global(cx) .update(cx, |call, cx| call.hang_up(cx)) .detach_and_log_err(cx); @@ -1813,15 +1645,13 @@ impl CollabPanel { } } - fn start_move_channel(&mut self, channel_id: ChannelId, cx: &mut ViewContext) { + fn start_move_channel(&mut self, channel_id: ChannelId, _cx: &mut ViewContext) { self.channel_clipboard = Some(ChannelMoveClipboard { channel_id }); } - fn start_move_selected_channel(&mut self, channel_id: ChannelId, cx: &mut ViewContext) { + fn start_move_selected_channel(&mut self, _: &StartMoveChannel, cx: &mut ViewContext) { if let Some(channel) = self.selected_channel() { - self.channel_clipboard = Some(ChannelMoveClipboard { - channel_id: channel.id, - }) + self.start_move_channel(channel.id, cx); } } @@ -1900,10 +1730,6 @@ impl CollabPanel { .detach(); } - // fn remove_selected_channel(&mut self, action: &RemoveChannel, cx: &mut ViewContext) { - // self.remove_channel(action.channel_id, cx) - // } - fn remove_channel(&mut self, channel_id: ChannelId, cx: &mut ViewContext) { let channel_store = self.channel_store.clone(); if let Some(channel) = channel_store.read(cx).channel_for_id(channel_id) { @@ -1911,9 +1737,7 @@ impl CollabPanel { "Are you sure you want to remove the channel \"{}\"?", channel.name ); - let mut answer = - cx.prompt(PromptLevel::Warning, &prompt_message, &["Remove", "Cancel"]); - let window = cx.window(); + let answer = cx.prompt(PromptLevel::Warning, &prompt_message, &["Remove", "Cancel"]); cx.spawn(|this, mut cx| async move { if answer.await? == 0 { channel_store @@ -1937,8 +1761,7 @@ impl CollabPanel { "Are you sure you want to remove \"{}\" from your contacts?", github_login ); - let mut answer = cx.prompt(PromptLevel::Warning, &prompt_message, &["Remove", "Cancel"]); - let window = cx.window(); + let answer = cx.prompt(PromptLevel::Warning, &prompt_message, &["Remove", "Cancel"]); cx.spawn(|_, mut cx| async move { if answer.await? == 0 { user_store @@ -1964,18 +1787,18 @@ impl CollabPanel { .detach_and_log_err(cx); } - // fn respond_to_channel_invite( - // &mut self, - // channel_id: u64, - // accept: bool, - // cx: &mut ViewContext, - // ) { - // self.channel_store - // .update(cx, |store, cx| { - // store.respond_to_channel_invite(channel_id, accept, cx) - // }) - // .detach(); - // } + fn respond_to_channel_invite( + &mut self, + channel_id: u64, + accept: bool, + cx: &mut ViewContext, + ) { + self.channel_store + .update(cx, |store, cx| { + store.respond_to_channel_invite(channel_id, accept, cx) + }) + .detach(); + } fn call(&mut self, recipient_user_id: u64, cx: &mut ViewContext) { ActiveCall::global(cx) @@ -2096,6 +1919,9 @@ impl CollabPanel { ListEntry::ChannelEditor { depth } => { self.render_channel_editor(*depth, cx).into_any_element() } + ListEntry::ChannelInvite(channel) => self + .render_channel_invite(channel, is_selected, cx) + .into_any_element(), ListEntry::CallParticipant { user, peer_id, @@ -2114,11 +1940,12 @@ impl CollabPanel { &worktree_root_names, *host_user_id, *is_last, + is_selected, cx, ) .into_any_element(), ListEntry::ParticipantScreen { peer_id, is_last } => self - .render_participant_screen(*peer_id, *is_last, cx) + .render_participant_screen(*peer_id, *is_last, is_selected, cx) .into_any_element(), ListEntry::ChannelNotes { channel_id } => self .render_channel_notes(*channel_id, cx) @@ -2233,7 +2060,7 @@ impl CollabPanel { ListHeader::new(text) .when(can_collapse, |header| { header.toggle(Some(!is_collapsed)).on_toggle(cx.listener( - move |this, event, cx| { + move |this, _, cx| { this.toggle_section_expanded(section, cx); }, )) @@ -2265,8 +2092,9 @@ impl CollabPanel { let busy = contact.busy || calling; let user_id = contact.user.id; let github_login = SharedString::from(contact.user.github_login.clone()); - let mut item = + let item = ListItem::new(github_login.clone()) + .selected(is_selected) .on_click(cx.listener(move |this, _, cx| this.call(user_id, cx))) .child( h_stack() @@ -2330,8 +2158,8 @@ impl CollabPanel { ) -> impl IntoElement { let github_login = SharedString::from(user.github_login.clone()); let user_id = user.id; - let is_contact_request_pending = self.user_store.read(cx).is_contact_request_pending(&user); - let color = if is_contact_request_pending { + let is_response_pending = self.user_store.read(cx).is_contact_request_pending(&user); + let color = if is_response_pending { Color::Muted } else { Color::Default @@ -2363,6 +2191,7 @@ impl CollabPanel { }; ListItem::new(github_login.clone()) + .selected(is_selected) .child( h_stack() .w_full() @@ -2373,6 +2202,54 @@ impl CollabPanel { .start_slot(Avatar::new(user.avatar_uri.clone())) } + fn render_channel_invite( + &self, + channel: &Arc, + is_selected: bool, + cx: &mut ViewContext, + ) -> impl IntoElement { + let channel_id = channel.id; + let response_is_pending = self + .channel_store + .read(cx) + .has_pending_channel_invite_response(&channel); + let color = if response_is_pending { + Color::Muted + } else { + Color::Default + }; + + let controls = [ + IconButton::new("remove_contact", Icon::Close) + .on_click(cx.listener(move |this, _, cx| { + this.respond_to_channel_invite(channel_id, false, cx); + })) + .icon_color(color) + .tooltip(|cx| Tooltip::text("Decline invite", cx)), + IconButton::new("remove_contact", Icon::Check) + .on_click(cx.listener(move |this, _, cx| { + this.respond_to_contact_request(channel_id, true, cx); + })) + .icon_color(color) + .tooltip(|cx| Tooltip::text("Accept invite", cx)), + ]; + + ListItem::new(("channel-invite", channel.id as usize)) + .selected(is_selected) + .child( + h_stack() + .w_full() + .justify_between() + .child(Label::new(channel.name.clone())) + .child(h_stack().children(controls)), + ) + .start_slot( + IconElement::new(Icon::Hash) + .size(IconSize::Small) + .color(Color::Muted), + ) + } + fn render_contact_placeholder( &self, is_selected: bool, @@ -2411,7 +2288,6 @@ impl CollabPanel { .channel_for_id(channel_id) .map(|channel| channel.visibility) == Some(proto::ChannelVisibility::Public); - let other_selected = self.selected_channel().map(|channel| channel.id) == Some(channel.id); let disclosed = has_children.then(|| !self.collapsed_channels.binary_search(&channel.id).is_ok()); @@ -2423,14 +2299,10 @@ impl CollabPanel { let face_pile = if !participants.is_empty() { let extra_count = participants.len().saturating_sub(FACEPILE_LIMIT); - let user = &participants[0]; - let result = FacePile { faces: participants .iter() - .filter_map(|user| { - Some(Avatar::new(user.avatar_uri.clone()).into_any_element()) - }) + .map(|user| Avatar::new(user.avatar_uri.clone()).into_any_element()) .take(FACEPILE_LIMIT) .chain(if extra_count > 0 { // todo!() @nate - this label looks wrong. @@ -2454,7 +2326,7 @@ impl CollabPanel { .flex() .w_full() .on_drag(channel.clone(), move |channel, cx| { - cx.build_view(|cx| DraggedChannelView { + cx.build_view(|_| DraggedChannelView { channel: channel.clone(), width, }) @@ -2480,12 +2352,10 @@ impl CollabPanel { }), ) .on_click(cx.listener(move |this, _, cx| { - if this.drag_target_channel == ChannelDragTarget::None { - if is_active { - this.open_channel_notes(channel_id, cx) - } else { - this.join_channel(channel_id, cx) - } + if is_active { + this.open_channel_notes(channel_id, cx) + } else { + this.join_channel(channel_id, cx) } })) .on_secondary_mouse_down(cx.listener( @@ -2537,316 +2407,9 @@ impl CollabPanel { ), ) .tooltip(|cx| Tooltip::text("Join channel", cx)) - - // let channel_id = channel.id; - // let collab_theme = &theme.collab_panel; - // let is_public = self - // .channel_store - // .read(cx) - // .channel_for_id(channel_id) - // .map(|channel| channel.visibility) - // == Some(proto::ChannelVisibility::Public); - // let other_selected = self.selected_channel().map(|channel| channel.id) == Some(channel.id); - // let disclosed = - // has_children.then(|| !self.collapsed_channels.binary_search(&channel.id).is_ok()); - - // enum ChannelCall {} - // enum ChannelNote {} - // enum NotesTooltip {} - // enum ChatTooltip {} - // enum ChannelTooltip {} - - // let mut is_dragged_over = false; - // if cx - // .global::>() - // .currently_dragged::(cx.window()) - // .is_some() - // && self.drag_target_channel == ChannelDragTarget::Channel(channel_id) - // { - // is_dragged_over = true; - // } - - // let has_messages_notification = channel.unseen_message_id.is_some(); - - // MouseEventHandler::new::(ix, cx, |state, cx| { - // let row_hovered = state.hovered(); - - // let mut select_state = |interactive: &Interactive| { - // if state.clicked() == Some(MouseButton::Left) && interactive.clicked.is_some() { - // interactive.clicked.as_ref().unwrap().clone() - // } else if state.hovered() || other_selected { - // interactive - // .hovered - // .as_ref() - // .unwrap_or(&interactive.default) - // .clone() - // } else { - // interactive.default.clone() - // } - // }; - - // Flex::::row() - // .with_child( - // Svg::new(if is_public { - // "icons/public.svg" - // } else { - // "icons/hash.svg" - // }) - // .with_color(collab_theme.channel_hash.color) - // .constrained() - // .with_width(collab_theme.channel_hash.width) - // .aligned() - // .left(), - // ) - // .with_child({ - // let style = collab_theme.channel_name.inactive_state(); - // Flex::row() - // .with_child( - // Label::new(channel.name.clone(), style.text.clone()) - // .contained() - // .with_style(style.container) - // .aligned() - // .left() - // .with_tooltip::( - // ix, - // "Join channel", - // None, - // theme.tooltip.clone(), - // cx, - // ), - // ) - // .with_children({ - // let participants = - // self.channel_store.read(cx).channel_participants(channel_id); - - // if !participants.is_empty() { - // let extra_count = participants.len().saturating_sub(FACEPILE_LIMIT); - - // let result = FacePile::new(collab_theme.face_overlap) - // .with_children( - // participants - // .iter() - // .filter_map(|user| { - // Some( - // Image::from_data(user.avatar.clone()?) - // .with_style(collab_theme.channel_avatar), - // ) - // }) - // .take(FACEPILE_LIMIT), - // ) - // .with_children((extra_count > 0).then(|| { - // Label::new( - // format!("+{}", extra_count), - // collab_theme.extra_participant_label.text.clone(), - // ) - // .contained() - // .with_style(collab_theme.extra_participant_label.container) - // })); - - // Some(result) - // } else { - // None - // } - // }) - // .with_spacing(8.) - // .align_children_center() - // .flex(1., true) - // }) - // .with_child( - // MouseEventHandler::new::(ix, cx, move |mouse_state, _| { - // let container_style = collab_theme - // .disclosure - // .button - // .style_for(mouse_state) - // .container; - - // if channel.unseen_message_id.is_some() { - // Svg::new("icons/conversations.svg") - // .with_color(collab_theme.channel_note_active_color) - // .constrained() - // .with_width(collab_theme.channel_hash.width) - // .contained() - // .with_style(container_style) - // .with_uniform_padding(4.) - // .into_any() - // } else if row_hovered { - // Svg::new("icons/conversations.svg") - // .with_color(collab_theme.channel_hash.color) - // .constrained() - // .with_width(collab_theme.channel_hash.width) - // .contained() - // .with_style(container_style) - // .with_uniform_padding(4.) - // .into_any() - // } else { - // Empty::new().into_any() - // } - // }) - // .on_click(MouseButton::Left, move |_, this, cx| { - // this.join_channel_chat(&JoinChannelChat { channel_id }, cx); - // }) - // .with_tooltip::( - // ix, - // "Open channel chat", - // None, - // theme.tooltip.clone(), - // cx, - // ) - // .contained() - // .with_margin_right(4.), - // ) - // .with_child( - // MouseEventHandler::new::(ix, cx, move |mouse_state, cx| { - // let container_style = collab_theme - // .disclosure - // .button - // .style_for(mouse_state) - // .container; - // if row_hovered || channel.unseen_note_version.is_some() { - // Svg::new("icons/file.svg") - // .with_color(if channel.unseen_note_version.is_some() { - // collab_theme.channel_note_active_color - // } else { - // collab_theme.channel_hash.color - // }) - // .constrained() - // .with_width(collab_theme.channel_hash.width) - // .contained() - // .with_style(container_style) - // .with_uniform_padding(4.) - // .with_margin_right(collab_theme.channel_hash.container.margin.left) - // .with_tooltip::( - // ix as usize, - // "Open channel notes", - // None, - // theme.tooltip.clone(), - // cx, - // ) - // .into_any() - // } else if has_messages_notification { - // Empty::new() - // .constrained() - // .with_width(collab_theme.channel_hash.width) - // .contained() - // .with_uniform_padding(4.) - // .with_margin_right(collab_theme.channel_hash.container.margin.left) - // .into_any() - // } else { - // Empty::new().into_any() - // } - // }) - // .on_click(MouseButton::Left, move |_, this, cx| { - // this.open_channel_notes(&OpenChannelNotes { channel_id }, cx); - // }), - // ) - // .align_children_center() - // .styleable_component() - // .disclosable( - // disclosed, - // Box::new(ToggleCollapse { - // location: channel.id.clone(), - // }), - // ) - // .with_id(ix) - // .with_style(collab_theme.disclosure.clone()) - // .element() - // .constrained() - // .with_height(collab_theme.row_height) - // .contained() - // .with_style(select_state( - // collab_theme - // .channel_row - // .in_state(is_selected || is_active || is_dragged_over), - // )) - // .with_padding_left( - // collab_theme.channel_row.default_style().padding.left - // + collab_theme.channel_indent * depth as f32, - // ) - // }) - // .on_click(MouseButton::Left, move |_, this, cx| { - // if this. - // drag_target_channel == ChannelDragTarget::None { - // if is_active { - // this.open_channel_notes(&OpenChannelNotes { channel_id }, cx) - // } else { - // this.join_channel(channel_id, cx) - // } - // } - // }) - // .on_click(MouseButton::Right, { - // let channel = channel.clone(); - // move |e, this, cx| { - // this.deploy_channel_context_menu(Some(e.position), &channel, ix, cx); - // } - // }) - // .on_up(MouseButton::Left, move |_, this, cx| { - // if let Some((_, dragged_channel)) = cx - // .global::>() - // .currently_dragged::(cx.window()) - // { - // this.channel_store - // .update(cx, |channel_store, cx| { - // channel_store.move_channel(dragged_channel.id, Some(channel_id), cx) - // }) - // .detach_and_log_err(cx) - // } - // }) - // .on_move({ - // let channel = channel.clone(); - // move |_, this, cx| { - // if let Some((_, dragged_channel)) = cx - // .global::>() - // .currently_dragged::(cx.window()) - // { - // if channel.id != dragged_channel.id { - // this.drag_target_channel = ChannelDragTarget::Channel(channel.id); - // } - // cx.notify() - // } - // } - // }) - // .as_draggable::<_, Channel>( - // channel.clone(), - // move |_, channel, cx: &mut ViewContext| { - // let theme = &theme::current(cx).collab_panel; - - // Flex::::row() - // .with_child( - // Svg::new("icons/hash.svg") - // .with_color(theme.channel_hash.color) - // .constrained() - // .with_width(theme.channel_hash.width) - // .aligned() - // .left(), - // ) - // .with_child( - // Label::new(channel.name.clone(), theme.channel_name.text.clone()) - // .contained() - // .with_style(theme.channel_name.container) - // .aligned() - // .left(), - // ) - // .align_children_center() - // .contained() - // .with_background_color( - // theme - // .container - // .background_color - // .unwrap_or(gpui::color::Color::transparent_black()), - // ) - // .contained() - // .with_padding_left( - // theme.channel_row.default_style().padding.left - // + theme.channel_indent * depth as f32, - // ) - // .into_any() - // }, - // ) - // .with_cursor_style(CursorStyle::PointingHand) - // .into_any() } - fn render_channel_editor(&self, depth: usize, cx: &mut ViewContext) -> impl IntoElement { + fn render_channel_editor(&self, depth: usize, _cx: &mut ViewContext) -> impl IntoElement { let item = ListItem::new("channel-editor") .inset(false) .indent_level(depth) @@ -2916,20 +2479,12 @@ impl Render for CollabPanel { .on_action(cx.listener(CollabPanel::select_prev)) .on_action(cx.listener(CollabPanel::confirm)) .on_action(cx.listener(CollabPanel::insert_space)) - // .on_action(cx.listener(CollabPanel::remove)) .on_action(cx.listener(CollabPanel::remove_selected_channel)) .on_action(cx.listener(CollabPanel::show_inline_context_menu)) - // .on_action(cx.listener(CollabPanel::new_subchannel)) - // .on_action(cx.listener(CollabPanel::invite_members)) - // .on_action(cx.listener(CollabPanel::manage_members)) .on_action(cx.listener(CollabPanel::rename_selected_channel)) - // .on_action(cx.listener(CollabPanel::rename_channel)) - // .on_action(cx.listener(CollabPanel::toggle_channel_collapsed_action)) .on_action(cx.listener(CollabPanel::collapse_selected_channel)) .on_action(cx.listener(CollabPanel::expand_selected_channel)) - // .on_action(cx.listener(CollabPanel::open_channel_notes)) - // .on_action(cx.listener(CollabPanel::join_channel_chat)) - // .on_action(cx.listener(CollabPanel::copy_channel_link)) + .on_action(cx.listener(CollabPanel::start_move_selected_channel)) .track_focus(&self.focus_handle) .size_full() .child(if self.user_store.read(cx).current_user().is_none() { @@ -2946,105 +2501,6 @@ impl Render for CollabPanel { } } -// impl View for CollabPanel { -// fn ui_name() -> &'static str { -// "CollabPanel" -// } - -// fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext) { -// if !self.has_focus { -// self.has_focus = true; -// if !self.context_menu.is_focused(cx) { -// if let Some(editing_state) = &self.channel_editing_state { -// if editing_state.pending_name().is_none() { -// cx.focus(&self.channel_name_editor); -// } else { -// cx.focus(&self.filter_editor); -// } -// } else { -// cx.focus(&self.filter_editor); -// } -// } -// cx.emit(Event::Focus); -// } -// } - -// fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext) { -// self.has_focus = false; -// } - -// fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement { -// let theme = &theme::current(cx).collab_panel; - -// if self.user_store.read(cx).current_user().is_none() { -// enum LogInButton {} - -// return Flex::column() -// .with_child( -// MouseEventHandler::new::(0, cx, |state, _| { -// let button = theme.log_in_button.style_for(state); -// Label::new("Sign in to collaborate", button.text.clone()) -// .aligned() -// .left() -// .contained() -// .with_style(button.container) -// }) -// .on_click(MouseButton::Left, |_, this, cx| { -// let client = this.client.clone(); -// cx.spawn(|_, cx| async move { -// client.authenticate_and_connect(true, &cx).await.log_err(); -// }) -// .detach(); -// }) -// .with_cursor_style(CursorStyle::PointingHand), -// ) -// .contained() -// .with_style(theme.container) -// .into_any(); -// } - -// enum PanelFocus {} -// MouseEventHandler::new::(0, cx, |_, cx| { -// Stack::new() -// .with_child( -// Flex::column() -// .with_child( -// Flex::row().with_child( -// ChildView::new(&self.filter_editor, cx) -// .contained() -// .with_style(theme.user_query_editor.container) -// .flex(1.0, true), -// ), -// ) -// .with_child(List::new(self.list_state.clone()).flex(1., true).into_any()) -// .contained() -// .with_style(theme.container) -// .into_any(), -// ) -// .with_children( -// (!self.context_menu_on_selected) -// .then(|| ChildView::new(&self.context_menu, cx)), -// ) -// .into_any() -// }) -// .on_click(MouseButton::Left, |_, _, cx| cx.focus_self()) -// .into_any_named("collab panel") -// } - -// fn update_keymap_context( -// &self, -// keymap: &mut gpui::keymap_matcher::KeymapContext, -// _: &AppContext, -// ) { -// Self::reset_to_default_keymap_context(keymap); -// if self.channel_editing_state.is_some() { -// keymap.add_identifier("editing"); -// } else { -// keymap.add_identifier("not_editing"); -// } -// } -// } - impl EventEmitter for CollabPanel {} impl Panel for CollabPanel { @@ -3159,11 +2615,11 @@ impl PartialEq for ListEntry { return channel_id == other_id; } } - // ListEntry::ChannelInvite(channel_1) => { - // if let ListEntry::ChannelInvite(channel_2) = other { - // return channel_1.id == channel_2.id; - // } - // } + ListEntry::ChannelInvite(channel_1) => { + if let ListEntry::ChannelInvite(channel_2) = other { + return channel_1.id == channel_2.id; + } + } ListEntry::IncomingRequest(user_1) => { if let ListEntry::IncomingRequest(user_2) = other { return user_1.id == user_2.id; @@ -3199,19 +2655,6 @@ impl PartialEq for ListEntry { } } -// fn render_icon_button(style: &IconButton, svg_path: &'static str) -> impl Element { -// Svg::new(svg_path) -// .with_color(style.color) -// .constrained() -// .with_width(style.icon_width) -// .aligned() -// .constrained() -// .with_width(style.button_width) -// .with_height(style.button_width) -// .contained() -// .with_style(style.container) -// } - struct DraggedChannelView { channel: Channel, width: Pixels, diff --git a/crates/collab_ui2/src/collab_panel/channel_modal.rs b/crates/collab_ui2/src/collab_panel/channel_modal.rs index 8636dcafe4..d903ecb086 100644 --- a/crates/collab_ui2/src/collab_panel/channel_modal.rs +++ b/crates/collab_ui2/src/collab_panel/channel_modal.rs @@ -1,3 +1,4 @@ +#![allow(unused)] use channel::{ChannelId, ChannelMembership, ChannelStore}; use client::{ proto::{self, ChannelRole, ChannelVisibility}, diff --git a/crates/collab_ui2/src/collab_panel/contact_finder.rs b/crates/collab_ui2/src/collab_panel/contact_finder.rs index ff7e02a909..208727efd2 100644 --- a/crates/collab_ui2/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui2/src/collab_panel/contact_finder.rs @@ -1,3 +1,4 @@ +#![allow(unused)] use client::{ContactRequestStatus, User, UserStore}; use gpui::{ div, img, svg, AnyElement, AppContext, DismissEvent, Div, Entity, EventEmitter, FocusHandle, From 80b6922de70b1b72d12030bef6ba981f2b439219 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 10:15:00 -0800 Subject: [PATCH 157/644] wip --- .../src/collab_panel/channel_modal.rs | 211 +++++------------- 1 file changed, 50 insertions(+), 161 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel/channel_modal.rs b/crates/collab_ui2/src/collab_panel/channel_modal.rs index d903ecb086..0b407f0647 100644 --- a/crates/collab_ui2/src/collab_panel/channel_modal.rs +++ b/crates/collab_ui2/src/collab_panel/channel_modal.rs @@ -1,4 +1,3 @@ -#![allow(unused)] use channel::{ChannelId, ChannelMembership, ChannelStore}; use client::{ proto::{self, ChannelRole, ChannelVisibility}, @@ -12,7 +11,7 @@ use gpui::{ }; use picker::{Picker, PickerDelegate}; use std::sync::Arc; -use ui::prelude::*; +use ui::{prelude::*, Checkbox}; use util::TryFutureExt; use workspace::ModalView; @@ -157,167 +156,57 @@ impl Render for ChannelModal { type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - v_stack().w(rems(34.)).child(self.picker.clone()) - // let theme = &theme::current(cx).collab_panel.tabbed_modal; + let channel_store = self.channel_store.read(cx); + let Some(channel) = channel_store.channel_for_id(self.channel_id) else { + return div(); + }; + let mode = self.picker.read(cx).delegate.mode; - // let mode = self.picker.read(cx).delegate().mode; - // let Some(channel) = self.channel_store.read(cx).channel_for_id(self.channel_id) else { - // return Empty::new().into_any(); - // }; - - // enum InviteMembers {} - // enum ManageMembers {} - - // fn render_mode_button( - // mode: Mode, - // text: &'static str, - // current_mode: Mode, - // theme: &theme::TabbedModal, - // cx: &mut ViewContext, - // ) -> AnyElement { - // let active = mode == current_mode; - // MouseEventHandler::new::(0, cx, move |state, _| { - // let contained_text = theme.tab_button.style_for(active, state); - // Label::new(text, contained_text.text.clone()) - // .contained() - // .with_style(contained_text.container.clone()) - // }) - // .on_click(MouseButton::Left, move |_, this, cx| { - // if !active { - // this.set_mode(mode, cx); - // } - // }) - // .with_cursor_style(CursorStyle::PointingHand) - // .into_any() - // } - - // fn render_visibility( - // channel_id: ChannelId, - // visibility: ChannelVisibility, - // theme: &theme::TabbedModal, - // cx: &mut ViewContext, - // ) -> AnyElement { - // enum TogglePublic {} - - // if visibility == ChannelVisibility::Members { - // return Flex::row() - // .with_child( - // MouseEventHandler::new::(0, cx, move |state, _| { - // let style = theme.visibility_toggle.style_for(state); - // Label::new(format!("{}", "Public access: OFF"), style.text.clone()) - // .contained() - // .with_style(style.container.clone()) - // }) - // .on_click(MouseButton::Left, move |_, this, cx| { - // this.channel_store - // .update(cx, |channel_store, cx| { - // channel_store.set_channel_visibility( - // channel_id, - // ChannelVisibility::Public, - // cx, - // ) - // }) - // .detach_and_log_err(cx); - // }) - // .with_cursor_style(CursorStyle::PointingHand), - // ) - // .into_any(); - // } - - // Flex::row() - // .with_child( - // MouseEventHandler::new::(0, cx, move |state, _| { - // let style = theme.visibility_toggle.style_for(state); - // Label::new(format!("{}", "Public access: ON"), style.text.clone()) - // .contained() - // .with_style(style.container.clone()) - // }) - // .on_click(MouseButton::Left, move |_, this, cx| { - // this.channel_store - // .update(cx, |channel_store, cx| { - // channel_store.set_channel_visibility( - // channel_id, - // ChannelVisibility::Members, - // cx, - // ) - // }) - // .detach_and_log_err(cx); - // }) - // .with_cursor_style(CursorStyle::PointingHand), - // ) - // .with_spacing(14.0) - // .with_child( - // MouseEventHandler::new::(1, cx, move |state, _| { - // let style = theme.channel_link.style_for(state); - // Label::new(format!("{}", "copy link"), style.text.clone()) - // .contained() - // .with_style(style.container.clone()) - // }) - // .on_click(MouseButton::Left, move |_, this, cx| { - // if let Some(channel) = - // this.channel_store.read(cx).channel_for_id(channel_id) - // { - // let item = ClipboardItem::new(channel.link()); - // cx.write_to_clipboard(item); - // } - // }) - // .with_cursor_style(CursorStyle::PointingHand), - // ) - // .into_any() - // } - - // Flex::column() - // .with_child( - // Flex::column() - // .with_child( - // Label::new(format!("#{}", channel.name), theme.title.text.clone()) - // .contained() - // .with_style(theme.title.container.clone()), - // ) - // .with_child(render_visibility(channel.id, channel.visibility, theme, cx)) - // .with_child(Flex::row().with_children([ - // render_mode_button::( - // Mode::InviteMembers, - // "Invite members", - // mode, - // theme, - // cx, - // ), - // render_mode_button::( - // Mode::ManageMembers, - // "Manage members", - // mode, - // theme, - // cx, - // ), - // ])) - // .expanded() - // .contained() - // .with_style(theme.header), - // ) - // .with_child( - // ChildView::new(&self.picker, cx) - // .contained() - // .with_style(theme.body), - // ) - // .constrained() - // .with_max_height(theme.max_height) - // .with_max_width(theme.max_width) - // .contained() - // .with_style(theme.modal) - // .into_any() + v_stack() + .bg(cx.theme().colors().elevated_surface_background) + .w(rems(34.)) + .child(Label::new(channel.name.clone())) + .child( + div() + .w_full() + .flex_row() + .child(Checkbox::new( + "is-public", + if channel.visibility == ChannelVisibility::Public { + ui::Selection::Selected + } else { + ui::Selection::Unselected + }, + )) + .child(Label::new("Public")), + ) + .child( + div() + .w_full() + .flex_row() + .child( + Button::new("manage-members", "Manage Members") + .selected(mode == Mode::ManageMembers) + .on_click(cx.listener(|this, _, cx| { + this.picker.update(cx, |picker, _| { + picker.delegate.mode = Mode::ManageMembers + }); + cx.notify(); + })), + ) + .child( + Button::new("invite-members", "Invite Members") + .selected(mode == Mode::InviteMembers) + .on_click(cx.listener(|this, _, cx| { + this.picker.update(cx, |picker, _| { + picker.delegate.mode = Mode::InviteMembers + }); + cx.notify(); + })), + ), + ) + .child(self.picker.clone()) } - - // fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext) { - // self.has_focus = true; - // if cx.is_self_focused() { - // cx.focus(&self.picker) - // } - // } - - // fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext) { - // self.has_focus = false; - // } } #[derive(Copy, Clone, PartialEq)] From 4e07167288879ccc8bfeaa365b90e6ca5f566d6a Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 13:49:52 -0500 Subject: [PATCH 158/644] Use `child` instead of `children` (#3718) This PR refactors some code where we were using `children` when we could have used `child` instead. Release Notes: - N/A --- crates/search2/src/project_search.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 284875c7f5..4e41c8b5a9 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -1654,7 +1654,7 @@ impl Render for ProjectSearchBar { }; let actions_column = h_stack() .when(search.replace_enabled, |this| { - this.children([ + this.child( IconButton::new("project-search-replace-next", Icon::ReplaceNext) .on_click(cx.listener(|this, _, cx| { if let Some(search) = this.active_project_search.as_ref() { @@ -1664,6 +1664,8 @@ impl Render for ProjectSearchBar { } })) .tooltip(|cx| Tooltip::for_action("Replace next match", &ReplaceNext, cx)), + ) + .child( IconButton::new("project-search-replace-all", Icon::ReplaceAll) .on_click(cx.listener(|this, _, cx| { if let Some(search) = this.active_project_search.as_ref() { @@ -1673,7 +1675,7 @@ impl Render for ProjectSearchBar { } })) .tooltip(|cx| Tooltip::for_action("Replace all matches", &ReplaceAll, cx)), - ]) + ) }) .when_some(search.active_match_index, |mut this, index| { let index = index + 1; @@ -1684,7 +1686,7 @@ impl Render for ProjectSearchBar { } this }) - .children([ + .child( IconButton::new("project-search-prev-match", Icon::ChevronLeft) .disabled(search.active_match_index.is_none()) .on_click(cx.listener(|this, _, cx| { @@ -1697,6 +1699,8 @@ impl Render for ProjectSearchBar { .tooltip(|cx| { Tooltip::for_action("Go to previous match", &SelectPrevMatch, cx) }), + ) + .child( IconButton::new("project-search-next-match", Icon::ChevronRight) .disabled(search.active_match_index.is_none()) .on_click(cx.listener(|this, _, cx| { @@ -1707,7 +1711,8 @@ impl Render for ProjectSearchBar { } })) .tooltip(|cx| Tooltip::for_action("Go to next match", &SelectNextMatch, cx)), - ]); + ); + v_stack() .key_context(key_context) .flex_grow() From 1c3698ae20cdb2ec9aace81bb29d56f19e4f2888 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 12:02:35 -0800 Subject: [PATCH 159/644] Implement channel modal Co-authored-by: Nathan --- crates/collab_ui2/src/collab_panel.rs | 10 +- .../src/collab_panel/channel_modal.rs | 430 ++++++++---------- crates/gpui2/src/window.rs | 7 - crates/picker2/src/picker2.rs | 2 +- crates/ui2/src/components/context_menu.rs | 5 +- crates/ui2/src/components/icon.rs | 2 + 6 files changed, 213 insertions(+), 243 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index c58d7c47bc..3df8f06d3b 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2167,13 +2167,13 @@ impl CollabPanel { let controls = if is_incoming { vec![ - IconButton::new("remove_contact", Icon::Close) + IconButton::new("decline-contact", Icon::Close) .on_click(cx.listener(move |this, _, cx| { this.respond_to_contact_request(user_id, false, cx); })) .icon_color(color) .tooltip(|cx| Tooltip::text("Decline invite", cx)), - IconButton::new("remove_contact", Icon::Check) + IconButton::new("accept-contact", Icon::Check) .on_click(cx.listener(move |this, _, cx| { this.respond_to_contact_request(user_id, true, cx); })) @@ -2220,15 +2220,15 @@ impl CollabPanel { }; let controls = [ - IconButton::new("remove_contact", Icon::Close) + IconButton::new("reject-invite", Icon::Close) .on_click(cx.listener(move |this, _, cx| { this.respond_to_channel_invite(channel_id, false, cx); })) .icon_color(color) .tooltip(|cx| Tooltip::text("Decline invite", cx)), - IconButton::new("remove_contact", Icon::Check) + IconButton::new("accept-invite", Icon::Check) .on_click(cx.listener(move |this, _, cx| { - this.respond_to_contact_request(channel_id, true, cx); + this.respond_to_channel_invite(channel_id, true, cx); })) .icon_color(color) .tooltip(|cx| Tooltip::text("Accept invite", cx)), diff --git a/crates/collab_ui2/src/collab_panel/channel_modal.rs b/crates/collab_ui2/src/collab_panel/channel_modal.rs index 0b407f0647..f844c609ca 100644 --- a/crates/collab_ui2/src/collab_panel/channel_modal.rs +++ b/crates/collab_ui2/src/collab_panel/channel_modal.rs @@ -5,13 +5,13 @@ use client::{ }; use fuzzy::{match_strings, StringMatchCandidate}; use gpui::{ - actions, div, AppContext, ClipboardItem, DismissEvent, Div, Entity, EventEmitter, - FocusableView, Model, ParentElement, Render, Styled, Task, View, ViewContext, VisualContext, - WeakView, + actions, div, overlay, AppContext, ClipboardItem, DismissEvent, Div, EventEmitter, + FocusableView, Model, ParentElement, Render, Styled, Subscription, Task, View, ViewContext, + VisualContext, WeakView, }; use picker::{Picker, PickerDelegate}; use std::sync::Arc; -use ui::{prelude::*, Checkbox}; +use ui::{prelude::*, Avatar, Checkbox, ContextMenu, ListItem}; use util::TryFutureExt; use workspace::ModalView; @@ -25,19 +25,10 @@ actions!( ] ); -// pub fn init(cx: &mut AppContext) { -// Picker::::init(cx); -// cx.add_action(ChannelModal::toggle_mode); -// cx.add_action(ChannelModal::toggle_member_admin); -// cx.add_action(ChannelModal::remove_member); -// cx.add_action(ChannelModal::dismiss); -// } - pub struct ChannelModal { picker: View>, channel_store: Model, channel_id: ChannelId, - has_focus: bool, } impl ChannelModal { @@ -62,25 +53,19 @@ impl ChannelModal { channel_store: channel_store.clone(), channel_id, match_candidates: Vec::new(), + context_menu: None, members, mode, - // context_menu: cx.add_view(|cx| { - // let mut menu = ContextMenu::new(cx.view_id(), cx); - // menu.set_position_mode(OverlayPositionMode::Local); - // menu - // }), }, cx, ) + .modal(false) }); - let has_focus = picker.focus_handle(cx).contains_focused(cx); - Self { picker, channel_store, channel_id, - has_focus, } } @@ -126,15 +111,19 @@ impl ChannelModal { .detach(); } - fn toggle_member_admin(&mut self, _: &ToggleMemberAdmin, cx: &mut ViewContext) { - self.picker.update(cx, |picker, cx| { - picker.delegate.toggle_selected_member_admin(cx); - }) - } - - fn remove_member(&mut self, _: &RemoveMember, cx: &mut ViewContext) { - self.picker.update(cx, |picker, cx| { - picker.delegate.remove_selected_member(cx); + fn set_channel_visiblity(&mut self, selection: &Selection, cx: &mut ViewContext) { + self.channel_store.update(cx, |channel_store, cx| { + channel_store + .set_channel_visibility( + self.channel_id, + match selection { + Selection::Unselected => ChannelVisibility::Members, + Selection::Selected => ChannelVisibility::Public, + Selection::Indeterminate => return, + }, + cx, + ) + .detach_and_log_err(cx) }); } @@ -160,49 +149,79 @@ impl Render for ChannelModal { let Some(channel) = channel_store.channel_for_id(self.channel_id) else { return div(); }; + let channel_name = channel.name.clone(); + let channel_id = channel.id; + let visibility = channel.visibility; let mode = self.picker.read(cx).delegate.mode; v_stack() - .bg(cx.theme().colors().elevated_surface_background) + .key_context("ChannelModal") + .on_action(cx.listener(Self::toggle_mode)) + .on_action(cx.listener(Self::dismiss)) + .elevation_3(cx) .w(rems(34.)) - .child(Label::new(channel.name.clone())) .child( - div() - .w_full() - .flex_row() - .child(Checkbox::new( - "is-public", - if channel.visibility == ChannelVisibility::Public { - ui::Selection::Selected - } else { - ui::Selection::Unselected - }, - )) - .child(Label::new("Public")), - ) - .child( - div() - .w_full() - .flex_row() + v_stack() + .px_2() + .py_1() + .rounded_t(px(8.)) + .bg(cx.theme().colors().element_background) + .child(IconElement::new(Icon::Hash).size(IconSize::Medium)) + .child(Label::new(channel_name)) .child( - Button::new("manage-members", "Manage Members") - .selected(mode == Mode::ManageMembers) - .on_click(cx.listener(|this, _, cx| { - this.picker.update(cx, |picker, _| { - picker.delegate.mode = Mode::ManageMembers - }); - cx.notify(); - })), + h_stack() + .w_full() + .justify_between() + .child( + h_stack() + .gap_2() + .child( + Checkbox::new( + "is-public", + if visibility == ChannelVisibility::Public { + ui::Selection::Selected + } else { + ui::Selection::Unselected + }, + ) + .on_click(cx.listener(Self::set_channel_visiblity)), + ) + .child(Label::new("Public")), + ) + .children(if visibility == ChannelVisibility::Public { + Some(Button::new("copy-link", "Copy Link").on_click(cx.listener( + move |this, _, cx| { + if let Some(channel) = + this.channel_store.read(cx).channel_for_id(channel_id) + { + let item = ClipboardItem::new(channel.link()); + cx.write_to_clipboard(item); + } + }, + ))) + } else { + None + }), ) .child( - Button::new("invite-members", "Invite Members") - .selected(mode == Mode::InviteMembers) - .on_click(cx.listener(|this, _, cx| { - this.picker.update(cx, |picker, _| { - picker.delegate.mode = Mode::InviteMembers - }); - cx.notify(); - })), + div() + .w_full() + .flex() + .flex_row() + .child( + Button::new("manage-members", "Manage Members") + .selected(mode == Mode::ManageMembers) + .on_click(cx.listener(|this, _, cx| { + this.set_mode(Mode::ManageMembers, cx); + })), + ) + .child( + Button::new("invite-members", "Invite Members") + .selected(mode == Mode::InviteMembers) + .on_click(cx.listener(|this, _, cx| { + this.set_mode(Mode::InviteMembers, cx); + })), + ), ), ) .child(self.picker.clone()) @@ -226,11 +245,11 @@ pub struct ChannelModalDelegate { mode: Mode, match_candidates: Vec, members: Vec, - // context_menu: ViewHandle, + context_menu: Option<(View, Subscription)>, } impl PickerDelegate for ChannelModalDelegate { - type ListItem = Div; + type ListItem = ListItem; fn placeholder_text(&self) -> Arc { "Search collaborator by username...".into() @@ -310,11 +329,11 @@ impl PickerDelegate for ChannelModalDelegate { if let Some((selected_user, role)) = self.user_at_index(self.selected_index) { match self.mode { Mode::ManageMembers => { - self.show_context_menu(role.unwrap_or(ChannelRole::Member), cx) + self.show_context_menu(selected_user, role.unwrap_or(ChannelRole::Member), cx) } Mode::InviteMembers => match self.member_status(selected_user.id, cx) { Some(proto::channel_member::Kind::Invitee) => { - self.remove_selected_member(cx); + self.remove_member(selected_user.id, cx); } Some(proto::channel_member::Kind::AncestorMember) | None => { self.invite_member(selected_user, cx) @@ -326,11 +345,13 @@ impl PickerDelegate for ChannelModalDelegate { } fn dismissed(&mut self, cx: &mut ViewContext>) { - self.channel_modal - .update(cx, |_, cx| { - cx.emit(DismissEvent); - }) - .ok(); + if self.context_menu.is_none() { + self.channel_modal + .update(cx, |_, cx| { + cx.emit(DismissEvent); + }) + .ok(); + } } fn render_match( @@ -339,129 +360,54 @@ impl PickerDelegate for ChannelModalDelegate { selected: bool, cx: &mut ViewContext>, ) -> Option { - None - // let full_theme = &theme::current(cx); - // let theme = &full_theme.collab_panel.channel_modal; - // let tabbed_modal = &full_theme.collab_panel.tabbed_modal; - // let (user, role) = self.user_at_index(ix).unwrap(); - // let request_status = self.member_status(user.id, cx); + let (user, role) = self.user_at_index(ix)?; + let request_status = self.member_status(user.id, cx); - // let style = tabbed_modal - // .picker - // .item - // .in_state(selected) - // .style_for(mouse_state); - - // let in_manage = matches!(self.mode, Mode::ManageMembers); - - // let mut result = Flex::row() - // .with_children(user.avatar.clone().map(|avatar| { - // Image::from_data(avatar) - // .with_style(theme.contact_avatar) - // .aligned() - // .left() - // })) - // .with_child( - // Label::new(user.github_login.clone(), style.label.clone()) - // .contained() - // .with_style(theme.contact_username) - // .aligned() - // .left(), - // ) - // .with_children({ - // (in_manage && request_status == Some(proto::channel_member::Kind::Invitee)).then( - // || { - // Label::new("Invited", theme.member_tag.text.clone()) - // .contained() - // .with_style(theme.member_tag.container) - // .aligned() - // .left() - // }, - // ) - // }) - // .with_children(if in_manage && role == Some(ChannelRole::Admin) { - // Some( - // Label::new("Admin", theme.member_tag.text.clone()) - // .contained() - // .with_style(theme.member_tag.container) - // .aligned() - // .left(), - // ) - // } else if in_manage && role == Some(ChannelRole::Guest) { - // Some( - // Label::new("Guest", theme.member_tag.text.clone()) - // .contained() - // .with_style(theme.member_tag.container) - // .aligned() - // .left(), - // ) - // } else { - // None - // }) - // .with_children({ - // let svg = match self.mode { - // Mode::ManageMembers => Some( - // Svg::new("icons/ellipsis.svg") - // .with_color(theme.member_icon.color) - // .constrained() - // .with_width(theme.member_icon.icon_width) - // .aligned() - // .constrained() - // .with_width(theme.member_icon.button_width) - // .with_height(theme.member_icon.button_width) - // .contained() - // .with_style(theme.member_icon.container), - // ), - // Mode::InviteMembers => match request_status { - // Some(proto::channel_member::Kind::Member) => Some( - // Svg::new("icons/check.svg") - // .with_color(theme.member_icon.color) - // .constrained() - // .with_width(theme.member_icon.icon_width) - // .aligned() - // .constrained() - // .with_width(theme.member_icon.button_width) - // .with_height(theme.member_icon.button_width) - // .contained() - // .with_style(theme.member_icon.container), - // ), - // Some(proto::channel_member::Kind::Invitee) => Some( - // Svg::new("icons/check.svg") - // .with_color(theme.invitee_icon.color) - // .constrained() - // .with_width(theme.invitee_icon.icon_width) - // .aligned() - // .constrained() - // .with_width(theme.invitee_icon.button_width) - // .with_height(theme.invitee_icon.button_width) - // .contained() - // .with_style(theme.invitee_icon.container), - // ), - // Some(proto::channel_member::Kind::AncestorMember) | None => None, - // }, - // }; - - // svg.map(|svg| svg.aligned().flex_float().into_any()) - // }) - // .contained() - // .with_style(style.container) - // .constrained() - // .with_height(tabbed_modal.row_height) - // .into_any(); - - // if selected { - // result = Stack::new() - // .with_child(result) - // .with_child( - // ChildView::new(&self.context_menu, cx) - // .aligned() - // .top() - // .right(), - // ) - // .into_any(); - // } - - // result + Some( + ListItem::new(ix) + .inset(true) + .selected(selected) + .start_slot(Avatar::new(user.avatar_uri.clone())) + .child(Label::new(user.github_login.clone())) + .end_slot(h_stack().gap_2().map(|slot| { + match self.mode { + Mode::ManageMembers => slot + .children( + if request_status == Some(proto::channel_member::Kind::Invitee) { + Some(Label::new("Invited")) + } else { + None + }, + ) + .children(match role { + Some(ChannelRole::Admin) => Some(Label::new("Admin")), + Some(ChannelRole::Guest) => Some(Label::new("Guest")), + _ => None, + }) + .child(IconButton::new("ellipsis", Icon::Ellipsis)) + .children( + if let (Some((menu, _)), true) = (&self.context_menu, selected) { + Some( + overlay() + .anchor(gpui::AnchorCorner::TopLeft) + .child(menu.clone()), + ) + } else { + None + }, + ), + Mode::InviteMembers => match request_status { + Some(proto::channel_member::Kind::Invitee) => { + slot.children(Some(Label::new("Invited"))) + } + Some(proto::channel_member::Kind::Member) => { + slot.children(Some(Label::new("Member"))) + } + _ => slot, + }, + } + })), + ) } } @@ -495,21 +441,20 @@ impl ChannelModalDelegate { } } - fn toggle_selected_member_admin(&mut self, cx: &mut ViewContext>) -> Option<()> { - let (user, role) = self.user_at_index(self.selected_index)?; - let new_role = if role == Some(ChannelRole::Admin) { - ChannelRole::Member - } else { - ChannelRole::Admin - }; + fn set_user_role( + &mut self, + user_id: UserId, + new_role: ChannelRole, + cx: &mut ViewContext>, + ) -> Option<()> { let update = self.channel_store.update(cx, |store, cx| { - store.set_member_role(self.channel_id, user.id, new_role, cx) + store.set_member_role(self.channel_id, user_id, new_role, cx) }); cx.spawn(|picker, mut cx| async move { update.await?; picker.update(&mut cx, |picker, cx| { let this = &mut picker.delegate; - if let Some(member) = this.members.iter_mut().find(|m| m.user.id == user.id) { + if let Some(member) = this.members.iter_mut().find(|m| m.user.id == user_id) { member.role = new_role; } cx.focus_self(); @@ -520,9 +465,7 @@ impl ChannelModalDelegate { Some(()) } - fn remove_selected_member(&mut self, cx: &mut ViewContext>) -> Option<()> { - let (user, _) = self.user_at_index(self.selected_index)?; - let user_id = user.id; + fn remove_member(&mut self, user_id: UserId, cx: &mut ViewContext>) -> Option<()> { let update = self.channel_store.update(cx, |store, cx| { store.remove_member(self.channel_id, user_id, cx) }); @@ -546,7 +489,7 @@ impl ChannelModalDelegate { .selected_index .min(this.matching_member_indices.len().saturating_sub(1)); - cx.focus_self(); + picker.focus(cx); cx.notify(); }) }) @@ -579,24 +522,55 @@ impl ChannelModalDelegate { .detach_and_log_err(cx); } - fn show_context_menu(&mut self, role: ChannelRole, cx: &mut ViewContext>) { - // self.context_menu.update(cx, |context_menu, cx| { - // context_menu.show( - // Default::default(), - // AnchorCorner::TopRight, - // vec![ - // ContextMenuItem::action("Remove", RemoveMember), - // ContextMenuItem::action( - // if role == ChannelRole::Admin { - // "Make non-admin" - // } else { - // "Make admin" - // }, - // ToggleMemberAdmin, - // ), - // ], - // cx, - // ) - // }) + fn show_context_menu( + &mut self, + user: Arc, + role: ChannelRole, + cx: &mut ViewContext>, + ) { + let user_id = user.id; + let picker = cx.view().clone(); + let context_menu = ContextMenu::build(cx, |mut menu, _cx| { + menu = menu.entry("Remove Member", { + let picker = picker.clone(); + move |cx| { + picker.update(cx, |picker, cx| { + picker.delegate.remove_member(user_id, cx); + }) + } + }); + + let picker = picker.clone(); + match role { + ChannelRole::Admin => { + menu = menu.entry("Revoke Admin", move |cx| { + picker.update(cx, |picker, cx| { + picker + .delegate + .set_user_role(user_id, ChannelRole::Member, cx); + }) + }); + } + ChannelRole::Member => { + menu = menu.entry("Make Admin", move |cx| { + picker.update(cx, |picker, cx| { + picker + .delegate + .set_user_role(user_id, ChannelRole::Admin, cx); + }) + }); + } + _ => {} + }; + + menu + }); + cx.focus_view(&context_menu); + let subscription = cx.subscribe(&context_menu, |picker, _, _: &DismissEvent, cx| { + picker.delegate.context_menu = None; + picker.focus(cx); + cx.notify(); + }); + self.context_menu = Some((context_menu, subscription)); } } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 71799a6e00..f7ebddd0fe 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -2662,13 +2662,6 @@ impl<'a, V: 'static> ViewContext<'a, V> { self.defer(|view, cx| view.focus_handle(cx).focus(cx)) } - pub fn dismiss_self(&mut self) - where - V: ManagedView, - { - self.defer(|_, cx| cx.emit(DismissEvent)) - } - pub fn listener( &self, f: impl Fn(&mut V, &E, &mut ViewContext) + 'static, diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 70180112f9..8a75996f48 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -239,7 +239,7 @@ impl Render for Picker { ); div() - .key_context("picker") + .key_context("Picker") .size_full() .when_some(self.width, |el, width| { el.w(width) diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 250272b198..8fce15d1c6 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -72,11 +72,11 @@ impl ContextMenu { pub fn entry( mut self, label: impl Into, - on_click: impl Fn(&mut WindowContext) + 'static, + handler: impl Fn(&mut WindowContext) + 'static, ) -> Self { self.items.push(ContextMenuItem::Entry { label: label.into(), - handler: Rc::new(on_click), + handler: Rc::new(handler), icon: None, action: None, }); @@ -114,6 +114,7 @@ impl ContextMenu { pub fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { cx.emit(DismissEvent); + cx.emit(DismissEvent); } fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext) { diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index ca50cae7f8..a168f97a50 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -51,6 +51,7 @@ pub enum Icon { CopilotDisabled, Dash, Disconnected, + Ellipsis, Envelope, ExternalLink, ExclamationTriangle, @@ -133,6 +134,7 @@ impl Icon { Icon::CopilotDisabled => "icons/copilot_disabled.svg", Icon::Dash => "icons/dash.svg", Icon::Disconnected => "icons/disconnected.svg", + Icon::Ellipsis => "icons/ellipsis.svg", Icon::Envelope => "icons/feedback.svg", Icon::ExclamationTriangle => "icons/warning.svg", Icon::ExternalLink => "icons/external_link.svg", From a9b1273e2bd9d446bd11b7f35b2792f4ef6b0d53 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 12:06:47 -0800 Subject: [PATCH 160/644] Clean up commented code Co-authored-by: Nathan --- crates/collab_ui2/src/collab_panel.rs | 316 +++----------------------- 1 file changed, 34 insertions(+), 282 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 3df8f06d3b..b7dd24b9ab 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -1,128 +1,45 @@ mod channel_modal; mod contact_finder; -// use crate::{ -// channel_view::{self, ChannelView}, -// chat_panel::ChatPanel, -// face_pile::FacePile, -// panel_settings, CollaborationPanelSettings, -// }; -// use anyhow::Result; -// use call::ActiveCall; -// use channel::{Channel, ChannelEvent, ChannelId, ChannelStore}; -// use channel_modal::ChannelModal; -// use client::{ -// proto::{self, PeerId}, -// Client, Contact, User, UserStore, -// }; +use self::channel_modal::ChannelModal; +use crate::{ + channel_view::ChannelView, chat_panel::ChatPanel, face_pile::FacePile, + CollaborationPanelSettings, +}; +use call::ActiveCall; +use channel::{Channel, ChannelEvent, ChannelId, ChannelStore}; +use client::{Client, Contact, User, UserStore}; use contact_finder::ContactFinder; +use db::kvp::KEY_VALUE_STORE; +use editor::Editor; +use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt}; +use fuzzy::{match_strings, StringMatchCandidate}; +use gpui::{ + actions, canvas, div, fill, list, overlay, point, prelude::*, px, serde_json, AnyElement, + AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, EventEmitter, + FocusHandle, Focusable, FocusableView, InteractiveElement, IntoElement, ListOffset, ListState, + Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, RenderOnce, + SharedString, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, +}; use menu::{Cancel, Confirm, SelectNext, SelectPrev}; +use project::{Fs, Project}; use rpc::proto::{self, PeerId}; +use serde_derive::{Deserialize, Serialize}; +use settings::{Settings, SettingsStore}; use smallvec::SmallVec; +use std::{mem, sync::Arc}; use theme::{ActiveTheme, ThemeSettings}; -// use context_menu::{ContextMenu, ContextMenuItem}; -// use db::kvp::KEY_VALUE_STORE; -// use drag_and_drop::{DragAndDrop, Draggable}; -// use editor::{Cancel, Editor}; -// use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt}; -// use futures::StreamExt; -// use fuzzy::{match_strings, StringMatchCandidate}; -// use gpui::{ -// actions, -// elements::{ -// Canvas, ChildView, Component, ContainerStyle, Empty, Flex, Image, Label, List, ListOffset, -// ListState, MouseEventHandler, Orientation, OverlayPositionMode, Padding, ParentElement, -// SafeStylable, Stack, Svg, -// }, -// fonts::TextStyle, -// geometry::{ -// rect::RectF, -// vector::{vec2f, Vector2F}, -// }, -// impl_actions, -// platform::{CursorStyle, MouseButton, PromptLevel}, -// serde_json, AnyElement, AppContext, AsyncAppContext, ClipboardItem, Element, Entity, FontCache, -// ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, -// }; -// use menu::{Confirm, SelectNext, SelectPrev}; -// use project::{Fs, Project}; -// use serde_derive::{Deserialize, Serialize}; -// use settings::SettingsStore; -// use std::{borrow::Cow, hash::Hash, mem, sync::Arc}; -// use theme::{components::ComponentExt, IconButton, Interactive}; -// use util::{maybe, ResultExt, TryFutureExt}; -// use workspace::{ -// dock::{DockPosition, Panel}, -// item::ItemHandle, -// FollowNextCollaborator, Workspace, -// }; - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct ToggleCollapse { -// location: ChannelId, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct NewChannel { -// location: ChannelId, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct RenameChannel { -// channel_id: ChannelId, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct ToggleSelectedIx { -// ix: usize, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct RemoveChannel { -// channel_id: ChannelId, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct InviteMembers { -// channel_id: ChannelId, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct ManageMembers { -// channel_id: ChannelId, -// } - -#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)] -pub struct OpenChannelNotes { - pub channel_id: ChannelId, -} - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// pub struct JoinChannelCall { -// pub channel_id: u64, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// pub struct JoinChannelChat { -// pub channel_id: u64, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// pub struct CopyChannelLink { -// pub channel_id: u64, -// } - -// #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct StartMoveChannelFor { -// channel_id: ChannelId, -// } - -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// struct MoveChannel { -// to: ChannelId, -// } - -impl_actions!(collab_panel, [OpenChannelNotes]); +use ui::prelude::*; +use ui::{ + h_stack, v_stack, Avatar, Button, Color, ContextMenu, Icon, IconButton, IconElement, IconSize, + Label, ListHeader, ListItem, Tooltip, +}; +use util::{maybe, ResultExt, TryFutureExt}; +use workspace::{ + dock::{DockPosition, Panel, PanelEvent}, + notifications::NotifyResultExt, + Workspace, +}; actions!( collab_panel, @@ -138,25 +55,6 @@ actions!( ] ); -// impl_actions!( -// collab_panel, -// [ -// RemoveChannel, -// NewChannel, -// InviteMembers, -// ManageMembers, -// RenameChannel, -// ToggleCollapse, -// OpenChannelNotes, -// JoinChannelCall, -// JoinChannelChat, -// CopyChannelLink, -// StartMoveChannelFor, -// MoveChannel, -// ToggleSelectedIx -// ] -// ); - #[derive(Debug, Copy, Clone, PartialEq, Eq)] struct ChannelMoveClipboard { channel_id: ChannelId, @@ -164,44 +62,6 @@ struct ChannelMoveClipboard { const COLLABORATION_PANEL_KEY: &'static str = "CollaborationPanel"; -use std::{mem, sync::Arc}; - -use call::ActiveCall; -use channel::{Channel, ChannelEvent, ChannelId, ChannelStore}; -use client::{Client, Contact, User, UserStore}; -use db::kvp::KEY_VALUE_STORE; -use editor::Editor; -use feature_flags::{ChannelsAlpha, FeatureFlagAppExt, FeatureFlagViewExt}; -use fuzzy::{match_strings, StringMatchCandidate}; -use gpui::{ - actions, canvas, div, fill, impl_actions, list, overlay, point, prelude::*, px, serde_json, - AnyElement, AppContext, AsyncWindowContext, Bounds, ClipboardItem, DismissEvent, Div, - EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement, IntoElement, - ListOffset, ListState, Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, - Render, RenderOnce, SharedString, Styled, Subscription, Task, View, ViewContext, VisualContext, - WeakView, -}; -use project::{Fs, Project}; -use serde_derive::{Deserialize, Serialize}; -use settings::{Settings, SettingsStore}; -use ui::prelude::*; -use ui::{ - h_stack, v_stack, Avatar, Button, Color, ContextMenu, Icon, IconButton, IconElement, IconSize, - Label, ListHeader, ListItem, Tooltip, -}; -use util::{maybe, ResultExt, TryFutureExt}; -use workspace::{ - dock::{DockPosition, Panel, PanelEvent}, - notifications::NotifyResultExt, - Workspace, -}; - -use crate::channel_view::ChannelView; -use crate::chat_panel::ChatPanel; -use crate::{face_pile::FacePile, CollaborationPanelSettings}; - -use self::channel_modal::ChannelModal; - pub fn init(cx: &mut AppContext) { cx.observe_new_views(|workspace: &mut Workspace, _| { workspace.register_action(|workspace, _: &ToggleFocus, cx| { @@ -209,69 +69,6 @@ pub fn init(cx: &mut AppContext) { }); }) .detach(); - // contact_finder::init(cx); - // channel_modal::init(cx); - // channel_view::init(cx); - - // cx.add_action(CollabPanel::cancel); - // cx.add_action(CollabPanel::select_next); - // cx.add_action(CollabPanel::select_prev); - // cx.add_action(CollabPanel::confirm); - // cx.add_action(CollabPanel::insert_space); - // cx.add_action(CollabPanel::remove); - // cx.add_action(CollabPanel::remove_selected_channel); - // cx.add_action(CollabPanel::show_inline_context_menu); - // cx.add_action(CollabPanel::new_subchannel); - // cx.add_action(CollabPanel::invite_members); - // cx.add_action(CollabPanel::manage_members); - // cx.add_action(CollabPanel::rename_selected_channel); - // cx.add_action(CollabPanel::rename_channel); - // cx.add_action(CollabPanel::toggle_channel_collapsed_action); - // cx.add_action(CollabPanel::collapse_selected_channel); - // cx.add_action(CollabPanel::expand_selected_channel); - // cx.add_action(CollabPanel::open_channel_notes); - // cx.add_action(CollabPanel::join_channel_chat); - // cx.add_action(CollabPanel::copy_channel_link); - - // cx.add_action( - // |panel: &mut CollabPanel, action: &ToggleSelectedIx, cx: &mut ViewContext| { - // if panel.selection.take() != Some(action.ix) { - // panel.selection = Some(action.ix) - // } - - // cx.notify(); - // }, - // ); - - // cx.add_action( - // |panel: &mut CollabPanel, _: &MoveSelected, cx: &mut ViewContext| { - // let Some(clipboard) = panel.channel_clipboard.take() else { - // return; - // }; - // let Some(selected_channel) = panel.selected_channel() else { - // return; - // }; - - // panel - // .channel_store - // .update(cx, |channel_store, cx| { - // channel_store.move_channel(clipboard.channel_id, Some(selected_channel.id), cx) - // }) - // .detach_and_log_err(cx) - // }, - // ); - - // cx.add_action( - // |panel: &mut CollabPanel, action: &MoveChannel, cx: &mut ViewContext| { - // if let Some(clipboard) = panel.channel_clipboard.take() { - // panel.channel_store.update(cx, |channel_store, cx| { - // channel_store - // .move_channel(clipboard.channel_id, Some(action.to), cx) - // .detach_and_log_err(cx) - // }) - // } - // }, - // ); } #[derive(Debug)] @@ -317,7 +114,6 @@ pub struct CollabPanel { collapsed_sections: Vec
, collapsed_channels: Vec, workspace: WeakView, - // context_menu_on_selected: bool, } #[derive(Serialize, Deserialize)] @@ -326,13 +122,6 @@ struct SerializedCollabPanel { collapsed_channels: Option>, } -// #[derive(Debug)] -// pub enum Event { -// DockPositionChanged, -// Focus, -// Dismissed, -// } - #[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)] enum Section { ActiveCall, @@ -1131,40 +920,6 @@ impl CollabPanel { } } - // fn render_contact_placeholder( - // &self, - // theme: &theme::CollabPanel, - // is_selected: bool, - // cx: &mut ViewContext, - // ) -> AnyElement { - // enum AddContacts {} - // MouseEventHandler::new::(0, cx, |state, _| { - // let style = theme.list_empty_state.style_for(is_selected, state); - // Flex::row() - // .with_child( - // Svg::new("icons/plus.svg") - // .with_color(theme.list_empty_icon.color) - // .constrained() - // .with_width(theme.list_empty_icon.width) - // .aligned() - // .left(), - // ) - // .with_child( - // Label::new("Add a contact", style.text.clone()) - // .contained() - // .with_style(theme.list_empty_label_container), - // ) - // .align_children_center() - // .contained() - // .with_style(style.container) - // .into_any() - // }) - // .on_click(MouseButton::Left, |_, this, cx| { - // this.toggle_contact_finder(cx); - // }) - // .into_any() - // } - fn render_channel_notes( &self, channel_id: ChannelId, @@ -1752,9 +1507,6 @@ impl CollabPanel { } } - // // Should move to the filter editor if clicking on it - // // Should move selection to the channel editor if activating it - fn remove_contact(&mut self, user_id: u64, github_login: &str, cx: &mut ViewContext) { let user_store = self.user_store.clone(); let prompt_message = format!( From 7bc9319871d5519369b95a67a5bb4343bb091d2d Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 16:01:03 -0500 Subject: [PATCH 161/644] Apply padding at the toolbar level (#3720) This PR adjusts the padding in the toolbar to be applied within the toolbar itself. Previously the different elements within the toolbar were applying their own padding, which led to inconsistencies. Release Notes: - N/A --- crates/search2/src/buffer_search.rs | 1 - crates/search2/src/project_search.rs | 2 -- crates/workspace2/src/toolbar.rs | 3 ++- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index 17dc13feaa..ebaf111e60 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -240,7 +240,6 @@ impl Render for BufferSearchBar { this.on_action(cx.listener(Self::toggle_whole_word)) }) .w_full() - .p_1() .child( h_stack() .flex_1() diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 4e41c8b5a9..af8ac41834 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -1716,8 +1716,6 @@ impl Render for ProjectSearchBar { v_stack() .key_context(key_context) .flex_grow() - .p_1() - .m_2() .gap_2() .on_action(cx.listener(|this, _: &ToggleFilters, cx| { this.toggle_filters(cx); diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index 1c60b8967f..cd25582f36 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -103,6 +103,8 @@ impl Render for Toolbar { let secondary_item = self.secondary_items().next().map(|item| item.to_any()); v_stack() + .p_1() + .gap_2() .border_b() .border_color(cx.theme().colors().border_variant) .bg(cx.theme().colors().toolbar_background) @@ -112,7 +114,6 @@ impl Render for Toolbar { .when(self.left_items().count() > 0, |this| { this.child( h_stack() - .p_1() .flex_1() .justify_start() .children(self.left_items().map(|item| item.to_any())), From a9fe108dbb22b631bc81d24335c72ed295056ef2 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 16:21:58 -0500 Subject: [PATCH 162/644] Fix typo in "Quote Selection" tooltip (#3721) This PR fixes a typo in the "Quote Selection" tooltip. Release Notes: - N/A --- crates/assistant2/src/assistant_panel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index ec67d684da..7b15619758 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -990,7 +990,7 @@ impl AssistantPanel { } })) .icon_size(IconSize::Small) - .tooltip(|cx| Tooltip::for_action("Quote Seleciton", &QuoteSelection, cx)) + .tooltip(|cx| Tooltip::for_action("Quote Selection", &QuoteSelection, cx)) } fn render_plus_button(cx: &mut ViewContext) -> impl IntoElement { From 825a8f0927c17baa14b67c8d5ea1d212e2294350 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 18 Dec 2023 19:15:54 +0200 Subject: [PATCH 163/644] Initial fix of the z-index Co-Authored-By: Antonio Scandurra Co-Authored-By: Nathan Sobo --- crates/gpui2/src/elements/div.rs | 12 +- crates/gpui2/src/scene.rs | 153 ++++++++++++++------ crates/gpui2/src/window.rs | 75 ++++++++-- crates/ui2/src/components/list/list_item.rs | 4 +- crates/workspace2/src/toolbar.rs | 2 + 5 files changed, 181 insertions(+), 65 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 0d477fc62d..6e9c95e19f 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1447,9 +1447,15 @@ impl Interactivity { cx.on_action(action_type, listener) } - f(style, scroll_offset.unwrap_or_default(), cx) - }, - ); + cx.with_z_index(style.z_index.unwrap_or(0), |cx| { + if style.background.as_ref().is_some_and(|fill| { + fill.color().is_some_and(|color| !color.is_transparent()) + }) { + cx.add_opaque_layer(bounds) + }f(style, scroll_offset.unwrap_or_default(), cx) + }) + }, + ); if let Some(group) = self.group.as_ref() { GroupBounds::pop(group, cx); diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index 68c068dfe9..15a4a37d5b 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -857,55 +857,116 @@ impl Bounds { } } -// #[cfg(test)] -// mod tests { -// use crate::{point, size}; +#[cfg(test)] +mod tests { + use super::*; + use crate::{point, px, size, Size}; + use smallvec::smallvec; -// use super::*; -// use smallvec::smallvec; + // todo!() + // #[test] + // fn test_scene() { + // let mut scene = SceneBuilder::default(); + // assert_eq!(scene.layers_by_order.len(), 0); -// #[test] -// fn test_scene() { -// let mut scene = SceneBuilder::new(); -// assert_eq!(scene.layers_by_order.len(), 0); + // // div with z_index(1) + // // glyph with z_index(1) + // // div with z_index(1) + // // glyph with z_index(1) -// scene.insert(&smallvec![1].into(), quad()); -// scene.insert(&smallvec![2].into(), shadow()); -// scene.insert(&smallvec![3].into(), quad()); + // scene.insert( + // &smallvec![1].into(), + // quad( + // point(px(0.), px(0.)), + // size(px(100.), px(100.)), + // crate::black(), + // ), + // ); + // scene.insert( + // &smallvec![1, 1].into(), + // sprite( + // point(px(0.), px(0.)), + // size(px(10.), px(10.)), + // crate::white(), + // ), + // ); + // scene.insert( + // &smallvec![1].into(), + // quad( + // point(px(10.), px(10.)), + // size(px(20.), px(20.)), + // crate::green(), + // ), + // ); + // scene.insert( + // &smallvec![1, 1].into(), + // sprite(point(px(15.), px(15.)), size(px(5.), px(5.)), crate::blue()), + // ); -// let mut batches_count = 0; -// for _ in scene.build().batches() { -// batches_count += 1; -// } -// assert_eq!(batches_count, 3); -// } + // assert!(!scene.layers_by_order.is_empty()); -// fn quad() -> Quad { -// Quad { -// order: 0, -// bounds: Bounds { -// origin: point(ScaledPixels(0.), ScaledPixels(0.)), -// size: size(ScaledPixels(100.), ScaledPixels(100.)), -// }, -// content_mask: Default::default(), -// background: Default::default(), -// border_color: Default::default(), -// corner_radii: Default::default(), -// border_widths: Default::default(), -// } -// } + // for batch in scene.build().batches() { + // println!("new batch"); + // match batch { + // PrimitiveBatch::Quads(quads) => { + // for quad in quads { + // if quad.background == crate::black() { + // println!(" black quad"); + // } else if quad.background == crate::green() { + // println!(" green quad"); + // } else { + // todo!(" ((( bad quad"); + // } + // } + // } + // PrimitiveBatch::MonochromeSprites { sprites, .. } => { + // for sprite in sprites { + // if sprite.color == crate::white() { + // println!(" white sprite"); + // } else if sprite.color == crate::blue() { + // println!(" blue sprite"); + // } else { + // todo!(" ((( bad sprite") + // } + // } + // } + // _ => todo!(), + // } + // } + // } -// fn shadow() -> Shadow { -// Shadow { -// order: Default::default(), -// bounds: Bounds { -// origin: point(ScaledPixels(0.), ScaledPixels(0.)), -// size: size(ScaledPixels(100.), ScaledPixels(100.)), -// }, -// corner_radii: Default::default(), -// content_mask: Default::default(), -// color: Default::default(), -// blur_radius: Default::default(), -// } -// } -// } + fn quad(origin: Point, size: Size, background: Hsla) -> Quad { + Quad { + order: 0, + bounds: Bounds { origin, size }.scale(1.), + background, + content_mask: ContentMask { + bounds: Bounds { origin, size }, + } + .scale(1.), + border_color: Default::default(), + corner_radii: Default::default(), + border_widths: Default::default(), + } + } + + fn sprite(origin: Point, size: Size, color: Hsla) -> MonochromeSprite { + MonochromeSprite { + order: 0, + bounds: Bounds { origin, size }.scale(1.), + content_mask: ContentMask { + bounds: Bounds { origin, size }, + } + .scale(1.), + color, + tile: AtlasTile { + texture_id: AtlasTextureId { + index: 0, + kind: crate::AtlasTextureKind::Monochrome, + }, + tile_id: crate::TileId(0), + bounds: Default::default(), + }, + } + } +} diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index f7ebddd0fe..5d06cfe1a5 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -39,24 +39,36 @@ use std::{ Arc, }, }; -use util::ResultExt; +use util::{post_inc, ResultExt}; const ACTIVE_DRAG_Z_INDEX: u8 = 1; /// A global stacking order, which is created by stacking successive z-index values. /// Each z-index will always be interpreted in the context of its parent z-index. -#[derive(Deref, DerefMut, Clone, Debug, Ord, PartialOrd, PartialEq, Eq)] +#[derive(Deref, DerefMut, Clone, Ord, PartialOrd, PartialEq, Eq, Default)] pub struct StackingOrder { #[deref] #[deref_mut] - z_indices: SmallVec<[u8; 64]>, + context_stack: SmallVec<[StackingContext; 64]>, } -impl Default for StackingOrder { - fn default() -> Self { - StackingOrder { - z_indices: SmallVec::new(), +#[derive(Clone, Ord, PartialOrd, PartialEq, Eq)] +pub struct StackingContext { + // TODO kb use u16 and/or try to push the `id` above into the stacking order + z_index: u8, + id: u16, +} + +impl std::fmt::Debug for StackingOrder { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut stacks = self.context_stack.iter().peekable(); + while let Some(z_index) = stacks.next() { + write!(f, "{}.{}", z_index.z_index, z_index.id)?; + if stacks.peek().is_some() { + write!(f, "->")?; + } } + Ok(()) } } @@ -284,6 +296,7 @@ pub(crate) struct Frame { pub(crate) scene_builder: SceneBuilder, pub(crate) depth_map: Vec<(StackingOrder, Bounds)>, pub(crate) z_index_stack: StackingOrder, + pub(crate) stacking_context_id_stack: Vec, content_mask_stack: Vec>, element_offset_stack: Vec>, } @@ -297,6 +310,7 @@ impl Frame { dispatch_tree, scene_builder: SceneBuilder::default(), z_index_stack: StackingOrder::default(), + stacking_context_id_stack: vec![0], depth_map: Default::default(), content_mask_stack: Vec::new(), element_offset_stack: Vec::new(), @@ -308,6 +322,8 @@ impl Frame { self.mouse_listeners.values_mut().for_each(Vec::clear); self.dispatch_tree.clear(); self.depth_map.clear(); + self.stacking_context_id_stack.clear(); + self.stacking_context_id_stack.push(0); } fn focus_path(&self) -> SmallVec<[FocusId; 8]> { @@ -931,8 +947,20 @@ impl<'a> WindowContext<'a> { /// Called during painting to invoke the given closure in a new stacking context. The given /// z-index is interpreted relative to the previous call to `stack`. pub fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { - self.window.next_frame.z_index_stack.push(z_index); + let id = post_inc( + self.window + .next_frame + .stacking_context_id_stack + .last_mut() + .unwrap(), + ); + self.window.next_frame.stacking_context_id_stack.push(0); + self.window + .next_frame + .z_index_stack + .push(StackingContext { z_index, id }); let result = f(self); + self.window.next_frame.stacking_context_id_stack.pop(); self.window.next_frame.z_index_stack.pop(); result } @@ -2046,6 +2074,30 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { result } + /// Called during painting to invoke the given closure in a new stacking context. The given + /// z-index is interpreted relative to the previous call to `stack`. + fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { + let id = post_inc( + self.window_mut() + .next_frame + .stacking_context_id_stack + .last_mut() + .unwrap(), + ); + self.window_mut() + .next_frame + .stacking_context_id_stack + .push(0); + self.window_mut() + .next_frame + .z_index_stack + .push(StackingContext { z_index, id }); + let result = f(self); + self.window_mut().next_frame.stacking_context_id_stack.pop(); + self.window_mut().next_frame.z_index_stack.pop(); + result + } + /// Update the global element offset relative to the current offset. This is used to implement /// scrolling. fn with_element_offset( @@ -2269,13 +2321,6 @@ impl<'a, V: 'static> ViewContext<'a, V> { &mut self.window_cx } - pub fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { - self.window.next_frame.z_index_stack.push(z_index); - let result = f(self); - self.window.next_frame.z_index_stack.pop(); - result - } - pub fn on_next_frame(&mut self, f: impl FnOnce(&mut V, &mut ViewContext) + 'static) where V: 'static, diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index bdb5c2b854..a6f9935053 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -129,6 +129,7 @@ impl RenderOnce for ListItem { fn render(self, cx: &mut WindowContext) -> Self::Rendered { h_stack() .id(self.id) + .bg(gpui::green()) .w_full() .relative() // When an item is inset draw the indent spacing outside of the item @@ -171,7 +172,8 @@ impl RenderOnce for ListItem { }) }) .when_some(self.on_click, |this, on_click| { - this.cursor_pointer().on_click(on_click) + this.cursor_copy() + .on_click(move |event, cx| on_click(dbg!(event), cx)) }) .when_some(self.on_secondary_mouse_down, |this, on_mouse_down| { this.on_mouse_down(MouseButton::Right, move |event, cx| { diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index cd25582f36..f83879a64e 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -105,6 +105,8 @@ impl Render for Toolbar { v_stack() .p_1() .gap_2() + // todo!() use a proper constant here (ask Marshall & Nate) + .z_index(80) .border_b() .border_color(cx.theme().colors().border_variant) .bg(cx.theme().colors().toolbar_background) From 8f1c5375efa1ee8829f18755391da59d3b1cbaf8 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 19 Dec 2023 12:30:57 +0200 Subject: [PATCH 164/644] Fix more z-index and rendering issues Co-Authored-By: Antonio Scandurra --- crates/collab_ui2/src/collab_titlebar_item.rs | 1 + crates/ui2/src/components/context_menu.rs | 36 ++++++++++++++----- crates/ui2/src/components/list/list_item.rs | 5 ++- crates/ui2/src/components/tab_bar.rs | 1 + 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 023b77ab8f..914e5c7bb6 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -68,6 +68,7 @@ impl Render for CollabTitlebarItem { h_stack() .id("titlebar") + .z_index(160) .justify_between() .w_full() .h(rems(1.75)) diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 8fce15d1c6..84c66f3534 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -3,8 +3,8 @@ use crate::{ ListSeparator, ListSubHeader, }; use gpui::{ - px, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, - IntoElement, Render, Subscription, View, VisualContext, + px, Action, AnyElement, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, + FocusableView, IntoElement, Render, Subscription, View, VisualContext, }; use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev}; use std::{rc::Rc, time::Duration}; @@ -18,6 +18,9 @@ pub enum ContextMenuItem { handler: Rc, action: Option>, }, + CustomEntry { + entry_render: Box AnyElement>, + }, } pub struct ContextMenu { @@ -83,6 +86,16 @@ impl ContextMenu { self } + pub fn custom_entry( + mut self, + entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static, + ) -> Self { + self.items.push(ContextMenuItem::CustomEntry { + entry_render: Box::new(entry_render), + }); + self + } + pub fn action(mut self, label: impl Into, action: Box) -> Self { self.items.push(ContextMenuItem::Entry { label: label.into(), @@ -230,9 +243,9 @@ impl Render for ContextMenu { el }) .flex_none() - .child( - List::new().children(self.items.iter().enumerate().map( - |(ix, item)| match item { + .child(List::new().children(self.items.iter_mut().enumerate().map( + |(ix, item)| { + match item { ContextMenuItem::Separator => ListSeparator.into_any_element(), ContextMenuItem::Header(header) => { ListSubHeader::new(header.clone()).into_any_element() @@ -255,7 +268,7 @@ impl Render for ContextMenu { Label::new(label.clone()).into_any_element() }; - ListItem::new(label.clone()) + ListItem::new(ix) .inset(true) .selected(Some(ix) == self.selected_index) .on_click(move |_, cx| handler(cx)) @@ -271,9 +284,14 @@ impl Render for ContextMenu { ) .into_any_element() } - }, - )), - ), + ContextMenuItem::CustomEntry { entry_render } => ListItem::new(ix) + .inset(true) + .selected(Some(ix) == self.selected_index) + .child(entry_render(cx)) + .into_any_element(), + } + }, + ))), ) } } diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index a6f9935053..e8689030c3 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -129,7 +129,6 @@ impl RenderOnce for ListItem { fn render(self, cx: &mut WindowContext) -> Self::Rendered { h_stack() .id(self.id) - .bg(gpui::green()) .w_full() .relative() // When an item is inset draw the indent spacing outside of the item @@ -172,8 +171,8 @@ impl RenderOnce for ListItem { }) }) .when_some(self.on_click, |this, on_click| { - this.cursor_copy() - .on_click(move |event, cx| on_click(dbg!(event), cx)) + this.cursor_pointer() + .on_click(move |event, cx| on_click(event, cx)) }) .when_some(self.on_secondary_mouse_down, |this, on_mouse_down| { this.on_mouse_down(MouseButton::Right, move |event, cx| { diff --git a/crates/ui2/src/components/tab_bar.rs b/crates/ui2/src/components/tab_bar.rs index 7cff2f51bd..b10ffd1c63 100644 --- a/crates/ui2/src/components/tab_bar.rs +++ b/crates/ui2/src/components/tab_bar.rs @@ -96,6 +96,7 @@ impl RenderOnce for TabBar { div() .id(self.id) + .z_index(120) .group("tab_bar") .flex() .flex_none() From f6d31917c15d1328991ccae317964190b309f1ff Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 19 Dec 2023 17:05:39 +0200 Subject: [PATCH 165/644] Optimize stack id in-memory layout --- crates/gpui2/src/scene.rs | 212 ++++++++++++++++++------------------- crates/gpui2/src/window.rs | 66 ++++-------- 2 files changed, 129 insertions(+), 149 deletions(-) diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index 15a4a37d5b..517632ed79 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -857,116 +857,116 @@ impl Bounds { } } -#[cfg(test)] -mod tests { - use super::*; - use crate::{point, px, size, Size}; - use smallvec::smallvec; +// todo!() +// #[cfg(test)] +// mod tests { +// use super::*; +// use crate::{point, px, size, Size}; +// use smallvec::smallvec; - // todo!() - // #[test] - // fn test_scene() { - // let mut scene = SceneBuilder::default(); - // assert_eq!(scene.layers_by_order.len(), 0); +// #[test] +// fn test_scene() { +// let mut scene = SceneBuilder::default(); +// assert_eq!(scene.layers_by_order.len(), 0); - // // div with z_index(1) - // // glyph with z_index(1) - // // div with z_index(1) - // // glyph with z_index(1) +// // div with z_index(1) +// // glyph with z_index(1) +// // div with z_index(1) +// // glyph with z_index(1) - // scene.insert( - // &smallvec![1].into(), - // quad( - // point(px(0.), px(0.)), - // size(px(100.), px(100.)), - // crate::black(), - // ), - // ); - // scene.insert( - // &smallvec![1, 1].into(), - // sprite( - // point(px(0.), px(0.)), - // size(px(10.), px(10.)), - // crate::white(), - // ), - // ); - // scene.insert( - // &smallvec![1].into(), - // quad( - // point(px(10.), px(10.)), - // size(px(20.), px(20.)), - // crate::green(), - // ), - // ); - // scene.insert( - // &smallvec![1, 1].into(), - // sprite(point(px(15.), px(15.)), size(px(5.), px(5.)), crate::blue()), - // ); +// scene.insert( +// &smallvec![1].into(), +// quad( +// point(px(0.), px(0.)), +// size(px(100.), px(100.)), +// crate::black(), +// ), +// ); +// scene.insert( +// &smallvec![1, 1].into(), +// sprite( +// point(px(0.), px(0.)), +// size(px(10.), px(10.)), +// crate::white(), +// ), +// ); +// scene.insert( +// &smallvec![1].into(), +// quad( +// point(px(10.), px(10.)), +// size(px(20.), px(20.)), +// crate::green(), +// ), +// ); +// scene.insert( +// &smallvec![1, 1].into(), +// sprite(point(px(15.), px(15.)), size(px(5.), px(5.)), crate::blue()), +// ); - // assert!(!scene.layers_by_order.is_empty()); +// assert!(!scene.layers_by_order.is_empty()); - // for batch in scene.build().batches() { - // println!("new batch"); - // match batch { - // PrimitiveBatch::Quads(quads) => { - // for quad in quads { - // if quad.background == crate::black() { - // println!(" black quad"); - // } else if quad.background == crate::green() { - // println!(" green quad"); - // } else { - // todo!(" ((( bad quad"); - // } - // } - // } - // PrimitiveBatch::MonochromeSprites { sprites, .. } => { - // for sprite in sprites { - // if sprite.color == crate::white() { - // println!(" white sprite"); - // } else if sprite.color == crate::blue() { - // println!(" blue sprite"); - // } else { - // todo!(" ((( bad sprite") - // } - // } - // } - // _ => todo!(), - // } - // } - // } +// for batch in scene.build().batches() { +// println!("new batch"); +// match batch { +// PrimitiveBatch::Quads(quads) => { +// for quad in quads { +// if quad.background == crate::black() { +// println!(" black quad"); +// } else if quad.background == crate::green() { +// println!(" green quad"); +// } else { +// todo!(" ((( bad quad"); +// } +// } +// } +// PrimitiveBatch::MonochromeSprites { sprites, .. } => { +// for sprite in sprites { +// if sprite.color == crate::white() { +// println!(" white sprite"); +// } else if sprite.color == crate::blue() { +// println!(" blue sprite"); +// } else { +// todo!(" ((( bad sprite") +// } +// } +// } +// _ => todo!(), +// } +// } +// } - fn quad(origin: Point, size: Size, background: Hsla) -> Quad { - Quad { - order: 0, - bounds: Bounds { origin, size }.scale(1.), - background, - content_mask: ContentMask { - bounds: Bounds { origin, size }, - } - .scale(1.), - border_color: Default::default(), - corner_radii: Default::default(), - border_widths: Default::default(), - } - } +// fn quad(origin: Point, size: Size, background: Hsla) -> Quad { +// Quad { +// order: 0, +// bounds: Bounds { origin, size }.scale(1.), +// background, +// content_mask: ContentMask { +// bounds: Bounds { origin, size }, +// } +// .scale(1.), +// border_color: Default::default(), +// corner_radii: Default::default(), +// border_widths: Default::default(), +// } +// } - fn sprite(origin: Point, size: Size, color: Hsla) -> MonochromeSprite { - MonochromeSprite { - order: 0, - bounds: Bounds { origin, size }.scale(1.), - content_mask: ContentMask { - bounds: Bounds { origin, size }, - } - .scale(1.), - color, - tile: AtlasTile { - texture_id: AtlasTextureId { - index: 0, - kind: crate::AtlasTextureKind::Monochrome, - }, - tile_id: crate::TileId(0), - bounds: Default::default(), - }, - } - } -} +// fn sprite(origin: Point, size: Size, color: Hsla) -> MonochromeSprite { +// MonochromeSprite { +// order: 0, +// bounds: Bounds { origin, size }.scale(1.), +// content_mask: ContentMask { +// bounds: Bounds { origin, size }, +// } +// .scale(1.), +// color, +// tile: AtlasTile { +// texture_id: AtlasTextureId { +// index: 0, +// kind: crate::AtlasTextureKind::Monochrome, +// }, +// tile_id: crate::TileId(0), +// bounds: Default::default(), +// }, +// } +// } +// } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 5d06cfe1a5..ddda9f0302 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -39,7 +39,7 @@ use std::{ Arc, }, }; -use util::{post_inc, ResultExt}; +use util::ResultExt; const ACTIVE_DRAG_Z_INDEX: u8 = 1; @@ -49,25 +49,21 @@ const ACTIVE_DRAG_Z_INDEX: u8 = 1; pub struct StackingOrder { #[deref] #[deref_mut] - context_stack: SmallVec<[StackingContext; 64]>, -} - -#[derive(Clone, Ord, PartialOrd, PartialEq, Eq)] -pub struct StackingContext { - // TODO kb use u16 and/or try to push the `id` above into the stacking order - z_index: u8, - id: u16, + context_stack: SmallVec<[u8; 64]>, + id: u32, } impl std::fmt::Debug for StackingOrder { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut stacks = self.context_stack.iter().peekable(); + write!(f, "[({}): ", self.id)?; while let Some(z_index) = stacks.next() { - write!(f, "{}.{}", z_index.z_index, z_index.id)?; + write!(f, "{z_index}")?; if stacks.peek().is_some() { write!(f, "->")?; } } + write!(f, "]")?; Ok(()) } } @@ -296,7 +292,7 @@ pub(crate) struct Frame { pub(crate) scene_builder: SceneBuilder, pub(crate) depth_map: Vec<(StackingOrder, Bounds)>, pub(crate) z_index_stack: StackingOrder, - pub(crate) stacking_context_id_stack: Vec, + pub(crate) next_stacking_order_id: u32, content_mask_stack: Vec>, element_offset_stack: Vec>, } @@ -310,7 +306,7 @@ impl Frame { dispatch_tree, scene_builder: SceneBuilder::default(), z_index_stack: StackingOrder::default(), - stacking_context_id_stack: vec![0], + next_stacking_order_id: 0, depth_map: Default::default(), content_mask_stack: Vec::new(), element_offset_stack: Vec::new(), @@ -322,8 +318,7 @@ impl Frame { self.mouse_listeners.values_mut().for_each(Vec::clear); self.dispatch_tree.clear(); self.depth_map.clear(); - self.stacking_context_id_stack.clear(); - self.stacking_context_id_stack.push(0); + self.next_stacking_order_id = 0; } fn focus_path(&self) -> SmallVec<[FocusId; 8]> { @@ -947,20 +942,14 @@ impl<'a> WindowContext<'a> { /// Called during painting to invoke the given closure in a new stacking context. The given /// z-index is interpreted relative to the previous call to `stack`. pub fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { - let id = post_inc( - self.window - .next_frame - .stacking_context_id_stack - .last_mut() - .unwrap(), - ); - self.window.next_frame.stacking_context_id_stack.push(0); - self.window - .next_frame - .z_index_stack - .push(StackingContext { z_index, id }); + let new_stacking_order_id = self.window.next_frame.next_stacking_order_id; + let new_next_stacking_order_id = new_stacking_order_id + 1; + + self.window.next_frame.next_stacking_order_id = 0; + self.window.next_frame.z_index_stack.id = new_stacking_order_id; + self.window.next_frame.z_index_stack.push(z_index); let result = f(self); - self.window.next_frame.stacking_context_id_stack.pop(); + self.window.next_frame.next_stacking_order_id = new_next_stacking_order_id; self.window.next_frame.z_index_stack.pop(); result } @@ -2077,23 +2066,14 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { /// Called during painting to invoke the given closure in a new stacking context. The given /// z-index is interpreted relative to the previous call to `stack`. fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { - let id = post_inc( - self.window_mut() - .next_frame - .stacking_context_id_stack - .last_mut() - .unwrap(), - ); - self.window_mut() - .next_frame - .stacking_context_id_stack - .push(0); - self.window_mut() - .next_frame - .z_index_stack - .push(StackingContext { z_index, id }); + let new_stacking_order_id = self.window_mut().next_frame.next_stacking_order_id; + let new_next_stacking_order_id = new_stacking_order_id + 1; + + self.window_mut().next_frame.next_stacking_order_id = 0; + self.window_mut().next_frame.z_index_stack.id = new_stacking_order_id; + self.window_mut().next_frame.z_index_stack.push(z_index); let result = f(self); - self.window_mut().next_frame.stacking_context_id_stack.pop(); + self.window_mut().next_frame.next_stacking_order_id = new_next_stacking_order_id; self.window_mut().next_frame.z_index_stack.pop(); result } From 097640e7c5b81e3bad28b98fa81e99ae6c364439 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 16:32:57 -0500 Subject: [PATCH 166/644] Fix typo in `ButtonCommon` doc comment (#3722) This PR fixes a small typo in the doc comments for `ButtonCommon`. Was waiting to roll this up into another PR, but it never ended up happening. Release Notes: - N/A --- crates/ui2/src/components/button/button_like.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ui2/src/components/button/button_like.rs b/crates/ui2/src/components/button/button_like.rs index bd4e9cd523..19fa2b48a4 100644 --- a/crates/ui2/src/components/button/button_like.rs +++ b/crates/ui2/src/components/button/button_like.rs @@ -10,7 +10,7 @@ pub trait ButtonCommon: Clickable + Disableable { /// The visual style of the button. /// - /// Mosty commonly will be [`ButtonStyle::Subtle`], or [`ButtonStyle::Filled`] + /// Most commonly will be [`ButtonStyle::Subtle`], or [`ButtonStyle::Filled`] /// for an emphasized button. fn style(self, style: ButtonStyle) -> Self; From cf12d62fc5283ba0c0c2f8c482ef9a2cc20e704a Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 19 Dec 2023 23:36:32 +0200 Subject: [PATCH 167/644] Tidy up z-index handling Co-Authored-By: Antonio Scandurra --- crates/collab_ui2/src/collab_titlebar_item.rs | 2 +- crates/gpui2/src/elements/div.rs | 17 +-- crates/gpui2/src/elements/img.rs | 2 +- crates/gpui2/src/scene.rs | 114 ------------------ crates/gpui2/src/window.rs | 24 +--- crates/terminal_view2/src/terminal_element.rs | 10 +- crates/ui2/src/components/context_menu.rs | 36 ++---- crates/ui2/src/components/list/list_item.rs | 3 +- crates/ui2/src/components/tab_bar.rs | 2 +- crates/workspace2/src/toolbar.rs | 3 +- 10 files changed, 31 insertions(+), 182 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 914e5c7bb6..17ee5087bb 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -68,7 +68,7 @@ impl Render for CollabTitlebarItem { h_stack() .id("titlebar") - .z_index(160) + .z_index(160) // todo!("z-index") .justify_between() .w_full() .h(rems(1.75)) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 6e9c95e19f..57fd3d6a8a 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1448,14 +1448,15 @@ impl Interactivity { } cx.with_z_index(style.z_index.unwrap_or(0), |cx| { - if style.background.as_ref().is_some_and(|fill| { - fill.color().is_some_and(|color| !color.is_transparent()) - }) { - cx.add_opaque_layer(bounds) - }f(style, scroll_offset.unwrap_or_default(), cx) - }) - }, - ); + if style.background.as_ref().is_some_and(|fill| { + fill.color().is_some_and(|color| !color.is_transparent()) + }) { + cx.add_opaque_layer(bounds) + } + f(style, scroll_offset.unwrap_or_default(), cx) + }) + }, + ); if let Some(group) = self.group.as_ref() { GroupBounds::pop(group, cx); diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index 4f81f604c8..ab7b8d9140 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use crate::{ - point, size, Bounds, DevicePixels, Element, ImageData, InteractiveElement, + point, size, BorrowWindow, Bounds, DevicePixels, Element, ImageData, InteractiveElement, InteractiveElementState, Interactivity, IntoElement, LayoutId, Pixels, SharedString, Size, StyleRefinement, Styled, WindowContext, }; diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index 517632ed79..811b2b6e30 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -856,117 +856,3 @@ impl Bounds { .expect("Polygon should not be empty") } } - -// todo!() -// #[cfg(test)] -// mod tests { -// use super::*; -// use crate::{point, px, size, Size}; -// use smallvec::smallvec; - -// #[test] -// fn test_scene() { -// let mut scene = SceneBuilder::default(); -// assert_eq!(scene.layers_by_order.len(), 0); - -// // div with z_index(1) -// // glyph with z_index(1) -// // div with z_index(1) -// // glyph with z_index(1) - -// scene.insert( -// &smallvec![1].into(), -// quad( -// point(px(0.), px(0.)), -// size(px(100.), px(100.)), -// crate::black(), -// ), -// ); -// scene.insert( -// &smallvec![1, 1].into(), -// sprite( -// point(px(0.), px(0.)), -// size(px(10.), px(10.)), -// crate::white(), -// ), -// ); -// scene.insert( -// &smallvec![1].into(), -// quad( -// point(px(10.), px(10.)), -// size(px(20.), px(20.)), -// crate::green(), -// ), -// ); -// scene.insert( -// &smallvec![1, 1].into(), -// sprite(point(px(15.), px(15.)), size(px(5.), px(5.)), crate::blue()), -// ); - -// assert!(!scene.layers_by_order.is_empty()); - -// for batch in scene.build().batches() { -// println!("new batch"); -// match batch { -// PrimitiveBatch::Quads(quads) => { -// for quad in quads { -// if quad.background == crate::black() { -// println!(" black quad"); -// } else if quad.background == crate::green() { -// println!(" green quad"); -// } else { -// todo!(" ((( bad quad"); -// } -// } -// } -// PrimitiveBatch::MonochromeSprites { sprites, .. } => { -// for sprite in sprites { -// if sprite.color == crate::white() { -// println!(" white sprite"); -// } else if sprite.color == crate::blue() { -// println!(" blue sprite"); -// } else { -// todo!(" ((( bad sprite") -// } -// } -// } -// _ => todo!(), -// } -// } -// } - -// fn quad(origin: Point, size: Size, background: Hsla) -> Quad { -// Quad { -// order: 0, -// bounds: Bounds { origin, size }.scale(1.), -// background, -// content_mask: ContentMask { -// bounds: Bounds { origin, size }, -// } -// .scale(1.), -// border_color: Default::default(), -// corner_radii: Default::default(), -// border_widths: Default::default(), -// } -// } - -// fn sprite(origin: Point, size: Size, color: Hsla) -> MonochromeSprite { -// MonochromeSprite { -// order: 0, -// bounds: Bounds { origin, size }.scale(1.), -// content_mask: ContentMask { -// bounds: Bounds { origin, size }, -// } -// .scale(1.), -// color, -// tile: AtlasTile { -// texture_id: AtlasTextureId { -// index: 0, -// kind: crate::AtlasTextureKind::Monochrome, -// }, -// tile_id: crate::TileId(0), -// bounds: Default::default(), -// }, -// } -// } -// } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index ddda9f0302..1b2669b40c 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -39,7 +39,7 @@ use std::{ Arc, }, }; -use util::ResultExt; +use util::{post_inc, ResultExt}; const ACTIVE_DRAG_Z_INDEX: u8 = 1; @@ -939,21 +939,6 @@ impl<'a> WindowContext<'a> { self.window.requested_cursor_style = Some(style) } - /// Called during painting to invoke the given closure in a new stacking context. The given - /// z-index is interpreted relative to the previous call to `stack`. - pub fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { - let new_stacking_order_id = self.window.next_frame.next_stacking_order_id; - let new_next_stacking_order_id = new_stacking_order_id + 1; - - self.window.next_frame.next_stacking_order_id = 0; - self.window.next_frame.z_index_stack.id = new_stacking_order_id; - self.window.next_frame.z_index_stack.push(z_index); - let result = f(self); - self.window.next_frame.next_stacking_order_id = new_next_stacking_order_id; - self.window.next_frame.z_index_stack.pop(); - result - } - /// Called during painting to track which z-index is on top at each pixel position pub fn add_opaque_layer(&mut self, bounds: Bounds) { let stacking_order = self.window.next_frame.z_index_stack.clone(); @@ -2066,14 +2051,11 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { /// Called during painting to invoke the given closure in a new stacking context. The given /// z-index is interpreted relative to the previous call to `stack`. fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { - let new_stacking_order_id = self.window_mut().next_frame.next_stacking_order_id; - let new_next_stacking_order_id = new_stacking_order_id + 1; - - self.window_mut().next_frame.next_stacking_order_id = 0; + let new_stacking_order_id = + post_inc(&mut self.window_mut().next_frame.next_stacking_order_id); self.window_mut().next_frame.z_index_stack.id = new_stacking_order_id; self.window_mut().next_frame.z_index_stack.push(z_index); let result = f(self); - self.window_mut().next_frame.next_stacking_order_id = new_next_stacking_order_id; self.window_mut().next_frame.z_index_stack.pop(); result } diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index e9335a4220..07910896f3 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -1,11 +1,11 @@ use editor::{Cursor, HighlightedRange, HighlightedRangeLine}; use gpui::{ black, div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace, - Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, FontStyle, - FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, Interactivity, - IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, Pixels, - PlatformInputHandler, Point, Rgba, ShapedLine, Size, StatefulInteractiveElement, Styled, - TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, + BorrowWindow, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, + FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, + Interactivity, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, + Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, Size, StatefulInteractiveElement, + Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, }; use itertools::Itertools; use language::CursorShape; diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 84c66f3534..8fce15d1c6 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -3,8 +3,8 @@ use crate::{ ListSeparator, ListSubHeader, }; use gpui::{ - px, Action, AnyElement, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, - FocusableView, IntoElement, Render, Subscription, View, VisualContext, + px, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, + IntoElement, Render, Subscription, View, VisualContext, }; use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev}; use std::{rc::Rc, time::Duration}; @@ -18,9 +18,6 @@ pub enum ContextMenuItem { handler: Rc, action: Option>, }, - CustomEntry { - entry_render: Box AnyElement>, - }, } pub struct ContextMenu { @@ -86,16 +83,6 @@ impl ContextMenu { self } - pub fn custom_entry( - mut self, - entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static, - ) -> Self { - self.items.push(ContextMenuItem::CustomEntry { - entry_render: Box::new(entry_render), - }); - self - } - pub fn action(mut self, label: impl Into, action: Box) -> Self { self.items.push(ContextMenuItem::Entry { label: label.into(), @@ -243,9 +230,9 @@ impl Render for ContextMenu { el }) .flex_none() - .child(List::new().children(self.items.iter_mut().enumerate().map( - |(ix, item)| { - match item { + .child( + List::new().children(self.items.iter().enumerate().map( + |(ix, item)| match item { ContextMenuItem::Separator => ListSeparator.into_any_element(), ContextMenuItem::Header(header) => { ListSubHeader::new(header.clone()).into_any_element() @@ -268,7 +255,7 @@ impl Render for ContextMenu { Label::new(label.clone()).into_any_element() }; - ListItem::new(ix) + ListItem::new(label.clone()) .inset(true) .selected(Some(ix) == self.selected_index) .on_click(move |_, cx| handler(cx)) @@ -284,14 +271,9 @@ impl Render for ContextMenu { ) .into_any_element() } - ContextMenuItem::CustomEntry { entry_render } => ListItem::new(ix) - .inset(true) - .selected(Some(ix) == self.selected_index) - .child(entry_render(cx)) - .into_any_element(), - } - }, - ))), + }, + )), + ), ) } } diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index e8689030c3..bdb5c2b854 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -171,8 +171,7 @@ impl RenderOnce for ListItem { }) }) .when_some(self.on_click, |this, on_click| { - this.cursor_pointer() - .on_click(move |event, cx| on_click(event, cx)) + this.cursor_pointer().on_click(on_click) }) .when_some(self.on_secondary_mouse_down, |this, on_mouse_down| { this.on_mouse_down(MouseButton::Right, move |event, cx| { diff --git a/crates/ui2/src/components/tab_bar.rs b/crates/ui2/src/components/tab_bar.rs index b10ffd1c63..d2e6e9518b 100644 --- a/crates/ui2/src/components/tab_bar.rs +++ b/crates/ui2/src/components/tab_bar.rs @@ -96,7 +96,7 @@ impl RenderOnce for TabBar { div() .id(self.id) - .z_index(120) + .z_index(120) // todo!("z-index") .group("tab_bar") .flex() .flex_none() diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index f83879a64e..7436232b04 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -105,8 +105,7 @@ impl Render for Toolbar { v_stack() .p_1() .gap_2() - // todo!() use a proper constant here (ask Marshall & Nate) - .z_index(80) + .z_index(80) // todo!("z-index") .border_b() .border_color(cx.theme().colors().border_variant) .bg(cx.theme().colors().toolbar_background) From 1b09862384e84169c84bd7047bfbd21df7392c50 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 14:11:59 -0800 Subject: [PATCH 168/644] Restrcit context for some editor bindings that don't apply to single-line editors --- assets/keymaps/default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index b8d3711132..5d70000639 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -502,7 +502,7 @@ } }, { - "context": "Editor", + "context": "Editor && mode == full", "bindings": { "alt-enter": "editor::OpenExcerpts", "cmd-f8": "editor::GoToHunk", From 901795bcb98b9d85cfab42c95368e792122e7ca0 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 14:12:29 -0800 Subject: [PATCH 169/644] Don't reset the collab panel when it loses focus --- crates/collab_ui2/src/collab_panel.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index b7dd24b9ab..28d1b12bea 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -199,12 +199,6 @@ impl CollabPanel { .iter() .position(|entry| !matches!(entry, ListEntry::Header(_))); } - } else if let editor::EditorEvent::Blurred = event { - let query = this.filter_editor.read(cx).text(cx); - if query.is_empty() { - this.selection.take(); - this.update_entries(true, cx); - } } }) .detach(); From afd3bf77467849d3f0aad3639ce7ef9f720e3be0 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 14:12:45 -0800 Subject: [PATCH 170/644] Add missing selected state and keyboard action for some collab panel items --- crates/collab_ui2/src/collab_panel.rs | 107 +++++++++++------- .../src/collab_panel/contact_finder.rs | 6 +- 2 files changed, 69 insertions(+), 44 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 28d1b12bea..35e2f8d7ed 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -804,8 +804,9 @@ impl CollabPanel { user: &Arc, peer_id: Option, is_pending: bool, + is_selected: bool, cx: &mut ViewContext, - ) -> impl IntoElement { + ) -> ListItem { let is_current_user = self.user_store.read(cx).current_user().map(|user| user.id) == Some(user.id); let tooltip = format!("Follow {}", user.github_login); @@ -813,6 +814,7 @@ impl CollabPanel { ListItem::new(SharedString::from(user.github_login.clone())) .start_slot(Avatar::new(user.avatar_uri.clone())) .child(Label::new(user.github_login.clone())) + .selected(is_selected) .end_slot(if is_pending { Label::new("Calling").color(Color::Muted).into_any_element() } else if is_current_user { @@ -839,10 +841,8 @@ impl CollabPanel { project_id: u64, worktree_root_names: &[String], host_user_id: u64, - // is_current: bool, is_last: bool, is_selected: bool, - // theme: &theme::Theme, cx: &mut ViewContext, ) -> impl IntoElement { let project_name: SharedString = if worktree_root_names.is_empty() { @@ -917,9 +917,11 @@ impl CollabPanel { fn render_channel_notes( &self, channel_id: ChannelId, + is_selected: bool, cx: &mut ViewContext, ) -> impl IntoElement { ListItem::new("channel-notes") + .selected(is_selected) .on_click(cx.listener(move |this, _, cx| { this.open_channel_notes(channel_id, cx); })) @@ -936,9 +938,11 @@ impl CollabPanel { fn render_channel_chat( &self, channel_id: ChannelId, + is_selected: bool, cx: &mut ViewContext, ) -> impl IntoElement { ListItem::new("channel-chat") + .selected(is_selected) .on_click(cx.listener(move |this, _, cx| { this.join_channel_chat(channel_id, cx); })) @@ -1136,32 +1140,32 @@ impl CollabPanel { self.call(contact.user.id, cx); } } - // ListEntry::ParticipantProject { - // project_id, - // host_user_id, - // .. - // } => { - // if let Some(workspace) = self.workspace.upgrade(cx) { - // let app_state = workspace.read(cx).app_state().clone(); - // workspace::join_remote_project( - // *project_id, - // *host_user_id, - // app_state, - // cx, - // ) - // .detach_and_log_err(cx); - // } - // } - // ListEntry::ParticipantScreen { peer_id, .. } => { - // let Some(peer_id) = peer_id else { - // return; - // }; - // if let Some(workspace) = self.workspace.upgrade(cx) { - // workspace.update(cx, |workspace, cx| { - // workspace.open_shared_screen(*peer_id, cx) - // }); - // } - // } + ListEntry::ParticipantProject { + project_id, + host_user_id, + .. + } => { + if let Some(workspace) = self.workspace.upgrade() { + let app_state = workspace.read(cx).app_state().clone(); + workspace::join_remote_project( + *project_id, + *host_user_id, + app_state, + cx, + ) + .detach_and_log_err(cx); + } + } + ListEntry::ParticipantScreen { peer_id, .. } => { + let Some(peer_id) = peer_id else { + return; + }; + if let Some(workspace) = self.workspace.upgrade() { + workspace.update(cx, |workspace, cx| { + workspace.open_shared_screen(*peer_id, cx) + }); + } + } ListEntry::Channel { channel, .. } => { let is_active = maybe!({ let call_channel = ActiveCall::global(cx) @@ -1180,7 +1184,30 @@ impl CollabPanel { } } ListEntry::ContactPlaceholder => self.toggle_contact_finder(cx), - _ => {} + ListEntry::CallParticipant { user, peer_id, .. } => { + if Some(user) == self.user_store.read(cx).current_user().as_ref() { + Self::leave_call(cx); + } else if let Some(peer_id) = peer_id { + self.workspace + .update(cx, |workspace, cx| workspace.follow(*peer_id, cx)) + .ok(); + } + } + ListEntry::IncomingRequest(user) => { + self.respond_to_contact_request(user.id, true, cx) + } + ListEntry::ChannelInvite(channel) => { + self.respond_to_channel_invite(channel.id, true, cx) + } + ListEntry::ChannelNotes { channel_id } => { + self.open_channel_notes(*channel_id, cx) + } + ListEntry::ChannelChat { channel_id } => { + self.join_channel_chat(*channel_id, cx) + } + + ListEntry::OutgoingRequest(_) => {} + ListEntry::ChannelEditor { .. } => {} } } } @@ -1673,7 +1700,7 @@ impl CollabPanel { peer_id, is_pending, } => self - .render_call_participant(user, *peer_id, *is_pending, cx) + .render_call_participant(user, *peer_id, *is_pending, is_selected, cx) .into_any_element(), ListEntry::ParticipantProject { project_id, @@ -1694,11 +1721,11 @@ impl CollabPanel { .render_participant_screen(*peer_id, *is_last, is_selected, cx) .into_any_element(), ListEntry::ChannelNotes { channel_id } => self - .render_channel_notes(*channel_id, cx) + .render_channel_notes(*channel_id, is_selected, cx) + .into_any_element(), + ListEntry::ChannelChat { channel_id } => self + .render_channel_chat(*channel_id, is_selected, cx) .into_any_element(), - ListEntry::ChannelChat { channel_id } => { - self.render_channel_chat(*channel_id, cx).into_any_element() - } } } @@ -1953,7 +1980,7 @@ impl CollabPanel { channel: &Arc, is_selected: bool, cx: &mut ViewContext, - ) -> impl IntoElement { + ) -> ListItem { let channel_id = channel.id; let response_is_pending = self .channel_store @@ -2000,7 +2027,7 @@ impl CollabPanel { &self, is_selected: bool, cx: &mut ViewContext, - ) -> impl IntoElement { + ) -> ListItem { ListItem::new("contact-placeholder") .child(IconElement::new(Icon::Plus)) .child(Label::new("Add a Contact")) @@ -2087,9 +2114,8 @@ impl CollabPanel { })) .child( ListItem::new(channel_id as usize) - // Offset the indent depth by one to give us room to show the disclosure. + // Add one level of depth for the disclosure arrow. .indent_level(depth + 1) - .indent_step_size(cx.rem_size() * 14.0 / 16.0) // @todo()! @nate this is to step over the disclosure toggle .selected(is_selected || is_active) .toggle(disclosed) .on_toggle( @@ -2158,7 +2184,8 @@ impl CollabPanel { fn render_channel_editor(&self, depth: usize, _cx: &mut ViewContext) -> impl IntoElement { let item = ListItem::new("channel-editor") .inset(false) - .indent_level(depth) + // Add one level of depth for the disclosure arrow. + .indent_level(depth + 1) .start_slot( IconElement::new(Icon::Hash) .size(IconSize::Small) diff --git a/crates/collab_ui2/src/collab_panel/contact_finder.rs b/crates/collab_ui2/src/collab_panel/contact_finder.rs index 208727efd2..31d836279b 100644 --- a/crates/collab_ui2/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui2/src/collab_panel/contact_finder.rs @@ -1,9 +1,7 @@ -#![allow(unused)] use client::{ContactRequestStatus, User, UserStore}; use gpui::{ - div, img, svg, AnyElement, AppContext, DismissEvent, Div, Entity, EventEmitter, FocusHandle, - FocusableView, Img, IntoElement, Model, ParentElement as _, Render, Styled, Task, View, - ViewContext, VisualContext, WeakView, + AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Model, + ParentElement as _, Render, Styled, Task, View, ViewContext, VisualContext, WeakView, }; use picker::{Picker, PickerDelegate}; use std::sync::Arc; From 547ad77243709f3c9e10c4dfb23da781b9565dab Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 17:45:42 -0500 Subject: [PATCH 171/644] Style tab drop targets for project entries (#3725) This PR styles the drop targets when dragging a project entry onto a tab or the tab bar. I also adjusted the existing tab drop targets to use the `drop_target_background` from the theme. Release Notes: - N/A --- crates/workspace2/src/pane.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index e1bb006c11..6b498124e3 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1511,8 +1511,8 @@ impl Pane { }, |tab, cx| cx.build_view(|_| tab.clone()), ) - .drag_over::(|tab| tab.bg(cx.theme().colors().tab_active_background)) - .drag_over::(|tab| tab.bg(gpui::red())) + .drag_over::(|tab| tab.bg(cx.theme().colors().drop_target_background)) + .drag_over::(|tab| tab.bg(cx.theme().colors().drop_target_background)) .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { this.drag_split_direction = None; this.handle_tab_drop(dragged_tab, ix, cx) @@ -1664,9 +1664,11 @@ impl Pane { .h_full() .flex_grow() .drag_over::(|bar| { - bar.bg(cx.theme().colors().tab_active_background) + bar.bg(cx.theme().colors().drop_target_background) + }) + .drag_over::(|bar| { + bar.bg(cx.theme().colors().drop_target_background) }) - .drag_over::(|bar| bar.bg(gpui::red())) .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { this.drag_split_direction = None; this.handle_tab_drop(dragged_tab, this.items.len(), cx) From 53b76e3e4d0946128b271875358efd974e0716de Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 18:06:21 -0500 Subject: [PATCH 172/644] Style pane drop targets (#3726) This PR styles the pane drop targets using the `drop_target_background` color from the theme. We do have to adjust the alpha channel of the color so that it doesn't obscure the contents of the buffer. Release Notes: - N/A --- crates/workspace2/src/pane.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 6b498124e3..4d0d465309 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1817,9 +1817,6 @@ impl Render for Pane { type Element = Focusable
; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - let mut drag_target_color = cx.theme().colors().text; - drag_target_color.a = 0.5; - v_stack() .key_context("Pane") .track_focus(&self.focus_handle) @@ -1922,7 +1919,10 @@ impl Render for Pane { div() .invisible() .absolute() - .bg(drag_target_color) + .bg(theme::color_alpha( + cx.theme().colors().drop_target_background, + 0.75, + )) .group_drag_over::("", |style| style.visible()) .group_drag_over::("", |style| style.visible()) .on_drop(cx.listener(move |this, dragged_tab, cx| { From a0224b975b7e05beb730bb775185c15e982f2cf4 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 18:24:52 -0500 Subject: [PATCH 173/644] Use `link_text_hover` for go-to-definition links --- crates/editor2/src/link_go_to_definition.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/editor2/src/link_go_to_definition.rs b/crates/editor2/src/link_go_to_definition.rs index 60c966d4c7..ef17127797 100644 --- a/crates/editor2/src/link_go_to_definition.rs +++ b/crates/editor2/src/link_go_to_definition.rs @@ -491,7 +491,7 @@ pub fn show_link_definition( thickness: px(1.), ..Default::default() }), - color: Some(gpui::red()), + color: Some(cx.theme().colors().link_text_hover), ..Default::default() }; let highlight_range = From afcf6c685230d6731334b4ec2013de88f8c481b6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Tue, 19 Dec 2023 18:29:27 -0500 Subject: [PATCH 174/644] Map `textLink.activeForeground` from VS Code to `link_text_hover` --- crates/theme2/src/themes/ayu.rs | 3 +++ crates/theme2/src/themes/gruvbox.rs | 6 ++++++ crates/theme2/src/themes/noctis.rs | 11 +++++++++++ crates/theme2/src/themes/nord.rs | 1 + crates/theme2/src/themes/rose_pine.rs | 3 +++ crates/theme2/src/themes/synthwave_84.rs | 1 + crates/theme_importer/src/theme_printer.rs | 10 ++++++++++ crates/theme_importer/src/vscode/converter.rs | 4 ++++ crates/theme_importer/src/vscode/theme.rs | 7 +++++++ 9 files changed, 46 insertions(+) diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index 79aed9e1b5..9c977234b9 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -70,6 +70,7 @@ pub fn ayu() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0x9e75c7ff).into()), terminal_ansi_cyan: Some(rgba(0x46ba94ff).into()), terminal_ansi_white: Some(rgba(0xc7c7c7ff).into()), + link_text_hover: Some(rgba(0xffaa33ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -379,6 +380,7 @@ pub fn ayu() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xdabafaff).into()), terminal_ansi_cyan: Some(rgba(0x90e1c6ff).into()), terminal_ansi_white: Some(rgba(0xc7c7c7ff).into()), + link_text_hover: Some(rgba(0xffcc66ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -688,6 +690,7 @@ pub fn ayu() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xcda1faff).into()), terminal_ansi_cyan: Some(rgba(0x90e1c6ff).into()), terminal_ansi_white: Some(rgba(0xc7c7c7ff).into()), + link_text_hover: Some(rgba(0xe6b450ff).into()), ..Default::default() }, status: StatusColorsRefinement { diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 35f5b31aa2..abce861f91 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -70,6 +70,7 @@ pub fn gruvbox() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), terminal_ansi_white: Some(rgba(0xa89984ff).into()), + link_text_hover: Some(rgba(0x458588ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -365,6 +366,7 @@ pub fn gruvbox() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), terminal_ansi_white: Some(rgba(0xa89984ff).into()), + link_text_hover: Some(rgba(0x458588ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -660,6 +662,7 @@ pub fn gruvbox() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), terminal_ansi_white: Some(rgba(0xa89984ff).into()), + link_text_hover: Some(rgba(0x458588ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -955,6 +958,7 @@ pub fn gruvbox() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), terminal_ansi_white: Some(rgba(0x7c6f64ff).into()), + link_text_hover: Some(rgba(0x458588ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -1250,6 +1254,7 @@ pub fn gruvbox() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), terminal_ansi_white: Some(rgba(0x7c6f64ff).into()), + link_text_hover: Some(rgba(0x458588ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -1545,6 +1550,7 @@ pub fn gruvbox() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), terminal_ansi_white: Some(rgba(0x7c6f64ff).into()), + link_text_hover: Some(rgba(0x458588ff).into()), ..Default::default() }, status: StatusColorsRefinement { diff --git a/crates/theme2/src/themes/noctis.rs b/crates/theme2/src/themes/noctis.rs index 273b52a34a..ca1601df99 100644 --- a/crates/theme2/src/themes/noctis.rs +++ b/crates/theme2/src/themes/noctis.rs @@ -71,6 +71,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), terminal_ansi_white: Some(rgba(0xaec3d0ff).into()), + link_text_hover: Some(rgba(0x49ace9ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -351,6 +352,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), terminal_ansi_white: Some(rgba(0xb9acb0ff).into()), + link_text_hover: Some(rgba(0xf18eb0ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -631,6 +633,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xff5792ff).into()), terminal_ansi_cyan: Some(rgba(0x00bdd6ff).into()), terminal_ansi_white: Some(rgba(0x8ca6a6ff).into()), + link_text_hover: Some(rgba(0x00c6e0ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -911,6 +914,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xff5792ff).into()), terminal_ansi_cyan: Some(rgba(0x00bdd6ff).into()), terminal_ansi_white: Some(rgba(0x8ca6a6ff).into()), + link_text_hover: Some(rgba(0x00c6e0ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -1191,6 +1195,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xff5792ff).into()), terminal_ansi_cyan: Some(rgba(0x00bdd6ff).into()), terminal_ansi_white: Some(rgba(0x8ca6a6ff).into()), + link_text_hover: Some(rgba(0x00c6e0ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -1471,6 +1476,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xc28097ff).into()), terminal_ansi_cyan: Some(rgba(0x72b7c0ff).into()), terminal_ansi_white: Some(rgba(0xc5cdd3ff).into()), + link_text_hover: Some(rgba(0x5998c0ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -1751,6 +1757,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), terminal_ansi_white: Some(rgba(0xb2cacdff).into()), + link_text_hover: Some(rgba(0x40d4e7ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -2031,6 +2038,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), terminal_ansi_white: Some(rgba(0xb2cacdff).into()), + link_text_hover: Some(rgba(0x40d4e7ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -2311,6 +2319,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), terminal_ansi_white: Some(rgba(0xb2cacdff).into()), + link_text_hover: Some(rgba(0x40d4e7ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -2591,6 +2600,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), terminal_ansi_white: Some(rgba(0xb6b3ccff).into()), + link_text_hover: Some(rgba(0x998ef1ff).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -2871,6 +2881,7 @@ pub fn noctis() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), terminal_ansi_white: Some(rgba(0xbfafcfff).into()), + link_text_hover: Some(rgba(0xbf8ef1ff).into()), ..Default::default() }, status: StatusColorsRefinement { diff --git a/crates/theme2/src/themes/nord.rs b/crates/theme2/src/themes/nord.rs index 83fafa7a87..c44076c1f8 100644 --- a/crates/theme2/src/themes/nord.rs +++ b/crates/theme2/src/themes/nord.rs @@ -70,6 +70,7 @@ pub fn nord() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xb48eadff).into()), terminal_ansi_cyan: Some(rgba(0x88c0d0ff).into()), terminal_ansi_white: Some(rgba(0xe5e9f0ff).into()), + link_text_hover: Some(rgba(0x88c0d0ff).into()), ..Default::default() }, status: StatusColorsRefinement { diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index 51e3a2451c..828838530f 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -70,6 +70,7 @@ pub fn rose_pine() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xc4a7e7ff).into()), terminal_ansi_cyan: Some(rgba(0xebbcbaff).into()), terminal_ansi_white: Some(rgba(0xe0def4ff).into()), + link_text_hover: Some(rgba(0xc4a7e7e6).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -332,6 +333,7 @@ pub fn rose_pine() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0xc4a7e7ff).into()), terminal_ansi_cyan: Some(rgba(0xea9a97ff).into()), terminal_ansi_white: Some(rgba(0xe0def4ff).into()), + link_text_hover: Some(rgba(0xc4a7e7e6).into()), ..Default::default() }, status: StatusColorsRefinement { @@ -594,6 +596,7 @@ pub fn rose_pine() -> UserThemeFamily { terminal_ansi_magenta: Some(rgba(0x907aa9ff).into()), terminal_ansi_cyan: Some(rgba(0xd7827eff).into()), terminal_ansi_white: Some(rgba(0x575279ff).into()), + link_text_hover: Some(rgba(0x907aa9e6).into()), ..Default::default() }, status: StatusColorsRefinement { diff --git a/crates/theme2/src/themes/synthwave_84.rs b/crates/theme2/src/themes/synthwave_84.rs index 4f62732d7f..d7a0ef41a0 100644 --- a/crates/theme2/src/themes/synthwave_84.rs +++ b/crates/theme2/src/themes/synthwave_84.rs @@ -54,6 +54,7 @@ pub fn synthwave_84() -> UserThemeFamily { terminal_ansi_blue: Some(rgba(0x03edf9ff).into()), terminal_ansi_magenta: Some(rgba(0xff7edbff).into()), terminal_ansi_cyan: Some(rgba(0x03edf9ff).into()), + link_text_hover: Some(rgba(0xff7edbff).into()), ..Default::default() }, status: StatusColorsRefinement { diff --git a/crates/theme_importer/src/theme_printer.rs b/crates/theme_importer/src/theme_printer.rs index 13123d854f..eb304ff90d 100644 --- a/crates/theme_importer/src/theme_printer.rs +++ b/crates/theme_importer/src/theme_printer.rs @@ -270,6 +270,16 @@ impl<'a> Debug for ThemeColorsRefinementPrinter<'a> { ("terminal_ansi_magenta", self.0.terminal_ansi_magenta), ("terminal_ansi_cyan", self.0.terminal_ansi_cyan), ("terminal_ansi_white", self.0.terminal_ansi_white), + ("headline", self.0.headline), + ("paragraph", self.0.paragraph), + ("link_text", self.0.link_text), + ("link_text_hover", self.0.link_text_hover), + ("link_uri", self.0.link_uri), + ("inline_code_background", self.0.inline_code_background), + ("inline_code_border", self.0.inline_code_border), + ("code_block_background", self.0.code_block_background), + ("code_block_border", self.0.code_block_border), + ("emphasis", self.0.emphasis), ]; f.write_str("ThemeColorsRefinement {")?; diff --git a/crates/theme_importer/src/vscode/converter.rs b/crates/theme_importer/src/vscode/converter.rs index f5a606b329..8ade493731 100644 --- a/crates/theme_importer/src/vscode/converter.rs +++ b/crates/theme_importer/src/vscode/converter.rs @@ -217,6 +217,10 @@ impl VsCodeThemeConverter { .tab_inactive_foreground .as_ref() .traverse(|color| try_parse_color(&color))?, + link_text_hover: vscode_colors + .text_link_active_foreground + .as_ref() + .traverse(|color| try_parse_color(&color))?, tab_bar_background: vscode_colors .editor_group_header_tabs_background .as_ref() diff --git a/crates/theme_importer/src/vscode/theme.rs b/crates/theme_importer/src/vscode/theme.rs index f8e2c98da5..0c59a04c48 100644 --- a/crates/theme_importer/src/vscode/theme.rs +++ b/crates/theme_importer/src/vscode/theme.rs @@ -154,6 +154,13 @@ pub struct VsCodeColors { )] pub terminal_ansi_white: Option, + #[serde( + default, + rename = "textLink.activeForeground", + deserialize_with = "empty_string_as_none" + )] + pub text_link_active_foreground: Option, + #[serde( default, rename = "focusBorder", From 0390fb1449da8ee7585443353c2f6d8ae24b1098 Mon Sep 17 00:00:00 2001 From: Julia Date: Tue, 19 Dec 2023 18:38:25 -0500 Subject: [PATCH 175/644] Reintroduce LSP diagnostic/status message Co-Authored-By: Antonio Scandurra --- .../src/activity_indicator.rs | 4 ++-- crates/diagnostics2/src/items.rs | 22 ++++++++++++++++--- crates/workspace2/src/pane.rs | 17 ++++++++++++++ crates/workspace2/src/status_bar.rs | 9 ++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/crates/activity_indicator2/src/activity_indicator.rs b/crates/activity_indicator2/src/activity_indicator.rs index e4a5b01ba6..f83517e061 100644 --- a/crates/activity_indicator2/src/activity_indicator.rs +++ b/crates/activity_indicator2/src/activity_indicator.rs @@ -10,7 +10,7 @@ use language::{LanguageRegistry, LanguageServerBinaryStatus}; use project::{LanguageServerProgress, Project}; use smallvec::SmallVec; use std::{cmp::Reverse, fmt::Write, sync::Arc}; -use ui::h_stack; +use ui::{h_stack, Label}; use util::ResultExt; use workspace::{item::ItemHandle, StatusItemView, Workspace}; @@ -324,7 +324,7 @@ impl Render for ActivityIndicator { result .children(content.icon.map(|icon| svg().path(icon))) - .child(SharedString::from(content.message)) + .child(Label::new(SharedString::from(content.message))) } } diff --git a/crates/diagnostics2/src/items.rs b/crates/diagnostics2/src/items.rs index 92b0641dea..28bbe7aedc 100644 --- a/crates/diagnostics2/src/items.rs +++ b/crates/diagnostics2/src/items.rs @@ -1,13 +1,13 @@ use collections::HashSet; use editor::{Editor, GoToDiagnostic}; use gpui::{ - rems, Div, EventEmitter, InteractiveElement, ParentElement, Render, Stateful, + rems, Div, EventEmitter, InteractiveElement, IntoElement, ParentElement, Render, Stateful, StatefulInteractiveElement, Styled, Subscription, View, ViewContext, WeakView, }; use language::Diagnostic; use lsp::LanguageServerId; use theme::ActiveTheme; -use ui::{h_stack, Color, Icon, IconElement, Label, Tooltip}; +use ui::{h_stack, Button, Clickable, Color, Icon, IconElement, Label, Tooltip}; use workspace::{item::ItemHandle, StatusItemView, ToolbarItemEvent, Workspace}; use crate::ProjectDiagnosticsEditor; @@ -43,13 +43,28 @@ impl Render for DiagnosticIndicator { .child(Label::new(warning_count.to_string())), }; + let status = if !self.in_progress_checks.is_empty() { + Some(Label::new("Checking…").into_any_element()) + } else if let Some(diagnostic) = &self.current_diagnostic { + let message = diagnostic.message.split('\n').next().unwrap().to_string(); + Some( + Button::new("diagnostic_message", message) + .on_click(cx.listener(|this, _, cx| { + this.go_to_next_diagnostic(&GoToDiagnostic, cx); + })) + .into_any_element(), + ) + } else { + None + }; + h_stack() .id("diagnostic-indicator") .on_action(cx.listener(Self::go_to_next_diagnostic)) .rounded_md() .flex_none() .h(rems(1.375)) - .px_1() + .px_6() .cursor_pointer() .bg(cx.theme().colors().ghost_element_background) .hover(|style| style.bg(cx.theme().colors().ghost_element_hover)) @@ -63,6 +78,7 @@ impl Render for DiagnosticIndicator { } })) .child(diagnostic_indicator) + .children(status) } } diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index e1bb006c11..dcf4ed0811 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -789,6 +789,7 @@ impl Pane { } self.update_toolbar(cx); + self.update_status_bar(cx); if focus_item { self.focus_active_item(cx); @@ -1450,6 +1451,22 @@ impl Pane { }); } + fn update_status_bar(&mut self, cx: &mut ViewContext) { + let Ok(status_bar) = self + .workspace + .update(cx, |workspace, _| workspace.status_bar.clone()) + else { + return; + }; + + let pane = cx.view().clone(); + cx.window_context().defer(move |cx| { + status_bar.update(cx, move |status_bar, cx| { + status_bar.set_active_pane(&pane, cx); + }); + }); + } + fn render_tab( &self, ix: usize, diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index ba571d6e0a..f4e4ac9508 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -83,6 +83,9 @@ impl StatusBar { where T: 'static + StatusItemView, { + let active_pane_item = self.active_pane.read(cx).active_item(); + item.set_active_pane_item(active_pane_item.as_deref(), cx); + self.left_items.push(Box::new(item)); cx.notify(); } @@ -119,6 +122,9 @@ impl StatusBar { ) where T: 'static + StatusItemView, { + let active_pane_item = self.active_pane.read(cx).active_item(); + item.set_active_pane_item(active_pane_item.as_deref(), cx); + if position < self.left_items.len() { self.left_items.insert(position + 1, Box::new(item)) } else { @@ -141,6 +147,9 @@ impl StatusBar { where T: 'static + StatusItemView, { + let active_pane_item = self.active_pane.read(cx).active_item(); + item.set_active_pane_item(active_pane_item.as_deref(), cx); + self.right_items.push(Box::new(item)); cx.notify(); } From 3fccc648d66b2c3b8588a5a40434b7621e031ed8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 15:41:00 -0800 Subject: [PATCH 176/644] Fix layout of diagnostic blocks --- crates/diagnostics2/src/diagnostics.rs | 23 +++-- crates/editor2/src/editor.rs | 128 ++++++++++++------------- 2 files changed, 75 insertions(+), 76 deletions(-) diff --git a/crates/diagnostics2/src/diagnostics.rs b/crates/diagnostics2/src/diagnostics.rs index 1001ed880e..8103231ede 100644 --- a/crates/diagnostics2/src/diagnostics.rs +++ b/crates/diagnostics2/src/diagnostics.rs @@ -14,9 +14,9 @@ use editor::{ use futures::future::try_join_all; use gpui::{ actions, div, AnyElement, AnyView, AppContext, Context, Div, EventEmitter, FocusHandle, - Focusable, FocusableView, InteractiveElement, IntoElement, Model, ParentElement, Render, - SharedString, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, - WindowContext, + Focusable, FocusableView, HighlightStyle, InteractiveElement, IntoElement, Model, + ParentElement, Render, SharedString, Styled, StyledText, Subscription, Task, View, ViewContext, + VisualContext, WeakView, WindowContext, }; use language::{ Anchor, Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, @@ -36,7 +36,7 @@ use std::{ }; use theme::ActiveTheme; pub use toolbar_controls::ToolbarControls; -use ui::{h_stack, prelude::*, HighlightedLabel, Icon, IconElement, Label}; +use ui::{h_stack, prelude::*, Icon, IconElement, Label}; use util::TryFutureExt; use workspace::{ item::{BreadcrumbText, Item, ItemEvent, ItemHandle}, @@ -785,8 +785,10 @@ impl Item for ProjectDiagnosticsEditor { } fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock { - let (message, highlights) = highlight_diagnostic_message(Vec::new(), &diagnostic.message); - Arc::new(move |_| { + let (message, code_ranges) = highlight_diagnostic_message(&diagnostic); + let message: SharedString = message.into(); + Arc::new(move |cx| { + let highlight_style: HighlightStyle = cx.theme().colors().text_accent.into(); h_stack() .id("diagnostic header") .py_2() @@ -809,7 +811,14 @@ fn diagnostic_header_renderer(diagnostic: Diagnostic) -> RenderBlock { .child( h_stack() .gap_1() - .child(HighlightedLabel::new(message.clone(), highlights.clone())) + .child( + StyledText::new(message.clone()).with_highlights( + &cx.text_style(), + code_ranges + .iter() + .map(|range| (range.clone(), highlight_style)), + ), + ) .when_some(diagnostic.code.as_ref(), |stack, code| { stack.child(Label::new(format!("({code})")).color(Color::Muted)) }), diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 379c66df57..58f8e857a9 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -9719,90 +9719,80 @@ impl InvalidationRegion for SnippetState { } } -// impl Deref for EditorStyle { -// type Target = theme::Editor; - -// fn deref(&self) -> &Self::Target { -// &self.theme -// } -// } - pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock { - let mut highlighted_lines = Vec::new(); + let (text_without_backticks, code_ranges) = highlight_diagnostic_message(&diagnostic); - for (index, line) in diagnostic.message.lines().enumerate() { - let line = match &diagnostic.source { - Some(source) if index == 0 => { - let source_highlight = Vec::from_iter(0..source.len()); - highlight_diagnostic_message(source_highlight, &format!("{source}: {line}")) - } - - _ => highlight_diagnostic_message(Vec::new(), line), - }; - highlighted_lines.push(line); - } Arc::new(move |cx: &mut BlockContext| { - let copy_id: SharedString = format!("copy-{}", cx.block_id.clone()).to_string().into(); + let color = Some(cx.theme().colors().text_accent); + let group_id: SharedString = cx.block_id.to_string().into(); // TODO: Nate: We should tint the background of the block with the severity color // We need to extend the theme before we can do this - v_stack() + h_stack() .id(cx.block_id) + .group(group_id.clone()) .relative() + .pl(cx.anchor_x) .size_full() - .bg(gpui::red()) - .children(highlighted_lines.iter().map(|(line, highlights)| { - let group_id = cx.block_id.to_string(); - h_stack() - .group(group_id.clone()) - .gap_2() - .absolute() - .left(cx.anchor_x) - .px_1p5() - .child(HighlightedLabel::new(line.clone(), highlights.clone())) - .child( - div().z_index(1).child( - IconButton::new(copy_id.clone(), Icon::Copy) - .icon_color(Color::Muted) - .size(ButtonSize::Compact) - .style(ButtonStyle::Transparent) - .visible_on_hover(group_id) - .on_click(cx.listener({ - let message = diagnostic.message.clone(); - move |_, _, cx| { - cx.write_to_clipboard(ClipboardItem::new(message.clone())) - } - })) - .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)), - ), - ) - })) + .gap_2() + .child( + StyledText::new(text_without_backticks.clone()).with_highlights( + &cx.text_style(), + code_ranges.iter().map(|range| { + ( + range.clone(), + HighlightStyle { + color, + ..Default::default() + }, + ) + }), + ), + ) + .child( + IconButton::new(("copy-block", cx.block_id), Icon::Copy) + .icon_color(Color::Muted) + .size(ButtonSize::Compact) + .style(ButtonStyle::Transparent) + .visible_on_hover(group_id) + .on_click(cx.listener({ + let message = diagnostic.message.clone(); + move |_, _, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone())) + })) + .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)), + ) .into_any_element() }) } -pub fn highlight_diagnostic_message( - initial_highlights: Vec, - message: &str, -) -> (String, Vec) { - let mut message_without_backticks = String::new(); - let mut prev_offset = 0; - let mut inside_block = false; - let mut highlights = initial_highlights; - for (match_ix, (offset, _)) in message - .match_indices('`') - .chain([(message.len(), "")]) - .enumerate() - { - message_without_backticks.push_str(&message[prev_offset..offset]); - if inside_block { - highlights.extend(prev_offset - match_ix..offset - match_ix); - } +pub fn highlight_diagnostic_message(diagnostic: &Diagnostic) -> (SharedString, Vec>) { + let mut text_without_backticks = String::new(); + let mut code_ranges = Vec::new(); - inside_block = !inside_block; - prev_offset = offset + 1; + if let Some(source) = &diagnostic.source { + text_without_backticks.push_str(&source); + code_ranges.push(0..source.len()); + text_without_backticks.push_str(": "); } - (message_without_backticks, highlights) + let mut prev_offset = 0; + let mut in_code_block = false; + for (ix, _) in diagnostic + .message + .match_indices('`') + .chain([(diagnostic.message.len(), "")]) + { + let prev_len = text_without_backticks.len(); + text_without_backticks.push_str(&diagnostic.message[prev_offset..ix]); + prev_offset = ix + 1; + if in_code_block { + code_ranges.push(prev_len..text_without_backticks.len()); + in_code_block = false; + } else { + in_code_block = true; + } + } + + (text_without_backticks.into(), code_ranges) } pub fn diagnostic_style( From c81e89a4f40af9d8d095a014601480ed2cc73f95 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 19 Dec 2023 17:04:42 -0800 Subject: [PATCH 177/644] Ensure that new view observers are called by WindowContext::replace_root_view --- crates/gpui2/src/window.rs | 9 ++------- crates/workspace2/src/workspace2.rs | 5 ----- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 1b2669b40c..365338611b 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1926,14 +1926,9 @@ impl VisualContext for WindowContext<'_> { where V: 'static + Render, { - let slot = self.app.entities.reserve(); - let view = View { - model: slot.clone(), - }; - let mut cx = ViewContext::new(&mut *self.app, &mut *self.window, &view); - let entity = build_view(&mut cx); - self.entities.insert(slot, entity); + let view = self.build_view(build_view); self.window.root_view = Some(view.clone().into()); + self.notify(); view } diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 4f911d1073..95b05f314e 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -600,11 +600,6 @@ impl Workspace { let modal_layer = cx.build_view(|_| ModalLayer::new()); - // todo!() - // cx.update_default_global::, _, _>(|drag_and_drop, _| { - // drag_and_drop.register_container(weak_handle.clone()); - // }); - let mut active_call = None; if cx.has_global::>() { let call = cx.global::>().clone(); From 00927db7115c9b11f118c9c14dcce785ea243cdd Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Dec 2023 11:21:55 +0100 Subject: [PATCH 178/644] Fix sluggish experience when dragging tabs The problem was caused by a missing call to `WindowContext::notify` when moving the mouse. Actually, we *did* notify as part of a `MouseMoveEvent` listener registered in `Interactivity` but that code path was never exercised because we were clearing the `pending_mouse_down`. This commit fixes the issue by automatically redrawing the window in gpui when there is an active drag and the mouse moves. --- crates/gpui2/src/elements/div.rs | 11 +++++------ crates/gpui2/src/window.rs | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 57fd3d6a8a..fa1eb9e5b6 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1186,14 +1186,13 @@ impl Interactivity { cx.on_mouse_event({ let pending_mouse_down = pending_mouse_down.clone(); move |event: &MouseMoveEvent, phase, cx| { - let mut pending_mouse_down = pending_mouse_down.borrow_mut(); + if phase == DispatchPhase::Capture { + return; + } + let mut pending_mouse_down = pending_mouse_down.borrow_mut(); if let Some(mouse_down) = pending_mouse_down.clone() { - if cx.active_drag.is_some() { - if phase == DispatchPhase::Capture { - cx.notify(); - } - } else if phase == DispatchPhase::Bubble + if !cx.has_active_drag() && (event.position - mouse_down.position).magnitude() > DRAG_THRESHOLD { diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 365338611b..cc435bf0b2 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1516,15 +1516,24 @@ impl<'a> WindowContext<'a> { } } - if self.app.propagate_event && event.downcast_ref::().is_some() { - self.active_drag = None; - } - self.window .rendered_frame .mouse_listeners .insert(event.type_id(), handlers); } + + if self.app.propagate_event && self.has_active_drag() { + if event.is::() { + // If this was a mouse move event, redraw the window so that the + // active drag can follow the mouse cursor. + self.notify(); + } else if event.is::() { + // If this was a mouse up event, cancel the active drag and redraw + // the window. + self.active_drag = None; + self.notify(); + } + } } fn dispatch_key_event(&mut self, event: &dyn Any) { From 2f57a3ccfb74d663588d0792d88144d03fe22977 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:47:53 +0100 Subject: [PATCH 179/644] Popover buttons titlebar (#3732) Migrate project picker/vcs menu to use popover_menu. Release Notes: - N/A --- crates/collab_ui2/src/collab_titlebar_item.rs | 84 ++++++++----------- .../recent_projects2/src/recent_projects.rs | 43 ++++++---- crates/vcs_menu2/src/lib.rs | 78 +++++++++-------- 3 files changed, 106 insertions(+), 99 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 17ee5087bb..9359ff41d8 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -3,10 +3,10 @@ use auto_update::AutoUpdateStatus; use call::{ActiveCall, ParticipantLocation, Room}; use client::{proto::PeerId, Client, ParticipantIndex, User, UserStore}; use gpui::{ - actions, canvas, div, overlay, point, px, rems, Action, AnyElement, AppContext, DismissEvent, - Div, Element, FocusableView, Hsla, InteractiveElement, IntoElement, Model, ParentElement, Path, - Render, Stateful, StatefulInteractiveElement, Styled, Subscription, View, ViewContext, - VisualContext, WeakView, WindowBounds, + actions, canvas, div, point, px, rems, Action, AnyElement, AppContext, Div, Element, Hsla, + InteractiveElement, IntoElement, Model, ParentElement, Path, Render, Stateful, + StatefulInteractiveElement, Styled, Subscription, View, ViewContext, VisualContext, WeakView, + WindowBounds, }; use project::{Project, RepositoryEntry}; use recent_projects::RecentProjects; @@ -52,8 +52,8 @@ pub struct CollabTitlebarItem { user_store: Model, client: Arc, workspace: WeakView, - branch_popover: Option>, - project_popover: Option, + branch_popover: Option<(View, Subscription)>, + project_popover: Option<(View, Subscription)>, _subscriptions: Vec, } @@ -329,9 +329,8 @@ impl CollabTitlebarItem { }; let name = util::truncate_and_trailoff(name, MAX_PROJECT_NAME_LENGTH); - - div() - .child( + popover_menu("project_name_trigger") + .trigger( Button::new("project_name_trigger", name) .style(ButtonStyle::Subtle) .tooltip(move |cx| Tooltip::text("Recent Projects", cx)) @@ -339,16 +338,12 @@ impl CollabTitlebarItem { this.toggle_project_menu(&ToggleProjectMenu, cx); })), ) - .children(self.project_popover.as_ref().map(|popover| { - overlay().child( - div() - .min_w_56() - .on_mouse_down_out(cx.listener_for(&popover.picker, |picker, _, cx| { - picker.cancel(&Default::default(), cx) - })) - .child(popover.picker.clone()), - ) - })) + .when_some( + self.project_popover + .as_ref() + .map(|(project, _)| project.clone()), + |this, project| this.menu(move |_| project.clone()), + ) } pub fn render_project_branch(&self, cx: &mut ViewContext) -> Option { @@ -366,10 +361,9 @@ impl CollabTitlebarItem { .as_ref() .and_then(RepositoryEntry::branch) .map(|branch| util::truncate_and_trailoff(&branch, MAX_BRANCH_NAME_LENGTH))?; - Some( - div() - .child( + popover_menu("project_branch_trigger") + .trigger( Button::new("project_branch_trigger", branch_name) .color(Color::Muted) .style(ButtonStyle::Subtle) @@ -381,11 +375,16 @@ impl CollabTitlebarItem { cx, ) }) - .on_click( - cx.listener(|this, _, cx| this.toggle_vcs_menu(&ToggleVcsMenu, cx)), - ), + .on_click(cx.listener(|this, _, cx| { + this.toggle_vcs_menu(&ToggleVcsMenu, cx); + })), ) - .children(self.render_branches_popover_host()), + .when_some( + self.branch_popover + .as_ref() + .map(|(branch, _)| branch.clone()), + |this, branch| this.menu(move |_| branch.clone()), + ), ) } @@ -461,29 +460,19 @@ impl CollabTitlebarItem { .log_err(); } - fn render_branches_popover_host<'a>(&'a self) -> Option { - self.branch_popover.as_ref().map(|child| { - overlay() - .child(div().min_w_64().child(child.clone())) - .into_any() - }) - } - pub fn toggle_vcs_menu(&mut self, _: &ToggleVcsMenu, cx: &mut ViewContext) { if self.branch_popover.take().is_none() { if let Some(workspace) = self.workspace.upgrade() { let Some(view) = build_branch_list(workspace, cx).log_err() else { return; }; - cx.subscribe(&view, |this, _, _, cx| { - this.branch_popover = None; - cx.notify(); - }) - .detach(); self.project_popover.take(); let focus_handle = view.focus_handle(cx); cx.focus(&focus_handle); - self.branch_popover = Some(view); + let subscription = cx.subscribe(&view, |this, _, _, _| { + this.branch_popover.take(); + }); + self.branch_popover = Some((view, subscription)); } } @@ -491,8 +480,8 @@ impl CollabTitlebarItem { } pub fn toggle_project_menu(&mut self, _: &ToggleProjectMenu, cx: &mut ViewContext) { - let workspace = self.workspace.clone(); if self.project_popover.take().is_none() { + let workspace = self.workspace.clone(); cx.spawn(|this, mut cx| async move { let workspaces = WORKSPACE_DB .recent_workspaces_on_disk() @@ -506,16 +495,13 @@ impl CollabTitlebarItem { this.update(&mut cx, move |this, cx| { let view = RecentProjects::open_popover(workspace, workspaces, cx); - cx.subscribe(&view.picker, |this, _, _: &DismissEvent, cx| { - this.project_popover = None; - cx.notify(); - }) - .detach(); let focus_handle = view.focus_handle(cx); cx.focus(&focus_handle); - // todo!() - //this.branch_popover.take(); - this.project_popover = Some(view); + this.branch_popover.take(); + let subscription = cx.subscribe(&view, |this, _, _, _| { + this.project_popover.take(); + }); + this.project_popover = Some((view, subscription)); cx.notify(); }) .log_err(); diff --git a/crates/recent_projects2/src/recent_projects.rs b/crates/recent_projects2/src/recent_projects.rs index 3ecf1180af..13790a5b23 100644 --- a/crates/recent_projects2/src/recent_projects.rs +++ b/crates/recent_projects2/src/recent_projects.rs @@ -3,8 +3,8 @@ mod projects; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Result, Task, View, - ViewContext, WeakView, + AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Result, Subscription, + Task, View, ViewContext, WeakView, }; use highlighted_workspace_location::HighlightedWorkspaceLocation; use ordered_float::OrderedFloat; @@ -23,17 +23,22 @@ pub fn init(cx: &mut AppContext) { cx.observe_new_views(RecentProjects::register).detach(); } -#[derive(Clone)] pub struct RecentProjects { pub picker: View>, + rem_width: f32, + _subscription: Subscription, } impl ModalView for RecentProjects {} impl RecentProjects { - fn new(delegate: RecentProjectsDelegate, cx: &mut WindowContext<'_>) -> Self { + fn new(delegate: RecentProjectsDelegate, rem_width: f32, cx: &mut ViewContext) -> Self { + let picker = cx.build_view(|cx| Picker::new(delegate, cx)); + let _subscription = cx.subscribe(&picker, |_, _, _, cx| cx.emit(DismissEvent)); Self { - picker: cx.build_view(|cx| Picker::new(delegate, cx)), + picker, + rem_width, + _subscription, } } @@ -76,9 +81,7 @@ impl RecentProjects { let delegate = RecentProjectsDelegate::new(weak_workspace, workspace_locations, true); - let modal = RecentProjects::new(delegate, cx); - cx.subscribe(&modal.picker, |_, _, _, cx| cx.emit(DismissEvent)) - .detach(); + let modal = RecentProjects::new(delegate, 34., cx); modal }); } else { @@ -94,11 +97,14 @@ impl RecentProjects { workspace: WeakView, workspaces: Vec, cx: &mut WindowContext<'_>, - ) -> Self { - Self::new( - RecentProjectsDelegate::new(workspace, workspaces, false), - cx, - ) + ) -> View { + cx.build_view(|cx| { + Self::new( + RecentProjectsDelegate::new(workspace, workspaces, false), + 20., + cx, + ) + }) } } @@ -113,8 +119,15 @@ impl FocusableView for RecentProjects { impl Render for RecentProjects { type Element = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - v_stack().w(rems(34.)).child(self.picker.clone()) + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + v_stack() + .w(rems(self.rem_width)) + .child(self.picker.clone()) + .on_mouse_down_out(cx.listener(|this, _, cx| { + this.picker.update(cx, |this, cx| { + this.cancel(&Default::default(), cx); + }) + })) } } diff --git a/crates/vcs_menu2/src/lib.rs b/crates/vcs_menu2/src/lib.rs index ca3b685aa6..1483a2e81e 100644 --- a/crates/vcs_menu2/src/lib.rs +++ b/crates/vcs_menu2/src/lib.rs @@ -3,8 +3,8 @@ use fs::repository::Branch; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ actions, rems, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, - ParentElement, Render, SharedString, Styled, Task, View, ViewContext, VisualContext, - WindowContext, + InteractiveElement, ParentElement, Render, SharedString, Styled, Subscription, Task, View, + ViewContext, VisualContext, WindowContext, }; use picker::{Picker, PickerDelegate}; use std::sync::Arc; @@ -18,31 +18,61 @@ pub fn init(cx: &mut AppContext) { // todo!() po cx.observe_new_views(|workspace: &mut Workspace, _| { workspace.register_action(|workspace, action, cx| { - ModalBranchList::toggle_modal(workspace, action, cx).log_err(); + BranchList::toggle_modal(workspace, action, cx).log_err(); }); }) .detach(); } -pub type BranchList = Picker; -pub struct ModalBranchList { +pub struct BranchList { pub picker: View>, + rem_width: f32, + _subscription: Subscription, } -impl ModalView for ModalBranchList {} -impl EventEmitter for ModalBranchList {} +impl BranchList { + fn new(delegate: BranchListDelegate, rem_width: f32, cx: &mut ViewContext) -> Self { + let picker = cx.build_view(|cx| Picker::new(delegate, cx)); + let _subscription = cx.subscribe(&picker, |_, _, _, cx| cx.emit(DismissEvent)); + Self { + picker, + rem_width, + _subscription, + } + } + fn toggle_modal( + workspace: &mut Workspace, + _: &OpenRecent, + cx: &mut ViewContext, + ) -> Result<()> { + // Modal branch picker has a longer trailoff than a popover one. + let delegate = BranchListDelegate::new(workspace, cx.view().clone(), 70, cx)?; + workspace.toggle_modal(cx, |cx| BranchList::new(delegate, 34., cx)); -impl FocusableView for ModalBranchList { + Ok(()) + } +} +impl ModalView for BranchList {} +impl EventEmitter for BranchList {} + +impl FocusableView for BranchList { fn focus_handle(&self, cx: &AppContext) -> FocusHandle { self.picker.focus_handle(cx) } } -impl Render for ModalBranchList { +impl Render for BranchList { type Element = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - v_stack().w(rems(34.)).child(self.picker.clone()) + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + v_stack() + .w(rems(self.rem_width)) + .child(self.picker.clone()) + .on_mouse_down_out(cx.listener(|this, _, cx| { + this.picker.update(cx, |this, cx| { + this.cancel(&Default::default(), cx); + }) + })) } } @@ -53,29 +83,7 @@ pub fn build_branch_list( let delegate = workspace.update(cx, |workspace, cx| { BranchListDelegate::new(workspace, cx.view().clone(), 29, cx) })?; - - Ok(cx.build_view(|cx| Picker::new(delegate, cx))) -} - -impl ModalBranchList { - fn toggle_modal( - workspace: &mut Workspace, - _: &OpenRecent, - cx: &mut ViewContext, - ) -> Result<()> { - // Modal branch picker has a longer trailoff than a popover one. - let delegate = BranchListDelegate::new(workspace, cx.view().clone(), 70, cx)?; - workspace.toggle_modal(cx, |cx| { - let modal = ModalBranchList { - picker: cx.build_view(|cx| Picker::new(delegate, cx)), - }; - cx.subscribe(&modal.picker, |_, _, _, cx| cx.emit(DismissEvent)) - .detach(); - modal - }); - - Ok(()) - } + Ok(cx.build_view(move |cx| BranchList::new(delegate, 20., cx))) } pub struct BranchListDelegate { @@ -116,7 +124,7 @@ impl BranchListDelegate { }) } - fn display_error_toast(&self, message: String, cx: &mut ViewContext) { + fn display_error_toast(&self, message: String, cx: &mut WindowContext<'_>) { const GIT_CHECKOUT_FAILURE_ID: usize = 2048; self.workspace.update(cx, |model, ctx| { model.show_toast(Toast::new(GIT_CHECKOUT_FAILURE_ID, message), ctx) From 5781cf6604fe70931147673256d5735ccb6572ae Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Dec 2023 13:59:33 +0100 Subject: [PATCH 180/644] Use `InteractiveBounds` everywhere we change the cursor style --- crates/editor2/src/element.rs | 14 +++++++++++--- crates/gpui2/src/elements/text.rs | 7 +++---- crates/workspace2/src/pane_group.rs | 12 ++++++++---- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 7fc5244b92..8031bc5db6 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -884,7 +884,11 @@ impl EditorElement { bounds: text_bounds, }), |cx| { - if text_bounds.contains(&cx.mouse_position()) { + let interactive_text_bounds = InteractiveBounds { + bounds: text_bounds, + stacking_order: cx.stacking_order().clone(), + }; + if interactive_text_bounds.visibly_contains(&cx.mouse_position(), cx) { if self .editor .read(cx) @@ -1361,8 +1365,12 @@ impl EditorElement { )); } + let interactive_track_bounds = InteractiveBounds { + bounds: track_bounds, + stacking_order: cx.stacking_order().clone(), + }; let mut mouse_position = cx.mouse_position(); - if track_bounds.contains(&mouse_position) { + if interactive_track_bounds.visibly_contains(&mouse_position, cx) { cx.set_cursor_style(CursorStyle::Arrow); } @@ -1392,7 +1400,7 @@ impl EditorElement { cx.stop_propagation(); } else { editor.scroll_manager.set_is_dragging_scrollbar(false, cx); - if track_bounds.contains(&event.position) { + if interactive_track_bounds.visibly_contains(&event.position, cx) { editor.scroll_manager.show_scrollbar(cx); } } diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index 175a79c19a..7716d81536 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -358,14 +358,13 @@ impl Element for InteractiveText { fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { if let Some(click_listener) = self.click_listener.take() { - if let Some(ix) = state - .text_state - .index_for_position(bounds, cx.mouse_position()) - { + let mouse_position = cx.mouse_position(); + if let Some(ix) = state.text_state.index_for_position(bounds, mouse_position) { if self .clickable_ranges .iter() .any(|range| range.contains(&ix)) + && cx.was_top_layer(&mouse_position, cx.stacking_order()) { cx.set_cursor_style(crate::CursorStyle::PointingHand) } diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index 7416b72331..06bd506e56 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -564,9 +564,9 @@ mod element { use std::{cell::RefCell, iter, rc::Rc, sync::Arc}; use gpui::{ - px, relative, Along, AnyElement, Axis, Bounds, CursorStyle, Element, IntoElement, - MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Size, Style, - WindowContext, + px, relative, Along, AnyElement, Axis, Bounds, CursorStyle, Element, InteractiveBounds, + IntoElement, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, + Size, Style, WindowContext, }; use parking_lot::Mutex; use smallvec::SmallVec; @@ -717,7 +717,11 @@ mod element { }; cx.with_z_index(3, |cx| { - if handle_bounds.contains(&cx.mouse_position()) { + let interactive_handle_bounds = InteractiveBounds { + bounds: handle_bounds, + stacking_order: cx.stacking_order().clone(), + }; + if interactive_handle_bounds.visibly_contains(&cx.mouse_position(), cx) { cx.set_cursor_style(match axis { Axis::Vertical => CursorStyle::ResizeUpDown, Axis::Horizontal => CursorStyle::ResizeLeftRight, From 8273865fa39e0a7e83cb3ec7ee6d3f35ef198da6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Dec 2023 14:00:12 +0100 Subject: [PATCH 181/644] Introduce `InteractiveElement::capture_any_mouse_{down,up}` --- crates/gpui2/src/elements/div.rs | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index fa1eb9e5b6..908b302dfc 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -62,6 +62,18 @@ impl Interactivity { })); } + pub fn capture_any_mouse_down( + &mut self, + listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, + ) { + self.mouse_down_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Capture && bounds.visibly_contains(&event.position, cx) { + (listener)(event, cx) + } + })); + } + pub fn on_any_mouse_down( &mut self, listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, @@ -90,6 +102,18 @@ impl Interactivity { })); } + pub fn capture_any_mouse_up( + &mut self, + listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, + ) { + self.mouse_up_listeners + .push(Box::new(move |event, bounds, phase, cx| { + if phase == DispatchPhase::Capture && bounds.visibly_contains(&event.position, cx) { + (listener)(event, cx) + } + })); + } + pub fn on_any_mouse_up( &mut self, listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, @@ -384,6 +408,14 @@ pub trait InteractiveElement: Sized { self } + fn capture_any_mouse_down( + mut self, + listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, + ) -> Self { + self.interactivity().capture_any_mouse_down(listener); + self + } + fn on_any_mouse_down( mut self, listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, @@ -401,6 +433,14 @@ pub trait InteractiveElement: Sized { self } + fn capture_any_mouse_up( + mut self, + listener: impl Fn(&MouseUpEvent, &mut WindowContext) + 'static, + ) -> Self { + self.interactivity().capture_any_mouse_up(listener); + self + } + fn on_mouse_down_out( mut self, listener: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static, From 390ccbc6ad26068af1ce963eefb94961ebeee3b5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Dec 2023 14:00:47 +0100 Subject: [PATCH 182/644] Disable focus when disconnecting from host --- crates/gpui2/src/window.rs | 13 ++++++++++++- crates/workspace2/src/workspace2.rs | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index cc435bf0b2..07be281f0a 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -273,6 +273,7 @@ pub struct Window { pub(crate) drawing: bool, activation_observers: SubscriberSet<(), AnyObserver>, pub(crate) focus: Option, + focus_enabled: bool, #[cfg(any(test, feature = "test-support"))] pub(crate) focus_invalidated: bool, @@ -420,6 +421,7 @@ impl Window { drawing: false, activation_observers: SubscriberSet::new(), focus: None, + focus_enabled: true, #[cfg(any(test, feature = "test-support"))] focus_invalidated: false, @@ -496,7 +498,7 @@ impl<'a> WindowContext<'a> { /// Move focus to the element associated with the given `FocusHandle`. pub fn focus(&mut self, handle: &FocusHandle) { - if self.window.focus == Some(handle.id) { + if !self.window.focus_enabled || self.window.focus == Some(handle.id) { return; } @@ -516,10 +518,19 @@ impl<'a> WindowContext<'a> { /// Remove focus from all elements within this context's window. pub fn blur(&mut self) { + if !self.window.focus_enabled { + return; + } + self.window.focus = None; self.notify(); } + pub fn disable_focus(&mut self) { + self.blur(); + self.window.focus_enabled = false; + } + pub fn dispatch_action(&mut self, action: Box) { let focus_handle = self.focused(); diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 95b05f314e..a5acd1c1c7 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -502,7 +502,7 @@ impl Workspace { project::Event::DisconnectedFromHost => { this.update_window_edited(cx); - cx.blur(); + cx.disable_focus(); } project::Event::Closed => { From 57f3a882fe50fdc22dbf4317549e6222b0a735ea Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Dec 2023 14:07:01 +0100 Subject: [PATCH 183/644] Render disconnected overlay when project becomes readonly --- crates/workspace2/src/workspace2.rs | 95 +++++++++++++++++++---------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index a5acd1c1c7..797e95088d 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -25,12 +25,13 @@ use futures::{ Future, FutureExt, StreamExt, }; use gpui::{ - actions, canvas, div, impl_actions, point, size, Action, AnyModel, AnyView, AnyWeakView, - AnyWindowHandle, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Context, Div, - DragMoveEvent, Entity, EntityId, EventEmitter, FocusHandle, FocusableView, GlobalPixels, - InteractiveElement, KeyContext, ManagedView, Model, ModelContext, ParentElement, - PathPromptOptions, Pixels, Point, PromptLevel, Render, Size, Styled, Subscription, Task, View, - ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions, + actions, canvas, div, impl_actions, point, size, Action, AnyElement, AnyModel, AnyView, + AnyWeakView, AnyWindowHandle, AppContext, AsyncAppContext, AsyncWindowContext, BorrowWindow, + Bounds, Context, Div, DragMoveEvent, Element, Entity, EntityId, EventEmitter, FocusHandle, + FocusableView, GlobalPixels, InteractiveElement, IntoElement, KeyContext, LayoutId, + ManagedView, Model, ModelContext, ParentElement, PathPromptOptions, Pixels, Point, PromptLevel, + Render, Size, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, + WindowBounds, WindowContext, WindowHandle, WindowOptions, }; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem}; use itertools::Itertools; @@ -64,6 +65,7 @@ use std::{ use theme::{ActiveTheme, ThemeSettings}; pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView}; pub use ui; +use ui::Label; use util::ResultExt; use uuid::Uuid; pub use workspace_settings::{AutosaveSetting, WorkspaceSettings}; @@ -2519,32 +2521,6 @@ impl Workspace { } } - // fn render_disconnected_overlay( - // &self, - // cx: &mut ViewContext, - // ) -> Option> { - // if self.project.read(cx).is_read_only() { - // enum DisconnectedOverlay {} - // Some( - // MouseEventHandler::new::(0, cx, |_, cx| { - // let theme = &theme::current(cx); - // Label::new( - // "Your connection to the remote project has been lost.", - // theme.workspace.disconnected_overlay.text.clone(), - // ) - // .aligned() - // .contained() - // .with_style(theme.workspace.disconnected_overlay.container) - // }) - // .with_cursor_style(CursorStyle::Arrow) - // .capture_all() - // .into_any_named("disconnected overlay"), - // ) - // } else { - // None - // } - // } - fn render_notifications(&self, _cx: &ViewContext) -> Option
{ if self.notifications.is_empty() { None @@ -3661,6 +3637,11 @@ impl Render for Workspace { })), ) .child(self.status_bar.clone()) + .children(if self.project.read(cx).is_read_only() { + Some(DisconnectedOverlay) + } else { + None + }) } } @@ -4284,6 +4265,56 @@ fn parse_pixel_size_env_var(value: &str) -> Option> { Some(size((width as f64).into(), (height as f64).into())) } +struct DisconnectedOverlay; + +impl Element for DisconnectedOverlay { + type State = AnyElement; + + fn layout( + &mut self, + _: Option, + cx: &mut WindowContext, + ) -> (LayoutId, Self::State) { + let mut background = cx.theme().colors().elevated_surface_background; + background.fade_out(0.2); + let mut overlay = div() + .bg(background) + .absolute() + .left_0() + .top_0() + .size_full() + .flex() + .items_center() + .justify_center() + .capture_any_mouse_down(|_, cx| cx.stop_propagation()) + .capture_any_mouse_up(|_, cx| cx.stop_propagation()) + .child(Label::new( + "Your connection to the remote project has been lost.", + )) + .into_any(); + (overlay.layout(cx), overlay) + } + + fn paint(&mut self, bounds: Bounds, overlay: &mut Self::State, cx: &mut WindowContext) { + cx.with_z_index(u8::MAX, |cx| { + cx.add_opaque_layer(bounds); + overlay.paint(cx); + }) + } +} + +impl IntoElement for DisconnectedOverlay { + type Element = Self; + + fn element_id(&self) -> Option { + None + } + + fn into_element(self) -> Self::Element { + self + } +} + #[cfg(test)] mod tests { use std::{cell::RefCell, rc::Rc}; From 6e1ba645f3e73fe0e867d27b2152d853ef74a2ab Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Dec 2023 14:17:15 +0100 Subject: [PATCH 184/644] Show button as selected if screen sharing is on --- crates/collab_ui2/src/collab_titlebar_item.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 9359ff41d8..ae66485919 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -176,6 +176,7 @@ impl Render for CollabTitlebarItem { let is_shared = self.project.read(cx).is_shared(); let is_muted = room.is_muted(cx); let is_deafened = room.is_deafened().unwrap_or(false); + let is_screen_sharing = room.is_screen_sharing(); this.child( Button::new( @@ -225,7 +226,7 @@ impl Render for CollabTitlebarItem { }, ) .style(ButtonStyle::Subtle) - .selected(is_deafened.clone()) + .selected(is_deafened) .tooltip(move |cx| { Tooltip::with_meta("Deafen Audio", None, "Mic will be muted", cx) }) @@ -234,6 +235,7 @@ impl Render for CollabTitlebarItem { .child( IconButton::new("screen-share", ui::Icon::Screen) .style(ButtonStyle::Subtle) + .selected(is_screen_sharing) .on_click(move |_, cx| { crate::toggle_screen_sharing(&Default::default(), cx) }), From 12bb13b9fc73cb099c565b33b89a64479990fec7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 08:20:00 -0700 Subject: [PATCH 185/644] Perform a bounds check when allocating in the arena This ensures we don't invoke undefined behavior when overflowing. Co-Authored-By: Antonio --- crates/gpui2/src/arena.rs | 53 ++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index c99f09d29f..5992baf06e 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -2,13 +2,13 @@ use std::{ alloc, cell::Cell, ops::{Deref, DerefMut}, - ptr::{self, NonNull}, + ptr, rc::Rc, }; struct ArenaElement { - value: NonNull, - drop: unsafe fn(NonNull), + value: *mut u8, + drop: unsafe fn(*mut u8), } impl Drop for ArenaElement { @@ -21,8 +21,9 @@ impl Drop for ArenaElement { } pub struct Arena { - start: NonNull, - offset: usize, + start: *mut u8, + end: *mut u8, + offset: *mut u8, elements: Vec, valid: Rc>, } @@ -31,10 +32,12 @@ impl Arena { pub fn new(size_in_bytes: usize) -> Self { unsafe { let layout = alloc::Layout::from_size_align(size_in_bytes, 1).unwrap(); - let ptr = alloc::alloc(layout); + let start = alloc::alloc(layout); + let end = start.add(size_in_bytes); Self { - start: NonNull::new_unchecked(ptr), - offset: 0, + start, + end, + offset: start, elements: Vec::new(), valid: Rc::new(Cell::new(true)), } @@ -45,7 +48,7 @@ impl Arena { self.valid.set(false); self.valid = Rc::new(Cell::new(true)); self.elements.clear(); - self.offset = 0; + self.offset = self.start; } #[inline(always)] @@ -58,24 +61,28 @@ impl Arena { ptr::write(ptr, f()); } - unsafe fn drop(ptr: NonNull) { - std::ptr::drop_in_place(ptr.cast::().as_ptr()); + unsafe fn drop(ptr: *mut u8) { + std::ptr::drop_in_place(ptr.cast::()); } unsafe { let layout = alloc::Layout::new::().pad_to_align(); - let ptr = NonNull::new_unchecked(self.start.as_ptr().add(self.offset).cast::()); - inner_writer(ptr.as_ptr(), f); + let next_offset = self.offset.add(layout.size()); + assert!(next_offset <= self.end); + let result = ArenaRef { + ptr: self.offset.cast(), + valid: self.valid.clone(), + }; + + inner_writer(result.ptr, f); self.elements.push(ArenaElement { - value: ptr.cast(), + value: self.offset, drop: drop::, }); - self.offset += layout.size(); - ArenaRef { - ptr, - valid: self.valid.clone(), - } + self.offset = next_offset; + + result } } } @@ -87,7 +94,7 @@ impl Drop for Arena { } pub struct ArenaRef { - ptr: NonNull, + ptr: *mut T, valid: Rc>, } @@ -104,7 +111,7 @@ impl ArenaRef { #[inline(always)] pub fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef { ArenaRef { - ptr: unsafe { NonNull::new_unchecked(f(&mut *self)) }, + ptr: f(&mut self), valid: self.valid, } } @@ -123,7 +130,7 @@ impl Deref for ArenaRef { #[inline(always)] fn deref(&self) -> &Self::Target { self.validate(); - unsafe { self.ptr.as_ref() } + unsafe { &*self.ptr } } } @@ -131,7 +138,7 @@ impl DerefMut for ArenaRef { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { self.validate(); - unsafe { self.ptr.as_mut() } + unsafe { &mut *self.ptr } } } From 5b29c89e1ce333e298138988844d5080c8a33abf Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 08:55:18 -0700 Subject: [PATCH 186/644] Clear pending click state when dragging Once a drag starts, we won't fire click listeners or style any elements as active. Co-Authored-By: Antonio --- crates/gpui2/src/elements/div.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 908b302dfc..d5284c02a1 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -919,6 +919,15 @@ impl Interactivity { ) -> (LayoutId, InteractiveElementState) { let mut element_state = element_state.unwrap_or_default(); + if cx.has_active_drag() { + if let Some(pending_mouse_down) = element_state.pending_mouse_down.as_ref() { + *pending_mouse_down.borrow_mut() = None; + } + if let Some(clicked_state) = element_state.clicked_state.as_ref() { + *clicked_state.borrow_mut() = ElementClickedState::default(); + } + } + // Ensure we store a focus handle in our element state if we're focusable. // If there's an explicit focus handle we're tracking, use that. Otherwise // create a new handle and store it in the element state, which lives for as @@ -1204,7 +1213,7 @@ impl Interactivity { .get_or_insert_with(Default::default) .clone(); - let active_state = element_state + let clicked_state = element_state .clicked_state .get_or_insert_with(Default::default) .clone(); @@ -1237,7 +1246,7 @@ impl Interactivity { > DRAG_THRESHOLD { if let Some((drag_value, drag_listener)) = drag_listener.take() { - *active_state.borrow_mut() = ElementClickedState::default(); + *clicked_state.borrow_mut() = ElementClickedState::default(); let cursor_offset = event.position - bounds.origin; let drag = (drag_listener)(drag_value.as_ref(), cx); cx.active_drag = Some(AnyDrag { @@ -1384,14 +1393,14 @@ impl Interactivity { } } - let active_state = element_state + let clicked_state = element_state .clicked_state .get_or_insert_with(Default::default) .clone(); - if active_state.borrow().is_clicked() { + if clicked_state.borrow().is_clicked() { cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| { if phase == DispatchPhase::Capture { - *active_state.borrow_mut() = ElementClickedState::default(); + *clicked_state.borrow_mut() = ElementClickedState::default(); cx.notify(); } }); @@ -1407,7 +1416,7 @@ impl Interactivity { .map_or(false, |bounds| bounds.contains(&down.position)); let element = interactive_bounds.visibly_contains(&down.position, cx); if group || element { - *active_state.borrow_mut() = ElementClickedState { group, element }; + *clicked_state.borrow_mut() = ElementClickedState { group, element }; cx.notify(); } } From 229b5aa8f79976520be4883bfb01859f5e821e36 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 10:57:15 -0500 Subject: [PATCH 187/644] Style links in terminal (#3736) This PR styles links in the terminal using the colors from the theme. Release Notes: - N/A --- crates/terminal_view2/src/terminal_element.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index 07910896f3..f30c1cf1bc 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -395,13 +395,13 @@ impl TerminalElement { let theme = cx.theme().clone(); let link_style = HighlightStyle { - color: Some(gpui::blue()), + color: Some(theme.colors().link_text_hover), font_weight: None, font_style: None, background_color: None, underline: Some(UnderlineStyle { thickness: px(1.0), - color: Some(gpui::red()), + color: Some(theme.colors().link_text_hover), wavy: false, }), fade_out: None, From 64925231b0b3a6a40da37fd8d9b124bc3a6abaad Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 14 Dec 2023 15:20:49 +0200 Subject: [PATCH 188/644] Create a new crate --- Cargo.lock | 23 + Cargo.toml | 1 + crates/language_tools2/Cargo.toml | 33 + crates/language_tools2/src/language_tools.rs | 15 + crates/language_tools2/src/lsp_log.rs | 1023 +++++++++++++++++ crates/language_tools2/src/lsp_log_tests.rs | 109 ++ .../language_tools2/src/syntax_tree_view.rs | 677 +++++++++++ 7 files changed, 1881 insertions(+) create mode 100644 crates/language_tools2/Cargo.toml create mode 100644 crates/language_tools2/src/language_tools.rs create mode 100644 crates/language_tools2/src/lsp_log.rs create mode 100644 crates/language_tools2/src/lsp_log_tests.rs create mode 100644 crates/language_tools2/src/syntax_tree_view.rs diff --git a/Cargo.lock b/Cargo.lock index cb0d54022f..4f418a1813 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4990,6 +4990,29 @@ dependencies = [ "workspace", ] +[[package]] +name = "language_tools2" +version = "0.1.0" +dependencies = [ + "anyhow", + "client2", + "collections", + "editor2", + "env_logger 0.9.3", + "futures 0.3.28", + "gpui2", + "language2", + "lsp2", + "project2", + "serde", + "settings2", + "theme2", + "tree-sitter", + "unindent", + "util", + "workspace2", +] + [[package]] name = "lazy_static" version = "1.4.0" diff --git a/Cargo.toml b/Cargo.toml index 3b453527b8..42432a8a2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ members = [ "crates/language_selector", "crates/language_selector2", "crates/language_tools", + "crates/language_tools2", "crates/live_kit_client", "crates/live_kit_server", "crates/lsp", diff --git a/crates/language_tools2/Cargo.toml b/crates/language_tools2/Cargo.toml new file mode 100644 index 0000000000..ca3ede2ef9 --- /dev/null +++ b/crates/language_tools2/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "language_tools2" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +path = "src/language_tools.rs" +doctest = false + +[dependencies] +collections = { path = "../collections" } +editor = { package = "editor2", path = "../editor2" } +settings = { package = "settings2", path = "../settings2" } +theme = { package = "theme2", path = "../theme2" } +language = { package = "language2", path = "../language2" } +project = { package = "project2", path = "../project2" } +workspace = { package = "workspace2", path = "../workspace2" } +gpui = { package = "gpui2", path = "../gpui2" } +util = { path = "../util" } +lsp = { package = "lsp2", path = "../lsp2" } +futures.workspace = true +serde.workspace = true +anyhow.workspace = true +tree-sitter.workspace = true + +[dev-dependencies] +client = { package = "client2", path = "../client2", features = ["test-support"] } +editor = { package = "editor2", path = "../editor2", features = ["test-support"] } +gpui = { package = "gpui2", path = "../gpui2", features = ["test-support"] } +util = { path = "../util", features = ["test-support"] } +env_logger.workspace = true +unindent.workspace = true diff --git a/crates/language_tools2/src/language_tools.rs b/crates/language_tools2/src/language_tools.rs new file mode 100644 index 0000000000..0a1f31f03f --- /dev/null +++ b/crates/language_tools2/src/language_tools.rs @@ -0,0 +1,15 @@ +mod lsp_log; +mod syntax_tree_view; + +#[cfg(test)] +mod lsp_log_tests; + +use gpui::AppContext; + +pub use lsp_log::{LogStore, LspLogToolbarItemView, LspLogView}; +pub use syntax_tree_view::{SyntaxTreeToolbarItemView, SyntaxTreeView}; + +pub fn init(cx: &mut AppContext) { + lsp_log::init(cx); + syntax_tree_view::init(cx); +} diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs new file mode 100644 index 0000000000..9f27c62a04 --- /dev/null +++ b/crates/language_tools2/src/lsp_log.rs @@ -0,0 +1,1023 @@ +use collections::{HashMap, VecDeque}; +use editor::{Editor, MoveToEnd}; +use futures::{channel::mpsc, StreamExt}; +use gpui::{ + actions, + elements::{ + AnchorCorner, ChildView, Empty, Flex, Label, MouseEventHandler, Overlay, OverlayFitMode, + ParentElement, Stack, + }, + platform::{CursorStyle, MouseButton}, + AnyElement, AppContext, Element, Entity, Model, ModelContext, Subscription, View, View, + ViewContext, WeakModel, +}; +use language::{LanguageServerId, LanguageServerName}; +use lsp::IoKind; +use project::{search::SearchQuery, Project}; +use std::{borrow::Cow, sync::Arc}; +use theme::{ui, Theme}; +use workspace::{ + item::{Item, ItemHandle}, + searchable::{SearchableItem, SearchableItemHandle}, + ToolbarItemLocation, ToolbarItemView, Workspace, WorkspaceCreated, +}; + +const SEND_LINE: &str = "// Send:"; +const RECEIVE_LINE: &str = "// Receive:"; +const MAX_STORED_LOG_ENTRIES: usize = 2000; + +pub struct LogStore { + projects: HashMap, ProjectState>, + io_tx: mpsc::UnboundedSender<(WeakModel, LanguageServerId, IoKind, String)>, +} + +struct ProjectState { + servers: HashMap, + _subscriptions: [gpui::Subscription; 2], +} + +struct LanguageServerState { + log_messages: VecDeque, + rpc_state: Option, + _io_logs_subscription: Option, + _lsp_logs_subscription: Option, +} + +struct LanguageServerRpcState { + rpc_messages: VecDeque, + last_message_kind: Option, +} + +pub struct LspLogView { + pub(crate) editor: View, + editor_subscription: Subscription, + log_store: Model, + current_server_id: Option, + is_showing_rpc_trace: bool, + project: Model, + _log_store_subscriptions: Vec, +} + +pub struct LspLogToolbarItemView { + log_view: Option>, + _log_view_subscription: Option, + menu_open: bool, +} + +#[derive(Copy, Clone, PartialEq, Eq)] +enum MessageKind { + Send, + Receive, +} + +#[derive(Clone, Debug, PartialEq)] +pub(crate) struct LogMenuItem { + pub server_id: LanguageServerId, + pub server_name: LanguageServerName, + pub worktree_root_name: String, + pub rpc_trace_enabled: bool, + pub rpc_trace_selected: bool, + pub logs_selected: bool, +} + +actions!(debug, [OpenLanguageServerLogs]); + +pub fn init(cx: &mut AppContext) { + let log_store = cx.add_model(|cx| LogStore::new(cx)); + + cx.subscribe_global::({ + let log_store = log_store.clone(); + move |event, cx| { + let workspace = &event.0; + if let Some(workspace) = workspace.upgrade(cx) { + let project = workspace.read(cx).project().clone(); + if project.read(cx).is_local() { + log_store.update(cx, |store, cx| { + store.add_project(&project, cx); + }); + } + } + } + }) + .detach(); + + cx.add_action( + move |workspace: &mut Workspace, _: &OpenLanguageServerLogs, cx: _| { + let project = workspace.project().read(cx); + if project.is_local() { + workspace.add_item( + Box::new(cx.add_view(|cx| { + LspLogView::new(workspace.project().clone(), log_store.clone(), cx) + })), + cx, + ); + } + }, + ); +} + +impl LogStore { + pub fn new(cx: &mut ModelContext) -> Self { + let (io_tx, mut io_rx) = mpsc::unbounded(); + let this = Self { + projects: HashMap::default(), + io_tx, + }; + cx.spawn_weak(|this, mut cx| async move { + while let Some((project, server_id, io_kind, message)) = io_rx.next().await { + if let Some(this) = this.upgrade(&cx) { + this.update(&mut cx, |this, cx| { + this.on_io(project, server_id, io_kind, &message, cx); + }); + } + } + anyhow::Ok(()) + }) + .detach(); + this + } + + pub fn add_project(&mut self, project: &Model, cx: &mut ModelContext) { + let weak_project = project.downgrade(); + self.projects.insert( + weak_project, + ProjectState { + servers: HashMap::default(), + _subscriptions: [ + cx.observe_release(&project, move |this, _, _| { + this.projects.remove(&weak_project); + }), + cx.subscribe(project, |this, project, event, cx| match event { + project::Event::LanguageServerAdded(id) => { + this.add_language_server(&project, *id, cx); + } + project::Event::LanguageServerRemoved(id) => { + this.remove_language_server(&project, *id, cx); + } + project::Event::LanguageServerLog(id, message) => { + this.add_language_server_log(&project, *id, message, cx); + } + _ => {} + }), + ], + }, + ); + } + + fn add_language_server( + &mut self, + project: &Model, + id: LanguageServerId, + cx: &mut ModelContext, + ) -> Option<&mut LanguageServerState> { + let project_state = self.projects.get_mut(&project.downgrade())?; + let server_state = project_state.servers.entry(id).or_insert_with(|| { + cx.notify(); + LanguageServerState { + rpc_state: None, + log_messages: VecDeque::with_capacity(MAX_STORED_LOG_ENTRIES), + _io_logs_subscription: None, + _lsp_logs_subscription: None, + } + }); + + let server = project.read(cx).language_server_for_id(id); + if let Some(server) = server.as_deref() { + if server.has_notification_handler::() { + // Another event wants to re-add the server that was already added and subscribed to, avoid doing it again. + return Some(server_state); + } + } + + let weak_project = project.downgrade(); + let io_tx = self.io_tx.clone(); + server_state._io_logs_subscription = server.as_ref().map(|server| { + server.on_io(move |io_kind, message| { + io_tx + .unbounded_send((weak_project, id, io_kind, message.to_string())) + .ok(); + }) + }); + let this = cx.weak_handle(); + let weak_project = project.downgrade(); + server_state._lsp_logs_subscription = server.map(|server| { + let server_id = server.server_id(); + server.on_notification::({ + move |params, mut cx| { + if let Some((project, this)) = + weak_project.upgrade(&mut cx).zip(this.upgrade(&mut cx)) + { + this.update(&mut cx, |this, cx| { + this.add_language_server_log(&project, server_id, ¶ms.message, cx); + }); + } + } + }) + }); + Some(server_state) + } + + fn add_language_server_log( + &mut self, + project: &Model, + id: LanguageServerId, + message: &str, + cx: &mut ModelContext, + ) -> Option<()> { + let language_server_state = match self + .projects + .get_mut(&project.downgrade())? + .servers + .get_mut(&id) + { + Some(existing_state) => existing_state, + None => self.add_language_server(&project, id, cx)?, + }; + + let log_lines = &mut language_server_state.log_messages; + while log_lines.len() >= MAX_STORED_LOG_ENTRIES { + log_lines.pop_front(); + } + let message = message.trim(); + log_lines.push_back(message.to_string()); + cx.emit(Event::NewServerLogEntry { + id, + entry: message.to_string(), + is_rpc: false, + }); + cx.notify(); + Some(()) + } + + fn remove_language_server( + &mut self, + project: &Model, + id: LanguageServerId, + cx: &mut ModelContext, + ) -> Option<()> { + let project_state = self.projects.get_mut(&project.downgrade())?; + project_state.servers.remove(&id); + cx.notify(); + Some(()) + } + + fn server_logs( + &self, + project: &Model, + server_id: LanguageServerId, + ) -> Option<&VecDeque> { + let weak_project = project.downgrade(); + let project_state = self.projects.get(&weak_project)?; + let server_state = project_state.servers.get(&server_id)?; + Some(&server_state.log_messages) + } + + fn enable_rpc_trace_for_language_server( + &mut self, + project: &Model, + server_id: LanguageServerId, + ) -> Option<&mut LanguageServerRpcState> { + let weak_project = project.downgrade(); + let project_state = self.projects.get_mut(&weak_project)?; + let server_state = project_state.servers.get_mut(&server_id)?; + let rpc_state = server_state + .rpc_state + .get_or_insert_with(|| LanguageServerRpcState { + rpc_messages: VecDeque::with_capacity(MAX_STORED_LOG_ENTRIES), + last_message_kind: None, + }); + Some(rpc_state) + } + + pub fn disable_rpc_trace_for_language_server( + &mut self, + project: &Model, + server_id: LanguageServerId, + _: &mut ModelContext, + ) -> Option<()> { + let project = project.downgrade(); + let project_state = self.projects.get_mut(&project)?; + let server_state = project_state.servers.get_mut(&server_id)?; + server_state.rpc_state.take(); + Some(()) + } + + fn on_io( + &mut self, + project: WeakModel, + language_server_id: LanguageServerId, + io_kind: IoKind, + message: &str, + cx: &mut ModelContext, + ) -> Option<()> { + let is_received = match io_kind { + IoKind::StdOut => true, + IoKind::StdIn => false, + IoKind::StdErr => { + let project = project.upgrade(cx)?; + let message = format!("stderr: {}", message.trim()); + self.add_language_server_log(&project, language_server_id, &message, cx); + return Some(()); + } + }; + + let state = self + .projects + .get_mut(&project)? + .servers + .get_mut(&language_server_id)? + .rpc_state + .as_mut()?; + let kind = if is_received { + MessageKind::Receive + } else { + MessageKind::Send + }; + + let rpc_log_lines = &mut state.rpc_messages; + if state.last_message_kind != Some(kind) { + let line_before_message = match kind { + MessageKind::Send => SEND_LINE, + MessageKind::Receive => RECEIVE_LINE, + }; + rpc_log_lines.push_back(line_before_message.to_string()); + cx.emit(Event::NewServerLogEntry { + id: language_server_id, + entry: line_before_message.to_string(), + is_rpc: true, + }); + } + + while rpc_log_lines.len() >= MAX_STORED_LOG_ENTRIES { + rpc_log_lines.pop_front(); + } + let message = message.trim(); + rpc_log_lines.push_back(message.to_string()); + cx.emit(Event::NewServerLogEntry { + id: language_server_id, + entry: message.to_string(), + is_rpc: true, + }); + cx.notify(); + Some(()) + } +} + +impl LspLogView { + pub fn new( + project: Model, + log_store: Model, + cx: &mut ViewContext, + ) -> Self { + let server_id = log_store + .read(cx) + .projects + .get(&project.downgrade()) + .and_then(|project| project.servers.keys().copied().next()); + let model_changes_subscription = cx.observe(&log_store, |this, store, cx| { + (|| -> Option<()> { + let project_state = store.read(cx).projects.get(&this.project.downgrade())?; + if let Some(current_lsp) = this.current_server_id { + if !project_state.servers.contains_key(¤t_lsp) { + if let Some(server) = project_state.servers.iter().next() { + if this.is_showing_rpc_trace { + this.show_rpc_trace_for_server(*server.0, cx) + } else { + this.show_logs_for_server(*server.0, cx) + } + } else { + this.current_server_id = None; + this.editor.update(cx, |editor, cx| { + editor.set_read_only(false); + editor.clear(cx); + editor.set_read_only(true); + }); + cx.notify(); + } + } + } else { + if let Some(server) = project_state.servers.iter().next() { + if this.is_showing_rpc_trace { + this.show_rpc_trace_for_server(*server.0, cx) + } else { + this.show_logs_for_server(*server.0, cx) + } + } + } + + Some(()) + })(); + + cx.notify(); + }); + let events_subscriptions = cx.subscribe(&log_store, |log_view, _, e, cx| match e { + Event::NewServerLogEntry { id, entry, is_rpc } => { + if log_view.current_server_id == Some(*id) { + if (*is_rpc && log_view.is_showing_rpc_trace) + || (!*is_rpc && !log_view.is_showing_rpc_trace) + { + log_view.editor.update(cx, |editor, cx| { + editor.set_read_only(false); + editor.handle_input(entry.trim(), cx); + editor.handle_input("\n", cx); + editor.set_read_only(true); + }); + } + } + } + }); + let (editor, editor_subscription) = Self::editor_for_logs(String::new(), cx); + let mut this = Self { + editor, + editor_subscription, + project, + log_store, + current_server_id: None, + is_showing_rpc_trace: false, + _log_store_subscriptions: vec![model_changes_subscription, events_subscriptions], + }; + if let Some(server_id) = server_id { + this.show_logs_for_server(server_id, cx); + } + this + } + + fn editor_for_logs( + log_contents: String, + cx: &mut ViewContext, + ) -> (View, Subscription) { + let editor = cx.add_view(|cx| { + let mut editor = Editor::multi_line(None, cx); + editor.set_text(log_contents, cx); + editor.move_to_end(&MoveToEnd, cx); + editor.set_read_only(true); + editor + }); + let editor_subscription = cx.subscribe(&editor, |_, _, event, cx| cx.emit(event.clone())); + (editor, editor_subscription) + } + + pub(crate) fn menu_items<'a>(&'a self, cx: &'a AppContext) -> Option> { + let log_store = self.log_store.read(cx); + let state = log_store.projects.get(&self.project.downgrade())?; + let mut rows = self + .project + .read(cx) + .language_servers() + .filter_map(|(server_id, language_server_name, worktree_id)| { + let worktree = self.project.read(cx).worktree_for_id(worktree_id, cx)?; + let state = state.servers.get(&server_id)?; + Some(LogMenuItem { + server_id, + server_name: language_server_name, + worktree_root_name: worktree.read(cx).root_name().to_string(), + rpc_trace_enabled: state.rpc_state.is_some(), + rpc_trace_selected: self.is_showing_rpc_trace + && self.current_server_id == Some(server_id), + logs_selected: !self.is_showing_rpc_trace + && self.current_server_id == Some(server_id), + }) + }) + .chain( + self.project + .read(cx) + .supplementary_language_servers() + .filter_map(|(&server_id, (name, _))| { + let state = state.servers.get(&server_id)?; + Some(LogMenuItem { + server_id, + server_name: name.clone(), + worktree_root_name: "supplementary".to_string(), + rpc_trace_enabled: state.rpc_state.is_some(), + rpc_trace_selected: self.is_showing_rpc_trace + && self.current_server_id == Some(server_id), + logs_selected: !self.is_showing_rpc_trace + && self.current_server_id == Some(server_id), + }) + }), + ) + .collect::>(); + rows.sort_by_key(|row| row.server_id); + rows.dedup_by_key(|row| row.server_id); + Some(rows) + } + + fn show_logs_for_server(&mut self, server_id: LanguageServerId, cx: &mut ViewContext) { + let log_contents = self + .log_store + .read(cx) + .server_logs(&self.project, server_id) + .map(log_contents); + if let Some(log_contents) = log_contents { + self.current_server_id = Some(server_id); + self.is_showing_rpc_trace = false; + let (editor, editor_subscription) = Self::editor_for_logs(log_contents, cx); + self.editor = editor; + self.editor_subscription = editor_subscription; + cx.notify(); + } + } + + fn show_rpc_trace_for_server( + &mut self, + server_id: LanguageServerId, + cx: &mut ViewContext, + ) { + let rpc_log = self.log_store.update(cx, |log_store, _| { + log_store + .enable_rpc_trace_for_language_server(&self.project, server_id) + .map(|state| log_contents(&state.rpc_messages)) + }); + if let Some(rpc_log) = rpc_log { + self.current_server_id = Some(server_id); + self.is_showing_rpc_trace = true; + let (editor, editor_subscription) = Self::editor_for_logs(rpc_log, cx); + let language = self.project.read(cx).languages().language_for_name("JSON"); + editor + .read(cx) + .buffer() + .read(cx) + .as_singleton() + .expect("log buffer should be a singleton") + .update(cx, |_, cx| { + cx.spawn_weak({ + let buffer = cx.handle(); + |_, mut cx| async move { + let language = language.await.ok(); + buffer.update(&mut cx, |buffer, cx| { + buffer.set_language(language, cx); + }); + } + }) + .detach(); + }); + + self.editor = editor; + self.editor_subscription = editor_subscription; + cx.notify(); + } + } + + fn toggle_rpc_trace_for_server( + &mut self, + server_id: LanguageServerId, + enabled: bool, + cx: &mut ViewContext, + ) { + self.log_store.update(cx, |log_store, cx| { + if enabled { + log_store.enable_rpc_trace_for_language_server(&self.project, server_id); + } else { + log_store.disable_rpc_trace_for_language_server(&self.project, server_id, cx); + } + }); + if !enabled && Some(server_id) == self.current_server_id { + self.show_logs_for_server(server_id, cx); + cx.notify(); + } + } +} + +fn log_contents(lines: &VecDeque) -> String { + let (a, b) = lines.as_slices(); + let log_contents = a.join("\n"); + if b.is_empty() { + log_contents + } else { + log_contents + "\n" + &b.join("\n") + } +} + +impl View for LspLogView { + fn ui_name() -> &'static str { + "LspLogView" + } + + fn render(&mut self, cx: &mut ViewContext) -> AnyElement { + ChildView::new(&self.editor, cx).into_any() + } + + fn focus_in(&mut self, _: gpui::AnyView, cx: &mut ViewContext) { + if cx.is_self_focused() { + cx.focus(&self.editor); + } + } +} + +impl Item for LspLogView { + fn tab_content( + &self, + _: Option, + style: &theme::Tab, + _: &AppContext, + ) -> AnyElement { + Label::new("LSP Logs", style.label.clone()).into_any() + } + + fn as_searchable(&self, handle: &View) -> Option> { + Some(Box::new(handle.clone())) + } +} + +impl SearchableItem for LspLogView { + type Match = ::Match; + + fn to_search_event( + &mut self, + event: &Self::Event, + cx: &mut ViewContext, + ) -> Option { + self.editor + .update(cx, |editor, cx| editor.to_search_event(event, cx)) + } + + fn clear_matches(&mut self, cx: &mut ViewContext) { + self.editor.update(cx, |e, cx| e.clear_matches(cx)) + } + + fn update_matches(&mut self, matches: Vec, cx: &mut ViewContext) { + self.editor + .update(cx, |e, cx| e.update_matches(matches, cx)) + } + + fn query_suggestion(&mut self, cx: &mut ViewContext) -> String { + self.editor.update(cx, |e, cx| e.query_suggestion(cx)) + } + + fn activate_match( + &mut self, + index: usize, + matches: Vec, + cx: &mut ViewContext, + ) { + self.editor + .update(cx, |e, cx| e.activate_match(index, matches, cx)) + } + + fn select_matches(&mut self, matches: Vec, cx: &mut ViewContext) { + self.editor + .update(cx, |e, cx| e.select_matches(matches, cx)) + } + + fn find_matches( + &mut self, + query: Arc, + cx: &mut ViewContext, + ) -> gpui::Task> { + self.editor.update(cx, |e, cx| e.find_matches(query, cx)) + } + + fn replace(&mut self, _: &Self::Match, _: &SearchQuery, _: &mut ViewContext) { + // Since LSP Log is read-only, it doesn't make sense to support replace operation. + } + fn supported_options() -> workspace::searchable::SearchOptions { + workspace::searchable::SearchOptions { + case: true, + word: true, + regex: true, + // LSP log is read-only. + replacement: false, + } + } + fn active_match_index( + &mut self, + matches: Vec, + cx: &mut ViewContext, + ) -> Option { + self.editor + .update(cx, |e, cx| e.active_match_index(matches, cx)) + } +} + +impl ToolbarItemView for LspLogToolbarItemView { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn ItemHandle>, + cx: &mut ViewContext, + ) -> workspace::ToolbarItemLocation { + self.menu_open = false; + if let Some(item) = active_pane_item { + if let Some(log_view) = item.downcast::() { + self.log_view = Some(log_view.clone()); + self._log_view_subscription = Some(cx.observe(&log_view, |_, _, cx| { + cx.notify(); + })); + return ToolbarItemLocation::PrimaryLeft { + flex: Some((1., false)), + }; + } + } + self.log_view = None; + self._log_view_subscription = None; + ToolbarItemLocation::Hidden + } +} + +impl View for LspLogToolbarItemView { + fn ui_name() -> &'static str { + "LspLogView" + } + + fn render(&mut self, cx: &mut ViewContext) -> AnyElement { + let theme = theme::current(cx).clone(); + let Some(log_view) = self.log_view.as_ref() else { + return Empty::new().into_any(); + }; + let (menu_rows, current_server_id) = log_view.update(cx, |log_view, cx| { + let menu_rows = log_view.menu_items(cx).unwrap_or_default(); + let current_server_id = log_view.current_server_id; + (menu_rows, current_server_id) + }); + + let current_server = current_server_id.and_then(|current_server_id| { + if let Ok(ix) = menu_rows.binary_search_by_key(¤t_server_id, |e| e.server_id) { + Some(menu_rows[ix].clone()) + } else { + None + } + }); + let server_selected = current_server.is_some(); + + enum LspLogScroll {} + enum Menu {} + let lsp_menu = Stack::new() + .with_child(Self::render_language_server_menu_header( + current_server, + &theme, + cx, + )) + .with_children(if self.menu_open { + Some( + Overlay::new( + MouseEventHandler::new::(0, cx, move |_, cx| { + Flex::column() + .scrollable::(0, None, cx) + .with_children(menu_rows.into_iter().map(|row| { + Self::render_language_server_menu_item( + row.server_id, + row.server_name, + &row.worktree_root_name, + row.rpc_trace_enabled, + row.logs_selected, + row.rpc_trace_selected, + &theme, + cx, + ) + })) + .contained() + .with_style(theme.toolbar_dropdown_menu.container) + .constrained() + .with_width(400.) + .with_height(400.) + }) + .on_down_out(MouseButton::Left, |_, this, cx| { + this.menu_open = false; + cx.notify() + }), + ) + .with_hoverable(true) + .with_fit_mode(OverlayFitMode::SwitchAnchor) + .with_anchor_corner(AnchorCorner::TopLeft) + .with_z_index(999) + .aligned() + .bottom() + .left(), + ) + } else { + None + }) + .aligned() + .left() + .clipped(); + + enum LspCleanupButton {} + let log_cleanup_button = + MouseEventHandler::new::(1, cx, |state, cx| { + let theme = theme::current(cx).clone(); + let style = theme + .workspace + .toolbar + .toggleable_text_tool + .in_state(server_selected) + .style_for(state); + Label::new("Clear", style.text.clone()) + .aligned() + .contained() + .with_style(style.container) + .constrained() + .with_height(theme.toolbar_dropdown_menu.row_height / 6.0 * 5.0) + }) + .on_click(MouseButton::Left, move |_, this, cx| { + if let Some(log_view) = this.log_view.as_ref() { + log_view.update(cx, |log_view, cx| { + log_view.editor.update(cx, |editor, cx| { + editor.set_read_only(false); + editor.clear(cx); + editor.set_read_only(true); + }); + }) + } + }) + .with_cursor_style(CursorStyle::PointingHand) + .aligned() + .right(); + + Flex::row() + .with_child(lsp_menu) + .with_child(log_cleanup_button) + .contained() + .aligned() + .left() + .into_any_named("lsp log controls") + } +} + +const RPC_MESSAGES: &str = "RPC Messages"; +const SERVER_LOGS: &str = "Server Logs"; + +impl LspLogToolbarItemView { + pub fn new() -> Self { + Self { + menu_open: false, + log_view: None, + _log_view_subscription: None, + } + } + + fn toggle_menu(&mut self, cx: &mut ViewContext) { + self.menu_open = !self.menu_open; + cx.notify(); + } + + fn toggle_logging_for_server( + &mut self, + id: LanguageServerId, + enabled: bool, + cx: &mut ViewContext, + ) { + if let Some(log_view) = &self.log_view { + log_view.update(cx, |log_view, cx| { + log_view.toggle_rpc_trace_for_server(id, enabled, cx); + if !enabled && Some(id) == log_view.current_server_id { + log_view.show_logs_for_server(id, cx); + cx.notify(); + } + }); + } + cx.notify(); + } + + fn show_logs_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { + if let Some(log_view) = &self.log_view { + log_view.update(cx, |view, cx| view.show_logs_for_server(id, cx)); + self.menu_open = false; + cx.notify(); + } + } + + fn show_rpc_trace_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { + if let Some(log_view) = &self.log_view { + log_view.update(cx, |view, cx| view.show_rpc_trace_for_server(id, cx)); + self.menu_open = false; + cx.notify(); + } + } + + fn render_language_server_menu_header( + current_server: Option, + theme: &Arc, + cx: &mut ViewContext, + ) -> impl Element { + enum ToggleMenu {} + MouseEventHandler::new::(0, cx, move |state, _| { + let label: Cow = current_server + .and_then(|row| { + Some( + format!( + "{} ({}) - {}", + row.server_name.0, + row.worktree_root_name, + if row.rpc_trace_selected { + RPC_MESSAGES + } else { + SERVER_LOGS + }, + ) + .into(), + ) + }) + .unwrap_or_else(|| "No server selected".into()); + let style = theme.toolbar_dropdown_menu.header.style_for(state); + Label::new(label, style.text.clone()) + .contained() + .with_style(style.container) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, view, cx| { + view.toggle_menu(cx); + }) + } + + fn render_language_server_menu_item( + id: LanguageServerId, + name: LanguageServerName, + worktree_root_name: &str, + rpc_trace_enabled: bool, + logs_selected: bool, + rpc_trace_selected: bool, + theme: &Arc, + cx: &mut ViewContext, + ) -> impl Element { + enum ActivateLog {} + enum ActivateRpcTrace {} + enum LanguageServerCheckbox {} + + Flex::column() + .with_child({ + let style = &theme.toolbar_dropdown_menu.section_header; + Label::new( + format!("{} ({})", name.0, worktree_root_name), + style.text.clone(), + ) + .contained() + .with_style(style.container) + .constrained() + .with_height(theme.toolbar_dropdown_menu.row_height) + }) + .with_child( + MouseEventHandler::new::(id.0, cx, move |state, _| { + let style = theme + .toolbar_dropdown_menu + .item + .in_state(logs_selected) + .style_for(state); + Label::new(SERVER_LOGS, style.text.clone()) + .contained() + .with_style(style.container) + .constrained() + .with_height(theme.toolbar_dropdown_menu.row_height) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, view, cx| { + view.show_logs_for_server(id, cx); + }), + ) + .with_child( + MouseEventHandler::new::(id.0, cx, move |state, cx| { + let style = theme + .toolbar_dropdown_menu + .item + .in_state(rpc_trace_selected) + .style_for(state); + Flex::row() + .with_child( + Label::new(RPC_MESSAGES, style.text.clone()) + .constrained() + .with_height(theme.toolbar_dropdown_menu.row_height), + ) + .with_child( + ui::checkbox_with_label::( + Empty::new(), + &theme.welcome.checkbox, + rpc_trace_enabled, + id.0, + cx, + move |this, enabled, cx| { + this.toggle_logging_for_server(id, enabled, cx); + }, + ) + .flex_float(), + ) + .align_children_center() + .contained() + .with_style(style.container) + .constrained() + .with_height(theme.toolbar_dropdown_menu.row_height) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, view, cx| { + view.show_rpc_trace_for_server(id, cx); + }), + ) + } +} + +pub enum Event { + NewServerLogEntry { + id: LanguageServerId, + entry: String, + is_rpc: bool, + }, +} + +impl Entity for LogStore { + type Event = Event; +} + +impl Entity for LspLogView { + type Event = editor::Event; +} + +impl Entity for LspLogToolbarItemView { + type Event = (); +} diff --git a/crates/language_tools2/src/lsp_log_tests.rs b/crates/language_tools2/src/lsp_log_tests.rs new file mode 100644 index 0000000000..967e8a3382 --- /dev/null +++ b/crates/language_tools2/src/lsp_log_tests.rs @@ -0,0 +1,109 @@ +// todo!("TODO kb") +// use std::sync::Arc; + +// use crate::lsp_log::LogMenuItem; + +// use super::*; +// use futures::StreamExt; +// use gpui::{serde_json::json, TestAppContext}; +// use language::{tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig, LanguageServerName}; +// use project::{FakeFs, Project}; +// use settings::SettingsStore; + +// #[gpui::test] +// async fn test_lsp_logs(cx: &mut TestAppContext) { +// if std::env::var("RUST_LOG").is_ok() { +// env_logger::init(); +// } + +// init_test(cx); + +// let mut rust_language = Language::new( +// LanguageConfig { +// name: "Rust".into(), +// path_suffixes: vec!["rs".to_string()], +// ..Default::default() +// }, +// Some(tree_sitter_rust::language()), +// ); +// let mut fake_rust_servers = rust_language +// .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { +// name: "the-rust-language-server", +// ..Default::default() +// })) +// .await; + +// let fs = FakeFs::new(cx.background()); +// fs.insert_tree( +// "/the-root", +// json!({ +// "test.rs": "", +// "package.json": "", +// }), +// ) +// .await; +// let project = Project::test(fs.clone(), ["/the-root".as_ref()], cx).await; +// project.update(cx, |project, _| { +// project.languages().add(Arc::new(rust_language)); +// }); + +// let log_store = cx.add_model(|cx| LogStore::new(cx)); +// log_store.update(cx, |store, cx| store.add_project(&project, cx)); + +// let _rust_buffer = project +// .update(cx, |project, cx| { +// project.open_local_buffer("/the-root/test.rs", cx) +// }) +// .await +// .unwrap(); + +// let mut language_server = fake_rust_servers.next().await.unwrap(); +// language_server +// .receive_notification::() +// .await; + +// let log_view = cx +// .add_window(|cx| LspLogView::new(project.clone(), log_store.clone(), cx)) +// .root(cx); + +// language_server.notify::(lsp::LogMessageParams { +// message: "hello from the server".into(), +// typ: lsp::MessageType::INFO, +// }); +// cx.foreground().run_until_parked(); + +// log_view.read_with(cx, |view, cx| { +// assert_eq!( +// view.menu_items(cx).unwrap(), +// &[LogMenuItem { +// server_id: language_server.server.server_id(), +// server_name: LanguageServerName("the-rust-language-server".into()), +// worktree_root_name: project +// .read(cx) +// .worktrees(cx) +// .next() +// .unwrap() +// .read(cx) +// .root_name() +// .to_string(), +// rpc_trace_enabled: false, +// rpc_trace_selected: false, +// logs_selected: true, +// }] +// ); +// assert_eq!(view.editor.read(cx).text(cx), "hello from the server\n"); +// }); +// } + +// fn init_test(cx: &mut gpui::TestAppContext) { +// cx.foreground().forbid_parking(); + +// cx.update(|cx| { +// cx.set_global(SettingsStore::test(cx)); +// theme::init((), cx); +// language::init(cx); +// client::init_settings(cx); +// Project::init_settings(cx); +// editor::init_settings(cx); +// }); +// } diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs new file mode 100644 index 0000000000..7eaaab0130 --- /dev/null +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -0,0 +1,677 @@ +use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId}; +use gpui::{ + actions, + elements::{ + AnchorCorner, Empty, Flex, Label, MouseEventHandler, Overlay, OverlayFitMode, + ParentElement, ScrollTarget, Stack, UniformList, UniformListState, + }, + fonts::TextStyle, + AppContext, CursorStyle, Element, Entity, Model, MouseButton, View, View, ViewContext, + WeakView, +}; +use language::{Buffer, OwnedSyntaxLayerInfo, SyntaxLayerInfo}; +use std::{mem, ops::Range, sync::Arc}; +use theme::{Theme, ThemeSettings}; +use tree_sitter::{Node, TreeCursor}; +use workspace::{ + item::{Item, ItemHandle}, + ToolbarItemLocation, ToolbarItemView, Workspace, +}; + +actions!(debug, [OpenSyntaxTreeView]); + +pub fn init(cx: &mut AppContext) { + cx.add_action( + move |workspace: &mut Workspace, _: &OpenSyntaxTreeView, cx: _| { + let active_item = workspace.active_item(cx); + let workspace_handle = workspace.weak_handle(); + let syntax_tree_view = + cx.build_view(|cx| SyntaxTreeView::new(workspace_handle, active_item, cx)); + workspace.add_item(Box::new(syntax_tree_view), cx); + }, + ); +} + +pub struct SyntaxTreeView { + workspace_handle: WeakView, + editor: Option, + mouse_y: Option, + line_height: Option, + list_state: UniformListState, + selected_descendant_ix: Option, + hovered_descendant_ix: Option, +} + +pub struct SyntaxTreeToolbarItemView { + tree_view: Option>, + subscription: Option, + menu_open: bool, +} + +struct EditorState { + editor: ViewHandle, + active_buffer: Option, + _subscription: gpui::Subscription, +} + +#[derive(Clone)] +struct BufferState { + buffer: Model, + excerpt_id: ExcerptId, + active_layer: Option, +} + +impl SyntaxTreeView { + pub fn new( + workspace_handle: WeakView, + active_item: Option>, + cx: &mut ViewContext, + ) -> Self { + let mut this = Self { + workspace_handle: workspace_handle.clone(), + list_state: UniformListState::default(), + editor: None, + mouse_y: None, + line_height: None, + hovered_descendant_ix: None, + selected_descendant_ix: None, + }; + + this.workspace_updated(active_item, cx); + cx.observe( + &workspace_handle.upgrade(cx).unwrap(), + |this, workspace, cx| { + this.workspace_updated(workspace.read(cx).active_item(cx), cx); + }, + ) + .detach(); + + this + } + + fn workspace_updated( + &mut self, + active_item: Option>, + cx: &mut ViewContext, + ) { + if let Some(item) = active_item { + if item.id() != cx.view_id() { + if let Some(editor) = item.act_as::(cx) { + self.set_editor(editor, cx); + } + } + } + } + + fn set_editor(&mut self, editor: ViewHandle, cx: &mut ViewContext) { + if let Some(state) = &self.editor { + if state.editor == editor { + return; + } + editor.update(cx, |editor, cx| { + editor.clear_background_highlights::(cx) + }); + } + + let subscription = cx.subscribe(&editor, |this, _, event, cx| { + let did_reparse = match event { + editor::Event::Reparsed => true, + editor::Event::SelectionsChanged { .. } => false, + _ => return, + }; + this.editor_updated(did_reparse, cx); + }); + + self.editor = Some(EditorState { + editor, + _subscription: subscription, + active_buffer: None, + }); + self.editor_updated(true, cx); + } + + fn editor_updated(&mut self, did_reparse: bool, cx: &mut ViewContext) -> Option<()> { + // Find which excerpt the cursor is in, and the position within that excerpted buffer. + let editor_state = self.editor.as_mut()?; + let editor = &editor_state.editor.read(cx); + let selection_range = editor.selections.last::(cx).range(); + let multibuffer = editor.buffer().read(cx); + let (buffer, range, excerpt_id) = multibuffer + .range_to_buffer_ranges(selection_range, cx) + .pop()?; + + // If the cursor has moved into a different excerpt, retrieve a new syntax layer + // from that buffer. + let buffer_state = editor_state + .active_buffer + .get_or_insert_with(|| BufferState { + buffer: buffer.clone(), + excerpt_id, + active_layer: None, + }); + let mut prev_layer = None; + if did_reparse { + prev_layer = buffer_state.active_layer.take(); + } + if buffer_state.buffer != buffer || buffer_state.excerpt_id != buffer_state.excerpt_id { + buffer_state.buffer = buffer.clone(); + buffer_state.excerpt_id = excerpt_id; + buffer_state.active_layer = None; + } + + let layer = match &mut buffer_state.active_layer { + Some(layer) => layer, + None => { + let snapshot = buffer.read(cx).snapshot(); + let layer = if let Some(prev_layer) = prev_layer { + let prev_range = prev_layer.node().byte_range(); + snapshot + .syntax_layers() + .filter(|layer| layer.language == &prev_layer.language) + .min_by_key(|layer| { + let range = layer.node().byte_range(); + ((range.start as i64) - (prev_range.start as i64)).abs() + + ((range.end as i64) - (prev_range.end as i64)).abs() + })? + } else { + snapshot.syntax_layers().next()? + }; + buffer_state.active_layer.insert(layer.to_owned()) + } + }; + + // Within the active layer, find the syntax node under the cursor, + // and scroll to it. + let mut cursor = layer.node().walk(); + while cursor.goto_first_child_for_byte(range.start).is_some() { + if !range.is_empty() && cursor.node().end_byte() == range.start { + cursor.goto_next_sibling(); + } + } + + // Ascend to the smallest ancestor that contains the range. + loop { + let node_range = cursor.node().byte_range(); + if node_range.start <= range.start && node_range.end >= range.end { + break; + } + if !cursor.goto_parent() { + break; + } + } + + let descendant_ix = cursor.descendant_index(); + self.selected_descendant_ix = Some(descendant_ix); + self.list_state.scroll_to(ScrollTarget::Show(descendant_ix)); + + cx.notify(); + Some(()) + } + + fn handle_click(&mut self, y: f32, cx: &mut ViewContext) -> Option<()> { + let line_height = self.line_height?; + let ix = ((self.list_state.scroll_top() + y) / line_height) as usize; + + self.update_editor_with_range_for_descendant_ix(ix, cx, |editor, mut range, cx| { + // Put the cursor at the beginning of the node. + mem::swap(&mut range.start, &mut range.end); + + editor.change_selections(Some(Autoscroll::newest()), cx, |selections| { + selections.select_ranges(vec![range]); + }); + }); + Some(()) + } + + fn hover_state_changed(&mut self, cx: &mut ViewContext) { + if let Some((y, line_height)) = self.mouse_y.zip(self.line_height) { + let ix = ((self.list_state.scroll_top() + y) / line_height) as usize; + if self.hovered_descendant_ix != Some(ix) { + self.hovered_descendant_ix = Some(ix); + self.update_editor_with_range_for_descendant_ix(ix, cx, |editor, range, cx| { + editor.clear_background_highlights::(cx); + editor.highlight_background::( + vec![range], + |theme| theme.editor.document_highlight_write_background, + cx, + ); + }); + cx.notify(); + } + } + } + + fn update_editor_with_range_for_descendant_ix( + &self, + descendant_ix: usize, + cx: &mut ViewContext, + mut f: impl FnMut(&mut Editor, Range, &mut ViewContext), + ) -> Option<()> { + let editor_state = self.editor.as_ref()?; + let buffer_state = editor_state.active_buffer.as_ref()?; + let layer = buffer_state.active_layer.as_ref()?; + + // Find the node. + let mut cursor = layer.node().walk(); + cursor.goto_descendant(descendant_ix); + let node = cursor.node(); + let range = node.byte_range(); + + // Build a text anchor range. + let buffer = buffer_state.buffer.read(cx); + let range = buffer.anchor_before(range.start)..buffer.anchor_after(range.end); + + // Build a multibuffer anchor range. + let multibuffer = editor_state.editor.read(cx).buffer(); + let multibuffer = multibuffer.read(cx).snapshot(cx); + let excerpt_id = buffer_state.excerpt_id; + let range = multibuffer.anchor_in_excerpt(excerpt_id, range.start) + ..multibuffer.anchor_in_excerpt(excerpt_id, range.end); + + // Update the editor with the anchor range. + editor_state.editor.update(cx, |editor, cx| { + f(editor, range, cx); + }); + Some(()) + } + + fn render_node( + cursor: &TreeCursor, + depth: u32, + selected: bool, + hovered: bool, + list_hovered: bool, + style: &TextStyle, + editor_theme: &theme::Editor, + cx: &AppContext, + ) -> gpui::AnyElement { + let node = cursor.node(); + let mut range_style = style.clone(); + let em_width = style.em_width(cx.font_cache()); + let gutter_padding = (em_width * editor_theme.gutter_padding_factor).round(); + + range_style.color = editor_theme.line_number; + + let mut anonymous_node_style = style.clone(); + let string_color = editor_theme + .syntax + .highlights + .iter() + .find_map(|(name, style)| (name == "string").then(|| style.color)?); + let property_color = editor_theme + .syntax + .highlights + .iter() + .find_map(|(name, style)| (name == "property").then(|| style.color)?); + if let Some(color) = string_color { + anonymous_node_style.color = color; + } + + let mut row = Flex::row(); + if let Some(field_name) = cursor.field_name() { + let mut field_style = style.clone(); + if let Some(color) = property_color { + field_style.color = color; + } + + row.add_children([ + Label::new(field_name, field_style), + Label::new(": ", style.clone()), + ]); + } + + return row + .with_child( + if node.is_named() { + Label::new(node.kind(), style.clone()) + } else { + Label::new(format!("\"{}\"", node.kind()), anonymous_node_style) + } + .contained() + .with_margin_right(em_width), + ) + .with_child(Label::new(format_node_range(node), range_style)) + .contained() + .with_background_color(if selected { + editor_theme.selection.selection + } else if hovered && list_hovered { + editor_theme.active_line_background + } else { + Default::default() + }) + .with_padding_left(gutter_padding + depth as f32 * 18.0) + .into_any(); + } +} + +impl Entity for SyntaxTreeView { + type Event = (); +} + +impl View for SyntaxTreeView { + fn ui_name() -> &'static str { + "SyntaxTreeView" + } + + fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement { + let settings = settings::get::(cx); + let font_family_id = settings.buffer_font_family; + let font_family_name = cx.font_cache().family_name(font_family_id).unwrap(); + let font_properties = Default::default(); + let font_id = cx + .font_cache() + .select_font(font_family_id, &font_properties) + .unwrap(); + let font_size = settings.buffer_font_size(cx); + + let editor_theme = settings.theme.editor.clone(); + let style = TextStyle { + color: editor_theme.text_color, + font_family_name, + font_family_id, + font_id, + font_size, + font_properties: Default::default(), + underline: Default::default(), + soft_wrap: false, + }; + + let line_height = cx.font_cache().line_height(font_size); + if Some(line_height) != self.line_height { + self.line_height = Some(line_height); + self.hover_state_changed(cx); + } + + if let Some(layer) = self + .editor + .as_ref() + .and_then(|editor| editor.active_buffer.as_ref()) + .and_then(|buffer| buffer.active_layer.as_ref()) + { + let layer = layer.clone(); + let theme = editor_theme.clone(); + return MouseEventHandler::new::(0, cx, move |state, cx| { + let list_hovered = state.hovered(); + UniformList::new( + self.list_state.clone(), + layer.node().descendant_count(), + cx, + move |this, range, items, cx| { + let mut cursor = layer.node().walk(); + let mut descendant_ix = range.start as usize; + cursor.goto_descendant(descendant_ix); + let mut depth = cursor.depth(); + let mut visited_children = false; + while descendant_ix < range.end { + if visited_children { + if cursor.goto_next_sibling() { + visited_children = false; + } else if cursor.goto_parent() { + depth -= 1; + } else { + break; + } + } else { + items.push(Self::render_node( + &cursor, + depth, + Some(descendant_ix) == this.selected_descendant_ix, + Some(descendant_ix) == this.hovered_descendant_ix, + list_hovered, + &style, + &theme, + cx, + )); + descendant_ix += 1; + if cursor.goto_first_child() { + depth += 1; + } else { + visited_children = true; + } + } + } + }, + ) + }) + .on_move(move |event, this, cx| { + let y = event.position.y() - event.region.origin_y(); + this.mouse_y = Some(y); + this.hover_state_changed(cx); + }) + .on_click(MouseButton::Left, move |event, this, cx| { + let y = event.position.y() - event.region.origin_y(); + this.handle_click(y, cx); + }) + .contained() + .with_background_color(editor_theme.background) + .into_any(); + } + + Empty::new().into_any() + } +} + +impl Item for SyntaxTreeView { + fn tab_content( + &self, + _: Option, + style: &theme::Tab, + _: &AppContext, + ) -> gpui::AnyElement { + Label::new("Syntax Tree", style.label.clone()).into_any() + } + + fn clone_on_split( + &self, + _workspace_id: workspace::WorkspaceId, + cx: &mut ViewContext, + ) -> Option + where + Self: Sized, + { + let mut clone = Self::new(self.workspace_handle.clone(), None, cx); + if let Some(editor) = &self.editor { + clone.set_editor(editor.editor.clone(), cx) + } + Some(clone) + } +} + +impl SyntaxTreeToolbarItemView { + pub fn new() -> Self { + Self { + menu_open: false, + tree_view: None, + subscription: None, + } + } + + fn render_menu( + &mut self, + cx: &mut ViewContext<'_, '_, Self>, + ) -> Option> { + let theme = theme::current(cx).clone(); + let tree_view = self.tree_view.as_ref()?; + let tree_view = tree_view.read(cx); + + let editor_state = tree_view.editor.as_ref()?; + let buffer_state = editor_state.active_buffer.as_ref()?; + let active_layer = buffer_state.active_layer.clone()?; + let active_buffer = buffer_state.buffer.read(cx).snapshot(); + + enum Menu {} + + Some( + Stack::new() + .with_child(Self::render_header(&theme, &active_layer, cx)) + .with_children(self.menu_open.then(|| { + Overlay::new( + MouseEventHandler::new::(0, cx, move |_, cx| { + Flex::column() + .with_children(active_buffer.syntax_layers().enumerate().map( + |(ix, layer)| { + Self::render_menu_item(&theme, &active_layer, layer, ix, cx) + }, + )) + .contained() + .with_style(theme.toolbar_dropdown_menu.container) + .constrained() + .with_width(400.) + .with_height(400.) + }) + .on_down_out(MouseButton::Left, |_, this, cx| { + this.menu_open = false; + cx.notify() + }), + ) + .with_hoverable(true) + .with_fit_mode(OverlayFitMode::SwitchAnchor) + .with_anchor_corner(AnchorCorner::TopLeft) + .with_z_index(999) + .aligned() + .bottom() + .left() + })) + .aligned() + .left() + .clipped() + .into_any(), + ) + } + + fn toggle_menu(&mut self, cx: &mut ViewContext) { + self.menu_open = !self.menu_open; + cx.notify(); + } + + fn select_layer(&mut self, layer_ix: usize, cx: &mut ViewContext) -> Option<()> { + let tree_view = self.tree_view.as_ref()?; + tree_view.update(cx, |view, cx| { + let editor_state = view.editor.as_mut()?; + let buffer_state = editor_state.active_buffer.as_mut()?; + let snapshot = buffer_state.buffer.read(cx).snapshot(); + let layer = snapshot.syntax_layers().nth(layer_ix)?; + buffer_state.active_layer = Some(layer.to_owned()); + view.selected_descendant_ix = None; + self.menu_open = false; + cx.notify(); + Some(()) + }) + } + + fn render_header( + theme: &Arc, + active_layer: &OwnedSyntaxLayerInfo, + cx: &mut ViewContext, + ) -> impl Element { + enum ToggleMenu {} + MouseEventHandler::new::(0, cx, move |state, _| { + let style = theme.toolbar_dropdown_menu.header.style_for(state); + Flex::row() + .with_child( + Label::new(active_layer.language.name().to_string(), style.text.clone()) + .contained() + .with_margin_right(style.secondary_text_spacing), + ) + .with_child(Label::new( + format_node_range(active_layer.node()), + style + .secondary_text + .clone() + .unwrap_or_else(|| style.text.clone()), + )) + .contained() + .with_style(style.container) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, view, cx| { + view.toggle_menu(cx); + }) + } + + fn render_menu_item( + theme: &Arc, + active_layer: &OwnedSyntaxLayerInfo, + layer: SyntaxLayerInfo, + layer_ix: usize, + cx: &mut ViewContext, + ) -> impl Element { + enum ActivateLayer {} + MouseEventHandler::new::(layer_ix, cx, move |state, _| { + let is_selected = layer.node() == active_layer.node(); + let style = theme + .toolbar_dropdown_menu + .item + .in_state(is_selected) + .style_for(state); + Flex::row() + .with_child( + Label::new(layer.language.name().to_string(), style.text.clone()) + .contained() + .with_margin_right(style.secondary_text_spacing), + ) + .with_child(Label::new( + format_node_range(layer.node()), + style + .secondary_text + .clone() + .unwrap_or_else(|| style.text.clone()), + )) + .contained() + .with_style(style.container) + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, move |_, view, cx| { + view.select_layer(layer_ix, cx); + }) + } +} + +fn format_node_range(node: Node) -> String { + let start = node.start_position(); + let end = node.end_position(); + format!( + "[{}:{} - {}:{}]", + start.row + 1, + start.column + 1, + end.row + 1, + end.column + 1, + ) +} + +impl Entity for SyntaxTreeToolbarItemView { + type Event = (); +} + +impl View for SyntaxTreeToolbarItemView { + fn ui_name() -> &'static str { + "SyntaxTreeToolbarItemView" + } + + fn render(&mut self, cx: &mut ViewContext<'_, '_, Self>) -> gpui::AnyElement { + self.render_menu(cx) + .unwrap_or_else(|| Empty::new().into_any()) + } +} + +impl ToolbarItemView for SyntaxTreeToolbarItemView { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn ItemHandle>, + cx: &mut ViewContext, + ) -> workspace::ToolbarItemLocation { + self.menu_open = false; + if let Some(item) = active_pane_item { + if let Some(view) = item.downcast::() { + self.tree_view = Some(view.clone()); + self.subscription = Some(cx.observe(&view, |_, _, cx| cx.notify())); + return ToolbarItemLocation::PrimaryLeft { + flex: Some((1., false)), + }; + } + } + self.tree_view = None; + self.subscription = None; + ToolbarItemLocation::Hidden + } +} From 676a07270e24dfdce4c6445308efe5f694bbc0f7 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 11:17:02 +0200 Subject: [PATCH 189/644] First fixes --- crates/language_tools2/src/lsp_log.rs | 54 +++++--------- .../language_tools2/src/syntax_tree_view.rs | 73 ++++++++----------- 2 files changed, 51 insertions(+), 76 deletions(-) diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 9f27c62a04..6e433ba8a6 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -2,24 +2,19 @@ use collections::{HashMap, VecDeque}; use editor::{Editor, MoveToEnd}; use futures::{channel::mpsc, StreamExt}; use gpui::{ - actions, - elements::{ - AnchorCorner, ChildView, Empty, Flex, Label, MouseEventHandler, Overlay, OverlayFitMode, - ParentElement, Stack, - }, - platform::{CursorStyle, MouseButton}, - AnyElement, AppContext, Element, Entity, Model, ModelContext, Subscription, View, View, - ViewContext, WeakModel, + actions, AnchorCorner, AnyElement, AppContext, Context, CursorStyle, Element, Empty, Entity, + Model, ModelContext, MouseButton, Overlay, OverlayFitMode, Subscription, View, ViewContext, + VisualContext, WeakModel, }; use language::{LanguageServerId, LanguageServerName}; use lsp::IoKind; use project::{search::SearchQuery, Project}; use std::{borrow::Cow, sync::Arc}; -use theme::{ui, Theme}; +use theme::Theme; use workspace::{ item::{Item, ItemHandle}, searchable::{SearchableItem, SearchableItemHandle}, - ToolbarItemLocation, ToolbarItemView, Workspace, WorkspaceCreated, + ToolbarItemLocation, ToolbarItemView, Workspace, }; const SEND_LINE: &str = "// Send:"; @@ -83,37 +78,29 @@ pub(crate) struct LogMenuItem { actions!(debug, [OpenLanguageServerLogs]); pub fn init(cx: &mut AppContext) { - let log_store = cx.add_model(|cx| LogStore::new(cx)); + let log_store = cx.build_model(|cx| LogStore::new(cx)); - cx.subscribe_global::({ - let log_store = log_store.clone(); - move |event, cx| { - let workspace = &event.0; - if let Some(workspace) = workspace.upgrade(cx) { - let project = workspace.read(cx).project().clone(); - if project.read(cx).is_local() { - log_store.update(cx, |store, cx| { - store.add_project(&project, cx); - }); - } - } + cx.observe_new_views(|workspace: &mut Workspace, cx| { + let project = workspace.project(); + if project.read(cx).is_local() { + log_store.update(cx, |store, cx| { + store.add_project(&project, cx); + }); } - }) - .detach(); - cx.add_action( - move |workspace: &mut Workspace, _: &OpenLanguageServerLogs, cx: _| { + workspace.register_action(|workspace, _: &OpenLanguageServerLogs, cx| { let project = workspace.project().read(cx); if project.is_local() { workspace.add_item( - Box::new(cx.add_view(|cx| { + Box::new(cx.build_view(|cx| { LspLogView::new(workspace.project().clone(), log_store.clone(), cx) })), cx, ); } - }, - ); + }); + }) + .detach(); } impl LogStore { @@ -204,8 +191,7 @@ impl LogStore { let server_id = server.server_id(); server.on_notification::({ move |params, mut cx| { - if let Some((project, this)) = - weak_project.upgrade(&mut cx).zip(this.upgrade(&mut cx)) + if let Some((project, this)) = weak_project.upgrade().zip(this.upgrade(&mut cx)) { this.update(&mut cx, |this, cx| { this.add_language_server_log(&project, server_id, ¶ms.message, cx); @@ -314,7 +300,7 @@ impl LogStore { IoKind::StdOut => true, IoKind::StdIn => false, IoKind::StdErr => { - let project = project.upgrade(cx)?; + let project = project.upgrade()?; let message = format!("stderr: {}", message.trim()); self.add_language_server_log(&project, language_server_id, &message, cx); return Some(()); @@ -446,7 +432,7 @@ impl LspLogView { log_contents: String, cx: &mut ViewContext, ) -> (View, Subscription) { - let editor = cx.add_view(|cx| { + let editor = cx.build_view(|cx| { let mut editor = Editor::multi_line(None, cx); editor.set_text(log_contents, cx); editor.move_to_end(&MoveToEnd, cx); diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index 7eaaab0130..80ff211176 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -1,35 +1,32 @@ use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId}; use gpui::{ - actions, - elements::{ - AnchorCorner, Empty, Flex, Label, MouseEventHandler, Overlay, OverlayFitMode, - ParentElement, ScrollTarget, Stack, UniformList, UniformListState, - }, - fonts::TextStyle, - AppContext, CursorStyle, Element, Entity, Model, MouseButton, View, View, ViewContext, - WeakView, + actions, AnchorCorner, AppContext, CursorStyle, Div, Element, Empty, Entity, Focusable, Model, + MouseButton, Overlay, OverlayFitMode, ParentElement, Render, TextStyle, UniformList, + UniformListState, View, ViewContext, VisualContext, WeakView, }; use language::{Buffer, OwnedSyntaxLayerInfo, SyntaxLayerInfo}; use std::{mem, ops::Range, sync::Arc}; -use theme::{Theme, ThemeSettings}; +use theme::{ActiveTheme, Theme, ThemeSettings}; use tree_sitter::{Node, TreeCursor}; use workspace::{ item::{Item, ItemHandle}, + ui::v_stack, ToolbarItemLocation, ToolbarItemView, Workspace, }; actions!(debug, [OpenSyntaxTreeView]); pub fn init(cx: &mut AppContext) { - cx.add_action( - move |workspace: &mut Workspace, _: &OpenSyntaxTreeView, cx: _| { + cx.observe_new_views(|workspace: &mut Workspace, _| { + workspace.register_action(|workspace, _: &OpenSyntaxTreeView, cx| { let active_item = workspace.active_item(cx); let workspace_handle = workspace.weak_handle(); let syntax_tree_view = cx.build_view(|cx| SyntaxTreeView::new(workspace_handle, active_item, cx)); workspace.add_item(Box::new(syntax_tree_view), cx); - }, - ); + }); + }) + .detach(); } pub struct SyntaxTreeView { @@ -49,7 +46,7 @@ pub struct SyntaxTreeToolbarItemView { } struct EditorState { - editor: ViewHandle, + editor: View, active_buffer: Option, _subscription: gpui::Subscription, } @@ -79,7 +76,7 @@ impl SyntaxTreeView { this.workspace_updated(active_item, cx); cx.observe( - &workspace_handle.upgrade(cx).unwrap(), + &workspace_handle.upgrade().unwrap(), |this, workspace, cx| { this.workspace_updated(workspace.read(cx).active_item(cx), cx); }, @@ -95,7 +92,7 @@ impl SyntaxTreeView { cx: &mut ViewContext, ) { if let Some(item) = active_item { - if item.id() != cx.view_id() { + if item.item_id() != cx.entity_id() { if let Some(editor) = item.act_as::(cx) { self.set_editor(editor, cx); } @@ -103,7 +100,7 @@ impl SyntaxTreeView { } } - fn set_editor(&mut self, editor: ViewHandle, cx: &mut ViewContext) { + fn set_editor(&mut self, editor: View, cx: &mut ViewContext) { if let Some(state) = &self.editor { if state.editor == editor { return; @@ -115,8 +112,8 @@ impl SyntaxTreeView { let subscription = cx.subscribe(&editor, |this, _, event, cx| { let did_reparse = match event { - editor::Event::Reparsed => true, - editor::Event::SelectionsChanged { .. } => false, + editor::EditorEvent::Reparsed => true, + editor::EditorEvent::SelectionsChanged { .. } => false, _ => return, }; this.editor_updated(did_reparse, cx); @@ -490,7 +487,7 @@ impl SyntaxTreeToolbarItemView { &mut self, cx: &mut ViewContext<'_, '_, Self>, ) -> Option> { - let theme = theme::current(cx).clone(); + let theme = cx.theme().clone(); let tree_view = self.tree_view.as_ref()?; let tree_view = tree_view.read(cx); @@ -502,12 +499,12 @@ impl SyntaxTreeToolbarItemView { enum Menu {} Some( - Stack::new() - .with_child(Self::render_header(&theme, &active_layer, cx)) - .with_children(self.menu_open.then(|| { - Overlay::new( - MouseEventHandler::new::(0, cx, move |_, cx| { - Flex::column() + v_stack() + .child(Self::render_header(&theme, &active_layer, cx)) + .children(self.menu_open.then(|| { + overlay( + mouse_event_handler::(0, cx, move |_, cx| { + v_stack() .with_children(active_buffer.syntax_layers().enumerate().map( |(ix, layer)| { Self::render_menu_item(&theme, &active_layer, layer, ix, cx) @@ -525,16 +522,9 @@ impl SyntaxTreeToolbarItemView { }), ) .with_hoverable(true) - .with_fit_mode(OverlayFitMode::SwitchAnchor) - .with_anchor_corner(AnchorCorner::TopLeft) - .with_z_index(999) - .aligned() - .bottom() - .left() + .with_fit_content() + .into_any() })) - .aligned() - .left() - .clipped() .into_any(), ) } @@ -639,14 +629,13 @@ fn format_node_range(node: Node) -> String { ) } -impl Entity for SyntaxTreeToolbarItemView { - type Event = (); -} +impl Render for SyntaxTreeToolbarItemView { + type Element = Focusable
; -impl View for SyntaxTreeToolbarItemView { - fn ui_name() -> &'static str { - "SyntaxTreeToolbarItemView" - } + // todo!() + // fn ui_name() -> &'static str { + // "SyntaxTreeToolbarItemView" + // } fn render(&mut self, cx: &mut ViewContext<'_, '_, Self>) -> gpui::AnyElement { self.render_menu(cx) From 75074c329792d72ac53b2db0ae13c56e345d1466 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 15:32:09 +0200 Subject: [PATCH 190/644] Apply more fixes to the visual part --- Cargo.lock | 1 + crates/editor2/src/editor.rs | 13 +- crates/language_tools2/Cargo.toml | 1 + crates/language_tools2/src/lsp_log.rs | 388 ++++++++---------- .../language_tools2/src/syntax_tree_view.rs | 361 +++++++--------- 5 files changed, 335 insertions(+), 429 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f418a1813..7237ab6905 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5008,6 +5008,7 @@ dependencies = [ "settings2", "theme2", "tree-sitter", + "ui2", "unindent", "util", "workspace2", diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 58f8e857a9..81158c5351 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -1652,14 +1652,11 @@ impl Editor { Self::new(EditorMode::SingleLine, buffer, None, cx) } - // pub fn multi_line( - // field_editor_style: Option>, - // cx: &mut ViewContext, - // ) -> Self { - // let buffer = cx.build_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new())); - // let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); - // Self::new(EditorMode::Full, buffer, None, field_editor_style, cx) - // } + pub fn multi_line(cx: &mut ViewContext) -> Self { + let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new())); + let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); + Self::new(EditorMode::Full, buffer, None, cx) + } pub fn auto_height(max_lines: usize, cx: &mut ViewContext) -> Self { let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new())); diff --git a/crates/language_tools2/Cargo.toml b/crates/language_tools2/Cargo.toml index ca3ede2ef9..bf5202cda9 100644 --- a/crates/language_tools2/Cargo.toml +++ b/crates/language_tools2/Cargo.toml @@ -17,6 +17,7 @@ language = { package = "language2", path = "../language2" } project = { package = "project2", path = "../project2" } workspace = { package = "workspace2", path = "../workspace2" } gpui = { package = "gpui2", path = "../gpui2" } +ui = { package = "ui2", path = "../ui2" } util = { path = "../util" } lsp = { package = "lsp2", path = "../lsp2" } futures.workspace = true diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 6e433ba8a6..ca4f25e177 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -1,20 +1,22 @@ use collections::{HashMap, VecDeque}; -use editor::{Editor, MoveToEnd}; +use editor::{Editor, EditorElement, EditorEvent, MoveToEnd}; use futures::{channel::mpsc, StreamExt}; use gpui::{ - actions, AnchorCorner, AnyElement, AppContext, Context, CursorStyle, Element, Empty, Entity, - Model, ModelContext, MouseButton, Overlay, OverlayFitMode, Subscription, View, ViewContext, - VisualContext, WeakModel, + actions, div, overlay, red, AnchorCorner, AnyElement, AppContext, Context, CursorStyle, Div, + EventEmitter, FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ModelContext, + MouseButton, OverlayFitMode, ParentElement, Render, Styled, Subscription, View, ViewContext, + VisualContext, WeakModel, WindowContext, }; use language::{LanguageServerId, LanguageServerName}; use lsp::IoKind; use project::{search::SearchQuery, Project}; use std::{borrow::Cow, sync::Arc}; -use theme::Theme; +use theme::{ActiveTheme, Theme}; +use ui::{h_stack, v_stack, Label}; use workspace::{ item::{Item, ItemHandle}, - searchable::{SearchableItem, SearchableItemHandle}, - ToolbarItemLocation, ToolbarItemView, Workspace, + searchable::{SearchEvent, SearchableItem, SearchableItemHandle}, + ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace, }; const SEND_LINE: &str = "// Send:"; @@ -50,6 +52,7 @@ pub struct LspLogView { current_server_id: Option, is_showing_rpc_trace: bool, project: Model, + focus_handle: FocusHandle, _log_store_subscriptions: Vec, } @@ -110,9 +113,9 @@ impl LogStore { projects: HashMap::default(), io_tx, }; - cx.spawn_weak(|this, mut cx| async move { + cx.spawn(|this, mut cx| async move { while let Some((project, server_id, io_kind, message)) = io_rx.next().await { - if let Some(this) = this.upgrade(&cx) { + if let Some(this) = this.upgrade() { this.update(&mut cx, |this, cx| { this.on_io(project, server_id, io_kind, &message, cx); }); @@ -120,7 +123,7 @@ impl LogStore { } anyhow::Ok(()) }) - .detach(); + .detach_and_log_err(cx); this } @@ -131,7 +134,7 @@ impl LogStore { ProjectState { servers: HashMap::default(), _subscriptions: [ - cx.observe_release(&project, move |this, _, _| { + cx.observe_release(project, move |this, _, _| { this.projects.remove(&weak_project); }), cx.subscribe(project, |this, project, event, cx| match event { @@ -185,14 +188,13 @@ impl LogStore { .ok(); }) }); - let this = cx.weak_handle(); + let this = cx.handle().downgrade(); let weak_project = project.downgrade(); server_state._lsp_logs_subscription = server.map(|server| { let server_id = server.server_id(); server.on_notification::({ move |params, mut cx| { - if let Some((project, this)) = weak_project.upgrade().zip(this.upgrade(&mut cx)) - { + if let Some((project, this)) = weak_project.upgrade().zip(this.upgrade()) { this.update(&mut cx, |this, cx| { this.add_language_server_log(&project, server_id, ¶ms.message, cx); }); @@ -413,14 +415,25 @@ impl LspLogView { } }); let (editor, editor_subscription) = Self::editor_for_logs(String::new(), cx); + + let focus_handle = cx.focus_handle(); + let focus_subscription = cx.on_focus(&focus_handle, |log_view, cx| { + cx.focus_view(&log_view.editor); + }); + let mut this = Self { + focus_handle, editor, editor_subscription, project, log_store, current_server_id: None, is_showing_rpc_trace: false, - _log_store_subscriptions: vec![model_changes_subscription, events_subscriptions], + _log_store_subscriptions: vec![ + model_changes_subscription, + events_subscriptions, + focus_subscription, + ], }; if let Some(server_id) = server_id { this.show_logs_for_server(server_id, cx); @@ -433,13 +446,18 @@ impl LspLogView { cx: &mut ViewContext, ) -> (View, Subscription) { let editor = cx.build_view(|cx| { - let mut editor = Editor::multi_line(None, cx); + let mut editor = Editor::multi_line(cx); editor.set_text(log_contents, cx); editor.move_to_end(&MoveToEnd, cx); editor.set_read_only(true); editor }); - let editor_subscription = cx.subscribe(&editor, |_, _, event, cx| cx.emit(event.clone())); + let editor_subscription = cx.subscribe( + &editor, + |_, _, event: &EditorEvent, cx: &mut ViewContext<'_, LspLogView>| { + cx.emit(event.clone()) + }, + ); (editor, editor_subscription) } @@ -526,7 +544,7 @@ impl LspLogView { .as_singleton() .expect("log buffer should be a singleton") .update(cx, |_, cx| { - cx.spawn_weak({ + cx.spawn({ let buffer = cx.handle(); |_, mut cx| async move { let language = language.await.ok(); @@ -574,30 +592,34 @@ fn log_contents(lines: &VecDeque) -> String { } } -impl View for LspLogView { - fn ui_name() -> &'static str { - "LspLogView" - } +impl Render for LspLogView { + // todo!() + // fn ui_name() -> &'static str { + // "LspLogView" + // } - fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - ChildView::new(&self.editor, cx).into_any() - } + type Element = EditorElement; - fn focus_in(&mut self, _: gpui::AnyView, cx: &mut ViewContext) { - if cx.is_self_focused() { - cx.focus(&self.editor); - } + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + self.editor.update(cx, |editor, cx| editor.render(cx)) + } +} + +impl FocusableView for LspLogView { + fn focus_handle(&self, _: &AppContext) -> FocusHandle { + self.focus_handle.clone() } } impl Item for LspLogView { - fn tab_content( - &self, - _: Option, - style: &theme::Tab, - _: &AppContext, - ) -> AnyElement { - Label::new("LSP Logs", style.label.clone()).into_any() + type Event = EditorEvent; + + fn to_item_events(event: &Self::Event, f: impl FnMut(workspace::item::ItemEvent)) { + Editor::to_item_events(event, f) + } + + fn tab_content(&self, _: Option, _: bool, _: &WindowContext<'_>) -> AnyElement { + Label::new("LSP Logs").into_any_element() } fn as_searchable(&self, handle: &View) -> Option> { @@ -608,15 +630,6 @@ impl Item for LspLogView { impl SearchableItem for LspLogView { type Match = ::Match; - fn to_search_event( - &mut self, - event: &Self::Event, - cx: &mut ViewContext, - ) -> Option { - self.editor - .update(cx, |editor, cx| editor.to_search_event(event, cx)) - } - fn clear_matches(&mut self, cx: &mut ViewContext) { self.editor.update(cx, |e, cx| e.clear_matches(cx)) } @@ -675,6 +688,8 @@ impl SearchableItem for LspLogView { } } +impl EventEmitter for LspLogToolbarItemView {} + impl ToolbarItemView for LspLogToolbarItemView { fn set_active_pane_item( &mut self, @@ -688,9 +703,7 @@ impl ToolbarItemView for LspLogToolbarItemView { self._log_view_subscription = Some(cx.observe(&log_view, |_, _, cx| { cx.notify(); })); - return ToolbarItemLocation::PrimaryLeft { - flex: Some((1., false)), - }; + return ToolbarItemLocation::PrimaryLeft; } } self.log_view = None; @@ -699,15 +712,17 @@ impl ToolbarItemView for LspLogToolbarItemView { } } -impl View for LspLogToolbarItemView { - fn ui_name() -> &'static str { - "LspLogView" - } +impl Render for LspLogToolbarItemView { + type Element = Div; + // todo!() + // fn ui_name() -> &'static str { + // "LspLogView" + // } - fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = theme::current(cx).clone(); + fn render(&mut self, cx: &mut ViewContext) -> Div { + let theme = cx.theme().clone(); let Some(log_view) = self.log_view.as_ref() else { - return Empty::new().into_any(); + return div(); }; let (menu_rows, current_server_id) = log_view.update(cx, |log_view, cx| { let menu_rows = log_view.menu_items(cx).unwrap_or_default(); @@ -726,19 +741,15 @@ impl View for LspLogToolbarItemView { enum LspLogScroll {} enum Menu {} - let lsp_menu = Stack::new() - .with_child(Self::render_language_server_menu_header( - current_server, - &theme, - cx, - )) - .with_children(if self.menu_open { + let lsp_menu = h_stack() + .child(Self::render_language_server_menu_header(current_server, cx)) + .children(if self.menu_open { Some( - Overlay::new( - MouseEventHandler::new::(0, cx, move |_, cx| { - Flex::column() + overlay() + .child( + v_stack() .scrollable::(0, None, cx) - .with_children(menu_rows.into_iter().map(|row| { + .children(menu_rows.into_iter().map(|row| { Self::render_language_server_menu_item( row.server_id, row.server_name, @@ -750,51 +761,27 @@ impl View for LspLogToolbarItemView { cx, ) })) - .contained() - .with_style(theme.toolbar_dropdown_menu.container) - .constrained() - .with_width(400.) - .with_height(400.) - }) - .on_down_out(MouseButton::Left, |_, this, cx| { - this.menu_open = false; - cx.notify() - }), - ) - .with_hoverable(true) - .with_fit_mode(OverlayFitMode::SwitchAnchor) - .with_anchor_corner(AnchorCorner::TopLeft) - .with_z_index(999) - .aligned() - .bottom() - .left(), + .on_down_out(MouseButton::Left, |_, this, cx| { + this.menu_open = false; + cx.notify() + }), + ) + .with_hoverable(true) + .with_fit_mode(OverlayFitMode::SwitchAnchor) + .with_anchor_corner(AnchorCorner::TopLeft) + .with_z_index(999) + .bottom() + .left(), ) } else { None - }) - .aligned() - .left() - .clipped(); + }); enum LspCleanupButton {} - let log_cleanup_button = - MouseEventHandler::new::(1, cx, |state, cx| { - let theme = theme::current(cx).clone(); - let style = theme - .workspace - .toolbar - .toggleable_text_tool - .in_state(server_selected) - .style_for(state); - Label::new("Clear", style.text.clone()) - .aligned() - .contained() - .with_style(style.container) - .constrained() - .with_height(theme.toolbar_dropdown_menu.row_height / 6.0 * 5.0) - }) - .on_click(MouseButton::Left, move |_, this, cx| { - if let Some(log_view) = this.log_view.as_ref() { + let log_cleanup_button = div() + .child(Label::new("Clear")) + .on_mouse_down(MouseButton::Left, move |_, cx| { + if let Some(log_view) = self.log_view.as_ref() { log_view.update(cx, |log_view, cx| { log_view.editor.update(cx, |editor, cx| { editor.set_read_only(false); @@ -804,17 +791,13 @@ impl View for LspLogToolbarItemView { }) } }) - .with_cursor_style(CursorStyle::PointingHand) - .aligned() - .right(); + .cursor(CursorStyle::PointingHand); - Flex::row() - .with_child(lsp_menu) - .with_child(log_cleanup_button) - .contained() - .aligned() - .left() - .into_any_named("lsp log controls") + h_stack() + .child(lsp_menu) + .child(log_cleanup_button) + .border_1() + .border_color(red()) } } @@ -871,37 +854,37 @@ impl LspLogToolbarItemView { fn render_language_server_menu_header( current_server: Option, - theme: &Arc, cx: &mut ViewContext, - ) -> impl Element { + ) -> Div { + let view = cx.view().clone(); enum ToggleMenu {} - MouseEventHandler::new::(0, cx, move |state, _| { - let label: Cow = current_server - .and_then(|row| { - Some( - format!( - "{} ({}) - {}", - row.server_name.0, - row.worktree_root_name, - if row.rpc_trace_selected { - RPC_MESSAGES - } else { - SERVER_LOGS - }, - ) - .into(), + let label: Cow = current_server + .and_then(|row| { + Some( + format!( + "{} ({}) - {}", + row.server_name.0, + row.worktree_root_name, + if row.rpc_trace_selected { + RPC_MESSAGES + } else { + SERVER_LOGS + }, ) + .into(), + ) + }) + .unwrap_or_else(|| "No server selected".into()); + div() + .child(Label::new(label)) + .cursor(CursorStyle::PointingHand) + .on_mouse_down(MouseButton::Left, move |_, cx| { + view.update(cx, |view, cx| { + view.toggle_menu(cx); }) - .unwrap_or_else(|| "No server selected".into()); - let style = theme.toolbar_dropdown_menu.header.style_for(state); - Label::new(label, style.text.clone()) - .contained() - .with_style(style.container) - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, view, cx| { - view.toggle_menu(cx); - }) + }) + .border_1() + .border_color(red()) } fn render_language_server_menu_item( @@ -913,78 +896,52 @@ impl LspLogToolbarItemView { rpc_trace_selected: bool, theme: &Arc, cx: &mut ViewContext, - ) -> impl Element { + ) -> Div { enum ActivateLog {} enum ActivateRpcTrace {} enum LanguageServerCheckbox {} - Flex::column() - .with_child({ - let style = &theme.toolbar_dropdown_menu.section_header; - Label::new( - format!("{} ({})", name.0, worktree_root_name), - style.text.clone(), - ) - .contained() - .with_style(style.container) - .constrained() - .with_height(theme.toolbar_dropdown_menu.row_height) - }) - .with_child( - MouseEventHandler::new::(id.0, cx, move |state, _| { - let style = theme - .toolbar_dropdown_menu - .item - .in_state(logs_selected) - .style_for(state); - Label::new(SERVER_LOGS, style.text.clone()) - .contained() - .with_style(style.container) - .constrained() - .with_height(theme.toolbar_dropdown_menu.row_height) - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, view, cx| { - view.show_logs_for_server(id, cx); - }), + let view = cx.view().clone(); + + v_stack() + .child(Label::new(format!("{} ({})", name.0, worktree_root_name))) + .child( + div() + .child(Label::new(SERVER_LOGS)) + .cursor(CursorStyle::PointingHand) + .on_mouse_down(MouseButton::Left, move |_, cx| { + view.update(cx, |view, cx| { + view.show_logs_for_server(id, cx); + }) + }), ) - .with_child( - MouseEventHandler::new::(id.0, cx, move |state, cx| { - let style = theme - .toolbar_dropdown_menu - .item - .in_state(rpc_trace_selected) - .style_for(state); - Flex::row() - .with_child( - Label::new(RPC_MESSAGES, style.text.clone()) - .constrained() - .with_height(theme.toolbar_dropdown_menu.row_height), + .child( + h_stack() + .child(Label::new(RPC_MESSAGES)) + .child( + ui::checkbox_with_label::( + div(), + &theme.welcome.checkbox, + rpc_trace_enabled, + id.0, + cx, + move |this, enabled, cx| { + this.toggle_logging_for_server(id, enabled, cx); + }, ) - .with_child( - ui::checkbox_with_label::( - Empty::new(), - &theme.welcome.checkbox, - rpc_trace_enabled, - id.0, - cx, - move |this, enabled, cx| { - this.toggle_logging_for_server(id, enabled, cx); - }, - ) - .flex_float(), - ) - .align_children_center() - .contained() - .with_style(style.container) - .constrained() - .with_height(theme.toolbar_dropdown_menu.row_height) - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, view, cx| { - view.show_rpc_trace_for_server(id, cx); - }), + .flex_float(), + ) + .border_1() + .border_color(red()) + .cursor(CursorStyle::PointingHand) + .on_mouse_down(MouseButton::Left, move |_, cx| { + view.update(cx, |view, cx| { + view.show_rpc_trace_for_server(id, cx); + }) + }), ) + .border_1() + .border_color(red()) } } @@ -996,14 +953,7 @@ pub enum Event { }, } -impl Entity for LogStore { - type Event = Event; -} - -impl Entity for LspLogView { - type Event = editor::Event; -} - -impl Entity for LspLogToolbarItemView { - type Event = (); -} +impl EventEmitter for LogStore {} +impl EventEmitter for LspLogView {} +impl EventEmitter for LspLogView {} +impl EventEmitter for LspLogView {} diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index 80ff211176..7efd5f5723 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -1,17 +1,20 @@ use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId}; use gpui::{ - actions, AnchorCorner, AppContext, CursorStyle, Div, Element, Empty, Entity, Focusable, Model, - MouseButton, Overlay, OverlayFitMode, ParentElement, Render, TextStyle, UniformList, - UniformListState, View, ViewContext, VisualContext, WeakView, + actions, div, overlay, red, uniform_list, AnyElement, AppContext, CursorStyle, Div, + EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model, + MouseButton, ParentElement, Render, Styled, TextStyle, UniformListState, View, ViewContext, + VisualContext, WeakView, WindowContext, }; use language::{Buffer, OwnedSyntaxLayerInfo, SyntaxLayerInfo}; -use std::{mem, ops::Range, sync::Arc}; -use theme::{ActiveTheme, Theme, ThemeSettings}; +use settings::Settings; +use std::{mem, ops::Range}; +use theme::{ActiveTheme, ThemeSettings}; use tree_sitter::{Node, TreeCursor}; +use ui::{h_stack, Label}; use workspace::{ item::{Item, ItemHandle}, ui::v_stack, - ToolbarItemLocation, ToolbarItemView, Workspace, + ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace, }; actions!(debug, [OpenSyntaxTreeView]); @@ -37,6 +40,7 @@ pub struct SyntaxTreeView { list_state: UniformListState, selected_descendant_ix: Option, hovered_descendant_ix: Option, + focus_handle: FocusHandle, } pub struct SyntaxTreeToolbarItemView { @@ -72,6 +76,7 @@ impl SyntaxTreeView { line_height: None, hovered_descendant_ix: None, selected_descendant_ix: None, + focus_handle: cx.focus_handle(), }; this.workspace_updated(active_item, cx); @@ -229,7 +234,7 @@ impl SyntaxTreeView { editor.clear_background_highlights::(cx); editor.highlight_background::( vec![range], - |theme| theme.editor.document_highlight_write_background, + |theme| theme.editor_document_highlight_write_background, cx, ); }); @@ -281,10 +286,10 @@ impl SyntaxTreeView { style: &TextStyle, editor_theme: &theme::Editor, cx: &AppContext, - ) -> gpui::AnyElement { + ) -> Div { let node = cursor.node(); let mut range_style = style.clone(); - let em_width = style.em_width(cx.font_cache()); + let em_width = style.em_width(cx.text_system()); let gutter_padding = (em_width * editor_theme.gutter_padding_factor).round(); range_style.color = editor_theme.line_number; @@ -304,64 +309,54 @@ impl SyntaxTreeView { anonymous_node_style.color = color; } - let mut row = Flex::row(); + let mut row = h_stack(); if let Some(field_name) = cursor.field_name() { let mut field_style = style.clone(); if let Some(color) = property_color { field_style.color = color; } - row.add_children([ - Label::new(field_name, field_style), - Label::new(": ", style.clone()), - ]); + row = row.children([Label::new(field_name), Label::new(": ")]); } return row - .with_child( + .child( if node.is_named() { - Label::new(node.kind(), style.clone()) + Label::new(node.kind()) } else { - Label::new(format!("\"{}\"", node.kind()), anonymous_node_style) - } - .contained() - .with_margin_right(em_width), + Label::new(format!("\"{}\"", node.kind())) + }, // todo!() + // .margin(em_width), ) - .with_child(Label::new(format_node_range(node), range_style)) - .contained() - .with_background_color(if selected { + .child(Label::new(format_node_range(node))) + .text_bg(if selected { editor_theme.selection.selection } else if hovered && list_hovered { editor_theme.active_line_background } else { - Default::default() + Hsla::default() }) - .with_padding_left(gutter_padding + depth as f32 * 18.0) - .into_any(); + // todo!() + // .padding(gutter_padding + depth as f32 * 18.0) + .border_1() + .border_color(red()); } } -impl Entity for SyntaxTreeView { - type Event = (); -} +impl Render for SyntaxTreeView { + // todo!() + // fn ui_name() -> &'static str { + // "SyntaxTreeView" + // } -impl View for SyntaxTreeView { - fn ui_name() -> &'static str { - "SyntaxTreeView" - } + type Element = Div; - fn render(&mut self, cx: &mut gpui::ViewContext<'_, '_, Self>) -> gpui::AnyElement { - let settings = settings::get::(cx); - let font_family_id = settings.buffer_font_family; - let font_family_name = cx.font_cache().family_name(font_family_id).unwrap(); - let font_properties = Default::default(); - let font_id = cx - .font_cache() - .select_font(font_family_id, &font_properties) - .unwrap(); + fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Div { + let settings = ThemeSettings::get_global(cx); + let font = settings.buffer_font; let font_size = settings.buffer_font_size(cx); - let editor_theme = settings.theme.editor.clone(); + let editor_theme = settings.active_theme; let style = TextStyle { color: editor_theme.text_color, font_family_name, @@ -370,10 +365,16 @@ impl View for SyntaxTreeView { font_size, font_properties: Default::default(), underline: Default::default(), - soft_wrap: false, + font_family: todo!(), + font_features: todo!(), + line_height: todo!(), + font_weight: todo!(), + font_style: todo!(), + background_color: todo!(), + white_space: todo!(), }; - let line_height = cx.font_cache().line_height(font_size); + let line_height = cx.text_system().line_height(font_size); if Some(line_height) != self.line_height { self.line_height = Some(line_height); self.hover_state_changed(cx); @@ -387,90 +388,95 @@ impl View for SyntaxTreeView { { let layer = layer.clone(); let theme = editor_theme.clone(); - return MouseEventHandler::new::(0, cx, move |state, cx| { - let list_hovered = state.hovered(); - UniformList::new( - self.list_state.clone(), - layer.node().descendant_count(), - cx, - move |this, range, items, cx| { - let mut cursor = layer.node().walk(); - let mut descendant_ix = range.start as usize; - cursor.goto_descendant(descendant_ix); - let mut depth = cursor.depth(); - let mut visited_children = false; - while descendant_ix < range.end { - if visited_children { - if cursor.goto_next_sibling() { - visited_children = false; - } else if cursor.goto_parent() { - depth -= 1; - } else { - break; - } + + let list_hovered = state.hovered(); + uniform_list( + self.list_state.clone(), + layer.node().descendant_count(), + cx, + move |this, range, items, cx| { + let mut cursor = layer.node().walk(); + let mut descendant_ix = range.start as usize; + cursor.goto_descendant(descendant_ix); + let mut depth = cursor.depth(); + let mut visited_children = false; + while descendant_ix < range.end { + if visited_children { + if cursor.goto_next_sibling() { + visited_children = false; + } else if cursor.goto_parent() { + depth -= 1; } else { - items.push(Self::render_node( - &cursor, - depth, - Some(descendant_ix) == this.selected_descendant_ix, - Some(descendant_ix) == this.hovered_descendant_ix, - list_hovered, - &style, - &theme, - cx, - )); - descendant_ix += 1; - if cursor.goto_first_child() { - depth += 1; - } else { - visited_children = true; - } + break; + } + } else { + items.push(Self::render_node( + &cursor, + depth, + Some(descendant_ix) == this.selected_descendant_ix, + Some(descendant_ix) == this.hovered_descendant_ix, + list_hovered, + &style, + &theme, + cx, + )); + descendant_ix += 1; + if cursor.goto_first_child() { + depth += 1; + } else { + visited_children = true; } } - }, - ) - }) + } + }, + ) .on_move(move |event, this, cx| { let y = event.position.y() - event.region.origin_y(); this.mouse_y = Some(y); this.hover_state_changed(cx); }) - .on_click(MouseButton::Left, move |event, this, cx| { + .on_mouse_down(MouseButton::Left, move |event, cx| { let y = event.position.y() - event.region.origin_y(); - this.handle_click(y, cx); - }) - .contained() - .with_background_color(editor_theme.background) - .into_any(); + self.handle_click(y, cx); + }); } - Empty::new().into_any() + div() + } +} + +impl EventEmitter<()> for SyntaxTreeView {} + +impl FocusableView for SyntaxTreeView { + fn focus_handle(&self, _: &AppContext) -> gpui::FocusHandle { + self.focus_handle.clone() } } impl Item for SyntaxTreeView { - fn tab_content( - &self, - _: Option, - style: &theme::Tab, - _: &AppContext, - ) -> gpui::AnyElement { - Label::new("Syntax Tree", style.label.clone()).into_any() + type Event = (); + + fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {} + + fn tab_content(&self, _: Option, _: bool, _: &WindowContext<'_>) -> AnyElement { + Label::new("Syntax Tree").into_any_element() } fn clone_on_split( &self, - _workspace_id: workspace::WorkspaceId, + _: workspace::WorkspaceId, cx: &mut ViewContext, - ) -> Option + ) -> Option> where Self: Sized, { - let mut clone = Self::new(self.workspace_handle.clone(), None, cx); - if let Some(editor) = &self.editor { - clone.set_editor(editor.editor.clone(), cx) - } - Some(clone) + Some(cx.build_view(|cx| { + let mut clone = Self::new(self.workspace_handle.clone(), None, cx); + if let Some(editor) = &self.editor { + clone.set_editor(editor.editor.clone(), cx) + } + clone + })) } } @@ -483,10 +489,7 @@ impl SyntaxTreeToolbarItemView { } } - fn render_menu( - &mut self, - cx: &mut ViewContext<'_, '_, Self>, - ) -> Option> { + fn render_menu(&mut self, cx: &mut ViewContext<'_, Self>) -> Option
{ let theme = cx.theme().clone(); let tree_view = self.tree_view.as_ref()?; let tree_view = tree_view.read(cx); @@ -496,36 +499,23 @@ impl SyntaxTreeToolbarItemView { let active_layer = buffer_state.active_layer.clone()?; let active_buffer = buffer_state.buffer.read(cx).snapshot(); - enum Menu {} - Some( v_stack() - .child(Self::render_header(&theme, &active_layer, cx)) + .child(Self::render_header(&active_layer, cx)) .children(self.menu_open.then(|| { - overlay( - mouse_event_handler::(0, cx, move |_, cx| { - v_stack() - .with_children(active_buffer.syntax_layers().enumerate().map( - |(ix, layer)| { - Self::render_menu_item(&theme, &active_layer, layer, ix, cx) - }, - )) - .contained() - .with_style(theme.toolbar_dropdown_menu.container) - .constrained() - .with_width(400.) - .with_height(400.) - }) - .on_down_out(MouseButton::Left, |_, this, cx| { - this.menu_open = false; - cx.notify() - }), + overlay().child( + v_stack() + .children(active_buffer.syntax_layers().enumerate().map( + |(ix, layer)| Self::render_menu_item(&active_layer, layer, ix, cx), + )) + .on_mouse_down_out(|e, cx| { + if e.button == MouseButton::Left { + self.menu_open = false; + cx.notify() + } + }), ) - .with_hoverable(true) - .with_fit_content() - .into_any() - })) - .into_any(), + })), ) } @@ -549,71 +539,39 @@ impl SyntaxTreeToolbarItemView { }) } - fn render_header( - theme: &Arc, - active_layer: &OwnedSyntaxLayerInfo, - cx: &mut ViewContext, - ) -> impl Element { - enum ToggleMenu {} - MouseEventHandler::new::(0, cx, move |state, _| { - let style = theme.toolbar_dropdown_menu.header.style_for(state); - Flex::row() - .with_child( - Label::new(active_layer.language.name().to_string(), style.text.clone()) - .contained() - .with_margin_right(style.secondary_text_spacing), - ) - .with_child(Label::new( - format_node_range(active_layer.node()), - style - .secondary_text - .clone() - .unwrap_or_else(|| style.text.clone()), - )) - .contained() - .with_style(style.container) - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, view, cx| { - view.toggle_menu(cx); - }) + fn render_header(active_layer: &OwnedSyntaxLayerInfo, cx: &mut ViewContext) -> Div { + let view = cx.view().clone(); + h_stack() + .child(Label::new(active_layer.language.name())) + .child(Label::new(format_node_range(active_layer.node()))) + .on_mouse_down(MouseButton::Left, move |_, cx| { + view.update(cx, |view, cx| view.toggle_menu(cx)); + }) + .cursor(CursorStyle::PointingHand) + .border_1() + .border_color(red()) } fn render_menu_item( - theme: &Arc, active_layer: &OwnedSyntaxLayerInfo, layer: SyntaxLayerInfo, layer_ix: usize, cx: &mut ViewContext, - ) -> impl Element { - enum ActivateLayer {} - MouseEventHandler::new::(layer_ix, cx, move |state, _| { - let is_selected = layer.node() == active_layer.node(); - let style = theme - .toolbar_dropdown_menu - .item - .in_state(is_selected) - .style_for(state); - Flex::row() - .with_child( - Label::new(layer.language.name().to_string(), style.text.clone()) - .contained() - .with_margin_right(style.secondary_text_spacing), - ) - .with_child(Label::new( - format_node_range(layer.node()), - style - .secondary_text - .clone() - .unwrap_or_else(|| style.text.clone()), - )) - .contained() - .with_style(style.container) - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, move |_, view, cx| { - view.select_layer(layer_ix, cx); - }) + ) -> Div { + // todo!() styling + let _is_selected = layer.node() == active_layer.node(); + let view = cx.view().clone(); + h_stack() + .child(Label::new(layer.language.name().to_string())) + .child(Label::new(format_node_range(layer.node()))) + .cursor(CursorStyle::PointingHand) + .on_mouse_down(MouseButton::Left, move |_, cx| { + view.update(cx, |view, cx| { + view.select_layer(layer_ix, cx); + }) + }) + .border_1() + .border_color(red()) } } @@ -630,33 +588,32 @@ fn format_node_range(node: Node) -> String { } impl Render for SyntaxTreeToolbarItemView { - type Element = Focusable
; + type Element = Div; // todo!() // fn ui_name() -> &'static str { // "SyntaxTreeToolbarItemView" // } - fn render(&mut self, cx: &mut ViewContext<'_, '_, Self>) -> gpui::AnyElement { - self.render_menu(cx) - .unwrap_or_else(|| Empty::new().into_any()) + fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> Div { + self.render_menu(cx).unwrap_or_else(|| div()) } } +impl EventEmitter for SyntaxTreeToolbarItemView {} + impl ToolbarItemView for SyntaxTreeToolbarItemView { fn set_active_pane_item( &mut self, active_pane_item: Option<&dyn ItemHandle>, cx: &mut ViewContext, - ) -> workspace::ToolbarItemLocation { + ) -> ToolbarItemLocation { self.menu_open = false; if let Some(item) = active_pane_item { if let Some(view) = item.downcast::() { self.tree_view = Some(view.clone()); self.subscription = Some(cx.observe(&view, |_, _, cx| cx.notify())); - return ToolbarItemLocation::PrimaryLeft { - flex: Some((1., false)), - }; + return ToolbarItemLocation::PrimaryLeft; } } self.tree_view = None; From 8471a5f80b04dfcebdb701a4c1958cef63152e65 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 17:04:24 +0200 Subject: [PATCH 191/644] Finish all but the styling --- crates/gpui2/src/elements/uniform_list.rs | 8 + crates/language_tools2/src/lsp_log.rs | 170 +++++++++--------- .../language_tools2/src/syntax_tree_view.rs | 144 ++++++++------- 3 files changed, 167 insertions(+), 155 deletions(-) diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 7fba7ef477..e8587683d6 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -91,6 +91,14 @@ impl UniformListScrollHandle { } } } + + pub fn scroll_top(&self) -> Pixels { + if let Some(state) = &*self.0.borrow() { + -state.scroll_offset.borrow().y + } else { + Pixels::ZERO + } + } } impl Styled for UniformList { diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index ca4f25e177..3c3df41442 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -2,17 +2,16 @@ use collections::{HashMap, VecDeque}; use editor::{Editor, EditorElement, EditorEvent, MoveToEnd}; use futures::{channel::mpsc, StreamExt}; use gpui::{ - actions, div, overlay, red, AnchorCorner, AnyElement, AppContext, Context, CursorStyle, Div, - EventEmitter, FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ModelContext, - MouseButton, OverlayFitMode, ParentElement, Render, Styled, Subscription, View, ViewContext, - VisualContext, WeakModel, WindowContext, + actions, div, overlay, red, AnyElement, AppContext, Context, CursorStyle, Div, EventEmitter, + FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ModelContext, MouseButton, + MouseDownEvent, ParentElement, Render, Styled, Subscription, View, ViewContext, VisualContext, + WeakModel, WindowContext, }; use language::{LanguageServerId, LanguageServerName}; use lsp::IoKind; use project::{search::SearchQuery, Project}; use std::{borrow::Cow, sync::Arc}; -use theme::{ActiveTheme, Theme}; -use ui::{h_stack, v_stack, Label}; +use ui::{h_stack, v_stack, Checkbox, Label}; use workspace::{ item::{Item, ItemHandle}, searchable::{SearchEvent, SearchableItem, SearchableItemHandle}, @@ -83,7 +82,7 @@ actions!(debug, [OpenLanguageServerLogs]); pub fn init(cx: &mut AppContext) { let log_store = cx.build_model(|cx| LogStore::new(cx)); - cx.observe_new_views(|workspace: &mut Workspace, cx| { + cx.observe_new_views(move |workspace: &mut Workspace, cx| { let project = workspace.project(); if project.read(cx).is_local() { log_store.update(cx, |store, cx| { @@ -91,7 +90,8 @@ pub fn init(cx: &mut AppContext) { }); } - workspace.register_action(|workspace, _: &OpenLanguageServerLogs, cx| { + let log_store = log_store.clone(); + workspace.register_action(move |workspace, _: &OpenLanguageServerLogs, cx| { let project = workspace.project().read(cx); if project.is_local() { workspace.add_item( @@ -118,7 +118,7 @@ impl LogStore { if let Some(this) = this.upgrade() { this.update(&mut cx, |this, cx| { this.on_io(project, server_id, io_kind, &message, cx); - }); + })?; } } anyhow::Ok(()) @@ -130,7 +130,7 @@ impl LogStore { pub fn add_project(&mut self, project: &Model, cx: &mut ModelContext) { let weak_project = project.downgrade(); self.projects.insert( - weak_project, + project.downgrade(), ProjectState { servers: HashMap::default(), _subscriptions: [ @@ -184,7 +184,7 @@ impl LogStore { server_state._io_logs_subscription = server.as_ref().map(|server| { server.on_io(move |io_kind, message| { io_tx - .unbounded_send((weak_project, id, io_kind, message.to_string())) + .unbounded_send((weak_project.clone(), id, io_kind, message.to_string())) .ok(); }) }); @@ -197,7 +197,8 @@ impl LogStore { if let Some((project, this)) = weak_project.upgrade().zip(this.upgrade()) { this.update(&mut cx, |this, cx| { this.add_language_server_log(&project, server_id, ¶ms.message, cx); - }); + }) + .ok(); } } }) @@ -550,10 +551,10 @@ impl LspLogView { let language = language.await.ok(); buffer.update(&mut cx, |buffer, cx| { buffer.set_language(language, cx); - }); + }) } }) - .detach(); + .detach_and_log_err(cx); }); self.editor = editor; @@ -720,7 +721,6 @@ impl Render for LspLogToolbarItemView { // } fn render(&mut self, cx: &mut ViewContext) -> Div { - let theme = cx.theme().clone(); let Some(log_view) = self.log_view.as_ref() else { return div(); }; @@ -737,60 +737,60 @@ impl Render for LspLogToolbarItemView { None } }); - let server_selected = current_server.is_some(); + // todo!() styling + let _server_selected = current_server.is_some(); - enum LspLogScroll {} - enum Menu {} let lsp_menu = h_stack() .child(Self::render_language_server_menu_header(current_server, cx)) .children(if self.menu_open { Some( - overlay() - .child( - v_stack() - .scrollable::(0, None, cx) - .children(menu_rows.into_iter().map(|row| { - Self::render_language_server_menu_item( - row.server_id, - row.server_name, - &row.worktree_root_name, - row.rpc_trace_enabled, - row.logs_selected, - row.rpc_trace_selected, - &theme, - cx, - ) - })) - .on_down_out(MouseButton::Left, |_, this, cx| { + overlay().child( + v_stack() + // todo!() + // .scrollable::(0, None, cx) + .children(menu_rows.into_iter().map(|row| { + Self::render_language_server_menu_item( + row.server_id, + row.server_name, + &row.worktree_root_name, + row.rpc_trace_enabled, + row.logs_selected, + row.rpc_trace_selected, + cx, + ) + })) + .on_mouse_down_out(cx.listener(|this, event: &MouseDownEvent, cx| { + if event.button == MouseButton::Left { this.menu_open = false; cx.notify() - }), - ) - .with_hoverable(true) - .with_fit_mode(OverlayFitMode::SwitchAnchor) - .with_anchor_corner(AnchorCorner::TopLeft) - .with_z_index(999) - .bottom() - .left(), + } + })), + ), // todo!() + // .with_hoverable(true) + // .with_fit_mode(OverlayFitMode::SwitchAnchor) + // .with_anchor_corner(AnchorCorner::TopLeft) + // .with_z_index(999), ) } else { None }); - enum LspCleanupButton {} let log_cleanup_button = div() .child(Label::new("Clear")) - .on_mouse_down(MouseButton::Left, move |_, cx| { - if let Some(log_view) = self.log_view.as_ref() { - log_view.update(cx, |log_view, cx| { - log_view.editor.update(cx, |editor, cx| { - editor.set_read_only(false); - editor.clear(cx); - editor.set_read_only(true); - }); - }) - } - }) + .on_mouse_down( + MouseButton::Left, + cx.listener(move |this, _, cx| { + if let Some(log_view) = this.log_view.as_ref() { + log_view.update(cx, |log_view, cx| { + log_view.editor.update(cx, |editor, cx| { + editor.set_read_only(false); + editor.clear(cx); + editor.set_read_only(true); + }); + }) + } + }), + ) .cursor(CursorStyle::PointingHand); h_stack() @@ -856,8 +856,6 @@ impl LspLogToolbarItemView { current_server: Option, cx: &mut ViewContext, ) -> Div { - let view = cx.view().clone(); - enum ToggleMenu {} let label: Cow = current_server .and_then(|row| { Some( @@ -878,11 +876,12 @@ impl LspLogToolbarItemView { div() .child(Label::new(label)) .cursor(CursorStyle::PointingHand) - .on_mouse_down(MouseButton::Left, move |_, cx| { - view.update(cx, |view, cx| { + .on_mouse_down( + MouseButton::Left, + cx.listener(move |view, _, cx| { view.toggle_menu(cx); - }) - }) + }), + ) .border_1() .border_color(red()) } @@ -892,53 +891,52 @@ impl LspLogToolbarItemView { name: LanguageServerName, worktree_root_name: &str, rpc_trace_enabled: bool, - logs_selected: bool, - rpc_trace_selected: bool, - theme: &Arc, + // todo!() styling + _logs_selected: bool, + _rpc_trace_selected: bool, cx: &mut ViewContext, ) -> Div { - enum ActivateLog {} - enum ActivateRpcTrace {} - enum LanguageServerCheckbox {} - - let view = cx.view().clone(); - v_stack() .child(Label::new(format!("{} ({})", name.0, worktree_root_name))) .child( div() .child(Label::new(SERVER_LOGS)) .cursor(CursorStyle::PointingHand) - .on_mouse_down(MouseButton::Left, move |_, cx| { - view.update(cx, |view, cx| { + .on_mouse_down( + MouseButton::Left, + cx.listener(move |view, _, cx| { view.show_logs_for_server(id, cx); - }) - }), + }), + ), ) .child( h_stack() .child(Label::new(RPC_MESSAGES)) .child( - ui::checkbox_with_label::( - div(), - &theme.welcome.checkbox, - rpc_trace_enabled, + Checkbox::new( id.0, - cx, - move |this, enabled, cx| { - this.toggle_logging_for_server(id, enabled, cx); + if rpc_trace_enabled { + ui::Selection::Selected + } else { + ui::Selection::Unselected }, ) - .flex_float(), + .on_click(cx.listener( + move |this, selection, cx| { + let enabled = matches!(selection, ui::Selection::Selected); + this.toggle_logging_for_server(id, enabled, cx); + }, + )), ) .border_1() .border_color(red()) .cursor(CursorStyle::PointingHand) - .on_mouse_down(MouseButton::Left, move |_, cx| { - view.update(cx, |view, cx| { + .on_mouse_down( + MouseButton::Left, + cx.listener(move |view, _, cx| { view.show_rpc_trace_for_server(id, cx); - }) - }), + }), + ), ) .border_1() .border_color(red()) diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index 7efd5f5723..9c8ec0ee04 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -2,13 +2,13 @@ use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId}; use gpui::{ actions, div, overlay, red, uniform_list, AnyElement, AppContext, CursorStyle, Div, EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model, - MouseButton, ParentElement, Render, Styled, TextStyle, UniformListState, View, ViewContext, - VisualContext, WeakView, WindowContext, + MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Render, Styled, TextStyle, + UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext, }; use language::{Buffer, OwnedSyntaxLayerInfo, SyntaxLayerInfo}; use settings::Settings; use std::{mem, ops::Range}; -use theme::{ActiveTheme, ThemeSettings}; +use theme::{Theme, ThemeSettings}; use tree_sitter::{Node, TreeCursor}; use ui::{h_stack, Label}; use workspace::{ @@ -35,9 +35,9 @@ pub fn init(cx: &mut AppContext) { pub struct SyntaxTreeView { workspace_handle: WeakView, editor: Option, - mouse_y: Option, - line_height: Option, - list_state: UniformListState, + mouse_y: Option, + line_height: Option, + list_scroll_handle: UniformListScrollHandle, selected_descendant_ix: Option, hovered_descendant_ix: Option, focus_handle: FocusHandle, @@ -70,7 +70,7 @@ impl SyntaxTreeView { ) -> Self { let mut this = Self { workspace_handle: workspace_handle.clone(), - list_state: UniformListState::default(), + list_scroll_handle: UniformListScrollHandle::new(), editor: None, mouse_y: None, line_height: None, @@ -204,15 +204,15 @@ impl SyntaxTreeView { let descendant_ix = cursor.descendant_index(); self.selected_descendant_ix = Some(descendant_ix); - self.list_state.scroll_to(ScrollTarget::Show(descendant_ix)); + self.list_scroll_handle.scroll_to_item(descendant_ix); cx.notify(); Some(()) } - fn handle_click(&mut self, y: f32, cx: &mut ViewContext) -> Option<()> { + fn handle_click(&mut self, y: Pixels, cx: &mut ViewContext) -> Option<()> { let line_height = self.line_height?; - let ix = ((self.list_state.scroll_top() + y) / line_height) as usize; + let ix = ((self.list_scroll_handle.scroll_top() + y) / line_height) as usize; self.update_editor_with_range_for_descendant_ix(ix, cx, |editor, mut range, cx| { // Put the cursor at the beginning of the node. @@ -227,7 +227,7 @@ impl SyntaxTreeView { fn hover_state_changed(&mut self, cx: &mut ViewContext) { if let Some((y, line_height)) = self.mouse_y.zip(self.line_height) { - let ix = ((self.list_state.scroll_top() + y) / line_height) as usize; + let ix = ((self.list_scroll_handle.scroll_top() + y) / line_height) as usize; if self.hovered_descendant_ix != Some(ix) { self.hovered_descendant_ix = Some(ix); self.update_editor_with_range_for_descendant_ix(ix, cx, |editor, range, cx| { @@ -279,29 +279,39 @@ impl SyntaxTreeView { fn render_node( cursor: &TreeCursor, - depth: u32, + _depth: u32, selected: bool, hovered: bool, list_hovered: bool, style: &TextStyle, - editor_theme: &theme::Editor, - cx: &AppContext, + editor_theme: &Theme, + _cx: &AppContext, ) -> Div { + let editor_colors = editor_theme.colors(); let node = cursor.node(); let mut range_style = style.clone(); - let em_width = style.em_width(cx.text_system()); - let gutter_padding = (em_width * editor_theme.gutter_padding_factor).round(); + // todo!() styling + // let font_id = cx.text_system().font_id(&style.text.font()).unwrap(); + // let font_size = style.text.font_size.to_pixels(cx.rem_size()); + // let line_height = style.text.line_height_in_pixels(cx.rem_size()); + // let em_width = cx + // .text_system() + // .typographic_bounds(font_id, font_size, 'm') + // .unwrap() + // .size + // .width; + // let gutter_padding = (em_width * editor_theme.gutter_padding_factor).round(); - range_style.color = editor_theme.line_number; + range_style.color = editor_colors.editor_line_number; let mut anonymous_node_style = style.clone(); let string_color = editor_theme - .syntax + .syntax() .highlights .iter() .find_map(|(name, style)| (name == "string").then(|| style.color)?); let property_color = editor_theme - .syntax + .syntax() .highlights .iter() .find_map(|(name, style)| (name == "property").then(|| style.color)?); @@ -330,9 +340,9 @@ impl SyntaxTreeView { ) .child(Label::new(format_node_range(node))) .text_bg(if selected { - editor_theme.selection.selection + editor_colors.element_selected } else if hovered && list_hovered { - editor_theme.active_line_background + editor_colors.element_active } else { Hsla::default() }) @@ -344,37 +354,25 @@ impl SyntaxTreeView { } impl Render for SyntaxTreeView { - // todo!() - // fn ui_name() -> &'static str { - // "SyntaxTreeView" - // } - type Element = Div; fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Div { let settings = ThemeSettings::get_global(cx); - let font = settings.buffer_font; + let font = settings.buffer_font.clone(); let font_size = settings.buffer_font_size(cx); - let editor_theme = settings.active_theme; + let editor_theme = settings.active_theme.clone(); + let editor_colors = editor_theme.colors(); let style = TextStyle { - color: editor_theme.text_color, - font_family_name, - font_family_id, - font_id, - font_size, - font_properties: Default::default(), - underline: Default::default(), - font_family: todo!(), - font_features: todo!(), - line_height: todo!(), - font_weight: todo!(), - font_style: todo!(), - background_color: todo!(), - white_space: todo!(), + color: editor_colors.text, + font_family: font.family, + font_features: font.features, + font_weight: font.weight, + font_style: font.style, + ..Default::default() }; - let line_height = cx.text_system().line_height(font_size); + let line_height = cx.text_style().line_height_in_pixels(font_size); if Some(line_height) != self.line_height { self.line_height = Some(line_height); self.hover_state_changed(cx); @@ -389,12 +387,15 @@ impl Render for SyntaxTreeView { let layer = layer.clone(); let theme = editor_theme.clone(); - let list_hovered = state.hovered(); + // todo!() + // let list_hovered = state.hovered(); + let list_hovered = false; uniform_list( - self.list_state.clone(), + cx.view().clone(), + "SyntaxTreeView", layer.node().descendant_count(), - cx, - move |this, range, items, cx| { + move |this, range, cx| { + let mut items = Vec::new(); let mut cursor = layer.node().walk(); let mut descendant_ix = range.start as usize; cursor.goto_descendant(descendant_ix); @@ -428,17 +429,21 @@ impl Render for SyntaxTreeView { } } } + items }, ) - .on_move(move |event, this, cx| { - let y = event.position.y() - event.region.origin_y(); - this.mouse_y = Some(y); - this.hover_state_changed(cx); - }) - .on_mouse_down(MouseButton::Left, move |event, cx| { - let y = event.position.y() - event.region.origin_y(); - self.handle_click(y, cx); - }); + .track_scroll(self.list_scroll_handle.clone()) + .on_mouse_move(cx.listener(move |tree_view, event: &MouseMoveEvent, cx| { + tree_view.mouse_y = Some(event.position.y); + tree_view.hover_state_changed(cx); + })) + .on_mouse_down( + MouseButton::Left, + cx.listener(move |tree_view, event: &MouseDownEvent, cx| { + tree_view.handle_click(event.position.y, cx); + }), + ) + .text_bg(editor_colors.background); } div() @@ -490,7 +495,6 @@ impl SyntaxTreeToolbarItemView { } fn render_menu(&mut self, cx: &mut ViewContext<'_, Self>) -> Option
{ - let theme = cx.theme().clone(); let tree_view = self.tree_view.as_ref()?; let tree_view = tree_view.read(cx); @@ -508,12 +512,12 @@ impl SyntaxTreeToolbarItemView { .children(active_buffer.syntax_layers().enumerate().map( |(ix, layer)| Self::render_menu_item(&active_layer, layer, ix, cx), )) - .on_mouse_down_out(|e, cx| { + .on_mouse_down_out(cx.listener(|this, e: &MouseDownEvent, cx| { if e.button == MouseButton::Left { - self.menu_open = false; + this.menu_open = false; cx.notify() } - }), + })), ) })), ) @@ -540,13 +544,15 @@ impl SyntaxTreeToolbarItemView { } fn render_header(active_layer: &OwnedSyntaxLayerInfo, cx: &mut ViewContext) -> Div { - let view = cx.view().clone(); h_stack() .child(Label::new(active_layer.language.name())) .child(Label::new(format_node_range(active_layer.node()))) - .on_mouse_down(MouseButton::Left, move |_, cx| { - view.update(cx, |view, cx| view.toggle_menu(cx)); - }) + .on_mouse_down( + MouseButton::Left, + cx.listener(move |view, _, cx| { + view.toggle_menu(cx); + }), + ) .cursor(CursorStyle::PointingHand) .border_1() .border_color(red()) @@ -560,16 +566,16 @@ impl SyntaxTreeToolbarItemView { ) -> Div { // todo!() styling let _is_selected = layer.node() == active_layer.node(); - let view = cx.view().clone(); h_stack() .child(Label::new(layer.language.name().to_string())) .child(Label::new(format_node_range(layer.node()))) .cursor(CursorStyle::PointingHand) - .on_mouse_down(MouseButton::Left, move |_, cx| { - view.update(cx, |view, cx| { + .on_mouse_down( + MouseButton::Left, + cx.listener(move |view, _, cx| { view.select_layer(layer_ix, cx); - }) - }) + }), + ) .border_1() .border_color(red()) } From 7e6dac383e380370d38381def811d5e47192776b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 17:14:52 +0200 Subject: [PATCH 192/644] Uncomment tests --- crates/language_tools2/src/lsp_log_tests.rs | 190 ++++++++++---------- 1 file changed, 94 insertions(+), 96 deletions(-) diff --git a/crates/language_tools2/src/lsp_log_tests.rs b/crates/language_tools2/src/lsp_log_tests.rs index 967e8a3382..93e869369a 100644 --- a/crates/language_tools2/src/lsp_log_tests.rs +++ b/crates/language_tools2/src/lsp_log_tests.rs @@ -1,109 +1,107 @@ -// todo!("TODO kb") -// use std::sync::Arc; +use std::sync::Arc; -// use crate::lsp_log::LogMenuItem; +use crate::lsp_log::LogMenuItem; -// use super::*; -// use futures::StreamExt; -// use gpui::{serde_json::json, TestAppContext}; -// use language::{tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig, LanguageServerName}; -// use project::{FakeFs, Project}; -// use settings::SettingsStore; +use super::*; +use futures::StreamExt; +use gpui::{serde_json::json, Context, TestAppContext, VisualTestContext}; +use language::{tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig, LanguageServerName}; +use project::{FakeFs, Project}; +use settings::SettingsStore; -// #[gpui::test] -// async fn test_lsp_logs(cx: &mut TestAppContext) { -// if std::env::var("RUST_LOG").is_ok() { -// env_logger::init(); -// } +#[gpui::test] +async fn test_lsp_logs(cx: &mut TestAppContext) { + if std::env::var("RUST_LOG").is_ok() { + env_logger::init(); + } -// init_test(cx); + init_test(cx); -// let mut rust_language = Language::new( -// LanguageConfig { -// name: "Rust".into(), -// path_suffixes: vec!["rs".to_string()], -// ..Default::default() -// }, -// Some(tree_sitter_rust::language()), -// ); -// let mut fake_rust_servers = rust_language -// .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { -// name: "the-rust-language-server", -// ..Default::default() -// })) -// .await; + let mut rust_language = Language::new( + LanguageConfig { + name: "Rust".into(), + path_suffixes: vec!["rs".to_string()], + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ); + let mut fake_rust_servers = rust_language + .set_fake_lsp_adapter(Arc::new(FakeLspAdapter { + name: "the-rust-language-server", + ..Default::default() + })) + .await; -// let fs = FakeFs::new(cx.background()); -// fs.insert_tree( -// "/the-root", -// json!({ -// "test.rs": "", -// "package.json": "", -// }), -// ) -// .await; -// let project = Project::test(fs.clone(), ["/the-root".as_ref()], cx).await; -// project.update(cx, |project, _| { -// project.languages().add(Arc::new(rust_language)); -// }); + let fs = FakeFs::new(cx.background_executor.clone()); + fs.insert_tree( + "/the-root", + json!({ + "test.rs": "", + "package.json": "", + }), + ) + .await; + let project = Project::test(fs.clone(), ["/the-root".as_ref()], cx).await; + project.update(cx, |project, _| { + project.languages().add(Arc::new(rust_language)); + }); -// let log_store = cx.add_model(|cx| LogStore::new(cx)); -// log_store.update(cx, |store, cx| store.add_project(&project, cx)); + let log_store = cx.build_model(|cx| LogStore::new(cx)); + log_store.update(cx, |store, cx| store.add_project(&project, cx)); -// let _rust_buffer = project -// .update(cx, |project, cx| { -// project.open_local_buffer("/the-root/test.rs", cx) -// }) -// .await -// .unwrap(); + let _rust_buffer = project + .update(cx, |project, cx| { + project.open_local_buffer("/the-root/test.rs", cx) + }) + .await + .unwrap(); -// let mut language_server = fake_rust_servers.next().await.unwrap(); -// language_server -// .receive_notification::() -// .await; + let mut language_server = fake_rust_servers.next().await.unwrap(); + language_server + .receive_notification::() + .await; -// let log_view = cx -// .add_window(|cx| LspLogView::new(project.clone(), log_store.clone(), cx)) -// .root(cx); + let window = cx.add_window(|cx| LspLogView::new(project.clone(), log_store.clone(), cx)); + let log_view = window.root(cx).unwrap(); + let mut cx = VisualTestContext::from_window(*window, cx); -// language_server.notify::(lsp::LogMessageParams { -// message: "hello from the server".into(), -// typ: lsp::MessageType::INFO, -// }); -// cx.foreground().run_until_parked(); + language_server.notify::(lsp::LogMessageParams { + message: "hello from the server".into(), + typ: lsp::MessageType::INFO, + }); + cx.executor().run_until_parked(); -// log_view.read_with(cx, |view, cx| { -// assert_eq!( -// view.menu_items(cx).unwrap(), -// &[LogMenuItem { -// server_id: language_server.server.server_id(), -// server_name: LanguageServerName("the-rust-language-server".into()), -// worktree_root_name: project -// .read(cx) -// .worktrees(cx) -// .next() -// .unwrap() -// .read(cx) -// .root_name() -// .to_string(), -// rpc_trace_enabled: false, -// rpc_trace_selected: false, -// logs_selected: true, -// }] -// ); -// assert_eq!(view.editor.read(cx).text(cx), "hello from the server\n"); -// }); -// } + log_view.update(&mut cx, |view, cx| { + assert_eq!( + view.menu_items(cx).unwrap(), + &[LogMenuItem { + server_id: language_server.server.server_id(), + server_name: LanguageServerName("the-rust-language-server".into()), + worktree_root_name: project + .read(cx) + .worktrees() + .next() + .unwrap() + .read(cx) + .root_name() + .to_string(), + rpc_trace_enabled: false, + rpc_trace_selected: false, + logs_selected: true, + }] + ); + assert_eq!(view.editor.read(cx).text(cx), "hello from the server\n"); + }); +} -// fn init_test(cx: &mut gpui::TestAppContext) { -// cx.foreground().forbid_parking(); - -// cx.update(|cx| { -// cx.set_global(SettingsStore::test(cx)); -// theme::init((), cx); -// language::init(cx); -// client::init_settings(cx); -// Project::init_settings(cx); -// editor::init_settings(cx); -// }); -// } +fn init_test(cx: &mut gpui::TestAppContext) { + cx.update(|cx| { + let settings_store = SettingsStore::test(cx); + cx.set_global(settings_store); + theme::init(theme::LoadThemes::JustBase, cx); + language::init(cx); + client::init_settings(cx); + Project::init_settings(cx); + editor::init_settings(cx); + }); +} From c1f8929e43d17f2cf595de4f7cf7e66b8c9ff6f2 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 17:28:07 +0200 Subject: [PATCH 193/644] Add new panels into zed2 --- Cargo.lock | 1 + crates/zed2/Cargo.toml | 2 +- crates/zed2/src/main.rs | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7237ab6905..3226037d51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12198,6 +12198,7 @@ dependencies = [ "journal2", "language2", "language_selector2", + "language_tools2", "lazy_static", "libc", "log", diff --git a/crates/zed2/Cargo.toml b/crates/zed2/Cargo.toml index 6646eb5ffc..8cc3333484 100644 --- a/crates/zed2/Cargo.toml +++ b/crates/zed2/Cargo.toml @@ -47,7 +47,7 @@ language = { package = "language2", path = "../language2" } language_selector = { package = "language_selector2", path = "../language_selector2" } lsp = { package = "lsp2", path = "../lsp2" } menu = { package = "menu2", path = "../menu2" } -# language_tools = { path = "../language_tools" } +language_tools = { package = "language_tools2", path = "../language_tools2" } node_runtime = { path = "../node_runtime" } notifications = { package = "notifications2", path = "../notifications2" } assistant = { package = "assistant2", path = "../assistant2" } diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index ca8cd7a2a2..f4d9aa2510 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -217,8 +217,7 @@ fn main() { // journal2::init(app_state.clone(), cx); language_selector::init(cx); theme_selector::init(cx); - // activity_indicator::init(cx); - // language_tools::init(cx); + language_tools::init(cx); call::init(app_state.client.clone(), app_state.user_store.clone(), cx); notifications::init(app_state.client.clone(), app_state.user_store.clone(), cx); collab_ui::init(&app_state, cx); From 3586bf8b6ba2b275ccaa2f95dca10b45a5845cfa Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 17:38:52 +0200 Subject: [PATCH 194/644] Display something --- crates/language_tools2/src/lsp_log.rs | 10 ++++++++-- crates/language_tools2/src/syntax_tree_view.rs | 18 ++++++++++++++---- crates/zed2/src/zed2.rs | 11 +++++------ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 3c3df41442..06cdaf3bf9 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -741,11 +741,13 @@ impl Render for LspLogToolbarItemView { let _server_selected = current_server.is_some(); let lsp_menu = h_stack() + .size_full() .child(Self::render_language_server_menu_header(current_server, cx)) .children(if self.menu_open { Some( overlay().child( v_stack() + .size_full() // todo!() // .scrollable::(0, None, cx) .children(menu_rows.into_iter().map(|row| { @@ -769,11 +771,11 @@ impl Render for LspLogToolbarItemView { // .with_hoverable(true) // .with_fit_mode(OverlayFitMode::SwitchAnchor) // .with_anchor_corner(AnchorCorner::TopLeft) - // .with_z_index(999), ) } else { None - }); + }) + .z_index(99); let log_cleanup_button = div() .child(Label::new("Clear")) @@ -794,6 +796,7 @@ impl Render for LspLogToolbarItemView { .cursor(CursorStyle::PointingHand); h_stack() + .size_full() .child(lsp_menu) .child(log_cleanup_button) .border_1() @@ -897,6 +900,7 @@ impl LspLogToolbarItemView { cx: &mut ViewContext, ) -> Div { v_stack() + .size_full() .child(Label::new(format!("{} ({})", name.0, worktree_root_name))) .child( div() @@ -911,6 +915,7 @@ impl LspLogToolbarItemView { ) .child( h_stack() + .size_full() .child(Label::new(RPC_MESSAGES)) .child( Checkbox::new( @@ -940,6 +945,7 @@ impl LspLogToolbarItemView { ) .border_1() .border_color(red()) + .bg(red()) } } diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index 9c8ec0ee04..4c9e7529c5 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -319,7 +319,7 @@ impl SyntaxTreeView { anonymous_node_style.color = color; } - let mut row = h_stack(); + let mut row = h_stack().size_full(); if let Some(field_name) = cursor.field_name() { let mut field_style = style.clone(); if let Some(color) = property_color { @@ -378,6 +378,8 @@ impl Render for SyntaxTreeView { self.hover_state_changed(cx); } + let mut rendered = div(); + if let Some(layer) = self .editor .as_ref() @@ -390,7 +392,7 @@ impl Render for SyntaxTreeView { // todo!() // let list_hovered = state.hovered(); let list_hovered = false; - uniform_list( + let list = uniform_list( cx.view().clone(), "SyntaxTreeView", layer.node().descendant_count(), @@ -444,9 +446,11 @@ impl Render for SyntaxTreeView { }), ) .text_bg(editor_colors.background); + + rendered = rendered.child(list); } - div() + rendered } } @@ -505,10 +509,12 @@ impl SyntaxTreeToolbarItemView { Some( v_stack() + .size_full() .child(Self::render_header(&active_layer, cx)) .children(self.menu_open.then(|| { overlay().child( v_stack() + .size_full() .children(active_buffer.syntax_layers().enumerate().map( |(ix, layer)| Self::render_menu_item(&active_layer, layer, ix, cx), )) @@ -519,7 +525,8 @@ impl SyntaxTreeToolbarItemView { } })), ) - })), + })) + .z_index(99), ) } @@ -545,6 +552,7 @@ impl SyntaxTreeToolbarItemView { fn render_header(active_layer: &OwnedSyntaxLayerInfo, cx: &mut ViewContext) -> Div { h_stack() + .size_full() .child(Label::new(active_layer.language.name())) .child(Label::new(format_node_range(active_layer.node()))) .on_mouse_down( @@ -567,6 +575,7 @@ impl SyntaxTreeToolbarItemView { // todo!() styling let _is_selected = layer.node() == active_layer.node(); h_stack() + .size_full() .child(Label::new(layer.language.name().to_string())) .child(Label::new(format_node_range(layer.node()))) .cursor(CursorStyle::PointingHand) @@ -578,6 +587,7 @@ impl SyntaxTreeToolbarItemView { ) .border_1() .border_color(red()) + .bg(red()) } } diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index 27e32fff17..aa21a3e995 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -429,12 +429,11 @@ fn initialize_pane(workspace: &mut Workspace, pane: &View, cx: &mut ViewCo toolbar.add_item(diagnostic_editor_controls, cx); let project_search_bar = cx.build_view(|_| ProjectSearchBar::new()); toolbar.add_item(project_search_bar, cx); - // let lsp_log_item = - // cx.add_view(|_| language_tools::LspLogToolbarItemView::new()); - // toolbar.add_item(lsp_log_item, cx); - // let syntax_tree_item = cx - // .add_view(|_| language_tools::SyntaxTreeToolbarItemView::new()); - // toolbar.add_item(syntax_tree_item, cx); + let lsp_log_item = cx.build_view(|_| language_tools::LspLogToolbarItemView::new()); + toolbar.add_item(lsp_log_item, cx); + let syntax_tree_item = + cx.build_view(|_| language_tools::SyntaxTreeToolbarItemView::new()); + toolbar.add_item(syntax_tree_item, cx); }) }); } From 6a90a76bf2353ea03a86523e287495234cc5b56b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 15 Dec 2023 23:50:20 +0200 Subject: [PATCH 195/644] Use stock gpui2 ui components --- crates/language_tools2/src/lsp_log.rs | 183 +++++++----------- .../language_tools2/src/syntax_tree_view.rs | 143 ++++---------- crates/ui2/src/components/context_menu.rs | 2 +- 3 files changed, 114 insertions(+), 214 deletions(-) diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 06cdaf3bf9..3cff408280 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -2,16 +2,18 @@ use collections::{HashMap, VecDeque}; use editor::{Editor, EditorElement, EditorEvent, MoveToEnd}; use futures::{channel::mpsc, StreamExt}; use gpui::{ - actions, div, overlay, red, AnyElement, AppContext, Context, CursorStyle, Div, EventEmitter, - FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ModelContext, MouseButton, - MouseDownEvent, ParentElement, Render, Styled, Subscription, View, ViewContext, VisualContext, + actions, div, red, AnchorCorner, AnyElement, AppContext, Context, CursorStyle, Div, + EventEmitter, FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ModelContext, + MouseButton, ParentElement, Render, Styled, Subscription, View, ViewContext, VisualContext, WeakModel, WindowContext, }; use language::{LanguageServerId, LanguageServerName}; use lsp::IoKind; use project::{search::SearchQuery, Project}; use std::{borrow::Cow, sync::Arc}; -use ui::{h_stack, v_stack, Checkbox, Label}; +use ui::{ + h_stack, popover_menu, v_stack, Button, Checkbox, Clickable, ContextMenu, Divider, Label, +}; use workspace::{ item::{Item, ItemHandle}, searchable::{SearchEvent, SearchableItem, SearchableItemHandle}, @@ -58,7 +60,6 @@ pub struct LspLogView { pub struct LspLogToolbarItemView { log_view: Option>, _log_view_subscription: Option, - menu_open: bool, } #[derive(Copy, Clone, PartialEq, Eq)] @@ -594,11 +595,6 @@ fn log_contents(lines: &VecDeque) -> String { } impl Render for LspLogView { - // todo!() - // fn ui_name() -> &'static str { - // "LspLogView" - // } - type Element = EditorElement; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { @@ -697,7 +693,6 @@ impl ToolbarItemView for LspLogToolbarItemView { active_pane_item: Option<&dyn ItemHandle>, cx: &mut ViewContext, ) -> workspace::ToolbarItemLocation { - self.menu_open = false; if let Some(item) = active_pane_item { if let Some(log_view) = item.downcast::() { self.log_view = Some(log_view.clone()); @@ -715,13 +710,9 @@ impl ToolbarItemView for LspLogToolbarItemView { impl Render for LspLogToolbarItemView { type Element = Div; - // todo!() - // fn ui_name() -> &'static str { - // "LspLogView" - // } - fn render(&mut self, cx: &mut ViewContext) -> Div { - let Some(log_view) = self.log_view.as_ref() else { + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + let Some(log_view) = self.log_view.clone() else { return div(); }; let (menu_rows, current_server_id) = log_view.update(cx, |log_view, cx| { @@ -737,70 +728,63 @@ impl Render for LspLogToolbarItemView { None } }); - // todo!() styling - let _server_selected = current_server.is_some(); - let lsp_menu = h_stack() - .size_full() - .child(Self::render_language_server_menu_header(current_server, cx)) - .children(if self.menu_open { - Some( - overlay().child( - v_stack() - .size_full() - // todo!() - // .scrollable::(0, None, cx) - .children(menu_rows.into_iter().map(|row| { - Self::render_language_server_menu_item( - row.server_id, - row.server_name, - &row.worktree_root_name, - row.rpc_trace_enabled, - row.logs_selected, - row.rpc_trace_selected, - cx, - ) - })) - .on_mouse_down_out(cx.listener(|this, event: &MouseDownEvent, cx| { - if event.button == MouseButton::Left { - this.menu_open = false; - cx.notify() - } - })), - ), // todo!() - // .with_hoverable(true) - // .with_fit_mode(OverlayFitMode::SwitchAnchor) - // .with_anchor_corner(AnchorCorner::TopLeft) - ) - } else { - None - }) - .z_index(99); - - let log_cleanup_button = div() - .child(Label::new("Clear")) - .on_mouse_down( - MouseButton::Left, - cx.listener(move |this, _, cx| { - if let Some(log_view) = this.log_view.as_ref() { - log_view.update(cx, |log_view, cx| { - log_view.editor.update(cx, |editor, cx| { - editor.set_read_only(false); - editor.clear(cx); - editor.set_read_only(true); - }); - }) + let lsp_menu = popover_menu("LspLogView") + .anchor(AnchorCorner::TopLeft) + .trigger(Self::render_language_server_menu_header(current_server)) + .menu(move |cx| { + let menu_rows = menu_rows.clone(); + let log_view = log_view.clone(); + ContextMenu::build(cx, move |mut menu, cx| { + for row in menu_rows { + menu = menu + .header(format!( + "{} ({})", + row.server_name.0, row.worktree_root_name + )) + .entry( + format!("{SERVER_LOGS} ({})", row.server_name.0), + |cx| { + dbg!("????????????????????"); + }, // cx.handler_for(&log_view, move |view, cx| { + // // todo!() why does not it work??? + // dbg!("~~~~~~~~~~~~~~~~~~~~~~~~~~??@@@#", row.server_id); + // view.show_logs_for_server(row.server_id, cx) + // }), + ) + // TODO kb custom element with checkbox & toggle logging for server + .entry( + format!("{RPC_MESSAGES} ({})", row.server_name.0), + |cx| { + dbg!("?????????????@@@@@@@@@@@@@@@"); + }, // cx.handler_for(&log_view, move |view, cx| { + // view.show_rpc_trace_for_server(row.server_id, cx) + // }), + ) } - }), - ) - .cursor(CursorStyle::PointingHand); + menu + }) + }); - h_stack() - .size_full() - .child(lsp_menu) - .child(log_cleanup_button) - .border_1() - .border_color(red()) + h_stack().size_full().child(lsp_menu).child( + div() + .child( + Button::new("clear_log_button", "Clear").on_click(cx.listener( + |this, _, cx| { + if let Some(log_view) = this.log_view.as_ref() { + log_view.update(cx, |log_view, cx| { + log_view.editor.update(cx, |editor, cx| { + editor.set_read_only(false); + editor.clear(cx); + editor.set_read_only(true); + }); + }) + } + }, + )), + ) + .ml_2(), + ) } } @@ -810,17 +794,11 @@ const SERVER_LOGS: &str = "Server Logs"; impl LspLogToolbarItemView { pub fn new() -> Self { Self { - menu_open: false, log_view: None, _log_view_subscription: None, } } - fn toggle_menu(&mut self, cx: &mut ViewContext) { - self.menu_open = !self.menu_open; - cx.notify(); - } - fn toggle_logging_for_server( &mut self, id: LanguageServerId, @@ -842,7 +820,6 @@ impl LspLogToolbarItemView { fn show_logs_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { if let Some(log_view) = &self.log_view { log_view.update(cx, |view, cx| view.show_logs_for_server(id, cx)); - self.menu_open = false; cx.notify(); } } @@ -850,19 +827,16 @@ impl LspLogToolbarItemView { fn show_rpc_trace_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { if let Some(log_view) = &self.log_view { log_view.update(cx, |view, cx| view.show_rpc_trace_for_server(id, cx)); - self.menu_open = false; cx.notify(); } } - fn render_language_server_menu_header( - current_server: Option, - cx: &mut ViewContext, - ) -> Div { - let label: Cow = current_server - .and_then(|row| { - Some( - format!( + fn render_language_server_menu_header(current_server: Option) -> Button { + Button::new( + "language_server_menu_header", + current_server + .and_then(|row| { + Some(Cow::Owned(format!( "{} ({}) - {}", row.server_name.0, row.worktree_root_name, @@ -871,22 +845,10 @@ impl LspLogToolbarItemView { } else { SERVER_LOGS }, - ) - .into(), - ) - }) - .unwrap_or_else(|| "No server selected".into()); - div() - .child(Label::new(label)) - .cursor(CursorStyle::PointingHand) - .on_mouse_down( - MouseButton::Left, - cx.listener(move |view, _, cx| { - view.toggle_menu(cx); - }), - ) - .border_1() - .border_color(red()) + ))) + }) + .unwrap_or_else(|| "No server selected".into()), + ) } fn render_language_server_menu_item( @@ -894,7 +856,6 @@ impl LspLogToolbarItemView { name: LanguageServerName, worktree_root_name: &str, rpc_trace_enabled: bool, - // todo!() styling _logs_selected: bool, _rpc_trace_selected: bool, cx: &mut ViewContext, diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index 4c9e7529c5..9b205cb28b 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -1,20 +1,19 @@ use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId}; use gpui::{ - actions, div, overlay, red, uniform_list, AnyElement, AppContext, CursorStyle, Div, - EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model, - MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Render, Styled, TextStyle, - UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext, + actions, div, rems, uniform_list, AnyElement, AppContext, Div, EventEmitter, FocusHandle, + FocusableView, Hsla, InteractiveElement, IntoElement, Model, MouseButton, MouseDownEvent, + MouseMoveEvent, ParentElement, Pixels, Render, Styled, TextStyle, UniformListScrollHandle, + View, ViewContext, VisualContext, WeakView, WindowContext, }; -use language::{Buffer, OwnedSyntaxLayerInfo, SyntaxLayerInfo}; +use language::{Buffer, OwnedSyntaxLayerInfo}; use settings::Settings; use std::{mem, ops::Range}; use theme::{Theme, ThemeSettings}; use tree_sitter::{Node, TreeCursor}; -use ui::{h_stack, Label}; +use ui::{h_stack, popover_menu, ButtonLike, ContextMenu, Label, PopoverMenu}; use workspace::{ item::{Item, ItemHandle}, - ui::v_stack, - ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace, + SplitDirection, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace, }; actions!(debug, [OpenSyntaxTreeView]); @@ -26,7 +25,7 @@ pub fn init(cx: &mut AppContext) { let workspace_handle = workspace.weak_handle(); let syntax_tree_view = cx.build_view(|cx| SyntaxTreeView::new(workspace_handle, active_item, cx)); - workspace.add_item(Box::new(syntax_tree_view), cx); + workspace.split_item(SplitDirection::Right, Box::new(syntax_tree_view), cx) }); }) .detach(); @@ -46,7 +45,6 @@ pub struct SyntaxTreeView { pub struct SyntaxTreeToolbarItemView { tree_view: Option>, subscription: Option, - menu_open: bool, } struct EditorState { @@ -279,7 +277,7 @@ impl SyntaxTreeView { fn render_node( cursor: &TreeCursor, - _depth: u32, + depth: u32, selected: bool, hovered: bool, list_hovered: bool, @@ -290,18 +288,6 @@ impl SyntaxTreeView { let editor_colors = editor_theme.colors(); let node = cursor.node(); let mut range_style = style.clone(); - // todo!() styling - // let font_id = cx.text_system().font_id(&style.text.font()).unwrap(); - // let font_size = style.text.font_size.to_pixels(cx.rem_size()); - // let line_height = style.text.line_height_in_pixels(cx.rem_size()); - // let em_width = cx - // .text_system() - // .typographic_bounds(font_id, font_size, 'm') - // .unwrap() - // .size - // .width; - // let gutter_padding = (em_width * editor_theme.gutter_padding_factor).round(); - range_style.color = editor_colors.editor_line_number; let mut anonymous_node_style = style.clone(); @@ -335,8 +321,7 @@ impl SyntaxTreeView { Label::new(node.kind()) } else { Label::new(format!("\"{}\"", node.kind())) - }, // todo!() - // .margin(em_width), + }, ) .child(Label::new(format_node_range(node))) .text_bg(if selected { @@ -346,10 +331,10 @@ impl SyntaxTreeView { } else { Hsla::default() }) - // todo!() + // todo!() does not work + .ml(rems(depth as f32 * 180.0)) // .padding(gutter_padding + depth as f32 * 18.0) - .border_1() - .border_color(red()); + ; } } @@ -389,8 +374,6 @@ impl Render for SyntaxTreeView { let layer = layer.clone(); let theme = editor_theme.clone(); - // todo!() - // let list_hovered = state.hovered(); let list_hovered = false; let list = uniform_list( cx.view().clone(), @@ -434,6 +417,7 @@ impl Render for SyntaxTreeView { items }, ) + // todo!() does scroll either editor or the tree .track_scroll(self.list_scroll_handle.clone()) .on_mouse_move(cx.listener(move |tree_view, event: &MouseMoveEvent, cx| { tree_view.mouse_y = Some(event.position.y); @@ -492,13 +476,12 @@ impl Item for SyntaxTreeView { impl SyntaxTreeToolbarItemView { pub fn new() -> Self { Self { - menu_open: false, tree_view: None, subscription: None, } } - fn render_menu(&mut self, cx: &mut ViewContext<'_, Self>) -> Option
{ + fn render_menu(&mut self, cx: &mut ViewContext<'_, Self>) -> Option> { let tree_view = self.tree_view.as_ref()?; let tree_view = tree_view.read(cx); @@ -507,34 +490,30 @@ impl SyntaxTreeToolbarItemView { let active_layer = buffer_state.active_layer.clone()?; let active_buffer = buffer_state.buffer.read(cx).snapshot(); + let view = cx.view().clone(); Some( - v_stack() - .size_full() - .child(Self::render_header(&active_layer, cx)) - .children(self.menu_open.then(|| { - overlay().child( - v_stack() - .size_full() - .children(active_buffer.syntax_layers().enumerate().map( - |(ix, layer)| Self::render_menu_item(&active_layer, layer, ix, cx), - )) - .on_mouse_down_out(cx.listener(|this, e: &MouseDownEvent, cx| { - if e.button == MouseButton::Left { - this.menu_open = false; - cx.notify() - } - })), - ) - })) - .z_index(99), + popover_menu("Syntax Tree") + .trigger(Self::render_header(&active_layer)) + .menu(move |cx| { + ContextMenu::build(cx, |mut menu, cx| { + for (layer_ix, layer) in active_buffer.syntax_layers().enumerate() { + menu = menu.entry( + format!( + "{} {}", + layer.language.name(), + format_node_range(layer.node()) + ), + cx.handler_for(&view, move |view, cx| { + view.select_layer(layer_ix, cx); + }), + ); + } + menu + }) + }), ) } - fn toggle_menu(&mut self, cx: &mut ViewContext) { - self.menu_open = !self.menu_open; - cx.notify(); - } - fn select_layer(&mut self, layer_ix: usize, cx: &mut ViewContext) -> Option<()> { let tree_view = self.tree_view.as_ref()?; tree_view.update(cx, |view, cx| { @@ -544,50 +523,15 @@ impl SyntaxTreeToolbarItemView { let layer = snapshot.syntax_layers().nth(layer_ix)?; buffer_state.active_layer = Some(layer.to_owned()); view.selected_descendant_ix = None; - self.menu_open = false; cx.notify(); Some(()) }) } - fn render_header(active_layer: &OwnedSyntaxLayerInfo, cx: &mut ViewContext) -> Div { - h_stack() - .size_full() + fn render_header(active_layer: &OwnedSyntaxLayerInfo) -> ButtonLike { + ButtonLike::new("syntax tree header") .child(Label::new(active_layer.language.name())) .child(Label::new(format_node_range(active_layer.node()))) - .on_mouse_down( - MouseButton::Left, - cx.listener(move |view, _, cx| { - view.toggle_menu(cx); - }), - ) - .cursor(CursorStyle::PointingHand) - .border_1() - .border_color(red()) - } - - fn render_menu_item( - active_layer: &OwnedSyntaxLayerInfo, - layer: SyntaxLayerInfo, - layer_ix: usize, - cx: &mut ViewContext, - ) -> Div { - // todo!() styling - let _is_selected = layer.node() == active_layer.node(); - h_stack() - .size_full() - .child(Label::new(layer.language.name().to_string())) - .child(Label::new(format_node_range(layer.node()))) - .cursor(CursorStyle::PointingHand) - .on_mouse_down( - MouseButton::Left, - cx.listener(move |view, _, cx| { - view.select_layer(layer_ix, cx); - }), - ) - .border_1() - .border_color(red()) - .bg(red()) } } @@ -604,15 +548,11 @@ fn format_node_range(node: Node) -> String { } impl Render for SyntaxTreeToolbarItemView { - type Element = Div; + type Element = PopoverMenu; - // todo!() - // fn ui_name() -> &'static str { - // "SyntaxTreeToolbarItemView" - // } - - fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> Div { - self.render_menu(cx).unwrap_or_else(|| div()) + fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> PopoverMenu { + self.render_menu(cx) + .unwrap_or_else(|| popover_menu("Empty Syntax Tree")) } } @@ -624,7 +564,6 @@ impl ToolbarItemView for SyntaxTreeToolbarItemView { active_pane_item: Option<&dyn ItemHandle>, cx: &mut ViewContext, ) -> ToolbarItemLocation { - self.menu_open = false; if let Some(item) = active_pane_item { if let Some(view) = item.downcast::() { self.tree_view = Some(view.clone()); diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 8fce15d1c6..4e3c03ad80 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -9,7 +9,7 @@ use gpui::{ use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev}; use std::{rc::Rc, time::Duration}; -pub enum ContextMenuItem { +enum ContextMenuItem { Separator, Header(SharedString), Entry { From 7b83d65debcba1c1b4967be88843b98a9f8f200d Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 18 Dec 2023 19:15:54 +0200 Subject: [PATCH 196/644] Remove temporary imports, fix syntax_tree_view --- crates/gpui2/src/elements/div.rs | 39 ++-- crates/gpui2/src/elements/uniform_list.rs | 5 + crates/language_tools2/src/lsp_log.rs | 190 +++++++----------- .../language_tools2/src/syntax_tree_view.rs | 30 ++- 4 files changed, 124 insertions(+), 140 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 908b302dfc..24784d695c 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1427,8 +1427,16 @@ impl Interactivity { let line_height = cx.line_height(); let scroll_max = (content_size - bounds.size).max(&Size::default()); let interactive_bounds = interactive_bounds.clone(); - + let id = self.element_id.clone(); cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { + if id == Some(ElementId::Name("SyntaxTreeView".into())) { + dbg!( + &overflow, + event.position, + &interactive_bounds, + interactive_bounds.visibly_contains(&event.position, cx) + ); + } if phase == DispatchPhase::Bubble && interactive_bounds.visibly_contains(&event.position, cx) { @@ -1442,9 +1450,15 @@ impl Interactivity { } if overflow.y == Overflow::Scroll { - scroll_offset.y = - (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); + if id == Some(ElementId::Name("SyntaxTreeView".into())) { + println!("prev scroll offset: {old_scroll_offset:?}, scroll_max: {scroll_max:?}, delta:{delta:?}"); } + scroll_offset.y = + (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); + if id == Some(ElementId::Name("SyntaxTreeView".into())) { + println!("new scroll offset: {scroll_offset:?}, scroll_max: {scroll_max:?}, delta:{delta:?}"); + } + } if *scroll_offset != old_scroll_offset { cx.notify(); @@ -1487,15 +1501,16 @@ impl Interactivity { } cx.with_z_index(style.z_index.unwrap_or(0), |cx| { - if style.background.as_ref().is_some_and(|fill| { - fill.color().is_some_and(|color| !color.is_transparent()) - }) { - cx.add_opaque_layer(bounds) - } - f(style, scroll_offset.unwrap_or_default(), cx) - }) - }, - ); + if style.background.as_ref().is_some_and(|fill| { + fill.color().is_some_and(|color| !color.is_transparent()) + }) { + cx.add_opaque_layer(bounds) + } + + f(style, scroll_offset.unwrap_or_default(), cx) + }) + }, + ); if let Some(group) = self.group.as_ref() { GroupBounds::pop(group, cx); diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index e8587683d6..016f016024 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -127,6 +127,7 @@ impl Element for UniformList { .map(|s| s.item_size) .unwrap_or_else(|| self.measure_item(None, cx)); + let element_id = self.interactivity.element_id.clone(); let (layout_id, interactive) = self.interactivity .layout(state.map(|s| s.interactive), cx, |style, cx| { @@ -143,6 +144,10 @@ impl Element for UniformList { item_size.width } }); + + if element_id == Some(ElementId::Name("SyntaxTreeView".into())) { + dbg!(known_dimensions, available_space.height); + } let height = match available_space.height { AvailableSpace::Definite(height) => desired_height.min(height), AvailableSpace::MinContent | AvailableSpace::MaxContent => { diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 3cff408280..9a8ec9f71a 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -2,18 +2,16 @@ use collections::{HashMap, VecDeque}; use editor::{Editor, EditorElement, EditorEvent, MoveToEnd}; use futures::{channel::mpsc, StreamExt}; use gpui::{ - actions, div, red, AnchorCorner, AnyElement, AppContext, Context, CursorStyle, Div, - EventEmitter, FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ModelContext, - MouseButton, ParentElement, Render, Styled, Subscription, View, ViewContext, VisualContext, - WeakModel, WindowContext, + actions, div, AnchorCorner, AnyElement, AppContext, Context, Div, EventEmitter, FocusHandle, + FocusableView, InteractiveElement, IntoElement, Model, ModelContext, MouseButton, + ParentElement, Render, Styled, Subscription, View, ViewContext, VisualContext, WeakModel, + WindowContext, }; use language::{LanguageServerId, LanguageServerName}; use lsp::IoKind; use project::{search::SearchQuery, Project}; use std::{borrow::Cow, sync::Arc}; -use ui::{ - h_stack, popover_menu, v_stack, Button, Checkbox, Clickable, ContextMenu, Divider, Label, -}; +use ui::{h_stack, popover_menu, Button, Checkbox, Clickable, ContextMenu, Label, Selection}; use workspace::{ item::{Item, ItemHandle}, searchable::{SearchEvent, SearchableItem, SearchableItemHandle}, @@ -729,38 +727,86 @@ impl Render for LspLogToolbarItemView { } }); + let log_toolbar_view = cx.view().clone(); let lsp_menu = popover_menu("LspLogView") .anchor(AnchorCorner::TopLeft) - .trigger(Self::render_language_server_menu_header(current_server)) + .trigger(Button::new( + "language_server_menu_header", + current_server + .and_then(|row| { + Some(Cow::Owned(format!( + "{} ({}) - {}", + row.server_name.0, + row.worktree_root_name, + if row.rpc_trace_selected { + RPC_MESSAGES + } else { + SERVER_LOGS + }, + ))) + }) + .unwrap_or_else(|| "No server selected".into()), + )) .menu(move |cx| { let menu_rows = menu_rows.clone(); let log_view = log_view.clone(); + let log_toolbar_view = log_toolbar_view.clone(); ContextMenu::build(cx, move |mut menu, cx| { - for row in menu_rows { + for (ix, row) in menu_rows.into_iter().enumerate() { menu = menu .header(format!( "{} ({})", row.server_name.0, row.worktree_root_name )) .entry( - format!("{SERVER_LOGS} ({})", row.server_name.0), - |cx| { - dbg!("????????????????????"); - }, // cx.handler_for(&log_view, move |view, cx| { - // // todo!() why does not it work??? - // dbg!("~~~~~~~~~~~~~~~~~~~~~~~~~~??@@@#", row.server_id); - // view.show_logs_for_server(row.server_id, cx) - // }), - ) - // TODO kb custom element with checkbox & toggle logging for server - .entry( - format!("{RPC_MESSAGES} ({})", row.server_name.0), - |cx| { - dbg!("?????????????@@@@@@@@@@@@@@@"); - }, // cx.handler_for(&log_view, move |view, cx| { - // view.show_rpc_trace_for_server(row.server_id, cx) - // }), + SERVER_LOGS, + cx.handler_for(&log_view, move |view, cx| { + view.show_logs_for_server(row.server_id, cx) + }), ) + .custom_entry({ + let log_view = log_view.clone(); + let log_toolbar_view = log_toolbar_view.clone(); + move |cx| { + h_stack() + .w_full() + .justify_between() + .child(Label::new(RPC_MESSAGES)) + .child( + Checkbox::new( + ix, + if row.rpc_trace_enabled { + Selection::Selected + } else { + Selection::Unselected + }, + ) + .on_click( + cx.listener_for( + &log_toolbar_view, + move |view, selection, cx| { + let enabled = matches!( + selection, + Selection::Selected + ); + view.toggle_logging_for_server( + row.server_id, + enabled, + cx, + ); + }, + ), + ), + ) + .on_mouse_down( + MouseButton::Left, + cx.listener_for(&log_view, move |view, _, cx| { + view.show_rpc_trace_for_server(row.server_id, cx) + }), + ) + .into_any_element() + } + }) } menu }) @@ -816,98 +862,6 @@ impl LspLogToolbarItemView { } cx.notify(); } - - fn show_logs_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { - if let Some(log_view) = &self.log_view { - log_view.update(cx, |view, cx| view.show_logs_for_server(id, cx)); - cx.notify(); - } - } - - fn show_rpc_trace_for_server(&mut self, id: LanguageServerId, cx: &mut ViewContext) { - if let Some(log_view) = &self.log_view { - log_view.update(cx, |view, cx| view.show_rpc_trace_for_server(id, cx)); - cx.notify(); - } - } - - fn render_language_server_menu_header(current_server: Option) -> Button { - Button::new( - "language_server_menu_header", - current_server - .and_then(|row| { - Some(Cow::Owned(format!( - "{} ({}) - {}", - row.server_name.0, - row.worktree_root_name, - if row.rpc_trace_selected { - RPC_MESSAGES - } else { - SERVER_LOGS - }, - ))) - }) - .unwrap_or_else(|| "No server selected".into()), - ) - } - - fn render_language_server_menu_item( - id: LanguageServerId, - name: LanguageServerName, - worktree_root_name: &str, - rpc_trace_enabled: bool, - _logs_selected: bool, - _rpc_trace_selected: bool, - cx: &mut ViewContext, - ) -> Div { - v_stack() - .size_full() - .child(Label::new(format!("{} ({})", name.0, worktree_root_name))) - .child( - div() - .child(Label::new(SERVER_LOGS)) - .cursor(CursorStyle::PointingHand) - .on_mouse_down( - MouseButton::Left, - cx.listener(move |view, _, cx| { - view.show_logs_for_server(id, cx); - }), - ), - ) - .child( - h_stack() - .size_full() - .child(Label::new(RPC_MESSAGES)) - .child( - Checkbox::new( - id.0, - if rpc_trace_enabled { - ui::Selection::Selected - } else { - ui::Selection::Unselected - }, - ) - .on_click(cx.listener( - move |this, selection, cx| { - let enabled = matches!(selection, ui::Selection::Selected); - this.toggle_logging_for_server(id, enabled, cx); - }, - )), - ) - .border_1() - .border_color(red()) - .cursor(CursorStyle::PointingHand) - .on_mouse_down( - MouseButton::Left, - cx.listener(move |view, _, cx| { - view.show_rpc_trace_for_server(id, cx); - }), - ), - ) - .border_1() - .border_color(red()) - .bg(red()) - } } pub enum Event { diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index 9b205cb28b..62efda19b5 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -1,9 +1,9 @@ use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId}; use gpui::{ - actions, div, rems, uniform_list, AnyElement, AppContext, Div, EventEmitter, FocusHandle, - FocusableView, Hsla, InteractiveElement, IntoElement, Model, MouseButton, MouseDownEvent, - MouseMoveEvent, ParentElement, Pixels, Render, Styled, TextStyle, UniformListScrollHandle, - View, ViewContext, VisualContext, WeakView, WindowContext, + actions, canvas, div, rems, uniform_list, AnyElement, AppContext, AvailableSpace, Div, + EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model, + MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Render, Styled, TextStyle, + UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext, }; use language::{Buffer, OwnedSyntaxLayerInfo}; use settings::Settings; @@ -305,7 +305,7 @@ impl SyntaxTreeView { anonymous_node_style.color = color; } - let mut row = h_stack().size_full(); + let mut row = h_stack().bg(gpui::yellow()); if let Some(field_name) = cursor.field_name() { let mut field_style = style.clone(); if let Some(color) = property_color { @@ -332,7 +332,8 @@ impl SyntaxTreeView { Hsla::default() }) // todo!() does not work - .ml(rems(depth as f32 * 180.0)) + // .ml(rems(dbg!(depth) as f32 * 10.0)) + .pl(rems(dbg!(depth) as f32 * 10.0)) // .padding(gutter_padding + depth as f32 * 18.0) ; } @@ -341,7 +342,7 @@ impl SyntaxTreeView { impl Render for SyntaxTreeView { type Element = Div; - fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Div { + fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Self::Element { let settings = ThemeSettings::get_global(cx); let font = settings.buffer_font.clone(); let font_size = settings.buffer_font_size(cx); @@ -363,7 +364,7 @@ impl Render for SyntaxTreeView { self.hover_state_changed(cx); } - let mut rendered = div(); + let mut rendered = div().flex_1(); if let Some(layer) = self .editor @@ -417,7 +418,7 @@ impl Render for SyntaxTreeView { items }, ) - // todo!() does scroll either editor or the tree + .size_full() .track_scroll(self.list_scroll_handle.clone()) .on_mouse_move(cx.listener(move |tree_view, event: &MouseMoveEvent, cx| { tree_view.mouse_y = Some(event.position.y); @@ -431,7 +432,16 @@ impl Render for SyntaxTreeView { ) .text_bg(editor_colors.background); - rendered = rendered.child(list); + rendered = rendered.child( + canvas(move |bounds, cx| { + list.into_any_element().draw( + bounds.origin, + bounds.size.map(AvailableSpace::Definite), + cx, + ) + }) + .size_full(), + ); } rendered From 1474816a932bbb50018591059573e182847a4d5a Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 20 Dec 2023 12:18:26 +0200 Subject: [PATCH 197/644] Syntax tree panel style fixes --- crates/gpui2/src/elements/div.rs | 37 +++------ .../language_tools2/src/syntax_tree_view.rs | 80 +++++-------------- crates/ui2/src/components/context_menu.rs | 36 ++++++--- 3 files changed, 56 insertions(+), 97 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 24784d695c..55791a56a9 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1427,16 +1427,7 @@ impl Interactivity { let line_height = cx.line_height(); let scroll_max = (content_size - bounds.size).max(&Size::default()); let interactive_bounds = interactive_bounds.clone(); - let id = self.element_id.clone(); cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - if id == Some(ElementId::Name("SyntaxTreeView".into())) { - dbg!( - &overflow, - event.position, - &interactive_bounds, - interactive_bounds.visibly_contains(&event.position, cx) - ); - } if phase == DispatchPhase::Bubble && interactive_bounds.visibly_contains(&event.position, cx) { @@ -1450,15 +1441,9 @@ impl Interactivity { } if overflow.y == Overflow::Scroll { - if id == Some(ElementId::Name("SyntaxTreeView".into())) { - println!("prev scroll offset: {old_scroll_offset:?}, scroll_max: {scroll_max:?}, delta:{delta:?}"); + scroll_offset.y = + (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); } - scroll_offset.y = - (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); - if id == Some(ElementId::Name("SyntaxTreeView".into())) { - println!("new scroll offset: {scroll_offset:?}, scroll_max: {scroll_max:?}, delta:{delta:?}"); - } - } if *scroll_offset != old_scroll_offset { cx.notify(); @@ -1501,16 +1486,16 @@ impl Interactivity { } cx.with_z_index(style.z_index.unwrap_or(0), |cx| { - if style.background.as_ref().is_some_and(|fill| { - fill.color().is_some_and(|color| !color.is_transparent()) - }) { - cx.add_opaque_layer(bounds) - } + if style.background.as_ref().is_some_and(|fill| { + fill.color().is_some_and(|color| !color.is_transparent()) + }) { + cx.add_opaque_layer(bounds) + } - f(style, scroll_offset.unwrap_or_default(), cx) - }) - }, - ); + f(style, scroll_offset.unwrap_or_default(), cx) + }) + }, + ); if let Some(group) = self.group.as_ref() { GroupBounds::pop(group, cx); diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index 62efda19b5..0fd33cb3cd 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -2,7 +2,7 @@ use editor::{scroll::autoscroll::Autoscroll, Anchor, Editor, ExcerptId}; use gpui::{ actions, canvas, div, rems, uniform_list, AnyElement, AppContext, AvailableSpace, Div, EventEmitter, FocusHandle, FocusableView, Hsla, InteractiveElement, IntoElement, Model, - MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Render, Styled, TextStyle, + MouseButton, MouseDownEvent, MouseMoveEvent, ParentElement, Pixels, Render, Styled, UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext, }; use language::{Buffer, OwnedSyntaxLayerInfo}; @@ -10,7 +10,7 @@ use settings::Settings; use std::{mem, ops::Range}; use theme::{Theme, ThemeSettings}; use tree_sitter::{Node, TreeCursor}; -use ui::{h_stack, popover_menu, ButtonLike, ContextMenu, Label, PopoverMenu}; +use ui::{h_stack, popover_menu, ButtonLike, Color, ContextMenu, Label, LabelCommon, PopoverMenu}; use workspace::{ item::{Item, ItemHandle}, SplitDirection, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace, @@ -279,63 +279,34 @@ impl SyntaxTreeView { cursor: &TreeCursor, depth: u32, selected: bool, - hovered: bool, - list_hovered: bool, - style: &TextStyle, editor_theme: &Theme, _cx: &AppContext, ) -> Div { let editor_colors = editor_theme.colors(); - let node = cursor.node(); - let mut range_style = style.clone(); - range_style.color = editor_colors.editor_line_number; - - let mut anonymous_node_style = style.clone(); - let string_color = editor_theme - .syntax() - .highlights - .iter() - .find_map(|(name, style)| (name == "string").then(|| style.color)?); - let property_color = editor_theme - .syntax() - .highlights - .iter() - .find_map(|(name, style)| (name == "property").then(|| style.color)?); - if let Some(color) = string_color { - anonymous_node_style.color = color; - } - - let mut row = h_stack().bg(gpui::yellow()); + let mut row = h_stack(); if let Some(field_name) = cursor.field_name() { - let mut field_style = style.clone(); - if let Some(color) = property_color { - field_style.color = color; - } - - row = row.children([Label::new(field_name), Label::new(": ")]); + row = row.children([Label::new(field_name).color(Color::Info), Label::new(": ")]); } + let node = cursor.node(); return row + .child(if node.is_named() { + Label::new(node.kind()).color(Color::Default) + } else { + Label::new(format!("\"{}\"", node.kind())).color(Color::Created) + }) .child( - if node.is_named() { - Label::new(node.kind()) - } else { - Label::new(format!("\"{}\"", node.kind())) - }, + div() + .child(Label::new(format_node_range(node)).color(Color::Muted)) + .pl_1(), ) - .child(Label::new(format_node_range(node))) .text_bg(if selected { editor_colors.element_selected - } else if hovered && list_hovered { - editor_colors.element_active } else { Hsla::default() }) - // todo!() does not work - // .ml(rems(dbg!(depth) as f32 * 10.0)) - .pl(rems(dbg!(depth) as f32 * 10.0)) - // .padding(gutter_padding + depth as f32 * 18.0) - ; + .pl(rems(depth as f32)) + .hover(|style| style.bg(editor_colors.element_active)); } } @@ -344,21 +315,11 @@ impl Render for SyntaxTreeView { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Self::Element { let settings = ThemeSettings::get_global(cx); - let font = settings.buffer_font.clone(); - let font_size = settings.buffer_font_size(cx); - let editor_theme = settings.active_theme.clone(); let editor_colors = editor_theme.colors(); - let style = TextStyle { - color: editor_colors.text, - font_family: font.family, - font_features: font.features, - font_weight: font.weight, - font_style: font.style, - ..Default::default() - }; - - let line_height = cx.text_style().line_height_in_pixels(font_size); + let line_height = cx + .text_style() + .line_height_in_pixels(settings.buffer_font_size(cx)); if Some(line_height) != self.line_height { self.line_height = Some(line_height); self.hover_state_changed(cx); @@ -374,8 +335,6 @@ impl Render for SyntaxTreeView { { let layer = layer.clone(); let theme = editor_theme.clone(); - - let list_hovered = false; let list = uniform_list( cx.view().clone(), "SyntaxTreeView", @@ -401,9 +360,6 @@ impl Render for SyntaxTreeView { &cursor, depth, Some(descendant_ix) == this.selected_descendant_ix, - Some(descendant_ix) == this.hovered_descendant_ix, - list_hovered, - &style, &theme, cx, )); diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 4e3c03ad80..940d41a94c 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -3,8 +3,8 @@ use crate::{ ListSeparator, ListSubHeader, }; use gpui::{ - px, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, - IntoElement, Render, Subscription, View, VisualContext, + px, Action, AnyElement, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, + FocusableView, IntoElement, Render, Subscription, View, VisualContext, }; use menu::{SelectFirst, SelectLast, SelectNext, SelectPrev}; use std::{rc::Rc, time::Duration}; @@ -18,6 +18,9 @@ enum ContextMenuItem { handler: Rc, action: Option>, }, + CustomEntry { + entry_render: Box AnyElement>, + }, } pub struct ContextMenu { @@ -83,6 +86,16 @@ impl ContextMenu { self } + pub fn custom_entry( + mut self, + entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static, + ) -> Self { + self.items.push(ContextMenuItem::CustomEntry { + entry_render: Box::new(entry_render), + }); + self + } + pub fn action(mut self, label: impl Into, action: Box) -> Self { self.items.push(ContextMenuItem::Entry { label: label.into(), @@ -230,9 +243,9 @@ impl Render for ContextMenu { el }) .flex_none() - .child( - List::new().children(self.items.iter().enumerate().map( - |(ix, item)| match item { + .child(List::new().children(self.items.iter_mut().enumerate().map( + |(ix, item)| { + match item { ContextMenuItem::Separator => ListSeparator.into_any_element(), ContextMenuItem::Header(header) => { ListSubHeader::new(header.clone()).into_any_element() @@ -255,7 +268,7 @@ impl Render for ContextMenu { Label::new(label.clone()).into_any_element() }; - ListItem::new(label.clone()) + ListItem::new(ix) .inset(true) .selected(Some(ix) == self.selected_index) .on_click(move |_, cx| handler(cx)) @@ -271,9 +284,14 @@ impl Render for ContextMenu { ) .into_any_element() } - }, - )), - ), + ContextMenuItem::CustomEntry { entry_render } => ListItem::new(ix) + .inset(true) + .selected(Some(ix) == self.selected_index) + .child(entry_render(cx)) + .into_any_element(), + } + }, + ))), ) } } From fe40e3920bc1126bc5ad2186e09c0b407db6a20d Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 20 Dec 2023 17:02:03 +0200 Subject: [PATCH 198/644] Fix remaining z-index bugs Co-Authored-By: Antonio Scandurra --- crates/collab_ui2/src/collab_titlebar_item.rs | 1 - crates/gpui2/src/window.rs | 10 ++++++++++ crates/ui2/src/components/tab_bar.rs | 1 - crates/workspace2/src/toolbar.rs | 1 - 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index ae66485919..24e510ae8d 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -68,7 +68,6 @@ impl Render for CollabTitlebarItem { h_stack() .id("titlebar") - .z_index(160) // todo!("z-index") .justify_between() .w_full() .h(rems(1.75)) diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 07be281f0a..986458ebf7 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -2057,9 +2057,14 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { size: self.window().viewport_size, }, }; + let new_stacking_order_id = + post_inc(&mut self.window_mut().next_frame.next_stacking_order_id); + let old_stacking_order = mem::take(&mut self.window_mut().next_frame.z_index_stack); + self.window_mut().next_frame.z_index_stack.id = new_stacking_order_id; self.window_mut().next_frame.content_mask_stack.push(mask); let result = f(self); self.window_mut().next_frame.content_mask_stack.pop(); + self.window_mut().next_frame.z_index_stack = old_stacking_order; result } @@ -2068,9 +2073,14 @@ pub trait BorrowWindow: BorrowMut + BorrowMut { fn with_z_index(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R { let new_stacking_order_id = post_inc(&mut self.window_mut().next_frame.next_stacking_order_id); + let old_stacking_order_id = mem::replace( + &mut self.window_mut().next_frame.z_index_stack.id, + new_stacking_order_id, + ); self.window_mut().next_frame.z_index_stack.id = new_stacking_order_id; self.window_mut().next_frame.z_index_stack.push(z_index); let result = f(self); + self.window_mut().next_frame.z_index_stack.id = old_stacking_order_id; self.window_mut().next_frame.z_index_stack.pop(); result } diff --git a/crates/ui2/src/components/tab_bar.rs b/crates/ui2/src/components/tab_bar.rs index d2e6e9518b..7cff2f51bd 100644 --- a/crates/ui2/src/components/tab_bar.rs +++ b/crates/ui2/src/components/tab_bar.rs @@ -96,7 +96,6 @@ impl RenderOnce for TabBar { div() .id(self.id) - .z_index(120) // todo!("z-index") .group("tab_bar") .flex() .flex_none() diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index 7436232b04..cd25582f36 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -105,7 +105,6 @@ impl Render for Toolbar { v_stack() .p_1() .gap_2() - .z_index(80) // todo!("z-index") .border_b() .border_color(cx.theme().colors().border_variant) .bg(cx.theme().colors().toolbar_background) From 19d15681406ad2cbf7db855a42320c75eecfd5e9 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 20 Dec 2023 17:11:04 +0200 Subject: [PATCH 199/644] Lsp log selector fixes --- crates/gpui2/src/elements/uniform_list.rs | 4 - crates/language_tools2/src/lsp_log.rs | 104 ++++++++++-------- .../language_tools2/src/syntax_tree_view.rs | 22 +--- crates/ui2/src/components/context_menu.rs | 23 ++-- 4 files changed, 82 insertions(+), 71 deletions(-) diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 016f016024..82eac59097 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -127,7 +127,6 @@ impl Element for UniformList { .map(|s| s.item_size) .unwrap_or_else(|| self.measure_item(None, cx)); - let element_id = self.interactivity.element_id.clone(); let (layout_id, interactive) = self.interactivity .layout(state.map(|s| s.interactive), cx, |style, cx| { @@ -145,9 +144,6 @@ impl Element for UniformList { } }); - if element_id == Some(ElementId::Name("SyntaxTreeView".into())) { - dbg!(known_dimensions, available_space.height); - } let height = match available_space.height { AvailableSpace::Definite(height) => desired_height.min(height), AvailableSpace::MinContent | AvailableSpace::MaxContent => { diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 9a8ec9f71a..20039d3908 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -520,6 +520,7 @@ impl LspLogView { self.editor_subscription = editor_subscription; cx.notify(); } + cx.focus(&self.focus_handle); } fn show_rpc_trace_for_server( @@ -560,6 +561,8 @@ impl LspLogView { self.editor_subscription = editor_subscription; cx.notify(); } + + cx.focus(&self.focus_handle); } fn toggle_rpc_trace_for_server( @@ -753,6 +756,7 @@ impl Render for LspLogToolbarItemView { let log_toolbar_view = log_toolbar_view.clone(); ContextMenu::build(cx, move |mut menu, cx| { for (ix, row) in menu_rows.into_iter().enumerate() { + let server_selected = Some(row.server_id) == current_server_id; menu = menu .header(format!( "{} ({})", @@ -761,52 +765,65 @@ impl Render for LspLogToolbarItemView { .entry( SERVER_LOGS, cx.handler_for(&log_view, move |view, cx| { - view.show_logs_for_server(row.server_id, cx) + view.show_logs_for_server(row.server_id, cx); }), - ) - .custom_entry({ - let log_view = log_view.clone(); - let log_toolbar_view = log_toolbar_view.clone(); - move |cx| { - h_stack() - .w_full() - .justify_between() - .child(Label::new(RPC_MESSAGES)) - .child( - Checkbox::new( - ix, - if row.rpc_trace_enabled { - Selection::Selected - } else { - Selection::Unselected + ); + if server_selected && row.logs_selected { + debug_assert_eq!( + Some(ix * 3 + 1), + menu.select_last(), + "Could not scroll to a just added LSP menu item" + ); + } + + menu = menu.custom_entry({ + let log_view = log_view.clone(); + let log_toolbar_view = log_toolbar_view.clone(); + move |cx| { + h_stack() + .w_full() + .justify_between() + .child(Label::new(RPC_MESSAGES)) + .child( + Checkbox::new( + ix, + if row.rpc_trace_enabled { + Selection::Selected + } else { + Selection::Unselected + }, + ) + .on_click( + cx.listener_for( + &log_toolbar_view, + move |view, selection, cx| { + let enabled = + matches!(selection, Selection::Selected); + view.toggle_logging_for_server( + row.server_id, + enabled, + cx, + ); }, - ) - .on_click( - cx.listener_for( - &log_toolbar_view, - move |view, selection, cx| { - let enabled = matches!( - selection, - Selection::Selected - ); - view.toggle_logging_for_server( - row.server_id, - enabled, - cx, - ); - }, - ), ), - ) - .on_mouse_down( - MouseButton::Left, - cx.listener_for(&log_view, move |view, _, cx| { - view.show_rpc_trace_for_server(row.server_id, cx) - }), - ) - .into_any_element() - } - }) + ), + ) + .on_mouse_down( + MouseButton::Left, + cx.listener_for(&log_view, move |view, _, cx| { + view.show_rpc_trace_for_server(row.server_id, cx); + }), + ) + .into_any_element() + } + }); + if server_selected && row.rpc_trace_selected { + debug_assert_eq!( + Some(ix * 3 + 2), + menu.select_last(), + "Could not scroll to a just added LSP menu item" + ); + } } menu }) @@ -858,6 +875,7 @@ impl LspLogToolbarItemView { log_view.show_logs_for_server(id, cx); cx.notify(); } + cx.focus(&log_view.focus_handle); }); } cx.notify(); diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index 0fd33cb3cd..f0b03422cb 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -8,7 +8,7 @@ use gpui::{ use language::{Buffer, OwnedSyntaxLayerInfo}; use settings::Settings; use std::{mem, ops::Range}; -use theme::{Theme, ThemeSettings}; +use theme::{ActiveTheme, ThemeSettings}; use tree_sitter::{Node, TreeCursor}; use ui::{h_stack, popover_menu, ButtonLike, Color, ContextMenu, Label, LabelCommon, PopoverMenu}; use workspace::{ @@ -275,14 +275,8 @@ impl SyntaxTreeView { Some(()) } - fn render_node( - cursor: &TreeCursor, - depth: u32, - selected: bool, - editor_theme: &Theme, - _cx: &AppContext, - ) -> Div { - let editor_colors = editor_theme.colors(); + fn render_node(cursor: &TreeCursor, depth: u32, selected: bool, cx: &AppContext) -> Div { + let colors = cx.theme().colors(); let mut row = h_stack(); if let Some(field_name) = cursor.field_name() { row = row.children([Label::new(field_name).color(Color::Info), Label::new(": ")]); @@ -301,12 +295,12 @@ impl SyntaxTreeView { .pl_1(), ) .text_bg(if selected { - editor_colors.element_selected + colors.element_selected } else { Hsla::default() }) .pl(rems(depth as f32)) - .hover(|style| style.bg(editor_colors.element_active)); + .hover(|style| style.bg(colors.element_hover)); } } @@ -315,8 +309,6 @@ impl Render for SyntaxTreeView { fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Self::Element { let settings = ThemeSettings::get_global(cx); - let editor_theme = settings.active_theme.clone(); - let editor_colors = editor_theme.colors(); let line_height = cx .text_style() .line_height_in_pixels(settings.buffer_font_size(cx)); @@ -334,7 +326,6 @@ impl Render for SyntaxTreeView { .and_then(|buffer| buffer.active_layer.as_ref()) { let layer = layer.clone(); - let theme = editor_theme.clone(); let list = uniform_list( cx.view().clone(), "SyntaxTreeView", @@ -360,7 +351,6 @@ impl Render for SyntaxTreeView { &cursor, depth, Some(descendant_ix) == this.selected_descendant_ix, - &theme, cx, )); descendant_ix += 1; @@ -386,7 +376,7 @@ impl Render for SyntaxTreeView { tree_view.handle_click(event.position.y, cx); }), ) - .text_bg(editor_colors.background); + .text_bg(cx.theme().colors().background); rendered = rendered.child( canvas(move |bounds, cx| { diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 940d41a94c..1fda44e86d 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -122,6 +122,7 @@ impl ContextMenu { { (handler)(cx) } + cx.emit(DismissEvent); } @@ -135,14 +136,20 @@ impl ContextMenu { cx.notify(); } - fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext) { + pub fn select_last(&mut self) -> Option { for (ix, item) in self.items.iter().enumerate().rev() { if item.is_selectable() { self.selected_index = Some(ix); - cx.notify(); - break; + return Some(ix); } } + None + } + + fn handle_select_last(&mut self, _: &SelectLast, cx: &mut ViewContext) { + if self.select_last().is_some() { + cx.notify(); + } } fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext) { @@ -169,7 +176,7 @@ impl ContextMenu { } } } else { - self.select_last(&Default::default(), cx); + self.handle_select_last(&Default::default(), cx); } } @@ -195,7 +202,7 @@ impl ContextMenu { .await; this.update(&mut cx, |this, cx| { cx.dispatch_action(action); - this.cancel(&Default::default(), cx) + this.cancel(&menu::Cancel, cx) }) }) .detach_and_log_err(cx); @@ -207,7 +214,7 @@ impl ContextMenu { impl ContextMenuItem { fn is_selectable(&self) -> bool { - matches!(self, Self::Entry { .. }) + matches!(self, Self::Entry { .. } | Self::CustomEntry { .. }) } } @@ -219,10 +226,10 @@ impl Render for ContextMenu { v_stack() .min_w(px(200.)) .track_focus(&self.focus_handle) - .on_mouse_down_out(cx.listener(|this, _, cx| this.cancel(&Default::default(), cx))) + .on_mouse_down_out(cx.listener(|this, _, cx| this.cancel(&menu::Cancel, cx))) .key_context("menu") .on_action(cx.listener(ContextMenu::select_first)) - .on_action(cx.listener(ContextMenu::select_last)) + .on_action(cx.listener(ContextMenu::handle_select_last)) .on_action(cx.listener(ContextMenu::select_next)) .on_action(cx.listener(ContextMenu::select_prev)) .on_action(cx.listener(ContextMenu::confirm)) From 331af82cb16dbb474cc92fff4d57cb867ee916bf Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 20 Dec 2023 18:22:39 +0200 Subject: [PATCH 200/644] Rework context menu's custom element API to handle clicks properly --- crates/language_tools2/src/lsp_log.rs | 86 ++++++++++---------- crates/ui2/src/components/context_menu.rs | 98 +++++++++++++---------- 2 files changed, 97 insertions(+), 87 deletions(-) diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 20039d3908..597c9c5b54 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -3,9 +3,8 @@ use editor::{Editor, EditorElement, EditorEvent, MoveToEnd}; use futures::{channel::mpsc, StreamExt}; use gpui::{ actions, div, AnchorCorner, AnyElement, AppContext, Context, Div, EventEmitter, FocusHandle, - FocusableView, InteractiveElement, IntoElement, Model, ModelContext, MouseButton, - ParentElement, Render, Styled, Subscription, View, ViewContext, VisualContext, WeakModel, - WindowContext, + FocusableView, IntoElement, Model, ModelContext, ParentElement, Render, Styled, Subscription, + View, ViewContext, VisualContext, WeakModel, WindowContext, }; use language::{LanguageServerId, LanguageServerName}; use lsp::IoKind; @@ -776,47 +775,48 @@ impl Render for LspLogToolbarItemView { ); } - menu = menu.custom_entry({ - let log_view = log_view.clone(); - let log_toolbar_view = log_toolbar_view.clone(); - move |cx| { - h_stack() - .w_full() - .justify_between() - .child(Label::new(RPC_MESSAGES)) - .child( - Checkbox::new( - ix, - if row.rpc_trace_enabled { - Selection::Selected - } else { - Selection::Unselected - }, - ) - .on_click( - cx.listener_for( - &log_toolbar_view, - move |view, selection, cx| { - let enabled = - matches!(selection, Selection::Selected); - view.toggle_logging_for_server( - row.server_id, - enabled, - cx, - ); - }, + menu = menu.custom_entry( + { + let log_toolbar_view = log_toolbar_view.clone(); + move |cx| { + h_stack() + .w_full() + .justify_between() + .child(Label::new(RPC_MESSAGES)) + .child( + div().z_index(120).child( + Checkbox::new( + ix, + if row.rpc_trace_enabled { + Selection::Selected + } else { + Selection::Unselected + }, + ) + .on_click(cx.listener_for( + &log_toolbar_view, + move |view, selection, cx| { + let enabled = matches!( + selection, + Selection::Selected + ); + view.toggle_logging_for_server( + row.server_id, + enabled, + cx, + ); + cx.stop_propagation(); + }, + )), ), - ), - ) - .on_mouse_down( - MouseButton::Left, - cx.listener_for(&log_view, move |view, _, cx| { - view.show_rpc_trace_for_server(row.server_id, cx); - }), - ) - .into_any_element() - } - }); + ) + .into_any_element() + } + }, + cx.handler_for(&log_view, move |view, cx| { + view.show_rpc_trace_for_server(row.server_id, cx); + }), + ); if server_selected && row.rpc_trace_selected { debug_assert_eq!( Some(ix * 3 + 2), diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 1fda44e86d..97bb3865ef 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -20,6 +20,7 @@ enum ContextMenuItem { }, CustomEntry { entry_render: Box AnyElement>, + handler: Rc, }, } @@ -89,9 +90,11 @@ impl ContextMenu { pub fn custom_entry( mut self, entry_render: impl Fn(&mut WindowContext) -> AnyElement + 'static, + handler: impl Fn(&mut WindowContext) + 'static, ) -> Self { self.items.push(ContextMenuItem::CustomEntry { entry_render: Box::new(entry_render), + handler: Rc::new(handler), }); self } @@ -117,10 +120,12 @@ impl ContextMenu { } pub fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext) { - if let Some(ContextMenuItem::Entry { handler, .. }) = - self.selected_index.and_then(|ix| self.items.get(ix)) - { - (handler)(cx) + match self.selected_index.and_then(|ix| self.items.get(ix)) { + Some( + ContextMenuItem::Entry { handler, .. } + | ContextMenuItem::CustomEntry { handler, .. }, + ) => (handler)(cx), + _ => {} } cx.emit(DismissEvent); @@ -251,51 +256,56 @@ impl Render for ContextMenu { }) .flex_none() .child(List::new().children(self.items.iter_mut().enumerate().map( - |(ix, item)| { - match item { - ContextMenuItem::Separator => ListSeparator.into_any_element(), - ContextMenuItem::Header(header) => { - ListSubHeader::new(header.clone()).into_any_element() - } - ContextMenuItem::Entry { - label, - handler, - icon, - action, - } => { - let handler = handler.clone(); + |(ix, item)| match item { + ContextMenuItem::Separator => ListSeparator.into_any_element(), + ContextMenuItem::Header(header) => { + ListSubHeader::new(header.clone()).into_any_element() + } + ContextMenuItem::Entry { + label, + handler, + icon, + action, + } => { + let handler = handler.clone(); - let label_element = if let Some(icon) = icon { - h_stack() - .gap_1() - .child(Label::new(label.clone())) - .child(IconElement::new(*icon)) - .into_any_element() - } else { - Label::new(label.clone()).into_any_element() - }; - - ListItem::new(ix) - .inset(true) - .selected(Some(ix) == self.selected_index) - .on_click(move |_, cx| handler(cx)) - .child( - h_stack() - .w_full() - .justify_between() - .child(label_element) - .children(action.as_ref().and_then(|action| { - KeyBinding::for_action(&**action, cx) - .map(|binding| div().ml_1().child(binding)) - })), - ) + let label_element = if let Some(icon) = icon { + h_stack() + .gap_1() + .child(Label::new(label.clone())) + .child(IconElement::new(*icon)) .into_any_element() - } - ContextMenuItem::CustomEntry { entry_render } => ListItem::new(ix) + } else { + Label::new(label.clone()).into_any_element() + }; + + ListItem::new(ix) .inset(true) .selected(Some(ix) == self.selected_index) + .on_click(move |_, cx| handler(cx)) + .child( + h_stack() + .w_full() + .justify_between() + .child(label_element) + .children(action.as_ref().and_then(|action| { + KeyBinding::for_action(&**action, cx) + .map(|binding| div().ml_1().child(binding)) + })), + ) + .into_any_element() + } + ContextMenuItem::CustomEntry { + entry_render, + handler, + } => { + let handler = handler.clone(); + ListItem::new(ix) + .inset(true) + .selected(Some(ix) == self.selected_index) + .on_click(move |_, cx| handler(cx)) .child(entry_render(cx)) - .into_any_element(), + .into_any_element() } }, ))), From 5145795f33ed5a127cbff792f464156201786b9b Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 11:27:28 -0500 Subject: [PATCH 201/644] Adjust styles for notification panel container --- crates/collab_ui2/src/notification_panel.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index 35288e810d..e2deced60f 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -19,7 +19,7 @@ use serde::{Deserialize, Serialize}; use settings::{Settings, SettingsStore}; use std::{sync::Arc, time::Duration}; use time::{OffsetDateTime, UtcOffset}; -use ui::{h_stack, v_stack, Avatar, Button, Clickable, Icon, IconButton, IconElement, Label}; +use ui::{h_stack, prelude::*, v_stack, Avatar, Button, Icon, IconButton, IconElement, Label}; use util::{ResultExt, TryFutureExt}; use workspace::{ dock::{DockPosition, Panel, PanelEvent}, @@ -545,16 +545,22 @@ impl NotificationPanel { impl Render for NotificationPanel { type Element = AnyElement; - fn render(&mut self, _: &mut ViewContext) -> AnyElement { + fn render(&mut self, cx: &mut ViewContext) -> AnyElement { if self.client.user_id().is_none() { self.render_sign_in_prompt() } else if self.notification_list.item_count() == 0 { self.render_empty_state() } else { v_stack() - .bg(gpui::red()) .child( h_stack() + .justify_between() + .px_2() + .py_1() + // Match the height of the tab bar so they line up. + .h(rems(ui::Tab::HEIGHT_IN_REMS)) + .border_b_1() + .border_color(cx.theme().colors().border) .child(Label::new("Notifications")) .child(IconElement::new(Icon::Envelope)), ) From fc923a2a98044cb31c8739b9e63092edd77500c7 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Wed, 20 Dec 2023 18:28:32 +0200 Subject: [PATCH 202/644] Close syntax tree view menu on click too --- crates/language_tools2/src/syntax_tree_view.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index f0b03422cb..dcdcb612b7 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -480,6 +480,7 @@ impl SyntaxTreeToolbarItemView { buffer_state.active_layer = Some(layer.to_owned()); view.selected_descendant_ix = None; cx.notify(); + view.focus_handle.focus(cx); Some(()) }) } From 5840750b3d854575e9503a321dbeac5252ab633c Mon Sep 17 00:00:00 2001 From: Julia Date: Wed, 20 Dec 2023 11:28:56 -0500 Subject: [PATCH 203/644] Avoid workspace use while leased --- crates/workspace2/src/pane.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index dcf4ed0811..9d14c25fc7 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1452,15 +1452,15 @@ impl Pane { } fn update_status_bar(&mut self, cx: &mut ViewContext) { - let Ok(status_bar) = self - .workspace - .update(cx, |workspace, _| workspace.status_bar.clone()) - else { - return; - }; - + let workspace = self.workspace.clone(); let pane = cx.view().clone(); + cx.window_context().defer(move |cx| { + let Ok(status_bar) = workspace.update(cx, |workspace, _| workspace.status_bar.clone()) + else { + return; + }; + status_bar.update(cx, move |status_bar, cx| { status_bar.set_active_pane(&pane, cx); }); From 6e2346c53704f83431a58be09fb6d62e15c7578c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 20 Dec 2023 17:32:59 +0100 Subject: [PATCH 204/644] Prevent `ArenaRef` from being cloned --- crates/gpui2/src/arena.rs | 9 ----- crates/gpui2/src/key_dispatch.rs | 5 ++- crates/gpui2/src/window.rs | 57 +++++++++++++++++++++++--------- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index 5992baf06e..ef66188a0e 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -98,15 +98,6 @@ pub struct ArenaRef { valid: Rc>, } -impl Clone for ArenaRef { - fn clone(&self) -> Self { - Self { - ptr: self.ptr, - valid: self.valid.clone(), - } - } -} - impl ArenaRef { #[inline(always)] pub fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef { diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index a9d717ea1a..03adf887b5 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -35,7 +35,6 @@ pub(crate) struct DispatchNode { type KeyListener = ArenaRef; -#[derive(Clone)] pub(crate) struct DispatchActionListener { pub(crate) action_type: TypeId, pub(crate) listener: ArenaRef, @@ -267,6 +266,10 @@ impl DispatchTree { &self.nodes[node_id.0] } + pub fn node_mut(&mut self, node_id: DispatchNodeId) -> &mut DispatchNode { + &mut self.nodes[node_id.0] + } + fn active_node(&mut self) -> &mut DispatchNode { let active_node_id = self.active_node_id(); &mut self.nodes[active_node_id.0] diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 07be281f0a..21eb04a44f 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1572,30 +1572,43 @@ impl<'a> WindowContext<'a> { self.propagate_event = true; for node_id in &dispatch_path { - let node = self.window.rendered_frame.dispatch_tree.node(*node_id); - + let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); if let Some(context) = node.context.clone() { context_stack.push(context); } - for key_listener in node.key_listeners.clone() { + let key_listeners = mem::take(&mut node.key_listeners); + for key_listener in &key_listeners { key_listener(event, DispatchPhase::Capture, self); if !self.propagate_event { - return; + break; } } + let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); + node.key_listeners = key_listeners; + + if !self.propagate_event { + return; + } } // Bubble phase for node_id in dispatch_path.iter().rev() { // Handle low level key events - let node = self.window.rendered_frame.dispatch_tree.node(*node_id); - for key_listener in node.key_listeners.clone() { + let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); + let key_listeners = mem::take(&mut node.key_listeners); + for key_listener in &key_listeners { key_listener(event, DispatchPhase::Bubble, self); if !self.propagate_event { - return; + break; } } + let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); + node.key_listeners = key_listeners; + + if !self.propagate_event { + return; + } // Match keystrokes let node = self.window.rendered_frame.dispatch_tree.node(*node_id); @@ -1639,38 +1652,52 @@ impl<'a> WindowContext<'a> { // Capture phase for node_id in &dispatch_path { - let node = self.window.rendered_frame.dispatch_tree.node(*node_id); + let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); + let action_listeners = mem::take(&mut node.action_listeners); for DispatchActionListener { action_type, listener, - } in node.action_listeners.clone() + } in &action_listeners { let any_action = action.as_any(); - if action_type == any_action.type_id() { + if *action_type == any_action.type_id() { listener(any_action, DispatchPhase::Capture, self); if !self.propagate_event { - return; + break; } } } + let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); + node.action_listeners = action_listeners; + + if !self.propagate_event { + return; + } } // Bubble phase for node_id in dispatch_path.iter().rev() { - let node = self.window.rendered_frame.dispatch_tree.node(*node_id); + let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); + let action_listeners = mem::take(&mut node.action_listeners); for DispatchActionListener { action_type, listener, - } in node.action_listeners.clone() + } in &action_listeners { let any_action = action.as_any(); - if action_type == any_action.type_id() { + if *action_type == any_action.type_id() { self.propagate_event = false; // Actions stop propagation by default during the bubble phase listener(any_action, DispatchPhase::Bubble, self); if !self.propagate_event { - return; + break; } } } + + let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); + node.action_listeners = action_listeners; + if !self.propagate_event { + return; + } } } From 3886b1993d22ae66a89f5c32d3139553fe159bca Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 11:41:51 -0500 Subject: [PATCH 205/644] Fix formatting breakage --- crates/collab_ui2/src/collab_panel.rs | 67 ++++++++++++++------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 35e2f8d7ed..52149a481f 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -1624,40 +1624,43 @@ impl CollabPanel { } fn render_signed_out(&mut self, cx: &mut ViewContext) -> Div { - v_stack() - .items_center() - .child(v_stack().gap_6().p_4() - .child( - Label::new("Work with your team in realtime with collaborative editing, voice, shared notes and more.") - ) - .child(v_stack().gap_2() + let collab_blurb = "Work with your team in realtime with collaborative editing, voice, shared notes and more."; + v_stack().items_center().child( + v_stack() + .gap_6() + .p_4() + .child(Label::new(collab_blurb)) .child( - Button::new("sign_in", "Sign in") - .icon_color(Color::Muted) - .icon(Icon::Github) - .icon_position(IconPosition::Start) - .style(ButtonStyle::Filled) - .full_width() - .on_click(cx.listener( - |this, _, cx| { - let client = this.client.clone(); - cx.spawn(|_, mut cx| async move { - client - .authenticate_and_connect(true, &cx) - .await - .notify_async_err(&mut cx); - }) - .detach() - }, - ))) - .child( - div().flex().w_full().items_center().child( - Label::new("Sign in to enable collaboration.") - .color(Color::Muted) - .size(LabelSize::Small) - )), - )) + v_stack() + .gap_2() + .child( + Button::new("sign_in", "Sign in") + .icon_color(Color::Muted) + .icon(Icon::Github) + .icon_position(IconPosition::Start) + .style(ButtonStyle::Filled) + .full_width() + .on_click(cx.listener(|this, _, cx| { + let client = this.client.clone(); + cx.spawn(|_, mut cx| async move { + client + .authenticate_and_connect(true, &cx) + .await + .notify_async_err(&mut cx); + }) + .detach() + })), + ) + .child( + div().flex().w_full().items_center().child( + Label::new("Sign in to enable collaboration.") + .color(Color::Muted) + .size(LabelSize::Small), + ), + ), + ), + ) } fn render_list_entry(&mut self, ix: usize, cx: &mut ViewContext) -> AnyElement { From 636c12ec3f140745152b4dbd92a4fcc7160636fb Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 11:45:18 -0500 Subject: [PATCH 206/644] Style signed-out and empty states for the notification panel --- crates/collab_ui2/src/notification_panel.rs | 111 ++++++++++++-------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index e2deced60f..8a16261da4 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -439,28 +439,6 @@ impl NotificationPanel { false } - fn render_sign_in_prompt(&self) -> AnyElement { - Button::new( - "sign_in_prompt_button", - "Sign in to view your notifications", - ) - .on_click({ - let client = self.client.clone(); - move |_, cx| { - let client = client.clone(); - cx.spawn(move |cx| async move { - client.authenticate_and_connect(true, &cx).log_err().await; - }) - .detach() - } - }) - .into_any_element() - } - - fn render_empty_state(&self) -> AnyElement { - Label::new("You have no notifications").into_any_element() - } - fn on_notification_event( &mut self, _: Model, @@ -543,31 +521,72 @@ impl NotificationPanel { } impl Render for NotificationPanel { - type Element = AnyElement; + type Element = Div; - fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - if self.client.user_id().is_none() { - self.render_sign_in_prompt() - } else if self.notification_list.item_count() == 0 { - self.render_empty_state() - } else { - v_stack() - .child( - h_stack() - .justify_between() - .px_2() - .py_1() - // Match the height of the tab bar so they line up. - .h(rems(ui::Tab::HEIGHT_IN_REMS)) - .border_b_1() - .border_color(cx.theme().colors().border) - .child(Label::new("Notifications")) - .child(IconElement::new(Icon::Envelope)), - ) - .child(list(self.notification_list.clone()).size_full()) - .size_full() - .into_any_element() - } + fn render(&mut self, cx: &mut ViewContext) -> Div { + v_stack() + .size_full() + .child( + h_stack() + .justify_between() + .px_2() + .py_1() + // Match the height of the tab bar so they line up. + .h(rems(ui::Tab::HEIGHT_IN_REMS)) + .border_b_1() + .border_color(cx.theme().colors().border) + .child(Label::new("Notifications")) + .child(IconElement::new(Icon::Envelope)), + ) + .map(|this| { + if self.client.user_id().is_none() { + this.child( + v_stack() + .gap_2() + .p_4() + .child( + Button::new("sign_in_prompt_button", "Sign in") + .icon_color(Color::Muted) + .icon(Icon::Github) + .icon_position(IconPosition::Start) + .style(ButtonStyle::Filled) + .full_width() + .on_click({ + let client = self.client.clone(); + move |_, cx| { + let client = client.clone(); + cx.spawn(move |cx| async move { + client + .authenticate_and_connect(true, &cx) + .log_err() + .await; + }) + .detach() + } + }), + ) + .child( + div().flex().w_full().items_center().child( + Label::new("Sign in to view notifications.") + .color(Color::Muted) + .size(LabelSize::Small), + ), + ), + ) + } else if self.notification_list.item_count() == 0 { + this.child( + v_stack().p_4().child( + div().flex().w_full().items_center().child( + Label::new("You have no notifications.") + .color(Color::Muted) + .size(LabelSize::Small), + ), + ), + ) + } else { + this.child(list(self.notification_list.clone()).size_full()) + } + }) } } From 11140a1d348d4eb50a01b990f6bd11f1f10131bc Mon Sep 17 00:00:00 2001 From: Julia Date: Wed, 20 Dec 2023 12:15:13 -0500 Subject: [PATCH 207/644] Use ButtonLike rather than ad-hoc button Co-Authored-By: Marshall Bowers --- crates/diagnostics2/src/items.rs | 51 +++++++++++++++----------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/crates/diagnostics2/src/items.rs b/crates/diagnostics2/src/items.rs index 28bbe7aedc..14ebe0c516 100644 --- a/crates/diagnostics2/src/items.rs +++ b/crates/diagnostics2/src/items.rs @@ -1,16 +1,15 @@ use collections::HashSet; -use editor::{Editor, GoToDiagnostic}; +use editor::Editor; use gpui::{ - rems, Div, EventEmitter, InteractiveElement, IntoElement, ParentElement, Render, Stateful, - StatefulInteractiveElement, Styled, Subscription, View, ViewContext, WeakView, + rems, Div, EventEmitter, IntoElement, ParentElement, Render, Styled, Subscription, View, + ViewContext, WeakView, }; use language::Diagnostic; use lsp::LanguageServerId; -use theme::ActiveTheme; -use ui::{h_stack, Button, Clickable, Color, Icon, IconElement, Label, Tooltip}; +use ui::{h_stack, prelude::*, Button, ButtonLike, Color, Icon, IconElement, Label, Tooltip}; use workspace::{item::ItemHandle, StatusItemView, ToolbarItemEvent, Workspace}; -use crate::ProjectDiagnosticsEditor; +use crate::{Deploy, ProjectDiagnosticsEditor}; pub struct DiagnosticIndicator { summary: project::DiagnosticSummary, @@ -22,7 +21,7 @@ pub struct DiagnosticIndicator { } impl Render for DiagnosticIndicator { - type Element = Stateful
; + type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) { @@ -49,8 +48,11 @@ impl Render for DiagnosticIndicator { let message = diagnostic.message.split('\n').next().unwrap().to_string(); Some( Button::new("diagnostic_message", message) + .tooltip(|cx| { + Tooltip::for_action("Next Diagnostic", &editor::GoToDiagnostic, cx) + }) .on_click(cx.listener(|this, _, cx| { - this.go_to_next_diagnostic(&GoToDiagnostic, cx); + this.go_to_next_diagnostic(cx); })) .into_any_element(), ) @@ -59,25 +61,20 @@ impl Render for DiagnosticIndicator { }; h_stack() - .id("diagnostic-indicator") - .on_action(cx.listener(Self::go_to_next_diagnostic)) - .rounded_md() - .flex_none() .h(rems(1.375)) - .px_6() - .cursor_pointer() - .bg(cx.theme().colors().ghost_element_background) - .hover(|style| style.bg(cx.theme().colors().ghost_element_hover)) - .active(|style| style.bg(cx.theme().colors().ghost_element_active)) - .tooltip(|cx| Tooltip::text("Project Diagnostics", cx)) - .on_click(cx.listener(|this, _, cx| { - if let Some(workspace) = this.workspace.upgrade() { - workspace.update(cx, |workspace, cx| { - ProjectDiagnosticsEditor::deploy(workspace, &Default::default(), cx) - }) - } - })) - .child(diagnostic_indicator) + .gap_2() + .child( + ButtonLike::new("diagnostic-indicator") + .child(diagnostic_indicator) + .tooltip(|cx| Tooltip::for_action("Project Diagnostics", &Deploy, cx)) + .on_click(cx.listener(|this, _, cx| { + if let Some(workspace) = this.workspace.upgrade() { + workspace.update(cx, |workspace, cx| { + ProjectDiagnosticsEditor::deploy(workspace, &Default::default(), cx) + }) + } + })), + ) .children(status) } } @@ -120,7 +117,7 @@ impl DiagnosticIndicator { } } - fn go_to_next_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext) { + fn go_to_next_diagnostic(&mut self, cx: &mut ViewContext) { if let Some(editor) = self.active_editor.as_ref().and_then(|e| e.upgrade()) { editor.update(cx, |editor, cx| { editor.go_to_diagnostic_impl(editor::Direction::Next, cx); From 8f677cc0c6f589ae279d9c8a6c04dcf6e00d51d9 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 20 Dec 2023 09:43:04 -0800 Subject: [PATCH 208/644] Assign draw order to surfaces using plane splitter --- crates/gpui2/src/scene.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index 811b2b6e30..e6b601b62f 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -104,6 +104,15 @@ impl SceneBuilder { ); } + for (ix, surface) in self.surfaces.iter().enumerate() { + let z = layer_z_values[surface.order as LayerId as usize]; + self.splitter.add( + surface + .bounds + .to_bsp_polygon(z, (PrimitiveKind::Surface, ix)), + ); + } + // Sort all polygons, then reassign the order field of each primitive to `draw_order` // We need primitives to be repr(C), hence the weird reuse of the order field for two different types. for (draw_order, polygon) in self From 9c4e8699bad5502325f2a4860b9ad65aab89e6eb Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 12:45:18 -0500 Subject: [PATCH 209/644] Remove unneeded wrapping element --- crates/collab_ui2/src/collab_panel.rs | 66 +++++++++++++-------------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 52149a481f..20edd9be56 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -1626,41 +1626,39 @@ impl CollabPanel { fn render_signed_out(&mut self, cx: &mut ViewContext) -> Div { let collab_blurb = "Work with your team in realtime with collaborative editing, voice, shared notes and more."; - v_stack().items_center().child( - v_stack() - .gap_6() - .p_4() - .child(Label::new(collab_blurb)) - .child( - v_stack() - .gap_2() - .child( - Button::new("sign_in", "Sign in") - .icon_color(Color::Muted) - .icon(Icon::Github) - .icon_position(IconPosition::Start) - .style(ButtonStyle::Filled) - .full_width() - .on_click(cx.listener(|this, _, cx| { - let client = this.client.clone(); - cx.spawn(|_, mut cx| async move { - client - .authenticate_and_connect(true, &cx) - .await - .notify_async_err(&mut cx); - }) - .detach() - })), - ) - .child( - div().flex().w_full().items_center().child( - Label::new("Sign in to enable collaboration.") - .color(Color::Muted) - .size(LabelSize::Small), - ), + v_stack() + .gap_6() + .p_4() + .child(Label::new(collab_blurb)) + .child( + v_stack() + .gap_2() + .child( + Button::new("sign_in", "Sign in") + .icon_color(Color::Muted) + .icon(Icon::Github) + .icon_position(IconPosition::Start) + .style(ButtonStyle::Filled) + .full_width() + .on_click(cx.listener(|this, _, cx| { + let client = this.client.clone(); + cx.spawn(|_, mut cx| async move { + client + .authenticate_and_connect(true, &cx) + .await + .notify_async_err(&mut cx); + }) + .detach() + })), + ) + .child( + div().flex().w_full().items_center().child( + Label::new("Sign in to enable collaboration.") + .color(Color::Muted) + .size(LabelSize::Small), ), - ), - ) + ), + ) } fn render_list_entry(&mut self, ix: usize, cx: &mut ViewContext) -> AnyElement { From dc047437c6718f22a02f72c756272d37d5d47c56 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 10:46:36 -0700 Subject: [PATCH 210/644] Don't consider any element hovered when actively dragging Co-Authored-By: Antonio --- crates/gpui2/src/elements/div.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index d5284c02a1..54c0884870 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1311,6 +1311,7 @@ impl Interactivity { return; } let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) + && !cx.has_active_drag() && has_mouse_down.borrow().is_none(); let mut was_hovered = was_hovered.borrow_mut(); @@ -1538,22 +1539,25 @@ impl Interactivity { if let Some(bounds) = bounds { let mouse_position = cx.mouse_position(); - if let Some(group_hover) = self.group_hover_style.as_ref() { - if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { - if group_bounds.contains(&mouse_position) - && cx.was_top_layer(&mouse_position, cx.stacking_order()) - { - style.refine(&group_hover.style); + if !cx.has_active_drag() { + if let Some(group_hover) = self.group_hover_style.as_ref() { + if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) { + if group_bounds.contains(&mouse_position) + && cx.was_top_layer(&mouse_position, cx.stacking_order()) + { + style.refine(&group_hover.style); + } } } - } - if let Some(hover_style) = self.hover_style.as_ref() { - if bounds - .intersect(&cx.content_mask().bounds) - .contains(&mouse_position) - && cx.was_top_layer(&mouse_position, cx.stacking_order()) - { - style.refine(hover_style); + + if let Some(hover_style) = self.hover_style.as_ref() { + if bounds + .intersect(&cx.content_mask().bounds) + .contains(&mouse_position) + && cx.was_top_layer(&mouse_position, cx.stacking_order()) + { + style.refine(hover_style); + } } } From 87f879bfa974c21742a96a89a89a2a7e488999b0 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 12:48:30 -0500 Subject: [PATCH 211/644] Add text wrapping to notifications --- crates/collab_ui2/src/notification_panel.rs | 129 +++++++++++--------- 1 file changed, 68 insertions(+), 61 deletions(-) diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index 8a16261da4..e13d4bbe79 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -6,11 +6,11 @@ use collections::HashMap; use db::kvp::KEY_VALUE_STORE; use futures::StreamExt; use gpui::{ - actions, div, list, px, serde_json, AnyElement, AppContext, AsyncWindowContext, CursorStyle, - DismissEvent, Div, Element, EventEmitter, FocusHandle, FocusableView, InteractiveElement, - IntoElement, ListAlignment, ListScrollEvent, ListState, Model, ParentElement, Render, Stateful, - StatefulInteractiveElement, Styled, Task, View, ViewContext, VisualContext, WeakView, - WindowContext, + actions, div, img, list, px, serde_json, AnyElement, AppContext, AsyncWindowContext, + CursorStyle, DismissEvent, Div, Element, EventEmitter, FocusHandle, FocusableView, + InteractiveElement, IntoElement, ListAlignment, ListScrollEvent, ListState, Model, + ParentElement, Render, Stateful, StatefulInteractiveElement, Styled, Task, View, ViewContext, + VisualContext, WeakView, WindowContext, }; use notifications::{NotificationEntry, NotificationEvent, NotificationStore}; use project::Fs; @@ -227,63 +227,10 @@ impl NotificationPanel { } Some( - div() + h_stack() .id(ix) - .child( - h_stack() - .children(actor.map(|actor| Avatar::new(actor.avatar_uri.clone()))) - .child( - v_stack().child(Label::new(text)).child( - h_stack() - .child(Label::new(format_timestamp( - timestamp, - now, - self.local_timezone, - ))) - .children(if let Some(is_accepted) = response { - Some(div().child(Label::new(if is_accepted { - "You accepted" - } else { - "You declined" - }))) - } else if needs_response { - Some( - h_stack() - .child(Button::new("decline", "Decline").on_click( - { - let notification = notification.clone(); - let view = cx.view().clone(); - move |_, cx| { - view.update(cx, |this, cx| { - this.respond_to_notification( - notification.clone(), - false, - cx, - ) - }); - } - }, - )) - .child(Button::new("accept", "Accept").on_click({ - let notification = notification.clone(); - let view = cx.view().clone(); - move |_, cx| { - view.update(cx, |this, cx| { - this.respond_to_notification( - notification.clone(), - true, - cx, - ) - }); - } - })), - ) - } else { - None - }), - ), - ), - ) + .size_full() + .gap_2() .when(can_navigate, |el| { el.cursor(CursorStyle::PointingHand).on_click({ let notification = notification.clone(); @@ -292,6 +239,66 @@ impl NotificationPanel { }) }) }) + .children( + actor.map(|actor| img(actor.avatar_uri.clone()).w_8().h_8().rounded_full()), + ) + .child( + v_stack() + .gap_1() + .size_full() + .child(Label::new(text.clone())) + .child( + h_stack() + .justify_between() + .child( + Label::new(format_timestamp( + timestamp, + now, + self.local_timezone, + )) + .color(Color::Muted), + ) + .children(if let Some(is_accepted) = response { + Some(div().child(Label::new(if is_accepted { + "You accepted" + } else { + "You declined" + }))) + } else if needs_response { + Some( + h_stack() + .child(Button::new("decline", "Decline").on_click({ + let notification = notification.clone(); + let view = cx.view().clone(); + move |_, cx| { + view.update(cx, |this, cx| { + this.respond_to_notification( + notification.clone(), + false, + cx, + ) + }); + } + })) + .child(Button::new("accept", "Accept").on_click({ + let notification = notification.clone(); + let view = cx.view().clone(); + move |_, cx| { + view.update(cx, |this, cx| { + this.respond_to_notification( + notification.clone(), + true, + cx, + ) + }); + } + })), + ) + } else { + None + }), + ), + ) .into_any(), ) } From 73b13b7dc65d7b0a3e1eb67a4ba054cf55644cc3 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 20 Dec 2023 13:00:01 -0500 Subject: [PATCH 212/644] v0.119.x dev --- Cargo.lock | 2 +- crates/zed/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3226037d51..c73484b16d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12012,7 +12012,7 @@ dependencies = [ [[package]] name = "zed" -version = "0.118.0" +version = "0.119.0" dependencies = [ "activity_indicator", "ai", diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 0c115fb285..987208880b 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] description = "The fast, collaborative code editor." edition = "2021" name = "zed" -version = "0.118.0" +version = "0.119.0" publish = false [lib] From fffb30ac6d57e3974f2b12a6f97ea71dfe7da71b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 11:02:47 -0700 Subject: [PATCH 213/644] Add InteractiveElement::block_mouse which renders an "opaque" layer Co-Authored-By: Antonio Co-Authored-By: Max Brunsfeld --- crates/gpui2/src/elements/div.rs | 20 ++++++++++++++++---- crates/workspace2/src/dock.rs | 3 ++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 54c0884870..0c67d1648e 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -345,6 +345,10 @@ impl Interactivity { ); self.tooltip_builder = Some(Rc::new(build_tooltip)); } + + pub fn block_mouse(&mut self) { + self.block_mouse = true; + } } pub trait InteractiveElement: Sized { @@ -564,6 +568,11 @@ pub trait InteractiveElement: Sized { self.interactivity().on_drop(listener); self } + + fn block_mouse(mut self) -> Self { + self.interactivity().block_mouse(); + self + } } pub trait StatefulInteractiveElement: InteractiveElement { @@ -888,6 +897,7 @@ pub struct Interactivity { pub drag_listener: Option<(Box, DragListener)>, pub hover_listener: Option>, pub tooltip_builder: Option, + pub block_mouse: bool, #[cfg(debug_assertions)] pub location: Option>, @@ -1076,10 +1086,11 @@ impl Interactivity { }); } - if style - .background - .as_ref() - .is_some_and(|fill| fill.color().is_some_and(|color| !color.is_transparent())) + if self.block_mouse + || style + .background + .as_ref() + .is_some_and(|fill| fill.color().is_some_and(|color| !color.is_transparent())) { cx.add_opaque_layer(bounds) } @@ -1642,6 +1653,7 @@ impl Default for Interactivity { drag_listener: None, hover_listener: None, tooltip_builder: None, + block_mouse: false, #[cfg(debug_assertions)] location: None, diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index d0aba998b9..82f00da6f9 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -499,7 +499,8 @@ impl Render for Dock { cx.stop_propagation(); } })) - .z_index(1); + .z_index(1) + .block_mouse(); const HANDLE_SIZE: Pixels = Pixels(6.); From b0b4610a73f014333935bc72e954e2bd706d7521 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 13:05:21 -0500 Subject: [PATCH 214/644] Fix positioning of right items --- crates/collab_ui2/src/notification_panel.rs | 31 ++++++++++++++------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index e13d4bbe79..f3df2fc1d3 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -227,9 +227,13 @@ impl NotificationPanel { } Some( - h_stack() + div() .id(ix) + .flex() + .flex_row() .size_full() + .px_2() + .py_1() .gap_2() .when(can_navigate, |el| { el.cursor(CursorStyle::PointingHand).on_click({ @@ -239,9 +243,13 @@ impl NotificationPanel { }) }) }) - .children( - actor.map(|actor| img(actor.avatar_uri.clone()).w_8().h_8().rounded_full()), - ) + .children(actor.map(|actor| { + img(actor.avatar_uri.clone()) + .flex_none() + .w_8() + .h_8() + .rounded_full() + })) .child( v_stack() .gap_1() @@ -249,7 +257,6 @@ impl NotificationPanel { .child(Label::new(text.clone())) .child( h_stack() - .justify_between() .child( Label::new(format_timestamp( timestamp, @@ -259,14 +266,18 @@ impl NotificationPanel { .color(Color::Muted), ) .children(if let Some(is_accepted) = response { - Some(div().child(Label::new(if is_accepted { - "You accepted" - } else { - "You declined" - }))) + Some(div().flex().flex_grow().justify_end().child(Label::new( + if is_accepted { + "You accepted" + } else { + "You declined" + }, + ))) } else if needs_response { Some( h_stack() + .flex_grow() + .justify_end() .child(Button::new("decline", "Decline").on_click({ let notification = notification.clone(); let view = cx.view().clone(); From 4c0856e09679cea31e9cc8d5a5f05fe97e82d7f9 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 20 Dec 2023 13:15:44 -0500 Subject: [PATCH 215/644] collab 0.32.0 --- Cargo.lock | 2 +- crates/collab/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c73484b16d..af4d5317e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1753,7 +1753,7 @@ dependencies = [ [[package]] name = "collab" -version = "0.31.0" +version = "0.32.0" dependencies = [ "anyhow", "async-trait", diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index fd5c183d2a..7bab81c4ed 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -3,7 +3,7 @@ authors = ["Nathan Sobo "] default-run = "collab" edition = "2021" name = "collab" -version = "0.31.0" +version = "0.32.0" publish = false [[bin]] From da34dd49bbb648d8e696098e80ed9f2d39b5c58f Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 13:25:17 -0500 Subject: [PATCH 216/644] Fix text wrapping issues with `overflow_hidden` This seems to influence sizing calculations in ways I don't fully understand. --- crates/collab_ui2/src/notification_panel.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index f3df2fc1d3..20951b34db 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -254,6 +254,7 @@ impl NotificationPanel { v_stack() .gap_1() .size_full() + .overflow_hidden() .child(Label::new(text.clone())) .child( h_stack() From 15f16f08d986613802678eece12f2bcec35d6865 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 11:43:45 -0700 Subject: [PATCH 217/644] Move application of content mask and z-index into Interactivity::paint This allows the content mask to correctly apply to bounds used in event handlers, which prevents content under opaque borders from being hovered in overflow hidden containers. Co-Authored-By: Antonio Co-Authored-By: Max Brunsfeld --- crates/gpui2/src/elements/div.rs | 1029 +++++++++++---------- crates/gpui2/src/elements/uniform_list.rs | 86 +- crates/gpui2/src/style.rs | 131 +-- crates/workspace2/src/dock.rs | 1 + 4 files changed, 643 insertions(+), 604 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 0c67d1648e..e51c8b2a2e 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -826,17 +826,11 @@ impl Element for Div { content_size, &mut element_state.interactive_state, cx, - |style, scroll_offset, cx| { - style.paint(bounds, cx, |cx| { - cx.with_text_style(style.text_style().cloned(), |cx| { - cx.with_content_mask(style.overflow_mask(bounds), |cx| { - cx.with_element_offset(scroll_offset, |cx| { - for child in &mut self.children { - child.paint(cx); - } - }) - }) - }) + |_style, scroll_offset, cx| { + cx.with_element_offset(scroll_offset, |cx| { + for child in &mut self.children { + child.paint(cx); + } }) }, ); @@ -965,7 +959,7 @@ impl Interactivity { content_size: Size, element_state: &mut InteractiveElementState, cx: &mut WindowContext, - f: impl FnOnce(Style, Point, &mut WindowContext), + f: impl FnOnce(&Style, Point, &mut WindowContext), ) { let style = self.compute_style(Some(bounds), element_state, cx); @@ -975,50 +969,219 @@ impl Interactivity { let z_index = style.z_index.unwrap_or(0); cx.with_z_index(z_index, |cx| { - #[cfg(debug_assertions)] - if self.element_id.is_some() - && (style.debug || style.debug_below || cx.has_global::()) - && bounds.contains(&cx.mouse_position()) - { - const FONT_SIZE: crate::Pixels = crate::Pixels(10.); - let element_id = format!("{:?}", self.element_id.as_ref().unwrap()); - let str_len = element_id.len(); - - let render_debug_text = |cx: &mut WindowContext| { - if let Some(text) = cx - .text_system() - .shape_text( - &element_id, - FONT_SIZE, - &[cx.text_style().to_run(str_len)], - None, - ) - .ok() - .map(|mut text| text.pop()) - .flatten() - { - text.paint(bounds.origin, FONT_SIZE, cx).ok(); - - let text_bounds = crate::Bounds { - origin: bounds.origin, - size: text.size(FONT_SIZE), - }; - if self.location.is_some() - && text_bounds.contains(&cx.mouse_position()) - && cx.modifiers().command + style.paint(bounds, cx, |cx| { + cx.with_text_style(style.text_style().cloned(), |cx| { + cx.with_content_mask(style.overflow_mask(bounds, cx.rem_size()), |cx| { + #[cfg(debug_assertions)] + if self.element_id.is_some() + && (style.debug + || style.debug_below + || cx.has_global::()) + && bounds.contains(&cx.mouse_position()) { - let command_held = cx.modifiers().command; - cx.on_key_event({ - let text_bounds = text_bounds.clone(); - move |e: &crate::ModifiersChangedEvent, _phase, cx| { - if e.modifiers.command != command_held + const FONT_SIZE: crate::Pixels = crate::Pixels(10.); + let element_id = format!("{:?}", self.element_id.as_ref().unwrap()); + let str_len = element_id.len(); + + let render_debug_text = |cx: &mut WindowContext| { + if let Some(text) = cx + .text_system() + .shape_text( + &element_id, + FONT_SIZE, + &[cx.text_style().to_run(str_len)], + None, + ) + .ok() + .map(|mut text| text.pop()) + .flatten() + { + text.paint(bounds.origin, FONT_SIZE, cx).ok(); + + let text_bounds = crate::Bounds { + origin: bounds.origin, + size: text.size(FONT_SIZE), + }; + if self.location.is_some() && text_bounds.contains(&cx.mouse_position()) + && cx.modifiers().command { + let command_held = cx.modifiers().command; + cx.on_key_event({ + let text_bounds = text_bounds.clone(); + move |e: &crate::ModifiersChangedEvent, _phase, cx| { + if e.modifiers.command != command_held + && text_bounds.contains(&cx.mouse_position()) + { + cx.notify(); + } + } + }); + + let hovered = bounds.contains(&cx.mouse_position()); + cx.on_mouse_event( + move |event: &MouseMoveEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if bounds.contains(&event.position) != hovered { + cx.notify(); + } + } + }, + ); + + cx.on_mouse_event({ + let location = self.location.clone().unwrap(); + let text_bounds = text_bounds.clone(); + move |e: &crate::MouseDownEvent, phase, cx| { + if text_bounds.contains(&e.position) + && phase.capture() + { + cx.stop_propagation(); + let Ok(dir) = std::env::current_dir() else { + return; + }; + + eprintln!( + "This element is created at:\n{}:{}:{}", + location.file(), + location.line(), + location.column() + ); + + std::process::Command::new("zed") + .arg(format!( + "{}/{}:{}:{}", + dir.to_string_lossy(), + location.file(), + location.line(), + location.column() + )) + .spawn() + .ok(); + } + } + }); + cx.paint_quad(crate::outline( + crate::Bounds { + origin: bounds.origin + + crate::point( + crate::px(0.), + FONT_SIZE - px(2.), + ), + size: crate::Size { + width: text_bounds.size.width, + height: crate::px(1.), + }, + }, + crate::red(), + )) + } + } + }; + + cx.with_z_index(1, |cx| { + cx.with_text_style( + Some(crate::TextStyleRefinement { + color: Some(crate::red()), + line_height: Some(FONT_SIZE.into()), + background_color: Some(crate::white()), + ..Default::default() + }), + render_debug_text, + ) + }); + } + + if self.block_mouse + || style.background.as_ref().is_some_and(|fill| { + fill.color().is_some_and(|color| !color.is_transparent()) + }) + { + cx.add_opaque_layer(bounds) + } + + let interactive_bounds = InteractiveBounds { + bounds: bounds.intersect(&cx.content_mask().bounds), + stacking_order: cx.stacking_order().clone(), + }; + + if let Some(mouse_cursor) = style.mouse_cursor { + let mouse_position = &cx.mouse_position(); + let hovered = interactive_bounds.visibly_contains(mouse_position, cx); + if hovered { + cx.set_cursor_style(mouse_cursor); + } + } + + // If this element can be focused, register a mouse down listener + // that will automatically transfer focus when hitting the element. + // This behavior can be suppressed by using `cx.prevent_default()`. + if let Some(focus_handle) = element_state.focus_handle.clone() { + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + move |event: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Bubble + && !cx.default_prevented() + && interactive_bounds.visibly_contains(&event.position, cx) + { + cx.focus(&focus_handle); + // If there is a parent that is also focusable, prevent it + // from transferring focus because we already did so. + cx.prevent_default(); + } + } + }); + } + + for listener in self.mouse_down_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { + listener(event, &interactive_bounds, phase, cx); + }) + } + + for listener in self.mouse_up_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { + listener(event, &interactive_bounds, phase, cx); + }) + } + + for listener in self.mouse_move_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + listener(event, &interactive_bounds, phase, cx); + }) + } + + for listener in self.scroll_wheel_listeners.drain(..) { + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { + listener(event, &interactive_bounds, phase, cx); + }) + } + + let hover_group_bounds = self + .group_hover_style + .as_ref() + .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx)); + + if let Some(group_bounds) = hover_group_bounds { + let hovered = group_bounds.contains(&cx.mouse_position()); + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + if phase == DispatchPhase::Capture { + if group_bounds.contains(&event.position) != hovered { cx.notify(); } } }); + } + if self.hover_style.is_some() + || self.base_style.mouse_cursor.is_some() + || cx.active_drag.is_some() && !self.drag_over_styles.is_empty() + { + let bounds = bounds.intersect(&cx.content_mask().bounds); let hovered = bounds.contains(&cx.mouse_position()); cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { if phase == DispatchPhase::Capture { @@ -1027,500 +1190,350 @@ impl Interactivity { } } }); + } + let mut drag_listener = mem::take(&mut self.drag_listener); + let drop_listeners = mem::take(&mut self.drop_listeners); + let click_listeners = mem::take(&mut self.click_listeners); + + if !drop_listeners.is_empty() { cx.on_mouse_event({ - let location = self.location.clone().unwrap(); - let text_bounds = text_bounds.clone(); - move |e: &crate::MouseDownEvent, phase, cx| { - if text_bounds.contains(&e.position) && phase.capture() { - cx.stop_propagation(); - let Ok(dir) = std::env::current_dir() else { - return; - }; + let interactive_bounds = interactive_bounds.clone(); + move |event: &MouseUpEvent, phase, cx| { + if let Some(drag) = &cx.active_drag { + if phase == DispatchPhase::Bubble + && interactive_bounds + .drag_target_contains(&event.position, cx) + { + let drag_state_type = drag.value.as_ref().type_id(); + for (drop_state_type, listener) in &drop_listeners { + if *drop_state_type == drag_state_type { + let drag = cx.active_drag.take().expect( + "checked for type drag state type above", + ); - eprintln!( - "This element is created at:\n{}:{}:{}", - location.file(), - location.line(), - location.column() - ); - - std::process::Command::new("zed") - .arg(format!( - "{}/{}:{}:{}", - dir.to_string_lossy(), - location.file(), - location.line(), - location.column() - )) - .spawn() - .ok(); + listener(drag.value.as_ref(), cx); + cx.notify(); + cx.stop_propagation(); + } + } + } } } }); - cx.paint_quad(crate::outline( - crate::Bounds { - origin: bounds.origin - + crate::point(crate::px(0.), FONT_SIZE - px(2.)), - size: crate::Size { - width: text_bounds.size.width, - height: crate::px(1.), - }, - }, - crate::red(), - )) } - } - }; - cx.with_z_index(1, |cx| { - cx.with_text_style( - Some(crate::TextStyleRefinement { - color: Some(crate::red()), - line_height: Some(FONT_SIZE.into()), - background_color: Some(crate::white()), - ..Default::default() - }), - render_debug_text, - ) - }); - } + if !click_listeners.is_empty() || drag_listener.is_some() { + let pending_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); - if self.block_mouse - || style - .background - .as_ref() - .is_some_and(|fill| fill.color().is_some_and(|color| !color.is_transparent())) - { - cx.add_opaque_layer(bounds) - } + let clicked_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .clone(); - let interactive_bounds = InteractiveBounds { - bounds: bounds.intersect(&cx.content_mask().bounds), - stacking_order: cx.stacking_order().clone(), - }; + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + let pending_mouse_down = pending_mouse_down.clone(); + move |event: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Bubble + && event.button == MouseButton::Left + && interactive_bounds.visibly_contains(&event.position, cx) + { + *pending_mouse_down.borrow_mut() = Some(event.clone()); + cx.notify(); + } + } + }); - if let Some(mouse_cursor) = style.mouse_cursor { - let mouse_position = &cx.mouse_position(); - let hovered = interactive_bounds.visibly_contains(mouse_position, cx); - if hovered { - cx.set_cursor_style(mouse_cursor); - } - } + cx.on_mouse_event({ + let pending_mouse_down = pending_mouse_down.clone(); + move |event: &MouseMoveEvent, phase, cx| { + if phase == DispatchPhase::Capture { + return; + } - // If this element can be focused, register a mouse down listener - // that will automatically transfer focus when hitting the element. - // This behavior can be suppressed by using `cx.prevent_default()`. - if let Some(focus_handle) = element_state.focus_handle.clone() { - cx.on_mouse_event({ - let interactive_bounds = interactive_bounds.clone(); - move |event: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && !cx.default_prevented() - && interactive_bounds.visibly_contains(&event.position, cx) - { - cx.focus(&focus_handle); - // If there is a parent that is also focusable, prevent it - // from transferring focus because we already did so. - cx.prevent_default(); + let mut pending_mouse_down = pending_mouse_down.borrow_mut(); + if let Some(mouse_down) = pending_mouse_down.clone() { + if !cx.has_active_drag() + && (event.position - mouse_down.position).magnitude() + > DRAG_THRESHOLD + { + if let Some((drag_value, drag_listener)) = + drag_listener.take() + { + *clicked_state.borrow_mut() = + ElementClickedState::default(); + let cursor_offset = event.position - bounds.origin; + let drag = (drag_listener)(drag_value.as_ref(), cx); + cx.active_drag = Some(AnyDrag { + view: drag, + value: drag_value, + cursor_offset, + }); + pending_mouse_down.take(); + cx.notify(); + cx.stop_propagation(); + } + } + } + } + }); + + cx.on_mouse_event({ + let interactive_bounds = interactive_bounds.clone(); + let mut captured_mouse_down = None; + move |event: &MouseUpEvent, phase, cx| match phase { + // Clear the pending mouse down during the capture phase, + // so that it happens even if another event handler stops + // propagation. + DispatchPhase::Capture => { + let mut pending_mouse_down = + pending_mouse_down.borrow_mut(); + if pending_mouse_down.is_some() { + captured_mouse_down = pending_mouse_down.take(); + cx.notify(); + } + } + // Fire click handlers during the bubble phase. + DispatchPhase::Bubble => { + if let Some(mouse_down) = captured_mouse_down.take() { + if interactive_bounds + .visibly_contains(&event.position, cx) + { + let mouse_click = ClickEvent { + down: mouse_down, + up: event.clone(), + }; + for listener in &click_listeners { + listener(&mouse_click, cx); + } + } + } + } + } + }); } - } - }); - } - for listener in self.mouse_down_listeners.drain(..) { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| { - listener(event, &interactive_bounds, phase, cx); - }) - } + if let Some(hover_listener) = self.hover_listener.take() { + let was_hovered = element_state + .hover_state + .get_or_insert_with(Default::default) + .clone(); + let has_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); + let interactive_bounds = interactive_bounds.clone(); - for listener in self.mouse_up_listeners.drain(..) { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseUpEvent, phase, cx| { - listener(event, &interactive_bounds, phase, cx); - }) - } + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + if phase != DispatchPhase::Bubble { + return; + } + let is_hovered = interactive_bounds + .visibly_contains(&event.position, cx) + && !cx.has_active_drag() + && has_mouse_down.borrow().is_none(); + let mut was_hovered = was_hovered.borrow_mut(); - for listener in self.mouse_move_listeners.drain(..) { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - listener(event, &interactive_bounds, phase, cx); - }) - } + if is_hovered != was_hovered.clone() { + *was_hovered = is_hovered; + drop(was_hovered); - for listener in self.scroll_wheel_listeners.drain(..) { - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - listener(event, &interactive_bounds, phase, cx); - }) - } - - let hover_group_bounds = self - .group_hover_style - .as_ref() - .and_then(|group_hover| GroupBounds::get(&group_hover.group, cx)); - - if let Some(group_bounds) = hover_group_bounds { - let hovered = group_bounds.contains(&cx.mouse_position()); - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Capture { - if group_bounds.contains(&event.position) != hovered { - cx.notify(); + hover_listener(&is_hovered, cx); + } + }); } - } - }); - } - if self.hover_style.is_some() - || self.base_style.mouse_cursor.is_some() - || cx.active_drag.is_some() && !self.drag_over_styles.is_empty() - { - let bounds = bounds.intersect(&cx.content_mask().bounds); - let hovered = bounds.contains(&cx.mouse_position()); - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Capture { - if bounds.contains(&event.position) != hovered { - cx.notify(); - } - } - }); - } + if let Some(tooltip_builder) = self.tooltip_builder.take() { + let active_tooltip = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .clone(); + let pending_mouse_down = element_state + .pending_mouse_down + .get_or_insert_with(Default::default) + .clone(); + let interactive_bounds = interactive_bounds.clone(); - let mut drag_listener = mem::take(&mut self.drag_listener); - let drop_listeners = mem::take(&mut self.drop_listeners); - let click_listeners = mem::take(&mut self.click_listeners); + cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { + let is_hovered = interactive_bounds + .visibly_contains(&event.position, cx) + && pending_mouse_down.borrow().is_none(); + if !is_hovered { + active_tooltip.borrow_mut().take(); + return; + } - if !drop_listeners.is_empty() { - cx.on_mouse_event({ - let interactive_bounds = interactive_bounds.clone(); - move |event: &MouseUpEvent, phase, cx| { - if let Some(drag) = &cx.active_drag { - if phase == DispatchPhase::Bubble - && interactive_bounds.drag_target_contains(&event.position, cx) + if phase != DispatchPhase::Bubble { + return; + } + + if active_tooltip.borrow().is_none() { + let task = cx.spawn({ + let active_tooltip = active_tooltip.clone(); + let tooltip_builder = tooltip_builder.clone(); + + move |mut cx| async move { + cx.background_executor().timer(TOOLTIP_DELAY).await; + cx.update(|_, cx| { + active_tooltip.borrow_mut().replace( + ActiveTooltip { + tooltip: Some(AnyTooltip { + view: tooltip_builder(cx), + cursor_offset: cx.mouse_position(), + }), + _task: None, + }, + ); + cx.notify(); + }) + .ok(); + } + }); + active_tooltip.borrow_mut().replace(ActiveTooltip { + tooltip: None, + _task: Some(task), + }); + } + }); + + let active_tooltip = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .clone(); + cx.on_mouse_event(move |_: &MouseDownEvent, _, _| { + active_tooltip.borrow_mut().take(); + }); + + if let Some(active_tooltip) = element_state + .active_tooltip + .get_or_insert_with(Default::default) + .borrow() + .as_ref() { - let drag_state_type = drag.value.as_ref().type_id(); - for (drop_state_type, listener) in &drop_listeners { - if *drop_state_type == drag_state_type { - let drag = cx - .active_drag - .take() - .expect("checked for type drag state type above"); + if active_tooltip.tooltip.is_some() { + cx.active_tooltip = active_tooltip.tooltip.clone() + } + } + } - listener(drag.value.as_ref(), cx); + let clicked_state = element_state + .clicked_state + .get_or_insert_with(Default::default) + .clone(); + if clicked_state.borrow().is_clicked() { + cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| { + if phase == DispatchPhase::Capture { + *clicked_state.borrow_mut() = ElementClickedState::default(); + cx.notify(); + } + }); + } else { + let active_group_bounds = self + .group_active_style + .as_ref() + .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); + let interactive_bounds = interactive_bounds.clone(); + cx.on_mouse_event(move |down: &MouseDownEvent, phase, cx| { + if phase == DispatchPhase::Bubble && !cx.default_prevented() { + let group = active_group_bounds + .map_or(false, |bounds| bounds.contains(&down.position)); + let element = + interactive_bounds.visibly_contains(&down.position, cx); + if group || element { + *clicked_state.borrow_mut() = + ElementClickedState { group, element }; + cx.notify(); + } + } + }); + } + + let overflow = style.overflow; + if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll { + if let Some(scroll_handle) = &self.scroll_handle { + scroll_handle.0.borrow_mut().overflow = overflow; + } + + let scroll_offset = element_state + .scroll_offset + .get_or_insert_with(Rc::default) + .clone(); + let line_height = cx.line_height(); + let scroll_max = (content_size - bounds.size).max(&Size::default()); + let interactive_bounds = interactive_bounds.clone(); + + cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { + if phase == DispatchPhase::Bubble + && interactive_bounds.visibly_contains(&event.position, cx) + { + let mut scroll_offset = scroll_offset.borrow_mut(); + let old_scroll_offset = *scroll_offset; + let delta = event.delta.pixel_delta(line_height); + + if overflow.x == Overflow::Scroll { + scroll_offset.x = (scroll_offset.x + delta.x) + .clamp(-scroll_max.width, px(0.)); + } + + if overflow.y == Overflow::Scroll { + scroll_offset.y = (scroll_offset.y + delta.y) + .clamp(-scroll_max.height, px(0.)); + } + + if *scroll_offset != old_scroll_offset { cx.notify(); cx.stop_propagation(); } } - } - } - } - }); - } - - if !click_listeners.is_empty() || drag_listener.is_some() { - let pending_mouse_down = element_state - .pending_mouse_down - .get_or_insert_with(Default::default) - .clone(); - - let clicked_state = element_state - .clicked_state - .get_or_insert_with(Default::default) - .clone(); - - cx.on_mouse_event({ - let interactive_bounds = interactive_bounds.clone(); - let pending_mouse_down = pending_mouse_down.clone(); - move |event: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && event.button == MouseButton::Left - && interactive_bounds.visibly_contains(&event.position, cx) - { - *pending_mouse_down.borrow_mut() = Some(event.clone()); - cx.notify(); - } - } - }); - - cx.on_mouse_event({ - let pending_mouse_down = pending_mouse_down.clone(); - move |event: &MouseMoveEvent, phase, cx| { - if phase == DispatchPhase::Capture { - return; + }); } - let mut pending_mouse_down = pending_mouse_down.borrow_mut(); - if let Some(mouse_down) = pending_mouse_down.clone() { - if !cx.has_active_drag() - && (event.position - mouse_down.position).magnitude() - > DRAG_THRESHOLD - { - if let Some((drag_value, drag_listener)) = drag_listener.take() { - *clicked_state.borrow_mut() = ElementClickedState::default(); - let cursor_offset = event.position - bounds.origin; - let drag = (drag_listener)(drag_value.as_ref(), cx); - cx.active_drag = Some(AnyDrag { - view: drag, - value: drag_value, - cursor_offset, - }); - pending_mouse_down.take(); - cx.notify(); - cx.stop_propagation(); + if let Some(group) = self.group.clone() { + GroupBounds::push(group, bounds, cx); + } + + let scroll_offset = element_state + .scroll_offset + .as_ref() + .map(|scroll_offset| *scroll_offset.borrow()); + + let key_down_listeners = mem::take(&mut self.key_down_listeners); + let key_up_listeners = mem::take(&mut self.key_up_listeners); + let action_listeners = mem::take(&mut self.action_listeners); + cx.with_key_dispatch( + self.key_context.clone(), + element_state.focus_handle.clone(), + |_, cx| { + for listener in key_down_listeners { + cx.on_key_event(move |event: &KeyDownEvent, phase, cx| { + listener(event, phase, cx); + }) } - } - } - } - }); - cx.on_mouse_event({ - let interactive_bounds = interactive_bounds.clone(); - let mut captured_mouse_down = None; - move |event: &MouseUpEvent, phase, cx| match phase { - // Clear the pending mouse down during the capture phase, - // so that it happens even if another event handler stops - // propagation. - DispatchPhase::Capture => { - let mut pending_mouse_down = pending_mouse_down.borrow_mut(); - if pending_mouse_down.is_some() { - captured_mouse_down = pending_mouse_down.take(); - cx.notify(); - } - } - // Fire click handlers during the bubble phase. - DispatchPhase::Bubble => { - if let Some(mouse_down) = captured_mouse_down.take() { - if interactive_bounds.visibly_contains(&event.position, cx) { - let mouse_click = ClickEvent { - down: mouse_down, - up: event.clone(), - }; - for listener in &click_listeners { - listener(&mouse_click, cx); - } + for listener in key_up_listeners { + cx.on_key_event(move |event: &KeyUpEvent, phase, cx| { + listener(event, phase, cx); + }) } - } + + for (action_type, listener) in action_listeners { + cx.on_action(action_type, listener) + } + + f(&style, scroll_offset.unwrap_or_default(), cx) + }, + ); + + if let Some(group) = self.group.as_ref() { + GroupBounds::pop(group, cx); } - } + }); }); - } - - if let Some(hover_listener) = self.hover_listener.take() { - let was_hovered = element_state - .hover_state - .get_or_insert_with(Default::default) - .clone(); - let has_mouse_down = element_state - .pending_mouse_down - .get_or_insert_with(Default::default) - .clone(); - let interactive_bounds = interactive_bounds.clone(); - - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - if phase != DispatchPhase::Bubble { - return; - } - let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) - && !cx.has_active_drag() - && has_mouse_down.borrow().is_none(); - let mut was_hovered = was_hovered.borrow_mut(); - - if is_hovered != was_hovered.clone() { - *was_hovered = is_hovered; - drop(was_hovered); - - hover_listener(&is_hovered, cx); - } - }); - } - - if let Some(tooltip_builder) = self.tooltip_builder.take() { - let active_tooltip = element_state - .active_tooltip - .get_or_insert_with(Default::default) - .clone(); - let pending_mouse_down = element_state - .pending_mouse_down - .get_or_insert_with(Default::default) - .clone(); - let interactive_bounds = interactive_bounds.clone(); - - cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| { - let is_hovered = interactive_bounds.visibly_contains(&event.position, cx) - && pending_mouse_down.borrow().is_none(); - if !is_hovered { - active_tooltip.borrow_mut().take(); - return; - } - - if phase != DispatchPhase::Bubble { - return; - } - - if active_tooltip.borrow().is_none() { - let task = cx.spawn({ - let active_tooltip = active_tooltip.clone(); - let tooltip_builder = tooltip_builder.clone(); - - move |mut cx| async move { - cx.background_executor().timer(TOOLTIP_DELAY).await; - cx.update(|_, cx| { - active_tooltip.borrow_mut().replace(ActiveTooltip { - tooltip: Some(AnyTooltip { - view: tooltip_builder(cx), - cursor_offset: cx.mouse_position(), - }), - _task: None, - }); - cx.notify(); - }) - .ok(); - } - }); - active_tooltip.borrow_mut().replace(ActiveTooltip { - tooltip: None, - _task: Some(task), - }); - } - }); - - let active_tooltip = element_state - .active_tooltip - .get_or_insert_with(Default::default) - .clone(); - cx.on_mouse_event(move |_: &MouseDownEvent, _, _| { - active_tooltip.borrow_mut().take(); - }); - - if let Some(active_tooltip) = element_state - .active_tooltip - .get_or_insert_with(Default::default) - .borrow() - .as_ref() - { - if active_tooltip.tooltip.is_some() { - cx.active_tooltip = active_tooltip.tooltip.clone() - } - } - } - - let clicked_state = element_state - .clicked_state - .get_or_insert_with(Default::default) - .clone(); - if clicked_state.borrow().is_clicked() { - cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| { - if phase == DispatchPhase::Capture { - *clicked_state.borrow_mut() = ElementClickedState::default(); - cx.notify(); - } - }); - } else { - let active_group_bounds = self - .group_active_style - .as_ref() - .and_then(|group_active| GroupBounds::get(&group_active.group, cx)); - let interactive_bounds = interactive_bounds.clone(); - cx.on_mouse_event(move |down: &MouseDownEvent, phase, cx| { - if phase == DispatchPhase::Bubble && !cx.default_prevented() { - let group = active_group_bounds - .map_or(false, |bounds| bounds.contains(&down.position)); - let element = interactive_bounds.visibly_contains(&down.position, cx); - if group || element { - *clicked_state.borrow_mut() = ElementClickedState { group, element }; - cx.notify(); - } - } - }); - } - - let overflow = style.overflow; - if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll { - if let Some(scroll_handle) = &self.scroll_handle { - scroll_handle.0.borrow_mut().overflow = overflow; - } - - let scroll_offset = element_state - .scroll_offset - .get_or_insert_with(Rc::default) - .clone(); - let line_height = cx.line_height(); - let scroll_max = (content_size - bounds.size).max(&Size::default()); - let interactive_bounds = interactive_bounds.clone(); - - cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { - if phase == DispatchPhase::Bubble - && interactive_bounds.visibly_contains(&event.position, cx) - { - let mut scroll_offset = scroll_offset.borrow_mut(); - let old_scroll_offset = *scroll_offset; - let delta = event.delta.pixel_delta(line_height); - - if overflow.x == Overflow::Scroll { - scroll_offset.x = - (scroll_offset.x + delta.x).clamp(-scroll_max.width, px(0.)); - } - - if overflow.y == Overflow::Scroll { - scroll_offset.y = - (scroll_offset.y + delta.y).clamp(-scroll_max.height, px(0.)); - } - - if *scroll_offset != old_scroll_offset { - cx.notify(); - cx.stop_propagation(); - } - } - }); - } - - if let Some(group) = self.group.clone() { - GroupBounds::push(group, bounds, cx); - } - - let scroll_offset = element_state - .scroll_offset - .as_ref() - .map(|scroll_offset| *scroll_offset.borrow()); - - let key_down_listeners = mem::take(&mut self.key_down_listeners); - let key_up_listeners = mem::take(&mut self.key_up_listeners); - let action_listeners = mem::take(&mut self.action_listeners); - cx.with_key_dispatch( - self.key_context.clone(), - element_state.focus_handle.clone(), - |_, cx| { - for listener in key_down_listeners { - cx.on_key_event(move |event: &KeyDownEvent, phase, cx| { - listener(event, phase, cx); - }) - } - - for listener in key_up_listeners { - cx.on_key_event(move |event: &KeyUpEvent, phase, cx| { - listener(event, phase, cx); - }) - } - - for (action_type, listener) in action_listeners { - cx.on_action(action_type, listener) - } - - cx.with_z_index(style.z_index.unwrap_or(0), |cx| { - if style.background.as_ref().is_some_and(|fill| { - fill.color().is_some_and(|color| !color.is_transparent()) - }) { - cx.add_opaque_layer(bounds) - } - f(style, scroll_offset.unwrap_or_default(), cx) - }) - }, - ); - - if let Some(group) = self.group.as_ref() { - GroupBounds::pop(group, cx); - } + }); }); } diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index 7fba7ef477..53d8a3cb95 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -200,54 +200,52 @@ impl Element for UniformList { bounds.lower_right() - point(border.right + padding.right, border.bottom), ); - style.paint(bounds, cx, |cx| { - if self.item_count > 0 { - let content_height = - item_height * self.item_count + padding.top + padding.bottom; - let min_scroll_offset = padded_bounds.size.height - content_height; - let is_scrolled = scroll_offset.y != px(0.); + if self.item_count > 0 { + let content_height = + item_height * self.item_count + padding.top + padding.bottom; + let min_scroll_offset = padded_bounds.size.height - content_height; + let is_scrolled = scroll_offset.y != px(0.); - if is_scrolled && scroll_offset.y < min_scroll_offset { - shared_scroll_offset.borrow_mut().y = min_scroll_offset; - scroll_offset.y = min_scroll_offset; - } + if is_scrolled && scroll_offset.y < min_scroll_offset { + shared_scroll_offset.borrow_mut().y = min_scroll_offset; + scroll_offset.y = min_scroll_offset; + } - if let Some(scroll_handle) = self.scroll_handle.clone() { - scroll_handle.0.borrow_mut().replace(ScrollHandleState { - item_height, - list_height: padded_bounds.size.height, - scroll_offset: shared_scroll_offset, - }); - } - - let first_visible_element_ix = - (-(scroll_offset.y + padding.top) / item_height).floor() as usize; - let last_visible_element_ix = - ((-scroll_offset.y + padded_bounds.size.height) / item_height).ceil() - as usize; - let visible_range = first_visible_element_ix - ..cmp::min(last_visible_element_ix, self.item_count); - - let mut items = (self.render_items)(visible_range.clone(), cx); - cx.with_z_index(1, |cx| { - let content_mask = ContentMask { bounds }; - cx.with_content_mask(Some(content_mask), |cx| { - for (item, ix) in items.iter_mut().zip(visible_range) { - let item_origin = padded_bounds.origin - + point( - px(0.), - item_height * ix + scroll_offset.y + padding.top, - ); - let available_space = size( - AvailableSpace::Definite(padded_bounds.size.width), - AvailableSpace::Definite(item_height), - ); - item.draw(item_origin, available_space, cx); - } - }); + if let Some(scroll_handle) = self.scroll_handle.clone() { + scroll_handle.0.borrow_mut().replace(ScrollHandleState { + item_height, + list_height: padded_bounds.size.height, + scroll_offset: shared_scroll_offset, }); } - }); + + let first_visible_element_ix = + (-(scroll_offset.y + padding.top) / item_height).floor() as usize; + let last_visible_element_ix = ((-scroll_offset.y + padded_bounds.size.height) + / item_height) + .ceil() as usize; + let visible_range = first_visible_element_ix + ..cmp::min(last_visible_element_ix, self.item_count); + + let mut items = (self.render_items)(visible_range.clone(), cx); + cx.with_z_index(1, |cx| { + let content_mask = ContentMask { bounds }; + cx.with_content_mask(Some(content_mask), |cx| { + for (item, ix) in items.iter_mut().zip(visible_range) { + let item_origin = padded_bounds.origin + + point( + px(0.), + item_height * ix + scroll_offset.y + padding.top, + ); + let available_space = size( + AvailableSpace::Definite(padded_bounds.size.width), + AvailableSpace::Definite(item_height), + ); + item.draw(item_origin, available_space, cx); + } + }); + }); + } }, ) } diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index f777e2d8cf..89527c9d5a 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -258,16 +258,30 @@ impl Style { } } - pub fn overflow_mask(&self, bounds: Bounds) -> Option> { + pub fn overflow_mask( + &self, + bounds: Bounds, + rem_size: Pixels, + ) -> Option> { match self.overflow { Point { x: Overflow::Visible, y: Overflow::Visible, } => None, _ => { - let current_mask = bounds; - let min = current_mask.origin; - let max = current_mask.lower_right(); + let mut min = bounds.origin; + let mut max = bounds.lower_right(); + + if self + .border_color + .map_or(false, |color| !color.is_transparent()) + { + min.x += self.border_widths.left.to_pixels(rem_size); + max.x -= self.border_widths.right.to_pixels(rem_size); + min.y += self.border_widths.top.to_pixels(rem_size); + max.y -= self.border_widths.bottom.to_pixels(rem_size); + } + let bounds = match ( self.overflow.x == Overflow::Visible, self.overflow.y == Overflow::Visible, @@ -285,61 +299,62 @@ impl Style { point(bounds.lower_right().x, max.y), ), // both hidden - (false, false) => bounds, + (false, false) => Bounds::from_corners(min, max), }; + Some(ContentMask { bounds }) } } } - pub fn apply_text_style(&self, cx: &mut C, f: F) -> R - where - C: BorrowAppContext, - F: FnOnce(&mut C) -> R, - { - if self.text.is_some() { - cx.with_text_style(Some(self.text.clone()), f) - } else { - f(cx) - } - } + // pub fn apply_text_style(&self, cx: &mut C, f: F) -> R + // where + // C: BorrowAppContext, + // F: FnOnce(&mut C) -> R, + // { + // if self.text.is_some() { + // cx.with_text_style(Some(self.text.clone()), f) + // } else { + // f(cx) + // } + // } - /// Apply overflow to content mask - pub fn apply_overflow(&self, bounds: Bounds, cx: &mut C, f: F) -> R - where - C: BorrowWindow, - F: FnOnce(&mut C) -> R, - { - let current_mask = cx.content_mask(); + // /// Apply overflow to content mask + // pub fn apply_overflow(&self, bounds: Bounds, cx: &mut C, f: F) -> R + // where + // C: BorrowWindow, + // F: FnOnce(&mut C) -> R, + // { + // let current_mask = cx.content_mask(); - let min = current_mask.bounds.origin; - let max = current_mask.bounds.lower_right(); + // let min = current_mask.bounds.origin; + // let max = current_mask.bounds.lower_right(); - let mask_bounds = match ( - self.overflow.x == Overflow::Visible, - self.overflow.y == Overflow::Visible, - ) { - // x and y both visible - (true, true) => return f(cx), - // x visible, y hidden - (true, false) => Bounds::from_corners( - point(min.x, bounds.origin.y), - point(max.x, bounds.lower_right().y), - ), - // x hidden, y visible - (false, true) => Bounds::from_corners( - point(bounds.origin.x, min.y), - point(bounds.lower_right().x, max.y), - ), - // both hidden - (false, false) => bounds, - }; - let mask = ContentMask { - bounds: mask_bounds, - }; + // let mask_bounds = match ( + // self.overflow.x == Overflow::Visible, + // self.overflow.y == Overflow::Visible, + // ) { + // // x and y both visible + // (true, true) => return f(cx), + // // x visible, y hidden + // (true, false) => Bounds::from_corners( + // point(min.x, bounds.origin.y), + // point(max.x, bounds.lower_right().y), + // ), + // // x hidden, y visible + // (false, true) => Bounds::from_corners( + // point(bounds.origin.x, min.y), + // point(bounds.lower_right().x, max.y), + // ), + // // both hidden + // (false, false) => bounds, + // }; + // let mask = ContentMask { + // bounds: mask_bounds, + // }; - cx.with_content_mask(Some(mask), f) - } + // cx.with_content_mask(Some(mask), f) + // } /// Paints the background of an element styled with this style. pub fn paint( @@ -369,14 +384,14 @@ impl Style { }); let background_color = self.background.as_ref().and_then(Fill::color); - if background_color.is_some() || self.is_border_visible() { + if background_color.is_some() { cx.with_z_index(1, |cx| { cx.paint_quad(quad( bounds, self.corner_radii.to_pixels(bounds.size, rem_size), background_color.unwrap_or_default(), - self.border_widths.to_pixels(rem_size), - self.border_color.unwrap_or_default(), + Edges::default(), + Hsla::transparent_black(), )); }); } @@ -385,6 +400,18 @@ impl Style { continuation(cx); }); + if self.is_border_visible() { + cx.with_z_index(3, |cx| { + cx.paint_quad(quad( + bounds, + self.corner_radii.to_pixels(bounds.size, rem_size), + Hsla::transparent_black(), + self.border_widths.to_pixels(rem_size), + self.border_color.unwrap_or_default(), + )); + }); + } + #[cfg(debug_assertions)] if self.debug_below { cx.remove_global::(); diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 82f00da6f9..e59d7ee494 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -537,6 +537,7 @@ impl Render for Dock { div() .flex() .border_color(cx.theme().colors().border) + .overflow_hidden() .map(|this| match self.position().axis() { Axis::Horizontal => this.w(px(size)).h_full().flex_row(), Axis::Vertical => this.h(px(size)).w_full().flex_col(), From 26fb67b3e4ab900fcf328d1b459a2d69ac8f578b Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Wed, 20 Dec 2023 20:38:37 +0100 Subject: [PATCH 218/644] chore: Remove 'db' dependency from recent_projects2 (#3740) It was pulling in gpui1 into zed2 build. Release Notes: - N/A --- Cargo.lock | 1 - crates/recent_projects2/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af4d5317e8..bd0a86d161 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7481,7 +7481,6 @@ dependencies = [ name = "recent_projects2" version = "0.1.0" dependencies = [ - "db", "editor2", "futures 0.3.28", "fuzzy2", diff --git a/crates/recent_projects2/Cargo.toml b/crates/recent_projects2/Cargo.toml index 3d10c147e0..46854ab4e8 100644 --- a/crates/recent_projects2/Cargo.toml +++ b/crates/recent_projects2/Cargo.toml @@ -9,7 +9,6 @@ path = "src/recent_projects.rs" doctest = false [dependencies] -db = { path = "../db" } editor = { package = "editor2", path = "../editor2" } fuzzy = { package = "fuzzy2", path = "../fuzzy2" } gpui = { package = "gpui2", path = "../gpui2" } From 9acb5825e66f694406a52f3757faa6d203998dff Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 13:00:52 -0700 Subject: [PATCH 219/644] Compute the query editor placeholder text with a focus handle So we're not beholden to the current focus. --- crates/editor2/src/editor.rs | 7 +++++-- crates/editor2/src/element.rs | 3 ++- crates/search2/src/buffer_search.rs | 5 +++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 58f8e857a9..aa627db2a3 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -2003,8 +2003,11 @@ impl Editor { placeholder_text: impl Into>, cx: &mut ViewContext, ) { - self.placeholder_text = Some(placeholder_text.into()); - cx.notify(); + let placeholder_text = Some(placeholder_text.into()); + if self.placeholder_text != placeholder_text { + self.placeholder_text = placeholder_text; + cx.notify(); + } } pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext) { diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 8031bc5db6..9dab9d00ae 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -1722,11 +1722,12 @@ impl EditorElement { return Vec::new(); } - // When the editor is empty and unfocused, then show the placeholder. + // Show the placeholder when the editor is empty if snapshot.is_empty() { let font_size = self.style.text.font_size.to_pixels(cx.rem_size()); let placeholder_color = cx.theme().styles.colors.text_placeholder; let placeholder_text = snapshot.placeholder_text(); + let placeholder_lines = placeholder_text .as_ref() .map_or("", AsRef::as_ref) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index ebaf111e60..f84db72c13 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -113,8 +113,9 @@ impl Render for BufferSearchBar { } let supported_options = self.supported_options(); + let query_focus_handle = self.query_editor.focus_handle(cx); let previous_query_keystrokes = cx - .bindings_for_action(&PreviousHistoryQuery {}) + .bindings_for_action_in(&PreviousHistoryQuery {}, &query_focus_handle) .into_iter() .next() .map(|binding| { @@ -125,7 +126,7 @@ impl Render for BufferSearchBar { .collect::>() }); let next_query_keystrokes = cx - .bindings_for_action(&NextHistoryQuery {}) + .bindings_for_action_in(&NextHistoryQuery {}, &query_focus_handle) .into_iter() .next() .map(|binding| { From 9a06b7e77d1e795c4e0b505ec8b7412574154f7f Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 15:59:01 -0500 Subject: [PATCH 220/644] Style incoming call notifications --- .../incoming_call_notification.rs | 72 ++++++++++++------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/crates/collab_ui2/src/notifications/incoming_call_notification.rs b/crates/collab_ui2/src/notifications/incoming_call_notification.rs index 53ff51d1cd..d5bdf4ff44 100644 --- a/crates/collab_ui2/src/notifications/incoming_call_notification.rs +++ b/crates/collab_ui2/src/notifications/incoming_call_notification.rs @@ -2,12 +2,14 @@ use crate::notification_window_options; use call::{ActiveCall, IncomingCall}; use futures::StreamExt; use gpui::{ - div, px, red, AppContext, Div, Element, ParentElement, Render, RenderOnce, Styled, ViewContext, + img, px, AppContext, Div, ParentElement, Render, RenderOnce, Styled, ViewContext, VisualContext as _, WindowHandle, }; +use settings::Settings; use std::sync::{Arc, Weak}; +use theme::ThemeSettings; use ui::prelude::*; -use ui::{h_stack, v_stack, Avatar, Button, Label}; +use ui::{h_stack, v_stack, Button, Label}; use util::ResultExt; use workspace::AppState; @@ -112,36 +114,52 @@ impl IncomingCallNotification { state: Arc::new(IncomingCallNotificationState::new(call, app_state)), } } - fn render_caller(&self, cx: &mut ViewContext) -> impl Element { - h_stack() - .child(Avatar::new(self.state.call.calling_user.avatar_uri.clone())) - .child( - v_stack() - .child(Label::new(format!( - "{} is sharing a project in Zed", - self.state.call.calling_user.github_login - ))) - .child(self.render_buttons(cx)), - ) - } - - fn render_buttons(&self, cx: &mut ViewContext) -> impl Element { - h_stack() - .child(Button::new("accept", "Accept").render(cx).on_click({ - let state = self.state.clone(); - move |_, cx| state.respond(true, cx) - })) - .child(Button::new("decline", "Decline").render(cx).on_click({ - let state = self.state.clone(); - move |_, cx| state.respond(false, cx) - })) - } } impl Render for IncomingCallNotification { type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - div().bg(red()).flex_none().child(self.render_caller(cx)) + // TODO: Is there a better place for us to initialize the font? + let (ui_font, ui_font_size) = { + let theme_settings = ThemeSettings::get_global(cx); + ( + theme_settings.ui_font.family.clone(), + theme_settings.ui_font_size.clone(), + ) + }; + + cx.set_rem_size(ui_font_size); + + h_stack() + .font(ui_font) + .text_ui() + .justify_between() + .size_full() + .overflow_hidden() + .elevation_3(cx) + .p_2() + .gap_2() + .child( + img(self.state.call.calling_user.avatar_uri.clone()) + .w_12() + .h_12() + .rounded_full(), + ) + .child(v_stack().overflow_hidden().child(Label::new(format!( + "{} is sharing a project in Zed", + self.state.call.calling_user.github_login + )))) + .child( + v_stack() + .child(Button::new("accept", "Accept").render(cx).on_click({ + let state = self.state.clone(); + move |_, cx| state.respond(true, cx) + })) + .child(Button::new("decline", "Decline").render(cx).on_click({ + let state = self.state.clone(); + move |_, cx| state.respond(false, cx) + })), + ) } } From 7b51f738267a0245d6a96b9c5f9f89f852fbc837 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 16:06:59 -0500 Subject: [PATCH 221/644] Tighten up project share notifications --- .../project_shared_notification.rs | 50 +++++++++---------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/crates/collab_ui2/src/notifications/project_shared_notification.rs b/crates/collab_ui2/src/notifications/project_shared_notification.rs index 2dc0dee6f4..707e961423 100644 --- a/crates/collab_ui2/src/notifications/project_shared_notification.rs +++ b/crates/collab_ui2/src/notifications/project_shared_notification.rs @@ -23,7 +23,7 @@ pub fn init(app_state: &Arc, cx: &mut AppContext) { } => { let window_size = Size { width: px(400.), - height: px(96.), + height: px(72.), }; for screen in cx.displays() { @@ -139,35 +139,33 @@ impl Render for ProjectSharedNotification { .text_ui() .justify_between() .size_full() + .overflow_hidden() .elevation_3(cx) .p_2() .gap_2() .child( - h_stack() - .gap_2() - .child( - img(self.owner.avatar_uri.clone()) - .w_16() - .h_16() - .rounded_full(), - ) - .child( - v_stack() - .child(Label::new(self.owner.github_login.clone())) - .child(Label::new(format!( - "is sharing a project in Zed{}", - if self.worktree_root_names.is_empty() { - "" - } else { - ":" - } - ))) - .children(if self.worktree_root_names.is_empty() { - None - } else { - Some(Label::new(self.worktree_root_names.join(", "))) - }), - ), + img(self.owner.avatar_uri.clone()) + .w_12() + .h_12() + .rounded_full(), + ) + .child( + v_stack() + .overflow_hidden() + .child(Label::new(self.owner.github_login.clone())) + .child(Label::new(format!( + "is sharing a project in Zed{}", + if self.worktree_root_names.is_empty() { + "" + } else { + ":" + } + ))) + .children(if self.worktree_root_names.is_empty() { + None + } else { + Some(Label::new(self.worktree_root_names.join(", "))) + }), ) .child( v_stack() From d499cccebb02257d43eef8345d283370fb3d549d Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 14:47:56 -0700 Subject: [PATCH 222/644] Only compute placeholder text once --- crates/editor2/src/editor.rs | 4 ++ crates/search2/src/buffer_search.rs | 97 +++++++++++++---------------- 2 files changed, 48 insertions(+), 53 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index aa627db2a3..cb607a7e6c 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -1998,6 +1998,10 @@ impl Editor { self.collaboration_hub = Some(hub); } + pub fn placeholder_text(&self) -> Option<&str> { + self.placeholder_text.as_deref() + } + pub fn set_placeholder_text( &mut self, placeholder_text: impl Into>, diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index f84db72c13..5b4113aee2 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -102,66 +102,57 @@ impl EventEmitter for BufferSearchBar {} impl EventEmitter for BufferSearchBar {} impl Render for BufferSearchBar { type Element = Div; + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - // let query_container_style = if self.query_contains_error { - // theme.search.invalid_editor - // } else { - // theme.search.editor.input.container - // }; if self.dismissed { return div(); } + let supported_options = self.supported_options(); - let query_focus_handle = self.query_editor.focus_handle(cx); - let previous_query_keystrokes = cx - .bindings_for_action_in(&PreviousHistoryQuery {}, &query_focus_handle) - .into_iter() - .next() - .map(|binding| { - binding - .keystrokes() - .iter() - .map(|k| k.to_string()) - .collect::>() - }); - let next_query_keystrokes = cx - .bindings_for_action_in(&NextHistoryQuery {}, &query_focus_handle) - .into_iter() - .next() - .map(|binding| { - binding - .keystrokes() - .iter() - .map(|k| k.to_string()) - .collect::>() - }); - let new_placeholder_text = match (previous_query_keystrokes, next_query_keystrokes) { - (Some(previous_query_keystrokes), Some(next_query_keystrokes)) => { - format!( - "Search ({}/{} for previous/next query)", - previous_query_keystrokes.join(" "), - next_query_keystrokes.join(" ") - ) + if self.query_editor.read(cx).placeholder_text().is_none() { + let query_focus_handle = self.query_editor.focus_handle(cx); + let up_keystrokes = cx + .bindings_for_action_in(&PreviousHistoryQuery {}, &query_focus_handle) + .into_iter() + .next() + .map(|binding| { + binding + .keystrokes() + .iter() + .map(|k| k.to_string()) + .collect::>() + }); + let down_keystrokes = cx + .bindings_for_action_in(&NextHistoryQuery {}, &query_focus_handle) + .into_iter() + .next() + .map(|binding| { + binding + .keystrokes() + .iter() + .map(|k| k.to_string()) + .collect::>() + }); + + let placeholder_text = + up_keystrokes + .zip(down_keystrokes) + .map(|(up_keystrokes, down_keystrokes)| { + Arc::from(format!( + "Search ({}/{} for previous/next query)", + up_keystrokes.join(" "), + down_keystrokes.join(" ") + )) + }); + + if let Some(placeholder_text) = placeholder_text { + self.query_editor.update(cx, |editor, cx| { + editor.set_placeholder_text(placeholder_text, cx); + }); } - (None, Some(next_query_keystrokes)) => { - format!( - "Search ({} for next query)", - next_query_keystrokes.join(" ") - ) - } - (Some(previous_query_keystrokes), None) => { - format!( - "Search ({} for previous query)", - previous_query_keystrokes.join(" ") - ) - } - (None, None) => String::new(), - }; - let new_placeholder_text = Arc::from(new_placeholder_text); - self.query_editor.update(cx, |editor, cx| { - editor.set_placeholder_text(new_placeholder_text, cx); - }); + } + self.replacement_editor.update(cx, |editor, cx| { editor.set_placeholder_text("Replace with...", cx); }); From 53b608378c23fbdc2ba3baf79a180c1fe91aeb18 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 17:02:15 -0500 Subject: [PATCH 223/644] Don't apply the gap when we don't have any items in the first row --- crates/workspace2/src/toolbar.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index cd25582f36..4431e1b3ff 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -102,16 +102,19 @@ impl Render for Toolbar { let secondary_item = self.secondary_items().next().map(|item| item.to_any()); + let has_left_items = self.left_items().count() > 0; + let has_right_items = self.right_items().count() > 0; + v_stack() .p_1() - .gap_2() + .when(has_left_items || has_right_items, |this| this.gap_2()) .border_b() .border_color(cx.theme().colors().border_variant) .bg(cx.theme().colors().toolbar_background) .child( h_stack() .justify_between() - .when(self.left_items().count() > 0, |this| { + .when(has_left_items, |this| { this.child( h_stack() .flex_1() @@ -119,7 +122,7 @@ impl Render for Toolbar { .children(self.left_items().map(|item| item.to_any())), ) }) - .when(self.right_items().count() > 0, |this| { + .when(has_right_items, |this| { this.child( h_stack() .flex_1() From b9bc74abe55915a8e05308b07e3dcf27a244fc07 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 17:03:44 -0500 Subject: [PATCH 224/644] Increase toolbar padding --- crates/workspace2/src/toolbar.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/workspace2/src/toolbar.rs b/crates/workspace2/src/toolbar.rs index 4431e1b3ff..f8bca157c3 100644 --- a/crates/workspace2/src/toolbar.rs +++ b/crates/workspace2/src/toolbar.rs @@ -106,7 +106,7 @@ impl Render for Toolbar { let has_right_items = self.right_items().count() > 0; v_stack() - .p_1() + .p_2() .when(has_left_items || has_right_items, |this| this.gap_2()) .border_b() .border_color(cx.theme().colors().border_variant) From b493d8f6c0b84e90af061eabe0b825072b18b0b6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 17:10:27 -0500 Subject: [PATCH 225/644] Improve spacing of items in buffer search bar --- crates/search2/src/buffer_search.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index ebaf111e60..51557320f7 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -214,6 +214,8 @@ impl Render for BufferSearchBar { } h_stack() + .w_full() + .gap_2() .key_context(key_context) .on_action(cx.listener(Self::previous_history_query)) .on_action(cx.listener(Self::next_history_query)) @@ -239,7 +241,6 @@ impl Render for BufferSearchBar { .when(self.supported_options().word, |this| { this.on_action(cx.listener(Self::toggle_whole_word)) }) - .w_full() .child( h_stack() .flex_1() @@ -268,6 +269,7 @@ impl Render for BufferSearchBar { ) .child( h_stack() + .gap_2() .flex_none() .child( h_stack() From 8a8b498ee114cded149172515dc1e2e13f2bfed2 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 17:25:38 -0500 Subject: [PATCH 226/644] Style replace input --- crates/search2/src/buffer_search.rs | 61 +++++++++++++++++------------ 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index 51557320f7..dcf9c4c6f2 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -189,22 +189,6 @@ impl Render for BufferSearchBar { Some(ui::Label::new(message)) }); let should_show_replace_input = self.replace_enabled && supported_options.replacement; - let replace_all = should_show_replace_input.then(|| { - super::render_replace_button( - ReplaceAll, - ui::Icon::ReplaceAll, - "Replace all", - cx.listener(|this, _, cx| this.replace_all(&ReplaceAll, cx)), - ) - }); - let replace_next = should_show_replace_input.then(|| { - super::render_replace_button( - ReplaceNext, - ui::Icon::ReplaceNext, - "Replace next", - cx.listener(|this, _, cx| this.replace_next(&ReplaceNext, cx)), - ) - }); let in_replace = self.replacement_editor.focus_handle(cx).is_focused(cx); let mut key_context = KeyContext::default(); @@ -290,16 +274,47 @@ impl Render for BufferSearchBar { .gap_0p5() .flex_1() .when(self.replace_enabled, |this| { - this.child(self.replacement_editor.clone()) - .children(replace_next) - .children(replace_all) + this.child( + h_stack() + .flex_1() + // We're giving this a fixed height to match the height of the search input, + // which has an icon inside that is increasing its height. + .h_8() + .px_2() + .py_1() + .gap_2() + .border_1() + .border_color(cx.theme().colors().border) + .rounded_lg() + .child(self.render_text_input(&self.replacement_editor, cx)), + ) + .when(should_show_replace_input, |this| { + this.child(super::render_replace_button( + ReplaceNext, + ui::Icon::ReplaceNext, + "Replace next", + cx.listener(|this, _, cx| this.replace_next(&ReplaceNext, cx)), + )) + .child(super::render_replace_button( + ReplaceAll, + ui::Icon::ReplaceAll, + "Replace all", + cx.listener(|this, _, cx| this.replace_all(&ReplaceAll, cx)), + )) + }) }), ) .child( h_stack() .gap_0p5() .flex_none() - .child(self.render_action_button()) + .child( + IconButton::new("select-all", ui::Icon::SelectAll) + .on_click(|_, cx| cx.dispatch_action(SelectAllMatches.boxed_clone())) + .tooltip(|cx| { + Tooltip::for_action("Select all matches", &SelectAllMatches, cx) + }), + ) .children(match_count) .child(render_nav_button( ui::Icon::ChevronLeft, @@ -627,12 +642,6 @@ impl BufferSearchBar { self.update_matches(cx) } - fn render_action_button(&self) -> impl IntoElement { - IconButton::new("select-all", ui::Icon::SelectAll) - .on_click(|_, cx| cx.dispatch_action(SelectAllMatches.boxed_clone())) - .tooltip(|cx| Tooltip::for_action("Select all matches", &SelectAllMatches, cx)) - } - fn render_search_option_button( &self, option: SearchOptions, From 2ac472e0e068770109c37917bf9d6368345a8325 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 17:31:36 -0500 Subject: [PATCH 227/644] Inline buttons --- crates/search2/src/buffer_search.rs | 32 ++++++++++++++++++----------- crates/search2/src/search.rs | 19 ----------------- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index dcf9c4c6f2..ec70b37219 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -289,18 +289,26 @@ impl Render for BufferSearchBar { .child(self.render_text_input(&self.replacement_editor, cx)), ) .when(should_show_replace_input, |this| { - this.child(super::render_replace_button( - ReplaceNext, - ui::Icon::ReplaceNext, - "Replace next", - cx.listener(|this, _, cx| this.replace_next(&ReplaceNext, cx)), - )) - .child(super::render_replace_button( - ReplaceAll, - ui::Icon::ReplaceAll, - "Replace all", - cx.listener(|this, _, cx| this.replace_all(&ReplaceAll, cx)), - )) + this.child( + IconButton::new("search-replace-next", ui::Icon::ReplaceNext) + .tooltip(move |cx| { + Tooltip::for_action("Replace next", &ReplaceNext, cx) + }) + .on_click(cx.listener(|this, _, cx| { + this.replace_next(&ReplaceNext, cx) + })), + ) + .child( + IconButton::new("search-replace-all", ui::Icon::ReplaceAll) + .tooltip(move |cx| { + Tooltip::for_action("Replace all", &ReplaceAll, cx) + }) + .on_click( + cx.listener(|this, _, cx| { + this.replace_all(&ReplaceAll, cx) + }), + ), + ) }) }), ) diff --git a/crates/search2/src/search.rs b/crates/search2/src/search.rs index 18fcc258f4..1d496a10b0 100644 --- a/crates/search2/src/search.rs +++ b/crates/search2/src/search.rs @@ -5,10 +5,6 @@ pub use mode::SearchMode; use project::search::SearchQuery; use ui::{prelude::*, Tooltip}; use ui::{ButtonStyle, Icon, IconButton}; -//pub use project_search::{ProjectSearchBar, ProjectSearchView}; -// use theme::components::{ -// action_button::Button, svg::Svg, ComponentExt, IconButtonStyle, ToggleIconButtonStyle, -// }; pub mod buffer_search; mod history; @@ -121,18 +117,3 @@ fn toggle_replace_button( .when(active, |button| button.style(ButtonStyle::Filled)) .tooltip(|cx| Tooltip::for_action("Toggle replace", &ToggleReplace, cx)) } - -fn render_replace_button( - action: impl Action + 'static + Send + Sync, - icon: Icon, - tooltip: &'static str, - on_click: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static, -) -> impl IntoElement { - let id: SharedString = format!("search-replace-{}", action.name()).into(); - IconButton::new(id, icon) - .tooltip({ - let action = action.boxed_clone(); - move |cx| Tooltip::for_action(tooltip, &*action, cx) - }) - .on_click(on_click) -} From e5e8e8882f162a125bfa15acaf41c10162fc1c21 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 17:34:08 -0500 Subject: [PATCH 228/644] Inline toggle replace button --- crates/search2/src/buffer_search.rs | 18 ++++++++++++++---- crates/search2/src/search.rs | 14 +------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index ec70b37219..06e1b625bc 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -261,12 +261,22 @@ impl Render for BufferSearchBar { .child(search_button_for_mode(SearchMode::Regex)), ) .when(supported_options.replacement, |this| { - this.child(super::toggle_replace_button( - self.replace_enabled, - cx.listener(|this, _: &ClickEvent, cx| { + this.child( + IconButton::new( + "buffer-search-bar-toggle-replace-button", + Icon::Replace, + ) + .style(ButtonStyle::Subtle) + .when(self.replace_enabled, |button| { + button.style(ButtonStyle::Filled) + }) + .on_click(cx.listener(|this, _: &ClickEvent, cx| { this.toggle_replace(&ToggleReplace, cx); + })) + .tooltip(|cx| { + Tooltip::for_action("Toggle replace", &ToggleReplace, cx) }), - )) + ) }), ) .child( diff --git a/crates/search2/src/search.rs b/crates/search2/src/search.rs index 1d496a10b0..a5bd299e87 100644 --- a/crates/search2/src/search.rs +++ b/crates/search2/src/search.rs @@ -4,7 +4,7 @@ use gpui::{actions, Action, AppContext, IntoElement}; pub use mode::SearchMode; use project::search::SearchQuery; use ui::{prelude::*, Tooltip}; -use ui::{ButtonStyle, Icon, IconButton}; +use ui::{ButtonStyle, IconButton}; pub mod buffer_search; mod history; @@ -105,15 +105,3 @@ impl SearchOptions { }) } } - -fn toggle_replace_button( - active: bool, - action: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static, -) -> impl IntoElement { - // todo: add toggle_replace button - IconButton::new("buffer-search-bar-toggle-replace-button", Icon::Replace) - .on_click(action) - .style(ButtonStyle::Subtle) - .when(active, |button| button.style(ButtonStyle::Filled)) - .tooltip(|cx| Tooltip::for_action("Toggle replace", &ToggleReplace, cx)) -} From 72c8beae30c6d4277b46de2dd0a30068ac137a68 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 21 Dec 2023 00:45:23 +0200 Subject: [PATCH 229/644] Restore "reveal in project panel" and "search in directory" context menu actions --- Cargo.lock | 1 + crates/project_panel2/Cargo.toml | 1 + crates/project_panel2/src/project_panel.rs | 103 ++------------------- crates/search2/src/project_search.rs | 1 + crates/search2/src/search.rs | 1 + 5 files changed, 14 insertions(+), 93 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd0a86d161..cddd744a9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7057,6 +7057,7 @@ dependencies = [ "pretty_assertions", "project2", "schemars", + "search2", "serde", "serde_derive", "serde_json", diff --git a/crates/project_panel2/Cargo.toml b/crates/project_panel2/Cargo.toml index 48abfbe1de..d3ef1eb825 100644 --- a/crates/project_panel2/Cargo.toml +++ b/crates/project_panel2/Cargo.toml @@ -15,6 +15,7 @@ editor = { path = "../editor2", package = "editor2" } gpui = { path = "../gpui2", package = "gpui2" } menu = { path = "../menu2", package = "menu2" } project = { path = "../project2", package = "project2" } +search = { package = "search2", path = "../search2" } settings = { path = "../settings2", package = "settings2" } theme = { path = "../theme2", package = "theme2" } ui = { path = "../ui2", package = "ui2" } diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index d8b5c1551f..07a6e4be5e 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -55,7 +55,7 @@ pub struct ProjectPanel { filename_editor: View, clipboard_entry: Option, _dragged_entry_destination: Option>, - _workspace: WeakView, + workspace: WeakView, width: Option, pending_serialization: Task>, } @@ -152,10 +152,6 @@ pub enum Event { entry_id: ProjectEntryId, }, Focus, - NewSearchInDirectory { - dir_entry: Entry, - }, - ActivatePanel, } #[derive(Serialize, Deserialize)] @@ -190,10 +186,10 @@ impl ProjectPanel { } project::Event::RevealInProjectPanel(entry_id) => { this.reveal_entry(project, *entry_id, false, cx); - cx.emit(Event::ActivatePanel); + cx.emit(PanelEvent::Activate); } project::Event::ActivateProjectPanel => { - cx.emit(Event::ActivatePanel); + cx.emit(PanelEvent::Activate); } project::Event::WorktreeRemoved(id) => { this.expanded_dir_ids.remove(id); @@ -244,7 +240,7 @@ impl ProjectPanel { filename_editor, clipboard_entry: None, _dragged_entry_destination: None, - _workspace: workspace.weak_handle(), + workspace: workspace.weak_handle(), width: None, pending_serialization: Task::ready(None), }; @@ -1004,9 +1000,12 @@ impl ProjectPanel { ) { if let Some((_, entry)) = self.selected_entry(cx) { if entry.is_dir() { - cx.emit(Event::NewSearchInDirectory { - dir_entry: entry.clone(), - }); + let entry = entry.clone(); + self.workspace + .update(cx, |workspace, cx| { + search::ProjectSearchView::new_search_in_directory(workspace, &entry, cx); + }) + .ok(); } } } @@ -1666,7 +1665,6 @@ mod tests { use std::{ collections::HashSet, path::{Path, PathBuf}, - sync::atomic::{self, AtomicUsize}, }; use workspace::AppState; @@ -2705,87 +2703,6 @@ mod tests { ); } - #[gpui::test] - async fn test_new_search_in_directory_trigger(cx: &mut gpui::TestAppContext) { - init_test_with_editor(cx); - - let fs = FakeFs::new(cx.executor().clone()); - fs.insert_tree( - "/src", - json!({ - "test": { - "first.rs": "// First Rust file", - "second.rs": "// Second Rust file", - "third.rs": "// Third Rust file", - } - }), - ) - .await; - - let project = Project::test(fs.clone(), ["/src".as_ref()], cx).await; - let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); - let cx = &mut VisualTestContext::from_window(*workspace, cx); - let panel = workspace - .update(cx, |workspace, cx| ProjectPanel::new(workspace, cx)) - .unwrap(); - - let new_search_events_count = Arc::new(AtomicUsize::new(0)); - let _subscription = panel.update(cx, |_, cx| { - let subcription_count = Arc::clone(&new_search_events_count); - let view = cx.view().clone(); - cx.subscribe(&view, move |_, _, event, _| { - if matches!(event, Event::NewSearchInDirectory { .. }) { - subcription_count.fetch_add(1, atomic::Ordering::SeqCst); - } - }) - }); - - toggle_expand_dir(&panel, "src/test", cx); - select_path(&panel, "src/test/first.rs", cx); - panel.update(cx, |panel, cx| panel.confirm(&Confirm, cx)); - cx.executor().run_until_parked(); - assert_eq!( - visible_entries_as_strings(&panel, 0..10, cx), - &[ - "v src", - " v test", - " first.rs <== selected", - " second.rs", - " third.rs" - ] - ); - panel.update(cx, |panel, cx| { - panel.new_search_in_directory(&NewSearchInDirectory, cx) - }); - assert_eq!( - new_search_events_count.load(atomic::Ordering::SeqCst), - 0, - "Should not trigger new search in directory when called on a file" - ); - - select_path(&panel, "src/test", cx); - panel.update(cx, |panel, cx| panel.confirm(&Confirm, cx)); - cx.executor().run_until_parked(); - assert_eq!( - visible_entries_as_strings(&panel, 0..10, cx), - &[ - "v src", - " v test <== selected", - " first.rs", - " second.rs", - " third.rs" - ] - ); - panel.update(cx, |panel, cx| { - panel.new_search_in_directory(&NewSearchInDirectory, cx) - }); - assert_eq!( - new_search_events_count.load(atomic::Ordering::SeqCst), - 1, - "Should trigger new search in directory when called on a directory" - ); - } - #[gpui::test] async fn test_collapse_all_entries(cx: &mut gpui::TestAppContext) { init_test_with_editor(cx); diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index af8ac41834..3e245ed72d 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -918,6 +918,7 @@ impl ProjectSearchView { }) .unwrap_or(Task::ready(Ok(false))) } + pub fn new_search_in_directory( workspace: &mut Workspace, dir_entry: &Entry, diff --git a/crates/search2/src/search.rs b/crates/search2/src/search.rs index a5bd299e87..f0301a5bcc 100644 --- a/crates/search2/src/search.rs +++ b/crates/search2/src/search.rs @@ -3,6 +3,7 @@ pub use buffer_search::BufferSearchBar; use gpui::{actions, Action, AppContext, IntoElement}; pub use mode::SearchMode; use project::search::SearchQuery; +pub use project_search::ProjectSearchView; use ui::{prelude::*, Tooltip}; use ui::{ButtonStyle, IconButton}; From 2cd7d2db469ff38be0b374b06c065bd5322c3d22 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 21 Dec 2023 01:18:00 +0200 Subject: [PATCH 230/644] Remove nightly from zed1 and use proper namespaces for nightly in zed2 manifest --- crates/zed/Cargo.toml | 8 -------- crates/zed2/Cargo.toml | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 987208880b..53a5c1cdde 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -171,14 +171,6 @@ osx_minimum_system_version = "10.15.7" osx_info_plist_exts = ["resources/info/*"] osx_url_schemes = ["zed-dev"] -[package.metadata.bundle-nightly] -icon = ["resources/app-icon-nightly@2x.png", "resources/app-icon-nightly.png"] -identifier = "dev.zed.Zed-Nightly" -name = "Zed Nightly" -osx_minimum_system_version = "10.15.7" -osx_info_plist_exts = ["resources/info/*"] -osx_url_schemes = ["zed-nightly"] - [package.metadata.bundle-preview] icon = ["resources/app-icon-preview@2x.png", "resources/app-icon-preview.png"] identifier = "dev.zed.Zed-Preview" diff --git a/crates/zed2/Cargo.toml b/crates/zed2/Cargo.toml index 8cc3333484..3da22401e0 100644 --- a/crates/zed2/Cargo.toml +++ b/crates/zed2/Cargo.toml @@ -169,11 +169,11 @@ osx_url_schemes = ["zed-dev"] [package.metadata.bundle-nightly] icon = ["resources/app-icon-nightly@2x.png", "resources/app-icon-nightly.png"] -identifier = "dev.zed.Zed-Dev" +identifier = "dev.zed.Zed-Nightly" name = "Zed Nightly" osx_minimum_system_version = "10.15.7" osx_info_plist_exts = ["resources/info/*"] -osx_url_schemes = ["zed-dev"] +osx_url_schemes = ["zed-nightly"] [package.metadata.bundle-preview] icon = ["resources/app-icon-preview@2x.png", "resources/app-icon-preview.png"] From 443b1dd3458a97d93a71c9ae89a60a0cb539f2b6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 18:23:21 -0500 Subject: [PATCH 231/644] Add `ToggleButton` component --- crates/storybook2/src/story_selector.rs | 2 + crates/ui2/src/components/button.rs | 2 + .../ui2/src/components/button/button_like.rs | 20 ++- .../src/components/button/toggle_button.rs | 128 ++++++++++++++++++ crates/ui2/src/components/stories.rs | 2 + .../src/components/stories/toggle_button.rs | 89 ++++++++++++ 6 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 crates/ui2/src/components/button/toggle_button.rs create mode 100644 crates/ui2/src/components/stories/toggle_button.rs diff --git a/crates/storybook2/src/story_selector.rs b/crates/storybook2/src/story_selector.rs index bd87e1fde9..82dffd42fd 100644 --- a/crates/storybook2/src/story_selector.rs +++ b/crates/storybook2/src/story_selector.rs @@ -31,6 +31,7 @@ pub enum ComponentStory { Scroll, Tab, TabBar, + ToggleButton, Text, ViewportUnits, ZIndex, @@ -62,6 +63,7 @@ impl ComponentStory { Self::Text => TextStory::view(cx).into(), Self::Tab => cx.build_view(|_| ui::TabStory).into(), Self::TabBar => cx.build_view(|_| ui::TabBarStory).into(), + Self::ToggleButton => cx.build_view(|_| ui::ToggleButtonStory).into(), Self::ViewportUnits => cx.build_view(|_| crate::stories::ViewportUnitsStory).into(), Self::ZIndex => cx.build_view(|_| ZIndexStory).into(), Self::Picker => PickerStory::new(cx).into(), diff --git a/crates/ui2/src/components/button.rs b/crates/ui2/src/components/button.rs index 25e88201f4..71aaf7780c 100644 --- a/crates/ui2/src/components/button.rs +++ b/crates/ui2/src/components/button.rs @@ -2,7 +2,9 @@ mod button; pub(self) mod button_icon; mod button_like; mod icon_button; +mod toggle_button; pub use button::*; pub use button_like::*; pub use icon_button::*; +pub use toggle_button::*; diff --git a/crates/ui2/src/components/button/button_like.rs b/crates/ui2/src/components/button/button_like.rs index 19fa2b48a4..b25ac1d1ec 100644 --- a/crates/ui2/src/components/button/button_like.rs +++ b/crates/ui2/src/components/button/button_like.rs @@ -59,6 +59,13 @@ pub enum ButtonStyle { Transparent, } +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] +pub(crate) enum ButtonLikeRounding { + All, + Left, + Right, +} + #[derive(Debug, Clone)] pub(crate) struct ButtonLikeStyles { pub background: Hsla, @@ -256,6 +263,7 @@ pub struct ButtonLike { pub(super) selected: bool, pub(super) width: Option, size: ButtonSize, + rounding: Option, tooltip: Option AnyView>>, on_click: Option>, children: SmallVec<[AnyElement; 2]>, @@ -271,11 +279,17 @@ impl ButtonLike { selected: false, width: None, size: ButtonSize::Default, + rounding: Some(ButtonLikeRounding::All), tooltip: None, children: SmallVec::new(), on_click: None, } } + + pub(crate) fn rounding(mut self, rounding: impl Into>) -> Self { + self.rounding = rounding.into(); + self + } } impl Disableable for ButtonLike { @@ -356,7 +370,11 @@ impl RenderOnce for ButtonLike { .flex_none() .h(self.size.height()) .when_some(self.width, |this, width| this.w(width).justify_center()) - .rounded_md() + .when_some(self.rounding, |this, rounding| match rounding { + ButtonLikeRounding::All => this.rounded_md(), + ButtonLikeRounding::Left => this.rounded_l_md(), + ButtonLikeRounding::Right => this.rounded_r_md(), + }) .gap_1() .map(|this| match self.size { ButtonSize::Default | ButtonSize::Compact => this.px_1(), diff --git a/crates/ui2/src/components/button/toggle_button.rs b/crates/ui2/src/components/button/toggle_button.rs new file mode 100644 index 0000000000..39a517111b --- /dev/null +++ b/crates/ui2/src/components/button/toggle_button.rs @@ -0,0 +1,128 @@ +use gpui::{AnyView, ClickEvent}; + +use crate::{prelude::*, ButtonLike, ButtonLikeRounding}; + +/// The position of a [`ToggleButton`] within a group of buttons. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum ToggleButtonPosition { + /// The toggle button is first in the group. + First, + + /// The toggle button is in the middle of the group (i.e., it is not the first or last toggle button). + Middle, + + /// The toggle button is last in the group. + Last, +} + +#[derive(IntoElement)] +pub struct ToggleButton { + base: ButtonLike, + position_in_group: Option, + label: SharedString, + label_color: Option, +} + +impl ToggleButton { + pub fn new(id: impl Into, label: impl Into) -> Self { + Self { + base: ButtonLike::new(id), + position_in_group: None, + label: label.into(), + label_color: None, + } + } + + pub fn color(mut self, label_color: impl Into>) -> Self { + self.label_color = label_color.into(); + self + } + + pub fn position_in_group(mut self, position: ToggleButtonPosition) -> Self { + self.position_in_group = Some(position); + self + } + + pub fn first(self) -> Self { + self.position_in_group(ToggleButtonPosition::First) + } + + pub fn middle(self) -> Self { + self.position_in_group(ToggleButtonPosition::Middle) + } + + pub fn last(self) -> Self { + self.position_in_group(ToggleButtonPosition::Last) + } +} + +impl Selectable for ToggleButton { + fn selected(mut self, selected: bool) -> Self { + self.base = self.base.selected(selected); + self + } +} + +impl Disableable for ToggleButton { + fn disabled(mut self, disabled: bool) -> Self { + self.base = self.base.disabled(disabled); + self + } +} + +impl Clickable for ToggleButton { + fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self { + self.base = self.base.on_click(handler); + self + } +} + +impl ButtonCommon for ToggleButton { + fn id(&self) -> &ElementId { + self.base.id() + } + + fn style(mut self, style: ButtonStyle) -> Self { + self.base = self.base.style(style); + self + } + + fn size(mut self, size: ButtonSize) -> Self { + self.base = self.base.size(size); + self + } + + fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self { + self.base = self.base.tooltip(tooltip); + self + } +} + +impl RenderOnce for ToggleButton { + type Rendered = ButtonLike; + + fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + let is_disabled = self.base.disabled; + let is_selected = self.base.selected; + + let label_color = if is_disabled { + Color::Disabled + } else if is_selected { + Color::Selected + } else { + self.label_color.unwrap_or_default() + }; + + self.base + .when_some(self.position_in_group, |this, position| match position { + ToggleButtonPosition::First => this.rounding(ButtonLikeRounding::Left), + ToggleButtonPosition::Middle => this.rounding(None), + ToggleButtonPosition::Last => this.rounding(ButtonLikeRounding::Right), + }) + .child( + Label::new(self.label) + .color(label_color) + .line_height_style(LineHeightStyle::UILabel), + ) + } +} diff --git a/crates/ui2/src/components/stories.rs b/crates/ui2/src/components/stories.rs index f02787a1db..f321a7525f 100644 --- a/crates/ui2/src/components/stories.rs +++ b/crates/ui2/src/components/stories.rs @@ -12,6 +12,7 @@ mod list_header; mod list_item; mod tab; mod tab_bar; +mod toggle_button; pub use avatar::*; pub use button::*; @@ -27,3 +28,4 @@ pub use list_header::*; pub use list_item::*; pub use tab::*; pub use tab_bar::*; +pub use toggle_button::*; diff --git a/crates/ui2/src/components/stories/toggle_button.rs b/crates/ui2/src/components/stories/toggle_button.rs new file mode 100644 index 0000000000..6fe741ada3 --- /dev/null +++ b/crates/ui2/src/components/stories/toggle_button.rs @@ -0,0 +1,89 @@ +use gpui::{Component, Render}; +use story::{StoryContainer, StoryItem, StorySection}; + +use crate::{prelude::*, ToggleButton}; + +pub struct ToggleButtonStory; + +impl Render for ToggleButtonStory { + type Element = Component; + + fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + StoryContainer::new( + "Toggle Button", + "crates/ui2/src/components/stories/toggle_button.rs", + ) + .child( + StorySection::new().child( + StoryItem::new( + "Default", + ToggleButton::new("default_toggle_button", "Hello"), + ) + .description("Displays a toggle button.") + .usage(""), + ), + ) + .child( + StorySection::new().child( + StoryItem::new( + "Toggle button group", + h_stack() + .child( + ToggleButton::new(1, "Apple") + .style(ButtonStyle::Filled) + .first(), + ) + .child( + ToggleButton::new(2, "Banana") + .style(ButtonStyle::Filled) + .middle(), + ) + .child( + ToggleButton::new(3, "Cherry") + .style(ButtonStyle::Filled) + .middle(), + ) + .child( + ToggleButton::new(4, "Dragonfruit") + .style(ButtonStyle::Filled) + .last(), + ), + ) + .description("Displays a group of toggle buttons.") + .usage(""), + ), + ) + .child( + StorySection::new().child( + StoryItem::new( + "Toggle button group with selection", + h_stack() + .child( + ToggleButton::new(1, "Apple") + .style(ButtonStyle::Filled) + .first(), + ) + .child( + ToggleButton::new(2, "Banana") + .style(ButtonStyle::Filled) + .selected(true) + .middle(), + ) + .child( + ToggleButton::new(3, "Cherry") + .style(ButtonStyle::Filled) + .middle(), + ) + .child( + ToggleButton::new(4, "Dragonfruit") + .style(ButtonStyle::Filled) + .last(), + ), + ) + .description("Displays a group of toggle buttons.") + .usage(""), + ), + ) + .into_element() + } +} From 93c8bee7476b7813e24537d4501b998aa60b3061 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 18:32:12 -0500 Subject: [PATCH 232/644] Use `ToggleButton`s for search mode in buffer search --- crates/search2/src/buffer_search.rs | 43 +++++++++++++++++++++++------ crates/search2/src/search_bar.rs | 20 +------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index 06e1b625bc..f4f350893a 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -1,7 +1,7 @@ use crate::{ history::SearchHistory, mode::{next_mode, SearchMode}, - search_bar::{render_nav_button, render_search_mode_button}, + search_bar::render_nav_button, ActivateRegexMode, ActivateTextMode, CycleMode, NextHistoryQuery, PreviousHistoryQuery, ReplaceAll, ReplaceNext, SearchOptions, SelectAllMatches, SelectNextMatch, SelectPrevMatch, ToggleCaseSensitive, ToggleReplace, ToggleWholeWord, @@ -21,7 +21,7 @@ use settings::Settings; use std::{any::Any, sync::Arc}; use theme::ThemeSettings; -use ui::{h_stack, prelude::*, Icon, IconButton, IconElement, Tooltip}; +use ui::{h_stack, prelude::*, Icon, IconButton, IconElement, ToggleButton, Tooltip}; use util::ResultExt; use workspace::{ item::ItemHandle, @@ -165,11 +165,6 @@ impl Render for BufferSearchBar { editor.set_placeholder_text("Replace with...", cx); }); - let search_button_for_mode = |mode| { - let is_active = self.current_mode == mode; - - render_search_mode_button(mode, is_active) - }; let match_count = self .active_searchable_item .as_ref() @@ -257,8 +252,38 @@ impl Render for BufferSearchBar { .flex_none() .child( h_stack() - .child(search_button_for_mode(SearchMode::Text)) - .child(search_button_for_mode(SearchMode::Regex)), + .child( + ToggleButton::new("search-mode-text", SearchMode::Text.label()) + .style(ButtonStyle::Filled) + .selected(self.current_mode == SearchMode::Text) + .on_click(cx.listener(move |_, _event, cx| { + cx.dispatch_action(SearchMode::Text.action()) + })) + .tooltip(|cx| { + Tooltip::for_action( + SearchMode::Text.tooltip(), + &*SearchMode::Text.action(), + cx, + ) + }) + .first(), + ) + .child( + ToggleButton::new("search-mode-regex", SearchMode::Regex.label()) + .style(ButtonStyle::Filled) + .selected(self.current_mode == SearchMode::Regex) + .on_click(cx.listener(move |_, _event, cx| { + cx.dispatch_action(SearchMode::Regex.action()) + })) + .tooltip(|cx| { + Tooltip::for_action( + SearchMode::Regex.tooltip(), + &*SearchMode::Regex.action(), + cx, + ) + }) + .last(), + ), ) .when(supported_options.replacement, |this| { this.child( diff --git a/crates/search2/src/search_bar.rs b/crates/search2/src/search_bar.rs index dcc46ac228..628be3112e 100644 --- a/crates/search2/src/search_bar.rs +++ b/crates/search2/src/search_bar.rs @@ -1,8 +1,6 @@ use gpui::{Action, IntoElement}; +use ui::IconButton; use ui::{prelude::*, Tooltip}; -use ui::{Button, IconButton}; - -use crate::mode::SearchMode; pub(super) fn render_nav_button( icon: ui::Icon, @@ -18,19 +16,3 @@ pub(super) fn render_nav_button( .tooltip(move |cx| Tooltip::for_action(tooltip, action, cx)) .disabled(!active) } - -pub(crate) fn render_search_mode_button(mode: SearchMode, is_active: bool) -> Button { - Button::new(mode.label(), mode.label()) - .selected(is_active) - .on_click({ - let action = mode.action(); - move |_, cx| { - cx.dispatch_action(action.boxed_clone()); - } - }) - .tooltip({ - let action = mode.action(); - let tooltip_text = mode.tooltip(); - move |cx| Tooltip::for_action(tooltip_text.clone(), &*action, cx) - }) -} From 11807bb82db910e6ac0f09246b4c14b991845fe4 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Wed, 20 Dec 2023 18:47:22 -0500 Subject: [PATCH 233/644] Add large variant for buttons --- crates/search2/src/buffer_search.rs | 2 ++ crates/ui2/src/components/button/button_like.rs | 3 +++ crates/ui2/src/components/stories/toggle_button.rs | 8 ++++++++ 3 files changed, 13 insertions(+) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index f4f350893a..eae741afde 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -255,6 +255,7 @@ impl Render for BufferSearchBar { .child( ToggleButton::new("search-mode-text", SearchMode::Text.label()) .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .selected(self.current_mode == SearchMode::Text) .on_click(cx.listener(move |_, _event, cx| { cx.dispatch_action(SearchMode::Text.action()) @@ -271,6 +272,7 @@ impl Render for BufferSearchBar { .child( ToggleButton::new("search-mode-regex", SearchMode::Regex.label()) .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .selected(self.current_mode == SearchMode::Regex) .on_click(cx.listener(move |_, _event, cx| { cx.dispatch_action(SearchMode::Regex.action()) diff --git a/crates/ui2/src/components/button/button_like.rs b/crates/ui2/src/components/button/button_like.rs index b25ac1d1ec..44e18e850d 100644 --- a/crates/ui2/src/components/button/button_like.rs +++ b/crates/ui2/src/components/button/button_like.rs @@ -233,6 +233,7 @@ impl ButtonStyle { /// that are consistently sized with buttons. #[derive(Default, PartialEq, Clone, Copy)] pub enum ButtonSize { + Large, #[default] Default, Compact, @@ -242,6 +243,7 @@ pub enum ButtonSize { impl ButtonSize { fn height(self) -> Rems { match self { + ButtonSize::Large => rems(32. / 16.), ButtonSize::Default => rems(22. / 16.), ButtonSize::Compact => rems(18. / 16.), ButtonSize::None => rems(16. / 16.), @@ -377,6 +379,7 @@ impl RenderOnce for ButtonLike { }) .gap_1() .map(|this| match self.size { + ButtonSize::Large => this.px_2(), ButtonSize::Default | ButtonSize::Compact => this.px_1(), ButtonSize::None => this, }) diff --git a/crates/ui2/src/components/stories/toggle_button.rs b/crates/ui2/src/components/stories/toggle_button.rs index 6fe741ada3..0a4ea5f83e 100644 --- a/crates/ui2/src/components/stories/toggle_button.rs +++ b/crates/ui2/src/components/stories/toggle_button.rs @@ -31,21 +31,25 @@ impl Render for ToggleButtonStory { .child( ToggleButton::new(1, "Apple") .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .first(), ) .child( ToggleButton::new(2, "Banana") .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .middle(), ) .child( ToggleButton::new(3, "Cherry") .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .middle(), ) .child( ToggleButton::new(4, "Dragonfruit") .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .last(), ), ) @@ -61,22 +65,26 @@ impl Render for ToggleButtonStory { .child( ToggleButton::new(1, "Apple") .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .first(), ) .child( ToggleButton::new(2, "Banana") .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .selected(true) .middle(), ) .child( ToggleButton::new(3, "Cherry") .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .middle(), ) .child( ToggleButton::new(4, "Dragonfruit") .style(ButtonStyle::Filled) + .size(ButtonSize::Large) .last(), ), ) From 5e7c74c7b6c809df7acdea14fadcd0d2bf354619 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 20 Dec 2023 16:01:52 -0800 Subject: [PATCH 234/644] Ensure that on_release callbacks are called even if view outlives its window --- crates/go_to_line2/src/go_to_line.rs | 28 ++++++++++++++++------------ crates/gpui2/src/window.rs | 8 ++++++-- crates/vim2/src/editor_events.rs | 6 +++--- crates/workspace2/src/workspace2.rs | 2 +- crates/zed2/src/open_listener.rs | 2 +- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index d6b464cf0e..02fcd47716 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -1,8 +1,8 @@ use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor}; use gpui::{ - actions, div, prelude::*, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, - FocusableView, Render, SharedString, Styled, Subscription, View, ViewContext, VisualContext, - WindowContext, + actions, div, prelude::*, AnyWindowHandle, AppContext, DismissEvent, Div, EventEmitter, + FocusHandle, FocusableView, Render, SharedString, Styled, Subscription, View, ViewContext, + VisualContext, }; use text::{Bias, Point}; use theme::ActiveTheme; @@ -74,15 +74,19 @@ impl GoToLine { } } - fn release(&mut self, cx: &mut WindowContext) { - let scroll_position = self.prev_scroll_position.take(); - self.active_editor.update(cx, |editor, cx| { - editor.highlight_rows(None); - if let Some(scroll_position) = scroll_position { - editor.set_scroll_position(scroll_position, cx); - } - cx.notify(); - }) + fn release(&mut self, window: AnyWindowHandle, cx: &mut AppContext) { + window + .update(cx, |_, cx| { + let scroll_position = self.prev_scroll_position.take(); + self.active_editor.update(cx, |editor, cx| { + editor.highlight_rows(None); + if let Some(scroll_position) = scroll_position { + editor.set_scroll_position(scroll_position, cx); + } + cx.notify(); + }) + }) + .ok(); } fn on_line_editor_event( diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 8546e094d4..9e8347c783 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -2422,16 +2422,20 @@ impl<'a, V: 'static> ViewContext<'a, V> { subscription } + /// Register a callback to be invoked when the view is released. + /// + /// The callback receives a handle to the view's window. This handle may be + /// invalid, if the window was closed before the view was released. pub fn on_release( &mut self, - on_release: impl FnOnce(&mut V, &mut WindowContext) + 'static, + on_release: impl FnOnce(&mut V, AnyWindowHandle, &mut AppContext) + 'static, ) -> Subscription { let window_handle = self.window.handle; let (subscription, activate) = self.app.release_listeners.insert( self.view.model.entity_id, Box::new(move |this, cx| { let this = this.downcast_mut().expect("invalid entity type"); - let _ = window_handle.update(cx, |_, cx| on_release(this, cx)); + on_release(this, window_handle, cx) }), ); activate(); diff --git a/crates/vim2/src/editor_events.rs b/crates/vim2/src/editor_events.rs index 0e2a1451fe..70f486f298 100644 --- a/crates/vim2/src/editor_events.rs +++ b/crates/vim2/src/editor_events.rs @@ -13,7 +13,7 @@ pub fn init(cx: &mut AppContext) { .detach(); let id = cx.view().entity_id(); - cx.on_release(move |_, cx| released(id, cx)).detach(); + cx.on_release(move |_, _, cx| released(id, cx)).detach(); }) .detach(); } @@ -51,8 +51,8 @@ fn blurred(editor: View, cx: &mut WindowContext) { }); } -fn released(entity_id: EntityId, cx: &mut WindowContext) { - Vim::update(cx, |vim, _| { +fn released(entity_id: EntityId, cx: &mut AppContext) { + cx.update_global(|vim: &mut Vim, _| { if vim .active_editor .as_ref() diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 797e95088d..c8712205cb 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -642,7 +642,7 @@ impl Workspace { this.serialize_workspace(cx); cx.notify(); }), - cx.on_release(|this, cx| { + cx.on_release(|this, _, cx| { this.app_state.workspace_store.update(cx, |store, _| { store.workspaces.remove(&this.window_self); }) diff --git a/crates/zed2/src/open_listener.rs b/crates/zed2/src/open_listener.rs index 4c961a2b31..b45254f717 100644 --- a/crates/zed2/src/open_listener.rs +++ b/crates/zed2/src/open_listener.rs @@ -253,7 +253,7 @@ pub async fn handle_cli_connection( let (done_tx, done_rx) = oneshot::channel(); let _subscription = workspace.update(&mut cx, |workspace, cx| { - cx.on_release(move |_, _| { + cx.on_release(move |_, _, _| { let _ = done_tx.send(()); }) }); From 42bdc11112346aced8d596b91bb5bdc8f335da44 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 20 Dec 2023 16:08:58 -0800 Subject: [PATCH 235/644] Prune dead workspaces from WorkspaceStore on read Also, remove unnecessary window handle from Workspace. --- crates/workspace2/src/workspace2.rs | 33 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index c8712205cb..2bc0d40310 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -430,7 +430,6 @@ pub enum Event { } pub struct Workspace { - window_self: WindowHandle, weak_self: WeakView, workspace_actions: Vec) -> Div>>, zoomed: Option, @@ -642,9 +641,10 @@ impl Workspace { this.serialize_workspace(cx); cx.notify(); }), - cx.on_release(|this, _, cx| { + cx.on_release(|this, window, cx| { this.app_state.workspace_store.update(cx, |store, _| { - store.workspaces.remove(&this.window_self); + let window = window.downcast::().unwrap(); + debug_assert!(store.workspaces.remove(&window)); }) }), ]; @@ -665,7 +665,6 @@ impl Workspace { // }); }); Workspace { - window_self: window_handle, weak_self: weak_handle.clone(), zoomed: None, zoomed_position: None, @@ -3708,7 +3707,7 @@ impl WorkspaceStore { let active_project = ActiveCall::global(cx).read(cx).location().cloned(); let mut response = proto::FollowResponse::default(); - for workspace in &this.workspaces { + this.workspaces.retain(|workspace| { workspace .update(cx, |workspace, cx| { let handler_response = workspace.handle_follow(follower.project_id, cx); @@ -3726,8 +3725,8 @@ impl WorkspaceStore { } } }) - .ok(); - } + .is_ok() + }); if let Err(ix) = this.followers.binary_search(&follower) { this.followers.insert(ix, follower); @@ -3765,15 +3764,17 @@ impl WorkspaceStore { let update = envelope.payload; this.update(&mut cx, |this, cx| { - for workspace in &this.workspaces { - workspace.update(cx, |workspace, cx| { - let project_id = workspace.project.read(cx).remote_id(); - if update.project_id != project_id && update.project_id.is_some() { - return; - } - workspace.handle_update_followers(leader_id, update.clone(), cx); - })?; - } + this.workspaces.retain(|workspace| { + workspace + .update(cx, |workspace, cx| { + let project_id = workspace.project.read(cx).remote_id(); + if update.project_id != project_id && update.project_id.is_some() { + return; + } + workspace.handle_update_followers(leader_id, update.clone(), cx); + }) + .is_ok() + }); Ok(()) })? } From 2f56fe9129e98520ee9ffbc79c38f0d01ae4ca4d Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 21 Dec 2023 02:21:27 +0200 Subject: [PATCH 236/644] For file finder queries, search in all gitignored worktree entries --- crates/file_finder/src/file_finder.rs | 131 ++++++++++++++++++++++--- crates/file_finder2/src/file_finder.rs | 120 +++++++++++++++++++--- 2 files changed, 229 insertions(+), 22 deletions(-) diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 156b062df8..cd64e8c4fb 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -324,15 +324,10 @@ impl FileFinderDelegate { let include_root_name = worktrees.len() > 1; let candidate_sets = worktrees .into_iter() - .map(|worktree| { - let worktree = worktree.read(cx); - PathMatchCandidateSet { - snapshot: worktree.snapshot(), - include_ignored: worktree - .root_entry() - .map_or(false, |entry| entry.is_ignored), - include_root_name, - } + .map(|worktree| PathMatchCandidateSet { + snapshot: worktree.read(cx).snapshot(), + include_ignored: true, + include_root_name, }) .collect::>(); @@ -1058,7 +1053,7 @@ mod tests { } #[gpui::test] - async fn test_ignored_files(cx: &mut TestAppContext) { + async fn test_ignored_root(cx: &mut TestAppContext) { let app_state = init_test(cx); app_state .fs @@ -1115,7 +1110,105 @@ mod tests { f.delegate_mut().spawn_search(test_path_like("hi"), cx) }) .await; - finder.read_with(cx, |f, _| assert_eq!(f.delegate().matches.len(), 7)); + finder.update(cx, |f, _| { + assert_eq!( + collect_search_results(f), + vec![ + PathBuf::from("ignored-root/happiness"), + PathBuf::from("ignored-root/height"), + PathBuf::from("ignored-root/hi"), + PathBuf::from("ignored-root/hiccup"), + PathBuf::from("tracked-root/happiness"), + PathBuf::from("tracked-root/height"), + PathBuf::from("tracked-root/hi"), + PathBuf::from("tracked-root/hiccup"), + ], + "All files in all roots (including gitignored) should be searched" + ) + }); + } + + #[gpui::test] + async fn test_ignored_files(cx: &mut TestAppContext) { + let app_state = init_test(cx); + app_state + .fs + .as_fake() + .insert_tree( + "/root", + json!({ + ".git": {}, + ".gitignore": "ignored_a\n.env\n", + "a": { + "banana_env": "11", + "bandana_env": "12", + }, + "ignored_a": { + "ignored_banana_env": "21", + "ignored_bandana_env": "22", + "ignored_nested": { + "ignored_nested_banana_env": "31", + "ignored_nested_bandana_env": "32", + }, + }, + ".env": "something", + }), + ) + .await; + + let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; + let window = cx.add_window(|cx| Workspace::test_new(project, cx)); + let workspace = window.root(cx); + cx.dispatch_action(window.into(), Toggle); + + let finder = cx.read(|cx| workspace.read(cx).modal::().unwrap()); + + finder + .update(cx, |finder, cx| { + finder.delegate_mut().update_matches("env".to_string(), cx) + }) + .await; + finder.update(cx, |f, _| { + assert_eq!( + collect_search_results(f), + vec![ + PathBuf::from(".env"), + PathBuf::from("a/banana_env"), + PathBuf::from("a/bandana_env"), + ], + "Root gitignored files and all non-gitignored files should be searched" + ) + }); + + let _ = workspace + .update(cx, |workspace, cx| { + workspace.open_abs_path( + PathBuf::from("/root/ignored_a/ignored_banana_env"), + true, + cx, + ) + }) + .await + .unwrap(); + cx.foreground().run_until_parked(); + finder + .update(cx, |finder, cx| { + finder.delegate_mut().update_matches("env".to_string(), cx) + }) + .await; + finder.update(cx, |f, _| { + assert_eq!( + collect_search_results(f), + vec![ + PathBuf::from(".env"), + PathBuf::from("a/banana_env"), + PathBuf::from("a/bandana_env"), + PathBuf::from("ignored_a/ignored_banana_env"), + PathBuf::from("ignored_a/ignored_bandana_env"), + ], + "Root gitignored dir got listed and its entries got into worktree, but all gitignored dirs below it were not listed. Old entries + new listed gitignored entries should be searched" + ) + }); } #[gpui::test] @@ -2192,4 +2285,20 @@ mod tests { absolute: None, } } + + fn collect_search_results(picker: &Picker) -> Vec { + let matches = &picker.delegate().matches; + assert!( + matches.history.is_empty(), + "Should have no history matches, but got: {:?}", + matches.history + ); + let mut results = matches + .search + .iter() + .map(|path_match| Path::new(path_match.path_prefix.as_ref()).join(&path_match.path)) + .collect::>(); + results.sort(); + results + } } diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index a9619530c6..8faba99cb2 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -354,15 +354,10 @@ impl FileFinderDelegate { let include_root_name = worktrees.len() > 1; let candidate_sets = worktrees .into_iter() - .map(|worktree| { - let worktree = worktree.read(cx); - PathMatchCandidateSet { - snapshot: worktree.snapshot(), - include_ignored: worktree - .root_entry() - .map_or(false, |entry| entry.is_ignored), - include_root_name, - } + .map(|worktree| PathMatchCandidateSet { + snapshot: worktree.read(cx).snapshot(), + include_ignored: true, + include_root_name, }) .collect::>(); @@ -1038,7 +1033,7 @@ mod tests { } #[gpui::test] - async fn test_ignored_files(cx: &mut TestAppContext) { + async fn test_ignored_root(cx: &mut TestAppContext) { let app_state = init_test(cx); app_state .fs @@ -1081,7 +1076,94 @@ mod tests { picker.delegate.spawn_search(test_path_like("hi"), cx) }) .await; - picker.update(cx, |picker, _| assert_eq!(picker.delegate.matches.len(), 7)); + picker.update(cx, |picker, _| { + assert_eq!( + collect_search_results(picker), + vec![ + PathBuf::from("ignored-root/happiness"), + PathBuf::from("ignored-root/height"), + PathBuf::from("ignored-root/hi"), + PathBuf::from("ignored-root/hiccup"), + PathBuf::from("tracked-root/happiness"), + PathBuf::from("tracked-root/height"), + PathBuf::from("tracked-root/hi"), + PathBuf::from("tracked-root/hiccup"), + ], + "All files in all roots (including gitignored) should be searched" + ) + }); + } + + #[gpui::test] + async fn test_ignored_files(cx: &mut TestAppContext) { + let app_state = init_test(cx); + app_state + .fs + .as_fake() + .insert_tree( + "/root", + json!({ + ".git": {}, + ".gitignore": "ignored_a\n.env\n", + "a": { + "banana_env": "11", + "bandana_env": "12", + }, + "ignored_a": { + "ignored_banana_env": "21", + "ignored_bandana_env": "22", + "ignored_nested": { + "ignored_nested_banana_env": "31", + "ignored_nested_bandana_env": "32", + }, + }, + ".env": "something", + }), + ) + .await; + + let project = Project::test(app_state.fs.clone(), ["/root".as_ref()], cx).await; + + let (picker, workspace, cx) = build_find_picker(project, cx); + + cx.simulate_input("env"); + picker.update(cx, |picker, _| { + assert_eq!( + collect_search_results(picker), + vec![ + PathBuf::from(".env"), + PathBuf::from("a/banana_env"), + PathBuf::from("a/bandana_env"), + ], + "Root gitignored files and all non-gitignored files should be searched" + ) + }); + + let _ = workspace + .update(cx, |workspace, cx| { + workspace.open_abs_path( + PathBuf::from("/root/ignored_a/ignored_banana_env"), + true, + cx, + ) + }) + .await + .unwrap(); + cx.run_until_parked(); + cx.simulate_input("env"); + picker.update(cx, |picker, _| { + assert_eq!( + collect_search_results(picker), + vec![ + PathBuf::from(".env"), + PathBuf::from("a/banana_env"), + PathBuf::from("a/bandana_env"), + PathBuf::from("ignored_a/ignored_banana_env"), + PathBuf::from("ignored_a/ignored_bandana_env"), + ], + "Root gitignored dir got listed and its entries got into worktree, but all gitignored dirs below it were not listed. Old entries + new listed gitignored entries should be searched" + ) + }); } #[gpui::test] @@ -1846,4 +1928,20 @@ mod tests { .clone() }) } + + fn collect_search_results(picker: &Picker) -> Vec { + let matches = &picker.delegate.matches; + assert!( + matches.history.is_empty(), + "Should have no history matches, but got: {:?}", + matches.history + ); + let mut results = matches + .search + .iter() + .map(|path_match| Path::new(path_match.path_prefix.as_ref()).join(&path_match.path)) + .collect::>(); + results.sort(); + results + } } From 24970c1da9d19af78bd5dbdac9d873959770d06d Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 20 Dec 2023 16:33:10 -0800 Subject: [PATCH 237/644] Fix view handle leaks in ListState callbacks --- crates/collab_ui2/src/chat_panel.rs | 10 +++++++--- crates/collab_ui2/src/collab_panel.rs | 9 ++++++--- crates/collab_ui2/src/notification_panel.rs | 12 ++++++------ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/crates/collab_ui2/src/chat_panel.rs b/crates/collab_ui2/src/chat_panel.rs index f3f2a37171..27eb4ca17a 100644 --- a/crates/collab_ui2/src/chat_panel.rs +++ b/crates/collab_ui2/src/chat_panel.rs @@ -92,11 +92,15 @@ impl ChatPanel { let workspace_handle = workspace.weak_handle(); - cx.build_view(|cx| { - let view: View = cx.view().clone(); + cx.build_view(|cx: &mut ViewContext| { + let view = cx.view().downgrade(); let message_list = ListState::new(0, gpui::ListAlignment::Bottom, px(1000.), move |ix, cx| { - view.update(cx, |view, cx| view.render_message(ix, cx)) + if let Some(view) = view.upgrade() { + view.update(cx, |view, cx| view.render_message(ix, cx)) + } else { + div().into_any() + } }); message_list.set_scroll_handler(cx.listener(|this, event: &ListScrollEvent, cx| { diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 35e2f8d7ed..b19d0ba2eb 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -178,8 +178,6 @@ enum ListEntry { impl CollabPanel { pub fn new(workspace: &mut Workspace, cx: &mut ViewContext) -> View { cx.build_view(|cx| { - let view = cx.view().clone(); - let filter_editor = cx.build_view(|cx| { let mut editor = Editor::single_line(cx); editor.set_placeholder_text("Filter...", cx); @@ -219,9 +217,14 @@ impl CollabPanel { }) .detach(); + let view = cx.view().downgrade(); let list_state = ListState::new(0, gpui::ListAlignment::Top, px(1000.), move |ix, cx| { - view.update(cx, |view, cx| view.render_list_entry(ix, cx)) + if let Some(view) = view.upgrade() { + view.update(cx, |view, cx| view.render_list_entry(ix, cx)) + } else { + div().into_any() + } }); let mut this = Self { diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index 35288e810d..30c3439121 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -88,8 +88,6 @@ impl NotificationPanel { let workspace_handle = workspace.weak_handle(); cx.build_view(|cx: &mut ViewContext| { - let view = cx.view().clone(); - let mut status = client.status(); cx.spawn(|this, mut cx| async move { while let Some(_) = status.next().await { @@ -105,12 +103,14 @@ impl NotificationPanel { }) .detach(); + let view = cx.view().downgrade(); let notification_list = ListState::new(0, ListAlignment::Top, px(1000.), move |ix, cx| { - view.update(cx, |this, cx| { - this.render_notification(ix, cx) - .unwrap_or_else(|| div().into_any()) - }) + view.upgrade() + .and_then(|view| { + view.update(cx, |this, cx| this.render_notification(ix, cx)) + }) + .unwrap_or_else(|| div().into_any()) }); notification_list.set_scroll_handler(cx.listener( |this, event: &ListScrollEvent, cx| { From c56e7cd1241c61a6280e070cfa516d04d5007cae Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 19:53:57 -0700 Subject: [PATCH 238/644] Remove unused import --- crates/gpui2/src/style.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 89527c9d5a..3e9593b0fd 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -1,10 +1,10 @@ use std::{iter, mem, ops::Range}; use crate::{ - black, phi, point, quad, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, - ContentMask, Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, - Font, FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba, - SharedString, Size, SizeRefinement, Styled, TextRun, WindowContext, + black, phi, point, quad, rems, AbsoluteLength, BorrowWindow, Bounds, ContentMask, Corners, + CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, Font, FontFeatures, + FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba, SharedString, Size, + SizeRefinement, Styled, TextRun, WindowContext, }; use collections::HashSet; use refineable::{Cascade, Refineable}; From 5747c9b7a1a856710ea9c5319bf73c6e98514c4c Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 20 Dec 2023 19:52:08 -0700 Subject: [PATCH 239/644] Clear pending keystrokes when an action is dispatched --- crates/gpui2/src/key_dispatch.rs | 2 ++ crates/gpui2/src/keymap/matcher.rs | 5 ----- crates/gpui2/src/window.rs | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index 03adf887b5..3201e00bc6 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -103,6 +103,8 @@ impl DispatchTree { .keystroke_matchers .remove_entry(self.context_stack.as_slice()) { + dbg!("preserve matcher", matcher.has_pending_keystrokes()); + self.keystroke_matchers.insert(context_stack, matcher); } } diff --git a/crates/gpui2/src/keymap/matcher.rs b/crates/gpui2/src/keymap/matcher.rs index 7d4e408e93..9d74975c56 100644 --- a/crates/gpui2/src/keymap/matcher.rs +++ b/crates/gpui2/src/keymap/matcher.rs @@ -19,11 +19,6 @@ impl KeystrokeMatcher { } } - // todo!("replace with a function that calls an FnMut for every binding matching the action") - // pub fn bindings_for_action(&self, action_id: TypeId) -> impl Iterator { - // self.keymap.lock().bindings_for_action(action_id) - // } - pub fn clear_pending(&mut self) { self.pending_keystrokes.clear(); } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 9e8347c783..49fb60efe4 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -572,6 +572,17 @@ impl<'a> WindowContext<'a> { }); } + pub(crate) fn clear_pending_keystrokes(&mut self) { + self.window + .rendered_frame + .dispatch_tree + .clear_pending_keystrokes(); + self.window + .next_frame + .dispatch_tree + .clear_pending_keystrokes(); + } + /// Schedules the given function to be run at the end of the current effect cycle, allowing entities /// that are currently on the stack to be returned to the app. pub fn defer(&mut self, f: impl FnOnce(&mut WindowContext) + 'static) { @@ -1626,6 +1637,10 @@ impl<'a> WindowContext<'a> { } } + if !actions.is_empty() { + self.clear_pending_keystrokes(); + } + for action in actions { self.dispatch_action_on_node(node_id, action.boxed_clone()); if !self.propagate_event { From 036636ee808775fd96e8daca4222b72d17b34e9e Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 20 Dec 2023 23:54:50 -0500 Subject: [PATCH 240/644] Fix layout issues with feedback modal The feedback modal still needs a styling update --- crates/feedback2/src/feedback_modal.rs | 99 ++++++++++++-------------- 1 file changed, 47 insertions(+), 52 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 22904f3a0a..165a0a332c 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -447,66 +447,61 @@ impl Render for FeedbackModal { .child(self.feedback_editor.clone()), ) .child( - div() + h_stack() + .bg(cx.theme().colors().editor_background) + .p_2() + .border() + .rounded_md() + .border_color(if self.valid_email_address() { + cx.theme().colors().border + } else { + red() + }) + .child(self.email_address_editor.clone()), + ) + .child( + h_stack() + .justify_between() + .gap_1() .child( - h_stack() - .bg(cx.theme().colors().editor_background) - .p_2() - .border() - .rounded_md() - .border_color(if self.valid_email_address() { - cx.theme().colors().border - } else { - red() - }) - .child(self.email_address_editor.clone()), + Button::new("community_repository", "Community Repository") + .style(ButtonStyle::Transparent) + .icon(Icon::ExternalLink) + .icon_position(IconPosition::End) + .icon_size(IconSize::Small) + .on_click(open_community_repo), ) .child( h_stack() - .justify_between() .gap_1() .child( - Button::new("community_repo", "Community Repo") - .style(ButtonStyle::Transparent) - .icon(Icon::ExternalLink) - .icon_position(IconPosition::End) - .icon_size(IconSize::Small) - .on_click(open_community_repo), + Button::new("cancel_feedback", "Cancel") + .style(ButtonStyle::Subtle) + .color(Color::Muted) + .on_click(cx.listener(move |_, _, cx| { + cx.spawn(|this, mut cx| async move { + this.update(&mut cx, |_, cx| cx.emit(DismissEvent)) + .ok(); + }) + .detach(); + })), ) .child( - h_stack() - .gap_1() - .child( - Button::new("cancel_feedback", "Cancel") - .style(ButtonStyle::Subtle) - .color(Color::Muted) - .on_click(cx.listener(move |_, _, cx| { - cx.spawn(|this, mut cx| async move { - this.update(&mut cx, |_, cx| { - cx.emit(DismissEvent) - }) - .ok(); - }) - .detach(); - })), - ) - .child( - Button::new("submit_feedback", submit_button_text) - .color(Color::Accent) - .style(ButtonStyle::Filled) - .on_click(cx.listener(|this, _, cx| { - this.submit(cx).detach(); - })) - .tooltip(move |cx| { - Tooltip::with_meta( - "Submit feedback to the Zed team.", - None, - provide_an_email_address, - cx, - ) - }) - .when(!self.can_submit(), |this| this.disabled(true)), - ), + Button::new("submit_feedback", submit_button_text) + .color(Color::Accent) + .style(ButtonStyle::Filled) + .on_click(cx.listener(|this, _, cx| { + this.submit(cx).detach(); + })) + .tooltip(move |cx| { + Tooltip::with_meta( + "Submit feedback to the Zed team.", + None, + provide_an_email_address, + cx, + ) + }) + .when(!self.can_submit(), |this| this.disabled(true)), ), ), ) From 73682daf38c023646b1fec6cffad9412661f059c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 09:41:48 +0100 Subject: [PATCH 241/644] Provide mut access to allocated arena struct via non-cloneable ArenaBox This commit also allows turning an `ArenaBox` into an `ArenaRef` when non-mutable access is required, which makes `ArenaRef: Clone`. This fixes a bug that prevented the command palette from reading all the available actions while the `command_palette::Toggle` action was being dispatched. --- crates/gpui2/src/arena.rs | 42 ++++++++++++--- crates/gpui2/src/element.rs | 4 +- crates/gpui2/src/key_dispatch.rs | 5 +- crates/gpui2/src/window.rs | 92 ++++++++++++-------------------- 4 files changed, 70 insertions(+), 73 deletions(-) diff --git a/crates/gpui2/src/arena.rs b/crates/gpui2/src/arena.rs index ef66188a0e..bb493a6d06 100644 --- a/crates/gpui2/src/arena.rs +++ b/crates/gpui2/src/arena.rs @@ -52,7 +52,7 @@ impl Arena { } #[inline(always)] - pub fn alloc(&mut self, f: impl FnOnce() -> T) -> ArenaRef { + pub fn alloc(&mut self, f: impl FnOnce() -> T) -> ArenaBox { #[inline(always)] unsafe fn inner_writer(ptr: *mut T, f: F) where @@ -70,7 +70,7 @@ impl Arena { let next_offset = self.offset.add(layout.size()); assert!(next_offset <= self.end); - let result = ArenaRef { + let result = ArenaBox { ptr: self.offset.cast(), valid: self.valid.clone(), }; @@ -93,15 +93,15 @@ impl Drop for Arena { } } -pub struct ArenaRef { +pub struct ArenaBox { ptr: *mut T, valid: Rc>, } -impl ArenaRef { +impl ArenaBox { #[inline(always)] - pub fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaRef { - ArenaRef { + pub fn map(mut self, f: impl FnOnce(&mut T) -> &mut U) -> ArenaBox { + ArenaBox { ptr: f(&mut self), valid: self.valid, } @@ -115,7 +115,7 @@ impl ArenaRef { } } -impl Deref for ArenaRef { +impl Deref for ArenaBox { type Target = T; #[inline(always)] @@ -125,7 +125,7 @@ impl Deref for ArenaRef { } } -impl DerefMut for ArenaRef { +impl DerefMut for ArenaBox { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { self.validate(); @@ -133,6 +133,32 @@ impl DerefMut for ArenaRef { } } +pub struct ArenaRef(ArenaBox); + +impl From> for ArenaRef { + fn from(value: ArenaBox) -> Self { + ArenaRef(value) + } +} + +impl Clone for ArenaRef { + fn clone(&self) -> Self { + Self(ArenaBox { + ptr: self.0.ptr, + valid: self.0.valid.clone(), + }) + } +} + +impl Deref for ArenaRef { + type Target = T; + + #[inline(always)] + fn deref(&self) -> &Self::Target { + self.0.deref() + } +} + #[cfg(test)] mod tests { use std::{cell::Cell, rc::Rc}; diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index d0ed50a3d5..4201123a10 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -1,5 +1,5 @@ use crate::{ - ArenaRef, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, + ArenaBox, AvailableSpace, BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, Size, ViewContext, WindowContext, ELEMENT_ARENA, }; use derive_more::{Deref, DerefMut}; @@ -405,7 +405,7 @@ where } } -pub struct AnyElement(ArenaRef); +pub struct AnyElement(ArenaBox); impl AnyElement { pub fn new(element: E) -> Self diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index 3201e00bc6..cc6376e68d 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -35,6 +35,7 @@ pub(crate) struct DispatchNode { type KeyListener = ArenaRef; +#[derive(Clone)] pub(crate) struct DispatchActionListener { pub(crate) action_type: TypeId, pub(crate) listener: ArenaRef, @@ -268,10 +269,6 @@ impl DispatchTree { &self.nodes[node_id.0] } - pub fn node_mut(&mut self, node_id: DispatchNodeId) -> &mut DispatchNode { - &mut self.nodes[node_id.0] - } - fn active_node(&mut self) -> &mut DispatchNode { let active_node_id = self.active_node_id(); &mut self.nodes[active_node_id.0] diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 49fb60efe4..e57984fa0d 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1,17 +1,15 @@ use crate::{ - arena::{Arena, ArenaRef}, - key_dispatch::DispatchActionListener, - px, size, transparent_black, Action, AnyDrag, AnyView, AppContext, AsyncWindowContext, - AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, DevicePixels, DispatchNodeId, - DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, EventEmitter, FileDropEvent, Flatten, - FontId, GlobalElementId, GlyphId, Hsla, ImageData, InputEvent, IsZero, KeyBinding, KeyContext, - KeyDownEvent, KeystrokeEvent, LayoutId, Model, ModelContext, Modifiers, MonochromeSprite, - MouseButton, MouseMoveEvent, MouseUpEvent, Path, Pixels, PlatformAtlas, PlatformDisplay, - PlatformInputHandler, PlatformWindow, Point, PolychromeSprite, PromptLevel, Quad, Render, - RenderGlyphParams, RenderImageParams, RenderSvgParams, ScaledPixels, Scene, SceneBuilder, - Shadow, SharedString, Size, Style, SubscriberSet, Subscription, Surface, TaffyLayoutEngine, - Task, Underline, UnderlineStyle, View, VisualContext, WeakView, WindowBounds, WindowOptions, - SUBPIXEL_VARIANTS, + px, size, transparent_black, Action, AnyDrag, AnyView, AppContext, Arena, ArenaBox, ArenaRef, + AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, + DevicePixels, DispatchActionListener, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, + Entity, EntityId, EventEmitter, FileDropEvent, Flatten, FontId, GlobalElementId, GlyphId, Hsla, + ImageData, InputEvent, IsZero, KeyBinding, KeyContext, KeyDownEvent, KeystrokeEvent, LayoutId, + Model, ModelContext, Modifiers, MonochromeSprite, MouseButton, MouseMoveEvent, MouseUpEvent, + Path, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point, + PolychromeSprite, PromptLevel, Quad, Render, RenderGlyphParams, RenderImageParams, + RenderSvgParams, ScaledPixels, Scene, SceneBuilder, Shadow, SharedString, Size, Style, + SubscriberSet, Subscription, Surface, TaffyLayoutEngine, Task, Underline, UnderlineStyle, View, + VisualContext, WeakView, WindowBounds, WindowOptions, SUBPIXEL_VARIANTS, }; use anyhow::{anyhow, Context as _, Result}; use collections::FxHashMap; @@ -96,7 +94,7 @@ impl DispatchPhase { } type AnyObserver = Box bool + 'static>; -type AnyMouseListener = ArenaRef; +type AnyMouseListener = ArenaBox; type AnyWindowFocusListener = Box bool + 'static>; struct FocusEvent { @@ -906,7 +904,10 @@ impl<'a> WindowContext<'a> { } }) .map(|handler| handler as _); - self.window.next_frame.dispatch_tree.on_key_event(listener); + self.window + .next_frame + .dispatch_tree + .on_key_event(ArenaRef::from(listener)); } /// Register an action listener on the window for the next frame. The type of action @@ -928,7 +929,7 @@ impl<'a> WindowContext<'a> { self.window .next_frame .dispatch_tree - .on_action(action_type, listener); + .on_action(action_type, ArenaRef::from(listener)); } pub fn is_action_available(&self, action: &dyn Action) -> bool { @@ -1339,7 +1340,7 @@ impl<'a> WindowContext<'a> { cx.window .next_frame .dispatch_tree - .on_action(*action_type, listener) + .on_action(*action_type, ArenaRef::from(listener)) } } @@ -1583,43 +1584,30 @@ impl<'a> WindowContext<'a> { self.propagate_event = true; for node_id in &dispatch_path { - let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); + let node = self.window.rendered_frame.dispatch_tree.node(*node_id); + if let Some(context) = node.context.clone() { context_stack.push(context); } - let key_listeners = mem::take(&mut node.key_listeners); - for key_listener in &key_listeners { + for key_listener in node.key_listeners.clone() { key_listener(event, DispatchPhase::Capture, self); if !self.propagate_event { - break; + return; } } - let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); - node.key_listeners = key_listeners; - - if !self.propagate_event { - return; - } } // Bubble phase for node_id in dispatch_path.iter().rev() { // Handle low level key events - let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); - let key_listeners = mem::take(&mut node.key_listeners); - for key_listener in &key_listeners { + let node = self.window.rendered_frame.dispatch_tree.node(*node_id); + for key_listener in node.key_listeners.clone() { key_listener(event, DispatchPhase::Bubble, self); if !self.propagate_event { - break; + return; } } - let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); - node.key_listeners = key_listeners; - - if !self.propagate_event { - return; - } // Match keystrokes let node = self.window.rendered_frame.dispatch_tree.node(*node_id); @@ -1667,52 +1655,38 @@ impl<'a> WindowContext<'a> { // Capture phase for node_id in &dispatch_path { - let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); - let action_listeners = mem::take(&mut node.action_listeners); + let node = self.window.rendered_frame.dispatch_tree.node(*node_id); for DispatchActionListener { action_type, listener, - } in &action_listeners + } in node.action_listeners.clone() { let any_action = action.as_any(); - if *action_type == any_action.type_id() { + if action_type == any_action.type_id() { listener(any_action, DispatchPhase::Capture, self); if !self.propagate_event { - break; + return; } } } - let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); - node.action_listeners = action_listeners; - - if !self.propagate_event { - return; - } } // Bubble phase for node_id in dispatch_path.iter().rev() { - let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); - let action_listeners = mem::take(&mut node.action_listeners); + let node = self.window.rendered_frame.dispatch_tree.node(*node_id); for DispatchActionListener { action_type, listener, - } in &action_listeners + } in node.action_listeners.clone() { let any_action = action.as_any(); - if *action_type == any_action.type_id() { + if action_type == any_action.type_id() { self.propagate_event = false; // Actions stop propagation by default during the bubble phase listener(any_action, DispatchPhase::Bubble, self); if !self.propagate_event { - break; + return; } } } - - let node = self.window.rendered_frame.dispatch_tree.node_mut(*node_id); - node.action_listeners = action_listeners; - if !self.propagate_event { - return; - } } } From c7933a6ad8d5c1ca8dd296e82ed39747bc74c95b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 09:44:54 +0100 Subject: [PATCH 242/644] Remove stray dbg --- crates/gpui2/src/key_dispatch.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/gpui2/src/key_dispatch.rs b/crates/gpui2/src/key_dispatch.rs index cc6376e68d..a9d717ea1a 100644 --- a/crates/gpui2/src/key_dispatch.rs +++ b/crates/gpui2/src/key_dispatch.rs @@ -104,8 +104,6 @@ impl DispatchTree { .keystroke_matchers .remove_entry(self.context_stack.as_slice()) { - dbg!("preserve matcher", matcher.has_pending_keystrokes()); - self.keystroke_matchers.insert(context_stack, matcher); } } From b38a09526c5d7953daf3f7b9ad03481424bdb3ac Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 10:03:15 +0100 Subject: [PATCH 243/644] Fix stale scroll position in tab bar --- crates/gpui2/src/elements/div.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 74b414bb03..7bda5966f5 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1467,6 +1467,14 @@ impl Interactivity { .clone(); let line_height = cx.line_height(); let scroll_max = (content_size - bounds.size).max(&Size::default()); + // Clamp scroll offset in case scroll max is smaller now (e.g., if children + // were removed or the bounds became larger). + { + let mut scroll_offset = scroll_offset.borrow_mut(); + scroll_offset.x = scroll_offset.x.clamp(-scroll_max.width, px(0.)); + scroll_offset.y = scroll_offset.x.clamp(-scroll_max.height, px(0.)); + } + let interactive_bounds = interactive_bounds.clone(); cx.on_mouse_event(move |event: &ScrollWheelEvent, phase, cx| { if phase == DispatchPhase::Bubble From b14c07ca54d40ec9184bdcdebe3223109cdeb09b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 21 Dec 2023 14:27:13 +0200 Subject: [PATCH 244/644] Fix Zed cli actions: opening notes and joining calls --- crates/workspace2/src/workspace2.rs | 18 +++++- crates/zed2/src/main.rs | 97 +++++++++++++++++++++-------- 2 files changed, 87 insertions(+), 28 deletions(-) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 2bc0d40310..b4508b9dda 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -4023,7 +4023,23 @@ pub fn join_channel( }) } -pub fn activate_any_workspace_window(cx: &mut AsyncAppContext) -> Option { +pub async fn get_any_active_workspace( + app_state: Arc, + mut cx: AsyncAppContext, +) -> anyhow::Result> { + // find an existing workspace to focus and show call controls + let active_window = activate_any_workspace_window(&mut cx); + if active_window.is_none() { + cx.update(|cx| Workspace::new_local(vec![], app_state.clone(), None, cx))? + .await?; + } + activate_any_workspace_window(&mut cx) + .context("could not open zed")? + .downcast::() + .context("could not open zed workspace window") +} + +fn activate_any_workspace_window(cx: &mut AsyncAppContext) -> Option { cx.update(|cx| { for window in cx.windows() { let is_workspace = window.downcast::().is_some(); diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index f4d9aa2510..93643648b8 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -9,6 +9,7 @@ use backtrace::Backtrace; use chrono::Utc; use cli::FORCE_CLI_MODE_ENV_VAR_NAME; use client::{Client, UserStore}; +use collab_ui::channel_view::ChannelView; use db::kvp::KEY_VALUE_STORE; use editor::Editor; use fs::RealFs; @@ -274,22 +275,36 @@ fn main() { cx.spawn(move |cx| handle_cli_connection(connection, app_state, cx)) .detach(); } - Ok(Some(OpenRequest::JoinChannel { channel_id: _ })) => { + Ok(Some(OpenRequest::JoinChannel { channel_id })) => { + triggered_authentication = true; + let app_state = app_state.clone(); + let client = client.clone(); + cx.spawn(|cx| async move { + // ignore errors here, we'll show a generic "not signed in" + let _ = authenticate(client, &cx).await; + cx.update(|cx| workspace::join_channel(channel_id, app_state, None, cx))? + .await?; + anyhow::Ok(()) + }) + .detach_and_log_err(cx); + } + Ok(Some(OpenRequest::OpenChannelNotes { channel_id })) => { triggered_authentication = true; let app_state = app_state.clone(); let client = client.clone(); cx.spawn(|mut cx| async move { // ignore errors here, we'll show a generic "not signed in" let _ = authenticate(client, &cx).await; - //todo!() - // cx.update(|cx| workspace::join_channel(channel_id, app_state, None, cx)) - // .await + let workspace_window = + workspace::get_any_active_workspace(app_state, cx.clone()).await?; + let _ = workspace_window + .update(&mut cx, |_, cx| { + ChannelView::open(channel_id, cx.view().clone(), cx) + })? + .await?; anyhow::Ok(()) }) - .detach_and_log_err(cx) - } - Ok(Some(OpenRequest::OpenChannelNotes { channel_id: _ })) => { - todo!() + .detach_and_log_err(cx); } Ok(None) | Err(_) => cx .spawn({ @@ -300,25 +315,53 @@ fn main() { } let app_state = app_state.clone(); - cx.spawn(|cx| async move { - while let Some(request) = open_rx.next().await { - match request { - OpenRequest::Paths { paths } => { - cx.update(|cx| open_paths_and_log_errs(&paths, &app_state, cx)) - .ok(); - } - OpenRequest::CliConnection { connection } => { - let app_state = app_state.clone(); - cx.spawn(move |cx| { - handle_cli_connection(connection, app_state.clone(), cx) - }) - .detach(); - } - OpenRequest::JoinChannel { channel_id: _ } => { - todo!() - } - OpenRequest::OpenChannelNotes { channel_id: _ } => { - todo!() + let closure_client = client.clone(); + cx.spawn(move |mut cx| { + let client = closure_client.clone(); + async move { + while let Some(request) = open_rx.next().await { + match request { + OpenRequest::Paths { paths } => { + cx.update(|cx| open_paths_and_log_errs(&paths, &app_state, cx)) + .ok(); + } + OpenRequest::CliConnection { connection } => { + let app_state = app_state.clone(); + cx.spawn(move |cx| { + handle_cli_connection(connection, app_state.clone(), cx) + }) + .detach(); + } + OpenRequest::JoinChannel { channel_id } => { + let app_state = app_state.clone(); + cx.update(|mut cx| { + cx.spawn(|cx| async move { + cx.update(|cx| { + workspace::join_channel(channel_id, app_state, None, cx) + })? + .await?; + anyhow::Ok(()) + }) + .detach_and_log_err(&mut cx); + }) + .log_err(); + } + OpenRequest::OpenChannelNotes { channel_id } => { + let app_state = app_state.clone(); + let open_notes_task = cx.spawn(|mut cx| async move { + let workspace_window = + workspace::get_any_active_workspace(app_state, cx.clone()) + .await?; + let _ = workspace_window + .update(&mut cx, |_, cx| { + ChannelView::open(channel_id, cx.view().clone(), cx) + })? + .await?; + anyhow::Ok(()) + }); + cx.update(|cx| open_notes_task.detach_and_log_err(cx)) + .log_err(); + } } } } From b0ee7b2fb99a331ab9c1d4a15b231f4064be5692 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 14:28:06 +0100 Subject: [PATCH 245/644] Fix clicking on "+" button not working when a tab was underneath We were mistakenly pushing an opaque layer without intersecting it with the content mask. Also, we were pushing two opaque layers for the same div unnecessarily. --- crates/gpui2/src/elements/div.rs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 7bda5966f5..e6fc58e872 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1092,19 +1092,19 @@ impl Interactivity { }); } + let interactive_bounds = InteractiveBounds { + bounds: bounds.intersect(&cx.content_mask().bounds), + stacking_order: cx.stacking_order().clone(), + }; + if self.block_mouse || style.background.as_ref().is_some_and(|fill| { fill.color().is_some_and(|color| !color.is_transparent()) }) { - cx.add_opaque_layer(bounds) + cx.add_opaque_layer(interactive_bounds.bounds); } - let interactive_bounds = InteractiveBounds { - bounds: bounds.intersect(&cx.content_mask().bounds), - stacking_order: cx.stacking_order().clone(), - }; - if !cx.has_active_drag() { if let Some(mouse_cursor) = style.mouse_cursor { let mouse_position = &cx.mouse_position(); @@ -1534,15 +1534,7 @@ impl Interactivity { cx.on_action(action_type, listener) } - cx.with_z_index(style.z_index.unwrap_or(0), |cx| { - if style.background.as_ref().is_some_and(|fill| { - fill.color().is_some_and(|color| !color.is_transparent()) - }) { - cx.add_opaque_layer(bounds) - } - - f(&style, scroll_offset.unwrap_or_default(), cx) - }) + f(&style, scroll_offset.unwrap_or_default(), cx) }, ); From 73b527ec8fae4a33fd9dd1439f492246bd71237d Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Thu, 21 Dec 2023 09:04:54 -0500 Subject: [PATCH 246/644] Store email address on modal close --- crates/feedback2/src/feedback_modal.rs | 40 +++++++++++++++----------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 165a0a332c..d22d5d908b 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -87,6 +87,8 @@ impl EventEmitter for FeedbackModal {} impl ModalView for FeedbackModal { fn on_before_dismiss(&mut self, cx: &mut ViewContext) -> bool { + self.update_email_in_store(cx); + if self.dismiss_modal { return true; } @@ -214,21 +216,6 @@ impl FeedbackModal { cx.spawn(|this, mut cx| async move { let answer = answer.await.ok(); if answer == Some(0) { - match email.clone() { - Some(email) => { - KEY_VALUE_STORE - .write_kvp(DATABASE_KEY_NAME.to_string(), email) - .await - .ok(); - } - None => { - KEY_VALUE_STORE - .delete_kvp(DATABASE_KEY_NAME.to_string()) - .await - .ok(); - } - }; - this.update(&mut cx, |this, cx| { this.submission_state = Some(SubmissionState::CannotSubmit { reason: CannotSubmitReason::AwaitingSubmission, @@ -351,6 +338,28 @@ impl FeedbackModal { } } + fn update_email_in_store(&self, cx: &mut ViewContext) { + let email = self.email_address_editor.read(cx).text_option(cx); + + cx.spawn(|_, _| async move { + match email { + Some(email) => { + KEY_VALUE_STORE + .write_kvp(DATABASE_KEY_NAME.to_string(), email) + .await + .ok(); + } + None => { + KEY_VALUE_STORE + .delete_kvp(DATABASE_KEY_NAME.to_string()) + .await + .ok(); + } + } + }) + .detach(); + } + fn valid_email_address(&self) -> bool { !self.in_invalid_state(InvalidStateFlags::EmailAddress) } @@ -508,7 +517,6 @@ impl Render for FeedbackModal { } } -// TODO: Maybe store email address whenever the modal is closed, versus just on submit, so users can remove it if they want without submitting // TODO: Testing of various button states, dismissal prompts, etc. // #[cfg(test)] From e2a447420078fa194f772dbc031d57e297cd3d40 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 15:22:49 +0100 Subject: [PATCH 247/644] Allow scrolling saved conversations --- crates/assistant2/src/assistant_panel.rs | 45 +++++++++++++++--------- crates/gpui2/src/element.rs | 11 ++++++ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 7b15619758..2c1493cdfe 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -29,12 +29,12 @@ use editor::{ use fs::Fs; use futures::StreamExt; use gpui::{ - div, point, relative, rems, uniform_list, Action, AnyElement, AppContext, AsyncWindowContext, - ClipboardItem, Context, Div, EventEmitter, FocusHandle, Focusable, FocusableView, FontStyle, - FontWeight, HighlightStyle, InteractiveElement, IntoElement, Model, ModelContext, - ParentElement, Pixels, PromptLevel, Render, SharedString, StatefulInteractiveElement, Styled, - Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext, - WeakModel, WeakView, WhiteSpace, WindowContext, + canvas, div, point, relative, rems, uniform_list, Action, AnyElement, AppContext, + AsyncWindowContext, AvailableSpace, ClipboardItem, Context, Div, EventEmitter, FocusHandle, + Focusable, FocusableView, FontStyle, FontWeight, HighlightStyle, InteractiveElement, + IntoElement, Model, ModelContext, ParentElement, Pixels, PromptLevel, Render, SharedString, + StatefulInteractiveElement, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, + View, ViewContext, VisualContext, WeakModel, WeakView, WhiteSpace, WindowContext, }; use language::{language_settings::SoftWrap, Buffer, LanguageRegistry, ToOffset as _}; use project::Project; @@ -1184,17 +1184,28 @@ impl Render for AssistantPanel { .child(if let Some(editor) = self.active_editor() { editor.clone().into_any_element() } else { - uniform_list( - cx.view().clone(), - "saved_conversations", - self.saved_conversations.len(), - |this, range, cx| { - range - .map(|ix| this.render_saved_conversation(ix, cx)) - .collect() - }, - ) - .track_scroll(self.saved_conversations_scroll_handle.clone()) + let view = cx.view().clone(); + let scroll_handle = self.saved_conversations_scroll_handle.clone(); + let conversation_count = self.saved_conversations.len(); + canvas(move |bounds, cx| { + uniform_list( + view, + "saved_conversations", + conversation_count, + |this, range, cx| { + range + .map(|ix| this.render_saved_conversation(ix, cx)) + .collect() + }, + ) + .track_scroll(scroll_handle) + .draw( + bounds.origin, + bounds.size, + cx, + ); + }) + .size_full() .into_any_element() }), ) diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 4201123a10..3901db73e0 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -23,6 +23,17 @@ pub trait IntoElement: Sized { self.into_element().into_any() } + fn draw(self, origin: Point, available_space: Size, cx: &mut WindowContext) + where + T: Clone + Default + Debug + Into, + { + let element = DrawableElement { + element: Some(self.into_element()), + phase: ElementDrawPhase::Start, + }; + DrawableElement::draw(element, origin, available_space.map(Into::into), cx); + } + fn draw_and_update_state( self, origin: Point, From 176a022b10ac6c9e4ca6237a6c44e73de4044a88 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 15:23:16 +0100 Subject: [PATCH 248/644] Correctly clamp scroll offset vertically --- crates/gpui2/src/elements/div.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index e6fc58e872..90af9e130e 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1472,7 +1472,7 @@ impl Interactivity { { let mut scroll_offset = scroll_offset.borrow_mut(); scroll_offset.x = scroll_offset.x.clamp(-scroll_max.width, px(0.)); - scroll_offset.y = scroll_offset.x.clamp(-scroll_max.height, px(0.)); + scroll_offset.y = scroll_offset.y.clamp(-scroll_max.height, px(0.)); } let interactive_bounds = interactive_bounds.clone(); From 5e4557ed1634807e9ae8199a80d059ac00c42f75 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 15:26:41 +0100 Subject: [PATCH 249/644] Fix warnings --- crates/assistant2/src/assistant_panel.rs | 6 +++--- crates/terminal_view2/src/terminal_element.rs | 18 ++++++++---------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 2c1493cdfe..85d3f6f740 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -30,9 +30,9 @@ use fs::Fs; use futures::StreamExt; use gpui::{ canvas, div, point, relative, rems, uniform_list, Action, AnyElement, AppContext, - AsyncWindowContext, AvailableSpace, ClipboardItem, Context, Div, EventEmitter, FocusHandle, - Focusable, FocusableView, FontStyle, FontWeight, HighlightStyle, InteractiveElement, - IntoElement, Model, ModelContext, ParentElement, Pixels, PromptLevel, Render, SharedString, + AsyncWindowContext, ClipboardItem, Context, Div, EventEmitter, FocusHandle, Focusable, + FocusableView, FontStyle, FontWeight, HighlightStyle, InteractiveElement, IntoElement, Model, + ModelContext, ParentElement, Pixels, PromptLevel, Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext, WeakModel, WeakView, WhiteSpace, WindowContext, }; diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index f30c1cf1bc..3b7b32dd6f 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -1,11 +1,11 @@ use editor::{Cursor, HighlightedRange, HighlightedRangeLine}; use gpui::{ - black, div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace, - BorrowWindow, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, - FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, - Interactivity, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, - Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, Size, StatefulInteractiveElement, - Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, + black, div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, BorrowWindow, + Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, FontStyle, + FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, Interactivity, + IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, Pixels, + PlatformInputHandler, Point, Rgba, ShapedLine, StatefulInteractiveElement, Styled, TextRun, + TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, }; use itertools::Itertools; use language::CursorShape; @@ -854,10 +854,8 @@ impl Element for TerminalElement { }); } - if let Some(mut element) = layout.hyperlink_tooltip.take() { - let width: AvailableSpace = bounds.size.width.into(); - let height: AvailableSpace = bounds.size.height.into(); - element.draw(origin, Size { width, height }, cx) + if let Some(element) = layout.hyperlink_tooltip.take() { + element.draw(origin, bounds.size, cx) } }); } From 01947ed730056b3bfa89c3c5e3850838417f7a06 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 15:32:05 +0100 Subject: [PATCH 250/644] Use existing AnyElement::draw --- crates/assistant2/src/assistant_panel.rs | 9 +++++---- crates/gpui2/src/element.rs | 11 ----------- crates/terminal_view2/src/terminal_element.rs | 16 ++++++++-------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 85d3f6f740..d50fdccd6f 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -30,9 +30,9 @@ use fs::Fs; use futures::StreamExt; use gpui::{ canvas, div, point, relative, rems, uniform_list, Action, AnyElement, AppContext, - AsyncWindowContext, ClipboardItem, Context, Div, EventEmitter, FocusHandle, Focusable, - FocusableView, FontStyle, FontWeight, HighlightStyle, InteractiveElement, IntoElement, Model, - ModelContext, ParentElement, Pixels, PromptLevel, Render, SharedString, + AsyncWindowContext, AvailableSpace, ClipboardItem, Context, Div, EventEmitter, FocusHandle, + Focusable, FocusableView, FontStyle, FontWeight, HighlightStyle, InteractiveElement, + IntoElement, Model, ModelContext, ParentElement, Pixels, PromptLevel, Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext, WeakModel, WeakView, WhiteSpace, WindowContext, }; @@ -1199,9 +1199,10 @@ impl Render for AssistantPanel { }, ) .track_scroll(scroll_handle) + .into_any_element() .draw( bounds.origin, - bounds.size, + bounds.size.map(AvailableSpace::Definite), cx, ); }) diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 3901db73e0..4201123a10 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -23,17 +23,6 @@ pub trait IntoElement: Sized { self.into_element().into_any() } - fn draw(self, origin: Point, available_space: Size, cx: &mut WindowContext) - where - T: Clone + Default + Debug + Into, - { - let element = DrawableElement { - element: Some(self.into_element()), - phase: ElementDrawPhase::Start, - }; - DrawableElement::draw(element, origin, available_space.map(Into::into), cx); - } - fn draw_and_update_state( self, origin: Point, diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index 3b7b32dd6f..ec1e1736c3 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -1,11 +1,11 @@ use editor::{Cursor, HighlightedRange, HighlightedRangeLine}; use gpui::{ - black, div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, BorrowWindow, - Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, FontStyle, - FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, Interactivity, - IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, Pixels, - PlatformInputHandler, Point, Rgba, ShapedLine, StatefulInteractiveElement, Styled, TextRun, - TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, + black, div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace, + BorrowWindow, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, + FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, + Interactivity, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, + Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, StatefulInteractiveElement, Styled, + TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, }; use itertools::Itertools; use language::CursorShape; @@ -854,8 +854,8 @@ impl Element for TerminalElement { }); } - if let Some(element) = layout.hyperlink_tooltip.take() { - element.draw(origin, bounds.size, cx) + if let Some(mut element) = layout.hyperlink_tooltip.take() { + element.draw(origin, bounds.size.map(AvailableSpace::Definite), cx) } }); } From 7a9c4057a7f2eb67e55439f74635f6c9d063674b Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 10:56:52 -0500 Subject: [PATCH 251/644] Increase inline assistant editor's line height (#3757) This PR increases the line height for the inline assistant editor. This fixes an issue where descenders were being clipped. Release Notes: - N/A --- crates/assistant2/src/assistant_panel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index d50fdccd6f..84576c5262 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -3066,7 +3066,7 @@ impl InlineAssistant { font_size: rems(0.875).into(), font_weight: FontWeight::NORMAL, font_style: FontStyle::Normal, - line_height: relative(1.).into(), + line_height: relative(1.3).into(), background_color: None, underline: None, white_space: WhiteSpace::Normal, From 67f76468f1299bbf79b7ef54646302cd75f0fc22 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 16:58:36 +0100 Subject: [PATCH 252/644] Replace `BspSplitter` with brute-force sorting of primitives --- Cargo.lock | 12 ---- crates/gpui2/Cargo.toml | 1 - crates/gpui2/src/scene.rs | 125 +++++++------------------------------- 3 files changed, 23 insertions(+), 115 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cddd744a9f..8b749a4f55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4060,7 +4060,6 @@ dependencies = [ "parking", "parking_lot 0.11.2", "pathfinder_geometry", - "plane-split", "png", "postage", "rand 0.8.5", @@ -6656,17 +6655,6 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" -[[package]] -name = "plane-split" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f7d82649829ecdef8e258790b0587acf0a8403f0ce963473d8e918acc1643" -dependencies = [ - "euclid", - "log", - "smallvec", -] - [[package]] name = "plist" version = "1.5.0" diff --git a/crates/gpui2/Cargo.toml b/crates/gpui2/Cargo.toml index afb5d3ea0c..bf0ac955a5 100644 --- a/crates/gpui2/Cargo.toml +++ b/crates/gpui2/Cargo.toml @@ -56,7 +56,6 @@ uuid = { version = "1.1.2", features = ["v4"] } waker-fn = "1.1.0" slotmap = "1.0.6" schemars.workspace = true -plane-split = "0.18.0" bitflags = "2.4.0" [dev-dependencies] diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index e6b601b62f..b26d73d7f6 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -3,8 +3,6 @@ use crate::{ ScaledPixels, StackingOrder, }; use collections::BTreeMap; -use etagere::euclid::{Point3D, Vector3D}; -use plane_split::{BspSplitter, Polygon as BspPolygon}; use std::{fmt::Debug, iter::Peekable, mem, slice}; // Exported to metal @@ -19,7 +17,6 @@ pub type DrawOrder = u32; pub(crate) struct SceneBuilder { last_order: Option<(StackingOrder, LayerId)>, layers_by_order: BTreeMap, - splitter: BspSplitter<(PrimitiveKind, usize)>, shadows: Vec, quads: Vec, paths: Vec>, @@ -34,7 +31,6 @@ impl Default for SceneBuilder { SceneBuilder { last_order: None, layers_by_order: BTreeMap::new(), - splitter: BspSplitter::new(), shadows: Vec::new(), quads: Vec::new(), paths: Vec::new(), @@ -49,102 +45,47 @@ impl Default for SceneBuilder { impl SceneBuilder { pub fn build(&mut self) -> Scene { // Map each layer id to a float between 0. and 1., with 1. closer to the viewer. - let mut layer_z_values = vec![0.; self.layers_by_order.len()]; + let mut orders = vec![0; self.layers_by_order.len()]; for (ix, layer_id) in self.layers_by_order.values().enumerate() { - layer_z_values[*layer_id as usize] = ix as f32 / self.layers_by_order.len() as f32; + orders[*layer_id as usize] = ix as u32; } self.layers_by_order.clear(); self.last_order = None; - // Add all primitives to the BSP splitter to determine draw order - self.splitter.reset(); - - for (ix, shadow) in self.shadows.iter().enumerate() { - let z = layer_z_values[shadow.order as LayerId as usize]; - self.splitter - .add(shadow.bounds.to_bsp_polygon(z, (PrimitiveKind::Shadow, ix))); + for shadow in &mut self.shadows { + shadow.order = orders[shadow.order as usize]; } + self.shadows.sort_by_key(|shadow| shadow.order); - for (ix, quad) in self.quads.iter().enumerate() { - let z = layer_z_values[quad.order as LayerId as usize]; - self.splitter - .add(quad.bounds.to_bsp_polygon(z, (PrimitiveKind::Quad, ix))); + for quad in &mut self.quads { + quad.order = orders[quad.order as usize]; } + self.quads.sort_by_key(|quad| quad.order); - for (ix, path) in self.paths.iter().enumerate() { - let z = layer_z_values[path.order as LayerId as usize]; - self.splitter - .add(path.bounds.to_bsp_polygon(z, (PrimitiveKind::Path, ix))); + for path in &mut self.paths { + path.order = orders[path.order as usize]; } + self.paths.sort_by_key(|path| path.order); - for (ix, underline) in self.underlines.iter().enumerate() { - let z = layer_z_values[underline.order as LayerId as usize]; - self.splitter.add( - underline - .bounds - .to_bsp_polygon(z, (PrimitiveKind::Underline, ix)), - ); + for underline in &mut self.underlines { + underline.order = orders[underline.order as usize]; } + self.underlines.sort_by_key(|underline| underline.order); - for (ix, monochrome_sprite) in self.monochrome_sprites.iter().enumerate() { - let z = layer_z_values[monochrome_sprite.order as LayerId as usize]; - self.splitter.add( - monochrome_sprite - .bounds - .to_bsp_polygon(z, (PrimitiveKind::MonochromeSprite, ix)), - ); + for monochrome_sprite in &mut self.monochrome_sprites { + monochrome_sprite.order = orders[monochrome_sprite.order as usize]; } + self.monochrome_sprites.sort_by_key(|sprite| sprite.order); - for (ix, polychrome_sprite) in self.polychrome_sprites.iter().enumerate() { - let z = layer_z_values[polychrome_sprite.order as LayerId as usize]; - self.splitter.add( - polychrome_sprite - .bounds - .to_bsp_polygon(z, (PrimitiveKind::PolychromeSprite, ix)), - ); + for polychrome_sprite in &mut self.polychrome_sprites { + polychrome_sprite.order = orders[polychrome_sprite.order as usize]; } + self.polychrome_sprites.sort_by_key(|sprite| sprite.order); - for (ix, surface) in self.surfaces.iter().enumerate() { - let z = layer_z_values[surface.order as LayerId as usize]; - self.splitter.add( - surface - .bounds - .to_bsp_polygon(z, (PrimitiveKind::Surface, ix)), - ); + for surface in &mut self.surfaces { + surface.order = orders[surface.order as usize]; } - - // Sort all polygons, then reassign the order field of each primitive to `draw_order` - // We need primitives to be repr(C), hence the weird reuse of the order field for two different types. - for (draw_order, polygon) in self - .splitter - .sort(Vector3D::new(0., 0., 1.)) - .iter() - .enumerate() - { - match polygon.anchor { - (PrimitiveKind::Shadow, ix) => self.shadows[ix].order = draw_order as DrawOrder, - (PrimitiveKind::Quad, ix) => self.quads[ix].order = draw_order as DrawOrder, - (PrimitiveKind::Path, ix) => self.paths[ix].order = draw_order as DrawOrder, - (PrimitiveKind::Underline, ix) => { - self.underlines[ix].order = draw_order as DrawOrder - } - (PrimitiveKind::MonochromeSprite, ix) => { - self.monochrome_sprites[ix].order = draw_order as DrawOrder - } - (PrimitiveKind::PolychromeSprite, ix) => { - self.polychrome_sprites[ix].order = draw_order as DrawOrder - } - (PrimitiveKind::Surface, ix) => self.surfaces[ix].order = draw_order as DrawOrder, - } - } - - self.shadows.sort_unstable(); - self.quads.sort_unstable(); - self.paths.sort_unstable(); - self.underlines.sort_unstable(); - self.monochrome_sprites.sort_unstable(); - self.polychrome_sprites.sort_unstable(); - self.surfaces.sort_unstable(); + self.surfaces.sort_by_key(|surface| surface.order); Scene { shadows: mem::take(&mut self.shadows), @@ -845,23 +786,3 @@ impl PathVertex { #[derive(Copy, Clone, Debug)] pub struct AtlasId(pub(crate) usize); - -impl Bounds { - fn to_bsp_polygon(&self, z: f32, anchor: A) -> BspPolygon { - let upper_left = self.origin; - let upper_right = self.upper_right(); - let lower_right = self.lower_right(); - let lower_left = self.lower_left(); - - BspPolygon::from_points( - [ - Point3D::new(upper_left.x.into(), upper_left.y.into(), z as f64), - Point3D::new(upper_right.x.into(), upper_right.y.into(), z as f64), - Point3D::new(lower_right.x.into(), lower_right.y.into(), z as f64), - Point3D::new(lower_left.x.into(), lower_left.y.into(), z as f64), - ], - anchor, - ) - .expect("Polygon should not be empty") - } -} From c03c0d50d5f26bacba46dab50f3977cc5db4f98d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 17:54:13 +0100 Subject: [PATCH 253/644] Use smaller quads to draw borders Co-Authored-By: Nathan Sobo --- crates/gpui2/src/geometry.rs | 21 +++++++++++++ crates/gpui2/src/style.rs | 60 +++++++++++++++++++++++++++++++++--- crates/gpui2/src/window.rs | 1 + 3 files changed, 78 insertions(+), 4 deletions(-) diff --git a/crates/gpui2/src/geometry.rs b/crates/gpui2/src/geometry.rs index f58435d7b9..6b4d9ae807 100644 --- a/crates/gpui2/src/geometry.rs +++ b/crates/gpui2/src/geometry.rs @@ -1590,6 +1590,15 @@ impl Edges { left: self.left.scale(factor), } } + + /// Returns the maximum value of any edge. + /// + /// # Returns + /// + /// The maximum `Pixels` value among all four edges. + pub fn max(&self) -> Pixels { + self.top.max(self.right).max(self.bottom).max(self.left) + } } impl Into> for f32 { @@ -1740,6 +1749,18 @@ impl Corners { bottom_left: self.bottom_left.scale(factor), } } + + /// Returns the maximum value of any corner. + /// + /// # Returns + /// + /// The maximum `Pixels` value among all four corners. + pub fn max(&self) -> Pixels { + self.top_left + .max(self.top_right) + .max(self.bottom_right) + .max(self.bottom_left) + } } impl Corners { diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 3e9593b0fd..de54da79b3 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -402,13 +402,65 @@ impl Style { if self.is_border_visible() { cx.with_z_index(3, |cx| { - cx.paint_quad(quad( + let corner_radii = self.corner_radii.to_pixels(bounds.size, rem_size); + let border_widths = self.border_widths.to_pixels(rem_size); + let max_border_width = border_widths.max(); + let max_corner_radius = corner_radii.max(); + + let top_bounds = Bounds::from_corners( + bounds.origin, + bounds.upper_right() + + point(Pixels::ZERO, max_border_width.max(max_corner_radius)), + ); + let bottom_bounds = Bounds::from_corners( + bounds.lower_left() + - point(Pixels::ZERO, max_border_width.max(max_corner_radius)), + bounds.lower_right(), + ); + let left_bounds = Bounds::from_corners( + top_bounds.lower_left(), + bottom_bounds.origin + point(max_border_width, Pixels::ZERO), + ); + let right_bounds = Bounds::from_corners( + top_bounds.lower_right() - point(max_border_width, Pixels::ZERO), + bottom_bounds.upper_right(), + ); + + let quad = quad( bounds, - self.corner_radii.to_pixels(bounds.size, rem_size), + corner_radii, Hsla::transparent_black(), - self.border_widths.to_pixels(rem_size), + border_widths, self.border_color.unwrap_or_default(), - )); + ); + + cx.with_content_mask(Some(ContentMask { bounds: top_bounds }), |cx| { + cx.paint_quad(quad.clone()); + }); + cx.with_content_mask( + Some(ContentMask { + bounds: right_bounds, + }), + |cx| { + cx.paint_quad(quad.clone()); + }, + ); + cx.with_content_mask( + Some(ContentMask { + bounds: bottom_bounds, + }), + |cx| { + cx.paint_quad(quad.clone()); + }, + ); + cx.with_content_mask( + Some(ContentMask { + bounds: left_bounds, + }), + |cx| { + cx.paint_quad(quad); + }, + ); }); } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index e57984fa0d..c20e2f7b94 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -3074,6 +3074,7 @@ impl From<(&'static str, u64)> for ElementId { } /// A rectangle, to be rendered on the screen by GPUI at the given position and size. +#[derive(Clone)] pub struct PaintQuad { bounds: Bounds, corner_radii: Corners, From 53a4b711dd79b7e7a5e79a13c509605962428e16 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 17:55:26 +0100 Subject: [PATCH 254/644] Delete stray comment --- crates/gpui2/src/scene.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index b26d73d7f6..cb62ce314f 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -44,7 +44,6 @@ impl Default for SceneBuilder { impl SceneBuilder { pub fn build(&mut self) -> Scene { - // Map each layer id to a float between 0. and 1., with 1. closer to the viewer. let mut orders = vec![0; self.layers_by_order.len()]; for (ix, layer_id) in self.layers_by_order.values().enumerate() { orders[*layer_id as usize] = ix as u32; From 824b68788fbd99b454ff18c7aeb53d50bb40f2e2 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 12:15:11 -0500 Subject: [PATCH 255/644] Improve chat panel styling (#3758) This PR improves the chat panel styling, especially with regards to the spacing. Release Notes: - N/A --- crates/collab_ui2/src/chat_panel.rs | 168 ++++++++++++++------------- crates/ui2/src/components/tab_bar.rs | 44 +++---- 2 files changed, 114 insertions(+), 98 deletions(-) diff --git a/crates/collab_ui2/src/chat_panel.rs b/crates/collab_ui2/src/chat_panel.rs index 27eb4ca17a..108d53b072 100644 --- a/crates/collab_ui2/src/chat_panel.rs +++ b/crates/collab_ui2/src/chat_panel.rs @@ -21,7 +21,7 @@ use settings::{Settings, SettingsStore}; use std::sync::Arc; use theme::ActiveTheme as _; use time::{OffsetDateTime, UtcOffset}; -use ui::{prelude::*, Avatar, Button, Icon, IconButton, Label, Tooltip}; +use ui::{prelude::*, Avatar, Button, Icon, IconButton, Label, TabBar, Tooltip}; use util::{ResultExt, TryFutureExt}; use workspace::{ dock::{DockPosition, Panel, PanelEvent}, @@ -97,7 +97,9 @@ impl ChatPanel { let message_list = ListState::new(0, gpui::ListAlignment::Bottom, px(1000.), move |ix, cx| { if let Some(view) = view.upgrade() { - view.update(cx, |view, cx| view.render_message(ix, cx)) + view.update(cx, |view, cx| { + view.render_message(ix, cx).into_any_element() + }) } else { div().into_any() } @@ -263,37 +265,41 @@ impl ChatPanel { .full() .on_action(cx.listener(Self::send)) .child( - h_stack() - .w_full() - .h_7() - .justify_between() - .z_index(1) - .bg(cx.theme().colors().background) - .child(Label::new( - self.active_chat - .as_ref() - .and_then(|c| Some(format!("#{}", c.0.read(cx).channel(cx)?.name))) - .unwrap_or_default(), - )) - .child( - h_stack() - .child( - IconButton::new("notes", Icon::File) - .on_click(cx.listener(Self::open_notes)) - .tooltip(|cx| Tooltip::text("Open notes", cx)), - ) - .child( - IconButton::new("call", Icon::AudioOn) - .on_click(cx.listener(Self::join_call)) - .tooltip(|cx| Tooltip::text("Join call", cx)), - ), - ), - ) - .child( - div() - .flex_grow() - .child(self.render_active_channel_messages(cx)), + h_stack().z_index(1).child( + TabBar::new("chat_header") + .child( + h_stack() + .w_full() + .h(rems(ui::Tab::HEIGHT_IN_REMS)) + .px_2() + .child(Label::new( + self.active_chat + .as_ref() + .and_then(|c| { + Some(format!("#{}", c.0.read(cx).channel(cx)?.name)) + }) + .unwrap_or_default(), + )), + ) + .end_child( + IconButton::new("notes", Icon::File) + .on_click(cx.listener(Self::open_notes)) + .tooltip(|cx| Tooltip::text("Open notes", cx)), + ) + .end_child( + IconButton::new("call", Icon::AudioOn) + .on_click(cx.listener(Self::join_call)) + .tooltip(|cx| Tooltip::text("Join call", cx)), + ), + ), ) + .child(div().flex_grow().px_2().py_1().map(|this| { + if self.active_chat.is_some() { + this.child(list(self.message_list.clone()).full()) + } else { + this + } + })) .child( div() .z_index(1) @@ -304,39 +310,42 @@ impl ChatPanel { .into_any() } - fn render_active_channel_messages(&self, _cx: &mut ViewContext) -> AnyElement { - if self.active_chat.is_some() { - list(self.message_list.clone()).full().into_any_element() - } else { - div().into_any_element() - } - } - - fn render_message(&mut self, ix: usize, cx: &mut ViewContext) -> AnyElement { + fn render_message(&mut self, ix: usize, cx: &mut ViewContext) -> impl IntoElement { let active_chat = &self.active_chat.as_ref().unwrap().0; - let (message, is_continuation, is_admin) = active_chat.update(cx, |active_chat, cx| { - let is_admin = self - .channel_store - .read(cx) - .is_channel_admin(active_chat.channel_id); + let (message, is_continuation_from_previous, is_continuation_to_next, is_admin) = + active_chat.update(cx, |active_chat, cx| { + let is_admin = self + .channel_store + .read(cx) + .is_channel_admin(active_chat.channel_id); - let last_message = active_chat.message(ix.saturating_sub(1)); - let this_message = active_chat.message(ix).clone(); - let is_continuation = last_message.id != this_message.id - && this_message.sender.id == last_message.sender.id; + let last_message = active_chat.message(ix.saturating_sub(1)); + let this_message = active_chat.message(ix).clone(); + let next_message = + active_chat.message(ix.saturating_add(1).min(active_chat.message_count() - 1)); - if let ChannelMessageId::Saved(id) = this_message.id { - if this_message - .mentions - .iter() - .any(|(_, user_id)| Some(*user_id) == self.client.user_id()) - { - active_chat.acknowledge_message(id); + let is_continuation_from_previous = last_message.id != this_message.id + && last_message.sender.id == this_message.sender.id; + let is_continuation_to_next = this_message.id != next_message.id + && this_message.sender.id == next_message.sender.id; + + if let ChannelMessageId::Saved(id) = this_message.id { + if this_message + .mentions + .iter() + .any(|(_, user_id)| Some(*user_id) == self.client.user_id()) + { + active_chat.acknowledge_message(id); + } } - } - (this_message, is_continuation, is_admin) - }); + ( + this_message, + is_continuation_from_previous, + is_continuation_to_next, + is_admin, + ) + }); let _is_pending = message.is_pending(); let text = self.markdown_data.entry(message.id).or_insert_with(|| { @@ -359,27 +368,31 @@ impl ChatPanel { ChannelMessageId::Pending(id) => ("pending-message", id).into(), }; - let mut result = v_stack() + v_stack() .w_full() .id(element_id) .relative() + .overflow_hidden() .group("") - .mb_1(); - - if !is_continuation { - result = result.child( - h_stack() - .child(Avatar::new(message.sender.avatar_uri.clone())) - .child(Label::new(message.sender.github_login.clone())) - .child(Label::new(format_timestamp( - message.timestamp, - now, - self.local_timezone, - ))), - ); - } - - result + .when(!is_continuation_from_previous, |this| { + this.child( + h_stack() + .gap_2() + .child(Avatar::new(message.sender.avatar_uri.clone())) + .child(Label::new(message.sender.github_login.clone())) + .child( + Label::new(format_timestamp( + message.timestamp, + now, + self.local_timezone, + )) + .color(Color::Muted), + ), + ) + }) + .when(!is_continuation_to_next, |this| + // HACK: This should really be a margin, but margins seem to get collapsed. + this.pb_2()) .child(text.element("body".into(), cx)) .child( div() @@ -396,7 +409,6 @@ impl ChatPanel { ) })), ) - .into_any() } fn render_markdown_with_mentions( diff --git a/crates/ui2/src/components/tab_bar.rs b/crates/ui2/src/components/tab_bar.rs index 7cff2f51bd..c0d9953196 100644 --- a/crates/ui2/src/components/tab_bar.rs +++ b/crates/ui2/src/components/tab_bar.rs @@ -102,16 +102,18 @@ impl RenderOnce for TabBar { .w_full() .h(rems(HEIGHT_IN_REMS)) .bg(cx.theme().colors().tab_bar_background) - .child( - h_stack() - .flex_none() - .gap_1() - .px_1() - .border_b() - .border_r() - .border_color(cx.theme().colors().border) - .children(self.start_children), - ) + .when(!self.start_children.is_empty(), |this| { + this.child( + h_stack() + .flex_none() + .gap_1() + .px_1() + .border_b() + .border_r() + .border_color(cx.theme().colors().border) + .children(self.start_children), + ) + }) .child( div() .relative() @@ -140,15 +142,17 @@ impl RenderOnce for TabBar { .children(self.children), ), ) - .child( - h_stack() - .flex_none() - .gap_1() - .px_1() - .border_b() - .border_l() - .border_color(cx.theme().colors().border) - .children(self.end_children), - ) + .when(!self.end_children.is_empty(), |this| { + this.child( + h_stack() + .flex_none() + .gap_1() + .px_1() + .border_b() + .border_l() + .border_color(cx.theme().colors().border) + .children(self.end_children), + ) + }) } } From 38a8aa2d047a3d69f702e4cd6a936788225bb91f Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Thu, 21 Dec 2023 12:15:27 -0500 Subject: [PATCH 256/644] Bump tree-sitter-nu rev id --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cddd744a9f..82cc00bf9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10510,7 +10510,7 @@ dependencies = [ [[package]] name = "tree-sitter-nu" version = "0.0.1" -source = "git+https://github.com/nushell/tree-sitter-nu?rev=786689b0562b9799ce53e824cb45a1a2a04dc673#786689b0562b9799ce53e824cb45a1a2a04dc673" +source = "git+https://github.com/nushell/tree-sitter-nu?rev=a0b80b2e21e5e39571252dc799e19eb89f1fc912#a0b80b2e21e5e39571252dc799e19eb89f1fc912" dependencies = [ "cc", "tree-sitter", diff --git a/Cargo.toml b/Cargo.toml index 42432a8a2a..e8299d6ce3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -207,7 +207,7 @@ tree-sitter-racket = { git = "https://github.com/zed-industries/tree-sitter-rack tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "f545a41f57502e1b5ddf2a6668896c1b0620f930"} tree-sitter-lua = "0.0.14" tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "66e3e9ce9180ae08fc57372061006ef83f0abde7" } -tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "786689b0562b9799ce53e824cb45a1a2a04dc673"} +tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "a0b80b2e21e5e39571252dc799e19eb89f1fc912"} tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "6608d9d60c386f19d80af7d8132322fa11199c42"} tree-sitter-uiua = {git = "https://github.com/shnarazk/tree-sitter-uiua", rev = "9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"} From 31e47f9b525f316fb862684df42e952eb6a91e84 Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 21 Dec 2023 12:56:30 -0500 Subject: [PATCH 257/644] Prevent panic dragging tab into terminal panel --- crates/workspace2/src/pane.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 4d20699528..7b9ac4ab13 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1754,6 +1754,10 @@ impl Pane { } fn handle_drag_move(&mut self, event: &DragMoveEvent, cx: &mut ViewContext) { + if !self.can_split { + return; + } + let edge_width = cx.rem_size() * 8; let cursor = event.event.position; let direction = if cursor.x < event.bounds.left() + edge_width { @@ -1767,9 +1771,9 @@ impl Pane { } else { None }; + if direction != self.drag_split_direction { self.drag_split_direction = direction; - cx.notify(); } } From 9efe5a30aab08aded81b45addea299123e77dc41 Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 21 Dec 2023 13:08:48 -0500 Subject: [PATCH 258/644] Fix pane drag target not appearing over terminal element --- crates/workspace2/src/pane.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 7b9ac4ab13..d0b47a2d1e 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1938,6 +1938,7 @@ impl Render for Pane { .child( // drag target div() + .z_index(1) .invisible() .absolute() .bg(theme::color_alpha( From 7cfea09019bf9ec6088b5964b3b4da1ee897d182 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 19:40:03 +0100 Subject: [PATCH 259/644] Revert "Optimize order rendering and border drawing" --- Cargo.lock | 12 ++++ crates/gpui2/Cargo.toml | 1 + crates/gpui2/src/geometry.rs | 21 ------ crates/gpui2/src/scene.rs | 128 ++++++++++++++++++++++++++++------- crates/gpui2/src/style.rs | 60 ++-------------- crates/gpui2/src/window.rs | 1 - 6 files changed, 121 insertions(+), 102 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e591ae58f..82cc00bf9e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4060,6 +4060,7 @@ dependencies = [ "parking", "parking_lot 0.11.2", "pathfinder_geometry", + "plane-split", "png", "postage", "rand 0.8.5", @@ -6655,6 +6656,17 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "plane-split" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f7d82649829ecdef8e258790b0587acf0a8403f0ce963473d8e918acc1643" +dependencies = [ + "euclid", + "log", + "smallvec", +] + [[package]] name = "plist" version = "1.5.0" diff --git a/crates/gpui2/Cargo.toml b/crates/gpui2/Cargo.toml index bf0ac955a5..afb5d3ea0c 100644 --- a/crates/gpui2/Cargo.toml +++ b/crates/gpui2/Cargo.toml @@ -56,6 +56,7 @@ uuid = { version = "1.1.2", features = ["v4"] } waker-fn = "1.1.0" slotmap = "1.0.6" schemars.workspace = true +plane-split = "0.18.0" bitflags = "2.4.0" [dev-dependencies] diff --git a/crates/gpui2/src/geometry.rs b/crates/gpui2/src/geometry.rs index 6b4d9ae807..f58435d7b9 100644 --- a/crates/gpui2/src/geometry.rs +++ b/crates/gpui2/src/geometry.rs @@ -1590,15 +1590,6 @@ impl Edges { left: self.left.scale(factor), } } - - /// Returns the maximum value of any edge. - /// - /// # Returns - /// - /// The maximum `Pixels` value among all four edges. - pub fn max(&self) -> Pixels { - self.top.max(self.right).max(self.bottom).max(self.left) - } } impl Into> for f32 { @@ -1749,18 +1740,6 @@ impl Corners { bottom_left: self.bottom_left.scale(factor), } } - - /// Returns the maximum value of any corner. - /// - /// # Returns - /// - /// The maximum `Pixels` value among all four corners. - pub fn max(&self) -> Pixels { - self.top_left - .max(self.top_right) - .max(self.bottom_right) - .max(self.bottom_left) - } } impl Corners { diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index cb62ce314f..e6b601b62f 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -3,6 +3,8 @@ use crate::{ ScaledPixels, StackingOrder, }; use collections::BTreeMap; +use etagere::euclid::{Point3D, Vector3D}; +use plane_split::{BspSplitter, Polygon as BspPolygon}; use std::{fmt::Debug, iter::Peekable, mem, slice}; // Exported to metal @@ -17,6 +19,7 @@ pub type DrawOrder = u32; pub(crate) struct SceneBuilder { last_order: Option<(StackingOrder, LayerId)>, layers_by_order: BTreeMap, + splitter: BspSplitter<(PrimitiveKind, usize)>, shadows: Vec, quads: Vec, paths: Vec>, @@ -31,6 +34,7 @@ impl Default for SceneBuilder { SceneBuilder { last_order: None, layers_by_order: BTreeMap::new(), + splitter: BspSplitter::new(), shadows: Vec::new(), quads: Vec::new(), paths: Vec::new(), @@ -44,47 +48,103 @@ impl Default for SceneBuilder { impl SceneBuilder { pub fn build(&mut self) -> Scene { - let mut orders = vec![0; self.layers_by_order.len()]; + // Map each layer id to a float between 0. and 1., with 1. closer to the viewer. + let mut layer_z_values = vec![0.; self.layers_by_order.len()]; for (ix, layer_id) in self.layers_by_order.values().enumerate() { - orders[*layer_id as usize] = ix as u32; + layer_z_values[*layer_id as usize] = ix as f32 / self.layers_by_order.len() as f32; } self.layers_by_order.clear(); self.last_order = None; - for shadow in &mut self.shadows { - shadow.order = orders[shadow.order as usize]; - } - self.shadows.sort_by_key(|shadow| shadow.order); + // Add all primitives to the BSP splitter to determine draw order + self.splitter.reset(); - for quad in &mut self.quads { - quad.order = orders[quad.order as usize]; + for (ix, shadow) in self.shadows.iter().enumerate() { + let z = layer_z_values[shadow.order as LayerId as usize]; + self.splitter + .add(shadow.bounds.to_bsp_polygon(z, (PrimitiveKind::Shadow, ix))); } - self.quads.sort_by_key(|quad| quad.order); - for path in &mut self.paths { - path.order = orders[path.order as usize]; + for (ix, quad) in self.quads.iter().enumerate() { + let z = layer_z_values[quad.order as LayerId as usize]; + self.splitter + .add(quad.bounds.to_bsp_polygon(z, (PrimitiveKind::Quad, ix))); } - self.paths.sort_by_key(|path| path.order); - for underline in &mut self.underlines { - underline.order = orders[underline.order as usize]; + for (ix, path) in self.paths.iter().enumerate() { + let z = layer_z_values[path.order as LayerId as usize]; + self.splitter + .add(path.bounds.to_bsp_polygon(z, (PrimitiveKind::Path, ix))); } - self.underlines.sort_by_key(|underline| underline.order); - for monochrome_sprite in &mut self.monochrome_sprites { - monochrome_sprite.order = orders[monochrome_sprite.order as usize]; + for (ix, underline) in self.underlines.iter().enumerate() { + let z = layer_z_values[underline.order as LayerId as usize]; + self.splitter.add( + underline + .bounds + .to_bsp_polygon(z, (PrimitiveKind::Underline, ix)), + ); } - self.monochrome_sprites.sort_by_key(|sprite| sprite.order); - for polychrome_sprite in &mut self.polychrome_sprites { - polychrome_sprite.order = orders[polychrome_sprite.order as usize]; + for (ix, monochrome_sprite) in self.monochrome_sprites.iter().enumerate() { + let z = layer_z_values[monochrome_sprite.order as LayerId as usize]; + self.splitter.add( + monochrome_sprite + .bounds + .to_bsp_polygon(z, (PrimitiveKind::MonochromeSprite, ix)), + ); } - self.polychrome_sprites.sort_by_key(|sprite| sprite.order); - for surface in &mut self.surfaces { - surface.order = orders[surface.order as usize]; + for (ix, polychrome_sprite) in self.polychrome_sprites.iter().enumerate() { + let z = layer_z_values[polychrome_sprite.order as LayerId as usize]; + self.splitter.add( + polychrome_sprite + .bounds + .to_bsp_polygon(z, (PrimitiveKind::PolychromeSprite, ix)), + ); } - self.surfaces.sort_by_key(|surface| surface.order); + + for (ix, surface) in self.surfaces.iter().enumerate() { + let z = layer_z_values[surface.order as LayerId as usize]; + self.splitter.add( + surface + .bounds + .to_bsp_polygon(z, (PrimitiveKind::Surface, ix)), + ); + } + + // Sort all polygons, then reassign the order field of each primitive to `draw_order` + // We need primitives to be repr(C), hence the weird reuse of the order field for two different types. + for (draw_order, polygon) in self + .splitter + .sort(Vector3D::new(0., 0., 1.)) + .iter() + .enumerate() + { + match polygon.anchor { + (PrimitiveKind::Shadow, ix) => self.shadows[ix].order = draw_order as DrawOrder, + (PrimitiveKind::Quad, ix) => self.quads[ix].order = draw_order as DrawOrder, + (PrimitiveKind::Path, ix) => self.paths[ix].order = draw_order as DrawOrder, + (PrimitiveKind::Underline, ix) => { + self.underlines[ix].order = draw_order as DrawOrder + } + (PrimitiveKind::MonochromeSprite, ix) => { + self.monochrome_sprites[ix].order = draw_order as DrawOrder + } + (PrimitiveKind::PolychromeSprite, ix) => { + self.polychrome_sprites[ix].order = draw_order as DrawOrder + } + (PrimitiveKind::Surface, ix) => self.surfaces[ix].order = draw_order as DrawOrder, + } + } + + self.shadows.sort_unstable(); + self.quads.sort_unstable(); + self.paths.sort_unstable(); + self.underlines.sort_unstable(); + self.monochrome_sprites.sort_unstable(); + self.polychrome_sprites.sort_unstable(); + self.surfaces.sort_unstable(); Scene { shadows: mem::take(&mut self.shadows), @@ -785,3 +845,23 @@ impl PathVertex { #[derive(Copy, Clone, Debug)] pub struct AtlasId(pub(crate) usize); + +impl Bounds { + fn to_bsp_polygon(&self, z: f32, anchor: A) -> BspPolygon { + let upper_left = self.origin; + let upper_right = self.upper_right(); + let lower_right = self.lower_right(); + let lower_left = self.lower_left(); + + BspPolygon::from_points( + [ + Point3D::new(upper_left.x.into(), upper_left.y.into(), z as f64), + Point3D::new(upper_right.x.into(), upper_right.y.into(), z as f64), + Point3D::new(lower_right.x.into(), lower_right.y.into(), z as f64), + Point3D::new(lower_left.x.into(), lower_left.y.into(), z as f64), + ], + anchor, + ) + .expect("Polygon should not be empty") + } +} diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index de54da79b3..3e9593b0fd 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -402,65 +402,13 @@ impl Style { if self.is_border_visible() { cx.with_z_index(3, |cx| { - let corner_radii = self.corner_radii.to_pixels(bounds.size, rem_size); - let border_widths = self.border_widths.to_pixels(rem_size); - let max_border_width = border_widths.max(); - let max_corner_radius = corner_radii.max(); - - let top_bounds = Bounds::from_corners( - bounds.origin, - bounds.upper_right() - + point(Pixels::ZERO, max_border_width.max(max_corner_radius)), - ); - let bottom_bounds = Bounds::from_corners( - bounds.lower_left() - - point(Pixels::ZERO, max_border_width.max(max_corner_radius)), - bounds.lower_right(), - ); - let left_bounds = Bounds::from_corners( - top_bounds.lower_left(), - bottom_bounds.origin + point(max_border_width, Pixels::ZERO), - ); - let right_bounds = Bounds::from_corners( - top_bounds.lower_right() - point(max_border_width, Pixels::ZERO), - bottom_bounds.upper_right(), - ); - - let quad = quad( + cx.paint_quad(quad( bounds, - corner_radii, + self.corner_radii.to_pixels(bounds.size, rem_size), Hsla::transparent_black(), - border_widths, + self.border_widths.to_pixels(rem_size), self.border_color.unwrap_or_default(), - ); - - cx.with_content_mask(Some(ContentMask { bounds: top_bounds }), |cx| { - cx.paint_quad(quad.clone()); - }); - cx.with_content_mask( - Some(ContentMask { - bounds: right_bounds, - }), - |cx| { - cx.paint_quad(quad.clone()); - }, - ); - cx.with_content_mask( - Some(ContentMask { - bounds: bottom_bounds, - }), - |cx| { - cx.paint_quad(quad.clone()); - }, - ); - cx.with_content_mask( - Some(ContentMask { - bounds: left_bounds, - }), - |cx| { - cx.paint_quad(quad); - }, - ); + )); }); } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index c20e2f7b94..e57984fa0d 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -3074,7 +3074,6 @@ impl From<(&'static str, u64)> for ElementId { } /// A rectangle, to be rendered on the screen by GPUI at the given position and size. -#[derive(Clone)] pub struct PaintQuad { bounds: Bounds, corner_radii: Corners, From dabc98690cdc1f47793ce3dfa680fd074139b6f8 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 15:48:37 -0500 Subject: [PATCH 260/644] Use small labels for title bar buttons (#3763) This PR adjusts the sizing of the labels in the buttons in the title bar to use the small label size. This should bring them more in line with how things looked in Zed1. Release Notes: - N/A --- crates/collab_ui2/src/collab_titlebar_item.rs | 2 ++ crates/ui2/src/components/button/button.rs | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 24e510ae8d..8e542e413e 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -334,6 +334,7 @@ impl CollabTitlebarItem { .trigger( Button::new("project_name_trigger", name) .style(ButtonStyle::Subtle) + .label_size(LabelSize::Small) .tooltip(move |cx| Tooltip::text("Recent Projects", cx)) .on_click(cx.listener(|this, _, cx| { this.toggle_project_menu(&ToggleProjectMenu, cx); @@ -368,6 +369,7 @@ impl CollabTitlebarItem { Button::new("project_branch_trigger", branch_name) .color(Color::Muted) .style(ButtonStyle::Subtle) + .label_size(LabelSize::Small) .tooltip(move |cx| { Tooltip::with_meta( "Recent Branches", diff --git a/crates/ui2/src/components/button/button.rs b/crates/ui2/src/components/button/button.rs index 014a2f5362..406cd1f420 100644 --- a/crates/ui2/src/components/button/button.rs +++ b/crates/ui2/src/components/button/button.rs @@ -12,6 +12,7 @@ pub struct Button { base: ButtonLike, label: SharedString, label_color: Option, + label_size: Option, selected_label: Option, icon: Option, icon_position: Option, @@ -26,6 +27,7 @@ impl Button { base: ButtonLike::new(id), label: label.into(), label_color: None, + label_size: None, selected_label: None, icon: None, icon_position: None, @@ -40,6 +42,11 @@ impl Button { self } + pub fn label_size(mut self, label_size: impl Into>) -> Self { + self.label_size = label_size.into(); + self + } + pub fn selected_label>(mut self, label: impl Into>) -> Self { self.selected_label = label.into().map(Into::into); self @@ -164,6 +171,7 @@ impl RenderOnce for Button { .child( Label::new(label) .color(label_color) + .size(self.label_size.unwrap_or_default()) .line_height_style(LineHeightStyle::UILabel), ) .when(!self.icon_position.is_some(), |this| { From a773a3cb9234ae7a4ce03c704dafe2e7c855cfa9 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 16:07:55 -0500 Subject: [PATCH 261/644] Increase horizontal padding for inset `ListItem`s --- crates/ui2/src/components/list/list_item.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index bdb5c2b854..797a6faba5 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -134,7 +134,7 @@ impl RenderOnce for ListItem { // When an item is inset draw the indent spacing outside of the item .when(self.inset, |this| { this.ml(self.indent_level as f32 * self.indent_step_size) - .px_1() + .px_2() }) .when(!self.inset, |this| { this From dc09dbc98c2d27886146cdb1ab328d6f55031441 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 16:17:04 -0500 Subject: [PATCH 262/644] Use a `ListItem` as the empty state for `Picker`s --- crates/picker2/src/picker2.rs | 27 ++++++--------------- crates/ui2/src/components/list/list_item.rs | 11 ++++++++- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 8a75996f48..3cc9f8a1ad 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -1,11 +1,11 @@ use editor::Editor; use gpui::{ - div, prelude::*, rems, uniform_list, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, + div, prelude::*, uniform_list, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Length, MouseButton, MouseDownEvent, Render, Task, UniformListScrollHandle, View, ViewContext, WindowContext, }; use std::{cmp, sync::Arc}; -use ui::{prelude::*, v_stack, Color, Divider, Label}; +use ui::{prelude::*, v_stack, Color, Divider, Label, ListItem}; use workspace::ModalView; pub struct Picker { @@ -229,21 +229,10 @@ impl Render for Picker { .px_3() .child(self.editor.clone()); - let empty_state = div().p_1().child( - h_stack() - // TODO: This number matches the height of the uniform list items. - // Align these two with a less magic number. - .h(rems(1.4375)) - .px_2() - .child(Label::new("No matches").color(Color::Muted)), - ); - div() .key_context("Picker") .size_full() - .when_some(self.width, |el, width| { - el.w(width) - }) + .when_some(self.width, |el, width| el.w(width)) .overflow_hidden() // This is a bit of a hack to remove the modal styling when we're rendering the `Picker` // as a part of a modal rather than the entire modal. @@ -257,9 +246,7 @@ impl Render for Picker { .on_action(cx.listener(Self::cancel)) .on_action(cx.listener(Self::confirm)) .on_action(cx.listener(Self::secondary_confirm)) - .child( - picker_editor - ) + .child(picker_editor) .child(Divider::horizontal()) .when(self.delegate.match_count() > 0, |el| { el.child( @@ -272,7 +259,6 @@ impl Render for Picker { self.delegate.match_count(), { let selected_index = self.delegate.selected_index(); - move |picker, visible_range, cx| { visible_range .map(|ix| { @@ -305,7 +291,10 @@ impl Render for Picker { }) .when(self.delegate.match_count() == 0, |el| { el.child( - empty_state + ListItem::new("empty_state") + .inset(true) + .disabled(true) + .child(Label::new("No matches").color(Color::Muted)), ) }) } diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index 797a6faba5..ca161b12f4 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -8,6 +8,7 @@ use crate::{prelude::*, Disclosure}; #[derive(IntoElement)] pub struct ListItem { id: ElementId, + disabled: bool, selected: bool, indent_level: usize, indent_step_size: Pixels, @@ -32,6 +33,7 @@ impl ListItem { pub fn new(id: impl Into) -> Self { Self { id: id.into(), + disabled: false, selected: false, indent_level: 0, indent_step_size: px(12.), @@ -110,6 +112,13 @@ impl ListItem { } } +impl Disableable for ListItem { + fn disabled(mut self, disabled: bool) -> Self { + self.disabled = disabled; + self + } +} + impl Selectable for ListItem { fn selected(mut self, selected: bool) -> Self { self.selected = selected; @@ -157,7 +166,7 @@ impl RenderOnce for ListItem { .gap_1() .px_2() .group("list_item") - .when(self.inset, |this| { + .when(self.inset && !self.disabled, |this| { this // TODO: Add focus state // .when(self.state == InteractionState::Focused, |this| { From 71a222abcb597e7b306aecb771e250f7587b5406 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 16:33:41 -0500 Subject: [PATCH 263/644] Use sparse spacing for `ListItem`s in `Picker`s --- .../src/collab_panel/channel_modal.rs | 3 +- .../src/collab_panel/contact_finder.rs | 3 +- .../command_palette2/src/command_palette.rs | 34 +++++++++++-------- crates/file_finder2/src/file_finder.rs | 21 +++++++----- .../src/language_selector.rs | 3 +- crates/outline2/src/outline.rs | 18 ++++++---- crates/picker2/src/picker2.rs | 3 +- .../project_symbols2/src/project_symbols.rs | 28 ++++++++------- .../recent_projects2/src/recent_projects.rs | 20 ++++++----- crates/storybook2/src/stories/picker.rs | 3 +- crates/theme_selector2/src/theme_selector.rs | 3 +- crates/ui2/src/components/list/list_item.rs | 18 ++++++++++ crates/vcs_menu2/src/lib.rs | 9 +++-- crates/welcome2/src/base_keymap_picker.rs | 5 +-- 14 files changed, 110 insertions(+), 61 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel/channel_modal.rs b/crates/collab_ui2/src/collab_panel/channel_modal.rs index f844c609ca..f373dbad1f 100644 --- a/crates/collab_ui2/src/collab_panel/channel_modal.rs +++ b/crates/collab_ui2/src/collab_panel/channel_modal.rs @@ -11,7 +11,7 @@ use gpui::{ }; use picker::{Picker, PickerDelegate}; use std::sync::Arc; -use ui::{prelude::*, Avatar, Checkbox, ContextMenu, ListItem}; +use ui::{prelude::*, Avatar, Checkbox, ContextMenu, ListItem, ListItemSpacing}; use util::TryFutureExt; use workspace::ModalView; @@ -366,6 +366,7 @@ impl PickerDelegate for ChannelModalDelegate { Some( ListItem::new(ix) .inset(true) + .spacing(ListItemSpacing::Sparse) .selected(selected) .start_slot(Avatar::new(user.avatar_uri.clone())) .child(Label::new(user.github_login.clone())) diff --git a/crates/collab_ui2/src/collab_panel/contact_finder.rs b/crates/collab_ui2/src/collab_panel/contact_finder.rs index 31d836279b..a38d22c096 100644 --- a/crates/collab_ui2/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui2/src/collab_panel/contact_finder.rs @@ -6,7 +6,7 @@ use gpui::{ use picker::{Picker, PickerDelegate}; use std::sync::Arc; use theme::ActiveTheme as _; -use ui::{prelude::*, Avatar, ListItem}; +use ui::{prelude::*, Avatar, ListItem, ListItemSpacing}; use util::{ResultExt as _, TryFutureExt}; use workspace::ModalView; @@ -153,6 +153,7 @@ impl PickerDelegate for ContactFinderDelegate { Some( ListItem::new(ix) .inset(true) + .spacing(ListItemSpacing::Sparse) .selected(selected) .start_slot(Avatar::new(user.avatar_uri.clone())) .child(Label::new(user.github_login.clone())) diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 04efe1df53..05891bc0f1 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -11,7 +11,7 @@ use gpui::{ }; use picker::{Picker, PickerDelegate}; -use ui::{h_stack, prelude::*, v_stack, HighlightedLabel, KeyBinding, ListItem}; +use ui::{h_stack, prelude::*, v_stack, HighlightedLabel, KeyBinding, ListItem, ListItemSpacing}; use util::{ channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL}, ResultExt, @@ -308,20 +308,24 @@ impl PickerDelegate for CommandPaletteDelegate { let r#match = self.matches.get(ix)?; let command = self.commands.get(r#match.candidate_id)?; Some( - ListItem::new(ix).inset(true).selected(selected).child( - h_stack() - .w_full() - .justify_between() - .child(HighlightedLabel::new( - command.name.clone(), - r#match.positions.clone(), - )) - .children(KeyBinding::for_action_in( - &*command.action, - &self.previous_focus_handle, - cx, - )), - ), + ListItem::new(ix) + .inset(true) + .spacing(ListItemSpacing::Sparse) + .selected(selected) + .child( + h_stack() + .w_full() + .justify_between() + .child(HighlightedLabel::new( + command.name.clone(), + r#match.positions.clone(), + )) + .children(KeyBinding::for_action_in( + &*command.action, + &self.previous_focus_handle, + cx, + )), + ), ) } } diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 8faba99cb2..369128a753 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -15,7 +15,7 @@ use std::{ }, }; use text::Point; -use ui::{prelude::*, HighlightedLabel, ListItem}; +use ui::{prelude::*, HighlightedLabel, ListItem, ListItemSpacing}; use util::{paths::PathLikeWithPosition, post_inc, ResultExt}; use workspace::{ModalView, Workspace}; @@ -714,13 +714,18 @@ impl PickerDelegate for FileFinderDelegate { self.labels_for_match(path_match, cx, ix); Some( - ListItem::new(ix).inset(true).selected(selected).child( - v_stack() - .child(HighlightedLabel::new(file_name, file_name_positions)) - .child( - HighlightedLabel::new(full_path, full_path_positions).color(Color::Muted), - ), - ), + ListItem::new(ix) + .spacing(ListItemSpacing::Sparse) + .inset(true) + .selected(selected) + .child( + v_stack() + .child(HighlightedLabel::new(file_name, file_name_positions)) + .child( + HighlightedLabel::new(full_path, full_path_positions) + .color(Color::Muted), + ), + ), ) } } diff --git a/crates/language_selector2/src/language_selector.rs b/crates/language_selector2/src/language_selector.rs index 8b28eab11d..3da8649c6e 100644 --- a/crates/language_selector2/src/language_selector.rs +++ b/crates/language_selector2/src/language_selector.rs @@ -12,7 +12,7 @@ use language::{Buffer, LanguageRegistry}; use picker::{Picker, PickerDelegate}; use project::Project; use std::sync::Arc; -use ui::{prelude::*, HighlightedLabel, ListItem}; +use ui::{prelude::*, HighlightedLabel, ListItem, ListItemSpacing}; use util::ResultExt; use workspace::{ModalView, Workspace}; @@ -226,6 +226,7 @@ impl PickerDelegate for LanguageSelectorDelegate { Some( ListItem::new(ix) .inset(true) + .spacing(ListItemSpacing::Sparse) .selected(selected) .child(HighlightedLabel::new(label, mat.positions.clone())), ) diff --git a/crates/outline2/src/outline.rs b/crates/outline2/src/outline.rs index f3d1f327da..ba67f33b25 100644 --- a/crates/outline2/src/outline.rs +++ b/crates/outline2/src/outline.rs @@ -18,7 +18,7 @@ use std::{ }; use theme::{color_alpha, ActiveTheme, ThemeSettings}; -use ui::{prelude::*, ListItem}; +use ui::{prelude::*, ListItem, ListItemSpacing}; use util::ResultExt; use workspace::ModalView; @@ -296,12 +296,16 @@ impl PickerDelegate for OutlineViewDelegate { StyledText::new(outline_item.text.clone()).with_highlights(&text_style, highlights); Some( - ListItem::new(ix).inset(true).selected(selected).child( - div() - .text_ui() - .pl(rems(outline_item.depth as f32)) - .child(styled_text), - ), + ListItem::new(ix) + .inset(true) + .spacing(ListItemSpacing::Sparse) + .selected(selected) + .child( + div() + .text_ui() + .pl(rems(outline_item.depth as f32)) + .child(styled_text), + ), ) } } diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 3cc9f8a1ad..d37638293c 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -5,7 +5,7 @@ use gpui::{ View, ViewContext, WindowContext, }; use std::{cmp, sync::Arc}; -use ui::{prelude::*, v_stack, Color, Divider, Label, ListItem}; +use ui::{prelude::*, v_stack, Color, Divider, Label, ListItem, ListItemSpacing}; use workspace::ModalView; pub struct Picker { @@ -293,6 +293,7 @@ impl Render for Picker { el.child( ListItem::new("empty_state") .inset(true) + .spacing(ListItemSpacing::Sparse) .disabled(true) .child(Label::new("No matches").color(Color::Muted)), ) diff --git a/crates/project_symbols2/src/project_symbols.rs b/crates/project_symbols2/src/project_symbols.rs index da67fc888f..d9bdd41b6e 100644 --- a/crates/project_symbols2/src/project_symbols.rs +++ b/crates/project_symbols2/src/project_symbols.rs @@ -11,7 +11,7 @@ use std::{borrow::Cow, cmp::Reverse, sync::Arc}; use theme::ActiveTheme; use util::ResultExt; use workspace::{ - ui::{v_stack, Color, Label, LabelCommon, LabelLike, ListItem, Selectable}, + ui::{v_stack, Color, Label, LabelCommon, LabelLike, ListItem, ListItemSpacing, Selectable}, Workspace, }; @@ -237,17 +237,21 @@ impl PickerDelegate for ProjectSymbolsDelegate { ); Some( - ListItem::new(ix).inset(true).selected(selected).child( - // todo!() combine_syntax_and_fuzzy_match_highlights() - v_stack() - .child( - LabelLike::new().child( - StyledText::new(label) - .with_highlights(&cx.text_style().clone(), highlights), - ), - ) - .child(Label::new(path).color(Color::Muted)), - ), + ListItem::new(ix) + .inset(true) + .spacing(ListItemSpacing::Sparse) + .selected(selected) + .child( + // todo!() combine_syntax_and_fuzzy_match_highlights() + v_stack() + .child( + LabelLike::new().child( + StyledText::new(label) + .with_highlights(&cx.text_style().clone(), highlights), + ), + ) + .child(Label::new(path).color(Color::Muted)), + ), ) } } diff --git a/crates/recent_projects2/src/recent_projects.rs b/crates/recent_projects2/src/recent_projects.rs index 13790a5b23..1a38a5c200 100644 --- a/crates/recent_projects2/src/recent_projects.rs +++ b/crates/recent_projects2/src/recent_projects.rs @@ -10,7 +10,7 @@ use highlighted_workspace_location::HighlightedWorkspaceLocation; use ordered_float::OrderedFloat; use picker::{Picker, PickerDelegate}; use std::sync::Arc; -use ui::{prelude::*, ListItem}; +use ui::{prelude::*, ListItem, ListItemSpacing}; use util::paths::PathExt; use workspace::{ notifications::simple_message_notification::MessageNotification, ModalView, Workspace, @@ -251,13 +251,17 @@ impl PickerDelegate for RecentProjectsDelegate { ); Some( - ListItem::new(ix).inset(true).selected(selected).child( - v_stack() - .child(highlighted_location.names) - .when(self.render_paths, |this| { - this.children(highlighted_location.paths) - }), - ), + ListItem::new(ix) + .inset(true) + .spacing(ListItemSpacing::Sparse) + .selected(selected) + .child( + v_stack() + .child(highlighted_location.names) + .when(self.render_paths, |this| { + this.children(highlighted_location.paths) + }), + ), ) } } diff --git a/crates/storybook2/src/stories/picker.rs b/crates/storybook2/src/stories/picker.rs index 75aa7aed05..edaaaa70bd 100644 --- a/crates/storybook2/src/stories/picker.rs +++ b/crates/storybook2/src/stories/picker.rs @@ -4,7 +4,7 @@ use gpui::{ }; use picker::{Picker, PickerDelegate}; use std::sync::Arc; -use ui::prelude::*; +use ui::{prelude::*, ListItemSpacing}; use ui::{Label, ListItem}; pub struct PickerStory { @@ -62,6 +62,7 @@ impl PickerDelegate for Delegate { Some( ListItem::new(ix) .inset(true) + .spacing(ListItemSpacing::Sparse) .selected(selected) .child(Label::new(candidate)), ) diff --git a/crates/theme_selector2/src/theme_selector.rs b/crates/theme_selector2/src/theme_selector.rs index e0cdc45555..ae067ce87c 100644 --- a/crates/theme_selector2/src/theme_selector.rs +++ b/crates/theme_selector2/src/theme_selector.rs @@ -9,7 +9,7 @@ use picker::{Picker, PickerDelegate}; use settings::{update_settings_file, SettingsStore}; use std::sync::Arc; use theme::{Theme, ThemeMeta, ThemeRegistry, ThemeSettings}; -use ui::{prelude::*, v_stack, ListItem}; +use ui::{prelude::*, v_stack, ListItem, ListItemSpacing}; use util::ResultExt; use workspace::{ui::HighlightedLabel, ModalView, Workspace}; @@ -276,6 +276,7 @@ impl PickerDelegate for ThemeSelectorDelegate { Some( ListItem::new(ix) .inset(true) + .spacing(ListItemSpacing::Sparse) .selected(selected) .child(HighlightedLabel::new( theme_match.string.clone(), diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index ca161b12f4..6295e2940d 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -5,11 +5,19 @@ use smallvec::SmallVec; use crate::{prelude::*, Disclosure}; +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)] +pub enum ListItemSpacing { + #[default] + Dense, + Sparse, +} + #[derive(IntoElement)] pub struct ListItem { id: ElementId, disabled: bool, selected: bool, + spacing: ListItemSpacing, indent_level: usize, indent_step_size: Pixels, /// A slot for content that appears before the children, like an icon or avatar. @@ -35,6 +43,7 @@ impl ListItem { id: id.into(), disabled: false, selected: false, + spacing: ListItemSpacing::Dense, indent_level: 0, indent_step_size: px(12.), start_slot: None, @@ -50,6 +59,11 @@ impl ListItem { } } + pub fn spacing(mut self, spacing: ListItemSpacing) -> Self { + self.spacing = spacing; + self + } + pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self { self.on_click = Some(Box::new(handler)); self @@ -165,6 +179,10 @@ impl RenderOnce for ListItem { .relative() .gap_1() .px_2() + .map(|this| match self.spacing { + ListItemSpacing::Dense => this, + ListItemSpacing::Sparse => this.py_1(), + }) .group("list_item") .when(self.inset && !self.disabled, |this| { this diff --git a/crates/vcs_menu2/src/lib.rs b/crates/vcs_menu2/src/lib.rs index 1483a2e81e..cece283d4e 100644 --- a/crates/vcs_menu2/src/lib.rs +++ b/crates/vcs_menu2/src/lib.rs @@ -8,7 +8,7 @@ use gpui::{ }; use picker::{Picker, PickerDelegate}; use std::sync::Arc; -use ui::{v_stack, HighlightedLabel, ListItem, Selectable}; +use ui::{v_stack, HighlightedLabel, ListItem, ListItemSpacing, Selectable}; use util::ResultExt; use workspace::{ModalView, Toast, Workspace}; @@ -134,6 +134,7 @@ impl BranchListDelegate { impl PickerDelegate for BranchListDelegate { type ListItem = ListItem; + fn placeholder_text(&self) -> Arc { "Select branch...".into() } @@ -281,8 +282,10 @@ impl PickerDelegate for BranchListDelegate { .collect(); Some( ListItem::new(SharedString::from(format!("vcs-menu-{ix}"))) - .start_slot(HighlightedLabel::new(shortened_branch_name, highlights)) - .selected(selected), + .inset(true) + .spacing(ListItemSpacing::Sparse) + .selected(selected) + .start_slot(HighlightedLabel::new(shortened_branch_name, highlights)), ) } // fn render_header( diff --git a/crates/welcome2/src/base_keymap_picker.rs b/crates/welcome2/src/base_keymap_picker.rs index 7f799c6339..9655d7e135 100644 --- a/crates/welcome2/src/base_keymap_picker.rs +++ b/crates/welcome2/src/base_keymap_picker.rs @@ -8,7 +8,7 @@ use picker::{Picker, PickerDelegate}; use project::Fs; use settings::{update_settings_file, Settings}; use std::sync::Arc; -use ui::{prelude::*, ListItem}; +use ui::{prelude::*, ListItem, ListItemSpacing}; use util::ResultExt; use workspace::{ui::HighlightedLabel, ModalView, Workspace}; @@ -198,8 +198,9 @@ impl PickerDelegate for BaseKeymapSelectorDelegate { Some( ListItem::new(ix) - .selected(selected) .inset(true) + .spacing(ListItemSpacing::Sparse) + .selected(selected) .child(HighlightedLabel::new( keymap_match.string.clone(), keymap_match.positions.clone(), From e2c36633ea2898ea3b5856194329c98edaf7e1fc Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 17:03:57 -0500 Subject: [PATCH 264/644] Align `Picker` editor with entries (#3765) This PR re-aligns the `Picker` editor with the entries after the changes in #3764. Release Notes: - N/A --- crates/picker2/src/picker2.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index d37638293c..42b1d7433f 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -226,7 +226,7 @@ impl Render for Picker { .overflow_hidden() .flex_none() .h_9() - .px_3() + .px_4() .child(self.editor.clone()); div() From 3d1e52297eef39d164e4d838088095179070a8b4 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 17:42:54 -0500 Subject: [PATCH 265/644] Scale down status bar items (#3766) This PR scales down the sizes of items in the status bar. This brings us more in line with Zed1. Release Notes: - N/A --- .../src/activity_indicator.rs | 4 +- crates/copilot_button2/src/copilot_button.rs | 4 +- crates/diagnostics2/src/items.rs | 45 ++++++++++++++----- crates/editor2/src/items.rs | 2 +- .../feedback2/src/deploy_feedback_button.rs | 1 + .../src/active_buffer_language.rs | 3 +- crates/vim2/src/mode_indicator.rs | 6 +-- crates/workspace2/src/dock.rs | 1 + 8 files changed, 48 insertions(+), 18 deletions(-) diff --git a/crates/activity_indicator2/src/activity_indicator.rs b/crates/activity_indicator2/src/activity_indicator.rs index f83517e061..2b7846cd8d 100644 --- a/crates/activity_indicator2/src/activity_indicator.rs +++ b/crates/activity_indicator2/src/activity_indicator.rs @@ -10,7 +10,7 @@ use language::{LanguageRegistry, LanguageServerBinaryStatus}; use project::{LanguageServerProgress, Project}; use smallvec::SmallVec; use std::{cmp::Reverse, fmt::Write, sync::Arc}; -use ui::{h_stack, Label}; +use ui::prelude::*; use util::ResultExt; use workspace::{item::ItemHandle, StatusItemView, Workspace}; @@ -324,7 +324,7 @@ impl Render for ActivityIndicator { result .children(content.icon.map(|icon| svg().path(icon))) - .child(Label::new(SharedString::from(content.message))) + .child(Label::new(SharedString::from(content.message)).size(LabelSize::Small)) } } diff --git a/crates/copilot_button2/src/copilot_button.rs b/crates/copilot_button2/src/copilot_button.rs index dc6f808533..705bdc1bec 100644 --- a/crates/copilot_button2/src/copilot_button.rs +++ b/crates/copilot_button2/src/copilot_button.rs @@ -18,7 +18,8 @@ use workspace::{ create_and_open_local_file, item::ItemHandle, ui::{ - popover_menu, ButtonCommon, Clickable, ContextMenu, Icon, IconButton, PopoverMenu, Tooltip, + popover_menu, ButtonCommon, Clickable, ContextMenu, Icon, IconButton, IconSize, + PopoverMenu, Tooltip, }, StatusItemView, Toast, Workspace, }; @@ -69,6 +70,7 @@ impl Render for CopilotButton { if let Status::Error(e) = status { return div().child( IconButton::new("copilot-error", icon) + .icon_size(IconSize::Small) .on_click(cx.listener(move |this, _, cx| { if let Some(workspace) = cx.window_handle().downcast::() { workspace.update(cx, |workspace, cx| { diff --git a/crates/diagnostics2/src/items.rs b/crates/diagnostics2/src/items.rs index 14ebe0c516..cc598ba90c 100644 --- a/crates/diagnostics2/src/items.rs +++ b/crates/diagnostics2/src/items.rs @@ -25,29 +25,54 @@ impl Render for DiagnosticIndicator { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) { - (0, 0) => h_stack().child(IconElement::new(Icon::Check).color(Color::Success)), + (0, 0) => h_stack().child( + IconElement::new(Icon::Check) + .size(IconSize::Small) + .color(Color::Success), + ), (0, warning_count) => h_stack() .gap_1() - .child(IconElement::new(Icon::ExclamationTriangle).color(Color::Warning)) - .child(Label::new(warning_count.to_string())), + .child( + IconElement::new(Icon::ExclamationTriangle) + .size(IconSize::Small) + .color(Color::Warning), + ) + .child(Label::new(warning_count.to_string()).size(LabelSize::Small)), (error_count, 0) => h_stack() .gap_1() - .child(IconElement::new(Icon::XCircle).color(Color::Error)) - .child(Label::new(error_count.to_string())), + .child( + IconElement::new(Icon::XCircle) + .size(IconSize::Small) + .color(Color::Error), + ) + .child(Label::new(error_count.to_string()).size(LabelSize::Small)), (error_count, warning_count) => h_stack() .gap_1() - .child(IconElement::new(Icon::XCircle).color(Color::Error)) - .child(Label::new(error_count.to_string())) - .child(IconElement::new(Icon::ExclamationTriangle).color(Color::Warning)) - .child(Label::new(warning_count.to_string())), + .child( + IconElement::new(Icon::XCircle) + .size(IconSize::Small) + .color(Color::Error), + ) + .child(Label::new(error_count.to_string()).size(LabelSize::Small)) + .child( + IconElement::new(Icon::ExclamationTriangle) + .size(IconSize::Small) + .color(Color::Warning), + ) + .child(Label::new(warning_count.to_string()).size(LabelSize::Small)), }; let status = if !self.in_progress_checks.is_empty() { - Some(Label::new("Checking…").into_any_element()) + Some( + Label::new("Checking…") + .size(LabelSize::Small) + .into_any_element(), + ) } else if let Some(diagnostic) = &self.current_diagnostic { let message = diagnostic.message.split('\n').next().unwrap().to_string(); Some( Button::new("diagnostic_message", message) + .label_size(LabelSize::Small) .tooltip(|cx| { Tooltip::for_action("Next Diagnostic", &editor::GoToDiagnostic, cx) }) diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index fc8f7dfbbf..e0374d3d73 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -1200,7 +1200,7 @@ impl Render for CursorPosition { write!(text, " ({} selected)", self.selected_count).unwrap(); } - el.child(Label::new(text)) + el.child(Label::new(text).size(LabelSize::Small)) }) } } diff --git a/crates/feedback2/src/deploy_feedback_button.rs b/crates/feedback2/src/deploy_feedback_button.rs index 3b28c64dc3..926a5d791e 100644 --- a/crates/feedback2/src/deploy_feedback_button.rs +++ b/crates/feedback2/src/deploy_feedback_button.rs @@ -31,6 +31,7 @@ impl Render for DeployFeedbackButton { .is_some(); IconButton::new("give-feedback", Icon::Envelope) .style(ui::ButtonStyle::Subtle) + .icon_size(IconSize::Small) .selected(is_open) .tooltip(|cx| Tooltip::text("Share Feedback", cx)) .on_click(|_, cx| { diff --git a/crates/language_selector2/src/active_buffer_language.rs b/crates/language_selector2/src/active_buffer_language.rs index 4034cb0429..48224198a2 100644 --- a/crates/language_selector2/src/active_buffer_language.rs +++ b/crates/language_selector2/src/active_buffer_language.rs @@ -3,7 +3,7 @@ use gpui::{ div, Div, IntoElement, ParentElement, Render, Subscription, View, ViewContext, WeakView, }; use std::sync::Arc; -use ui::{Button, ButtonCommon, Clickable, Tooltip}; +use ui::{Button, ButtonCommon, Clickable, LabelSize, Tooltip}; use workspace::{item::ItemHandle, StatusItemView, Workspace}; use crate::LanguageSelector; @@ -50,6 +50,7 @@ impl Render for ActiveBufferLanguage { el.child( Button::new("change-language", active_language_text) + .label_size(LabelSize::Small) .on_click(cx.listener(|this, _, cx| { if let Some(workspace) = this.workspace.upgrade() { workspace.update(cx, |workspace, cx| { diff --git a/crates/vim2/src/mode_indicator.rs b/crates/vim2/src/mode_indicator.rs index 8c831ba797..f3b16e68ae 100644 --- a/crates/vim2/src/mode_indicator.rs +++ b/crates/vim2/src/mode_indicator.rs @@ -1,6 +1,6 @@ -use gpui::{div, AnyElement, Element, IntoElement, Render, Subscription, ViewContext}; +use gpui::{div, AnyElement, Element, Render, Subscription, ViewContext}; use settings::SettingsStore; -use workspace::{item::ItemHandle, ui::Label, StatusItemView}; +use workspace::{item::ItemHandle, ui::prelude::*, StatusItemView}; use crate::{state::Mode, Vim}; @@ -61,7 +61,7 @@ impl Render for ModeIndicator { Mode::VisualLine => "-- VISUAL LINE --", Mode::VisualBlock => "-- VISUAL BLOCK --", }; - Label::new(text).into_any_element() + Label::new(text).size(LabelSize::Small).into_any_element() } } diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index e59d7ee494..6f17d77fef 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -637,6 +637,7 @@ impl Render for PanelButtons { .attach(menu_attach) .trigger( IconButton::new(name, icon) + .icon_size(IconSize::Small) .selected(is_active_button) .on_click({ let action = action.boxed_clone(); From f3fda8018f37afae08121b8ce28b195cf52a75b9 Mon Sep 17 00:00:00 2001 From: Julia Date: Thu, 21 Dec 2023 17:52:29 -0500 Subject: [PATCH 266/644] Prevent drag-dropping non-terminal item into terminal pane --- crates/gpui2/src/elements/div.rs | 78 +++++++++++++++------ crates/terminal_view2/src/terminal_panel.rs | 9 +++ crates/workspace2/src/pane.rs | 17 ++++- crates/workspace2/src/workspace2.rs | 2 + 4 files changed, 81 insertions(+), 25 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 90af9e130e..7c74eb1039 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -297,6 +297,10 @@ impl Interactivity { )); } + pub fn can_drop(&mut self, predicate: impl Fn(&dyn Any, &mut WindowContext) -> bool + 'static) { + self.can_drop_predicate = Some(Box::new(predicate)); + } + pub fn on_click(&mut self, listener: impl Fn(&ClickEvent, &mut WindowContext) + 'static) where Self: Sized, @@ -569,6 +573,14 @@ pub trait InteractiveElement: Sized { self } + fn can_drop( + mut self, + predicate: impl Fn(&dyn Any, &mut WindowContext) -> bool + 'static, + ) -> Self { + self.interactivity().can_drop(predicate); + self + } + fn block_mouse(mut self) -> Self { self.interactivity().block_mouse(); self @@ -699,6 +711,8 @@ pub type DragListener = Box AnyView + 's type DropListener = Box; +type CanDropPredicate = Box bool + 'static>; + pub type TooltipBuilder = Rc AnyView + 'static>; pub type KeyDownListener = Box; @@ -887,6 +901,7 @@ pub struct Interactivity { pub key_up_listeners: Vec, pub action_listeners: Vec<(TypeId, ActionListener)>, pub drop_listeners: Vec<(TypeId, DropListener)>, + pub can_drop_predicate: Option, pub click_listeners: Vec, pub drag_listener: Option<(Box, DragListener)>, pub hover_listener: Option>, @@ -1198,6 +1213,7 @@ impl Interactivity { let mut drag_listener = mem::take(&mut self.drag_listener); let drop_listeners = mem::take(&mut self.drop_listeners); let click_listeners = mem::take(&mut self.click_listeners); + let can_drop_predicate = mem::take(&mut self.can_drop_predicate); if !drop_listeners.is_empty() { cx.on_mouse_event({ @@ -1215,9 +1231,17 @@ impl Interactivity { "checked for type drag state type above", ); - listener(drag.value.as_ref(), cx); - cx.notify(); - cx.stop_propagation(); + let mut can_drop = true; + if let Some(predicate) = &can_drop_predicate { + can_drop = + predicate(drag.value.as_ref(), cx); + } + + if can_drop { + listener(drag.value.as_ref(), cx); + cx.notify(); + cx.stop_propagation(); + } } } } @@ -1596,27 +1620,36 @@ impl Interactivity { } if let Some(drag) = cx.active_drag.take() { - for (state_type, group_drag_style) in &self.group_drag_over_styles { - if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) { - if *state_type == drag.value.as_ref().type_id() - && group_bounds.contains(&mouse_position) - { - style.refine(&group_drag_style.style); - } - } + let mut can_drop = true; + if let Some(can_drop_predicate) = &self.can_drop_predicate { + can_drop = can_drop_predicate(drag.value.as_ref(), cx); } - for (state_type, drag_over_style) in &self.drag_over_styles { - if *state_type == drag.value.as_ref().type_id() - && bounds - .intersect(&cx.content_mask().bounds) - .contains(&mouse_position) - && cx.was_top_layer_under_active_drag( - &mouse_position, - cx.stacking_order(), - ) - { - style.refine(drag_over_style); + if can_drop { + for (state_type, group_drag_style) in &self.group_drag_over_styles { + if let Some(group_bounds) = + GroupBounds::get(&group_drag_style.group, cx) + { + if *state_type == drag.value.as_ref().type_id() + && group_bounds.contains(&mouse_position) + { + style.refine(&group_drag_style.style); + } + } + } + + for (state_type, drag_over_style) in &self.drag_over_styles { + if *state_type == drag.value.as_ref().type_id() + && bounds + .intersect(&cx.content_mask().bounds) + .contains(&mouse_position) + && cx.was_top_layer_under_active_drag( + &mouse_position, + cx.stacking_order(), + ) + { + style.refine(drag_over_style); + } } } @@ -1672,6 +1705,7 @@ impl Default for Interactivity { key_up_listeners: Vec::new(), action_listeners: Vec::new(), drop_listeners: Vec::new(), + can_drop_predicate: None, click_listeners: Vec::new(), drag_listener: None, hover_listener: None, diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index fa266ceb6c..245add3eeb 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -58,6 +58,15 @@ impl TerminalPanel { workspace.weak_handle(), workspace.project().clone(), Default::default(), + Some(Arc::new(|a, cx| { + if let Some(tab) = a.downcast_ref::() { + if let Some(item) = tab.pane.read(cx).item_for_index(tab.ix) { + return item.downcast::().is_some(); + } + } + + false + })), cx, ); pane.set_can_split(false, cx); diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index d0b47a2d1e..66bbe85087 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -181,7 +181,7 @@ pub struct Pane { workspace: WeakView, project: Model, drag_split_direction: Option, - // can_drop: Rc, &WindowContext) -> bool>, + can_drop_predicate: Option bool>>, can_split: bool, // render_tab_bar_buttons: Rc) -> AnyElement>, _subscriptions: Vec, @@ -229,7 +229,7 @@ pub struct NavigationEntry { } #[derive(Clone)] -struct DraggedTab { +pub struct DraggedTab { pub pane: View, pub ix: usize, pub item_id: EntityId, @@ -325,6 +325,7 @@ impl Pane { workspace: WeakView, project: Model, next_timestamp: Arc, + can_drop_predicate: Option bool + 'static>>, cx: &mut ViewContext, ) -> Self { // todo!("context menu") @@ -371,7 +372,7 @@ impl Pane { // tab_context_menu: cx.build_view(|_| ContextMenu::new(pane_view_id, cx)), workspace, project, - // can_drop: Rc::new(|_, _| true), + can_drop_predicate, can_split: true, // render_tab_bar_buttons: Rc::new(move |pane, cx| { // Flex::row() @@ -746,6 +747,10 @@ impl Pane { .position(|i| i.item_id() == item.item_id()) } + pub fn item_for_index(&self, ix: usize) -> Option<&dyn ItemHandle> { + self.items.get(ix).map(|i| i.as_ref()) + } + pub fn toggle_zoom(&mut self, _: &ToggleZoom, cx: &mut ViewContext) { if self.zoomed { cx.emit(Event::ZoomOut); @@ -1530,6 +1535,9 @@ impl Pane { ) .drag_over::(|tab| tab.bg(cx.theme().colors().drop_target_background)) .drag_over::(|tab| tab.bg(cx.theme().colors().drop_target_background)) + .when_some(self.can_drop_predicate.clone(), |this, p| { + this.can_drop(move |a, cx| p(a, cx)) + }) .on_drop(cx.listener(move |this, dragged_tab: &DraggedTab, cx| { this.drag_split_direction = None; this.handle_tab_drop(dragged_tab, ix, cx) @@ -1947,6 +1955,9 @@ impl Render for Pane { )) .group_drag_over::("", |style| style.visible()) .group_drag_over::("", |style| style.visible()) + .when_some(self.can_drop_predicate.clone(), |this, p| { + this.can_drop(move |a, cx| p(a, cx)) + }) .on_drop(cx.listener(move |this, dragged_tab, cx| { this.handle_tab_drop(dragged_tab, this.active_item_index(), cx) })) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index b4508b9dda..c1695891f6 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -542,6 +542,7 @@ impl Workspace { weak_handle.clone(), project.clone(), pane_history_timestamp.clone(), + None, cx, ) }); @@ -1724,6 +1725,7 @@ impl Workspace { self.weak_handle(), self.project.clone(), self.pane_history_timestamp.clone(), + None, cx, ) }); From 5307b75b2f81a105922b4f271ea34d8f969193a8 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 22:29:30 -0500 Subject: [PATCH 267/644] Add more left padding to title bar (#3768) This PR adds more left padding to the title bar to achieve the same positioning of the title bar items that we have in Zed1. Release Notes: - N/A --- crates/collab_ui2/src/collab_titlebar_item.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 8e542e413e..e4a6ff089a 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -74,14 +74,13 @@ impl Render for CollabTitlebarItem { // Set a non-scaling min-height here to ensure the titlebar is // always at least the height of the traffic lights. .min_h(px(32.)) - .pl_2() .map(|this| { if matches!(cx.window_bounds(), WindowBounds::Fullscreen) { this.pl_2() } else { // Use pixels here instead of a rem-based size because the macOS traffic // lights are a static size, and don't scale with the rest of the UI. - this.pl(px(72.)) + this.pl(px(80.)) } }) .bg(cx.theme().colors().title_bar_background) From 4fb12cb348e9c2f35d51ce4c73b329b148dc6f03 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 22:36:15 -0500 Subject: [PATCH 268/644] Add vertical padding to the picker entry list (#3769) This PR adds vertical padding to the list of picker entries. This prevents us from ending up with entries squished against the edges of the picker. Release Notes: - N/A --- crates/picker2/src/picker2.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 42b1d7433f..8dcc8b9698 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -252,6 +252,7 @@ impl Render for Picker { el.child( v_stack() .flex_grow() + .py_2() .child( uniform_list( cx.view().clone(), From 94e22ae515191cdadcd13fa933182dd5a17fbb1a Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 22:36:40 -0500 Subject: [PATCH 269/644] Fix typo in "Noctis Hibernus" theme name (#3770) This PR fixes a typo in the name of the "Noctis Hibernus" theme. Release Notes: - N/A --- assets/themes/src/vscode/noctis/family.json | 2 +- crates/theme2/src/themes/noctis.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/themes/src/vscode/noctis/family.json b/assets/themes/src/vscode/noctis/family.json index 525cb160f5..623be89c90 100644 --- a/assets/themes/src/vscode/noctis/family.json +++ b/assets/themes/src/vscode/noctis/family.json @@ -13,7 +13,7 @@ "appearance": "dark" }, { - "name": "Noctus Hibernus", + "name": "Noctis Hibernus", "file_name": "hibernus.json", "appearance": "light" }, diff --git a/crates/theme2/src/themes/noctis.rs b/crates/theme2/src/themes/noctis.rs index ca1601df99..55aea3d24c 100644 --- a/crates/theme2/src/themes/noctis.rs +++ b/crates/theme2/src/themes/noctis.rs @@ -577,7 +577,7 @@ pub fn noctis() -> UserThemeFamily { }, }, UserTheme { - name: "Noctus Hibernus".into(), + name: "Noctis Hibernus".into(), appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { From 80143b2571d664b01e031f6d4a353c959cd0ddc0 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 22:45:29 -0500 Subject: [PATCH 270/644] =?UTF-8?q?Fix=20names=20for=20Ros=C3=A9=20Pine=20?= =?UTF-8?q?themes=20(#3771)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR fixes the names of the Rosé Pine themes. We want to keep the Unicode "é" in the theme name, both because this is the actual name of the theme, and also to maintain parity with Zed1. Release Notes: - N/A --- Cargo.lock | 7 +++++++ assets/themes/src/vscode/rose-pine/family.json | 8 ++++---- crates/theme2/src/themes/rose_pine.rs | 8 ++++---- crates/theme_importer/Cargo.toml | 1 + crates/theme_importer/src/main.rs | 3 ++- crates/theme_importer/src/vscode/converter.rs | 2 +- 6 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82cc00bf9e..f8d8c1cc0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -306,6 +306,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "any_ascii" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea50b14b7a4b9343f8c627a7a53c52076482bd4bdad0a24fd3ec533ed616cc2c" + [[package]] name = "anyhow" version = "1.0.75" @@ -9836,6 +9842,7 @@ dependencies = [ name = "theme_importer" version = "0.1.0" dependencies = [ + "any_ascii", "anyhow", "clap 4.4.4", "convert_case 0.6.0", diff --git a/assets/themes/src/vscode/rose-pine/family.json b/assets/themes/src/vscode/rose-pine/family.json index 3f7b149db8..517b20c652 100644 --- a/assets/themes/src/vscode/rose-pine/family.json +++ b/assets/themes/src/vscode/rose-pine/family.json @@ -1,19 +1,19 @@ { - "name": "Rose Pine", + "name": "Rosé Pine", "author": "Rosé Pine", "themes": [ { - "name": "Rose Pine", + "name": "Rosé Pine", "file_name": "rose-pine.json", "appearance": "dark" }, { - "name": "Rose Pine Moon", + "name": "Rosé Pine Moon", "file_name": "rose-pine-moon.json", "appearance": "dark" }, { - "name": "Rose Pine Dawn", + "name": "Rosé Pine Dawn", "file_name": "rose-pine-dawn.json", "appearance": "light" } diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index 828838530f..a24c7ef80d 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -11,11 +11,11 @@ use crate::{ pub fn rose_pine() -> UserThemeFamily { UserThemeFamily { - name: "Rose Pine".into(), + name: "Rosé Pine".into(), author: "Rosé Pine".into(), themes: vec![ UserTheme { - name: "Rose Pine".into(), + name: "Rosé Pine".into(), appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { @@ -278,7 +278,7 @@ pub fn rose_pine() -> UserThemeFamily { }, }, UserTheme { - name: "Rose Pine Moon".into(), + name: "Rosé Pine Moon".into(), appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { @@ -541,7 +541,7 @@ pub fn rose_pine() -> UserThemeFamily { }, }, UserTheme { - name: "Rose Pine Dawn".into(), + name: "Rosé Pine Dawn".into(), appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { diff --git a/crates/theme_importer/Cargo.toml b/crates/theme_importer/Cargo.toml index 4b8641faa4..23a53053ce 100644 --- a/crates/theme_importer/Cargo.toml +++ b/crates/theme_importer/Cargo.toml @@ -7,6 +7,7 @@ publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +any_ascii = "0.3.2" anyhow.workspace = true clap = { version = "4.4", features = ["derive"] } convert_case = "0.6.0" diff --git a/crates/theme_importer/src/main.rs b/crates/theme_importer/src/main.rs index a02b1ca114..01ab191571 100644 --- a/crates/theme_importer/src/main.rs +++ b/crates/theme_importer/src/main.rs @@ -9,6 +9,7 @@ use std::path::PathBuf; use std::process::Command; use std::str::FromStr; +use any_ascii::any_ascii; use anyhow::{anyhow, Context, Result}; use clap::Parser; use convert_case::{Case, Casing}; @@ -187,7 +188,7 @@ fn main() -> Result<()> { let mut theme_modules = Vec::new(); for theme_family in theme_families { - let theme_family_slug = theme_family.name.to_string().to_case(Case::Snake); + let theme_family_slug = any_ascii(&theme_family.name).to_case(Case::Snake); let mut output_file = File::create(themes_output_path.join(format!("{theme_family_slug}.rs")))?; diff --git a/crates/theme_importer/src/vscode/converter.rs b/crates/theme_importer/src/vscode/converter.rs index 8ade493731..41534d0d0e 100644 --- a/crates/theme_importer/src/vscode/converter.rs +++ b/crates/theme_importer/src/vscode/converter.rs @@ -56,7 +56,7 @@ impl VsCodeThemeConverter { let syntax_theme = self.convert_syntax_theme()?; Ok(UserTheme { - name: self.theme_metadata.name.into(), + name: self.theme_metadata.name, appearance, styles: UserThemeStylesRefinement { colors: theme_colors_refinements, From cd9156886f60908e01702834b27bf74630a27110 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 23:22:22 -0500 Subject: [PATCH 271/644] Increase the indent step size for the collab panel (#3772) This PR increases the indent step size for the collab panel. This gives the channel list a clearer hierarchy for nested channels, as well as help align the disclosures with the parent channel's icon. Release Notes: - N/A --- crates/collab_ui2/src/collab_panel.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 7d01c080e8..b5b7a726d3 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2120,6 +2120,7 @@ impl CollabPanel { ListItem::new(channel_id as usize) // Add one level of depth for the disclosure arrow. .indent_level(depth + 1) + .indent_step_size(px(20.)) .selected(is_selected || is_active) .toggle(disclosed) .on_toggle( @@ -2190,6 +2191,7 @@ impl CollabPanel { .inset(false) // Add one level of depth for the disclosure arrow. .indent_level(depth + 1) + .indent_step_size(px(20.)) .start_slot( IconElement::new(Icon::Hash) .size(IconSize::Small) From 248458cef51cb86320ff429d9b40ce089e7a0da7 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 23:35:50 -0500 Subject: [PATCH 272/644] Indent contacts in collab panel (#3773) This PR indents contacts in the collab panel. Release Notes: - N/A --- crates/collab_ui2/src/collab_panel.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index b5b7a726d3..ad11877fd3 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -1871,6 +1871,8 @@ impl CollabPanel { let github_login = SharedString::from(contact.user.github_login.clone()); let item = ListItem::new(github_login.clone()) + .indent_level(1) + .indent_step_size(px(20.)) .selected(is_selected) .on_click(cx.listener(move |this, _, cx| this.call(user_id, cx))) .child( @@ -1968,6 +1970,8 @@ impl CollabPanel { }; ListItem::new(github_login.clone()) + .indent_level(1) + .indent_step_size(px(20.)) .selected(is_selected) .child( h_stack() From 2659b2744a010721604298f00aa8e97bd8175a6f Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 21 Dec 2023 23:41:24 -0500 Subject: [PATCH 273/644] Add vertical padding to the picker empty state (#3774) This PR adds vertical padding to the picker's empty state. This matches the styles added in #3769. Release Notes: - N/A --- crates/picker2/src/picker2.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 8dcc8b9698..aa88d70dc4 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -292,11 +292,13 @@ impl Render for Picker { }) .when(self.delegate.match_count() == 0, |el| { el.child( - ListItem::new("empty_state") - .inset(true) - .spacing(ListItemSpacing::Sparse) - .disabled(true) - .child(Label::new("No matches").color(Color::Muted)), + v_stack().flex_grow().py_2().child( + ListItem::new("empty_state") + .inset(true) + .spacing(ListItemSpacing::Sparse) + .disabled(true) + .child(Label::new("No matches").color(Color::Muted)), + ), ) }) } From 48ad53baddbff58b0b706c67acbd7664a2b3462b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 21 Dec 2023 19:52:15 +0100 Subject: [PATCH 274/644] Revert "Revert "Optimize order rendering and border drawing"" --- Cargo.lock | 12 ---- crates/gpui2/Cargo.toml | 1 - crates/gpui2/src/geometry.rs | 21 ++++++ crates/gpui2/src/scene.rs | 126 +++++++---------------------------- crates/gpui2/src/style.rs | 60 +++++++++++++++-- crates/gpui2/src/window.rs | 1 + 6 files changed, 101 insertions(+), 120 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f8d8c1cc0d..1bcbd3be38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4066,7 +4066,6 @@ dependencies = [ "parking", "parking_lot 0.11.2", "pathfinder_geometry", - "plane-split", "png", "postage", "rand 0.8.5", @@ -6662,17 +6661,6 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" -[[package]] -name = "plane-split" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f7d82649829ecdef8e258790b0587acf0a8403f0ce963473d8e918acc1643" -dependencies = [ - "euclid", - "log", - "smallvec", -] - [[package]] name = "plist" version = "1.5.0" diff --git a/crates/gpui2/Cargo.toml b/crates/gpui2/Cargo.toml index afb5d3ea0c..bf0ac955a5 100644 --- a/crates/gpui2/Cargo.toml +++ b/crates/gpui2/Cargo.toml @@ -56,7 +56,6 @@ uuid = { version = "1.1.2", features = ["v4"] } waker-fn = "1.1.0" slotmap = "1.0.6" schemars.workspace = true -plane-split = "0.18.0" bitflags = "2.4.0" [dev-dependencies] diff --git a/crates/gpui2/src/geometry.rs b/crates/gpui2/src/geometry.rs index f58435d7b9..6b4d9ae807 100644 --- a/crates/gpui2/src/geometry.rs +++ b/crates/gpui2/src/geometry.rs @@ -1590,6 +1590,15 @@ impl Edges { left: self.left.scale(factor), } } + + /// Returns the maximum value of any edge. + /// + /// # Returns + /// + /// The maximum `Pixels` value among all four edges. + pub fn max(&self) -> Pixels { + self.top.max(self.right).max(self.bottom).max(self.left) + } } impl Into> for f32 { @@ -1740,6 +1749,18 @@ impl Corners { bottom_left: self.bottom_left.scale(factor), } } + + /// Returns the maximum value of any corner. + /// + /// # Returns + /// + /// The maximum `Pixels` value among all four corners. + pub fn max(&self) -> Pixels { + self.top_left + .max(self.top_right) + .max(self.bottom_right) + .max(self.bottom_left) + } } impl Corners { diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index e6b601b62f..cb62ce314f 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -3,8 +3,6 @@ use crate::{ ScaledPixels, StackingOrder, }; use collections::BTreeMap; -use etagere::euclid::{Point3D, Vector3D}; -use plane_split::{BspSplitter, Polygon as BspPolygon}; use std::{fmt::Debug, iter::Peekable, mem, slice}; // Exported to metal @@ -19,7 +17,6 @@ pub type DrawOrder = u32; pub(crate) struct SceneBuilder { last_order: Option<(StackingOrder, LayerId)>, layers_by_order: BTreeMap, - splitter: BspSplitter<(PrimitiveKind, usize)>, shadows: Vec, quads: Vec, paths: Vec>, @@ -34,7 +31,6 @@ impl Default for SceneBuilder { SceneBuilder { last_order: None, layers_by_order: BTreeMap::new(), - splitter: BspSplitter::new(), shadows: Vec::new(), quads: Vec::new(), paths: Vec::new(), @@ -48,103 +44,47 @@ impl Default for SceneBuilder { impl SceneBuilder { pub fn build(&mut self) -> Scene { - // Map each layer id to a float between 0. and 1., with 1. closer to the viewer. - let mut layer_z_values = vec![0.; self.layers_by_order.len()]; + let mut orders = vec![0; self.layers_by_order.len()]; for (ix, layer_id) in self.layers_by_order.values().enumerate() { - layer_z_values[*layer_id as usize] = ix as f32 / self.layers_by_order.len() as f32; + orders[*layer_id as usize] = ix as u32; } self.layers_by_order.clear(); self.last_order = None; - // Add all primitives to the BSP splitter to determine draw order - self.splitter.reset(); - - for (ix, shadow) in self.shadows.iter().enumerate() { - let z = layer_z_values[shadow.order as LayerId as usize]; - self.splitter - .add(shadow.bounds.to_bsp_polygon(z, (PrimitiveKind::Shadow, ix))); + for shadow in &mut self.shadows { + shadow.order = orders[shadow.order as usize]; } + self.shadows.sort_by_key(|shadow| shadow.order); - for (ix, quad) in self.quads.iter().enumerate() { - let z = layer_z_values[quad.order as LayerId as usize]; - self.splitter - .add(quad.bounds.to_bsp_polygon(z, (PrimitiveKind::Quad, ix))); + for quad in &mut self.quads { + quad.order = orders[quad.order as usize]; } + self.quads.sort_by_key(|quad| quad.order); - for (ix, path) in self.paths.iter().enumerate() { - let z = layer_z_values[path.order as LayerId as usize]; - self.splitter - .add(path.bounds.to_bsp_polygon(z, (PrimitiveKind::Path, ix))); + for path in &mut self.paths { + path.order = orders[path.order as usize]; } + self.paths.sort_by_key(|path| path.order); - for (ix, underline) in self.underlines.iter().enumerate() { - let z = layer_z_values[underline.order as LayerId as usize]; - self.splitter.add( - underline - .bounds - .to_bsp_polygon(z, (PrimitiveKind::Underline, ix)), - ); + for underline in &mut self.underlines { + underline.order = orders[underline.order as usize]; } + self.underlines.sort_by_key(|underline| underline.order); - for (ix, monochrome_sprite) in self.monochrome_sprites.iter().enumerate() { - let z = layer_z_values[monochrome_sprite.order as LayerId as usize]; - self.splitter.add( - monochrome_sprite - .bounds - .to_bsp_polygon(z, (PrimitiveKind::MonochromeSprite, ix)), - ); + for monochrome_sprite in &mut self.monochrome_sprites { + monochrome_sprite.order = orders[monochrome_sprite.order as usize]; } + self.monochrome_sprites.sort_by_key(|sprite| sprite.order); - for (ix, polychrome_sprite) in self.polychrome_sprites.iter().enumerate() { - let z = layer_z_values[polychrome_sprite.order as LayerId as usize]; - self.splitter.add( - polychrome_sprite - .bounds - .to_bsp_polygon(z, (PrimitiveKind::PolychromeSprite, ix)), - ); + for polychrome_sprite in &mut self.polychrome_sprites { + polychrome_sprite.order = orders[polychrome_sprite.order as usize]; } + self.polychrome_sprites.sort_by_key(|sprite| sprite.order); - for (ix, surface) in self.surfaces.iter().enumerate() { - let z = layer_z_values[surface.order as LayerId as usize]; - self.splitter.add( - surface - .bounds - .to_bsp_polygon(z, (PrimitiveKind::Surface, ix)), - ); + for surface in &mut self.surfaces { + surface.order = orders[surface.order as usize]; } - - // Sort all polygons, then reassign the order field of each primitive to `draw_order` - // We need primitives to be repr(C), hence the weird reuse of the order field for two different types. - for (draw_order, polygon) in self - .splitter - .sort(Vector3D::new(0., 0., 1.)) - .iter() - .enumerate() - { - match polygon.anchor { - (PrimitiveKind::Shadow, ix) => self.shadows[ix].order = draw_order as DrawOrder, - (PrimitiveKind::Quad, ix) => self.quads[ix].order = draw_order as DrawOrder, - (PrimitiveKind::Path, ix) => self.paths[ix].order = draw_order as DrawOrder, - (PrimitiveKind::Underline, ix) => { - self.underlines[ix].order = draw_order as DrawOrder - } - (PrimitiveKind::MonochromeSprite, ix) => { - self.monochrome_sprites[ix].order = draw_order as DrawOrder - } - (PrimitiveKind::PolychromeSprite, ix) => { - self.polychrome_sprites[ix].order = draw_order as DrawOrder - } - (PrimitiveKind::Surface, ix) => self.surfaces[ix].order = draw_order as DrawOrder, - } - } - - self.shadows.sort_unstable(); - self.quads.sort_unstable(); - self.paths.sort_unstable(); - self.underlines.sort_unstable(); - self.monochrome_sprites.sort_unstable(); - self.polychrome_sprites.sort_unstable(); - self.surfaces.sort_unstable(); + self.surfaces.sort_by_key(|surface| surface.order); Scene { shadows: mem::take(&mut self.shadows), @@ -845,23 +785,3 @@ impl PathVertex { #[derive(Copy, Clone, Debug)] pub struct AtlasId(pub(crate) usize); - -impl Bounds { - fn to_bsp_polygon(&self, z: f32, anchor: A) -> BspPolygon { - let upper_left = self.origin; - let upper_right = self.upper_right(); - let lower_right = self.lower_right(); - let lower_left = self.lower_left(); - - BspPolygon::from_points( - [ - Point3D::new(upper_left.x.into(), upper_left.y.into(), z as f64), - Point3D::new(upper_right.x.into(), upper_right.y.into(), z as f64), - Point3D::new(lower_right.x.into(), lower_right.y.into(), z as f64), - Point3D::new(lower_left.x.into(), lower_left.y.into(), z as f64), - ], - anchor, - ) - .expect("Polygon should not be empty") - } -} diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index 3e9593b0fd..de54da79b3 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -402,13 +402,65 @@ impl Style { if self.is_border_visible() { cx.with_z_index(3, |cx| { - cx.paint_quad(quad( + let corner_radii = self.corner_radii.to_pixels(bounds.size, rem_size); + let border_widths = self.border_widths.to_pixels(rem_size); + let max_border_width = border_widths.max(); + let max_corner_radius = corner_radii.max(); + + let top_bounds = Bounds::from_corners( + bounds.origin, + bounds.upper_right() + + point(Pixels::ZERO, max_border_width.max(max_corner_radius)), + ); + let bottom_bounds = Bounds::from_corners( + bounds.lower_left() + - point(Pixels::ZERO, max_border_width.max(max_corner_radius)), + bounds.lower_right(), + ); + let left_bounds = Bounds::from_corners( + top_bounds.lower_left(), + bottom_bounds.origin + point(max_border_width, Pixels::ZERO), + ); + let right_bounds = Bounds::from_corners( + top_bounds.lower_right() - point(max_border_width, Pixels::ZERO), + bottom_bounds.upper_right(), + ); + + let quad = quad( bounds, - self.corner_radii.to_pixels(bounds.size, rem_size), + corner_radii, Hsla::transparent_black(), - self.border_widths.to_pixels(rem_size), + border_widths, self.border_color.unwrap_or_default(), - )); + ); + + cx.with_content_mask(Some(ContentMask { bounds: top_bounds }), |cx| { + cx.paint_quad(quad.clone()); + }); + cx.with_content_mask( + Some(ContentMask { + bounds: right_bounds, + }), + |cx| { + cx.paint_quad(quad.clone()); + }, + ); + cx.with_content_mask( + Some(ContentMask { + bounds: bottom_bounds, + }), + |cx| { + cx.paint_quad(quad.clone()); + }, + ); + cx.with_content_mask( + Some(ContentMask { + bounds: left_bounds, + }), + |cx| { + cx.paint_quad(quad); + }, + ); }); } diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index e57984fa0d..c20e2f7b94 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -3074,6 +3074,7 @@ impl From<(&'static str, u64)> for ElementId { } /// A rectangle, to be rendered on the screen by GPUI at the given position and size. +#[derive(Clone)] pub struct PaintQuad { bounds: Bounds, corner_radii: Corners, From 2a516ec1e0d05976a396968e4020f7ee5077a81b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 09:24:01 +0100 Subject: [PATCH 275/644] Honor `PrimitiveKind` ordering when `order` is the same This was a bug in the previous implementation that was being masked by how we were using BSP. --- crates/gpui2/src/scene.rs | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/crates/gpui2/src/scene.rs b/crates/gpui2/src/scene.rs index cb62ce314f..687943a7b1 100644 --- a/crates/gpui2/src/scene.rs +++ b/crates/gpui2/src/scene.rs @@ -269,10 +269,11 @@ impl<'a> Iterator for BatchIterator<'a> { match batch_kind { PrimitiveKind::Shadow => { let shadows_start = self.shadows_start; - let mut shadows_end = shadows_start; + let mut shadows_end = shadows_start + 1; + self.shadows_iter.next(); while self .shadows_iter - .next_if(|shadow| shadow.order <= max_order) + .next_if(|shadow| shadow.order < max_order) .is_some() { shadows_end += 1; @@ -284,10 +285,11 @@ impl<'a> Iterator for BatchIterator<'a> { } PrimitiveKind::Quad => { let quads_start = self.quads_start; - let mut quads_end = quads_start; + let mut quads_end = quads_start + 1; + self.quads_iter.next(); while self .quads_iter - .next_if(|quad| quad.order <= max_order) + .next_if(|quad| quad.order < max_order) .is_some() { quads_end += 1; @@ -297,10 +299,11 @@ impl<'a> Iterator for BatchIterator<'a> { } PrimitiveKind::Path => { let paths_start = self.paths_start; - let mut paths_end = paths_start; + let mut paths_end = paths_start + 1; + self.paths_iter.next(); while self .paths_iter - .next_if(|path| path.order <= max_order) + .next_if(|path| path.order < max_order) .is_some() { paths_end += 1; @@ -310,10 +313,11 @@ impl<'a> Iterator for BatchIterator<'a> { } PrimitiveKind::Underline => { let underlines_start = self.underlines_start; - let mut underlines_end = underlines_start; + let mut underlines_end = underlines_start + 1; + self.underlines_iter.next(); while self .underlines_iter - .next_if(|underline| underline.order <= max_order) + .next_if(|underline| underline.order < max_order) .is_some() { underlines_end += 1; @@ -326,11 +330,12 @@ impl<'a> Iterator for BatchIterator<'a> { PrimitiveKind::MonochromeSprite => { let texture_id = self.monochrome_sprites_iter.peek().unwrap().tile.texture_id; let sprites_start = self.monochrome_sprites_start; - let mut sprites_end = sprites_start; + let mut sprites_end = sprites_start + 1; + self.monochrome_sprites_iter.next(); while self .monochrome_sprites_iter .next_if(|sprite| { - sprite.order <= max_order && sprite.tile.texture_id == texture_id + sprite.order < max_order && sprite.tile.texture_id == texture_id }) .is_some() { @@ -345,11 +350,12 @@ impl<'a> Iterator for BatchIterator<'a> { PrimitiveKind::PolychromeSprite => { let texture_id = self.polychrome_sprites_iter.peek().unwrap().tile.texture_id; let sprites_start = self.polychrome_sprites_start; - let mut sprites_end = self.polychrome_sprites_start; + let mut sprites_end = self.polychrome_sprites_start + 1; + self.polychrome_sprites_iter.next(); while self .polychrome_sprites_iter .next_if(|sprite| { - sprite.order <= max_order && sprite.tile.texture_id == texture_id + sprite.order < max_order && sprite.tile.texture_id == texture_id }) .is_some() { @@ -363,10 +369,11 @@ impl<'a> Iterator for BatchIterator<'a> { } PrimitiveKind::Surface => { let surfaces_start = self.surfaces_start; - let mut surfaces_end = surfaces_start; + let mut surfaces_end = surfaces_start + 1; + self.surfaces_iter.next(); while self .surfaces_iter - .next_if(|surface| surface.order <= max_order) + .next_if(|surface| surface.order < max_order) .is_some() { surfaces_end += 1; From 01ce2044917825e6656825cf87573e788af3b339 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 09:29:56 +0100 Subject: [PATCH 276/644] Avoid painting a background quad if it is fully transparent --- crates/gpui2/src/style.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index de54da79b3..c281818c0f 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -384,7 +384,7 @@ impl Style { }); let background_color = self.background.as_ref().and_then(Fill::color); - if background_color.is_some() { + if background_color.map_or(false, |color| !color.is_transparent()) { cx.with_z_index(1, |cx| { cx.paint_quad(quad( bounds, From 6c4670287d7bc4c671d81b19b5c88a9e8346a17a Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 10:45:51 +0200 Subject: [PATCH 277/644] Highlight termina on external files drag and drop --- crates/terminal_view2/src/terminal_element.rs | 21 +++++++------------ crates/terminal_view2/src/terminal_panel.rs | 14 +++++-------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index ec1e1736c3..eb7348b935 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -4,8 +4,9 @@ use gpui::{ BorrowWindow, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, Interactivity, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, - Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, StatefulInteractiveElement, Styled, - TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, + Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, StatefulInteractiveElement, + StyleRefinement, Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, + WindowContext, }; use itertools::Itertools; use language::CursorShape; @@ -24,7 +25,7 @@ use terminal::{ use theme::{ActiveTheme, Theme, ThemeSettings}; use ui::Tooltip; -use std::mem; +use std::{any::TypeId, mem}; use std::{fmt::Debug, ops::RangeInclusive}; ///The information generated during layout that is necessary for painting @@ -689,6 +690,10 @@ impl TerminalElement { } }); + self.interactivity.drag_over_styles.push(( + TypeId::of::(), + StyleRefinement::default().bg(cx.theme().colors().drop_target_background), + )); self.interactivity.on_drop::({ let focus = focus.clone(); let terminal = terminal.clone(); @@ -787,8 +792,6 @@ impl Element for TerminalElement { ) { let mut layout = self.compute_layout(bounds, cx); - let theme = cx.theme(); - cx.paint_quad(fill(bounds, layout.background_color)); let origin = bounds.origin + Point::new(layout.gutter, px(0.)); @@ -801,16 +804,8 @@ impl Element for TerminalElement { .map(|cursor| cursor.bounding_rect(origin)), }; - let terminal_focus_handle = self.focus.clone(); - let terminal_handle = self.terminal.clone(); self.register_mouse_listeners(origin, layout.mode, bounds, cx); - // todo!(change this to work in terms of on_drag_move or some such) - // .drag_over::(|style| { - // // todo!() why does not it work? z-index of elements? - // style.bg(cx.theme().colors().ghost_element_hover) - // }) - let mut interactivity = mem::take(&mut self.interactivity); interactivity.paint(bounds, bounds.size, state, cx, |_, _, cx| { cx.handle_input(&self.focus, terminal_input_handler); diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index 245add3eeb..3c7b2a2e0e 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -4,8 +4,8 @@ use crate::TerminalView; use db::kvp::KEY_VALUE_STORE; use gpui::{ actions, div, serde_json, AppContext, AsyncWindowContext, Div, Entity, EventEmitter, - FocusHandle, FocusableView, ParentElement, Render, Styled, Subscription, Task, View, - ViewContext, VisualContext, WeakView, WindowContext, + ExternalPaths, FocusHandle, FocusableView, ParentElement, Render, Styled, Subscription, Task, + View, ViewContext, VisualContext, WeakView, WindowContext, }; use project::Fs; use serde::{Deserialize, Serialize}; @@ -64,6 +64,9 @@ impl TerminalPanel { return item.downcast::().is_some(); } } + if a.downcast_ref::().is_some() { + return true; + } false })), @@ -72,13 +75,6 @@ impl TerminalPanel { pane.set_can_split(false, cx); pane.set_can_navigate(false, cx); // todo!() - // pane.on_can_drop(move |drag_and_drop, cx| { - // drag_and_drop - // .currently_dragged::(window) - // .map_or(false, |(_, item)| { - // item.handle.act_as::(cx).is_some() - // }) - // }); // pane.set_render_tab_bar_buttons(cx, move |pane, cx| { // let this = weak_self.clone(); // Flex::row() From 3de72f83666ea787e0c32ddc84732467bc65d252 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 10:23:27 +0100 Subject: [PATCH 278/644] Fix context menu in tab bar --- crates/collab_ui2/src/collab_panel.rs | 11 +++ .../src/collab_panel/channel_modal.rs | 6 +- crates/copilot_button2/src/copilot_button.rs | 10 ++- crates/language_tools2/src/lsp_log.rs | 1 + .../language_tools2/src/syntax_tree_view.rs | 1 + crates/project_panel2/src/project_panel.rs | 1 + crates/ui2/src/components/context_menu.rs | 13 +++- .../src/components/stories/context_menu.rs | 11 +-- crates/workspace2/src/dock.rs | 2 +- crates/workspace2/src/pane.rs | 74 +++++++++++++++---- 10 files changed, 100 insertions(+), 30 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index ad11877fd3..3f0115e3fc 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -993,6 +993,7 @@ impl CollabPanel { }; context_menu = context_menu.entry( expand_action_name, + None, cx.handler_for(&this, move |this, cx| { this.toggle_channel_collapsed(channel_id, cx) }), @@ -1002,18 +1003,21 @@ impl CollabPanel { context_menu = context_menu .entry( "Open Notes", + None, cx.handler_for(&this, move |this, cx| { this.open_channel_notes(channel_id, cx) }), ) .entry( "Open Chat", + None, cx.handler_for(&this, move |this, cx| { this.join_channel_chat(channel_id, cx) }), ) .entry( "Copy Channel Link", + None, cx.handler_for(&this, move |this, cx| { this.copy_channel_link(channel_id, cx) }), @@ -1024,14 +1028,17 @@ impl CollabPanel { .separator() .entry( "New Subchannel", + None, cx.handler_for(&this, move |this, cx| this.new_subchannel(channel_id, cx)), ) .entry( "Rename", + None, cx.handler_for(&this, move |this, cx| this.rename_channel(channel_id, cx)), ) .entry( "Move this channel", + None, cx.handler_for(&this, move |this, cx| { this.start_move_channel(channel_id, cx) }), @@ -1040,6 +1047,7 @@ impl CollabPanel { if let Some(channel_name) = clipboard_channel_name { context_menu = context_menu.separator().entry( format!("Move '#{}' here", channel_name), + None, cx.handler_for(&this, move |this, cx| { this.move_channel_on_clipboard(channel_id, cx) }), @@ -1050,14 +1058,17 @@ impl CollabPanel { .separator() .entry( "Invite Members", + None, cx.handler_for(&this, move |this, cx| this.invite_members(channel_id, cx)), ) .entry( "Manage Members", + None, cx.handler_for(&this, move |this, cx| this.manage_members(channel_id, cx)), ) .entry( "Delete", + None, cx.handler_for(&this, move |this, cx| this.remove_channel(channel_id, cx)), ); } diff --git a/crates/collab_ui2/src/collab_panel/channel_modal.rs b/crates/collab_ui2/src/collab_panel/channel_modal.rs index f373dbad1f..d68aa32e9b 100644 --- a/crates/collab_ui2/src/collab_panel/channel_modal.rs +++ b/crates/collab_ui2/src/collab_panel/channel_modal.rs @@ -532,7 +532,7 @@ impl ChannelModalDelegate { let user_id = user.id; let picker = cx.view().clone(); let context_menu = ContextMenu::build(cx, |mut menu, _cx| { - menu = menu.entry("Remove Member", { + menu = menu.entry("Remove Member", None, { let picker = picker.clone(); move |cx| { picker.update(cx, |picker, cx| { @@ -544,7 +544,7 @@ impl ChannelModalDelegate { let picker = picker.clone(); match role { ChannelRole::Admin => { - menu = menu.entry("Revoke Admin", move |cx| { + menu = menu.entry("Revoke Admin", None, move |cx| { picker.update(cx, |picker, cx| { picker .delegate @@ -553,7 +553,7 @@ impl ChannelModalDelegate { }); } ChannelRole::Member => { - menu = menu.entry("Make Admin", move |cx| { + menu = menu.entry("Make Admin", None, move |cx| { picker.update(cx, |picker, cx| { picker .delegate diff --git a/crates/copilot_button2/src/copilot_button.rs b/crates/copilot_button2/src/copilot_button.rs index 705bdc1bec..7cd2b09db8 100644 --- a/crates/copilot_button2/src/copilot_button.rs +++ b/crates/copilot_button2/src/copilot_button.rs @@ -133,8 +133,11 @@ impl CopilotButton { pub fn build_copilot_start_menu(&mut self, cx: &mut ViewContext) -> View { let fs = self.fs.clone(); ContextMenu::build(cx, |menu, cx| { - menu.entry("Sign In", initiate_sign_in) - .entry("Disable Copilot", move |cx| hide_copilot(fs.clone(), cx)) + menu.entry("Sign In", None, initiate_sign_in).entry( + "Disable Copilot", + None, + move |cx| hide_copilot(fs.clone(), cx), + ) }) } @@ -154,6 +157,7 @@ impl CopilotButton { if language_enabled { "Hide" } else { "Show" }, language.name() ), + None, move |cx| toggle_copilot_for_language(language.clone(), fs.clone(), cx), ); } @@ -169,6 +173,7 @@ impl CopilotButton { "{} Suggestions for This Path", if path_enabled { "Hide" } else { "Show" } ), + None, move |cx| { if let Some(workspace) = cx.window_handle().downcast::() { if let Ok(workspace) = workspace.root_view(cx) { @@ -194,6 +199,7 @@ impl CopilotButton { } else { "Show Suggestions for All Files" }, + None, move |cx| toggle_copilot_globally(fs.clone(), cx), ) .separator() diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 597c9c5b54..973cd9c355 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -763,6 +763,7 @@ impl Render for LspLogToolbarItemView { )) .entry( SERVER_LOGS, + None, cx.handler_for(&log_view, move |view, cx| { view.show_logs_for_server(row.server_id, cx); }), diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index dcdcb612b7..c9a621f967 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -459,6 +459,7 @@ impl SyntaxTreeToolbarItemView { layer.language.name(), format_node_range(layer.node()) ), + None, cx.handler_for(&view, move |view, cx| { view.select_layer(layer_ix, cx); }), diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 07a6e4be5e..7f6ae63ee1 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -400,6 +400,7 @@ impl ProjectPanel { if is_root { menu = menu.entry( "Remove from Project", + None, cx.handler_for(&this, move |this, cx| { this.project.update(cx, |project, cx| { project.remove_worktree(worktree_id, cx) diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 97bb3865ef..8502169833 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -76,13 +76,14 @@ impl ContextMenu { pub fn entry( mut self, label: impl Into, + action: Option>, handler: impl Fn(&mut WindowContext) + 'static, ) -> Self { self.items.push(ContextMenuItem::Entry { label: label.into(), handler: Rc::new(handler), icon: None, - action: None, + action, }); self } @@ -282,7 +283,10 @@ impl Render for ContextMenu { ListItem::new(ix) .inset(true) .selected(Some(ix) == self.selected_index) - .on_click(move |_, cx| handler(cx)) + .on_click(cx.listener(move |_, _, cx| { + handler(cx); + cx.emit(DismissEvent); + })) .child( h_stack() .w_full() @@ -303,7 +307,10 @@ impl Render for ContextMenu { ListItem::new(ix) .inset(true) .selected(Some(ix) == self.selected_index) - .on_click(move |_, cx| handler(cx)) + .on_click(cx.listener(move |_, _, cx| { + handler(cx); + cx.emit(DismissEvent); + })) .child(entry_render(cx)) .into_any_element() } diff --git a/crates/ui2/src/components/stories/context_menu.rs b/crates/ui2/src/components/stories/context_menu.rs index cae5939f2a..68d5f7bd33 100644 --- a/crates/ui2/src/components/stories/context_menu.rs +++ b/crates/ui2/src/components/stories/context_menu.rs @@ -1,4 +1,4 @@ -use gpui::{actions, Action, AnchorCorner, Div, Render, View}; +use gpui::{actions, AnchorCorner, Div, Render, View}; use story::Story; use crate::prelude::*; @@ -10,12 +10,9 @@ fn build_menu(cx: &mut WindowContext, header: impl Into) -> View, mut save_intent: SaveIntent, - should_close: impl 'static + Fn(EntityId) -> bool, + should_close: impl Fn(EntityId) -> bool, ) -> Task> { // Find the items to close. let mut items_to_close = Vec::new(); @@ -1571,28 +1571,74 @@ impl Pane { } }; + let pane = cx.view().clone(); right_click_menu(ix).trigger(tab).menu(move |cx| { - ContextMenu::build(cx, |menu, _| { + let pane = pane.clone(); + ContextMenu::build(cx, move |menu, cx| { let menu = menu - .action("Close", CloseActiveItem { save_intent: None }.boxed_clone()) - .action("Close Others", CloseInactiveItems.boxed_clone()) + .entry( + "Close", + Some(Box::new(CloseActiveItem { save_intent: None })), + cx.handler_for(&pane, move |pane, cx| { + pane.close_item_by_id(item_id, SaveIntent::Close, cx) + .detach_and_log_err(cx); + }), + ) + .entry( + "Close Others", + Some(Box::new(CloseInactiveItems)), + cx.handler_for(&pane, move |pane, cx| { + pane.close_items(cx, SaveIntent::Close, |id| id != item_id) + .detach_and_log_err(cx); + }), + ) .separator() - .action("Close Left", CloseItemsToTheLeft.boxed_clone()) - .action("Close Right", CloseItemsToTheRight.boxed_clone()) + .entry( + "Close Left", + Some(Box::new(CloseItemsToTheLeft)), + cx.handler_for(&pane, move |pane, cx| { + pane.close_items_to_the_left_by_id(item_id, cx) + .detach_and_log_err(cx); + }), + ) + .entry( + "Close Right", + Some(Box::new(CloseItemsToTheRight)), + cx.handler_for(&pane, move |pane, cx| { + pane.close_items_to_the_right_by_id(item_id, cx) + .detach_and_log_err(cx); + }), + ) .separator() - .action("Close Clean", CloseCleanItems.boxed_clone()) - .action( + .entry( + "Close Clean", + Some(Box::new(CloseCleanItems)), + cx.handler_for(&pane, move |pane, cx| { + pane.close_clean_items(&CloseCleanItems, cx) + .map(|task| task.detach_and_log_err(cx)); + }), + ) + .entry( "Close All", - CloseAllItems { save_intent: None }.boxed_clone(), + Some(Box::new(CloseAllItems { save_intent: None })), + cx.handler_for(&pane, |pane, cx| { + pane.close_all_items(&CloseAllItems { save_intent: None }, cx) + .map(|task| task.detach_and_log_err(cx)); + }), ); if let Some(entry) = single_entry_to_resolve { - menu.separator().action( + let entry_id = entry.to_proto(); + menu.separator().entry( "Reveal In Project Panel", - RevealInProjectPanel { - entry_id: entry.to_proto(), - } - .boxed_clone(), + Some(Box::new(RevealInProjectPanel { entry_id })), + cx.handler_for(&pane, move |pane, cx| { + pane.project.update(cx, |_, cx| { + cx.emit(project::Event::RevealInProjectPanel( + ProjectEntryId::from_proto(entry_id), + )) + }); + }), ) } else { menu From 41ff37d56e9161ed2946b6cfe5d9758edc2ae8be Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 22 Dec 2023 01:27:22 -0500 Subject: [PATCH 279/644] Slow down sampling metric collection rate --- crates/client/src/telemetry.rs | 7 ++++--- crates/client2/src/telemetry.rs | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index a3e7449cf8..6d70de6138 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -187,10 +187,11 @@ impl Telemetry { // Avoiding calling `refresh_all()`, just update what we need system.refresh_specifics(refresh_kind); + // Waiting some amount of time before the first query is important to get a reasonable value + // https://docs.rs/sysinfo/0.29.10/sysinfo/trait.ProcessExt.html#tymethod.cpu_usage + const DURATION_BETWEEN_SYSTEM_EVENTS: Duration = Duration::from_secs(4 * 60); + loop { - // Waiting some amount of time before the first query is important to get a reasonable value - // https://docs.rs/sysinfo/0.29.10/sysinfo/trait.ProcessExt.html#tymethod.cpu_usage - const DURATION_BETWEEN_SYSTEM_EVENTS: Duration = Duration::from_secs(60); smol::Timer::after(DURATION_BETWEEN_SYSTEM_EVENTS).await; system.refresh_specifics(refresh_kind); diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index b303e68183..71c4c33491 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -205,10 +205,11 @@ impl Telemetry { // Avoiding calling `refresh_all()`, just update what we need system.refresh_specifics(refresh_kind); + // Waiting some amount of time before the first query is important to get a reasonable value + // https://docs.rs/sysinfo/0.29.10/sysinfo/trait.ProcessExt.html#tymethod.cpu_usage + const DURATION_BETWEEN_SYSTEM_EVENTS: Duration = Duration::from_secs(4 * 60); + loop { - // Waiting some amount of time before the first query is important to get a reasonable value - // https://docs.rs/sysinfo/0.29.10/sysinfo/trait.ProcessExt.html#tymethod.cpu_usage - const DURATION_BETWEEN_SYSTEM_EVENTS: Duration = Duration::from_secs(60); smol::Timer::after(DURATION_BETWEEN_SYSTEM_EVENTS).await; system.refresh_specifics(refresh_kind); From fce31b7ddfde208ea79f730d2cf5003983a37dfa Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 10:50:33 +0200 Subject: [PATCH 280/644] Remove the warnings from element.rs --- crates/editor2/src/element.rs | 103 +++++++++++++++------------------- 1 file changed, 45 insertions(+), 58 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 9dab9d00ae..d97883beba 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -493,8 +493,8 @@ impl EditorElement { event: &MouseMoveEvent, position_map: &PositionMap, text_bounds: Bounds, - gutter_bounds: Bounds, - stacking_order: &StackingOrder, + _gutter_bounds: Bounds, + _stacking_order: &StackingOrder, cx: &mut ViewContext, ) { if !editor.has_pending_selection() { @@ -738,7 +738,7 @@ impl EditorElement { cx.with_z_index(1, |cx| { for (ix, fold_indicator) in layout.fold_indicators.drain(..).enumerate() { - if let Some(mut fold_indicator) = fold_indicator { + if let Some(fold_indicator) = fold_indicator { let mut fold_indicator = fold_indicator.into_any_element(); let available_space = size( AvailableSpace::MinContent, @@ -867,7 +867,6 @@ impl EditorElement { layout: &mut LayoutState, cx: &mut WindowContext, ) { - let scroll_position = layout.position_map.snapshot.scroll_position(); let start_row = layout.visible_display_row_range.start; let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); let line_end_overshoot = 0.15 * layout.position_map.line_height; @@ -1411,7 +1410,7 @@ impl EditorElement { if self.editor.read(cx).scroll_manager.is_dragging_scrollbar() { cx.on_mouse_event({ let editor = self.editor.clone(); - move |event: &MouseUpEvent, phase, cx| { + move |_: &MouseUpEvent, phase, cx| { if phase == DispatchPhase::Capture { return; } @@ -1767,11 +1766,7 @@ impl EditorElement { } } - fn compute_layout( - &mut self, - mut bounds: Bounds, - cx: &mut WindowContext, - ) -> LayoutState { + fn compute_layout(&mut self, bounds: Bounds, cx: &mut WindowContext) -> LayoutState { self.editor.update(cx, |editor, cx| { let snapshot = editor.snapshot(cx); let style = self.style.clone(); @@ -1811,22 +1806,23 @@ impl EditorElement { let text_width = bounds.size.width - gutter_width; let overscroll = size(em_width, px(0.)); - let snapshot = { - editor.set_visible_line_count((bounds.size.height / line_height).into(), cx); + // todo!() + // let snapshot = { + // editor.set_visible_line_count((bounds.size.height / line_height).into(), cx); - let editor_width = text_width - gutter_margin - overscroll.width - em_width; - let wrap_width = match editor.soft_wrap_mode(cx) { - SoftWrap::None => (MAX_LINE_LEN / 2) as f32 * em_advance, - SoftWrap::EditorWidth => editor_width, - SoftWrap::Column(column) => editor_width.min(column as f32 * em_advance), - }; + // let editor_width = text_width - gutter_margin - overscroll.width - em_width; + // let wrap_width = match editor.soft_wrap_mode(cx) { + // SoftWrap::None => (MAX_LINE_LEN / 2) as f32 * em_advance, + // SoftWrap::EditorWidth => editor_width, + // SoftWrap::Column(column) => editor_width.min(column as f32 * em_advance), + // }; - if editor.set_wrap_width(Some(wrap_width), cx) { - editor.snapshot(cx) - } else { - snapshot - } - }; + // if editor.set_wrap_width(Some(wrap_width), cx) { + // editor.snapshot(cx) + // } else { + // snapshot + // } + // }; let wrap_guides = editor .wrap_guides(cx) @@ -1834,7 +1830,6 @@ impl EditorElement { .map(|(guide, active)| (self.column_pixels(*guide, cx), *active)) .collect::>(); - let scroll_height = Pixels::from(snapshot.max_point().row() + 1) * line_height; let gutter_size = size(gutter_width, bounds.size.height); let text_size = size(text_width, bounds.size.height); @@ -2101,7 +2096,7 @@ impl EditorElement { .max(MIN_POPOVER_LINE_HEIGHT * line_height), // Apply minimum height of 4 lines ); - let mut hover = editor.hover_state.render( + let hover = editor.hover_state.render( &snapshot, &style, visible_rows, @@ -2110,7 +2105,7 @@ impl EditorElement { cx, ); - let mut fold_indicators = cx.with_element_id(Some("gutter_fold_indicators"), |cx| { + let fold_indicators = cx.with_element_id(Some("gutter_fold_indicators"), |cx| { editor.render_fold_indicators( fold_statuses, &style, @@ -2212,7 +2207,6 @@ impl EditorElement { cx: &mut ViewContext, ) -> (Pixels, Vec) { let mut block_id = 0; - let scroll_x = snapshot.scroll_anchor.offset.x; let (fixed_blocks, non_fixed_blocks) = snapshot .blocks_in_range(rows.clone()) .partition::, _>(|(_, block)| match block { @@ -2220,11 +2214,11 @@ impl EditorElement { TransformBlock::Custom(block) => block.style() == BlockStyle::Fixed, }); - let mut render_block = |block: &TransformBlock, - available_space: Size, - block_id: usize, - editor: &mut Editor, - cx: &mut ViewContext| { + let render_block = |block: &TransformBlock, + available_space: Size, + block_id: usize, + editor: &mut Editor, + cx: &mut ViewContext| { let mut element = match block { TransformBlock::Custom(block) => { let align_to = block @@ -2277,7 +2271,7 @@ impl EditorElement { .map_or(range.context.start, |primary| primary.start); let jump_position = language::ToPoint::to_point(&jump_anchor, buffer); - let jump_handler = cx.listener_for(&self.editor, move |editor, e, cx| { + let jump_handler = cx.listener_for(&self.editor, move |editor, _, cx| { editor.jump(jump_path.clone(), jump_position, jump_anchor, cx); }); @@ -2296,8 +2290,6 @@ impl EditorElement { .map(|p| SharedString::from(p.to_string_lossy().to_string() + "/")); } - let is_open = true; - div().id("path header container").size_full().p_1p5().child( h_stack() .id("path header block") @@ -2336,7 +2328,6 @@ impl EditorElement { })), // .p_x(gutter_padding) ) } else { - let text_style = style.text.clone(); h_stack() .id("collapsed context") .size_full() @@ -2447,7 +2438,6 @@ impl EditorElement { layout: &LayoutState, cx: &mut WindowContext, ) { - let content_origin = text_bounds.origin + point(layout.gutter_margin, Pixels::ZERO); let interactive_bounds = InteractiveBounds { bounds: bounds.intersect(&cx.content_mask().bounds), stacking_order: cx.stacking_order().clone(), @@ -2764,7 +2754,7 @@ impl Element for EditorElement { fn layout( &mut self, - element_state: Option, + _element_state: Option, cx: &mut gpui::WindowContext, ) -> (gpui::LayoutId, Self::State) { self.editor.update(cx, |editor, cx| { @@ -2782,22 +2772,19 @@ impl Element for EditorElement { let editor_handle = cx.view().clone(); let max_line_number_width = self.max_line_number_width(&editor.snapshot(cx), cx); - cx.request_measured_layout( - Style::default(), - move |known_dimensions, available_space, cx| { - editor_handle - .update(cx, |editor, cx| { - compute_auto_height_layout( - editor, - max_lines, - max_line_number_width, - known_dimensions, - cx, - ) - }) - .unwrap_or_default() - }, - ) + cx.request_measured_layout(Style::default(), move |known_dimensions, _, cx| { + editor_handle + .update(cx, |editor, cx| { + compute_auto_height_layout( + editor, + max_lines, + max_line_number_width, + known_dimensions, + cx, + ) + }) + .unwrap_or_default() + }) } EditorMode::Full => { let mut style = Style::default(); @@ -2814,7 +2801,7 @@ impl Element for EditorElement { fn paint( &mut self, bounds: Bounds, - element_state: &mut Self::State, + _element_state: &mut Self::State, cx: &mut gpui::WindowContext, ) { let editor = self.editor.clone(); @@ -3137,7 +3124,7 @@ impl HighlightedRange { &self, start_y: Pixels, lines: &[HighlightedRangeLine], - bounds: Bounds, + _bounds: Bounds, cx: &mut WindowContext, ) { if lines.is_empty() { @@ -3755,7 +3742,7 @@ fn compute_auto_height_layout( known_dimensions: Size>, cx: &mut ViewContext, ) -> Option> { - let mut width = known_dimensions.width?; + let width = known_dimensions.width?; if let Some(height) = known_dimensions.height { return Some(size(width, height)); } From d36ec81725009745e65418a28a76425c107683ae Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 11:55:25 +0200 Subject: [PATCH 281/644] Move multibuffer "go to file" button into the buffer header Co-Authored-By: Antonio Scandurra --- crates/editor2/src/element.rs | 101 +++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index d97883beba..c6d468f40b 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2290,46 +2290,55 @@ impl EditorElement { .map(|p| SharedString::from(p.to_string_lossy().to_string() + "/")); } - div().id("path header container").size_full().p_1p5().child( - h_stack() - .id("path header block") - .py_1p5() - .pl_3() - .pr_2() - .rounded_lg() - .shadow_md() - .border() - .border_color(cx.theme().colors().border) - .bg(cx.theme().colors().editor_subheader_background) - .justify_between() - .cursor_pointer() - .hover(|style| style.bg(cx.theme().colors().element_hover)) - .child( - h_stack().gap_3().child( - h_stack() - .gap_2() - .child(Label::new( - filename - .map(SharedString::from) - .unwrap_or_else(|| "untitled".into()), - )) - .when_some(parent_path, |then, path| { - then.child(Label::new(path).color(Color::Muted)) - }), - ), - ) - .children(jump_handler.map(|jump_handler| { - IconButton::new(block_id, Icon::ArrowUpRight) - .style(ButtonStyle::Subtle) - .on_click(jump_handler) - .tooltip(|cx| { - Tooltip::for_action("Jump to Buffer", &OpenExcerpts, cx) - }) - })), // .p_x(gutter_padding) - ) + div() + .id(("path header container", block_id)) + .size_full() + .p_1p5() + .child( + h_stack() + .id("path header block") + .py_1p5() + .pl_3() + .pr_2() + .rounded_lg() + .shadow_md() + .border() + .border_color(cx.theme().colors().border) + .bg(cx.theme().colors().editor_subheader_background) + .justify_between() + .hover(|style| style.bg(cx.theme().colors().element_hover)) + .child( + h_stack().gap_3().child( + h_stack() + .gap_2() + .child(Label::new( + filename + .map(SharedString::from) + .unwrap_or_else(|| "untitled".into()), + )) + .when_some(parent_path, |then, path| { + then.child(Label::new(path).color(Color::Muted)) + }), + ), + ) + .when_some(jump_handler, |this, jump_handler| { + this.cursor_pointer() + .tooltip(|cx| { + Tooltip::for_action( + "Jump to Buffer", + &OpenExcerpts, + cx, + ) + }) + .on_mouse_down(MouseButton::Left, |_, cx| { + cx.stop_propagation() + }) + .on_click(jump_handler) + }), + ) } else { h_stack() - .id("collapsed context") + .id(("collapsed context", block_id)) .size_full() .gap(gutter_padding) .child( @@ -2834,17 +2843,19 @@ impl Element for EditorElement { cx.with_z_index(0, |cx| { self.paint_mouse_listeners(bounds, gutter_bounds, text_bounds, &layout, cx); - - if !layout.blocks.is_empty() { - cx.with_element_id(Some("editor_blocks"), |cx| { - self.paint_blocks(bounds, &mut layout, cx); - }); - } }); cx.with_z_index(1, |cx| self.paint_scrollbar(bounds, &mut layout, cx)); - cx.with_z_index(2, |cx| { + if !layout.blocks.is_empty() { + cx.with_z_index(2, |cx| { + cx.with_element_id(Some("editor_blocks"), |cx| { + self.paint_blocks(bounds, &mut layout, cx); + }); + }) + } + + cx.with_z_index(3, |cx| { self.paint_overlays(text_bounds, &mut layout, cx); }); }); From 4d5ff77abee0a7f0891fe95fcdc200e7a454a630 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 12:14:53 +0200 Subject: [PATCH 282/644] Fix the tests --- crates/editor2/src/element.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index c6d468f40b..294cc2c4e3 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -1806,23 +1806,22 @@ impl EditorElement { let text_width = bounds.size.width - gutter_width; let overscroll = size(em_width, px(0.)); - // todo!() - // let snapshot = { - // editor.set_visible_line_count((bounds.size.height / line_height).into(), cx); + let _snapshot = { + editor.set_visible_line_count((bounds.size.height / line_height).into(), cx); - // let editor_width = text_width - gutter_margin - overscroll.width - em_width; - // let wrap_width = match editor.soft_wrap_mode(cx) { - // SoftWrap::None => (MAX_LINE_LEN / 2) as f32 * em_advance, - // SoftWrap::EditorWidth => editor_width, - // SoftWrap::Column(column) => editor_width.min(column as f32 * em_advance), - // }; + let editor_width = text_width - gutter_margin - overscroll.width - em_width; + let wrap_width = match editor.soft_wrap_mode(cx) { + SoftWrap::None => (MAX_LINE_LEN / 2) as f32 * em_advance, + SoftWrap::EditorWidth => editor_width, + SoftWrap::Column(column) => editor_width.min(column as f32 * em_advance), + }; - // if editor.set_wrap_width(Some(wrap_width), cx) { - // editor.snapshot(cx) - // } else { - // snapshot - // } - // }; + if editor.set_wrap_width(Some(wrap_width), cx) { + editor.snapshot(cx) + } else { + snapshot + } + }; let wrap_guides = editor .wrap_guides(cx) From a551647ec1ca098caef33721c06a79b7035ded56 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 12:12:39 +0100 Subject: [PATCH 283/644] Fix panic in completions menu We were shifting all the positions while keeping the original string, which caused problems later when combining highlighted ranges with matched indices. --- crates/editor2/src/editor.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index f1f053acbb..943ddf47bd 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -1350,15 +1350,15 @@ impl CompletionsMenu { completion.sort_key(), ) }); - drop(completions); for mat in &mut matches { - let completions = self.completions.read(); - let filter_start = completions[mat.candidate_id].label.filter_range.start; + let completion = &completions[mat.candidate_id]; + mat.string = completion.label.text.clone(); for position in &mut mat.positions { - *position += filter_start; + *position += completion.label.filter_range.start; } } + drop(completions); self.matches = matches.into(); self.selected_item = 0; From c1ad079f09cfdeafa2f5228bbccae62deef82e8e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 12:27:20 +0100 Subject: [PATCH 284/644] Fix dismissing context menu when clicking on an item dispatched action --- crates/ui2/src/components/context_menu.rs | 29 ++++- crates/workspace2/src/pane.rs | 138 +++++++++++----------- 2 files changed, 93 insertions(+), 74 deletions(-) diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 8502169833..6df6a29096 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -29,6 +29,7 @@ pub struct ContextMenu { focus_handle: FocusHandle, selected_index: Option, delayed: bool, + clicked: bool, _on_blur_subscription: Subscription, } @@ -56,6 +57,7 @@ impl ContextMenu { focus_handle, selected_index: None, delayed: false, + clicked: false, _on_blur_subscription, }, cx, @@ -187,6 +189,11 @@ impl ContextMenu { } pub fn on_action_dispatch(&mut self, dispatched: &Box, cx: &mut ViewContext) { + if self.clicked { + cx.propagate(); + return; + } + if let Some(ix) = self.items.iter().position(|item| { if let ContextMenuItem::Entry { action: Some(action), @@ -269,6 +276,7 @@ impl Render for ContextMenu { action, } => { let handler = handler.clone(); + let menu = cx.view().downgrade(); let label_element = if let Some(icon) = icon { h_stack() @@ -283,10 +291,14 @@ impl Render for ContextMenu { ListItem::new(ix) .inset(true) .selected(Some(ix) == self.selected_index) - .on_click(cx.listener(move |_, _, cx| { + .on_click(move |_, cx| { handler(cx); - cx.emit(DismissEvent); - })) + menu.update(cx, |menu, cx| { + menu.clicked = true; + cx.emit(DismissEvent); + }) + .ok(); + }) .child( h_stack() .w_full() @@ -304,13 +316,18 @@ impl Render for ContextMenu { handler, } => { let handler = handler.clone(); + let menu = cx.view().downgrade(); ListItem::new(ix) .inset(true) .selected(Some(ix) == self.selected_index) - .on_click(cx.listener(move |_, _, cx| { + .on_click(move |_, cx| { handler(cx); - cx.emit(DismissEvent); - })) + menu.update(cx, |menu, cx| { + menu.clicked = true; + cx.emit(DismissEvent); + }) + .ok(); + }) .child(entry_render(cx)) .into_any_element() } diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 96daeb24ed..911c292133 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1571,78 +1571,80 @@ impl Pane { } }; - let pane = cx.view().clone(); + let pane = cx.view().downgrade(); right_click_menu(ix).trigger(tab).menu(move |cx| { let pane = pane.clone(); - ContextMenu::build(cx, move |menu, cx| { - let menu = menu - .entry( - "Close", - Some(Box::new(CloseActiveItem { save_intent: None })), - cx.handler_for(&pane, move |pane, cx| { - pane.close_item_by_id(item_id, SaveIntent::Close, cx) - .detach_and_log_err(cx); - }), - ) - .entry( - "Close Others", - Some(Box::new(CloseInactiveItems)), - cx.handler_for(&pane, move |pane, cx| { - pane.close_items(cx, SaveIntent::Close, |id| id != item_id) - .detach_and_log_err(cx); - }), - ) - .separator() - .entry( - "Close Left", - Some(Box::new(CloseItemsToTheLeft)), - cx.handler_for(&pane, move |pane, cx| { - pane.close_items_to_the_left_by_id(item_id, cx) - .detach_and_log_err(cx); - }), - ) - .entry( - "Close Right", - Some(Box::new(CloseItemsToTheRight)), - cx.handler_for(&pane, move |pane, cx| { - pane.close_items_to_the_right_by_id(item_id, cx) - .detach_and_log_err(cx); - }), - ) - .separator() - .entry( - "Close Clean", - Some(Box::new(CloseCleanItems)), - cx.handler_for(&pane, move |pane, cx| { - pane.close_clean_items(&CloseCleanItems, cx) - .map(|task| task.detach_and_log_err(cx)); - }), - ) - .entry( - "Close All", - Some(Box::new(CloseAllItems { save_intent: None })), - cx.handler_for(&pane, |pane, cx| { - pane.close_all_items(&CloseAllItems { save_intent: None }, cx) - .map(|task| task.detach_and_log_err(cx)); - }), - ); + ContextMenu::build(cx, move |mut menu, cx| { + if let Some(pane) = pane.upgrade() { + menu = menu + .entry( + "Close", + Some(Box::new(CloseActiveItem { save_intent: None })), + cx.handler_for(&pane, move |pane, cx| { + pane.close_item_by_id(item_id, SaveIntent::Close, cx) + .detach_and_log_err(cx); + }), + ) + .entry( + "Close Others", + Some(Box::new(CloseInactiveItems)), + cx.handler_for(&pane, move |pane, cx| { + pane.close_items(cx, SaveIntent::Close, |id| id != item_id) + .detach_and_log_err(cx); + }), + ) + .separator() + .entry( + "Close Left", + Some(Box::new(CloseItemsToTheLeft)), + cx.handler_for(&pane, move |pane, cx| { + pane.close_items_to_the_left_by_id(item_id, cx) + .detach_and_log_err(cx); + }), + ) + .entry( + "Close Right", + Some(Box::new(CloseItemsToTheRight)), + cx.handler_for(&pane, move |pane, cx| { + pane.close_items_to_the_right_by_id(item_id, cx) + .detach_and_log_err(cx); + }), + ) + .separator() + .entry( + "Close Clean", + Some(Box::new(CloseCleanItems)), + cx.handler_for(&pane, move |pane, cx| { + pane.close_clean_items(&CloseCleanItems, cx) + .map(|task| task.detach_and_log_err(cx)); + }), + ) + .entry( + "Close All", + Some(Box::new(CloseAllItems { save_intent: None })), + cx.handler_for(&pane, |pane, cx| { + pane.close_all_items(&CloseAllItems { save_intent: None }, cx) + .map(|task| task.detach_and_log_err(cx)); + }), + ); - if let Some(entry) = single_entry_to_resolve { - let entry_id = entry.to_proto(); - menu.separator().entry( - "Reveal In Project Panel", - Some(Box::new(RevealInProjectPanel { entry_id })), - cx.handler_for(&pane, move |pane, cx| { - pane.project.update(cx, |_, cx| { - cx.emit(project::Event::RevealInProjectPanel( - ProjectEntryId::from_proto(entry_id), - )) - }); - }), - ) - } else { - menu + if let Some(entry) = single_entry_to_resolve { + let entry_id = entry.to_proto(); + menu = menu.separator().entry( + "Reveal In Project Panel", + Some(Box::new(RevealInProjectPanel { entry_id })), + cx.handler_for(&pane, move |pane, cx| { + pane.project.update(cx, |_, cx| { + cx.emit(project::Event::RevealInProjectPanel( + ProjectEntryId::from_proto(entry_id), + )) + }); + }), + ); + } } + + menu }) }) } From 420253a75295596fb7fb9aeac025f992f428115a Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 15:32:47 +0200 Subject: [PATCH 285/644] Restore zoom buttons in pane tab bars, fix + button in the terminal one --- crates/terminal_view2/src/terminal_panel.rs | 72 +++----- crates/workspace2/src/pane.rs | 189 ++++++++------------ 2 files changed, 103 insertions(+), 158 deletions(-) diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index 3c7b2a2e0e..def56f3760 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -4,13 +4,14 @@ use crate::TerminalView; use db::kvp::KEY_VALUE_STORE; use gpui::{ actions, div, serde_json, AppContext, AsyncWindowContext, Div, Entity, EventEmitter, - ExternalPaths, FocusHandle, FocusableView, ParentElement, Render, Styled, Subscription, Task, - View, ViewContext, VisualContext, WeakView, WindowContext, + ExternalPaths, FocusHandle, FocusableView, IntoElement, ParentElement, Render, Styled, + Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use project::Fs; use serde::{Deserialize, Serialize}; use settings::{Settings, SettingsStore}; use terminal::terminal_settings::{TerminalDockPosition, TerminalSettings}; +use ui::{h_stack, ButtonCommon, Clickable, IconButton, IconSize, Selectable, Tooltip}; use util::{ResultExt, TryFutureExt}; use workspace::{ dock::{DockPosition, Panel, PanelEvent}, @@ -51,9 +52,8 @@ pub struct TerminalPanel { impl TerminalPanel { fn new(workspace: &Workspace, cx: &mut ViewContext) -> Self { - let _weak_self = cx.view().downgrade(); + let terminal_panel = cx.view().clone(); let pane = cx.build_view(|cx| { - let _window = cx.window_handle(); let mut pane = Pane::new( workspace.weak_handle(), workspace.project().clone(), @@ -74,45 +74,31 @@ impl TerminalPanel { ); pane.set_can_split(false, cx); pane.set_can_navigate(false, cx); - // todo!() - // pane.set_render_tab_bar_buttons(cx, move |pane, cx| { - // let this = weak_self.clone(); - // Flex::row() - // .with_child(Pane::render_tab_bar_button( - // 0, - // "icons/plus.svg", - // false, - // Some(("New Terminal", Some(Box::new(workspace::NewTerminal)))), - // cx, - // move |_, cx| { - // let this = this.clone(); - // cx.window_context().defer(move |cx| { - // if let Some(this) = this.upgrade() { - // this.update(cx, |this, cx| { - // this.add_terminal(None, cx); - // }); - // } - // }) - // }, - // |_, _| {}, - // None, - // )) - // .with_child(Pane::render_tab_bar_button( - // 1, - // if pane.is_zoomed() { - // "icons/minimize.svg" - // } else { - // "icons/maximize.svg" - // }, - // pane.is_zoomed(), - // Some(("Toggle Zoom".into(), Some(Box::new(workspace::ToggleZoom)))), - // cx, - // move |pane, cx| pane.toggle_zoom(&Default::default(), cx), - // |_, _| {}, - // None, - // )) - // .into_any() - // }); + pane.set_render_tab_bar_buttons(cx, move |pane, cx| { + h_stack() + .child( + IconButton::new("plus", Icon::Plus) + .icon_size(IconSize::Small) + .on_click(cx.listener_for(&terminal_panel, |terminal_panel, _, cx| { + terminal_panel.add_terminal(None, cx); + })) + .tooltip(|cx| Tooltip::text("New Terminal", cx)), + ) + .child({ + let zoomed = pane.is_zoomed(); + IconButton::new("toggle_zoom", Icon::Maximize) + .icon_size(IconSize::Small) + .selected(zoomed) + .selected_icon(Icon::Minimize) + .on_click(cx.listener(|pane, _, cx| { + pane.toggle_zoom(&workspace::ToggleZoom, cx); + })) + .tooltip(move |cx| { + Tooltip::text(if zoomed { "Zoom Out" } else { "Zoom In" }, cx) + }) + }) + .into_any_element() + }); // let buffer_search_bar = cx.build_view(search::BufferSearchBar::new); // pane.toolbar() // .update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx)); diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 911c292133..86894dee46 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -7,7 +7,7 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ - actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AppContext, + actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyElement, AppContext, AsyncWindowContext, DismissEvent, Div, DragMoveEvent, EntityId, EventEmitter, FocusHandle, Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView, @@ -21,6 +21,7 @@ use std::{ any::Any, cmp, fmt, mem, path::{Path, PathBuf}, + rc::Rc, sync::{ atomic::{AtomicUsize, Ordering}, Arc, @@ -183,7 +184,7 @@ pub struct Pane { drag_split_direction: Option, can_drop_predicate: Option bool>>, can_split: bool, - // render_tab_bar_buttons: Rc) -> AnyElement>, + render_tab_bar_buttons: Rc) -> AnyElement>, _subscriptions: Vec, tab_bar_scroll_handle: ScrollHandle, } @@ -374,63 +375,66 @@ impl Pane { project, can_drop_predicate, can_split: true, - // render_tab_bar_buttons: Rc::new(move |pane, cx| { - // Flex::row() - // // New menu - // .with_child(Self::render_tab_bar_button( - // 0, - // "icons/plus.svg", - // false, - // Some(("New...".into(), None)), - // cx, - // |pane, cx| pane.deploy_new_menu(cx), - // |pane, cx| { - // pane.tab_bar_context_menu - // .handle - // .update(cx, |menu, _| menu.delay_cancel()) - // }, - // pane.tab_bar_context_menu - // .handle_if_kind(TabBarContextMenuKind::New), - // )) - // .with_child(Self::render_tab_bar_button( - // 1, - // "icons/split.svg", - // false, - // Some(("Split Pane".into(), None)), - // cx, - // |pane, cx| pane.deploy_split_menu(cx), - // |pane, cx| { - // pane.tab_bar_context_menu - // .handle - // .update(cx, |menu, _| menu.delay_cancel()) - // }, - // pane.tab_bar_context_menu - // .handle_if_kind(TabBarContextMenuKind::Split), - // )) - // .with_child({ - // let icon_path; - // let tooltip_label; - // if pane.is_zoomed() { - // icon_path = "icons/minimize.svg"; - // tooltip_label = "Zoom In"; - // } else { - // icon_path = "icons/maximize.svg"; - // tooltip_label = "Zoom In"; - // } - - // Pane::render_tab_bar_button( - // 2, - // icon_path, - // pane.is_zoomed(), - // Some((tooltip_label, Some(Box::new(ToggleZoom)))), - // cx, - // move |pane, cx| pane.toggle_zoom(&Default::default(), cx), - // move |_, _| {}, - // None, - // ) - // }) - // .into_any() - // }), + render_tab_bar_buttons: Rc::new(move |pane, cx| { + h_stack() + .child( + IconButton::new("plus", Icon::Plus) + .icon_size(IconSize::Small) + .on_click(cx.listener(|pane, _, cx| { + let menu = ContextMenu::build(cx, |menu, _| { + menu.action("New File", NewFile.boxed_clone()) + .action("New Terminal", NewCenterTerminal.boxed_clone()) + .action("New Search", NewSearch.boxed_clone()) + }); + cx.subscribe(&menu, |pane, _, _: &DismissEvent, cx| { + pane.focus(cx); + pane.new_item_menu = None; + }) + .detach(); + pane.new_item_menu = Some(menu); + })) + .tooltip(|cx| Tooltip::text("New...", cx)), + ) + .when_some(pane.new_item_menu.as_ref(), |el, new_item_menu| { + el.child(Self::render_menu_overlay(new_item_menu)) + }) + .child( + IconButton::new("split", Icon::Split) + .icon_size(IconSize::Small) + .on_click(cx.listener(|pane, _, cx| { + let menu = ContextMenu::build(cx, |menu, _| { + menu.action("Split Right", SplitRight.boxed_clone()) + .action("Split Left", SplitLeft.boxed_clone()) + .action("Split Up", SplitUp.boxed_clone()) + .action("Split Down", SplitDown.boxed_clone()) + }); + cx.subscribe(&menu, |pane, _, _: &DismissEvent, cx| { + pane.focus(cx); + pane.split_item_menu = None; + }) + .detach(); + pane.split_item_menu = Some(menu); + })) + .tooltip(|cx| Tooltip::text("Split Pane", cx)), + ) + .child({ + let zoomed = pane.is_zoomed(); + IconButton::new("toggle_zoom", Icon::Maximize) + .icon_size(IconSize::Small) + .selected(zoomed) + .selected_icon(Icon::Minimize) + .on_click(cx.listener(|pane, _, cx| { + pane.toggle_zoom(&crate::ToggleZoom, cx); + })) + .tooltip(move |cx| { + Tooltip::text(if zoomed { "Zoom Out" } else { "Zoom In" }, cx) + }) + }) + .when_some(pane.split_item_menu.as_ref(), |el, split_item_menu| { + el.child(Self::render_menu_overlay(split_item_menu)) + }) + .into_any_element() + }), _subscriptions: subscriptions, } } @@ -510,13 +514,13 @@ impl Pane { cx.notify(); } - // pub fn set_render_tab_bar_buttons(&mut self, cx: &mut ViewContext, render: F) - // where - // F: 'static + Fn(&mut Pane, &mut ViewContext) -> AnyElement, - // { - // self.render_tab_bar_buttons = Rc::new(render); - // cx.notify(); - // } + pub fn set_render_tab_bar_buttons(&mut self, cx: &mut ViewContext, render: F) + where + F: 'static + Fn(&mut Pane, &mut ViewContext) -> AnyElement, + { + self.render_tab_bar_buttons = Rc::new(render); + cx.notify(); + } pub fn nav_history_for_item(&self, item: &View) -> ItemNavHistory { ItemNavHistory { @@ -1672,55 +1676,10 @@ impl Pane { .disabled(!self.can_navigate_forward()) .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), ) - .end_child( - div() - .child( - IconButton::new("plus", Icon::Plus) - .icon_size(IconSize::Small) - .on_click(cx.listener(|this, _, cx| { - let menu = ContextMenu::build(cx, |menu, _| { - menu.action("New File", NewFile.boxed_clone()) - .action("New Terminal", NewCenterTerminal.boxed_clone()) - .action("New Search", NewSearch.boxed_clone()) - }); - cx.subscribe(&menu, |this, _, _: &DismissEvent, cx| { - this.focus(cx); - this.new_item_menu = None; - }) - .detach(); - this.new_item_menu = Some(menu); - })) - .tooltip(|cx| Tooltip::text("New...", cx)), - ) - .when_some(self.new_item_menu.as_ref(), |el, new_item_menu| { - el.child(Self::render_menu_overlay(new_item_menu)) - }), - ) - .end_child( - div() - .child( - IconButton::new("split", Icon::Split) - .icon_size(IconSize::Small) - .on_click(cx.listener(|this, _, cx| { - let menu = ContextMenu::build(cx, |menu, _| { - menu.action("Split Right", SplitRight.boxed_clone()) - .action("Split Left", SplitLeft.boxed_clone()) - .action("Split Up", SplitUp.boxed_clone()) - .action("Split Down", SplitDown.boxed_clone()) - }); - cx.subscribe(&menu, |this, _, _: &DismissEvent, cx| { - this.focus(cx); - this.split_item_menu = None; - }) - .detach(); - this.split_item_menu = Some(menu); - })) - .tooltip(|cx| Tooltip::text("Split Pane", cx)), - ) - .when_some(self.split_item_menu.as_ref(), |el, split_item_menu| { - el.child(Self::render_menu_overlay(split_item_menu)) - }), - ) + .end_child({ + let render_tab_buttons = self.render_tab_bar_buttons.clone(); + render_tab_buttons(self, cx) + }) .children( self.items .iter() From 68cf631cfcdb07fb7adfdd25d6ea87969f8d69a0 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 14:39:16 +0100 Subject: [PATCH 286/644] Reveal item even if project panel was closed while active entry changed The project panel was actually working just fine, the problem was due to `UniformList` not re-hydrating the element state's scroll offset when being rendered again. --- crates/gpui2/src/elements/uniform_list.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index c26cfe6121..e38a37f90d 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -190,7 +190,15 @@ impl Element for UniformList { let shared_scroll_offset = element_state .interactive .scroll_offset - .get_or_insert_with(Rc::default) + .get_or_insert_with(|| { + if let Some(scroll_handle) = self.scroll_handle.as_ref() { + if let Some(scroll_handle) = scroll_handle.0.borrow().as_ref() { + return scroll_handle.scroll_offset.clone(); + } + } + + Rc::default() + }) .clone(); let item_height = self.measure_item(Some(padded_bounds.size.width), cx).height; From 2f3b4088803ccd8fcbf47b3425a7a7a39b8d03f5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 15:12:01 +0100 Subject: [PATCH 287/644] Dismiss mention notification when `x` icon is clicked We were emitting the wrong kind of event, which caused the workspace to never remove the notification. --- crates/collab_ui2/src/notification_panel.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index d9a26b4064..3ba1f0bd47 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -684,10 +684,6 @@ pub struct NotificationToast { workspace: WeakView, } -pub enum ToastEvent { - Dismiss, -} - impl NotificationToast { fn focus_notification_panel(&self, cx: &mut ViewContext) { let workspace = self.workspace.clone(); @@ -721,16 +717,15 @@ impl Render for NotificationToast { .child(Label::new(self.text.clone())) .child( IconButton::new("close", Icon::Close) - .on_click(cx.listener(|_, _, cx| cx.emit(ToastEvent::Dismiss))), + .on_click(cx.listener(|_, _, cx| cx.emit(DismissEvent))), ) .on_click(cx.listener(|this, _, cx| { this.focus_notification_panel(cx); - cx.emit(ToastEvent::Dismiss); + cx.emit(DismissEvent); })) } } -impl EventEmitter for NotificationToast {} impl EventEmitter for NotificationToast {} fn format_timestamp( From dd093477a399e699592b5c5fef84002d43e7da71 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 15:56:37 +0100 Subject: [PATCH 288/644] Allow horizontal scrolling of tab bar on vertical mouse wheel Now, if we receive a scroll event for an axis, but that axis can't be scrolled (overflow != scroll), we will apply it to the opposite axis instead if that axis supports scrolling. --- crates/gpui2/src/elements/div.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 7c74eb1039..fc129b4f1d 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -1,9 +1,10 @@ use crate::{ point, px, Action, AnyDrag, AnyElement, AnyTooltip, AnyView, AppContext, BorrowAppContext, BorrowWindow, Bounds, ClickEvent, DispatchPhase, Element, ElementId, FocusHandle, IntoElement, - KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, MouseMoveEvent, - MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent, SharedString, Size, - StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility, WindowContext, + IsZero, KeyContext, KeyDownEvent, KeyUpEvent, LayoutId, MouseButton, MouseDownEvent, + MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, Point, Render, ScrollWheelEvent, + SharedString, Size, StackingOrder, Style, StyleRefinement, Styled, Task, View, Visibility, + WindowContext, }; use collections::HashMap; @@ -1509,12 +1510,26 @@ impl Interactivity { let delta = event.delta.pixel_delta(line_height); if overflow.x == Overflow::Scroll { - scroll_offset.x = (scroll_offset.x + delta.x) + let mut delta_x = Pixels::ZERO; + if !delta.x.is_zero() { + delta_x = delta.x; + } else if overflow.y != Overflow::Scroll { + delta_x = delta.y; + } + + scroll_offset.x = (scroll_offset.x + delta_x) .clamp(-scroll_max.width, px(0.)); } if overflow.y == Overflow::Scroll { - scroll_offset.y = (scroll_offset.y + delta.y) + let mut delta_y = Pixels::ZERO; + if !delta.y.is_zero() { + delta_y = delta.y; + } else if overflow.x != Overflow::Scroll { + delta_y = delta.x; + } + + scroll_offset.y = (scroll_offset.y + delta_y) .clamp(-scroll_max.height, px(0.)); } From 5de32f7b0b7063a55b41f93b51de6915700c37bf Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 18:06:23 +0200 Subject: [PATCH 289/644] Do not display a getting start message when the project is open --- crates/workspace2/src/pane.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 86894dee46..7128288e7b 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1930,7 +1930,8 @@ impl Render for Pane { }), ) .child(self.render_tab_bar(cx)) - .child( + .child({ + let has_worktrees = self.project.read(cx).worktrees().next().is_some(); // main content div() .flex_1() @@ -1944,10 +1945,15 @@ impl Render for Pane { .child(self.toolbar.clone()) .child(item.to_any()) } else { - div.h_flex().size_full().justify_center().child( - Label::new("Open a file or project to get started.") - .color(Color::Muted), - ) + let placeholder = div.h_flex().size_full().justify_center(); + if has_worktrees { + placeholder + } else { + placeholder.child( + Label::new("Open a file or project to get started.") + .color(Color::Muted), + ) + } } }) .child( @@ -1984,8 +1990,8 @@ impl Render for Pane { div.top_0().bottom_0().right_0().w_32() } }), - ), - ) + ) + }) .on_mouse_down( MouseButton::Navigate(NavigationDirection::Back), cx.listener(|pane, _, cx| { From dc1ed3c39d27dc1689f2565665c2d436e38db8d9 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 22 Dec 2023 17:18:12 +0100 Subject: [PATCH 290/644] Titlebar project menu double click (#3784) This addresses a bug where popover menus in the titlebar were rendered only after a 2nd click. The first click was creating the View which the second one then rendered. In addition to this, `PopoverMenu::menu` function argument can now return an `Option>` instead of `View` as the creation of the menu can fail (as it might in case of git popover). Release Notes: - N/A --- crates/collab_ui2/src/collab_titlebar_item.rs | 97 +++++-------------- crates/copilot_button2/src/copilot_button.rs | 6 +- crates/language_tools2/src/lsp_log.rs | 1 + .../language_tools2/src/syntax_tree_view.rs | 1 + .../recent_projects2/src/recent_projects.rs | 78 ++++++--------- crates/ui2/src/components/popover_menu.rs | 10 +- 6 files changed, 67 insertions(+), 126 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index e4a6ff089a..75c4cc5263 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -18,7 +18,7 @@ use ui::{ }; use util::ResultExt; use vcs_menu::{build_branch_list, BranchList, OpenRecent as ToggleVcsMenu}; -use workspace::{notifications::NotifyResultExt, Workspace, WORKSPACE_DB}; +use workspace::{notifications::NotifyResultExt, Workspace}; const MAX_PROJECT_NAME_LENGTH: usize = 40; const MAX_BRANCH_NAME_LENGTH: usize = 40; @@ -52,8 +52,6 @@ pub struct CollabTitlebarItem { user_store: Model, client: Arc, workspace: WeakView, - branch_popover: Option<(View, Subscription)>, - project_popover: Option<(View, Subscription)>, _subscriptions: Vec, } @@ -291,8 +289,6 @@ impl CollabTitlebarItem { project, user_store, client, - branch_popover: None, - project_popover: None, _subscriptions: subscriptions, } } @@ -329,22 +325,15 @@ impl CollabTitlebarItem { }; let name = util::truncate_and_trailoff(name, MAX_PROJECT_NAME_LENGTH); + let workspace = self.workspace.clone(); popover_menu("project_name_trigger") .trigger( Button::new("project_name_trigger", name) .style(ButtonStyle::Subtle) .label_size(LabelSize::Small) - .tooltip(move |cx| Tooltip::text("Recent Projects", cx)) - .on_click(cx.listener(|this, _, cx| { - this.toggle_project_menu(&ToggleProjectMenu, cx); - })), - ) - .when_some( - self.project_popover - .as_ref() - .map(|(project, _)| project.clone()), - |this, project| this.menu(move |_| project.clone()), + .tooltip(move |cx| Tooltip::text("Recent Projects", cx)), ) + .menu(move |cx| Some(Self::render_project_popover(workspace.clone(), cx))) } pub fn render_project_branch(&self, cx: &mut ViewContext) -> Option { @@ -357,7 +346,7 @@ impl CollabTitlebarItem { names_and_branches.next().flatten() }; - + let workspace = self.workspace.upgrade()?; let branch_name = entry .as_ref() .and_then(RepositoryEntry::branch) @@ -376,17 +365,9 @@ impl CollabTitlebarItem { "Local branches only", cx, ) - }) - .on_click(cx.listener(|this, _, cx| { - this.toggle_vcs_menu(&ToggleVcsMenu, cx); - })), + }), ) - .when_some( - self.branch_popover - .as_ref() - .map(|(branch, _)| branch.clone()), - |this, branch| this.menu(move |_| branch.clone()), - ), + .menu(move |cx| Self::render_vcs_popover(workspace.clone(), cx)), ) } @@ -462,55 +443,25 @@ impl CollabTitlebarItem { .log_err(); } - pub fn toggle_vcs_menu(&mut self, _: &ToggleVcsMenu, cx: &mut ViewContext) { - if self.branch_popover.take().is_none() { - if let Some(workspace) = self.workspace.upgrade() { - let Some(view) = build_branch_list(workspace, cx).log_err() else { - return; - }; - self.project_popover.take(); - let focus_handle = view.focus_handle(cx); - cx.focus(&focus_handle); - let subscription = cx.subscribe(&view, |this, _, _, _| { - this.branch_popover.take(); - }); - self.branch_popover = Some((view, subscription)); - } - } - - cx.notify(); + pub fn render_vcs_popover( + workspace: View, + cx: &mut WindowContext<'_>, + ) -> Option> { + let view = build_branch_list(workspace, cx).log_err()?; + let focus_handle = view.focus_handle(cx); + cx.focus(&focus_handle); + Some(view) } - pub fn toggle_project_menu(&mut self, _: &ToggleProjectMenu, cx: &mut ViewContext) { - if self.project_popover.take().is_none() { - let workspace = self.workspace.clone(); - cx.spawn(|this, mut cx| async move { - let workspaces = WORKSPACE_DB - .recent_workspaces_on_disk() - .await - .unwrap_or_default() - .into_iter() - .map(|(_, location)| location) - .collect(); + pub fn render_project_popover( + workspace: WeakView, + cx: &mut WindowContext<'_>, + ) -> View { + let view = RecentProjects::open_popover(workspace, cx); - let workspace = workspace.clone(); - this.update(&mut cx, move |this, cx| { - let view = RecentProjects::open_popover(workspace, workspaces, cx); - - let focus_handle = view.focus_handle(cx); - cx.focus(&focus_handle); - this.branch_popover.take(); - let subscription = cx.subscribe(&view, |this, _, _, _| { - this.project_popover.take(); - }); - this.project_popover = Some((view, subscription)); - cx.notify(); - }) - .log_err(); - }) - .detach(); - } - cx.notify(); + let focus_handle = view.focus_handle(cx); + cx.focus(&focus_handle); + view } fn render_connection_status( @@ -587,6 +538,7 @@ impl CollabTitlebarItem { .action("Share Feedback", feedback::GiveFeedback.boxed_clone()) .action("Sign Out", client::SignOut.boxed_clone()) }) + .into() }) .trigger( ButtonLike::new("user-menu") @@ -609,6 +561,7 @@ impl CollabTitlebarItem { .separator() .action("Share Feedback", feedback::GiveFeedback.boxed_clone()) }) + .into() }) .trigger( ButtonLike::new("user-menu") diff --git a/crates/copilot_button2/src/copilot_button.rs b/crates/copilot_button2/src/copilot_button.rs index 7cd2b09db8..d3a1c1e58c 100644 --- a/crates/copilot_button2/src/copilot_button.rs +++ b/crates/copilot_button2/src/copilot_button.rs @@ -102,8 +102,10 @@ impl Render for CopilotButton { div().child( popover_menu("copilot") .menu(move |cx| match status { - Status::Authorized => this.update(cx, |this, cx| this.build_copilot_menu(cx)), - _ => this.update(cx, |this, cx| this.build_copilot_start_menu(cx)), + Status::Authorized => { + Some(this.update(cx, |this, cx| this.build_copilot_menu(cx))) + } + _ => Some(this.update(cx, |this, cx| this.build_copilot_start_menu(cx))), }) .anchor(AnchorCorner::BottomRight) .trigger( diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 973cd9c355..310726e4a5 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -828,6 +828,7 @@ impl Render for LspLogToolbarItemView { } menu }) + .into() }); h_stack().size_full().child(lsp_menu).child( diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index c9a621f967..e4ee4b0cfb 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -467,6 +467,7 @@ impl SyntaxTreeToolbarItemView { } menu }) + .into() }), ) } diff --git a/crates/recent_projects2/src/recent_projects.rs b/crates/recent_projects2/src/recent_projects.rs index 1a38a5c200..2d6f4bf0e3 100644 --- a/crates/recent_projects2/src/recent_projects.rs +++ b/crates/recent_projects2/src/recent_projects.rs @@ -12,10 +12,7 @@ use picker::{Picker, PickerDelegate}; use std::sync::Arc; use ui::{prelude::*, ListItem, ListItemSpacing}; use util::paths::PathExt; -use workspace::{ - notifications::simple_message_notification::MessageNotification, ModalView, Workspace, - WorkspaceLocation, WORKSPACE_DB, -}; +use workspace::{ModalView, Workspace, WorkspaceLocation, WORKSPACE_DB}; pub use projects::OpenRecent; @@ -35,6 +32,25 @@ impl RecentProjects { fn new(delegate: RecentProjectsDelegate, rem_width: f32, cx: &mut ViewContext) -> Self { let picker = cx.build_view(|cx| Picker::new(delegate, cx)); let _subscription = cx.subscribe(&picker, |_, _, _, cx| cx.emit(DismissEvent)); + // We do not want to block the UI on a potentially lenghty call to DB, so we're gonna swap + // out workspace locations once the future runs to completion. + cx.spawn(|this, mut cx| async move { + let workspaces = WORKSPACE_DB + .recent_workspaces_on_disk() + .await + .unwrap_or_default() + .into_iter() + .map(|(_, location)| location) + .collect(); + this.update(&mut cx, move |this, cx| { + this.picker.update(cx, move |picker, cx| { + picker.delegate.workspace_locations = workspaces; + picker.update_matches(picker.query(cx), cx) + }) + }) + .ok() + }) + .detach(); Self { picker, rem_width, @@ -61,50 +77,20 @@ impl RecentProjects { fn open(_: &mut Workspace, cx: &mut ViewContext) -> Option>> { Some(cx.spawn(|workspace, mut cx| async move { - let workspace_locations: Vec<_> = cx - .background_executor() - .spawn(async { - WORKSPACE_DB - .recent_workspaces_on_disk() - .await - .unwrap_or_default() - .into_iter() - .map(|(_, location)| location) - .collect() - }) - .await; - workspace.update(&mut cx, |workspace, cx| { - if !workspace_locations.is_empty() { - let weak_workspace = cx.view().downgrade(); - workspace.toggle_modal(cx, |cx| { - let delegate = - RecentProjectsDelegate::new(weak_workspace, workspace_locations, true); + let weak_workspace = cx.view().downgrade(); + workspace.toggle_modal(cx, |cx| { + let delegate = RecentProjectsDelegate::new(weak_workspace, true); - let modal = RecentProjects::new(delegate, 34., cx); - modal - }); - } else { - workspace.show_notification(0, cx, |cx| { - cx.build_view(|_| MessageNotification::new("No recent projects to open.")) - }) - } + let modal = RecentProjects::new(delegate, 34., cx); + modal + }); })?; Ok(()) })) } - pub fn open_popover( - workspace: WeakView, - workspaces: Vec, - cx: &mut WindowContext<'_>, - ) -> View { - cx.build_view(|cx| { - Self::new( - RecentProjectsDelegate::new(workspace, workspaces, false), - 20., - cx, - ) - }) + pub fn open_popover(workspace: WeakView, cx: &mut WindowContext<'_>) -> View { + cx.build_view(|cx| Self::new(RecentProjectsDelegate::new(workspace, false), 20., cx)) } } @@ -140,14 +126,10 @@ pub struct RecentProjectsDelegate { } impl RecentProjectsDelegate { - fn new( - workspace: WeakView, - workspace_locations: Vec, - render_paths: bool, - ) -> Self { + fn new(workspace: WeakView, render_paths: bool) -> Self { Self { workspace, - workspace_locations, + workspace_locations: vec![], selected_match_index: 0, matches: Default::default(), render_paths, diff --git a/crates/ui2/src/components/popover_menu.rs b/crates/ui2/src/components/popover_menu.rs index 0f2fa6d23f..1a02dd526e 100644 --- a/crates/ui2/src/components/popover_menu.rs +++ b/crates/ui2/src/components/popover_menu.rs @@ -18,19 +18,19 @@ pub struct PopoverMenu { Box< dyn FnOnce( Rc>>>, - Option View + 'static>>, + Option Option> + 'static>>, ) -> AnyElement + 'static, >, >, - menu_builder: Option View + 'static>>, + menu_builder: Option Option> + 'static>>, anchor: AnchorCorner, attach: Option, offset: Option>, } impl PopoverMenu { - pub fn menu(mut self, f: impl Fn(&mut WindowContext) -> View + 'static) -> Self { + pub fn menu(mut self, f: impl Fn(&mut WindowContext) -> Option> + 'static) -> Self { self.menu_builder = Some(Rc::new(f)); self } @@ -42,7 +42,9 @@ impl PopoverMenu { .when_some(builder, |el, builder| { el.on_click({ move |_, cx| { - let new_menu = (builder)(cx); + let Some(new_menu) = (builder)(cx) else { + return; + }; let menu2 = menu.clone(); let previous_focus_handle = cx.focused(); From a03306fd01bbc4989f03a31127d97901dcb8ecf8 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 18:37:24 +0200 Subject: [PATCH 291/644] Fix enter, tab and shift-tab behavior in project search 2 --- crates/search2/src/project_search.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 3e245ed72d..bc23f67567 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -1730,12 +1730,15 @@ impl Render for ProjectSearchBar { .on_action(cx.listener(|this, _: &ActivateSemanticMode, cx| { this.activate_search_mode(SearchMode::Semantic, cx) })) - .on_action(cx.listener(|this, action, cx| { + .capture_action(cx.listener(|this, action, cx| { this.tab(action, cx); + cx.stop_propagation(); })) - .on_action(cx.listener(|this, action, cx| { + .capture_action(cx.listener(|this, action, cx| { this.tab_previous(action, cx); + cx.stop_propagation(); })) + .on_action(cx.listener(|this, action, cx| this.confirm(action, cx))) .on_action(cx.listener(|this, action, cx| { this.cycle_mode(action, cx); })) From 2f4cedbd5306427c3807cf6bde12fde97b89f1e9 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 18:43:57 +0200 Subject: [PATCH 292/644] Remove the old code --- crates/search2/src/project_search.rs | 308 --------------------------- 1 file changed, 308 deletions(-) diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index bc23f67567..9a654c9bf4 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -1827,314 +1827,6 @@ impl Render for ProjectSearchBar { }) } } -// impl Entity for ProjectSearchBar { -// type Event = (); -// } - -// impl View for ProjectSearchBar { -// fn ui_name() -> &'static str { -// "ProjectSearchBar" -// } - -// fn update_keymap_context( -// &self, -// keymap: &mut gpui::keymap_matcher::KeymapContext, -// cx: &AppContext, -// ) { -// Self::reset_to_default_keymap_context(keymap); -// let in_replace = self -// .active_project_search -// .as_ref() -// .map(|search| { -// search -// .read(cx) -// .replacement_editor -// .read_with(cx, |_, cx| cx.is_self_focused()) -// }) -// .flatten() -// .unwrap_or(false); -// if in_replace { -// keymap.add_identifier("in_replace"); -// } -// } - -// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { -// if let Some(_search) = self.active_project_search.as_ref() { -// let search = _search.read(cx); -// let theme = theme::current(cx).clone(); -// let query_container_style = if search.panels_with_errors.contains(&InputPanel::Query) { -// theme.search.invalid_editor -// } else { -// theme.search.editor.input.container -// }; - -// let search = _search.read(cx); -// let filter_button = render_option_button_icon( -// search.filters_enabled, -// "icons/filter.svg", -// 0, -// "Toggle filters", -// Box::new(ToggleFilters), -// move |_, this, cx| { -// this.toggle_filters(cx); -// }, -// cx, -// ); - -// let search = _search.read(cx); -// let is_semantic_available = SemanticIndex::enabled(cx); -// let is_semantic_disabled = search.semantic_state.is_none(); -// let icon_style = theme.search.editor_icon.clone(); -// let is_active = search.active_match_index.is_some(); - -// let render_option_button_icon = |path, option, cx: &mut ViewContext| { -// crate::search_bar::render_option_button_icon( -// self.is_option_enabled(option, cx), -// path, -// option.bits as usize, -// format!("Toggle {}", option.label()), -// option.to_toggle_action(), -// move |_, this, cx| { -// this.toggle_search_option(option, cx); -// }, -// cx, -// ) -// }; -// let case_sensitive = is_semantic_disabled.then(|| { -// render_option_button_icon( -// "icons/case_insensitive.svg", -// SearchOptions::CASE_SENSITIVE, -// cx, -// ) -// }); - -// let whole_word = is_semantic_disabled.then(|| { -// render_option_button_icon("icons/word_search.svg", SearchOptions::WHOLE_WORD, cx) -// }); - -// let include_ignored = is_semantic_disabled.then(|| { -// render_option_button_icon( -// "icons/file_icons/git.svg", -// SearchOptions::INCLUDE_IGNORED, -// cx, -// ) -// }); - -// let search_button_for_mode = |mode, side, cx: &mut ViewContext| { -// let is_active = if let Some(search) = self.active_project_search.as_ref() { -// let search = search.read(cx); -// search.current_mode == mode -// } else { -// false -// }; -// render_search_mode_button( -// mode, -// side, -// is_active, -// move |_, this, cx| { -// this.activate_search_mode(mode, cx); -// }, -// cx, -// ) -// }; - -// let search = _search.read(cx); - -// let include_container_style = -// if search.panels_with_errors.contains(&InputPanel::Include) { -// theme.search.invalid_include_exclude_editor -// } else { -// theme.search.include_exclude_editor.input.container -// }; - -// let exclude_container_style = -// if search.panels_with_errors.contains(&InputPanel::Exclude) { -// theme.search.invalid_include_exclude_editor -// } else { -// theme.search.include_exclude_editor.input.container -// }; - -// let matches = search.active_match_index.map(|match_ix| { -// Label::new( -// format!( -// "{}/{}", -// match_ix + 1, -// search.model.read(cx).match_ranges.len() -// ), -// theme.search.match_index.text.clone(), -// ) -// .contained() -// .with_style(theme.search.match_index.container) -// .aligned() -// }); -// let should_show_replace_input = search.replace_enabled; -// let replacement = should_show_replace_input.then(|| { -// Flex::row() -// .with_child( -// Svg::for_style(theme.search.replace_icon.clone().icon) -// .contained() -// .with_style(theme.search.replace_icon.clone().container), -// ) -// .with_child(ChildView::new(&search.replacement_editor, cx).flex(1., true)) -// .align_children_center() -// .flex(1., true) -// .contained() -// .with_style(query_container_style) -// .constrained() -// .with_min_width(theme.search.editor.min_width) -// .with_max_width(theme.search.editor.max_width) -// .with_height(theme.search.search_bar_row_height) -// .flex(1., false) -// }); -// let replace_all = should_show_replace_input.then(|| { -// super::replace_action( -// ReplaceAll, -// "Replace all", -// "icons/replace_all.svg", -// theme.tooltip.clone(), -// theme.search.action_button.clone(), -// ) -// }); -// let replace_next = should_show_replace_input.then(|| { -// super::replace_action( -// ReplaceNext, -// "Replace next", -// "icons/replace_next.svg", -// theme.tooltip.clone(), -// theme.search.action_button.clone(), -// ) -// }); -// let query_column = Flex::column() -// .with_spacing(theme.search.search_row_spacing) -// .with_child( -// Flex::row() -// .with_child( -// Svg::for_style(icon_style.icon) -// .contained() -// .with_style(icon_style.container), -// ) -// .with_child(ChildView::new(&search.query_editor, cx).flex(1., true)) -// .with_child( -// Flex::row() -// .with_child(filter_button) -// .with_children(case_sensitive) -// .with_children(whole_word) -// .flex(1., false) -// .constrained() -// .contained(), -// ) -// .align_children_center() -// .contained() -// .with_style(query_container_style) -// .constrained() -// .with_min_width(theme.search.editor.min_width) -// .with_max_width(theme.search.editor.max_width) -// .with_height(theme.search.search_bar_row_height) -// .flex(1., false), -// ) -// .with_children(search.filters_enabled.then(|| { -// Flex::row() -// .with_child( -// Flex::row() -// .with_child( -// ChildView::new(&search.included_files_editor, cx) -// .contained() -// .constrained() -// .with_height(theme.search.search_bar_row_height) -// .flex(1., true), -// ) -// .with_children(include_ignored) -// .contained() -// .with_style(include_container_style) -// .constrained() -// .with_height(theme.search.search_bar_row_height) -// .flex(1., true), -// ) -// .with_child( -// ChildView::new(&search.excluded_files_editor, cx) -// .contained() -// .with_style(exclude_container_style) -// .constrained() -// .with_height(theme.search.search_bar_row_height) -// .flex(1., true), -// ) -// .constrained() -// .with_min_width(theme.search.editor.min_width) -// .with_max_width(theme.search.editor.max_width) -// .flex(1., false) -// })) -// .flex(1., false); -// let switches_column = Flex::row() -// .align_children_center() -// .with_child(super::toggle_replace_button( -// search.replace_enabled, -// theme.tooltip.clone(), -// theme.search.option_button_component.clone(), -// )) -// .constrained() -// .with_height(theme.search.search_bar_row_height) -// .contained() -// .with_style(theme.search.option_button_group); -// let mode_column = -// Flex::row() -// .with_child(search_button_for_mode( -// SearchMode::Text, -// Some(Side::Left), -// cx, -// )) -// .with_child(search_button_for_mode( -// SearchMode::Regex, -// if is_semantic_available { -// None -// } else { -// Some(Side::Right) -// }, -// cx, -// )) -// .with_children(is_semantic_available.then(|| { -// search_button_for_mode(SearchMode::Semantic, Some(Side::Right), cx) -// })) -// .contained() -// .with_style(theme.search.modes_container); - -// let nav_button_for_direction = |label, direction, cx: &mut ViewContext| { -// render_nav_button( -// label, -// direction, -// is_active, -// move |_, this, cx| { -// if let Some(search) = this.active_project_search.as_ref() { -// search.update(cx, |search, cx| search.select_match(direction, cx)); -// } -// }, -// cx, -// ) -// }; - -// let nav_column = Flex::row() -// .with_children(replace_next) -// .with_children(replace_all) -// .with_child(Flex::row().with_children(matches)) -// .with_child(nav_button_for_direction("<", Direction::Prev, cx)) -// .with_child(nav_button_for_direction(">", Direction::Next, cx)) -// .constrained() -// .with_height(theme.search.search_bar_row_height) -// .flex_float(); - -// Flex::row() -// .with_child(query_column) -// .with_child(mode_column) -// .with_child(switches_column) -// .with_children(replacement) -// .with_child(nav_column) -// .contained() -// .with_style(theme.search.container) -// .into_any_named("project search") -// } else { -// Empty::new().into_any() -// } -// } -// } impl EventEmitter for ProjectSearchBar {} From 54e45306c59d33d44e045bbf44d9c42d9427a2df Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 18:00:03 +0100 Subject: [PATCH 293/644] Fix resizing for bottom dock We were not using `flex` on the `PaneGroup`, which caused the bottom dock to be unable to satisfy the desired resize value. --- crates/workspace2/src/pane_group.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index 06bd506e56..800d03a50c 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -242,6 +242,7 @@ impl Member { div() .relative() + .flex_1() .size_full() .child(pane.clone()) .when_some(leader_border, |this, color| { @@ -778,6 +779,9 @@ mod element { cx: &mut ui::prelude::WindowContext, ) -> (gpui::LayoutId, Self::State) { let mut style = Style::default(); + style.flex_grow = 1.; + style.flex_shrink = 1.; + style.flex_basis = relative(0.).into(); style.size.width = relative(1.).into(); style.size.height = relative(1.).into(); let layout_id = cx.request_layout(&style, None); From 25a5eda76f2b66873d80403a97e067f2ad70a24b Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Fri, 22 Dec 2023 18:10:59 +0100 Subject: [PATCH 294/644] picker: Reintroduce headers and footers (#3786) Update VCS menu to match Zed1. image Release Notes: - N/A --- crates/picker2/src/picker2.rs | 15 +++- crates/vcs_menu2/src/lib.rs | 163 +++++++++++++++------------------- 2 files changed, 86 insertions(+), 92 deletions(-) diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index aa88d70dc4..8585d9e73b 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -1,8 +1,8 @@ use editor::Editor; use gpui::{ - div, prelude::*, uniform_list, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, - FocusableView, Length, MouseButton, MouseDownEvent, Render, Task, UniformListScrollHandle, - View, ViewContext, WindowContext, + div, prelude::*, uniform_list, AnyElement, AppContext, DismissEvent, Div, EventEmitter, + FocusHandle, FocusableView, Length, MouseButton, MouseDownEvent, Render, Task, + UniformListScrollHandle, View, ViewContext, WindowContext, }; use std::{cmp, sync::Arc}; use ui::{prelude::*, v_stack, Color, Divider, Label, ListItem, ListItemSpacing}; @@ -40,6 +40,12 @@ pub trait PickerDelegate: Sized + 'static { selected: bool, cx: &mut ViewContext>, ) -> Option; + fn render_header(&self, _: &mut ViewContext>) -> Option { + None + } + fn render_footer(&self, _: &mut ViewContext>) -> Option { + None + } } impl FocusableView for Picker { @@ -253,6 +259,7 @@ impl Render for Picker { v_stack() .flex_grow() .py_2() + .children(self.delegate.render_header(cx)) .child( uniform_list( cx.view().clone(), @@ -286,6 +293,7 @@ impl Render for Picker { ) .track_scroll(self.scroll_handle.clone()) ) + .max_h_72() .overflow_hidden(), ) @@ -301,5 +309,6 @@ impl Render for Picker { ), ) }) + .children(self.delegate.render_footer(cx)) } } diff --git a/crates/vcs_menu2/src/lib.rs b/crates/vcs_menu2/src/lib.rs index cece283d4e..497ea1a012 100644 --- a/crates/vcs_menu2/src/lib.rs +++ b/crates/vcs_menu2/src/lib.rs @@ -2,13 +2,16 @@ use anyhow::{anyhow, bail, Result}; use fs::repository::Branch; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, rems, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, - InteractiveElement, ParentElement, Render, SharedString, Styled, Subscription, Task, View, - ViewContext, VisualContext, WindowContext, + actions, rems, AnyElement, AppContext, DismissEvent, Div, Element, EventEmitter, FocusHandle, + FocusableView, InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, + Subscription, Task, View, ViewContext, VisualContext, WindowContext, }; use picker::{Picker, PickerDelegate}; -use std::sync::Arc; -use ui::{v_stack, HighlightedLabel, ListItem, ListItemSpacing, Selectable}; +use std::{ops::Not, sync::Arc}; +use ui::{ + h_stack, v_stack, Button, ButtonCommon, Clickable, HighlightedLabel, Label, LabelCommon, + LabelSize, ListItem, ListItemSpacing, Selectable, +}; use util::ResultExt; use workspace::{ModalView, Toast, Workspace}; @@ -288,88 +291,70 @@ impl PickerDelegate for BranchListDelegate { .start_slot(HighlightedLabel::new(shortened_branch_name, highlights)), ) } - // fn render_header( - // &self, - // cx: &mut ViewContext>, - // ) -> Option>> { - // let theme = &theme::current(cx); - // let style = theme.picker.header.clone(); - // let label = if self.last_query.is_empty() { - // Flex::row() - // .with_child(Label::new("Recent branches", style.label.clone())) - // .contained() - // .with_style(style.container) - // } else { - // Flex::row() - // .with_child(Label::new("Branches", style.label.clone())) - // .with_children(self.matches.is_empty().not().then(|| { - // let suffix = if self.matches.len() == 1 { "" } else { "es" }; - // Label::new( - // format!("{} match{}", self.matches.len(), suffix), - // style.label, - // ) - // .flex_float() - // })) - // .contained() - // .with_style(style.container) - // }; - // Some(label.into_any()) - // } - // fn render_footer( - // &self, - // cx: &mut ViewContext>, - // ) -> Option>> { - // if !self.last_query.is_empty() { - // let theme = &theme::current(cx); - // let style = theme.picker.footer.clone(); - // enum BranchCreateButton {} - // Some( - // Flex::row().with_child(MouseEventHandler::new::(0, cx, |state, _| { - // let style = style.style_for(state); - // Label::new("Create branch", style.label.clone()) - // .contained() - // .with_style(style.container) - // }) - // .with_cursor_style(CursorStyle::PointingHand) - // .on_down(MouseButton::Left, |_, _, cx| { - // cx.spawn(|picker, mut cx| async move { - // picker.update(&mut cx, |this, cx| { - // let project = this.delegate().workspace.read(cx).project().read(cx); - // let current_pick = &this.delegate().last_query; - // let mut cwd = project - // .visible_worktrees(cx) - // .next() - // .ok_or_else(|| anyhow!("There are no visisible worktrees."))? - // .read(cx) - // .abs_path() - // .to_path_buf(); - // cwd.push(".git"); - // let repo = project - // .fs() - // .open_repo(&cwd) - // .ok_or_else(|| anyhow!("Could not open repository at path `{}`", cwd.as_os_str().to_string_lossy()))?; - // let repo = repo - // .lock(); - // let status = repo - // .create_branch(¤t_pick); - // if status.is_err() { - // this.delegate().display_error_toast(format!("Failed to create branch '{current_pick}', check for conflicts or unstashed files"), cx); - // status?; - // } - // let status = repo.change_branch(¤t_pick); - // if status.is_err() { - // this.delegate().display_error_toast(format!("Failed to chec branch '{current_pick}', check for conflicts or unstashed files"), cx); - // status?; - // } - // cx.emit(PickerEvent::Dismiss); - // Ok::<(), anyhow::Error>(()) - // }) - // }).detach(); - // })).aligned().right() - // .into_any(), - // ) - // } else { - // None - // } - // } + fn render_header(&self, _: &mut ViewContext>) -> Option { + let label = if self.last_query.is_empty() { + h_stack() + .ml_3() + .child(Label::new("Recent branches").size(LabelSize::Small)) + } else { + let match_label = self.matches.is_empty().not().then(|| { + let suffix = if self.matches.len() == 1 { "" } else { "es" }; + Label::new(format!("{} match{}", self.matches.len(), suffix)).size(LabelSize::Small) + }); + h_stack() + .px_3() + .h_full() + .justify_between() + .child(Label::new("Branches").size(LabelSize::Small)) + .children(match_label) + }; + Some(label.into_any()) + } + fn render_footer(&self, cx: &mut ViewContext>) -> Option { + if self.last_query.is_empty() { + return None; + } + + Some( + h_stack().mr_3().pb_2().child(h_stack().w_full()).child( + Button::new("branch-picker-create-branch-button", "Create branch").on_click( + cx.listener(|_, _, cx| { + cx.spawn(|picker, mut cx| async move { + picker.update(&mut cx, |this, cx| { + let project = this.delegate.workspace.read(cx).project().read(cx); + let current_pick = &this.delegate.last_query; + let mut cwd = project + .visible_worktrees(cx) + .next() + .ok_or_else(|| anyhow!("There are no visisible worktrees."))? + .read(cx) + .abs_path() + .to_path_buf(); + cwd.push(".git"); + let repo = project + .fs() + .open_repo(&cwd) + .ok_or_else(|| anyhow!("Could not open repository at path `{}`", cwd.as_os_str().to_string_lossy()))?; + let repo = repo + .lock(); + let status = repo + .create_branch(¤t_pick); + if status.is_err() { + this.delegate.display_error_toast(format!("Failed to create branch '{current_pick}', check for conflicts or unstashed files"), cx); + status?; + } + let status = repo.change_branch(¤t_pick); + if status.is_err() { + this.delegate.display_error_toast(format!("Failed to chec branch '{current_pick}', check for conflicts or unstashed files"), cx); + status?; + } + this.cancel(&Default::default(), cx); + Ok::<(), anyhow::Error>(()) + }) + + }).detach_and_log_err(cx); + }), + ).style(ui::ButtonStyle::Filled)).into_any_element(), + ) + } } From 3715ddfa74b08c82e0aad95802b0e2151a562526 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 18:26:33 +0100 Subject: [PATCH 295/644] Use `Pixels` instead of `f32` for panel size --- crates/assistant2/src/assistant_panel.rs | 8 ++-- crates/assistant2/src/assistant_settings.rs | 5 +- crates/collab_ui2/src/chat_panel.rs | 8 ++-- crates/collab_ui2/src/collab_panel.rs | 12 ++--- crates/collab_ui2/src/notification_panel.rs | 8 ++-- crates/collab_ui2/src/panel_settings.rs | 7 +-- crates/project_panel2/src/project_panel.rs | 20 ++++---- .../src/project_panel_settings.rs | 3 +- crates/terminal2/src/terminal_settings.rs | 4 +- crates/terminal_view2/src/terminal_panel.rs | 14 +++--- crates/workspace2/src/dock.rs | 46 +++++++++---------- crates/workspace2/src/workspace2.rs | 6 +-- 12 files changed, 69 insertions(+), 72 deletions(-) diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index 84576c5262..bcfb5f0fbc 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -84,8 +84,8 @@ pub fn init(cx: &mut AppContext) { pub struct AssistantPanel { workspace: WeakView, - width: Option, - height: Option, + width: Option, + height: Option, active_editor_index: Option, prev_active_editor_index: Option, editors: Vec>, @@ -1242,7 +1242,7 @@ impl Panel for AssistantPanel { }); } - fn size(&self, cx: &WindowContext) -> f32 { + fn size(&self, cx: &WindowContext) -> Pixels { let settings = AssistantSettings::get_global(cx); match self.position(cx) { DockPosition::Left | DockPosition::Right => { @@ -1252,7 +1252,7 @@ impl Panel for AssistantPanel { } } - fn set_size(&mut self, size: Option, cx: &mut ViewContext) { + fn set_size(&mut self, size: Option, cx: &mut ViewContext) { match self.position(cx) { DockPosition::Left | DockPosition::Right => self.width = size, DockPosition::Bottom => self.height = size, diff --git a/crates/assistant2/src/assistant_settings.rs b/crates/assistant2/src/assistant_settings.rs index 5a727df621..c0fbc74e9a 100644 --- a/crates/assistant2/src/assistant_settings.rs +++ b/crates/assistant2/src/assistant_settings.rs @@ -1,4 +1,5 @@ use anyhow; +use gpui::Pixels; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::Settings; @@ -51,8 +52,8 @@ pub enum AssistantDockPosition { pub struct AssistantSettings { pub button: bool, pub dock: AssistantDockPosition, - pub default_width: f32, - pub default_height: f32, + pub default_width: Pixels, + pub default_height: Pixels, pub default_open_ai_model: OpenAIModel, } diff --git a/crates/collab_ui2/src/chat_panel.rs b/crates/collab_ui2/src/chat_panel.rs index 108d53b072..03e9cfbb4a 100644 --- a/crates/collab_ui2/src/chat_panel.rs +++ b/crates/collab_ui2/src/chat_panel.rs @@ -51,7 +51,7 @@ pub struct ChatPanel { input_editor: View, local_timezone: UtcOffset, fs: Arc, - width: Option, + width: Option, active: bool, pending_serialization: Task>, subscriptions: Vec, @@ -62,7 +62,7 @@ pub struct ChatPanel { #[derive(Serialize, Deserialize)] struct SerializedChatPanel { - width: Option, + width: Option, } #[derive(Debug)] @@ -584,12 +584,12 @@ impl Panel for ChatPanel { }); } - fn size(&self, cx: &gpui::WindowContext) -> f32 { + fn size(&self, cx: &gpui::WindowContext) -> Pixels { self.width .unwrap_or_else(|| ChatPanelSettings::get_global(cx).default_width) } - fn set_size(&mut self, size: Option, cx: &mut ViewContext) { + fn set_size(&mut self, size: Option, cx: &mut ViewContext) { self.width = size; self.serialize(cx); cx.notify(); diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 3f0115e3fc..8fd90af45b 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2314,15 +2314,13 @@ impl Panel for CollabPanel { ); } - fn size(&self, cx: &gpui::WindowContext) -> f32 { - self.width.map_or_else( - || CollaborationPanelSettings::get_global(cx).default_width, - |width| width.0, - ) + fn size(&self, cx: &gpui::WindowContext) -> Pixels { + self.width + .unwrap_or_else(|| CollaborationPanelSettings::get_global(cx).default_width) } - fn set_size(&mut self, size: Option, cx: &mut ViewContext) { - self.width = size.map(|s| px(s)); + fn set_size(&mut self, size: Option, cx: &mut ViewContext) { + self.width = size; self.serialize(cx); cx.notify(); } diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index 3ba1f0bd47..4b2f38de9b 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -37,7 +37,7 @@ pub struct NotificationPanel { channel_store: Model, notification_store: Model, fs: Arc, - width: Option, + width: Option, active: bool, notification_list: ListState, pending_serialization: Task>, @@ -51,7 +51,7 @@ pub struct NotificationPanel { #[derive(Serialize, Deserialize)] struct SerializedNotificationPanel { - width: Option, + width: Option, } #[derive(Debug)] @@ -639,12 +639,12 @@ impl Panel for NotificationPanel { ); } - fn size(&self, cx: &gpui::WindowContext) -> f32 { + fn size(&self, cx: &gpui::WindowContext) -> Pixels { self.width .unwrap_or_else(|| NotificationPanelSettings::get_global(cx).default_width) } - fn set_size(&mut self, size: Option, cx: &mut ViewContext) { + fn set_size(&mut self, size: Option, cx: &mut ViewContext) { self.width = size; self.serialize(cx); cx.notify(); diff --git a/crates/collab_ui2/src/panel_settings.rs b/crates/collab_ui2/src/panel_settings.rs index 3d062951a6..250817a803 100644 --- a/crates/collab_ui2/src/panel_settings.rs +++ b/crates/collab_ui2/src/panel_settings.rs @@ -1,4 +1,5 @@ use anyhow; +use gpui::Pixels; use schemars::JsonSchema; use serde_derive::{Deserialize, Serialize}; use settings::Settings; @@ -8,21 +9,21 @@ use workspace::dock::DockPosition; pub struct CollaborationPanelSettings { pub button: bool, pub dock: DockPosition, - pub default_width: f32, + pub default_width: Pixels, } #[derive(Deserialize, Debug)] pub struct ChatPanelSettings { pub button: bool, pub dock: DockPosition, - pub default_width: f32, + pub default_width: Pixels, } #[derive(Deserialize, Debug)] pub struct NotificationPanelSettings { pub button: bool, pub dock: DockPosition, - pub default_width: f32, + pub default_width: Pixels, } #[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 7f6ae63ee1..1259fc1d61 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -156,7 +156,7 @@ pub enum Event { #[derive(Serialize, Deserialize)] struct SerializedProjectPanel { - width: Option, + width: Option, } struct DraggedProjectEntryView { @@ -333,7 +333,7 @@ impl ProjectPanel { let panel = ProjectPanel::new(workspace, cx); if let Some(serialized_panel) = serialized_panel { panel.update(cx, |panel, cx| { - panel.width = serialized_panel.width.map(px); + panel.width = serialized_panel.width; cx.notify(); }); } @@ -348,9 +348,7 @@ impl ProjectPanel { KEY_VALUE_STORE .write_kvp( PROJECT_PANEL_KEY.into(), - serde_json::to_string(&SerializedProjectPanel { - width: width.map(|p| p.0), - })?, + serde_json::to_string(&SerializedProjectPanel { width })?, ) .await?; anyhow::Ok(()) @@ -1602,15 +1600,13 @@ impl Panel for ProjectPanel { ); } - fn size(&self, cx: &WindowContext) -> f32 { - self.width.map_or_else( - || ProjectPanelSettings::get_global(cx).default_width, - |width| width.0, - ) + fn size(&self, cx: &WindowContext) -> Pixels { + self.width + .unwrap_or_else(|| ProjectPanelSettings::get_global(cx).default_width) } - fn set_size(&mut self, size: Option, cx: &mut ViewContext) { - self.width = size.map(px); + fn set_size(&mut self, size: Option, cx: &mut ViewContext) { + self.width = size; self.serialize(cx); cx.notify(); } diff --git a/crates/project_panel2/src/project_panel_settings.rs b/crates/project_panel2/src/project_panel_settings.rs index c1009648a0..b9a87a1a03 100644 --- a/crates/project_panel2/src/project_panel_settings.rs +++ b/crates/project_panel2/src/project_panel_settings.rs @@ -1,4 +1,5 @@ use anyhow; +use gpui::Pixels; use schemars::JsonSchema; use serde_derive::{Deserialize, Serialize}; use settings::Settings; @@ -12,7 +13,7 @@ pub enum ProjectPanelDockPosition { #[derive(Deserialize, Debug)] pub struct ProjectPanelSettings { - pub default_width: f32, + pub default_width: Pixels, pub dock: ProjectPanelDockPosition, pub file_icons: bool, pub folder_icons: bool, diff --git a/crates/terminal2/src/terminal_settings.rs b/crates/terminal2/src/terminal_settings.rs index 1038c6d061..f63b575bf2 100644 --- a/crates/terminal2/src/terminal_settings.rs +++ b/crates/terminal2/src/terminal_settings.rs @@ -25,8 +25,8 @@ pub struct TerminalSettings { pub option_as_meta: bool, pub copy_on_select: bool, pub dock: TerminalDockPosition, - pub default_width: f32, - pub default_height: f32, + pub default_width: Pixels, + pub default_height: Pixels, pub detect_venv: VenvSettings, } diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index def56f3760..c2fe5de014 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -4,7 +4,7 @@ use crate::TerminalView; use db::kvp::KEY_VALUE_STORE; use gpui::{ actions, div, serde_json, AppContext, AsyncWindowContext, Div, Entity, EventEmitter, - ExternalPaths, FocusHandle, FocusableView, IntoElement, ParentElement, Render, Styled, + ExternalPaths, FocusHandle, FocusableView, IntoElement, ParentElement, Pixels, Render, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use project::Fs; @@ -44,8 +44,8 @@ pub struct TerminalPanel { pane: View, fs: Arc, workspace: WeakView, - width: Option, - height: Option, + width: Option, + height: Option, pending_serialization: Task>, _subscriptions: Vec, } @@ -364,7 +364,7 @@ impl Panel for TerminalPanel { }); } - fn size(&self, cx: &WindowContext) -> f32 { + fn size(&self, cx: &WindowContext) -> Pixels { let settings = TerminalSettings::get_global(cx); match self.position(cx) { DockPosition::Left | DockPosition::Right => { @@ -374,7 +374,7 @@ impl Panel for TerminalPanel { } } - fn set_size(&mut self, size: Option, cx: &mut ViewContext) { + fn set_size(&mut self, size: Option, cx: &mut ViewContext) { match self.position(cx) { DockPosition::Left | DockPosition::Right => self.width = size, DockPosition::Bottom => self.height = size, @@ -428,6 +428,6 @@ impl Panel for TerminalPanel { struct SerializedTerminalPanel { items: Vec, active_item_id: Option, - width: Option, - height: Option, + width: Option, + height: Option, } diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 2534e43895..7121f84681 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -11,6 +11,8 @@ use std::sync::Arc; use ui::{h_stack, ContextMenu, IconButton, Tooltip}; use ui::{prelude::*, right_click_menu}; +const RESIZE_HANDLE_SIZE: Pixels = Pixels(6.); + pub enum PanelEvent { ChangePosition, ZoomIn, @@ -25,8 +27,8 @@ pub trait Panel: FocusableView + EventEmitter { fn position(&self, cx: &WindowContext) -> DockPosition; fn position_is_valid(&self, position: DockPosition) -> bool; fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext); - fn size(&self, cx: &WindowContext) -> f32; - fn set_size(&mut self, size: Option, cx: &mut ViewContext); + fn size(&self, cx: &WindowContext) -> Pixels; + fn set_size(&mut self, size: Option, cx: &mut ViewContext); // todo!("We should have a icon tooltip method, rather than using persistant_name") fn icon(&self, cx: &WindowContext) -> Option; fn toggle_action(&self) -> Box; @@ -49,8 +51,8 @@ pub trait PanelHandle: Send + Sync { fn is_zoomed(&self, cx: &WindowContext) -> bool; fn set_zoomed(&self, zoomed: bool, cx: &mut WindowContext); fn set_active(&self, active: bool, cx: &mut WindowContext); - fn size(&self, cx: &WindowContext) -> f32; - fn set_size(&self, size: Option, cx: &mut WindowContext); + fn size(&self, cx: &WindowContext) -> Pixels; + fn set_size(&self, size: Option, cx: &mut WindowContext); fn icon(&self, cx: &WindowContext) -> Option; fn toggle_action(&self, cx: &WindowContext) -> Box; fn icon_label(&self, cx: &WindowContext) -> Option; @@ -94,11 +96,11 @@ where self.update(cx, |this, cx| this.set_active(active, cx)) } - fn size(&self, cx: &WindowContext) -> f32 { + fn size(&self, cx: &WindowContext) -> Pixels { self.read(cx).size(cx) } - fn set_size(&self, size: Option, cx: &mut WindowContext) { + fn set_size(&self, size: Option, cx: &mut WindowContext) { self.update(cx, |this, cx| this.set_size(size, cx)) } @@ -446,14 +448,14 @@ impl Dock { } } - pub fn panel_size(&self, panel: &dyn PanelHandle, cx: &WindowContext) -> Option { + pub fn panel_size(&self, panel: &dyn PanelHandle, cx: &WindowContext) -> Option { self.panel_entries .iter() .find(|entry| entry.panel.panel_id() == panel.panel_id()) .map(|entry| entry.panel.size(cx)) } - pub fn active_panel_size(&self, cx: &WindowContext) -> Option { + pub fn active_panel_size(&self, cx: &WindowContext) -> Option { if self.is_open { self.panel_entries .get(self.active_panel_index) @@ -463,7 +465,7 @@ impl Dock { } } - pub fn resize_active_panel(&mut self, size: Option, cx: &mut ViewContext) { + pub fn resize_active_panel(&mut self, size: Option, cx: &mut ViewContext) { if let Some(entry) = self.panel_entries.get_mut(self.active_panel_index) { entry.panel.set_size(size, cx); cx.notify(); @@ -502,8 +504,6 @@ impl Render for Dock { .z_index(1) .block_mouse(); - const HANDLE_SIZE: Pixels = Pixels(6.); - match self.position() { DockPosition::Left => { handle = handle @@ -511,7 +511,7 @@ impl Render for Dock { .right(px(0.)) .top(px(0.)) .h_full() - .w(HANDLE_SIZE) + .w(RESIZE_HANDLE_SIZE) .cursor_col_resize(); } DockPosition::Bottom => { @@ -520,7 +520,7 @@ impl Render for Dock { .top(px(0.)) .left(px(0.)) .w_full() - .h(HANDLE_SIZE) + .h(RESIZE_HANDLE_SIZE) .cursor_row_resize(); } DockPosition::Right => { @@ -529,7 +529,7 @@ impl Render for Dock { .top(px(0.)) .left(px(0.)) .h_full() - .w(HANDLE_SIZE) + .w(RESIZE_HANDLE_SIZE) .cursor_col_resize(); } } @@ -539,8 +539,8 @@ impl Render for Dock { .border_color(cx.theme().colors().border) .overflow_hidden() .map(|this| match self.position().axis() { - Axis::Horizontal => this.w(px(size)).h_full().flex_row(), - Axis::Vertical => this.h(px(size)).w_full().flex_col(), + Axis::Horizontal => this.w(size).h_full().flex_row(), + Axis::Vertical => this.h(size).w_full().flex_col(), }) .map(|this| match self.position() { DockPosition::Left => this.border_r(), @@ -550,8 +550,8 @@ impl Render for Dock { .child( div() .map(|this| match self.position().axis() { - Axis::Horizontal => this.min_w(px(size)).h_full(), - Axis::Vertical => this.min_h(px(size)).w_full(), + Axis::Horizontal => this.min_w(size).h_full(), + Axis::Vertical => this.min_h(size).w_full(), }) .child(entry.panel.to_any()), ) @@ -674,7 +674,7 @@ pub mod test { pub zoomed: bool, pub active: bool, pub focus_handle: FocusHandle, - pub size: f32, + pub size: Pixels, } actions!(test, [ToggleTestPanel]); @@ -687,7 +687,7 @@ pub mod test { zoomed: false, active: false, focus_handle: cx.focus_handle(), - size: 300., + size: px(300.), } } } @@ -718,12 +718,12 @@ pub mod test { cx.emit(PanelEvent::ChangePosition); } - fn size(&self, _: &WindowContext) -> f32 { + fn size(&self, _: &WindowContext) -> Pixels { self.size } - fn set_size(&mut self, size: Option, _: &mut ViewContext) { - self.size = size.unwrap_or(300.); + fn set_size(&mut self, size: Option, _: &mut ViewContext) { + self.size = size.unwrap_or(px(300.)); } fn icon(&self, _: &WindowContext) -> Option { diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index c1695891f6..f4484c827e 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -3549,19 +3549,19 @@ impl Render for Workspace { DockPosition::Left => { let size = workspace.bounds.left() + e.event.position.x; workspace.left_dock.update(cx, |left_dock, cx| { - left_dock.resize_active_panel(Some(size.0), cx); + left_dock.resize_active_panel(Some(size), cx); }); } DockPosition::Right => { let size = workspace.bounds.right() - e.event.position.x; workspace.right_dock.update(cx, |right_dock, cx| { - right_dock.resize_active_panel(Some(size.0), cx); + right_dock.resize_active_panel(Some(size), cx); }); } DockPosition::Bottom => { let size = workspace.bounds.bottom() - e.event.position.y; workspace.bottom_dock.update(cx, |bottom_dock, cx| { - bottom_dock.resize_active_panel(Some(size.0), cx); + bottom_dock.resize_active_panel(Some(size), cx); }); } } From 961d8331f32f7fe0fa36533c9cead9692e01c873 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 18:28:28 +0100 Subject: [PATCH 296/644] Prevent panels from getting so small they can't be resized --- crates/workspace2/src/dock.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 7121f84681..9c7ffc6e89 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -467,6 +467,7 @@ impl Dock { pub fn resize_active_panel(&mut self, size: Option, cx: &mut ViewContext) { if let Some(entry) = self.panel_entries.get_mut(self.active_panel_index) { + let size = size.map(|size| size.max(RESIZE_HANDLE_SIZE)); entry.panel.set_size(size, cx); cx.notify(); } From 9a6688bdfb87a38615239a2a05ac4061bf14fdbe Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 22 Dec 2023 18:41:43 +0100 Subject: [PATCH 297/644] Fix panic when deploying emoji picker (character palette) The panic was caused by Cocoa synchronously invoking the `selected_text_range` method on the registered input handler while we already had a borrow of the app. This commit fixes this issue by showing the character palette on the next tick of the loop (we've had this problem in other spots too and used the same technique). --- crates/gpui2/src/platform/mac/window.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/gpui2/src/platform/mac/window.rs b/crates/gpui2/src/platform/mac/window.rs index 12189e198a..a1fda0b75d 100644 --- a/crates/gpui2/src/platform/mac/window.rs +++ b/crates/gpui2/src/platform/mac/window.rs @@ -886,11 +886,16 @@ impl PlatformWindow for MacWindow { } fn show_character_palette(&self) { - unsafe { - let app = NSApplication::sharedApplication(nil); - let window = self.0.lock().native_window; - let _: () = msg_send![app, orderFrontCharacterPalette: window]; - } + let this = self.0.lock(); + let window = this.native_window; + this.executor + .spawn(async move { + unsafe { + let app = NSApplication::sharedApplication(nil); + let _: () = msg_send![app, orderFrontCharacterPalette: window]; + } + }) + .detach(); } fn minimize(&self) { From 7ef2ddd7a52df512a8f0e77e86ba2e761179b24d Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 12:46:06 -0500 Subject: [PATCH 298/644] Disambiguate GPUI2 macOS class names (#3789) This PR disambiguates the macOS class names used in GPUI2 from the ones used in GPUI1. Right now if you happen to end up with a copy of both `gpui` and `gpui2` in the dependency tree you get an unhelpful `unwrap` error when we try to build the class names. By giving them different names we are able to get to our more helpful error that informs you that both GPUI1 and GPUI2 are in the module tree. We can change these names back once we do the big "un-2-ing". Release Notes: - N/A --- crates/gpui2/src/platform/mac/platform.rs | 4 ++-- crates/gpui2/src/platform/mac/window.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/gpui2/src/platform/mac/platform.rs b/crates/gpui2/src/platform/mac/platform.rs index f3c3b8ea5d..2dcfb1a58d 100644 --- a/crates/gpui2/src/platform/mac/platform.rs +++ b/crates/gpui2/src/platform/mac/platform.rs @@ -66,7 +66,7 @@ static mut APP_DELEGATE_CLASS: *const Class = ptr::null(); #[ctor] unsafe fn build_classes() { APP_CLASS = { - let mut decl = ClassDecl::new("GPUIApplication", class!(NSApplication)).unwrap(); + let mut decl = ClassDecl::new("GPUI2Application", class!(NSApplication)).unwrap(); decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR); decl.add_method( sel!(sendEvent:), @@ -76,7 +76,7 @@ unsafe fn build_classes() { }; APP_DELEGATE_CLASS = { - let mut decl = ClassDecl::new("GPUIApplicationDelegate", class!(NSResponder)).unwrap(); + let mut decl = ClassDecl::new("GPUI2ApplicationDelegate", class!(NSResponder)).unwrap(); decl.add_ivar::<*mut c_void>(MAC_PLATFORM_IVAR); decl.add_method( sel!(applicationDidFinishLaunching:), diff --git a/crates/gpui2/src/platform/mac/window.rs b/crates/gpui2/src/platform/mac/window.rs index 12189e198a..de2fa42141 100644 --- a/crates/gpui2/src/platform/mac/window.rs +++ b/crates/gpui2/src/platform/mac/window.rs @@ -85,10 +85,10 @@ const NSDragOperationCopy: NSDragOperation = 1; unsafe fn build_classes() { ::util::gpui2_loaded(); - WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow)); - PANEL_CLASS = build_window_class("GPUIPanel", class!(NSPanel)); + WINDOW_CLASS = build_window_class("GPUI2Window", class!(NSWindow)); + PANEL_CLASS = build_window_class("GPUI2Panel", class!(NSPanel)); VIEW_CLASS = { - let mut decl = ClassDecl::new("GPUIView", class!(NSView)).unwrap(); + let mut decl = ClassDecl::new("GPUI2View", class!(NSView)).unwrap(); decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR); decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel)); From dc64411ccab069d9fd52d8d2868238467c8169a1 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 13:47:30 -0500 Subject: [PATCH 299/644] Extend `theme_importer` in preparation for importing Zed1 themes (#3791) This PR extends the `theme_importer` with the overall structure required to support importing themes from Zed1. Release Notes: - N/A --- Cargo.lock | 2 + crates/gpui/src/platform/mac.rs | 2 +- crates/gpui2/Cargo.toml | 6 + crates/theme2/src/themes/mod.rs | 16 +- crates/theme_importer/Cargo.toml | 6 +- crates/theme_importer/src/assets.rs | 26 +++ crates/theme_importer/src/main.rs | 118 ++++++++++++- crates/theme_importer/src/zed1.rs | 3 + crates/theme_importer/src/zed1/converter.rs | 176 ++++++++++++++++++++ crates/util/Cargo.toml | 6 + crates/util/src/util.rs | 7 +- 11 files changed, 352 insertions(+), 16 deletions(-) create mode 100644 crates/theme_importer/src/assets.rs create mode 100644 crates/theme_importer/src/zed1.rs create mode 100644 crates/theme_importer/src/zed1/converter.rs diff --git a/Cargo.lock b/Cargo.lock index 1bcbd3be38..01230cd805 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9834,6 +9834,7 @@ dependencies = [ "anyhow", "clap 4.4.4", "convert_case 0.6.0", + "gpui", "gpui2", "indexmap 1.9.3", "json_comments", @@ -9843,6 +9844,7 @@ dependencies = [ "serde", "simplelog", "strum", + "theme", "theme2", "uuid 1.4.1", ] diff --git a/crates/gpui/src/platform/mac.rs b/crates/gpui/src/platform/mac.rs index 92ab53f15e..193651c087 100644 --- a/crates/gpui/src/platform/mac.rs +++ b/crates/gpui/src/platform/mac.rs @@ -25,7 +25,7 @@ use window::MacWindow; use crate::executor; -pub(crate) fn platform() -> Arc { +pub fn platform() -> Arc { Arc::new(MacPlatform::new()) } diff --git a/crates/gpui2/Cargo.toml b/crates/gpui2/Cargo.toml index bf0ac955a5..cb3e1af70b 100644 --- a/crates/gpui2/Cargo.toml +++ b/crates/gpui2/Cargo.toml @@ -9,6 +9,12 @@ publish = false [features] test-support = ["backtrace", "dhat", "env_logger", "collections/test-support", "util/test-support"] +# Suppress a panic when both GPUI1 and GPUI2 are loaded. +# +# This is used in the `theme_importer` where we need to depend on both +# GPUI1 and GPUI2 in order to convert Zed1 themes to Zed2 themes. +allow-multiple-gpui-versions = ["util/allow-multiple-gpui-versions"] + [lib] path = "src/gpui2.rs" doctest = false diff --git a/crates/theme2/src/themes/mod.rs b/crates/theme2/src/themes/mod.rs index 4059d3751e..aaf111703f 100644 --- a/crates/theme2/src/themes/mod.rs +++ b/crates/theme2/src/themes/mod.rs @@ -29,16 +29,16 @@ use crate::UserThemeFamily; pub(crate) fn all_user_themes() -> Vec { vec![ - rose_pine(), - night_owl(), andromeda(), - synthwave_84(), - palenight(), - dracula(), - solarized(), - nord(), - noctis(), ayu(), + dracula(), gruvbox(), + night_owl(), + noctis(), + nord(), + palenight(), + rose_pine(), + solarized(), + synthwave_84(), ] } diff --git a/crates/theme_importer/Cargo.toml b/crates/theme_importer/Cargo.toml index 23a53053ce..2841839c09 100644 --- a/crates/theme_importer/Cargo.toml +++ b/crates/theme_importer/Cargo.toml @@ -4,14 +4,13 @@ version = "0.1.0" edition = "2021" publish = false -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] any_ascii = "0.3.2" anyhow.workspace = true clap = { version = "4.4", features = ["derive"] } convert_case = "0.6.0" -gpui = { package = "gpui2", path = "../gpui2" } +gpui = { package = "gpui2", path = "../gpui2", features = ["allow-multiple-gpui-versions"] } +gpui1 = { package = "gpui", path = "../gpui" } indexmap = { version = "1.6.2", features = ["serde"] } json_comments = "0.2.2" log.workspace = true @@ -21,4 +20,5 @@ serde.workspace = true simplelog = "0.9" strum = { version = "0.25.0", features = ["derive"] } theme = { package = "theme2", path = "../theme2", features = ["importing-themes"] } +theme1 = { package = "theme", path = "../theme" } uuid.workspace = true diff --git a/crates/theme_importer/src/assets.rs b/crates/theme_importer/src/assets.rs new file mode 100644 index 0000000000..9009b4c144 --- /dev/null +++ b/crates/theme_importer/src/assets.rs @@ -0,0 +1,26 @@ +use std::borrow::Cow; + +use anyhow::{anyhow, Result}; +use gpui::{AssetSource, SharedString}; +use rust_embed::RustEmbed; + +#[derive(RustEmbed)] +#[folder = "../../assets"] +#[include = "fonts/**/*"] +#[exclude = "*.DS_Store"] +pub struct Assets; + +impl AssetSource for Assets { + fn load(&self, path: &str) -> Result> { + Self::get(path) + .map(|f| f.data) + .ok_or_else(|| anyhow!("could not find asset at path \"{}\"", path)) + } + + fn list(&self, path: &str) -> Result> { + Ok(Self::iter() + .filter(|p| p.starts_with(path)) + .map(SharedString::from) + .collect()) + } +} diff --git a/crates/theme_importer/src/main.rs b/crates/theme_importer/src/main.rs index 01ab191571..e6cf8952d1 100644 --- a/crates/theme_importer/src/main.rs +++ b/crates/theme_importer/src/main.rs @@ -1,29 +1,36 @@ +mod assets; mod color; mod theme_printer; mod util; mod vscode; +mod zed1; +use std::collections::HashMap; use std::fs::{self, File}; use std::io::Write; use std::path::PathBuf; use std::process::Command; use std::str::FromStr; +use std::sync::Arc; use any_ascii::any_ascii; use anyhow::{anyhow, Context, Result}; use clap::Parser; use convert_case::{Case, Casing}; -use gpui::serde_json; +use gpui::{serde_json, AssetSource}; use indexmap::IndexMap; use json_comments::StripComments; use log::LevelFilter; use serde::Deserialize; use simplelog::{TermLogger, TerminalMode}; -use theme::{Appearance, UserThemeFamily}; +use theme::{Appearance, UserTheme, UserThemeFamily}; +use theme1::Theme as Zed1Theme; +use crate::assets::Assets; use crate::theme_printer::UserThemeFamilyPrinter; use crate::vscode::VsCodeTheme; use crate::vscode::VsCodeThemeConverter; +use crate::zed1::Zed1ThemeConverter; #[derive(Debug, Deserialize)] struct FamilyMetadata { @@ -66,6 +73,10 @@ pub struct ThemeMetadata { #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Args { + /// Whether to import Zed1 themes. + #[arg(long)] + zed1: bool, + /// Whether to warn when values are missing from the theme. #[arg(long)] warn_on_missing: bool, @@ -176,6 +187,102 @@ fn main() -> Result<()> { theme_families.push(theme_family); } + if args.zed1 { + let zed1_themes_path = PathBuf::from_str("assets/themes")?; + + let zed1_theme_familes = [ + "Andromeda", + "Atelier", + "Ayu", + "Gruvbox", + "One", + "Rosé Pine", + "Sandcastle", + "Solarized", + "Summercamp", + ]; + + let mut zed1_themes_by_family: HashMap> = HashMap::from_iter( + zed1_theme_familes + .into_iter() + .map(|family| (family.to_string(), Vec::new())), + ); + + let platform = gpui1::platform::current::platform(); + let zed1_font_cache = Arc::new(gpui1::FontCache::new(platform.fonts())); + + let mut embedded_fonts = Vec::new(); + for font_path in Assets.list("fonts")? { + if font_path.ends_with(".ttf") { + let font_bytes = Assets.load(&font_path)?.to_vec(); + embedded_fonts.push(Arc::from(font_bytes)); + } + } + + platform.fonts().add_fonts(&embedded_fonts)?; + + for entry in fs::read_dir(&zed1_themes_path)? { + let entry = entry?; + + if entry.file_type()?.is_dir() { + continue; + } + + match entry.path().extension() { + None => continue, + Some(extension) => { + if extension != "json" { + continue; + } + } + } + + let theme_file_path = entry.path(); + + let theme_file = match File::open(&theme_file_path) { + Ok(file) => file, + Err(_) => { + log::info!("Failed to open file at path: {:?}", theme_file_path); + continue; + } + }; + + let theme_without_comments = StripComments::new(theme_file); + + let zed1_theme: Zed1Theme = + gpui1::fonts::with_font_cache(zed1_font_cache.clone(), || { + serde_json::from_reader(theme_without_comments) + .context(format!("failed to parse theme {theme_file_path:?}")) + })?; + + let theme_name = zed1_theme.meta.name.clone(); + + let converter = Zed1ThemeConverter::new(zed1_theme); + + let theme = converter.convert()?; + + let Some((_, themes_for_family)) = zed1_themes_by_family + .iter_mut() + .find(|(family, _)| theme_name.starts_with(*family)) + else { + log::warn!("No theme family found for '{}'.", theme_name); + continue; + }; + + themes_for_family.push(theme); + } + + for (family, themes) in zed1_themes_by_family { + let theme_family = UserThemeFamily { + name: format!("{family} (Zed1)"), + author: "Zed Industries".to_string(), + themes, + }; + + theme_families.push(theme_family); + } + } + let themes_output_path = PathBuf::from_str(OUT_PATH)?; if !themes_output_path.exists() { @@ -188,7 +295,10 @@ fn main() -> Result<()> { let mut theme_modules = Vec::new(); for theme_family in theme_families { - let theme_family_slug = any_ascii(&theme_family.name).to_case(Case::Snake); + let theme_family_slug = any_ascii(&theme_family.name) + .replace("(", "") + .replace(")", "") + .to_case(Case::Snake); let mut output_file = File::create(themes_output_path.join(format!("{theme_family_slug}.rs")))?; @@ -222,6 +332,8 @@ fn main() -> Result<()> { theme_modules.push(theme_family_slug); } + theme_modules.sort(); + let themes_vector_contents = format!( r#" use crate::UserThemeFamily; diff --git a/crates/theme_importer/src/zed1.rs b/crates/theme_importer/src/zed1.rs new file mode 100644 index 0000000000..11bc94497f --- /dev/null +++ b/crates/theme_importer/src/zed1.rs @@ -0,0 +1,3 @@ +mod converter; + +pub use converter::*; diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs new file mode 100644 index 0000000000..1a5f7af8b7 --- /dev/null +++ b/crates/theme_importer/src/zed1/converter.rs @@ -0,0 +1,176 @@ +use anyhow::Result; +use gpui::{Hsla, Rgba}; +use gpui1::color::Color as Zed1Color; +use gpui1::fonts::HighlightStyle as Zed1HighlightStyle; +use theme::{ + Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, + UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeStylesRefinement, +}; +use theme1::Theme as Zed1Theme; + +fn zed1_color_to_hsla(color: Zed1Color) -> Hsla { + let r = color.r as f32 / 255.; + let g = color.g as f32 / 255.; + let b = color.b as f32 / 255.; + let a = color.a as f32 / 255.; + + Hsla::from(Rgba { r, g, b, a }) +} + +fn zed1_highlight_style_to_user_highlight_style( + highlight: Zed1HighlightStyle, +) -> UserHighlightStyle { + UserHighlightStyle { + color: highlight.color.map(zed1_color_to_hsla), + font_style: highlight.italic.map(|is_italic| { + if is_italic { + UserFontStyle::Italic + } else { + UserFontStyle::Normal + } + }), + font_weight: highlight.weight.map(|weight| UserFontWeight(weight.0)), + } +} + +pub struct Zed1ThemeConverter { + theme: Zed1Theme, +} + +impl Zed1ThemeConverter { + pub fn new(theme: Zed1Theme) -> Self { + Self { theme } + } + + pub fn convert(self) -> Result { + let appearance = match self.theme.meta.is_light { + true => Appearance::Light, + false => Appearance::Dark, + }; + + let status_colors_refinement = self.convert_status_colors()?; + let theme_colors_refinement = self.convert_theme_colors()?; + let syntax_theme = self.convert_syntax_theme()?; + + Ok(UserTheme { + name: format!("{} (Zed1)", self.theme.meta.name), + appearance, + styles: UserThemeStylesRefinement { + colors: theme_colors_refinement, + status: status_colors_refinement, + syntax: Some(syntax_theme), + }, + }) + } + + fn convert_status_colors(&self) -> Result { + fn convert(color: Zed1Color) -> Option { + Some(zed1_color_to_hsla(color)) + } + + let diff_style = self.theme.editor.diff.clone(); + + Ok(StatusColorsRefinement { + created: convert(diff_style.inserted), + modified: convert(diff_style.modified), + deleted: convert(diff_style.deleted), + ..Default::default() + }) + } + + fn convert_theme_colors(&self) -> Result { + fn convert(color: Zed1Color) -> Option { + Some(zed1_color_to_hsla(color)) + } + + let tab_bar = self.theme.workspace.tab_bar.clone(); + let active_tab = self.theme.workspace.tab_bar.tab_style(true, true).clone(); + let inactive_tab = self.theme.workspace.tab_bar.tab_style(true, false).clone(); + let toolbar = self.theme.workspace.toolbar.clone(); + let scrollbar = self.theme.editor.scrollbar.clone(); + + let zed1_titlebar_border = convert(self.theme.titlebar.container.border.color); + + Ok(ThemeColorsRefinement { + border: zed1_titlebar_border, + border_variant: zed1_titlebar_border, + background: convert(self.theme.workspace.background), + title_bar_background: self + .theme + .titlebar + .container + .background_color + .map(zed1_color_to_hsla), + status_bar_background: self + .theme + .workspace + .status_bar + .container + .background_color + .map(zed1_color_to_hsla), + text: convert(self.theme.editor.text_color), + tab_bar_background: tab_bar.container.background_color.map(zed1_color_to_hsla), + tab_active_background: active_tab + .container + .background_color + .map(zed1_color_to_hsla), + tab_inactive_background: inactive_tab + .container + .background_color + .map(zed1_color_to_hsla), + toolbar_background: toolbar.container.background_color.map(zed1_color_to_hsla), + editor_foreground: convert(self.theme.editor.text_color), + editor_background: convert(self.theme.editor.background), + editor_gutter_background: convert(self.theme.editor.gutter_background), + editor_line_number: convert(self.theme.editor.line_number), + editor_active_line_number: convert(self.theme.editor.line_number_active), + editor_wrap_guide: convert(self.theme.editor.wrap_guide), + editor_active_wrap_guide: convert(self.theme.editor.active_wrap_guide), + scrollbar_track_background: scrollbar.track.background_color.map(zed1_color_to_hsla), + scrollbar_track_border: convert(scrollbar.track.border.color), + scrollbar_thumb_background: scrollbar.thumb.background_color.map(zed1_color_to_hsla), + scrollbar_thumb_border: convert(scrollbar.thumb.border.color), + scrollbar_thumb_hover_background: scrollbar + .thumb + .background_color + .map(zed1_color_to_hsla), + terminal_background: convert(self.theme.terminal.background), + terminal_ansi_bright_black: convert(self.theme.terminal.bright_black), + terminal_ansi_bright_red: convert(self.theme.terminal.bright_red), + terminal_ansi_bright_green: convert(self.theme.terminal.bright_green), + terminal_ansi_bright_yellow: convert(self.theme.terminal.bright_yellow), + terminal_ansi_bright_blue: convert(self.theme.terminal.bright_blue), + terminal_ansi_bright_magenta: convert(self.theme.terminal.bright_magenta), + terminal_ansi_bright_cyan: convert(self.theme.terminal.bright_cyan), + terminal_ansi_bright_white: convert(self.theme.terminal.bright_white), + terminal_ansi_black: convert(self.theme.terminal.black), + terminal_ansi_red: convert(self.theme.terminal.red), + terminal_ansi_green: convert(self.theme.terminal.green), + terminal_ansi_yellow: convert(self.theme.terminal.yellow), + terminal_ansi_blue: convert(self.theme.terminal.blue), + terminal_ansi_magenta: convert(self.theme.terminal.magenta), + terminal_ansi_cyan: convert(self.theme.terminal.cyan), + terminal_ansi_white: convert(self.theme.terminal.white), + ..Default::default() + }) + } + + fn convert_syntax_theme(&self) -> Result { + Ok(UserSyntaxTheme { + highlights: self + .theme + .editor + .syntax + .highlights + .clone() + .into_iter() + .map(|(name, highlight_style)| { + ( + name, + zed1_highlight_style_to_user_highlight_style(highlight_style), + ) + }) + .collect(), + }) + } +} diff --git a/crates/util/Cargo.toml b/crates/util/Cargo.toml index cfbd7551f9..4320983c2f 100644 --- a/crates/util/Cargo.toml +++ b/crates/util/Cargo.toml @@ -11,6 +11,12 @@ doctest = true [features] test-support = ["tempdir", "git2"] +# Suppress a panic when both GPUI1 and GPUI2 are loaded. +# +# This is used in the `theme_importer` where we need to depend on both +# GPUI1 and GPUI2 in order to convert Zed1 themes to Zed2 themes. +allow-multiple-gpui-versions = [] + [dependencies] anyhow.workspace = true backtrace = "0.3" diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index 3f2371121c..ac96cc6652 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -13,10 +13,12 @@ use std::{ ops::{AddAssign, Range, RangeInclusive}, panic::Location, pin::Pin, - sync::atomic::AtomicU32, task::{Context, Poll}, }; +#[cfg(not(feature = "allow-multiple-gpui-versions"))] +use std::sync::atomic::AtomicU32; + pub use backtrace::Backtrace; use futures::Future; use rand::{seq::SliceRandom, Rng}; @@ -434,15 +436,18 @@ impl RangeExt for RangeInclusive { } } +#[cfg(not(feature = "allow-multiple-gpui-versions"))] static GPUI_LOADED: AtomicU32 = AtomicU32::new(0); pub fn gpui2_loaded() { + #[cfg(not(feature = "allow-multiple-gpui-versions"))] if GPUI_LOADED.fetch_add(2, std::sync::atomic::Ordering::SeqCst) != 0 { panic!("=========\nYou are loading both GPUI1 and GPUI2 in the same build!\nFix Your Dependencies with cargo tree!\n=========") } } pub fn gpui1_loaded() { + #[cfg(not(feature = "allow-multiple-gpui-versions"))] if GPUI_LOADED.fetch_add(1, std::sync::atomic::Ordering::SeqCst) != 0 { panic!("=========\nYou are loading both GPUI1 and GPUI2 in the same build!\nFix Your Dependencies with cargo tree!\n=========") } From 764a2755e259eb090ade88fe328e302a7c53f457 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 22:56:35 +0200 Subject: [PATCH 300/644] Fix multibuffer scroll by reordering z-index of its elements 1. Blocks (with their headers) and mouse listeners should be drawn together otherwise either starts to loose mouse events. 2. Scrollbar should be above all to match zed1 look and avoid buffer headers popping slightly to the right of the scrollbar. --- crates/editor2/src/element.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 294cc2c4e3..9e1d8e641f 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2840,23 +2840,26 @@ impl Element for EditorElement { } self.paint_text(text_bounds, &mut layout, cx); - cx.with_z_index(0, |cx| { - self.paint_mouse_listeners(bounds, gutter_bounds, text_bounds, &layout, cx); - }); - - cx.with_z_index(1, |cx| self.paint_scrollbar(bounds, &mut layout, cx)); - if !layout.blocks.is_empty() { - cx.with_z_index(2, |cx| { + cx.with_z_index(0, |cx| { cx.with_element_id(Some("editor_blocks"), |cx| { self.paint_blocks(bounds, &mut layout, cx); + self.paint_mouse_listeners( + bounds, + gutter_bounds, + text_bounds, + &layout, + cx, + ); }); }) } - cx.with_z_index(3, |cx| { + cx.with_z_index(1, |cx| { self.paint_overlays(text_bounds, &mut layout, cx); }); + + cx.with_z_index(2, |cx| self.paint_scrollbar(bounds, &mut layout, cx)); }); }) } From b501f4eafc782c5a186e03453461f81458cf0b06 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 17:37:53 -0500 Subject: [PATCH 301/644] Begin porting Zed1 themes to Zed2 (#3793) This PR is a first pass at porting the Zed1 themes to Zed2. For the initial release of Zed2 we'll be shipping just the themes that existed in Zed1, ported to Zed2. The new themes that were previously added just in Zed2 have been removed. Release Notes: - N/A --- crates/file_finder2/src/file_finder.rs | 5 +- crates/theme2/src/registry.rs | 19 +- crates/theme2/src/themes/andromeda.rs | 768 +- crates/theme2/src/themes/atelier.rs | 7159 +++++++++++++++++ crates/theme2/src/themes/ayu.rs | 1488 ++-- crates/theme2/src/themes/dracula.rs | 250 - crates/theme2/src/themes/gruvbox.rs | 2196 ++--- crates/theme2/src/themes/mod.rs | 30 +- crates/theme2/src/themes/night_owl.rs | 547 -- crates/theme2/src/themes/noctis.rs | 3110 ------- crates/theme2/src/themes/nord.rs | 277 - .../src/themes/{palenight.rs => one.rs} | 754 +- crates/theme2/src/themes/rose_pine.rs | 791 +- crates/theme2/src/themes/sandcastle.rs | 353 + crates/theme2/src/themes/solarized.rs | 487 +- crates/theme2/src/themes/summercamp.rs | 353 + crates/theme2/src/themes/synthwave_84.rs | 248 - crates/theme_importer/src/main.rs | 320 +- crates/theme_importer/src/theme_printer.rs | 1 + crates/theme_importer/src/zed1/converter.rs | 56 +- crates/workspace2/src/dock.rs | 1 + 21 files changed, 11599 insertions(+), 7614 deletions(-) create mode 100644 crates/theme2/src/themes/atelier.rs delete mode 100644 crates/theme2/src/themes/dracula.rs delete mode 100644 crates/theme2/src/themes/night_owl.rs delete mode 100644 crates/theme2/src/themes/noctis.rs delete mode 100644 crates/theme2/src/themes/nord.rs rename crates/theme2/src/themes/{palenight.rs => one.rs} (50%) create mode 100644 crates/theme2/src/themes/sandcastle.rs create mode 100644 crates/theme2/src/themes/summercamp.rs delete mode 100644 crates/theme2/src/themes/synthwave_84.rs diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 369128a753..7410ed7658 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -721,10 +721,7 @@ impl PickerDelegate for FileFinderDelegate { .child( v_stack() .child(HighlightedLabel::new(file_name, file_name_positions)) - .child( - HighlightedLabel::new(full_path, full_path_positions) - .color(Color::Muted), - ), + .child(HighlightedLabel::new(full_path, full_path_positions)), ), ) } diff --git a/crates/theme2/src/registry.rs b/crates/theme2/src/registry.rs index ec88fecd99..ac94d93bcd 100644 --- a/crates/theme2/src/registry.rs +++ b/crates/theme2/src/registry.rs @@ -6,8 +6,8 @@ use gpui::{HighlightStyle, SharedString}; use refineable::Refineable; use crate::{ - one_themes::one_family, zed_pro_family, Appearance, PlayerColors, StatusColors, SyntaxTheme, - SystemColors, Theme, ThemeColors, ThemeFamily, ThemeStyles, UserTheme, UserThemeFamily, + Appearance, PlayerColors, StatusColors, SyntaxTheme, SystemColors, Theme, ThemeColors, + ThemeFamily, ThemeStyles, UserTheme, UserThemeFamily, }; #[derive(Debug, Clone)] @@ -34,7 +34,7 @@ impl ThemeRegistry { } #[allow(unused)] - fn insert_user_theme_familes(&mut self, families: impl IntoIterator) { + fn insert_user_theme_families(&mut self, families: impl IntoIterator) { for family in families.into_iter() { self.insert_user_themes(family.themes); } @@ -117,18 +117,23 @@ impl ThemeRegistry { pub fn load_user_themes(&mut self) { #[cfg(not(feature = "importing-themes"))] - self.insert_user_theme_familes(crate::all_user_themes()); + self.insert_user_theme_families(crate::all_user_themes()); } } impl Default for ThemeRegistry { fn default() -> Self { - let mut this = Self { + let mut registry = Self { themes: HashMap::default(), }; - this.insert_theme_families([zed_pro_family(), one_family()]); + // We're loading our new versions of the One themes by default, as + // we need them to be loaded for tests. + // + // These themes will get overwritten when `load_user_themes` is called + // when Zed starts, so the One variants used will be the ones ported from Zed1. + registry.insert_theme_families([crate::one_themes::one_family()]); - this + registry } } diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index 513b6f0212..5affa63fb0 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -12,442 +12,342 @@ use crate::{ pub fn andromeda() -> UserThemeFamily { UserThemeFamily { name: "Andromeda".into(), - author: "Eliver Lara (EliverLara)".into(), - themes: vec![ - UserTheme { - name: "Andromeda".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x1b1d23ff).into()), - border_variant: Some(rgba(0x1b1d23ff).into()), - border_focused: Some(rgba(0x746f77ff).into()), - border_selected: Some(rgba(0x1b1d23ff).into()), - border_transparent: Some(rgba(0x1b1d23ff).into()), - border_disabled: Some(rgba(0x1b1d23ff).into()), - elevated_surface_background: Some(rgba(0x2b303bff).into()), - surface_background: Some(rgba(0x23262eff).into()), - background: Some(rgba(0x23262eff).into()), - element_background: Some(rgba(0x00e8c5cc).into()), - element_hover: Some(rgba(0x23262eff).into()), - element_selected: Some(rgba(0x23262eff).into()), - drop_target_background: Some(rgba(0x3a404eff).into()), - ghost_element_hover: Some(rgba(0x23262eff).into()), - ghost_element_selected: Some(rgba(0x23262eff).into()), - text: Some(rgba(0xd5ced9ff).into()), - text_muted: Some(rgba(0x746f77ff).into()), - status_bar_background: Some(rgba(0x23262eff).into()), - title_bar_background: Some(rgba(0x23262eff).into()), - toolbar_background: Some(rgba(0x23262eff).into()), - tab_bar_background: Some(rgba(0x23262eff).into()), - tab_inactive_background: Some(rgba(0x23262eff).into()), - tab_active_background: Some(rgba(0x23262eff).into()), - scrollbar_thumb_background: Some(rgba(0x3a3f4c77).into()), - scrollbar_thumb_hover_background: Some(rgba(0x3a3f4caa).into()), - scrollbar_thumb_border: Some(rgba(0x3a3f4c77).into()), - scrollbar_track_background: Some(rgba(0x23262eff).into()), - scrollbar_track_border: Some(rgba(0x1b1d23ff).into()), - editor_foreground: Some(rgba(0xd5ced9ff).into()), - editor_background: Some(rgba(0x23262eff).into()), - editor_gutter_background: Some(rgba(0x23262eff).into()), - editor_line_number: Some(rgba(0x746f77ff).into()), - editor_active_line_number: Some(rgba(0xd5ced9ff).into()), - editor_wrap_guide: Some(rgba(0x1b1d23ff).into()), - editor_active_wrap_guide: Some(rgba(0x1b1d23ff).into()), - terminal_ansi_bright_red: Some(rgba(0xee5d43ff).into()), - terminal_ansi_bright_green: Some(rgba(0x96e072ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffe66dff).into()), - terminal_ansi_bright_blue: Some(rgba(0x7cb7ffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xff00aaff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x00e8c6ff).into()), - terminal_ansi_red: Some(rgba(0xee5d43ff).into()), - terminal_ansi_green: Some(rgba(0x96e072ff).into()), - terminal_ansi_yellow: Some(rgba(0xffe66dff).into()), - terminal_ansi_blue: Some(rgba(0x7cb7ffff).into()), - terminal_ansi_magenta: Some(rgba(0xff00aaff).into()), - terminal_ansi_cyan: Some(rgba(0x00e8c6ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - created: Some(rgba(0x9bc53dbb).into()), - deleted: Some(rgba(0xfc644dbb).into()), - error: Some(rgba(0xfc644dff).into()), - hidden: Some(rgba(0x746f77ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x555555ff).into()), - modified: Some(rgba(0x5bc0ebbb).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xffe66dff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0xa0a1a7cc).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0xa0a1a7cc).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xee5d43ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xf92672ff).into()), - ..Default::default() - }, - ), - ( - "emphasis".into(), - UserHighlightStyle { - color: Some(rgba(0xc74dedff).into()), - ..Default::default() - }, - ), - ( - "emphasis.strong".into(), - UserHighlightStyle { - color: Some(rgba(0xf39c12ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0xffe66dff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xc74dedff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xf39c12ff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0xee5d43ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xf92672ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xffe66dff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0x00e8c6ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0x00e8c6ff).into()), - ..Default::default() - }, - ), - ], - }), + author: "Zed Industries".into(), + themes: vec![UserTheme { + name: "Andromeda".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x2b2f39ff).into()), + border_variant: Some(rgba(0x2b2f39ff).into()), + elevated_surface_background: Some(rgba(0x262a33ff).into()), + background: Some(rgba(0x262a33ff).into()), + panel_background: Some(rgba(0x21242bff).into()), + element_hover: Some(rgba(0x2b2f3980).into()), + element_selected: Some(rgba(0x383b4580).into()), + text: Some(rgba(0xaca8aeff).into()), + text_muted: Some(rgba(0x474a53ff).into()), + status_bar_background: Some(rgba(0x262a33ff).into()), + title_bar_background: Some(rgba(0x262a33ff).into()), + toolbar_background: Some(rgba(0x1e2025ff).into()), + tab_bar_background: Some(rgba(0x21242bff).into()), + tab_inactive_background: Some(rgba(0x21242bff).into()), + tab_active_background: Some(rgba(0x1e2025ff).into()), + scrollbar_thumb_background: Some(rgba(0xf7f7f84d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xf7f7f84d).into()), + scrollbar_thumb_border: Some(rgba(0x21232aff).into()), + scrollbar_track_border: Some(rgba(0x21232aff).into()), + editor_foreground: Some(rgba(0xf7f7f8ff).into()), + editor_background: Some(rgba(0x1e2025ff).into()), + editor_gutter_background: Some(rgba(0x1e2025ff).into()), + editor_line_number: Some(rgba(0xf7f7f859).into()), + editor_active_line_number: Some(rgba(0xf7f7f8ff).into()), + editor_wrap_guide: Some(rgba(0xf7f7f80d).into()), + editor_active_wrap_guide: Some(rgba(0xf7f7f81a).into()), + terminal_background: Some(rgba(0x1e2025ff).into()), + terminal_ansi_bright_black: Some(rgba(0x40434cff).into()), + terminal_ansi_bright_red: Some(rgba(0x8e103aff).into()), + terminal_ansi_bright_green: Some(rgba(0x457c38ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x958435ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x1b5148ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x682781ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x018169ff).into()), + terminal_ansi_bright_white: Some(rgba(0xf7f7f8ff).into()), + terminal_ansi_black: Some(rgba(0x1e2025ff).into()), + terminal_ansi_red: Some(rgba(0xf82872ff).into()), + terminal_ansi_green: Some(rgba(0x96df72ff).into()), + terminal_ansi_yellow: Some(rgba(0xfee56dff).into()), + terminal_ansi_blue: Some(rgba(0x11a793ff).into()), + terminal_ansi_magenta: Some(rgba(0xc74decff).into()), + terminal_ansi_cyan: Some(rgba(0x09e7c6ff).into()), + terminal_ansi_white: Some(rgba(0xf7f7f8ff).into()), + ..Default::default() }, - }, - UserTheme { - name: "Andromeda Bordered".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x1b1d23ff).into()), - border_variant: Some(rgba(0x1b1d23ff).into()), - border_focused: Some(rgba(0x746f77ff).into()), - border_selected: Some(rgba(0x1b1d23ff).into()), - border_transparent: Some(rgba(0x1b1d23ff).into()), - border_disabled: Some(rgba(0x1b1d23ff).into()), - elevated_surface_background: Some(rgba(0x2b303bff).into()), - surface_background: Some(rgba(0x23262eff).into()), - background: Some(rgba(0x262a33ff).into()), - element_background: Some(rgba(0x00e8c5cc).into()), - element_hover: Some(rgba(0x23262eff).into()), - element_selected: Some(rgba(0x23262eff).into()), - drop_target_background: Some(rgba(0x3a404eff).into()), - ghost_element_hover: Some(rgba(0x23262eff).into()), - ghost_element_selected: Some(rgba(0x23262eff).into()), - text: Some(rgba(0xd5ced9ff).into()), - text_muted: Some(rgba(0x746f77ff).into()), - status_bar_background: Some(rgba(0x23262eff).into()), - title_bar_background: Some(rgba(0x23262eff).into()), - toolbar_background: Some(rgba(0x262a33ff).into()), - tab_bar_background: Some(rgba(0x23262eff).into()), - tab_inactive_background: Some(rgba(0x23262eff).into()), - tab_active_background: Some(rgba(0x262a33ff).into()), - scrollbar_thumb_background: Some(rgba(0x3a3f4c77).into()), - scrollbar_thumb_hover_background: Some(rgba(0x3a3f4caa).into()), - scrollbar_thumb_border: Some(rgba(0x3a3f4c77).into()), - scrollbar_track_background: Some(rgba(0x262a33ff).into()), - scrollbar_track_border: Some(rgba(0x1b1d23ff).into()), - editor_foreground: Some(rgba(0xd5ced9ff).into()), - editor_background: Some(rgba(0x262a33ff).into()), - editor_gutter_background: Some(rgba(0x262a33ff).into()), - editor_line_number: Some(rgba(0x746f77ff).into()), - editor_active_line_number: Some(rgba(0xd5ced9ff).into()), - editor_wrap_guide: Some(rgba(0x1b1d23ff).into()), - editor_active_wrap_guide: Some(rgba(0x1b1d23ff).into()), - terminal_ansi_bright_red: Some(rgba(0xee5d43ff).into()), - terminal_ansi_bright_green: Some(rgba(0x96e072ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffe66dff).into()), - terminal_ansi_bright_blue: Some(rgba(0x7cb7ffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xff00aaff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x00e8c6ff).into()), - terminal_ansi_red: Some(rgba(0xee5d43ff).into()), - terminal_ansi_green: Some(rgba(0x96e072ff).into()), - terminal_ansi_yellow: Some(rgba(0xffe66dff).into()), - terminal_ansi_blue: Some(rgba(0x7cb7ffff).into()), - terminal_ansi_magenta: Some(rgba(0xff00aaff).into()), - terminal_ansi_cyan: Some(rgba(0x00e8c6ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - created: Some(rgba(0x9bc53dbb).into()), - deleted: Some(rgba(0xfc644dbb).into()), - error: Some(rgba(0xfc644dff).into()), - hidden: Some(rgba(0x746f77ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x555555ff).into()), - modified: Some(rgba(0x5bc0ebbb).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xffe66dff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0xa0a1a7cc).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0xa0a1a7cc).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xee5d43ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xf92672ff).into()), - ..Default::default() - }, - ), - ( - "emphasis".into(), - UserHighlightStyle { - color: Some(rgba(0xc74dedff).into()), - ..Default::default() - }, - ), - ( - "emphasis.strong".into(), - UserHighlightStyle { - color: Some(rgba(0xf39c12ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0xffe66dff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xc74dedff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xf39c12ff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0xee5d43ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xf92672ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x96e072ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xffe66dff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0x00e8c6ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0x00e8c6ff).into()), - ..Default::default() - }, - ), - ], - }), + status: StatusColorsRefinement { + created: Some(rgba(0x96df72ff).into()), + deleted: Some(rgba(0xcd1d5aff).into()), + error: Some(rgba(0xf82872ff).into()), + modified: Some(rgba(0xfee56dff).into()), + success: Some(rgba(0xf7f7f8ff).into()), + warning: Some(rgba(0xfee56dff).into()), + ..Default::default() }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x96df72ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0xafabb1ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0xafabb1ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x96df72ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xf7f7f8ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xf29c14ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0xfee56dff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x618399ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xf29c14ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x96df72ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x96df72ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xf29c14ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x315f70ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xf7f7f8ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xf7f7f8ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xd8d5dbff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xd8d5dbff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xd8d5dbff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xd8d5dbff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xd8d5dbff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0xf29c14ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0xafabb1ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0xf29c14ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xf29c14ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0xf29c14ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xf29c14ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xf7f7f8ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x09e7c6ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xf7f7f8ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x11a793ff).into()), + ..Default::default() + }, + ), + ], + }), }, - ], + }], } } diff --git a/crates/theme2/src/themes/atelier.rs b/crates/theme2/src/themes/atelier.rs new file mode 100644 index 0000000000..f1ec02cb75 --- /dev/null +++ b/crates/theme2/src/themes/atelier.rs @@ -0,0 +1,7159 @@ +// This file was generated by the `theme_importer`. +// Be careful when modifying it by hand. + +use gpui::rgba; + +#[allow(unused)] +use crate::{ + Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, + UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, +}; + +pub fn atelier() -> UserThemeFamily { + UserThemeFamily { + name: "Atelier".into(), + author: "Zed Industries".into(), + themes: vec![ + UserTheme { + name: "Atelier Estuary Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x969585ff).into()), + border_variant: Some(rgba(0x969585ff).into()), + elevated_surface_background: Some(rgba(0xc5c4b9ff).into()), + background: Some(rgba(0xc5c4b9ff).into()), + panel_background: Some(rgba(0xebeae3ff).into()), + element_hover: Some(rgba(0x96958580).into()), + element_selected: Some(rgba(0x8b8a7880).into()), + text: Some(rgba(0x61604fff).into()), + text_muted: Some(rgba(0x878573ff).into()), + status_bar_background: Some(rgba(0xc5c4b9ff).into()), + title_bar_background: Some(rgba(0xc5c4b9ff).into()), + toolbar_background: Some(rgba(0xf4f3ecff).into()), + tab_bar_background: Some(rgba(0xebeae3ff).into()), + tab_inactive_background: Some(rgba(0xebeae3ff).into()), + tab_active_background: Some(rgba(0xf4f3ecff).into()), + scrollbar_thumb_background: Some(rgba(0x22221b4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x22221b4d).into()), + scrollbar_thumb_border: Some(rgba(0xedece5ff).into()), + scrollbar_track_border: Some(rgba(0xedece5ff).into()), + editor_foreground: Some(rgba(0x302f27ff).into()), + editor_background: Some(rgba(0xf4f3ecff).into()), + editor_gutter_background: Some(rgba(0xf4f3ecff).into()), + editor_line_number: Some(rgba(0x22221b59).into()), + editor_active_line_number: Some(rgba(0x22221bff).into()), + editor_wrap_guide: Some(rgba(0x22221b0d).into()), + editor_active_wrap_guide: Some(rgba(0x22221b1a).into()), + terminal_background: Some(rgba(0xf4f3ecff).into()), + terminal_ansi_bright_black: Some(rgba(0x898775ff).into()), + terminal_ansi_bright_red: Some(rgba(0xe4af96ff).into()), + terminal_ansi_bright_green: Some(rgba(0xc0ca93ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xd7ca8dff).into()), + terminal_ansi_bright_blue: Some(rgba(0xa0d1b0ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xcfb4bcff).into()), + terminal_ansi_bright_cyan: Some(rgba(0xaecea1ff).into()), + terminal_ansi_bright_white: Some(rgba(0x22221bff).into()), + terminal_ansi_black: Some(rgba(0xf4f3ecff).into()), + terminal_ansi_red: Some(rgba(0xba6337ff).into()), + terminal_ansi_green: Some(rgba(0x7d9728ff).into()), + terminal_ansi_yellow: Some(rgba(0xa59810ff).into()), + terminal_ansi_blue: Some(rgba(0x38a166ff).into()), + terminal_ansi_magenta: Some(rgba(0x9d6c7cff).into()), + terminal_ansi_cyan: Some(rgba(0x5c9d49ff).into()), + terminal_ansi_white: Some(rgba(0x22221bff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x98ab54ff).into()), + deleted: Some(rgba(0xba6337ff).into()), + error: Some(rgba(0xba6337ff).into()), + modified: Some(rgba(0xa59810ff).into()), + success: Some(rgba(0x22221bff).into()), + warning: Some(rgba(0xa59810ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x38a166ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9728ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x878573ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x5f5e4eff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9728ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x38a166ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x22221bff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x38a166ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x38a166ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xae7315ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x36a166ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x36a166ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xa5980dff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x768962ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x5f9182ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x38a166ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xae7315ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9728ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xae7313ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x5f5e4eff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x879a72ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x22221bff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x302f27ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xba6236ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x302f27ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x5f5e4eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x5f5e4eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x302f27ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0x9d6c7cff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9726ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x5f5e4eff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x5b9d48ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0x9d6c7cff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9726ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x38a166ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xae7315ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x22221bff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xa5980dff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x302f27ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x5f9182ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xa5980dff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Forest Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x665f5cff).into()), + border_variant: Some(rgba(0x665f5cff).into()), + elevated_surface_background: Some(rgba(0x443c39ff).into()), + background: Some(rgba(0x443c39ff).into()), + panel_background: Some(rgba(0x27211eff).into()), + element_hover: Some(rgba(0x665f5c80).into()), + element_selected: Some(rgba(0x71696680).into()), + text: Some(rgba(0xa79f9dff).into()), + text_muted: Some(rgba(0x766e6bff).into()), + status_bar_background: Some(rgba(0x443c39ff).into()), + title_bar_background: Some(rgba(0x443c39ff).into()), + toolbar_background: Some(rgba(0x1b1918ff).into()), + tab_bar_background: Some(rgba(0x27211eff).into()), + tab_inactive_background: Some(rgba(0x27211eff).into()), + tab_active_background: Some(rgba(0x1b1918ff).into()), + scrollbar_thumb_background: Some(rgba(0xf1efee4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xf1efee4d).into()), + scrollbar_thumb_border: Some(rgba(0x251f1dff).into()), + scrollbar_track_border: Some(rgba(0x251f1dff).into()), + editor_foreground: Some(rgba(0xe6e2e0ff).into()), + editor_background: Some(rgba(0x1b1918ff).into()), + editor_gutter_background: Some(rgba(0x1b1918ff).into()), + editor_line_number: Some(rgba(0xf1efee59).into()), + editor_active_line_number: Some(rgba(0xf1efeeff).into()), + editor_wrap_guide: Some(rgba(0xf1efee0d).into()), + editor_active_wrap_guide: Some(rgba(0xf1efee1a).into()), + terminal_background: Some(rgba(0x1b1918ff).into()), + terminal_ansi_bright_black: Some(rgba(0x746c69ff).into()), + terminal_ansi_bright_red: Some(rgba(0x8c1223ff).into()), + terminal_ansi_bright_green: Some(rgba(0x3e491aff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x674115ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x213f78ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x662186ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x264958ff).into()), + terminal_ansi_bright_white: Some(rgba(0xf1efeeff).into()), + terminal_ansi_black: Some(rgba(0x1b1918ff).into()), + terminal_ansi_red: Some(rgba(0xf22d40ff).into()), + terminal_ansi_green: Some(rgba(0x7b9727ff).into()), + terminal_ansi_yellow: Some(rgba(0xc38419ff).into()), + terminal_ansi_blue: Some(rgba(0x417ee6ff).into()), + terminal_ansi_magenta: Some(rgba(0xc340f2ff).into()), + terminal_ansi_cyan: Some(rgba(0x3e97b8ff).into()), + terminal_ansi_white: Some(rgba(0xf1efeeff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x7b9727ff).into()), + deleted: Some(rgba(0xc82234ff).into()), + error: Some(rgba(0xf22d40ff).into()), + modified: Some(rgba(0xc38419ff).into()), + success: Some(rgba(0xf1efeeff).into()), + warning: Some(rgba(0xc38419ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9727ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x766e6bff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0xa8a19fff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9727ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xf1efeeff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xdf5321ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x407ee7ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x407ee7ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xc38418ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0xa87187ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x6666eaff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xdf5321ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9727ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xdf5320ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xa8a19fff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x8f5b71ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xf1efeeff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xe6e2e0ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xf22c40ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xe6e2e0ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xa8a19fff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xa8a19fff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xe6e2e0ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xc33ff3ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9726ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0xa8a19fff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x3d97b8ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xc33ff3ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9726ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xdf5321ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xf1efeeff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xc38418ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xe6e2e0ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x6666eaff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xc38418ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Savanna Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x8b968eff).into()), + border_variant: Some(rgba(0x8b968eff).into()), + elevated_surface_background: Some(rgba(0xbcc5bfff).into()), + background: Some(rgba(0xbcc5bfff).into()), + panel_background: Some(rgba(0xe3ebe6ff).into()), + element_hover: Some(rgba(0x8b968e80).into()), + element_selected: Some(rgba(0x7e8b8280).into()), + text: Some(rgba(0x546259ff).into()), + text_muted: Some(rgba(0x79877dff).into()), + status_bar_background: Some(rgba(0xbcc5bfff).into()), + title_bar_background: Some(rgba(0xbcc5bfff).into()), + toolbar_background: Some(rgba(0xecf4eeff).into()), + tab_bar_background: Some(rgba(0xe3ebe6ff).into()), + tab_inactive_background: Some(rgba(0xe3ebe6ff).into()), + tab_active_background: Some(rgba(0xecf4eeff).into()), + scrollbar_thumb_background: Some(rgba(0x171c194d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x171c194d).into()), + scrollbar_thumb_border: Some(rgba(0xe5ede7ff).into()), + scrollbar_track_border: Some(rgba(0xe5ede7ff).into()), + editor_foreground: Some(rgba(0x232a25ff).into()), + editor_background: Some(rgba(0xecf4eeff).into()), + editor_gutter_background: Some(rgba(0xecf4eeff).into()), + editor_line_number: Some(rgba(0x171c1959).into()), + editor_active_line_number: Some(rgba(0x171c19ff).into()), + editor_wrap_guide: Some(rgba(0x171c190d).into()), + editor_active_wrap_guide: Some(rgba(0x171c191a).into()), + terminal_background: Some(rgba(0xecf4eeff).into()), + terminal_ansi_bright_black: Some(rgba(0x7b897fff).into()), + terminal_ansi_bright_red: Some(rgba(0xdeae97ff).into()), + terminal_ansi_bright_green: Some(rgba(0xa5ccafff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xd3bd9aff).into()), + terminal_ansi_bright_blue: Some(rgba(0xa5c5c6ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xc2b7b1ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9dcdcfff).into()), + terminal_ansi_bright_white: Some(rgba(0x171c19ff).into()), + terminal_ansi_black: Some(rgba(0xecf4eeff).into()), + terminal_ansi_red: Some(rgba(0xb1623aff).into()), + terminal_ansi_green: Some(rgba(0x499963ff).into()), + terminal_ansi_yellow: Some(rgba(0xa07e3cff).into()), + terminal_ansi_blue: Some(rgba(0x488c90ff).into()), + terminal_ansi_magenta: Some(rgba(0x867469ff).into()), + terminal_ansi_cyan: Some(rgba(0x1f9aa0ff).into()), + terminal_ansi_white: Some(rgba(0x171c19ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x6fae80ff).into()), + deleted: Some(rgba(0xb1623aff).into()), + error: Some(rgba(0xb1623aff).into()), + modified: Some(rgba(0xa07e3cff).into()), + success: Some(rgba(0x171c19ff).into()), + warning: Some(rgba(0xa07e3cff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x488c90ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x499963ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x78877dff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x526057ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x499963ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x488c90ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x171c19ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x488c90ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x488c90ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0x9f713dff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x66847cff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x55859bff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x488c90ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x9f713dff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x499963ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x9f713cff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x526057ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x76958cff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x171c19ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x232a25ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xb16139ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x232a25ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x526057ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x526057ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x232a25ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0x867469ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x489963ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x526057ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x1c9aa0ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0x867469ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x489963ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x488c90ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0x9f713dff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x171c19ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x232a25ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x55859bff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Cave Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x56505eff).into()), + border_variant: Some(rgba(0x56505eff).into()), + elevated_surface_background: Some(rgba(0x3a353fff).into()), + background: Some(rgba(0x3a353fff).into()), + panel_background: Some(rgba(0x221f26ff).into()), + element_hover: Some(rgba(0x56505e80).into()), + element_selected: Some(rgba(0x605a6880).into()), + text: Some(rgba(0x898591ff).into()), + text_muted: Some(rgba(0x655f6dff).into()), + status_bar_background: Some(rgba(0x3a353fff).into()), + title_bar_background: Some(rgba(0x3a353fff).into()), + toolbar_background: Some(rgba(0x19171cff).into()), + tab_bar_background: Some(rgba(0x221f26ff).into()), + tab_inactive_background: Some(rgba(0x221f26ff).into()), + tab_active_background: Some(rgba(0x19171cff).into()), + scrollbar_thumb_background: Some(rgba(0xefecf44d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xefecf44d).into()), + scrollbar_thumb_border: Some(rgba(0x201e24ff).into()), + scrollbar_track_border: Some(rgba(0x201e24ff).into()), + editor_foreground: Some(rgba(0xe2dfe7ff).into()), + editor_background: Some(rgba(0x19171cff).into()), + editor_gutter_background: Some(rgba(0x19171cff).into()), + editor_line_number: Some(rgba(0xefecf459).into()), + editor_active_line_number: Some(rgba(0xefecf4ff).into()), + editor_wrap_guide: Some(rgba(0xefecf40d).into()), + editor_active_wrap_guide: Some(rgba(0xefecf41a).into()), + terminal_background: Some(rgba(0x19171cff).into()), + terminal_ansi_bright_black: Some(rgba(0x635d6bff).into()), + terminal_ansi_bright_red: Some(rgba(0x5c283cff).into()), + terminal_ansi_bright_green: Some(rgba(0x1f4747ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x4e3821ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x2d376fff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x60255bff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x26445eff).into()), + terminal_ansi_bright_white: Some(rgba(0xefecf4ff).into()), + terminal_ansi_black: Some(rgba(0x19171cff).into()), + terminal_ansi_red: Some(rgba(0xbe4678ff).into()), + terminal_ansi_green: Some(rgba(0x2c9292ff).into()), + terminal_ansi_yellow: Some(rgba(0xa06e3bff).into()), + terminal_ansi_blue: Some(rgba(0x576ddaff).into()), + terminal_ansi_magenta: Some(rgba(0xbf41bfff).into()), + terminal_ansi_cyan: Some(rgba(0x3a8bc6ff).into()), + terminal_ansi_white: Some(rgba(0xefecf4ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x2c9292ff).into()), + deleted: Some(rgba(0x953a5fff).into()), + error: Some(rgba(0xbe4678ff).into()), + modified: Some(rgba(0xa06e3bff).into()), + success: Some(rgba(0xefecf4ff).into()), + warning: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddaff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x2c9292ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x655f6dff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x8b8792ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x2c9292ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddaff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xefecf4ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddaff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddaff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xaa573cff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddbff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddbff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x716998ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x955ae7ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddaff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xaa573cff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x2c9292ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xaa573cff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x8b8792ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x625887ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xefecf4ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xe2dfe7ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xbe4678ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xe2dfe7ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x8b8792ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x8b8792ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xe2dfe7ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbf40bfff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x2a9292ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x8b8792ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x398bc6ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbf40bfff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x2a9292ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddaff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xaa573cff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xefecf4ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xe2dfe7ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x955ae7ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Estuary Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x5d5c4cff).into()), + border_variant: Some(rgba(0x5d5c4cff).into()), + elevated_surface_background: Some(rgba(0x424136ff).into()), + background: Some(rgba(0x424136ff).into()), + panel_background: Some(rgba(0x2c2b23ff).into()), + element_hover: Some(rgba(0x5d5c4c80).into()), + element_selected: Some(rgba(0x67665580).into()), + text: Some(rgba(0x91907fff).into()), + text_muted: Some(rgba(0x6c6b5aff).into()), + status_bar_background: Some(rgba(0x424136ff).into()), + title_bar_background: Some(rgba(0x424136ff).into()), + toolbar_background: Some(rgba(0x22221bff).into()), + tab_bar_background: Some(rgba(0x2c2b23ff).into()), + tab_inactive_background: Some(rgba(0x2c2b23ff).into()), + tab_active_background: Some(rgba(0x22221bff).into()), + scrollbar_thumb_background: Some(rgba(0xf4f3ec4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xf4f3ec4d).into()), + scrollbar_thumb_border: Some(rgba(0x2a2922ff).into()), + scrollbar_track_border: Some(rgba(0x2a2922ff).into()), + editor_foreground: Some(rgba(0xe7e6dfff).into()), + editor_background: Some(rgba(0x22221bff).into()), + editor_gutter_background: Some(rgba(0x22221bff).into()), + editor_line_number: Some(rgba(0xf4f3ec59).into()), + editor_active_line_number: Some(rgba(0xf4f3ecff).into()), + editor_wrap_guide: Some(rgba(0xf4f3ec0d).into()), + editor_active_wrap_guide: Some(rgba(0xf4f3ec1a).into()), + terminal_background: Some(rgba(0x22221bff).into()), + terminal_ansi_bright_black: Some(rgba(0x6a6958ff).into()), + terminal_ansi_bright_red: Some(rgba(0x5c331fff).into()), + terminal_ansi_bright_green: Some(rgba(0x3f491aff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x514a14ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x234e34ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x4c373eff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x314c27ff).into()), + terminal_ansi_bright_white: Some(rgba(0xf4f3ecff).into()), + terminal_ansi_black: Some(rgba(0x22221bff).into()), + terminal_ansi_red: Some(rgba(0xba6237ff).into()), + terminal_ansi_green: Some(rgba(0x7d9727ff).into()), + terminal_ansi_yellow: Some(rgba(0xa59810ff).into()), + terminal_ansi_blue: Some(rgba(0x37a166ff).into()), + terminal_ansi_magenta: Some(rgba(0x9d6c7cff).into()), + terminal_ansi_cyan: Some(rgba(0x5b9d48ff).into()), + terminal_ansi_white: Some(rgba(0xf4f3ecff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x7d9727ff).into()), + deleted: Some(rgba(0x934e2dff).into()), + error: Some(rgba(0xba6237ff).into()), + modified: Some(rgba(0xa59810ff).into()), + success: Some(rgba(0xf4f3ecff).into()), + warning: Some(rgba(0xa59810ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x37a166ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9727ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x6c6b5aff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x929181ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9727ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x37a166ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xf4f3ecff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x37a166ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x37a166ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xae7315ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x36a166ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x36a166ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xa5980dff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x70825bff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x5f9182ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x37a166ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xae7315ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9727ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xae7313ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x929181ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x5f724cff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xf4f3ecff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xe7e6dfff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xba6236ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xe7e6dfff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x929181ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x929181ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xe7e6dfff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0x9d6c7cff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9726ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x929181ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x5b9d48ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0x9d6c7cff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9726ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x37a166ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xae7315ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xf4f3ecff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xa5980dff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xe7e6dfff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x5f9182ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xa5980dff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Sulphurpool Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x5c6485ff).into()), + border_variant: Some(rgba(0x5c6485ff).into()), + elevated_surface_background: Some(rgba(0x3e4769ff).into()), + background: Some(rgba(0x3e4769ff).into()), + panel_background: Some(rgba(0x262f51ff).into()), + element_hover: Some(rgba(0x5c648580).into()), + element_selected: Some(rgba(0x666e8f80).into()), + text: Some(rgba(0x959bb2ff).into()), + text_muted: Some(rgba(0x6b7394ff).into()), + status_bar_background: Some(rgba(0x3e4769ff).into()), + title_bar_background: Some(rgba(0x3e4769ff).into()), + toolbar_background: Some(rgba(0x202746ff).into()), + tab_bar_background: Some(rgba(0x262f51ff).into()), + tab_inactive_background: Some(rgba(0x262f51ff).into()), + tab_active_background: Some(rgba(0x202746ff).into()), + scrollbar_thumb_background: Some(rgba(0xf5f7ff4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xf5f7ff4d).into()), + scrollbar_thumb_border: Some(rgba(0x252d4fff).into()), + scrollbar_track_border: Some(rgba(0x252d4fff).into()), + editor_foreground: Some(rgba(0xdfe2f1ff).into()), + editor_background: Some(rgba(0x202746ff).into()), + editor_gutter_background: Some(rgba(0x202746ff).into()), + editor_line_number: Some(rgba(0xf5f7ff59).into()), + editor_active_line_number: Some(rgba(0xf5f7ffff).into()), + editor_wrap_guide: Some(rgba(0xf5f7ff0d).into()), + editor_active_wrap_guide: Some(rgba(0xf5f7ff1a).into()), + terminal_background: Some(rgba(0x202746ff).into()), + terminal_ansi_bright_black: Some(rgba(0x697192ff).into()), + terminal_ansi_bright_red: Some(rgba(0x6d2616ff).into()), + terminal_ansi_bright_green: Some(rgba(0x534921ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x63441eff).into()), + terminal_ansi_bright_blue: Some(rgba(0x274664ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x4c333dff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x214e5fff).into()), + terminal_ansi_bright_white: Some(rgba(0xf5f7ffff).into()), + terminal_ansi_black: Some(rgba(0x202746ff).into()), + terminal_ansi_red: Some(rgba(0xc94923ff).into()), + terminal_ansi_green: Some(rgba(0xac973aff).into()), + terminal_ansi_yellow: Some(rgba(0xc08b31ff).into()), + terminal_ansi_blue: Some(rgba(0x3e8fd0ff).into()), + terminal_ansi_magenta: Some(rgba(0x9c637aff).into()), + terminal_ansi_cyan: Some(rgba(0x25a2c9ff).into()), + terminal_ansi_white: Some(rgba(0xf5f7ffff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0xac973aff).into()), + deleted: Some(rgba(0xa33a1eff).into()), + error: Some(rgba(0xc94923ff).into()), + modified: Some(rgba(0xc08b31ff).into()), + success: Some(rgba(0xf5f7ffff).into()), + warning: Some(rgba(0xc08b31ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x3e8fd0ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0xac973aff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x6b7394ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x979db4ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xac973aff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x3e8fd0ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xf5f7ffff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x3e8fd0ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x3e8fd0ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xc76b2aff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x3d8fd1ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x3d8fd1ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xc08b30ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x6d82a6ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x6679ccff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x3e8fd0ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xc76b2aff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0xac973aff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xc76b29ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x979db4ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x58709aff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xf5f7ffff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xdfe2f1ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xc94922ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xdfe2f1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x979db4ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x979db4ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xdfe2f1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0x9c637aff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0xac9739ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x979db4ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x22a2c9ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0x9c637aff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0xac9739ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x3e8fd0ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xc76b2aff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xf5f7ffff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xc08b30ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xdfe2f1ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x6679ccff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xc08b30ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Sulphurpool Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x9a9fb6ff).into()), + border_variant: Some(rgba(0x9a9fb6ff).into()), + elevated_surface_background: Some(rgba(0xc2c6d9ff).into()), + background: Some(rgba(0xc2c6d9ff).into()), + panel_background: Some(rgba(0xe5e8f5ff).into()), + element_hover: Some(rgba(0x9a9fb680).into()), + element_selected: Some(rgba(0x8e94aa80).into()), + text: Some(rgba(0x606889ff).into()), + text_muted: Some(rgba(0x898fa5ff).into()), + status_bar_background: Some(rgba(0xc2c6d9ff).into()), + title_bar_background: Some(rgba(0xc2c6d9ff).into()), + toolbar_background: Some(rgba(0xf5f7ffff).into()), + tab_bar_background: Some(rgba(0xe5e8f5ff).into()), + tab_inactive_background: Some(rgba(0xe5e8f5ff).into()), + tab_active_background: Some(rgba(0xf5f7ffff).into()), + scrollbar_thumb_background: Some(rgba(0x2027464d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x2027464d).into()), + scrollbar_thumb_border: Some(rgba(0xe9ebf7ff).into()), + scrollbar_track_border: Some(rgba(0xe9ebf7ff).into()), + editor_foreground: Some(rgba(0x293256ff).into()), + editor_background: Some(rgba(0xf5f7ffff).into()), + editor_gutter_background: Some(rgba(0xf5f7ffff).into()), + editor_line_number: Some(rgba(0x20274659).into()), + editor_active_line_number: Some(rgba(0x202746ff).into()), + editor_wrap_guide: Some(rgba(0x2027460d).into()), + editor_active_wrap_guide: Some(rgba(0x2027461a).into()), + terminal_background: Some(rgba(0xf5f7ffff).into()), + terminal_ansi_bright_black: Some(rgba(0x8b91a7ff).into()), + terminal_ansi_bright_red: Some(rgba(0xefa58cff).into()), + terminal_ansi_bright_green: Some(rgba(0xd9ca9bff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xe5c497ff).into()), + terminal_ansi_bright_blue: Some(rgba(0xa9c6e8ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xcfafbbff).into()), + terminal_ansi_bright_cyan: Some(rgba(0xa4d0e4ff).into()), + terminal_ansi_bright_white: Some(rgba(0x202746ff).into()), + terminal_ansi_black: Some(rgba(0xf5f7ffff).into()), + terminal_ansi_red: Some(rgba(0xc94a23ff).into()), + terminal_ansi_green: Some(rgba(0xac973aff).into()), + terminal_ansi_yellow: Some(rgba(0xc08b31ff).into()), + terminal_ansi_blue: Some(rgba(0x3f8fd0ff).into()), + terminal_ansi_magenta: Some(rgba(0x9c637aff).into()), + terminal_ansi_cyan: Some(rgba(0x25a2c9ff).into()), + terminal_ansi_white: Some(rgba(0x202746ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0xbfab61ff).into()), + deleted: Some(rgba(0xc94a23ff).into()), + error: Some(rgba(0xc94a23ff).into()), + modified: Some(rgba(0xc08b31ff).into()), + success: Some(rgba(0x202746ff).into()), + warning: Some(rgba(0xc08b31ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x3f8fd0ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0xac973aff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x898ea4ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6687ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xac973aff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x3f8fd0ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x202746ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x3f8fd0ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x3f8fd0ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xc76b2aff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x3d8fd1ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x3d8fd1ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xc08b30ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x7087b2ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x6679ccff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x3f8fd0ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xc76b2aff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0xac973aff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xc76b29ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6687ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x8599beff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x202746ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x293256ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xc94922ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x293256ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6687ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6687ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x293256ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0x9c637aff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0xac9739ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6687ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x22a2c9ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0x9c637aff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0xac9739ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x3f8fd0ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xc76b2aff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x202746ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xc08b30ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x293256ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x6679ccff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xc08b30ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Dune Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x6c695cff).into()), + border_variant: Some(rgba(0x6c695cff).into()), + elevated_surface_background: Some(rgba(0x45433bff).into()), + background: Some(rgba(0x45433bff).into()), + panel_background: Some(rgba(0x262622ff).into()), + element_hover: Some(rgba(0x6c695c80).into()), + element_selected: Some(rgba(0x77746480).into()), + text: Some(rgba(0xa4a08bff).into()), + text_muted: Some(rgba(0x7c7968ff).into()), + status_bar_background: Some(rgba(0x45433bff).into()), + title_bar_background: Some(rgba(0x45433bff).into()), + toolbar_background: Some(rgba(0x20201dff).into()), + tab_bar_background: Some(rgba(0x262622ff).into()), + tab_inactive_background: Some(rgba(0x262622ff).into()), + tab_active_background: Some(rgba(0x20201dff).into()), + scrollbar_thumb_background: Some(rgba(0xfefbec4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xfefbec4d).into()), + scrollbar_thumb_border: Some(rgba(0x252521ff).into()), + scrollbar_track_border: Some(rgba(0x252521ff).into()), + editor_foreground: Some(rgba(0xe8e4cfff).into()), + editor_background: Some(rgba(0x20201dff).into()), + editor_gutter_background: Some(rgba(0x20201dff).into()), + editor_line_number: Some(rgba(0xfefbec59).into()), + editor_active_line_number: Some(rgba(0xfefbecff).into()), + editor_wrap_guide: Some(rgba(0xfefbec0d).into()), + editor_active_wrap_guide: Some(rgba(0xfefbec1a).into()), + terminal_background: Some(rgba(0x20201dff).into()), + terminal_ansi_bright_black: Some(rgba(0x7a7766ff).into()), + terminal_ansi_bright_red: Some(rgba(0x781c1fff).into()), + terminal_ansi_bright_green: Some(rgba(0x335322ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x574815ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x334173ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x721d2bff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x1e5341ff).into()), + terminal_ansi_bright_white: Some(rgba(0xfefbecff).into()), + terminal_ansi_black: Some(rgba(0x20201dff).into()), + terminal_ansi_red: Some(rgba(0xd73837ff).into()), + terminal_ansi_green: Some(rgba(0x60ac3aff).into()), + terminal_ansi_yellow: Some(rgba(0xae9515ff).into()), + terminal_ansi_blue: Some(rgba(0x6684e0ff).into()), + terminal_ansi_magenta: Some(rgba(0xd43652ff).into()), + terminal_ansi_cyan: Some(rgba(0x21ad83ff).into()), + terminal_ansi_white: Some(rgba(0xfefbecff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x60ac3aff).into()), + deleted: Some(rgba(0xaf2c2eff).into()), + error: Some(rgba(0xd73837ff).into()), + modified: Some(rgba(0xae9515ff).into()), + success: Some(rgba(0xfefbecff).into()), + warning: Some(rgba(0xae9515ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e0ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x60ac3aff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x7d7a68ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0xa6a28cff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x60ac3aff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e0ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xfefbecff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e0ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e0ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xb65612ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e1ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e1ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xae9513ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0xb17272ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0xb854d4ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e0ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xb65612ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x60ac3aff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xb65611ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xa6a28cff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x9c6262ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xfefbecff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xe8e4cfff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xd73737ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xe8e4cfff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xa6a28cff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xa6a28cff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xe8e4cfff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xd43552ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x60ac39ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0xa6a28cff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x1fad83ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xd43552ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x60ac39ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e0ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xb65612ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xfefbecff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xae9513ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xe8e4cfff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0xb854d4ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xae9513ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Seaside Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x5c6c5cff).into()), + border_variant: Some(rgba(0x5c6c5cff).into()), + elevated_surface_background: Some(rgba(0x3b453bff).into()), + background: Some(rgba(0x3b453bff).into()), + panel_background: Some(rgba(0x1f231fff).into()), + element_hover: Some(rgba(0x5c6c5c80).into()), + element_selected: Some(rgba(0x64776480).into()), + text: Some(rgba(0x8ba48bff).into()), + text_muted: Some(rgba(0x687c68ff).into()), + status_bar_background: Some(rgba(0x3b453bff).into()), + title_bar_background: Some(rgba(0x3b453bff).into()), + toolbar_background: Some(rgba(0x131513ff).into()), + tab_bar_background: Some(rgba(0x1f231fff).into()), + tab_inactive_background: Some(rgba(0x1f231fff).into()), + tab_active_background: Some(rgba(0x131513ff).into()), + scrollbar_thumb_background: Some(rgba(0xf4fbf44d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xf4fbf44d).into()), + scrollbar_thumb_border: Some(rgba(0x1d201dff).into()), + scrollbar_track_border: Some(rgba(0x1d201dff).into()), + editor_foreground: Some(rgba(0xcfe8cfff).into()), + editor_background: Some(rgba(0x131513ff).into()), + editor_gutter_background: Some(rgba(0x131513ff).into()), + editor_line_number: Some(rgba(0xf4fbf459).into()), + editor_active_line_number: Some(rgba(0xf4fbf4ff).into()), + editor_wrap_guide: Some(rgba(0xf4fbf40d).into()), + editor_active_wrap_guide: Some(rgba(0xf4fbf41a).into()), + terminal_background: Some(rgba(0x131513ff).into()), + terminal_ansi_bright_black: Some(rgba(0x667a66ff).into()), + terminal_ansi_bright_red: Some(rgba(0x840b21ff).into()), + terminal_ansi_bright_green: Some(rgba(0x204f1bff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x4b4a17ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x193385ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x810e60ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x1d4a56ff).into()), + terminal_ansi_bright_white: Some(rgba(0xf4fbf4ff).into()), + terminal_ansi_black: Some(rgba(0x131513ff).into()), + terminal_ansi_red: Some(rgba(0xe61c3cff).into()), + terminal_ansi_green: Some(rgba(0x2ba32aff).into()), + terminal_ansi_yellow: Some(rgba(0x98981cff).into()), + terminal_ansi_blue: Some(rgba(0x3e62f4ff).into()), + terminal_ansi_magenta: Some(rgba(0xe61cc3ff).into()), + terminal_ansi_cyan: Some(rgba(0x1c99b3ff).into()), + terminal_ansi_white: Some(rgba(0xf4fbf4ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x2ba32aff).into()), + deleted: Some(rgba(0xbd1331ff).into()), + error: Some(rgba(0xe61c3cff).into()), + modified: Some(rgba(0x98981cff).into()), + success: Some(rgba(0xf4fbf4ff).into()), + warning: Some(rgba(0x98981cff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x3e62f4ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x2ba32aff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x687d68ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x8ca68cff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x2ba32aff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x3e62f4ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xf4fbf4ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x3e62f4ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x3e62f4ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0x87711eff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x3d62f5ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x3d62f5ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0x98981bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x008b9fff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0xad2beeff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x3e62f4ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x87711eff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x2ba32aff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x87711dff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x8ca68cff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x00788bff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xf4fbf4ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xcfe8cfff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xe6193cff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xcfe8cfff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x8ca68cff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x8ca68cff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xcfe8cfff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xe619c3ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x29a329ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x8ca68cff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x1999b3ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xe619c3ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x29a329ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x3e62f4ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0x87711eff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xf4fbf4ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x98981bff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xcfe8cfff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0xad2beeff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x98981bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Cave Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x8f8b96ff).into()), + border_variant: Some(rgba(0x8f8b96ff).into()), + elevated_surface_background: Some(rgba(0xbfbcc5ff).into()), + background: Some(rgba(0xbfbcc5ff).into()), + panel_background: Some(rgba(0xe6e3ebff).into()), + element_hover: Some(rgba(0x8f8b9680).into()), + element_selected: Some(rgba(0x837e8b80).into()), + text: Some(rgba(0x5a5462ff).into()), + text_muted: Some(rgba(0x7e7987ff).into()), + status_bar_background: Some(rgba(0xbfbcc5ff).into()), + title_bar_background: Some(rgba(0xbfbcc5ff).into()), + toolbar_background: Some(rgba(0xefecf4ff).into()), + tab_bar_background: Some(rgba(0xe6e3ebff).into()), + tab_inactive_background: Some(rgba(0xe6e3ebff).into()), + tab_active_background: Some(rgba(0xefecf4ff).into()), + scrollbar_thumb_background: Some(rgba(0x19171c4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x19171c4d).into()), + scrollbar_thumb_border: Some(rgba(0xe8e5edff).into()), + scrollbar_track_border: Some(rgba(0xe8e5edff).into()), + editor_foreground: Some(rgba(0x26232aff).into()), + editor_background: Some(rgba(0xefecf4ff).into()), + editor_gutter_background: Some(rgba(0xefecf4ff).into()), + editor_line_number: Some(rgba(0x19171c59).into()), + editor_active_line_number: Some(rgba(0x19171cff).into()), + editor_wrap_guide: Some(rgba(0x19171c0d).into()), + editor_active_wrap_guide: Some(rgba(0x19171c1a).into()), + terminal_background: Some(rgba(0xefecf4ff).into()), + terminal_ansi_bright_black: Some(rgba(0x807b89ff).into()), + terminal_ansi_bright_red: Some(rgba(0xe3a4b9ff).into()), + terminal_ansi_bright_green: Some(rgba(0x9dc8c8ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xd4b499ff).into()), + terminal_ansi_bright_blue: Some(rgba(0xb3b3eeff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xe3a4dfff).into()), + terminal_ansi_bright_cyan: Some(rgba(0xa6c4e3ff).into()), + terminal_ansi_bright_white: Some(rgba(0x19171cff).into()), + terminal_ansi_black: Some(rgba(0xefecf4ff).into()), + terminal_ansi_red: Some(rgba(0xbe4778ff).into()), + terminal_ansi_green: Some(rgba(0x2c9292ff).into()), + terminal_ansi_yellow: Some(rgba(0xa06e3cff).into()), + terminal_ansi_blue: Some(rgba(0x586ddaff).into()), + terminal_ansi_magenta: Some(rgba(0xbf41bfff).into()), + terminal_ansi_cyan: Some(rgba(0x3b8bc6ff).into()), + terminal_ansi_white: Some(rgba(0x19171cff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x5fa8a7ff).into()), + deleted: Some(rgba(0xbe4778ff).into()), + error: Some(rgba(0xbe4778ff).into()), + modified: Some(rgba(0xa06e3cff).into()), + success: Some(rgba(0x19171cff).into()), + warning: Some(rgba(0xa06e3cff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x586ddaff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x2c9292ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x7e7887ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x585260ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x2c9292ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x586ddaff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x19171cff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x586ddaff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x586ddaff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xaa583dff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddbff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x576ddbff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x786e9dff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x955ae7ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x586ddaff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xaa583dff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x2c9292ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xaa573cff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x585260ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x887fafff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x19171cff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x26232aff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xbe4678ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x26232aff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x585260ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x585260ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x26232aff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbf40bfff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x2a9292ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x585260ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x398bc6ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbf40bfff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x2a9292ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x586ddaff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xaa583dff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x19171cff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x26232aff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x955ae7ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Plateau Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x564e4eff).into()), + border_variant: Some(rgba(0x564e4eff).into()), + elevated_surface_background: Some(rgba(0x3b3535ff).into()), + background: Some(rgba(0x3b3535ff).into()), + panel_background: Some(rgba(0x252020ff).into()), + element_hover: Some(rgba(0x564e4e80).into()), + element_selected: Some(rgba(0x60585880).into()), + text: Some(rgba(0x898383ff).into()), + text_muted: Some(rgba(0x655d5dff).into()), + status_bar_background: Some(rgba(0x3b3535ff).into()), + title_bar_background: Some(rgba(0x3b3535ff).into()), + toolbar_background: Some(rgba(0x1b1818ff).into()), + tab_bar_background: Some(rgba(0x252020ff).into()), + tab_inactive_background: Some(rgba(0x252020ff).into()), + tab_active_background: Some(rgba(0x1b1818ff).into()), + scrollbar_thumb_background: Some(rgba(0xf4ecec4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xf4ecec4d).into()), + scrollbar_thumb_border: Some(rgba(0x231f1fff).into()), + scrollbar_track_border: Some(rgba(0x231f1fff).into()), + editor_foreground: Some(rgba(0xe7dfdfff).into()), + editor_background: Some(rgba(0x1b1818ff).into()), + editor_gutter_background: Some(rgba(0x1b1818ff).into()), + editor_line_number: Some(rgba(0xf4ecec59).into()), + editor_active_line_number: Some(rgba(0xf4ececff).into()), + editor_wrap_guide: Some(rgba(0xf4ecec0d).into()), + editor_active_wrap_guide: Some(rgba(0xf4ecec1a).into()), + terminal_background: Some(rgba(0x1b1818ff).into()), + terminal_ansi_bright_black: Some(rgba(0x635b5bff).into()), + terminal_ansi_bright_red: Some(rgba(0x692727ff).into()), + terminal_ansi_bright_green: Some(rgba(0x2a4444ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x4e3821ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x3b3960ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x5b2c42ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x2e4257ff).into()), + terminal_ansi_bright_white: Some(rgba(0xf4ececff).into()), + terminal_ansi_black: Some(rgba(0x1b1818ff).into()), + terminal_ansi_red: Some(rgba(0xca4949ff).into()), + terminal_ansi_green: Some(rgba(0x4b8b8bff).into()), + terminal_ansi_yellow: Some(rgba(0xa06e3bff).into()), + terminal_ansi_blue: Some(rgba(0x7272caff).into()), + terminal_ansi_magenta: Some(rgba(0xbd5187ff).into()), + terminal_ansi_cyan: Some(rgba(0x5485b6ff).into()), + terminal_ansi_white: Some(rgba(0xf4ececff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x4b8b8bff).into()), + deleted: Some(rgba(0xa23b3bff).into()), + error: Some(rgba(0xca4949ff).into()), + modified: Some(rgba(0xa06e3bff).into()), + success: Some(rgba(0xf4ececff).into()), + warning: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x4b8b8bff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x655d5dff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8585ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x4b8b8bff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xf4ececff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xb45a3cff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x8a647aff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x8464c4ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xb45a3cff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x4b8b8bff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xb45a3cff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8585ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x795369ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xf4ececff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xe7dfdfff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xca4949ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xe7dfdfff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8585ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8585ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xe7dfdfff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbd5187ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x4b8b8bff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8585ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x5485b6ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbd5187ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x4b8b8bff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xb45a3cff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xf4ececff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xe7dfdfff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x8464c4ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Heath Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x675b67ff).into()), + border_variant: Some(rgba(0x675b67ff).into()), + elevated_surface_background: Some(rgba(0x433a43ff).into()), + background: Some(rgba(0x433a43ff).into()), + panel_background: Some(rgba(0x252025ff).into()), + element_hover: Some(rgba(0x675b6780).into()), + element_selected: Some(rgba(0x72647280).into()), + text: Some(rgba(0xa99aa9ff).into()), + text_muted: Some(rgba(0x776977ff).into()), + status_bar_background: Some(rgba(0x433a43ff).into()), + title_bar_background: Some(rgba(0x433a43ff).into()), + toolbar_background: Some(rgba(0x1b181bff).into()), + tab_bar_background: Some(rgba(0x252025ff).into()), + tab_inactive_background: Some(rgba(0x252025ff).into()), + tab_active_background: Some(rgba(0x1b181bff).into()), + scrollbar_thumb_background: Some(rgba(0xf7f3f74d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xf7f3f74d).into()), + scrollbar_thumb_border: Some(rgba(0x231e23ff).into()), + scrollbar_track_border: Some(rgba(0x231e23ff).into()), + editor_foreground: Some(rgba(0xd8cad8ff).into()), + editor_background: Some(rgba(0x1b181bff).into()), + editor_gutter_background: Some(rgba(0x1b181bff).into()), + editor_line_number: Some(rgba(0xf7f3f759).into()), + editor_active_line_number: Some(rgba(0xf7f3f7ff).into()), + editor_wrap_guide: Some(rgba(0xf7f3f70d).into()), + editor_active_wrap_guide: Some(rgba(0xf7f3f71a).into()), + terminal_background: Some(rgba(0x1b181bff).into()), + terminal_ansi_bright_black: Some(rgba(0x756775ff).into()), + terminal_ansi_bright_red: Some(rgba(0x6d221aff).into()), + terminal_ansi_bright_green: Some(rgba(0x474422ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x5e441fff).into()), + terminal_ansi_bright_blue: Some(rgba(0x26367eff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x6c1e67ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x1a4848ff).into()), + terminal_ansi_bright_white: Some(rgba(0xf7f3f7ff).into()), + terminal_ansi_black: Some(rgba(0x1b181bff).into()), + terminal_ansi_red: Some(rgba(0xca402cff).into()), + terminal_ansi_green: Some(rgba(0x918b3bff).into()), + terminal_ansi_yellow: Some(rgba(0xbb8a36ff).into()), + terminal_ansi_blue: Some(rgba(0x526aebff).into()), + terminal_ansi_magenta: Some(rgba(0xcc34ccff).into()), + terminal_ansi_cyan: Some(rgba(0x189393ff).into()), + terminal_ansi_white: Some(rgba(0xf7f3f7ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x918b3bff).into()), + deleted: Some(rgba(0xa43424ff).into()), + error: Some(rgba(0xca402cff).into()), + modified: Some(rgba(0xbb8a36ff).into()), + success: Some(rgba(0xf7f3f7ff).into()), + warning: Some(rgba(0xbb8a36ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3bff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x776977ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0xab9babff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3bff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xf7f3f7ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xa65927ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x516aecff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x516aecff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xbb8a35ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x8d70a8ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x7b59c0ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xa65927ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3bff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xa65926ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xab9babff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x765990ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xf7f3f7ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xd8cad8ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xca402bff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xd8cad8ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xab9babff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xab9babff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xd8cad8ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xcc33ccff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3bff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0xab9babff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x159393ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xcc33ccff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3bff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xa65927ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xf7f3f7ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xbb8a35ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xd8cad8ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x7b59c0ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xbb8a35ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Lakeside Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x4f6b78ff).into()), + border_variant: Some(rgba(0x4f6b78ff).into()), + elevated_surface_background: Some(rgba(0x33444dff).into()), + background: Some(rgba(0x33444dff).into()), + panel_background: Some(rgba(0x1c2529ff).into()), + element_hover: Some(rgba(0x4f6b7880).into()), + element_selected: Some(rgba(0x57768580).into()), + text: Some(rgba(0x7ca0b3ff).into()), + text_muted: Some(rgba(0x5a7b8bff).into()), + status_bar_background: Some(rgba(0x33444dff).into()), + title_bar_background: Some(rgba(0x33444dff).into()), + toolbar_background: Some(rgba(0x161b1dff).into()), + tab_bar_background: Some(rgba(0x1c2529ff).into()), + tab_inactive_background: Some(rgba(0x1c2529ff).into()), + tab_active_background: Some(rgba(0x161b1dff).into()), + scrollbar_thumb_background: Some(rgba(0xebf8ff4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xebf8ff4d).into()), + scrollbar_thumb_border: Some(rgba(0x1b2327ff).into()), + scrollbar_track_border: Some(rgba(0x1b2327ff).into()), + editor_foreground: Some(rgba(0xc1e4f6ff).into()), + editor_background: Some(rgba(0x161b1dff).into()), + editor_gutter_background: Some(rgba(0x161b1dff).into()), + editor_line_number: Some(rgba(0xebf8ff59).into()), + editor_active_line_number: Some(rgba(0xebf8ffff).into()), + editor_wrap_guide: Some(rgba(0xebf8ff0d).into()), + editor_active_wrap_guide: Some(rgba(0xebf8ff1a).into()), + terminal_background: Some(rgba(0x161b1dff).into()), + terminal_ansi_bright_black: Some(rgba(0x587989ff).into()), + terminal_ansi_bright_red: Some(rgba(0x6f1c3aff).into()), + terminal_ansi_bright_green: Some(rgba(0x2e4522ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x454413ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x1e3f53ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x5c1e6bff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x1f4638ff).into()), + terminal_ansi_bright_white: Some(rgba(0xebf8ffff).into()), + terminal_ansi_black: Some(rgba(0x161b1dff).into()), + terminal_ansi_red: Some(rgba(0xd22e72ff).into()), + terminal_ansi_green: Some(rgba(0x568c3bff).into()), + terminal_ansi_yellow: Some(rgba(0x8a8a11ff).into()), + terminal_ansi_blue: Some(rgba(0x277fadff).into()), + terminal_ansi_magenta: Some(rgba(0xb72ed2ff).into()), + terminal_ansi_cyan: Some(rgba(0x2e8f6fff).into()), + terminal_ansi_white: Some(rgba(0xebf8ffff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x568c3bff).into()), + deleted: Some(rgba(0xa9275aff).into()), + error: Some(rgba(0xd22e72ff).into()), + modified: Some(rgba(0x8a8a11ff).into()), + success: Some(rgba(0xebf8ffff).into()), + warning: Some(rgba(0x8a8a11ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x568c3bff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x5a7b8cff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x7ea2b4ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x568c3bff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xebf8ffff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0x935c26ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x257fadff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x257fadff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8a0fff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x52809aff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x6b6bb8ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x935c26ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x568c3bff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x935c25ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x7ea2b4ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x427088ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xebf8ffff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xc1e4f6ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xd22d72ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xc1e4f6ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x7ea2b4ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x7ea2b4ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xc1e4f6ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xb72dd2ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x568c3bff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x7ea2b4ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x2d8f6fff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xb72dd2ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x568c3bff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0x935c26ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xebf8ffff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8a0fff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xc1e4f6ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x6b6bb8ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8a0fff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Forest Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0xaaa3a1ff).into()), + border_variant: Some(rgba(0xaaa3a1ff).into()), + elevated_surface_background: Some(rgba(0xcdc8c6ff).into()), + background: Some(rgba(0xcdc8c6ff).into()), + panel_background: Some(rgba(0xe9e6e4ff).into()), + element_hover: Some(rgba(0xaaa3a180).into()), + element_selected: Some(rgba(0xa1999680).into()), + text: Some(rgba(0x6a6360ff).into()), + text_muted: Some(rgba(0x9c9491ff).into()), + status_bar_background: Some(rgba(0xcdc8c6ff).into()), + title_bar_background: Some(rgba(0xcdc8c6ff).into()), + toolbar_background: Some(rgba(0xf1efeeff).into()), + tab_bar_background: Some(rgba(0xe9e6e4ff).into()), + tab_inactive_background: Some(rgba(0xe9e6e4ff).into()), + tab_active_background: Some(rgba(0xf1efeeff).into()), + scrollbar_thumb_background: Some(rgba(0x1b19184d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x1b19184d).into()), + scrollbar_thumb_border: Some(rgba(0xebe8e6ff).into()), + scrollbar_track_border: Some(rgba(0xebe8e6ff).into()), + editor_foreground: Some(rgba(0x2c2421ff).into()), + editor_background: Some(rgba(0xf1efeeff).into()), + editor_gutter_background: Some(rgba(0xf1efeeff).into()), + editor_line_number: Some(rgba(0x1b191859).into()), + editor_active_line_number: Some(rgba(0x1b1918ff).into()), + editor_wrap_guide: Some(rgba(0x1b19180d).into()), + editor_active_wrap_guide: Some(rgba(0x1b19181a).into()), + terminal_background: Some(rgba(0xf1efeeff).into()), + terminal_ansi_bright_black: Some(rgba(0x9e9693ff).into()), + terminal_ansi_bright_red: Some(rgba(0xffa29aff).into()), + terminal_ansi_bright_green: Some(rgba(0xbfca93ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xe9c08eff).into()), + terminal_ansi_bright_blue: Some(rgba(0xaebcf4ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xe7a6fbff).into()), + terminal_ansi_bright_cyan: Some(rgba(0xa6cadbff).into()), + terminal_ansi_bright_white: Some(rgba(0x1b1918ff).into()), + terminal_ansi_black: Some(rgba(0xf1efeeff).into()), + terminal_ansi_red: Some(rgba(0xf22e41ff).into()), + terminal_ansi_green: Some(rgba(0x7b9728ff).into()), + terminal_ansi_yellow: Some(rgba(0xc3841aff).into()), + terminal_ansi_blue: Some(rgba(0x417ee6ff).into()), + terminal_ansi_magenta: Some(rgba(0xc340f2ff).into()), + terminal_ansi_cyan: Some(rgba(0x3f97b8ff).into()), + terminal_ansi_white: Some(rgba(0x1b1918ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x97ab54ff).into()), + deleted: Some(rgba(0xf22e41ff).into()), + error: Some(rgba(0xf22e41ff).into()), + modified: Some(rgba(0xc3841aff).into()), + success: Some(rgba(0x1b1918ff).into()), + warning: Some(rgba(0xc3841aff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9728ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x9c9491ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x68615eff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9728ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x1b1918ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xdf5421ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x407ee7ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x407ee7ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xc38418ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0xa67287ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x6666eaff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xdf5421ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9728ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xdf5320ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x68615eff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0xbe899eff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x1b1918ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x2c2421ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xf22c40ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x2c2421ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x68615eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x68615eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x2c2421ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xc33ff3ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9726ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x68615eff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x3d97b8ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xc33ff3ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x7b9726ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x417ee6ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xdf5421ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x1b1918ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xc38418ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x2c2421ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x6666eaff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xc38418ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Dune Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0xa8a48eff).into()), + border_variant: Some(rgba(0xa8a48eff).into()), + elevated_surface_background: Some(rgba(0xcecab4ff).into()), + background: Some(rgba(0xcecab4ff).into()), + panel_background: Some(rgba(0xeeebd7ff).into()), + element_hover: Some(rgba(0xa8a48e80).into()), + element_selected: Some(rgba(0x9e9a8580).into()), + text: Some(rgba(0x706d5fff).into()), + text_muted: Some(rgba(0x999580ff).into()), + status_bar_background: Some(rgba(0xcecab4ff).into()), + title_bar_background: Some(rgba(0xcecab4ff).into()), + toolbar_background: Some(rgba(0xfefbecff).into()), + tab_bar_background: Some(rgba(0xeeebd7ff).into()), + tab_inactive_background: Some(rgba(0xeeebd7ff).into()), + tab_active_background: Some(rgba(0xfefbecff).into()), + scrollbar_thumb_background: Some(rgba(0x20201d4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x20201d4d).into()), + scrollbar_thumb_border: Some(rgba(0xf2eedcff).into()), + scrollbar_track_border: Some(rgba(0xf2eedcff).into()), + editor_foreground: Some(rgba(0x292824ff).into()), + editor_background: Some(rgba(0xfefbecff).into()), + editor_gutter_background: Some(rgba(0xfefbecff).into()), + editor_line_number: Some(rgba(0x20201d59).into()), + editor_active_line_number: Some(rgba(0x20201dff).into()), + editor_wrap_guide: Some(rgba(0x20201d0d).into()), + editor_active_wrap_guide: Some(rgba(0x20201d1a).into()), + terminal_background: Some(rgba(0xfefbecff).into()), + terminal_ansi_bright_black: Some(rgba(0x9b9782ff).into()), + terminal_ansi_bright_red: Some(rgba(0xf7a195ff).into()), + terminal_ansi_bright_green: Some(rgba(0xb3d69cff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xdcc98eff).into()), + terminal_ansi_bright_blue: Some(rgba(0xb8c0f1ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xf3a0a4ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9ed7c0ff).into()), + terminal_ansi_bright_white: Some(rgba(0x20201dff).into()), + terminal_ansi_black: Some(rgba(0xfefbecff).into()), + terminal_ansi_red: Some(rgba(0xd73838ff).into()), + terminal_ansi_green: Some(rgba(0x61ac3aff).into()), + terminal_ansi_yellow: Some(rgba(0xae9515ff).into()), + terminal_ansi_blue: Some(rgba(0x6784e0ff).into()), + terminal_ansi_magenta: Some(rgba(0xd43753ff).into()), + terminal_ansi_cyan: Some(rgba(0x22ad83ff).into()), + terminal_ansi_white: Some(rgba(0x20201dff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x83bd62ff).into()), + deleted: Some(rgba(0xd73838ff).into()), + error: Some(rgba(0xd73838ff).into()), + modified: Some(rgba(0xae9515ff).into()), + success: Some(rgba(0x20201dff).into()), + warning: Some(rgba(0xae9515ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x6784e0ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x61ac3aff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x999580ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x6e6b5eff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x61ac3aff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x6784e0ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x20201dff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x6784e0ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x6784e0ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xb65713ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e1ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x6684e1ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xae9513ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0xb37979ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0xb854d4ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x6784e0ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xb65713ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x61ac3aff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xb65611ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x6e6b5eff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0xc88a8aff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x20201dff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x292824ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xd73737ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x292824ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x6e6b5eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x6e6b5eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x292824ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xd43552ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x60ac39ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x6e6b5eff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x1fad83ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xd43552ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x60ac39ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x6784e0ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xb65713ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x20201dff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xae9513ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x292824ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0xb854d4ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xae9513ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Plateau Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x8e8989ff).into()), + border_variant: Some(rgba(0x8e8989ff).into()), + elevated_surface_background: Some(rgba(0xc1bbbbff).into()), + background: Some(rgba(0xc1bbbbff).into()), + panel_background: Some(rgba(0xebe3e3ff).into()), + element_hover: Some(rgba(0x8e898980).into()), + element_selected: Some(rgba(0x837c7c80).into()), + text: Some(rgba(0x5a5252ff).into()), + text_muted: Some(rgba(0x7e7777ff).into()), + status_bar_background: Some(rgba(0xc1bbbbff).into()), + title_bar_background: Some(rgba(0xc1bbbbff).into()), + toolbar_background: Some(rgba(0xf4ececff).into()), + tab_bar_background: Some(rgba(0xebe3e3ff).into()), + tab_inactive_background: Some(rgba(0xebe3e3ff).into()), + tab_active_background: Some(rgba(0xf4ececff).into()), + scrollbar_thumb_background: Some(rgba(0x1b18184d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x1b18184d).into()), + scrollbar_thumb_border: Some(rgba(0xede5e5ff).into()), + scrollbar_track_border: Some(rgba(0xede5e5ff).into()), + editor_foreground: Some(rgba(0x292424ff).into()), + editor_background: Some(rgba(0xf4ececff).into()), + editor_gutter_background: Some(rgba(0xf4ececff).into()), + editor_line_number: Some(rgba(0x1b181859).into()), + editor_active_line_number: Some(rgba(0x1b1818ff).into()), + editor_wrap_guide: Some(rgba(0x1b18180d).into()), + editor_active_wrap_guide: Some(rgba(0x1b18181a).into()), + terminal_background: Some(rgba(0xf4ececff).into()), + terminal_ansi_bright_black: Some(rgba(0x807979ff).into()), + terminal_ansi_bright_red: Some(rgba(0xeda69fff).into()), + terminal_ansi_bright_green: Some(rgba(0xa6c4c4ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xd4b499ff).into()), + terminal_ansi_bright_blue: Some(rgba(0xbbb6e5ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xe2a9c2ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0xacc0daff).into()), + terminal_ansi_bright_white: Some(rgba(0x1b1818ff).into()), + terminal_ansi_black: Some(rgba(0xf4ececff).into()), + terminal_ansi_red: Some(rgba(0xca4a4aff).into()), + terminal_ansi_green: Some(rgba(0x4c8b8bff).into()), + terminal_ansi_yellow: Some(rgba(0xa06e3cff).into()), + terminal_ansi_blue: Some(rgba(0x7372caff).into()), + terminal_ansi_magenta: Some(rgba(0xbd5287ff).into()), + terminal_ansi_cyan: Some(rgba(0x5585b6ff).into()), + terminal_ansi_white: Some(rgba(0x1b1818ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x70a2a1ff).into()), + deleted: Some(rgba(0xca4a4aff).into()), + error: Some(rgba(0xca4a4aff).into()), + modified: Some(rgba(0xa06e3cff).into()), + success: Some(rgba(0x1b1818ff).into()), + warning: Some(rgba(0xa06e3cff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x7372caff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x4c8b8bff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x7e7777ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x585050ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x4c8b8bff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x7372caff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x1b1818ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x7372caff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x7372caff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xb45b3dff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x7272caff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x916a80ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x8464c4ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x7372caff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xb45b3dff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x4c8b8bff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xb45a3cff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x585050ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0xa27a91ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x1b1818ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x292424ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xca4949ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x292424ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x585050ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x585050ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x292424ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbd5187ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x4b8b8bff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x585050ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x5485b6ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbd5187ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x4b8b8bff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x7372caff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xb45b3dff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x1b1818ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x292424ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x8464c4ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xa06e3bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Seaside Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x8ea88eff).into()), + border_variant: Some(rgba(0x8ea88eff).into()), + elevated_surface_background: Some(rgba(0xb4ceb4ff).into()), + background: Some(rgba(0xb4ceb4ff).into()), + panel_background: Some(rgba(0xdaeedaff).into()), + element_hover: Some(rgba(0x8ea88e80).into()), + element_selected: Some(rgba(0x859e8580).into()), + text: Some(rgba(0x5f705fff).into()), + text_muted: Some(rgba(0x809980ff).into()), + status_bar_background: Some(rgba(0xb4ceb4ff).into()), + title_bar_background: Some(rgba(0xb4ceb4ff).into()), + toolbar_background: Some(rgba(0xf4fbf4ff).into()), + tab_bar_background: Some(rgba(0xdaeedaff).into()), + tab_inactive_background: Some(rgba(0xdaeedaff).into()), + tab_active_background: Some(rgba(0xf4fbf4ff).into()), + scrollbar_thumb_background: Some(rgba(0x1315134d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x1315134d).into()), + scrollbar_thumb_border: Some(rgba(0xdff0dfff).into()), + scrollbar_track_border: Some(rgba(0xdff0dfff).into()), + editor_foreground: Some(rgba(0x242924ff).into()), + editor_background: Some(rgba(0xf4fbf4ff).into()), + editor_gutter_background: Some(rgba(0xf4fbf4ff).into()), + editor_line_number: Some(rgba(0x13151359).into()), + editor_active_line_number: Some(rgba(0x131513ff).into()), + editor_wrap_guide: Some(rgba(0x1315130d).into()), + editor_active_wrap_guide: Some(rgba(0x1315131a).into()), + terminal_background: Some(rgba(0xf4fbf4ff).into()), + terminal_ansi_bright_black: Some(rgba(0x829b82ff).into()), + terminal_ansi_bright_red: Some(rgba(0xff9d98ff).into()), + terminal_ansi_bright_green: Some(rgba(0xa0d294ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xd0ca90ff).into()), + terminal_ansi_bright_blue: Some(rgba(0xb1adfcff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xf9a1e1ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9fccd9ff).into()), + terminal_ansi_bright_white: Some(rgba(0x131513ff).into()), + terminal_ansi_black: Some(rgba(0xf4fbf4ff).into()), + terminal_ansi_red: Some(rgba(0xe61c3dff).into()), + terminal_ansi_green: Some(rgba(0x2ba32bff).into()), + terminal_ansi_yellow: Some(rgba(0x98981dff).into()), + terminal_ansi_blue: Some(rgba(0x3f62f4ff).into()), + terminal_ansi_magenta: Some(rgba(0xe61dc3ff).into()), + terminal_ansi_cyan: Some(rgba(0x1d99b3ff).into()), + terminal_ansi_white: Some(rgba(0x131513ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x61b656ff).into()), + deleted: Some(rgba(0xe61c3dff).into()), + error: Some(rgba(0xe61c3dff).into()), + modified: Some(rgba(0x98981dff).into()), + success: Some(rgba(0x131513ff).into()), + warning: Some(rgba(0x98981dff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x3f62f4ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x2ba32bff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x809980ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6e5eff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x2ba32bff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x3f62f4ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x131513ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x3f62f4ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x3f62f4ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0x87711fff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x3d62f5ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x3d62f5ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0x98981bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x008fa1ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0xad2beeff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x3f62f4ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x87711fff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x2ba32bff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x87711dff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6e5eff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x00a2b5ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x131513ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x242924ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xe6193cff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x242924ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6e5eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6e5eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x242924ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xe619c3ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x29a329ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x5e6e5eff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x1999b3ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xe619c3ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x29a329ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x3f62f4ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0x87711fff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x131513ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x98981bff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x242924ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0xad2beeff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x98981bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Savanna Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x505e55ff).into()), + border_variant: Some(rgba(0x505e55ff).into()), + elevated_surface_background: Some(rgba(0x353f39ff).into()), + background: Some(rgba(0x353f39ff).into()), + panel_background: Some(rgba(0x1f2621ff).into()), + element_hover: Some(rgba(0x505e5580).into()), + element_selected: Some(rgba(0x5a685f80).into()), + text: Some(rgba(0x859188ff).into()), + text_muted: Some(rgba(0x5f6d64ff).into()), + status_bar_background: Some(rgba(0x353f39ff).into()), + title_bar_background: Some(rgba(0x353f39ff).into()), + toolbar_background: Some(rgba(0x171c19ff).into()), + tab_bar_background: Some(rgba(0x1f2621ff).into()), + tab_inactive_background: Some(rgba(0x1f2621ff).into()), + tab_active_background: Some(rgba(0x171c19ff).into()), + scrollbar_thumb_background: Some(rgba(0xecf4ee4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xecf4ee4d).into()), + scrollbar_thumb_border: Some(rgba(0x1e2420ff).into()), + scrollbar_track_border: Some(rgba(0x1e2420ff).into()), + editor_foreground: Some(rgba(0xdfe7e2ff).into()), + editor_background: Some(rgba(0x171c19ff).into()), + editor_gutter_background: Some(rgba(0x171c19ff).into()), + editor_line_number: Some(rgba(0xecf4ee59).into()), + editor_active_line_number: Some(rgba(0xecf4eeff).into()), + editor_wrap_guide: Some(rgba(0xecf4ee0d).into()), + editor_active_wrap_guide: Some(rgba(0xecf4ee1a).into()), + terminal_background: Some(rgba(0x171c19ff).into()), + terminal_ansi_bright_black: Some(rgba(0x5d6b62ff).into()), + terminal_ansi_bright_red: Some(rgba(0x563220ff).into()), + terminal_ansi_bright_green: Some(rgba(0x294a33ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x4e3f22ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x284546ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x423a36ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x1d4b4dff).into()), + terminal_ansi_bright_white: Some(rgba(0xecf4eeff).into()), + terminal_ansi_black: Some(rgba(0x171c19ff).into()), + terminal_ansi_red: Some(rgba(0xb16139ff).into()), + terminal_ansi_green: Some(rgba(0x489963ff).into()), + terminal_ansi_yellow: Some(rgba(0xa07e3bff).into()), + terminal_ansi_blue: Some(rgba(0x478c90ff).into()), + terminal_ansi_magenta: Some(rgba(0x867469ff).into()), + terminal_ansi_cyan: Some(rgba(0x1e9aa0ff).into()), + terminal_ansi_white: Some(rgba(0xecf4eeff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x489963ff).into()), + deleted: Some(rgba(0x8b4d2fff).into()), + error: Some(rgba(0xb16139ff).into()), + modified: Some(rgba(0xa07e3bff).into()), + success: Some(rgba(0xecf4eeff).into()), + warning: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x489963ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x5f6d64ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x87928aff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x489963ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xecf4eeff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0x9f713cff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x607e76ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x55859bff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x9f713cff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x489963ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x9f713cff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x87928aff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x506d66ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xecf4eeff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xdfe7e2ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xb16139ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xdfe7e2ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x87928aff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x87928aff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xdfe7e2ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0x867469ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x489963ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x87928aff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x1c9aa0ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0x867469ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x489963ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x478c90ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0x9f713cff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xecf4eeff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xdfe7e2ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x55859bff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Heath Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0xad9dadff).into()), + border_variant: Some(rgba(0xad9dadff).into()), + elevated_surface_background: Some(rgba(0xc6b8c6ff).into()), + background: Some(rgba(0xc6b8c6ff).into()), + panel_background: Some(rgba(0xe1d6e1ff).into()), + element_hover: Some(rgba(0xad9dad80).into()), + element_selected: Some(rgba(0xa394a380).into()), + text: Some(rgba(0x6b5e6bff).into()), + text_muted: Some(rgba(0x9e8f9eff).into()), + status_bar_background: Some(rgba(0xc6b8c6ff).into()), + title_bar_background: Some(rgba(0xc6b8c6ff).into()), + toolbar_background: Some(rgba(0xf7f3f7ff).into()), + tab_bar_background: Some(rgba(0xe1d6e1ff).into()), + tab_inactive_background: Some(rgba(0xe1d6e1ff).into()), + tab_active_background: Some(rgba(0xf7f3f7ff).into()), + scrollbar_thumb_background: Some(rgba(0x1b181b4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x1b181b4d).into()), + scrollbar_thumb_border: Some(rgba(0xe5dce5ff).into()), + scrollbar_track_border: Some(rgba(0xe5dce5ff).into()), + editor_foreground: Some(rgba(0x292329ff).into()), + editor_background: Some(rgba(0xf7f3f7ff).into()), + editor_gutter_background: Some(rgba(0xf7f3f7ff).into()), + editor_line_number: Some(rgba(0x1b181b59).into()), + editor_active_line_number: Some(rgba(0x1b181bff).into()), + editor_wrap_guide: Some(rgba(0x1b181b0d).into()), + editor_active_wrap_guide: Some(rgba(0x1b181b1a).into()), + terminal_background: Some(rgba(0xf7f3f7ff).into()), + terminal_ansi_bright_black: Some(rgba(0xa091a0ff).into()), + terminal_ansi_bright_red: Some(rgba(0xf0a28fff).into()), + terminal_ansi_bright_green: Some(rgba(0xcac49aff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xe2c398ff).into()), + terminal_ansi_bright_blue: Some(rgba(0xb4b2f7ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xeba2e6ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9ac9c8ff).into()), + terminal_ansi_bright_white: Some(rgba(0x1b181bff).into()), + terminal_ansi_black: Some(rgba(0xf7f3f7ff).into()), + terminal_ansi_red: Some(rgba(0xca412cff).into()), + terminal_ansi_green: Some(rgba(0x918b3cff).into()), + terminal_ansi_yellow: Some(rgba(0xbb8a36ff).into()), + terminal_ansi_blue: Some(rgba(0x526aebff).into()), + terminal_ansi_magenta: Some(rgba(0xcc35ccff).into()), + terminal_ansi_cyan: Some(rgba(0x199393ff).into()), + terminal_ansi_white: Some(rgba(0x1b181bff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0xa8a161ff).into()), + deleted: Some(rgba(0xca412cff).into()), + error: Some(rgba(0xca412cff).into()), + modified: Some(rgba(0xbb8a36ff).into()), + success: Some(rgba(0x1b181bff).into()), + warning: Some(rgba(0xbb8a36ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3cff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x9e8f9eff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x695d69ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3cff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x1b181bff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xa65a27ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x516aecff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x516aecff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0xbb8a35ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x8c70a6ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x7b59c0ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xa65a27ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3cff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xa65926ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x695d69ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0xa587bfff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x1b181bff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x292329ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xca402bff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x292329ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x695d69ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x695d69ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x292329ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xcc33ccff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3bff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x695d69ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x159393ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xcc33ccff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x918b3bff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x526aebff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xa65a27ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x1b181bff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xbb8a35ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x292329ff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x7b59c0ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0xbb8a35ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Atelier Lakeside Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x80a4b6ff).into()), + border_variant: Some(rgba(0x80a4b6ff).into()), + elevated_surface_background: Some(rgba(0xa6cadcff).into()), + background: Some(rgba(0xa6cadcff).into()), + panel_background: Some(rgba(0xcdeaf9ff).into()), + element_hover: Some(rgba(0x80a4b680).into()), + element_selected: Some(rgba(0x769aad80).into()), + text: Some(rgba(0x526f7dff).into()), + text_muted: Some(rgba(0x7195a8ff).into()), + status_bar_background: Some(rgba(0xa6cadcff).into()), + title_bar_background: Some(rgba(0xa6cadcff).into()), + toolbar_background: Some(rgba(0xebf8ffff).into()), + tab_bar_background: Some(rgba(0xcdeaf9ff).into()), + tab_inactive_background: Some(rgba(0xcdeaf9ff).into()), + tab_active_background: Some(rgba(0xebf8ffff).into()), + scrollbar_thumb_background: Some(rgba(0x161b1d4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x161b1d4d).into()), + scrollbar_thumb_border: Some(rgba(0xd3edfaff).into()), + scrollbar_track_border: Some(rgba(0xd3edfaff).into()), + editor_foreground: Some(rgba(0x1f292eff).into()), + editor_background: Some(rgba(0xebf8ffff).into()), + editor_gutter_background: Some(rgba(0xebf8ffff).into()), + editor_line_number: Some(rgba(0x161b1d59).into()), + editor_active_line_number: Some(rgba(0x161b1dff).into()), + editor_wrap_guide: Some(rgba(0x161b1d0d).into()), + editor_active_wrap_guide: Some(rgba(0x161b1d1a).into()), + terminal_background: Some(rgba(0xebf8ffff).into()), + terminal_ansi_bright_black: Some(rgba(0x7397aaff).into()), + terminal_ansi_bright_red: Some(rgba(0xf09fb6ff).into()), + terminal_ansi_bright_green: Some(rgba(0xabc59aff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xc8c38bff).into()), + terminal_ansi_bright_blue: Some(rgba(0x9ebdd6ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xe09fe9ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9bc7b5ff).into()), + terminal_ansi_bright_white: Some(rgba(0x161b1dff).into()), + terminal_ansi_black: Some(rgba(0xebf8ffff).into()), + terminal_ansi_red: Some(rgba(0xd22f72ff).into()), + terminal_ansi_green: Some(rgba(0x578c3cff).into()), + terminal_ansi_yellow: Some(rgba(0x8a8a11ff).into()), + terminal_ansi_blue: Some(rgba(0x277fadff).into()), + terminal_ansi_magenta: Some(rgba(0xb72fd2ff).into()), + terminal_ansi_cyan: Some(rgba(0x2f8f6fff).into()), + terminal_ansi_white: Some(rgba(0x161b1dff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x78a361ff).into()), + deleted: Some(rgba(0xd22f72ff).into()), + error: Some(rgba(0xd22f72ff).into()), + modified: Some(rgba(0x8a8a11ff).into()), + success: Some(rgba(0x161b1dff).into()), + warning: Some(rgba(0x8a8a11ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x578c3cff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x7195a8ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x516d7bff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x578c3cff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x161b1dff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0x935d26ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0x257fadff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0x257fadff).into()), + ..Default::default() + }, + ), + ( + "function.special.definition".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8a0fff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x5a87a0ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x6b6bb8ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x935d26ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x578c3cff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x935c25ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x516d7bff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x6a97b2ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x161b1dff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x1f292eff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xd22d72ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x1f292eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x516d7bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x516d7bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x1f292eff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xb72dd2ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x568c3bff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x516d7bff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x2d8f6fff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xb72dd2ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x568c3bff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x277fadff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0x935d26ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x161b1dff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8a0fff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x1f292eff).into()), + ..Default::default() + }, + ), + ( + "variable.special".into(), + UserHighlightStyle { + color: Some(rgba(0x6b6bb8ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8a0fff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + ], + } +} diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index 9c977234b9..4bd39894db 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -12,695 +12,65 @@ use crate::{ pub fn ayu() -> UserThemeFamily { UserThemeFamily { name: "Ayu".into(), - author: "dempfi (Ike Ku)".into(), + author: "Zed Industries".into(), themes: vec![ - UserTheme { - name: "Ayu Light".into(), - appearance: Appearance::Light, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x6b7d8f1f).into()), - border_variant: Some(rgba(0x6b7d8f1f).into()), - border_focused: Some(rgba(0xffaa33b3).into()), - border_selected: Some(rgba(0x6b7d8f1f).into()), - border_transparent: Some(rgba(0x6b7d8f1f).into()), - border_disabled: Some(rgba(0x6b7d8f1f).into()), - elevated_surface_background: Some(rgba(0xfcfcfcff).into()), - surface_background: Some(rgba(0xf8f9faff).into()), - background: Some(rgba(0xf8f9faff).into()), - element_background: Some(rgba(0xffaa33ff).into()), - element_hover: Some(rgba(0x56728f1f).into()), - element_selected: Some(rgba(0x56728f1f).into()), - ghost_element_hover: Some(rgba(0x56728f1f).into()), - ghost_element_selected: Some(rgba(0x56728f1f).into()), - text: Some(rgba(0x8a9199ff).into()), - text_muted: Some(rgba(0x8a9199ff).into()), - status_bar_background: Some(rgba(0xf8f9faff).into()), - title_bar_background: Some(rgba(0xf8f9faff).into()), - toolbar_background: Some(rgba(0xf8f9faff).into()), - tab_bar_background: Some(rgba(0xf8f9faff).into()), - tab_inactive_background: Some(rgba(0xf8f9faff).into()), - tab_active_background: Some(rgba(0xf8f9faff).into()), - scrollbar_thumb_background: Some(rgba(0x8a919966).into()), - scrollbar_thumb_hover_background: Some(rgba(0x8a919999).into()), - scrollbar_thumb_border: Some(rgba(0x8a919966).into()), - scrollbar_track_background: Some(rgba(0xf8f9faff).into()), - scrollbar_track_border: Some(rgba(0x6b7d8f1f).into()), - editor_foreground: Some(rgba(0x5c6166ff).into()), - editor_background: Some(rgba(0xf8f9faff).into()), - editor_gutter_background: Some(rgba(0xf8f9faff).into()), - editor_line_number: Some(rgba(0x8a919966).into()), - editor_active_line_number: Some(rgba(0x5c6166ff).into()), - editor_wrap_guide: Some(rgba(0x6b7d8f1f).into()), - editor_active_wrap_guide: Some(rgba(0x6b7d8f1f).into()), - terminal_background: Some(rgba(0xf8f9faff).into()), - terminal_ansi_bright_black: Some(rgba(0x686868ff).into()), - terminal_ansi_bright_red: Some(rgba(0xf07171ff).into()), - terminal_ansi_bright_green: Some(rgba(0x86b300ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xf2ae49ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x399ee6ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xa37accff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x4cbf99ff).into()), - terminal_ansi_bright_white: Some(rgba(0xd1d1d1ff).into()), - terminal_ansi_black: Some(rgba(0x000000ff).into()), - terminal_ansi_red: Some(rgba(0xea6c6dff).into()), - terminal_ansi_green: Some(rgba(0x6cbf43ff).into()), - terminal_ansi_yellow: Some(rgba(0xeca944ff).into()), - terminal_ansi_blue: Some(rgba(0x3199e1ff).into()), - terminal_ansi_magenta: Some(rgba(0x9e75c7ff).into()), - terminal_ansi_cyan: Some(rgba(0x46ba94ff).into()), - terminal_ansi_white: Some(rgba(0xc7c7c7ff).into()), - link_text_hover: Some(rgba(0xffaa33ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - created: Some(rgba(0x6cbf43cc).into()), - deleted: Some(rgba(0xff7383cc).into()), - error: Some(rgba(0xe65050ff).into()), - hidden: Some(rgba(0x8a9199ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x8a919980).into()), - modified: Some(rgba(0x478acccc).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xf2ae49ff).into()), - ..Default::default() - }, - ), - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0xa37accff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x787b8099).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x787b8099).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xa37accff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0x55b4d4ff).into()), - ..Default::default() - }, - ), - ( - "embedded".into(), - UserHighlightStyle { - color: Some(rgba(0x5c6166ff).into()), - ..Default::default() - }, - ), - ( - "emphasis".into(), - UserHighlightStyle { - color: Some(rgba(0xf07171ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "emphasis.strong".into(), - UserHighlightStyle { - color: Some(rgba(0xf07171ff).into()), - font_weight: Some(UserFontWeight(700.0)), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0xf2ae49ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xfa8d3eff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x86b300ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x55b4d4ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x55b4d4ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xa37accff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0xed9366ff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0xf07171ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0x5c6166ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0x55b4d480).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0x5c6166b3).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xf2ae49ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0x5c6166ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x86b300ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x4cbf99ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x86b300ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x86b300ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x86b300ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0x55b4d4ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x86b300ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x399ee6ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0x55b4d4ff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0x5c6166ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xf07171ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Ayu Mirage".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x171b24ff).into()), - border_variant: Some(rgba(0x171b24ff).into()), - border_focused: Some(rgba(0xffcc66b3).into()), - border_selected: Some(rgba(0x171b24ff).into()), - border_transparent: Some(rgba(0x171b24ff).into()), - border_disabled: Some(rgba(0x171b24ff).into()), - elevated_surface_background: Some(rgba(0x242936ff).into()), - surface_background: Some(rgba(0x1f2430ff).into()), - background: Some(rgba(0x1f2430ff).into()), - element_background: Some(rgba(0xffcc66ff).into()), - element_hover: Some(rgba(0x63759926).into()), - element_selected: Some(rgba(0x63759926).into()), - ghost_element_hover: Some(rgba(0x63759926).into()), - ghost_element_selected: Some(rgba(0x63759926).into()), - text: Some(rgba(0x707a8cff).into()), - text_muted: Some(rgba(0x707a8cff).into()), - status_bar_background: Some(rgba(0x1f2430ff).into()), - title_bar_background: Some(rgba(0x1f2430ff).into()), - toolbar_background: Some(rgba(0x1f2430ff).into()), - tab_bar_background: Some(rgba(0x1f2430ff).into()), - tab_inactive_background: Some(rgba(0x1f2430ff).into()), - tab_active_background: Some(rgba(0x1f2430ff).into()), - scrollbar_thumb_background: Some(rgba(0x707a8c66).into()), - scrollbar_thumb_hover_background: Some(rgba(0x707a8c99).into()), - scrollbar_thumb_border: Some(rgba(0x707a8c66).into()), - scrollbar_track_background: Some(rgba(0x1f2430ff).into()), - scrollbar_track_border: Some(rgba(0x171b24ff).into()), - editor_foreground: Some(rgba(0xcccac2ff).into()), - editor_background: Some(rgba(0x1f2430ff).into()), - editor_gutter_background: Some(rgba(0x1f2430ff).into()), - editor_line_number: Some(rgba(0x8a919966).into()), - editor_active_line_number: Some(rgba(0xcccac2ff).into()), - editor_wrap_guide: Some(rgba(0x171b24ff).into()), - editor_active_wrap_guide: Some(rgba(0x171b24ff).into()), - terminal_background: Some(rgba(0x1f2430ff).into()), - terminal_ansi_bright_black: Some(rgba(0x686868ff).into()), - terminal_ansi_bright_red: Some(rgba(0xf28779ff).into()), - terminal_ansi_bright_green: Some(rgba(0xd5ff80ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffd173ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x73d0ffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xdfbfffff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x95e6cbff).into()), - terminal_ansi_bright_white: Some(rgba(0xffffffff).into()), - terminal_ansi_black: Some(rgba(0x171b24ff).into()), - terminal_ansi_red: Some(rgba(0xed8274ff).into()), - terminal_ansi_green: Some(rgba(0x87d96cff).into()), - terminal_ansi_yellow: Some(rgba(0xfacc6eff).into()), - terminal_ansi_blue: Some(rgba(0x6dcbfaff).into()), - terminal_ansi_magenta: Some(rgba(0xdabafaff).into()), - terminal_ansi_cyan: Some(rgba(0x90e1c6ff).into()), - terminal_ansi_white: Some(rgba(0xc7c7c7ff).into()), - link_text_hover: Some(rgba(0xffcc66ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - created: Some(rgba(0x87d96ccc).into()), - deleted: Some(rgba(0xf27983cc).into()), - error: Some(rgba(0xff6666ff).into()), - hidden: Some(rgba(0x707a8cff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x707a8c80).into()), - modified: Some(rgba(0x80bfffcc).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xffd173ff).into()), - ..Default::default() - }, - ), - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0xdfbfffff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0xb8cfe680).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0xb8cfe680).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xdfbfffff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0x5ccfe6ff).into()), - ..Default::default() - }, - ), - ( - "embedded".into(), - UserHighlightStyle { - color: Some(rgba(0xcccac2ff).into()), - ..Default::default() - }, - ), - ( - "emphasis".into(), - UserHighlightStyle { - color: Some(rgba(0xf28779ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "emphasis.strong".into(), - UserHighlightStyle { - color: Some(rgba(0xf28779ff).into()), - font_weight: Some(UserFontWeight(700.0)), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0xffd173ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xffad66ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0xd5ff80ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x5ccfe6ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x5ccfe6ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xdfbfffff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0xf29e74ff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0xf28779ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xcccac2ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0x5ccfe680).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xcccac2b3).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xffd173ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xcccac2ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0xd5ff80ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x95e6cbff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0xd5ff80ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0xd5ff80ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0xd5ff80ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0x5ccfe6ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0xd5ff80ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x73d0ffff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0x5ccfe6ff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xcccac2ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xf28779ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, UserTheme { name: "Ayu Dark".into(), appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x1e232bff).into()), - border_variant: Some(rgba(0x1e232bff).into()), - border_focused: Some(rgba(0xe6b450b3).into()), - border_selected: Some(rgba(0x1e232bff).into()), - border_transparent: Some(rgba(0x1e232bff).into()), - border_disabled: Some(rgba(0x1e232bff).into()), - elevated_surface_background: Some(rgba(0x0d1017ff).into()), - surface_background: Some(rgba(0x0b0e14ff).into()), - background: Some(rgba(0x0b0e14ff).into()), - element_background: Some(rgba(0xe6b450ff).into()), - element_hover: Some(rgba(0x47526640).into()), - element_selected: Some(rgba(0x47526640).into()), - ghost_element_hover: Some(rgba(0x47526640).into()), - ghost_element_selected: Some(rgba(0x47526640).into()), - text: Some(rgba(0x565b66ff).into()), - text_muted: Some(rgba(0x565b66ff).into()), - status_bar_background: Some(rgba(0x0b0e14ff).into()), - title_bar_background: Some(rgba(0x0b0e14ff).into()), - toolbar_background: Some(rgba(0x0b0e14ff).into()), - tab_bar_background: Some(rgba(0x0b0e14ff).into()), - tab_inactive_background: Some(rgba(0x0b0e14ff).into()), - tab_active_background: Some(rgba(0x0b0e14ff).into()), - scrollbar_thumb_background: Some(rgba(0x565b6666).into()), - scrollbar_thumb_hover_background: Some(rgba(0x565b6699).into()), - scrollbar_thumb_border: Some(rgba(0x565b6666).into()), - scrollbar_track_background: Some(rgba(0x0b0e14ff).into()), - scrollbar_track_border: Some(rgba(0x1e232bff).into()), + border: Some(rgba(0x3f4043ff).into()), + border_variant: Some(rgba(0x3f4043ff).into()), + elevated_surface_background: Some(rgba(0x313337ff).into()), + background: Some(rgba(0x313337ff).into()), + panel_background: Some(rgba(0x1f2127ff).into()), + element_hover: Some(rgba(0x3f404380).into()), + element_selected: Some(rgba(0x50515280).into()), + text: Some(rgba(0x8a8986ff).into()), + text_muted: Some(rgba(0x58595aff).into()), + status_bar_background: Some(rgba(0x313337ff).into()), + title_bar_background: Some(rgba(0x313337ff).into()), + toolbar_background: Some(rgba(0x0d1017ff).into()), + tab_bar_background: Some(rgba(0x1f2127ff).into()), + tab_inactive_background: Some(rgba(0x1f2127ff).into()), + tab_active_background: Some(rgba(0x0d1017ff).into()), + scrollbar_thumb_background: Some(rgba(0xbfbdb64d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xbfbdb64d).into()), + scrollbar_thumb_border: Some(rgba(0x1b1e24ff).into()), + scrollbar_track_border: Some(rgba(0x1b1e24ff).into()), editor_foreground: Some(rgba(0xbfbdb6ff).into()), - editor_background: Some(rgba(0x0b0e14ff).into()), - editor_gutter_background: Some(rgba(0x0b0e14ff).into()), - editor_line_number: Some(rgba(0x6c738099).into()), + editor_background: Some(rgba(0x0d1017ff).into()), + editor_gutter_background: Some(rgba(0x0d1017ff).into()), + editor_line_number: Some(rgba(0xbfbdb659).into()), editor_active_line_number: Some(rgba(0xbfbdb6ff).into()), - editor_wrap_guide: Some(rgba(0x1e232bff).into()), - editor_active_wrap_guide: Some(rgba(0x1e232bff).into()), - terminal_background: Some(rgba(0x0b0e14ff).into()), - terminal_ansi_bright_black: Some(rgba(0x686868ff).into()), - terminal_ansi_bright_red: Some(rgba(0xf07178ff).into()), - terminal_ansi_bright_green: Some(rgba(0xaad94cff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffb454ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x59c2ffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xd2a6ffff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x95e6cbff).into()), - terminal_ansi_bright_white: Some(rgba(0xffffffff).into()), - terminal_ansi_black: Some(rgba(0x1e232bff).into()), - terminal_ansi_red: Some(rgba(0xea6c73ff).into()), - terminal_ansi_green: Some(rgba(0x7fd962ff).into()), - terminal_ansi_yellow: Some(rgba(0xf9af4fff).into()), - terminal_ansi_blue: Some(rgba(0x53bdfaff).into()), - terminal_ansi_magenta: Some(rgba(0xcda1faff).into()), - terminal_ansi_cyan: Some(rgba(0x90e1c6ff).into()), - terminal_ansi_white: Some(rgba(0xc7c7c7ff).into()), - link_text_hover: Some(rgba(0xe6b450ff).into()), + editor_wrap_guide: Some(rgba(0xbfbdb60d).into()), + editor_active_wrap_guide: Some(rgba(0xbfbdb61a).into()), + terminal_background: Some(rgba(0x0d1017ff).into()), + terminal_ansi_bright_black: Some(rgba(0x545557ff).into()), + terminal_ansi_bright_red: Some(rgba(0x83363cff).into()), + terminal_ansi_bright_green: Some(rgba(0x567627ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x92592cff).into()), + terminal_ansi_bright_blue: Some(rgba(0x28628cff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x205b78ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x4c806fff).into()), + terminal_ansi_bright_white: Some(rgba(0xbfbdb6ff).into()), + terminal_ansi_black: Some(rgba(0x0d1017ff).into()), + terminal_ansi_red: Some(rgba(0xef7178ff).into()), + terminal_ansi_green: Some(rgba(0xaad84cff).into()), + terminal_ansi_yellow: Some(rgba(0xfeb454ff).into()), + terminal_ansi_blue: Some(rgba(0x5ac2feff).into()), + terminal_ansi_magenta: Some(rgba(0x3abae5ff).into()), + terminal_ansi_cyan: Some(rgba(0x95e5cbff).into()), + terminal_ansi_white: Some(rgba(0xbfbdb6ff).into()), ..Default::default() }, status: StatusColorsRefinement { - created: Some(rgba(0x7fd962cc).into()), - deleted: Some(rgba(0xf26d78cc).into()), - error: Some(rgba(0xd95757ff).into()), - hidden: Some(rgba(0x565b66ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x565b6680).into()), - modified: Some(rgba(0x73b8ffcc).into()), + created: Some(rgba(0xaad84cff).into()), + deleted: Some(rgba(0xc3595fff).into()), + error: Some(rgba(0xef7178ff).into()), + modified: Some(rgba(0xfeb454ff).into()), + success: Some(rgba(0xbfbdb6ff).into()), + warning: Some(rgba(0xfeb454ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -708,7 +78,7 @@ pub fn ayu() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xffb454ff).into()), + color: Some(rgba(0x5ac2feff).into()), ..Default::default() }, ), @@ -723,15 +93,13 @@ pub fn ayu() -> UserThemeFamily { "comment".into(), UserHighlightStyle { color: Some(rgba(0xacb6bf8c).into()), - font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0xacb6bf8c).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x8c8b88ff).into()), ..Default::default() }, ), @@ -745,7 +113,7 @@ pub fn ayu() -> UserThemeFamily { ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0x39bae6ff).into()), + color: Some(rgba(0x5ac2feff).into()), ..Default::default() }, ), @@ -759,19 +127,25 @@ pub fn ayu() -> UserThemeFamily { ( "emphasis".into(), UserHighlightStyle { - color: Some(rgba(0xf07178ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x5ac2feff).into()), ..Default::default() }, ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xf07178ff).into()), + color: Some(rgba(0x5ac2feff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xfe8f40ff).into()), + ..Default::default() + }, + ), ( "function".into(), UserHighlightStyle { @@ -779,6 +153,14 @@ pub fn ayu() -> UserThemeFamily { ..Default::default() }, ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x638c81ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), ( "keyword".into(), UserHighlightStyle { @@ -789,21 +171,22 @@ pub fn ayu() -> UserThemeFamily { ( "label".into(), UserHighlightStyle { - color: Some(rgba(0xaad94cff).into()), + color: Some(rgba(0x5ac2feff).into()), ..Default::default() }, ), ( "link_text".into(), UserHighlightStyle { - color: Some(rgba(0x39bae6ff).into()), + color: Some(rgba(0xfe8f40ff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), ( "link_uri".into(), UserHighlightStyle { - color: Some(rgba(0x39bae6ff).into()), + color: Some(rgba(0xaad84cff).into()), ..Default::default() }, ), @@ -821,45 +204,67 @@ pub fn ayu() -> UserThemeFamily { ..Default::default() }, ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x5b728cff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xbfbdb6ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xbfbdb6ff).into()), + ..Default::default() + }, + ), ( "property".into(), UserHighlightStyle { - color: Some(rgba(0xf07178ff).into()), + color: Some(rgba(0x5ac2feff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0xbfbdb6ff).into()), + color: Some(rgba(0xa6a5a0ff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0x39bae680).into()), + color: Some(rgba(0xa6a5a0ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0xbfbdb6b3).into()), + color: Some(rgba(0xa6a5a0ff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0xffb454ff).into()), + color: Some(rgba(0xa6a5a0ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0xbfbdb6ff).into()), + color: Some(rgba(0xd2a6ffff).into()), ..Default::default() }, ), @@ -873,56 +278,57 @@ pub fn ayu() -> UserThemeFamily { ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0x95e6cbff).into()), + color: Some(rgba(0x8c8b88ff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0xaad94cff).into()), + color: Some(rgba(0x95e6cbff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0xaad94cff).into()), + color: Some(rgba(0xe6b673ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0xaad94cff).into()), + color: Some(rgba(0xfe8f40ff).into()), ..Default::default() }, ), ( "tag".into(), UserHighlightStyle { - color: Some(rgba(0x39bae6ff).into()), + color: Some(rgba(0x5ac2feff).into()), ..Default::default() }, ), ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0xaad94cff).into()), + color: Some(rgba(0xfe8f40ff).into()), ..Default::default() }, ), ( "title".into(), UserHighlightStyle { - color: Some(rgba(0x59c2ffff).into()), + color: Some(rgba(0xbfbdb6ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0x39bae6ff).into()), + color: Some(rgba(0x59c2ffff).into()), ..Default::default() }, ), @@ -934,9 +340,681 @@ pub fn ayu() -> UserThemeFamily { }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0xf07178ff).into()), + color: Some(rgba(0x5ac2feff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Ayu Light".into(), + appearance: Appearance::Light, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0xcfd1d2ff).into()), + border_variant: Some(rgba(0xcfd1d2ff).into()), + elevated_surface_background: Some(rgba(0xdcdddeff).into()), + background: Some(rgba(0xdcdddeff).into()), + panel_background: Some(rgba(0xececedff).into()), + element_hover: Some(rgba(0xcfd1d280).into()), + element_selected: Some(rgba(0xc0c2c480).into()), + text: Some(rgba(0x8c8f93ff).into()), + text_muted: Some(rgba(0xb9bbbdff).into()), + status_bar_background: Some(rgba(0xdcdddeff).into()), + title_bar_background: Some(rgba(0xdcdddeff).into()), + toolbar_background: Some(rgba(0xfcfcfcff).into()), + tab_bar_background: Some(rgba(0xececedff).into()), + tab_inactive_background: Some(rgba(0xececedff).into()), + tab_active_background: Some(rgba(0xfcfcfcff).into()), + scrollbar_thumb_background: Some(rgba(0x5c61664d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x5c61664d).into()), + scrollbar_thumb_border: Some(rgba(0xefeff0ff).into()), + scrollbar_track_border: Some(rgba(0xefeff0ff).into()), + editor_foreground: Some(rgba(0x5c6166ff).into()), + editor_background: Some(rgba(0xfcfcfcff).into()), + editor_gutter_background: Some(rgba(0xfcfcfcff).into()), + editor_line_number: Some(rgba(0x5c616659).into()), + editor_active_line_number: Some(rgba(0x5c6166ff).into()), + editor_wrap_guide: Some(rgba(0x5c61660d).into()), + editor_active_wrap_guide: Some(rgba(0x5c61661a).into()), + terminal_background: Some(rgba(0xfcfcfcff).into()), + terminal_ansi_bright_black: Some(rgba(0xbcbec0ff).into()), + terminal_ansi_bright_red: Some(rgba(0xfebab6ff).into()), + terminal_ansi_bright_green: Some(rgba(0xc7d98fff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xffd6a4ff).into()), + terminal_ansi_bright_blue: Some(rgba(0xaccef3ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xb2d9e9ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0xace0cbff).into()), + terminal_ansi_bright_white: Some(rgba(0x5c6166ff).into()), + terminal_ansi_black: Some(rgba(0xfcfcfcff).into()), + terminal_ansi_red: Some(rgba(0xef7271ff).into()), + terminal_ansi_green: Some(rgba(0x86b305ff).into()), + terminal_ansi_yellow: Some(rgba(0xf1ae4aff).into()), + terminal_ansi_blue: Some(rgba(0x3b9ee5ff).into()), + terminal_ansi_magenta: Some(rgba(0x56b4d3ff).into()), + terminal_ansi_cyan: Some(rgba(0x4dbf99ff).into()), + terminal_ansi_white: Some(rgba(0x5c6166ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0xa1c24bff).into()), + deleted: Some(rgba(0xef7271ff).into()), + error: Some(rgba(0xef7271ff).into()), + modified: Some(rgba(0xf1ae4aff).into()), + success: Some(rgba(0x5c6166ff).into()), + warning: Some(rgba(0xf1ae4aff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x3b9ee5ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0xa37accff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x787b8099).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8e91ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xa37accff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x3b9ee5ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x5c6166ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x3b9ee5ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x3b9ee5ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xf98d3fff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0xf2ae49ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x8ca7c2ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0xfa8d3eff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x3b9ee5ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xf98d3fff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x86b305ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xa37accff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xed9366ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x9eb9d3ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x5c6166ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x5c6166ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x3b9ee5ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0x73777bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0x73777bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0x73777bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0x73777bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xa37accff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0x86b300ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x8a8e91ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x4cbf99ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xe6ba7eff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0xf98d3fff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x3b9ee5ff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xf98d3fff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x5c6166ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x399ee6ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x5c6166ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x3b9ee5ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Ayu Mirage".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x53565dff).into()), + border_variant: Some(rgba(0x53565dff).into()), + elevated_surface_background: Some(rgba(0x464a52ff).into()), + background: Some(rgba(0x464a52ff).into()), + panel_background: Some(rgba(0x353944ff).into()), + element_hover: Some(rgba(0x53565d80).into()), + element_selected: Some(rgba(0x63656a80).into()), + text: Some(rgba(0x9a9a98ff).into()), + text_muted: Some(rgba(0x6b6d71ff).into()), + status_bar_background: Some(rgba(0x464a52ff).into()), + title_bar_background: Some(rgba(0x464a52ff).into()), + toolbar_background: Some(rgba(0x242936ff).into()), + tab_bar_background: Some(rgba(0x353944ff).into()), + tab_inactive_background: Some(rgba(0x353944ff).into()), + tab_active_background: Some(rgba(0x242936ff).into()), + scrollbar_thumb_background: Some(rgba(0xcccac24d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xcccac24d).into()), + scrollbar_thumb_border: Some(rgba(0x323641ff).into()), + scrollbar_track_border: Some(rgba(0x323641ff).into()), + editor_foreground: Some(rgba(0xcccac2ff).into()), + editor_background: Some(rgba(0x242936ff).into()), + editor_gutter_background: Some(rgba(0x242936ff).into()), + editor_line_number: Some(rgba(0xcccac259).into()), + editor_active_line_number: Some(rgba(0xcccac2ff).into()), + editor_wrap_guide: Some(rgba(0xcccac20d).into()), + editor_active_wrap_guide: Some(rgba(0xcccac21a).into()), + terminal_background: Some(rgba(0x242936ff).into()), + terminal_ansi_bright_black: Some(rgba(0x67696eff).into()), + terminal_ansi_bright_red: Some(rgba(0x83403dff).into()), + terminal_ansi_bright_green: Some(rgba(0x76993dff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x937238ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x346e8dff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x2b6c7bff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x4c806fff).into()), + terminal_ansi_bright_white: Some(rgba(0xcccac2ff).into()), + terminal_ansi_black: Some(rgba(0x242936ff).into()), + terminal_ansi_red: Some(rgba(0xf18779ff).into()), + terminal_ansi_green: Some(rgba(0xd5fe80ff).into()), + terminal_ansi_yellow: Some(rgba(0xfed073ff).into()), + terminal_ansi_blue: Some(rgba(0x73cffeff).into()), + terminal_ansi_magenta: Some(rgba(0x5ccee5ff).into()), + terminal_ansi_cyan: Some(rgba(0x95e5cbff).into()), + terminal_ansi_white: Some(rgba(0xcccac2ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0xd5fe80ff).into()), + deleted: Some(rgba(0xc46a60ff).into()), + error: Some(rgba(0xf18779ff).into()), + modified: Some(rgba(0xfed073ff).into()), + success: Some(rgba(0xcccac2ff).into()), + warning: Some(rgba(0xfed073ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x73cffeff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0xdfbfffff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0xb8cfe680).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x9b9b99ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xdfbfffff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x73cffeff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xcccac2ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x73cffeff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x73cffeff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xfead66ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0xffd173ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x7399a3ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0xffad66ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x73cffeff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xfead66ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0xd5fe80ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xdfbfffff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xf29e74ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x6d839bff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xcccac2ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xcccac2ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x73cffeff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xb4b3aeff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xb4b3aeff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xb4b3aeff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xb4b3aeff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xdfbfffff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0xd5ff80ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x9b9b99ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0x95e6cbff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xffdfb3ff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0xfead66ff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x73cffeff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xfead66ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xcccac2ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x73d0ffff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xcccac2ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x73cffeff).into()), ..Default::default() }, ), diff --git a/crates/theme2/src/themes/dracula.rs b/crates/theme2/src/themes/dracula.rs deleted file mode 100644 index 9d9da27eed..0000000000 --- a/crates/theme2/src/themes/dracula.rs +++ /dev/null @@ -1,250 +0,0 @@ -// This file was generated by the `theme_importer`. -// Be careful when modifying it by hand. - -use gpui::rgba; - -#[allow(unused)] -use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, -}; - -pub fn dracula() -> UserThemeFamily { - UserThemeFamily { - name: "Dracula".into(), - author: "Zeno Rocha".into(), - themes: vec![UserTheme { - name: "Dracula".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0xbd93f9ff).into()), - border_variant: Some(rgba(0xbd93f9ff).into()), - border_focused: Some(rgba(0x6272a4ff).into()), - border_selected: Some(rgba(0xbd93f9ff).into()), - border_transparent: Some(rgba(0xbd93f9ff).into()), - border_disabled: Some(rgba(0xbd93f9ff).into()), - elevated_surface_background: Some(rgba(0x343746ff).into()), - surface_background: Some(rgba(0x282a36ff).into()), - background: Some(rgba(0x282a36ff).into()), - element_background: Some(rgba(0x44475aff).into()), - element_hover: Some(rgba(0x44475a75).into()), - element_selected: Some(rgba(0x44475aff).into()), - drop_target_background: Some(rgba(0x44475aff).into()), - ghost_element_hover: Some(rgba(0x44475a75).into()), - ghost_element_selected: Some(rgba(0x44475aff).into()), - text: Some(rgba(0xf8f8f2ff).into()), - text_muted: Some(rgba(0x6272a4ff).into()), - status_bar_background: Some(rgba(0x191a21ff).into()), - title_bar_background: Some(rgba(0x21222cff).into()), - toolbar_background: Some(rgba(0x282a36ff).into()), - tab_bar_background: Some(rgba(0x191a21ff).into()), - tab_inactive_background: Some(rgba(0x21222cff).into()), - tab_active_background: Some(rgba(0x282a36ff).into()), - scrollbar_track_background: Some(rgba(0x282a36ff).into()), - scrollbar_track_border: Some(rgba(0x191a21ff).into()), - editor_foreground: Some(rgba(0xf8f8f2ff).into()), - editor_background: Some(rgba(0x282a36ff).into()), - editor_gutter_background: Some(rgba(0x282a36ff).into()), - editor_line_number: Some(rgba(0x6272a4ff).into()), - editor_active_line_number: Some(rgba(0xf8f8f2ff).into()), - editor_wrap_guide: Some(rgba(0xbd93f9ff).into()), - editor_active_wrap_guide: Some(rgba(0xbd93f9ff).into()), - terminal_background: Some(rgba(0x282a36ff).into()), - terminal_ansi_bright_black: Some(rgba(0x6272a4ff).into()), - terminal_ansi_bright_red: Some(rgba(0xff6e6eff).into()), - terminal_ansi_bright_green: Some(rgba(0x69ff94ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffffa5ff).into()), - terminal_ansi_bright_blue: Some(rgba(0xd6acffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xff92dfff).into()), - terminal_ansi_bright_cyan: Some(rgba(0xa4ffffff).into()), - terminal_ansi_bright_white: Some(rgba(0xffffffff).into()), - terminal_ansi_black: Some(rgba(0x21222cff).into()), - terminal_ansi_red: Some(rgba(0xff5555ff).into()), - terminal_ansi_green: Some(rgba(0x50fa7bff).into()), - terminal_ansi_yellow: Some(rgba(0xf1fa8cff).into()), - terminal_ansi_blue: Some(rgba(0xbd93f9ff).into()), - terminal_ansi_magenta: Some(rgba(0xff79c6ff).into()), - terminal_ansi_cyan: Some(rgba(0x8be9fdff).into()), - terminal_ansi_white: Some(rgba(0xf8f8f2ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xffb86cff).into()), - created: Some(rgba(0x50fa7b80).into()), - deleted: Some(rgba(0xff555580).into()), - error: Some(rgba(0xff5555ff).into()), - hidden: Some(rgba(0x6272a4ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x6272a4ff).into()), - modified: Some(rgba(0x8be9fd80).into()), - warning: Some(rgba(0xffb86cff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0x50fa7bff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x6272a4ff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x6272a4ff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xbd93f9ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xff79c6ff).into()), - ..Default::default() - }, - ), - ( - "emphasis".into(), - UserHighlightStyle { - color: Some(rgba(0xf1fa8cff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "emphasis.strong".into(), - UserHighlightStyle { - color: Some(rgba(0xffb86cff).into()), - font_weight: Some(UserFontWeight(700.0)), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x50fa7bff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xff79c6ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x8be9fdff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x8be9fdff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xbd93f9ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0xf1fa8cff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xf1fa8cff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0xf1fa8cff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0xf1fa8cff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0xf1fa8cff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xff79c6ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0xf1fa8cff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0x8be9fdff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xf8f8f2ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xbd93f9ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ], - }), - }, - }], - } -} diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index abce861f91..e0b2e44101 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -12,76 +12,65 @@ use crate::{ pub fn gruvbox() -> UserThemeFamily { UserThemeFamily { name: "Gruvbox".into(), - author: "morhetz".into(), + author: "Zed Industries".into(), themes: vec![ UserTheme { - name: "Gruvbox Dark Hard".into(), - appearance: Appearance::Dark, + name: "Gruvbox Light Hard".into(), + appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x3c3836ff).into()), - border_variant: Some(rgba(0x3c3836ff).into()), - border_focused: Some(rgba(0x3c3836ff).into()), - border_selected: Some(rgba(0x3c3836ff).into()), - border_transparent: Some(rgba(0x3c3836ff).into()), - border_disabled: Some(rgba(0x3c3836ff).into()), - elevated_surface_background: Some(rgba(0x1d2021ff).into()), - background: Some(rgba(0x1d2021ff).into()), - element_background: Some(rgba(0x45858880).into()), - element_hover: Some(rgba(0x3c383680).into()), - element_selected: Some(rgba(0x3c383680).into()), - drop_target_background: Some(rgba(0x3c3836ff).into()), - ghost_element_hover: Some(rgba(0x3c383680).into()), - ghost_element_selected: Some(rgba(0x3c383680).into()), - text: Some(rgba(0xebdbb2ff).into()), - text_muted: Some(rgba(0xa89984ff).into()), - status_bar_background: Some(rgba(0x1d2021ff).into()), - title_bar_background: Some(rgba(0x1d2021ff).into()), - toolbar_background: Some(rgba(0x1d2021ff).into()), - tab_bar_background: Some(rgba(0x1d2021ff).into()), - tab_inactive_background: Some(rgba(0x1d2021ff).into()), - tab_active_background: Some(rgba(0x32302fff).into()), - scrollbar_thumb_background: Some(rgba(0x50494599).into()), - scrollbar_thumb_hover_background: Some(rgba(0x665c54ff).into()), - scrollbar_thumb_border: Some(rgba(0x50494599).into()), - scrollbar_track_background: Some(rgba(0x1d2021ff).into()), - scrollbar_track_border: Some(rgba(0x1d202100).into()), - editor_foreground: Some(rgba(0xebdbb2ff).into()), - editor_background: Some(rgba(0x1d2021ff).into()), - editor_gutter_background: Some(rgba(0x1d2021ff).into()), - editor_line_number: Some(rgba(0x665c54ff).into()), - editor_active_line_number: Some(rgba(0xebdbb2ff).into()), - editor_wrap_guide: Some(rgba(0x3c3836ff).into()), - editor_active_wrap_guide: Some(rgba(0x3c3836ff).into()), - terminal_background: Some(rgba(0x1d2021ff).into()), - terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), - terminal_ansi_bright_red: Some(rgba(0xfb4934ff).into()), - terminal_ansi_bright_green: Some(rgba(0xb8bb26ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xfabd2fff).into()), - terminal_ansi_bright_blue: Some(rgba(0x83a598ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xd3869bff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x8ec07cff).into()), - terminal_ansi_bright_white: Some(rgba(0xebdbb2ff).into()), - terminal_ansi_black: Some(rgba(0x3c3836ff).into()), - terminal_ansi_red: Some(rgba(0xcc241dff).into()), - terminal_ansi_green: Some(rgba(0x98971aff).into()), - terminal_ansi_yellow: Some(rgba(0xd79921ff).into()), - terminal_ansi_blue: Some(rgba(0x458588ff).into()), - terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), - terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), - terminal_ansi_white: Some(rgba(0xa89984ff).into()), - link_text_hover: Some(rgba(0x458588ff).into()), + border: Some(rgba(0xc9b99aff).into()), + border_variant: Some(rgba(0xc9b99aff).into()), + elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), + background: Some(rgba(0xd9c8a4ff).into()), + panel_background: Some(rgba(0xecddb5ff).into()), + element_hover: Some(rgba(0xc9b99a80).into()), + element_selected: Some(rgba(0xb5a68e80).into()), + text: Some(rgba(0x5f5650ff).into()), + text_muted: Some(rgba(0xad9e87ff).into()), + status_bar_background: Some(rgba(0xd9c8a4ff).into()), + title_bar_background: Some(rgba(0xd9c8a4ff).into()), + toolbar_background: Some(rgba(0xf9f5d7ff).into()), + tab_bar_background: Some(rgba(0xecddb5ff).into()), + tab_inactive_background: Some(rgba(0xecddb5ff).into()), + tab_active_background: Some(rgba(0xf9f5d7ff).into()), + scrollbar_thumb_background: Some(rgba(0x2828284d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x2828284d).into()), + scrollbar_thumb_border: Some(rgba(0xefe2bcff).into()), + scrollbar_track_border: Some(rgba(0xefe2bcff).into()), + editor_foreground: Some(rgba(0x282828ff).into()), + editor_background: Some(rgba(0xf9f5d7ff).into()), + editor_gutter_background: Some(rgba(0xf9f5d7ff).into()), + editor_line_number: Some(rgba(0x28282859).into()), + editor_active_line_number: Some(rgba(0x282828ff).into()), + editor_wrap_guide: Some(rgba(0x2828280d).into()), + editor_active_wrap_guide: Some(rgba(0x2828281a).into()), + terminal_background: Some(rgba(0xf9f5d7ff).into()), + terminal_ansi_bright_black: Some(rgba(0xb1a28aff).into()), + terminal_ansi_bright_red: Some(rgba(0xdc8c7bff).into()), + terminal_ansi_bright_green: Some(rgba(0xbfb787ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xe2b88bff).into()), + terminal_ansi_bright_blue: Some(rgba(0x8fb0baff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xbcb5afff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9fbca8ff).into()), + terminal_ansi_bright_white: Some(rgba(0x282828ff).into()), + terminal_ansi_black: Some(rgba(0xf9f5d7ff).into()), + terminal_ansi_red: Some(rgba(0x9d0408ff).into()), + terminal_ansi_green: Some(rgba(0x797410ff).into()), + terminal_ansi_yellow: Some(rgba(0xb57616ff).into()), + terminal_ansi_blue: Some(rgba(0x0b6678ff).into()), + terminal_ansi_magenta: Some(rgba(0x7c6f64ff).into()), + terminal_ansi_cyan: Some(rgba(0x437b59ff).into()), + terminal_ansi_white: Some(rgba(0x282828ff).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xb16286ff).into()), - created: Some(rgba(0xb8bb26ff).into()), - deleted: Some(rgba(0xfb4934ff).into()), - error: Some(rgba(0xfb4934ff).into()), - hidden: Some(rgba(0xa89984ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x7c6f64ff).into()), - modified: Some(rgba(0x83a598ff).into()), + created: Some(rgba(0x958e43ff).into()), + deleted: Some(rgba(0x9d0408ff).into()), + error: Some(rgba(0x9d0408ff).into()), + modified: Some(rgba(0xb57616ff).into()), + success: Some(rgba(0x282828ff).into()), + warning: Some(rgba(0xb57616ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -89,516 +78,278 @@ pub fn gruvbox() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), + color: Some(rgba(0x0b6678ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x8f3f71ff).into()), ..Default::default() }, ), ( "comment".into(), UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x7c6f64ff).into()), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x5d544eff).into()), ..Default::default() }, ), ( "constant".into(), UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), + color: Some(rgba(0xb57614ff).into()), ..Default::default() }, ), ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), + color: Some(rgba(0x0b6678ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x427b58ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x0b6678ff).into()), ..Default::default() }, ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xfe8019ff).into()), + color: Some(rgba(0x0b6678ff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xaf3a03ff).into()), + ..Default::default() + }, + ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), + color: Some(rgba(0x79740eff).into()), ..Default::default() }, ), ( - "keyword".into(), + "function.builtin".into(), UserHighlightStyle { - color: Some(rgba(0xfb4934ff).into()), + color: Some(rgba(0x9d0006ff).into()), ..Default::default() }, ), ( - "label".into(), + "hint".into(), UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xfe8019ff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x689d6aff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xfb4934ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0x83a598ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0x83a598ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Gruvbox Dark Medium".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x3c3836ff).into()), - border_variant: Some(rgba(0x3c3836ff).into()), - border_focused: Some(rgba(0x3c3836ff).into()), - border_selected: Some(rgba(0x3c3836ff).into()), - border_transparent: Some(rgba(0x3c3836ff).into()), - border_disabled: Some(rgba(0x3c3836ff).into()), - elevated_surface_background: Some(rgba(0x282828ff).into()), - background: Some(rgba(0x282828ff).into()), - element_background: Some(rgba(0x45858880).into()), - element_hover: Some(rgba(0x3c383680).into()), - element_selected: Some(rgba(0x3c383680).into()), - drop_target_background: Some(rgba(0x3c3836ff).into()), - ghost_element_hover: Some(rgba(0x3c383680).into()), - ghost_element_selected: Some(rgba(0x3c383680).into()), - text: Some(rgba(0xebdbb2ff).into()), - text_muted: Some(rgba(0xa89984ff).into()), - status_bar_background: Some(rgba(0x282828ff).into()), - title_bar_background: Some(rgba(0x282828ff).into()), - toolbar_background: Some(rgba(0x282828ff).into()), - tab_bar_background: Some(rgba(0x282828ff).into()), - tab_inactive_background: Some(rgba(0x282828ff).into()), - tab_active_background: Some(rgba(0x3c3836ff).into()), - scrollbar_thumb_background: Some(rgba(0x50494599).into()), - scrollbar_thumb_hover_background: Some(rgba(0x665c54ff).into()), - scrollbar_thumb_border: Some(rgba(0x50494599).into()), - scrollbar_track_background: Some(rgba(0x282828ff).into()), - scrollbar_track_border: Some(rgba(0x28282800).into()), - editor_foreground: Some(rgba(0xebdbb2ff).into()), - editor_background: Some(rgba(0x282828ff).into()), - editor_gutter_background: Some(rgba(0x282828ff).into()), - editor_line_number: Some(rgba(0x665c54ff).into()), - editor_active_line_number: Some(rgba(0xebdbb2ff).into()), - editor_wrap_guide: Some(rgba(0x3c3836ff).into()), - editor_active_wrap_guide: Some(rgba(0x3c3836ff).into()), - terminal_background: Some(rgba(0x282828ff).into()), - terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), - terminal_ansi_bright_red: Some(rgba(0xfb4934ff).into()), - terminal_ansi_bright_green: Some(rgba(0xb8bb26ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xfabd2fff).into()), - terminal_ansi_bright_blue: Some(rgba(0x83a598ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xd3869bff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x8ec07cff).into()), - terminal_ansi_bright_white: Some(rgba(0xebdbb2ff).into()), - terminal_ansi_black: Some(rgba(0x3c3836ff).into()), - terminal_ansi_red: Some(rgba(0xcc241dff).into()), - terminal_ansi_green: Some(rgba(0x98971aff).into()), - terminal_ansi_yellow: Some(rgba(0xd79921ff).into()), - terminal_ansi_blue: Some(rgba(0x458588ff).into()), - terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), - terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), - terminal_ansi_white: Some(rgba(0xa89984ff).into()), - link_text_hover: Some(rgba(0x458588ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xb16286ff).into()), - created: Some(rgba(0xb8bb26ff).into()), - deleted: Some(rgba(0xfb4934ff).into()), - error: Some(rgba(0xfb4934ff).into()), - hidden: Some(rgba(0xa89984ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x7c6f64ff).into()), - modified: Some(rgba(0x83a598ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), - ..Default::default() - }, - ), - ( - "emphasis.strong".into(), - UserHighlightStyle { - color: Some(rgba(0xfe8019ff).into()), + color: Some(rgba(0x677562ff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), - ..Default::default() - }, - ), ( "keyword".into(), UserHighlightStyle { - color: Some(rgba(0xfb4934ff).into()), + color: Some(rgba(0x9d0006ff).into()), ..Default::default() }, ), ( "label".into(), UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), + color: Some(rgba(0x0b6678ff).into()), ..Default::default() }, ), ( "link_text".into(), UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), + color: Some(rgba(0x427b58ff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), ( "link_uri".into(), UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), + color: Some(rgba(0x8f3f71ff).into()), ..Default::default() }, ), ( "number".into(), UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), + color: Some(rgba(0x8f3f71ff).into()), ..Default::default() }, ), ( "operator".into(), UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), + color: Some(rgba(0x427b58ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9881ff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), ( "preproc".into(), UserHighlightStyle { - color: Some(rgba(0xfe8019ff).into()), + color: Some(rgba(0x282828ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "property".into(), UserHighlightStyle { - color: Some(rgba(0x689d6aff).into()), + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0x3c3836ff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0x665c54ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0x413d3aff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0x413d3aff).into()), ..Default::default() }, ), ( "string".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0x79740eff).into()), ..Default::default() }, ), ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0xfb4934ff).into()), + color: Some(rgba(0x5d544eff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0xaf3a03ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0x8f3f71ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0x427b58ff).into()), ..Default::default() }, ), ( "tag".into(), UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), + color: Some(rgba(0x427b58ff).into()), ..Default::default() }, ), ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0x076678ff).into()), ..Default::default() }, ), ( "title".into(), UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), + color: Some(rgba(0x79740eff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), + color: Some(rgba(0xb57614ff).into()), ..Default::default() }, ), ( "variable".into(), UserHighlightStyle { - color: Some(rgba(0x83a598ff).into()), + color: Some(rgba(0x076678ff).into()), ..Default::default() }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0x83a598ff).into()), + color: Some(rgba(0x0b6678ff).into()), ..Default::default() }, ), @@ -611,69 +362,58 @@ pub fn gruvbox() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x3c3836ff).into()), - border_variant: Some(rgba(0x3c3836ff).into()), - border_focused: Some(rgba(0x3c3836ff).into()), - border_selected: Some(rgba(0x3c3836ff).into()), - border_transparent: Some(rgba(0x3c3836ff).into()), - border_disabled: Some(rgba(0x3c3836ff).into()), - elevated_surface_background: Some(rgba(0x32302fff).into()), - background: Some(rgba(0x32302fff).into()), - element_background: Some(rgba(0x45858880).into()), - element_hover: Some(rgba(0x3c383680).into()), - element_selected: Some(rgba(0x3c383680).into()), - drop_target_background: Some(rgba(0x3c3836ff).into()), - ghost_element_hover: Some(rgba(0x3c383680).into()), - ghost_element_selected: Some(rgba(0x3c383680).into()), - text: Some(rgba(0xebdbb2ff).into()), - text_muted: Some(rgba(0xa89984ff).into()), - status_bar_background: Some(rgba(0x32302fff).into()), - title_bar_background: Some(rgba(0x32302fff).into()), + border: Some(rgba(0x5b534dff).into()), + border_variant: Some(rgba(0x5b534dff).into()), + elevated_surface_background: Some(rgba(0x4c4642ff).into()), + background: Some(rgba(0x4c4642ff).into()), + panel_background: Some(rgba(0x3b3735ff).into()), + element_hover: Some(rgba(0x5b534d80).into()), + element_selected: Some(rgba(0x6e635a80).into()), + text: Some(rgba(0xc5b597ff).into()), + text_muted: Some(rgba(0x776b61ff).into()), + status_bar_background: Some(rgba(0x4c4642ff).into()), + title_bar_background: Some(rgba(0x4c4642ff).into()), toolbar_background: Some(rgba(0x32302fff).into()), - tab_bar_background: Some(rgba(0x32302fff).into()), - tab_inactive_background: Some(rgba(0x32302fff).into()), - tab_active_background: Some(rgba(0x504945ff).into()), - scrollbar_thumb_background: Some(rgba(0x50494599).into()), - scrollbar_thumb_hover_background: Some(rgba(0x665c54ff).into()), - scrollbar_thumb_border: Some(rgba(0x50494599).into()), - scrollbar_track_background: Some(rgba(0x32302fff).into()), - scrollbar_track_border: Some(rgba(0x32302f00).into()), + tab_bar_background: Some(rgba(0x3b3735ff).into()), + tab_inactive_background: Some(rgba(0x3b3735ff).into()), + tab_active_background: Some(rgba(0x32302fff).into()), + scrollbar_thumb_background: Some(rgba(0xfbf1c74d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xfbf1c74d).into()), + scrollbar_thumb_border: Some(rgba(0x393634ff).into()), + scrollbar_track_border: Some(rgba(0x393634ff).into()), editor_foreground: Some(rgba(0xebdbb2ff).into()), editor_background: Some(rgba(0x32302fff).into()), editor_gutter_background: Some(rgba(0x32302fff).into()), - editor_line_number: Some(rgba(0x665c54ff).into()), - editor_active_line_number: Some(rgba(0xebdbb2ff).into()), - editor_wrap_guide: Some(rgba(0x3c3836ff).into()), - editor_active_wrap_guide: Some(rgba(0x3c3836ff).into()), + editor_line_number: Some(rgba(0xfbf1c759).into()), + editor_active_line_number: Some(rgba(0xfbf1c7ff).into()), + editor_wrap_guide: Some(rgba(0xfbf1c70d).into()), + editor_active_wrap_guide: Some(rgba(0xfbf1c71a).into()), terminal_background: Some(rgba(0x32302fff).into()), - terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), - terminal_ansi_bright_red: Some(rgba(0xfb4934ff).into()), - terminal_ansi_bright_green: Some(rgba(0xb8bb26ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xfabd2fff).into()), - terminal_ansi_bright_blue: Some(rgba(0x83a598ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xd3869bff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x8ec07cff).into()), - terminal_ansi_bright_white: Some(rgba(0xebdbb2ff).into()), - terminal_ansi_black: Some(rgba(0x3c3836ff).into()), - terminal_ansi_red: Some(rgba(0xcc241dff).into()), - terminal_ansi_green: Some(rgba(0x98971aff).into()), - terminal_ansi_yellow: Some(rgba(0xd79921ff).into()), - terminal_ansi_blue: Some(rgba(0x458588ff).into()), - terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), - terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), - terminal_ansi_white: Some(rgba(0xa89984ff).into()), - link_text_hover: Some(rgba(0x458588ff).into()), + terminal_ansi_bright_black: Some(rgba(0x73675eff).into()), + terminal_ansi_bright_red: Some(rgba(0x93211eff).into()), + terminal_ansi_bright_green: Some(rgba(0x615d1bff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x91611cff).into()), + terminal_ansi_bright_blue: Some(rgba(0x414f4aff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x514a41ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x45603eff).into()), + terminal_ansi_bright_white: Some(rgba(0xfbf1c7ff).into()), + terminal_ansi_black: Some(rgba(0x32302fff).into()), + terminal_ansi_red: Some(rgba(0xfb4a35ff).into()), + terminal_ansi_green: Some(rgba(0xb8bb27ff).into()), + terminal_ansi_yellow: Some(rgba(0xf9bd30ff).into()), + terminal_ansi_blue: Some(rgba(0x83a598ff).into()), + terminal_ansi_magenta: Some(rgba(0xa89984ff).into()), + terminal_ansi_cyan: Some(rgba(0x8ec07cff).into()), + terminal_ansi_white: Some(rgba(0xfbf1c7ff).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xb16286ff).into()), - created: Some(rgba(0xb8bb26ff).into()), - deleted: Some(rgba(0xfb4934ff).into()), - error: Some(rgba(0xfb4934ff).into()), - hidden: Some(rgba(0xa89984ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x7c6f64ff).into()), - modified: Some(rgba(0x83a598ff).into()), + created: Some(rgba(0xb8bb27ff).into()), + deleted: Some(rgba(0xd0382bff).into()), + error: Some(rgba(0xfb4a35ff).into()), + modified: Some(rgba(0xf9bd30ff).into()), + success: Some(rgba(0xfbf1c7ff).into()), + warning: Some(rgba(0xf9bd30ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -681,52 +421,93 @@ pub fn gruvbox() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), + color: Some(rgba(0x83a598ff).into()), ..Default::default() }, ), ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), + "boolean".into(), UserHighlightStyle { color: Some(rgba(0xd3869bff).into()), ..Default::default() }, ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0xa89984ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0xc7b798ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xfabd2fff).into()), + ..Default::default() + }, + ), ( "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), UserHighlightStyle { color: Some(rgba(0x8ec07cff).into()), ..Default::default() }, ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xfe8019ff).into()), + color: Some(rgba(0x83a598ff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xfe8019ff).into()), + ..Default::default() + }, + ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0x8ec07cff).into()), + color: Some(rgba(0xb8bb26ff).into()), + ..Default::default() + }, + ), + ( + "function.builtin".into(), + UserHighlightStyle { + color: Some(rgba(0xfb4934ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x8d957eff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), @@ -740,14 +521,15 @@ pub fn gruvbox() -> UserThemeFamily { ( "label".into(), UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), + color: Some(rgba(0x83a598ff).into()), ..Default::default() }, ), ( "link_text".into(), UserHighlightStyle { - color: Some(rgba(0xd3869bff).into()), + color: Some(rgba(0x8ec07cff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), @@ -772,24 +554,39 @@ pub fn gruvbox() -> UserThemeFamily { ..Default::default() }, ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x717363ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), ( "preproc".into(), UserHighlightStyle { - color: Some(rgba(0xfe8019ff).into()), + color: Some(rgba(0xfbf1c7ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xebdbb2ff).into()), ..Default::default() }, ), ( "property".into(), UserHighlightStyle { - color: Some(rgba(0x689d6aff).into()), + color: Some(rgba(0xebdbb2ff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0xd5c4a1ff).into()), ..Default::default() }, ), @@ -803,21 +600,21 @@ pub fn gruvbox() -> UserThemeFamily { ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0xe5d5adff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0xebdbb2ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0xa89984ff).into()), + color: Some(rgba(0xe5d5adff).into()), ..Default::default() }, ), @@ -831,28 +628,28 @@ pub fn gruvbox() -> UserThemeFamily { ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0xfb4934ff).into()), + color: Some(rgba(0xc7b798ff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0xfe8019ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0xd3869bff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0x8ec07cff).into()), ..Default::default() }, ), @@ -866,331 +663,36 @@ pub fn gruvbox() -> UserThemeFamily { ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0xb8bb26ff).into()), + color: Some(rgba(0x83a598ff).into()), ..Default::default() }, ), ( "title".into(), UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xfabd2fff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0x83a598ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0x83a598ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Gruvbox Light Hard".into(), - appearance: Appearance::Light, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0xebdbb2ff).into()), - border_variant: Some(rgba(0xebdbb2ff).into()), - border_focused: Some(rgba(0xebdbb2ff).into()), - border_selected: Some(rgba(0xebdbb2ff).into()), - border_transparent: Some(rgba(0xebdbb2ff).into()), - border_disabled: Some(rgba(0xebdbb2ff).into()), - elevated_surface_background: Some(rgba(0xf9f5d7ff).into()), - background: Some(rgba(0xf9f5d7ff).into()), - element_background: Some(rgba(0x45858880).into()), - element_hover: Some(rgba(0xebdbb280).into()), - element_selected: Some(rgba(0xebdbb280).into()), - drop_target_background: Some(rgba(0xebdbb2ff).into()), - ghost_element_hover: Some(rgba(0xebdbb280).into()), - ghost_element_selected: Some(rgba(0xebdbb280).into()), - text: Some(rgba(0x3c3836ff).into()), - text_muted: Some(rgba(0x7c6f64ff).into()), - status_bar_background: Some(rgba(0xf9f5d7ff).into()), - title_bar_background: Some(rgba(0xf9f5d7ff).into()), - toolbar_background: Some(rgba(0xf9f5d7ff).into()), - tab_bar_background: Some(rgba(0xf9f5d7ff).into()), - tab_inactive_background: Some(rgba(0xf9f5d7ff).into()), - tab_active_background: Some(rgba(0xf2e5bcff).into()), - scrollbar_thumb_background: Some(rgba(0xd5c4a199).into()), - scrollbar_thumb_hover_background: Some(rgba(0xbdae93ff).into()), - scrollbar_thumb_border: Some(rgba(0xd5c4a199).into()), - scrollbar_track_background: Some(rgba(0xf9f5d7ff).into()), - scrollbar_track_border: Some(rgba(0xf9f5d700).into()), - editor_foreground: Some(rgba(0x3c3836ff).into()), - editor_background: Some(rgba(0xf9f5d7ff).into()), - editor_gutter_background: Some(rgba(0xf9f5d7ff).into()), - editor_line_number: Some(rgba(0xbdae93ff).into()), - editor_active_line_number: Some(rgba(0x3c3836ff).into()), - editor_wrap_guide: Some(rgba(0xebdbb2ff).into()), - editor_active_wrap_guide: Some(rgba(0xebdbb2ff).into()), - terminal_background: Some(rgba(0xf9f5d7ff).into()), - terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), - terminal_ansi_bright_red: Some(rgba(0x9d0006ff).into()), - terminal_ansi_bright_green: Some(rgba(0x79740eff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xb57614ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x076678ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0x8f3f71ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x427b58ff).into()), - terminal_ansi_bright_white: Some(rgba(0x3c3836ff).into()), - terminal_ansi_black: Some(rgba(0xebdbb2ff).into()), - terminal_ansi_red: Some(rgba(0xcc241dff).into()), - terminal_ansi_green: Some(rgba(0x98971aff).into()), - terminal_ansi_yellow: Some(rgba(0xd79921ff).into()), - terminal_ansi_blue: Some(rgba(0x458588ff).into()), - terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), - terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), - terminal_ansi_white: Some(rgba(0x7c6f64ff).into()), - link_text_hover: Some(rgba(0x458588ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xb16286ff).into()), - created: Some(rgba(0x79740eff).into()), - deleted: Some(rgba(0x9d0006ff).into()), - error: Some(rgba(0x9d0006ff).into()), - hidden: Some(rgba(0x7c6f64ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0xa89984ff).into()), - modified: Some(rgba(0x076678ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0x8f3f71ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0x427b58ff).into()), - ..Default::default() - }, - ), - ( - "emphasis.strong".into(), - UserHighlightStyle { - color: Some(rgba(0xaf3a03ff).into()), + color: Some(rgba(0xb8bb26ff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x427b58ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0x9d0006ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x8f3f71ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x8f3f71ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x8f3f71ff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0x427b58ff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xaf3a03ff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x689d6aff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x9d0006ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0x427b58ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), - ..Default::default() - }, - ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), + color: Some(rgba(0xfabd2fff).into()), ..Default::default() }, ), ( "variable".into(), UserHighlightStyle { - color: Some(rgba(0x076678ff).into()), + color: Some(rgba(0x83a598ff).into()), ..Default::default() }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0x076678ff).into()), + color: Some(rgba(0x83a598ff).into()), ..Default::default() }, ), @@ -1199,73 +701,62 @@ pub fn gruvbox() -> UserThemeFamily { }, }, UserTheme { - name: "Gruvbox Light Medium".into(), + name: "Gruvbox Light".into(), appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xebdbb2ff).into()), - border_variant: Some(rgba(0xebdbb2ff).into()), - border_focused: Some(rgba(0xebdbb2ff).into()), - border_selected: Some(rgba(0xebdbb2ff).into()), - border_transparent: Some(rgba(0xebdbb2ff).into()), - border_disabled: Some(rgba(0xebdbb2ff).into()), - elevated_surface_background: Some(rgba(0xfbf1c7ff).into()), - background: Some(rgba(0xfbf1c7ff).into()), - element_background: Some(rgba(0x45858880).into()), - element_hover: Some(rgba(0xebdbb280).into()), - element_selected: Some(rgba(0xebdbb280).into()), - drop_target_background: Some(rgba(0xebdbb2ff).into()), - ghost_element_hover: Some(rgba(0xebdbb280).into()), - ghost_element_selected: Some(rgba(0xebdbb280).into()), - text: Some(rgba(0x3c3836ff).into()), - text_muted: Some(rgba(0x7c6f64ff).into()), - status_bar_background: Some(rgba(0xfbf1c7ff).into()), - title_bar_background: Some(rgba(0xfbf1c7ff).into()), + border: Some(rgba(0xc9b99aff).into()), + border_variant: Some(rgba(0xc9b99aff).into()), + elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), + background: Some(rgba(0xd9c8a4ff).into()), + panel_background: Some(rgba(0xecddb4ff).into()), + element_hover: Some(rgba(0xc9b99a80).into()), + element_selected: Some(rgba(0xb5a68e80).into()), + text: Some(rgba(0x5f5650ff).into()), + text_muted: Some(rgba(0xad9e87ff).into()), + status_bar_background: Some(rgba(0xd9c8a4ff).into()), + title_bar_background: Some(rgba(0xd9c8a4ff).into()), toolbar_background: Some(rgba(0xfbf1c7ff).into()), - tab_bar_background: Some(rgba(0xfbf1c7ff).into()), - tab_inactive_background: Some(rgba(0xfbf1c7ff).into()), - tab_active_background: Some(rgba(0xebdbb2ff).into()), - scrollbar_thumb_background: Some(rgba(0xd5c4a199).into()), - scrollbar_thumb_hover_background: Some(rgba(0xbdae93ff).into()), - scrollbar_thumb_border: Some(rgba(0xd5c4a199).into()), - scrollbar_track_background: Some(rgba(0xfbf1c7ff).into()), - scrollbar_track_border: Some(rgba(0xfbf1c700).into()), - editor_foreground: Some(rgba(0x3c3836ff).into()), + tab_bar_background: Some(rgba(0xecddb4ff).into()), + tab_inactive_background: Some(rgba(0xecddb4ff).into()), + tab_active_background: Some(rgba(0xfbf1c7ff).into()), + scrollbar_thumb_background: Some(rgba(0x2828284d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x2828284d).into()), + scrollbar_thumb_border: Some(rgba(0xefe1b8ff).into()), + scrollbar_track_border: Some(rgba(0xefe1b8ff).into()), + editor_foreground: Some(rgba(0x282828ff).into()), editor_background: Some(rgba(0xfbf1c7ff).into()), editor_gutter_background: Some(rgba(0xfbf1c7ff).into()), - editor_line_number: Some(rgba(0xbdae93ff).into()), - editor_active_line_number: Some(rgba(0x3c3836ff).into()), - editor_wrap_guide: Some(rgba(0xebdbb2ff).into()), - editor_active_wrap_guide: Some(rgba(0xebdbb2ff).into()), + editor_line_number: Some(rgba(0x28282859).into()), + editor_active_line_number: Some(rgba(0x282828ff).into()), + editor_wrap_guide: Some(rgba(0x2828280d).into()), + editor_active_wrap_guide: Some(rgba(0x2828281a).into()), terminal_background: Some(rgba(0xfbf1c7ff).into()), - terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), - terminal_ansi_bright_red: Some(rgba(0x9d0006ff).into()), - terminal_ansi_bright_green: Some(rgba(0x79740eff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xb57614ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x076678ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0x8f3f71ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x427b58ff).into()), - terminal_ansi_bright_white: Some(rgba(0x3c3836ff).into()), - terminal_ansi_black: Some(rgba(0xebdbb2ff).into()), - terminal_ansi_red: Some(rgba(0xcc241dff).into()), - terminal_ansi_green: Some(rgba(0x98971aff).into()), - terminal_ansi_yellow: Some(rgba(0xd79921ff).into()), - terminal_ansi_blue: Some(rgba(0x458588ff).into()), - terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), - terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), - terminal_ansi_white: Some(rgba(0x7c6f64ff).into()), - link_text_hover: Some(rgba(0x458588ff).into()), + terminal_ansi_bright_black: Some(rgba(0xb1a28aff).into()), + terminal_ansi_bright_red: Some(rgba(0xdc8c7bff).into()), + terminal_ansi_bright_green: Some(rgba(0xbfb787ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xe2b88bff).into()), + terminal_ansi_bright_blue: Some(rgba(0x8fb0baff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xbcb5afff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9fbca8ff).into()), + terminal_ansi_bright_white: Some(rgba(0x282828ff).into()), + terminal_ansi_black: Some(rgba(0xfbf1c7ff).into()), + terminal_ansi_red: Some(rgba(0x9d0408ff).into()), + terminal_ansi_green: Some(rgba(0x797410ff).into()), + terminal_ansi_yellow: Some(rgba(0xb57616ff).into()), + terminal_ansi_blue: Some(rgba(0x0b6678ff).into()), + terminal_ansi_magenta: Some(rgba(0x7c6f64ff).into()), + terminal_ansi_cyan: Some(rgba(0x437b59ff).into()), + terminal_ansi_white: Some(rgba(0x282828ff).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xb16286ff).into()), - created: Some(rgba(0x79740eff).into()), - deleted: Some(rgba(0x9d0006ff).into()), - error: Some(rgba(0x9d0006ff).into()), - hidden: Some(rgba(0x7c6f64ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0xa89984ff).into()), - modified: Some(rgba(0x076678ff).into()), + created: Some(rgba(0x958e43ff).into()), + deleted: Some(rgba(0x9d0408ff).into()), + error: Some(rgba(0x9d0408ff).into()), + modified: Some(rgba(0xb57616ff).into()), + success: Some(rgba(0x282828ff).into()), + warning: Some(rgba(0xb57616ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -1273,52 +764,93 @@ pub fn gruvbox() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), + color: Some(rgba(0x0b6678ff).into()), ..Default::default() }, ), ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), + "boolean".into(), UserHighlightStyle { color: Some(rgba(0x8f3f71ff).into()), ..Default::default() }, ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x7c6f64ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x5d544eff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xb57614ff).into()), + ..Default::default() + }, + ), ( "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x0b6678ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), UserHighlightStyle { color: Some(rgba(0x427b58ff).into()), ..Default::default() }, ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x0b6678ff).into()), + ..Default::default() + }, + ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xaf3a03ff).into()), + color: Some(rgba(0x0b6678ff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xaf3a03ff).into()), + ..Default::default() + }, + ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0x427b58ff).into()), + color: Some(rgba(0x79740eff).into()), + ..Default::default() + }, + ), + ( + "function.builtin".into(), + UserHighlightStyle { + color: Some(rgba(0x9d0006ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x677562ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), @@ -1332,14 +864,15 @@ pub fn gruvbox() -> UserThemeFamily { ( "label".into(), UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), + color: Some(rgba(0x0b6678ff).into()), ..Default::default() }, ), ( "link_text".into(), UserHighlightStyle { - color: Some(rgba(0x8f3f71ff).into()), + color: Some(rgba(0x427b58ff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), @@ -1364,52 +897,67 @@ pub fn gruvbox() -> UserThemeFamily { ..Default::default() }, ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9881ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), ( "preproc".into(), UserHighlightStyle { - color: Some(rgba(0xaf3a03ff).into()), + color: Some(rgba(0x282828ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "property".into(), UserHighlightStyle { - color: Some(rgba(0x689d6aff).into()), + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x3c3836ff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x665c54ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x413d3aff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x413d3aff).into()), ..Default::default() }, ), @@ -1423,28 +971,28 @@ pub fn gruvbox() -> UserThemeFamily { ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0x9d0006ff).into()), + color: Some(rgba(0x5d544eff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), + color: Some(rgba(0xaf3a03ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), + color: Some(rgba(0x8f3f71ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), + color: Some(rgba(0x427b58ff).into()), ..Default::default() }, ), @@ -1458,14 +1006,15 @@ pub fn gruvbox() -> UserThemeFamily { ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), + color: Some(rgba(0x076678ff).into()), ..Default::default() }, ), ( "title".into(), UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), + color: Some(rgba(0x79740eff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), @@ -1484,9 +1033,352 @@ pub fn gruvbox() -> UserThemeFamily { }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0x076678ff).into()), + color: Some(rgba(0x0b6678ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Gruvbox Dark".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x5b534dff).into()), + border_variant: Some(rgba(0x5b534dff).into()), + elevated_surface_background: Some(rgba(0x4c4642ff).into()), + background: Some(rgba(0x4c4642ff).into()), + panel_background: Some(rgba(0x3a3735ff).into()), + element_hover: Some(rgba(0x5b534d80).into()), + element_selected: Some(rgba(0x6e635a80).into()), + text: Some(rgba(0xc5b597ff).into()), + text_muted: Some(rgba(0x776b61ff).into()), + status_bar_background: Some(rgba(0x4c4642ff).into()), + title_bar_background: Some(rgba(0x4c4642ff).into()), + toolbar_background: Some(rgba(0x282828ff).into()), + tab_bar_background: Some(rgba(0x3a3735ff).into()), + tab_inactive_background: Some(rgba(0x3a3735ff).into()), + tab_active_background: Some(rgba(0x282828ff).into()), + scrollbar_thumb_background: Some(rgba(0xfbf1c74d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xfbf1c74d).into()), + scrollbar_thumb_border: Some(rgba(0x373432ff).into()), + scrollbar_track_border: Some(rgba(0x373432ff).into()), + editor_foreground: Some(rgba(0xebdbb2ff).into()), + editor_background: Some(rgba(0x282828ff).into()), + editor_gutter_background: Some(rgba(0x282828ff).into()), + editor_line_number: Some(rgba(0xfbf1c759).into()), + editor_active_line_number: Some(rgba(0xfbf1c7ff).into()), + editor_wrap_guide: Some(rgba(0xfbf1c70d).into()), + editor_active_wrap_guide: Some(rgba(0xfbf1c71a).into()), + terminal_background: Some(rgba(0x282828ff).into()), + terminal_ansi_bright_black: Some(rgba(0x73675eff).into()), + terminal_ansi_bright_red: Some(rgba(0x93211eff).into()), + terminal_ansi_bright_green: Some(rgba(0x615d1bff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x91611cff).into()), + terminal_ansi_bright_blue: Some(rgba(0x414f4aff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x514a41ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x45603eff).into()), + terminal_ansi_bright_white: Some(rgba(0xfbf1c7ff).into()), + terminal_ansi_black: Some(rgba(0x282828ff).into()), + terminal_ansi_red: Some(rgba(0xfb4a35ff).into()), + terminal_ansi_green: Some(rgba(0xb8bb27ff).into()), + terminal_ansi_yellow: Some(rgba(0xf9bd30ff).into()), + terminal_ansi_blue: Some(rgba(0x83a598ff).into()), + terminal_ansi_magenta: Some(rgba(0xa89984ff).into()), + terminal_ansi_cyan: Some(rgba(0x8ec07cff).into()), + terminal_ansi_white: Some(rgba(0xfbf1c7ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0xb8bb27ff).into()), + deleted: Some(rgba(0xd0382bff).into()), + error: Some(rgba(0xfb4a35ff).into()), + modified: Some(rgba(0xf9bd30ff).into()), + success: Some(rgba(0xfbf1c7ff).into()), + warning: Some(rgba(0xf9bd30ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0xd3869bff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0xa89984ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0xc7b798ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xfabd2fff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xfe8019ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0xb8bb26ff).into()), + ..Default::default() + }, + ), + ( + "function.builtin".into(), + UserHighlightStyle { + color: Some(rgba(0xfb4934ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x8d957eff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0xfb4934ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0xd3869bff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xd3869bff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x717363ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xfbf1c7ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xebdbb2ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xebdbb2ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xd5c4a1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xa89984ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xe5d5adff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xebdbb2ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xe5d5adff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0xb8bb26ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0xc7b798ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0xfe8019ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xd3869bff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xb8bb26ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xfabd2fff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), ..Default::default() }, ), @@ -1499,69 +1391,58 @@ pub fn gruvbox() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xebdbb2ff).into()), - border_variant: Some(rgba(0xebdbb2ff).into()), - border_focused: Some(rgba(0xebdbb2ff).into()), - border_selected: Some(rgba(0xebdbb2ff).into()), - border_transparent: Some(rgba(0xebdbb2ff).into()), - border_disabled: Some(rgba(0xebdbb2ff).into()), - elevated_surface_background: Some(rgba(0xf2e5bcff).into()), - background: Some(rgba(0xf2e5bcff).into()), - element_background: Some(rgba(0x45858880).into()), - element_hover: Some(rgba(0xebdbb280).into()), - element_selected: Some(rgba(0xebdbb280).into()), - drop_target_background: Some(rgba(0xebdbb2ff).into()), - ghost_element_hover: Some(rgba(0xebdbb280).into()), - ghost_element_selected: Some(rgba(0xebdbb280).into()), - text: Some(rgba(0x3c3836ff).into()), - text_muted: Some(rgba(0x7c6f64ff).into()), - status_bar_background: Some(rgba(0xf2e5bcff).into()), - title_bar_background: Some(rgba(0xf2e5bcff).into()), + border: Some(rgba(0xc9b99aff).into()), + border_variant: Some(rgba(0xc9b99aff).into()), + elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), + background: Some(rgba(0xd9c8a4ff).into()), + panel_background: Some(rgba(0xecdcb3ff).into()), + element_hover: Some(rgba(0xc9b99a80).into()), + element_selected: Some(rgba(0xb5a68e80).into()), + text: Some(rgba(0x5f5650ff).into()), + text_muted: Some(rgba(0xad9e87ff).into()), + status_bar_background: Some(rgba(0xd9c8a4ff).into()), + title_bar_background: Some(rgba(0xd9c8a4ff).into()), toolbar_background: Some(rgba(0xf2e5bcff).into()), - tab_bar_background: Some(rgba(0xf2e5bcff).into()), - tab_inactive_background: Some(rgba(0xf2e5bcff).into()), - tab_active_background: Some(rgba(0xd5c4a1ff).into()), - scrollbar_thumb_background: Some(rgba(0xd5c4a199).into()), - scrollbar_thumb_hover_background: Some(rgba(0xbdae93ff).into()), - scrollbar_thumb_border: Some(rgba(0xd5c4a199).into()), - scrollbar_track_background: Some(rgba(0xf2e5bcff).into()), - scrollbar_track_border: Some(rgba(0xf2e5bc00).into()), - editor_foreground: Some(rgba(0x3c3836ff).into()), + tab_bar_background: Some(rgba(0xecdcb3ff).into()), + tab_inactive_background: Some(rgba(0xecdcb3ff).into()), + tab_active_background: Some(rgba(0xf2e5bcff).into()), + scrollbar_thumb_background: Some(rgba(0x2828284d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x2828284d).into()), + scrollbar_thumb_border: Some(rgba(0xeddeb5ff).into()), + scrollbar_track_border: Some(rgba(0xeddeb5ff).into()), + editor_foreground: Some(rgba(0x282828ff).into()), editor_background: Some(rgba(0xf2e5bcff).into()), editor_gutter_background: Some(rgba(0xf2e5bcff).into()), - editor_line_number: Some(rgba(0xbdae93ff).into()), - editor_active_line_number: Some(rgba(0x3c3836ff).into()), - editor_wrap_guide: Some(rgba(0xebdbb2ff).into()), - editor_active_wrap_guide: Some(rgba(0xebdbb2ff).into()), + editor_line_number: Some(rgba(0x28282859).into()), + editor_active_line_number: Some(rgba(0x282828ff).into()), + editor_wrap_guide: Some(rgba(0x2828280d).into()), + editor_active_wrap_guide: Some(rgba(0x2828281a).into()), terminal_background: Some(rgba(0xf2e5bcff).into()), - terminal_ansi_bright_black: Some(rgba(0x928374ff).into()), - terminal_ansi_bright_red: Some(rgba(0x9d0006ff).into()), - terminal_ansi_bright_green: Some(rgba(0x79740eff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xb57614ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x076678ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0x8f3f71ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x427b58ff).into()), - terminal_ansi_bright_white: Some(rgba(0x3c3836ff).into()), - terminal_ansi_black: Some(rgba(0xebdbb2ff).into()), - terminal_ansi_red: Some(rgba(0xcc241dff).into()), - terminal_ansi_green: Some(rgba(0x98971aff).into()), - terminal_ansi_yellow: Some(rgba(0xd79921ff).into()), - terminal_ansi_blue: Some(rgba(0x458588ff).into()), - terminal_ansi_magenta: Some(rgba(0xb16286ff).into()), - terminal_ansi_cyan: Some(rgba(0x689d6aff).into()), - terminal_ansi_white: Some(rgba(0x7c6f64ff).into()), - link_text_hover: Some(rgba(0x458588ff).into()), + terminal_ansi_bright_black: Some(rgba(0xb1a28aff).into()), + terminal_ansi_bright_red: Some(rgba(0xdc8c7bff).into()), + terminal_ansi_bright_green: Some(rgba(0xbfb787ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xe2b88bff).into()), + terminal_ansi_bright_blue: Some(rgba(0x8fb0baff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xbcb5afff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9fbca8ff).into()), + terminal_ansi_bright_white: Some(rgba(0x282828ff).into()), + terminal_ansi_black: Some(rgba(0xf2e5bcff).into()), + terminal_ansi_red: Some(rgba(0x9d0408ff).into()), + terminal_ansi_green: Some(rgba(0x797410ff).into()), + terminal_ansi_yellow: Some(rgba(0xb57616ff).into()), + terminal_ansi_blue: Some(rgba(0x0b6678ff).into()), + terminal_ansi_magenta: Some(rgba(0x7c6f64ff).into()), + terminal_ansi_cyan: Some(rgba(0x437b59ff).into()), + terminal_ansi_white: Some(rgba(0x282828ff).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xb16286ff).into()), - created: Some(rgba(0x79740eff).into()), - deleted: Some(rgba(0x9d0006ff).into()), - error: Some(rgba(0x9d0006ff).into()), - hidden: Some(rgba(0x7c6f64ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0xa89984ff).into()), - modified: Some(rgba(0x076678ff).into()), + created: Some(rgba(0x958e43ff).into()), + deleted: Some(rgba(0x9d0408ff).into()), + error: Some(rgba(0x9d0408ff).into()), + modified: Some(rgba(0xb57616ff).into()), + success: Some(rgba(0x282828ff).into()), + warning: Some(rgba(0xb57616ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -1569,52 +1450,93 @@ pub fn gruvbox() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), + color: Some(rgba(0x0b6678ff).into()), ..Default::default() }, ), ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x928374ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), + "boolean".into(), UserHighlightStyle { color: Some(rgba(0x8f3f71ff).into()), ..Default::default() }, ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x7c6f64ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x5d544eff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xb57614ff).into()), + ..Default::default() + }, + ), ( "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x0b6678ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), UserHighlightStyle { color: Some(rgba(0x427b58ff).into()), ..Default::default() }, ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x0b6678ff).into()), + ..Default::default() + }, + ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xaf3a03ff).into()), + color: Some(rgba(0x0b6678ff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xaf3a03ff).into()), + ..Default::default() + }, + ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0x427b58ff).into()), + color: Some(rgba(0x79740eff).into()), + ..Default::default() + }, + ), + ( + "function.builtin".into(), + UserHighlightStyle { + color: Some(rgba(0x9d0006ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x677562ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), @@ -1628,14 +1550,15 @@ pub fn gruvbox() -> UserThemeFamily { ( "label".into(), UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), + color: Some(rgba(0x0b6678ff).into()), ..Default::default() }, ), ( "link_text".into(), UserHighlightStyle { - color: Some(rgba(0x8f3f71ff).into()), + color: Some(rgba(0x427b58ff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), @@ -1660,52 +1583,67 @@ pub fn gruvbox() -> UserThemeFamily { ..Default::default() }, ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x7d9881ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), ( "preproc".into(), UserHighlightStyle { - color: Some(rgba(0xaf3a03ff).into()), + color: Some(rgba(0x282828ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "property".into(), UserHighlightStyle { - color: Some(rgba(0x689d6aff).into()), + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x3c3836ff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x665c54ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x413d3aff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x282828ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0x7c6f64ff).into()), + color: Some(rgba(0x413d3aff).into()), ..Default::default() }, ), @@ -1719,28 +1657,28 @@ pub fn gruvbox() -> UserThemeFamily { ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0x9d0006ff).into()), + color: Some(rgba(0x5d544eff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), + color: Some(rgba(0xaf3a03ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), + color: Some(rgba(0x8f3f71ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), + color: Some(rgba(0x427b58ff).into()), ..Default::default() }, ), @@ -1754,14 +1692,15 @@ pub fn gruvbox() -> UserThemeFamily { ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0x79740eff).into()), + color: Some(rgba(0x076678ff).into()), ..Default::default() }, ), ( "title".into(), UserHighlightStyle { - color: Some(rgba(0xb57614ff).into()), + color: Some(rgba(0x79740eff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), @@ -1780,9 +1719,352 @@ pub fn gruvbox() -> UserThemeFamily { }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0x076678ff).into()), + color: Some(rgba(0x0b6678ff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }, + UserTheme { + name: "Gruvbox Dark Hard".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x5b534dff).into()), + border_variant: Some(rgba(0x5b534dff).into()), + elevated_surface_background: Some(rgba(0x4c4642ff).into()), + background: Some(rgba(0x4c4642ff).into()), + panel_background: Some(rgba(0x393634ff).into()), + element_hover: Some(rgba(0x5b534d80).into()), + element_selected: Some(rgba(0x6e635a80).into()), + text: Some(rgba(0xc5b597ff).into()), + text_muted: Some(rgba(0x776b61ff).into()), + status_bar_background: Some(rgba(0x4c4642ff).into()), + title_bar_background: Some(rgba(0x4c4642ff).into()), + toolbar_background: Some(rgba(0x1d2021ff).into()), + tab_bar_background: Some(rgba(0x393634ff).into()), + tab_inactive_background: Some(rgba(0x393634ff).into()), + tab_active_background: Some(rgba(0x1d2021ff).into()), + scrollbar_thumb_background: Some(rgba(0xfbf1c74d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xfbf1c74d).into()), + scrollbar_thumb_border: Some(rgba(0x343130ff).into()), + scrollbar_track_border: Some(rgba(0x343130ff).into()), + editor_foreground: Some(rgba(0xebdbb2ff).into()), + editor_background: Some(rgba(0x1d2021ff).into()), + editor_gutter_background: Some(rgba(0x1d2021ff).into()), + editor_line_number: Some(rgba(0xfbf1c759).into()), + editor_active_line_number: Some(rgba(0xfbf1c7ff).into()), + editor_wrap_guide: Some(rgba(0xfbf1c70d).into()), + editor_active_wrap_guide: Some(rgba(0xfbf1c71a).into()), + terminal_background: Some(rgba(0x1d2021ff).into()), + terminal_ansi_bright_black: Some(rgba(0x73675eff).into()), + terminal_ansi_bright_red: Some(rgba(0x93211eff).into()), + terminal_ansi_bright_green: Some(rgba(0x615d1bff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x91611cff).into()), + terminal_ansi_bright_blue: Some(rgba(0x414f4aff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x514a41ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x45603eff).into()), + terminal_ansi_bright_white: Some(rgba(0xfbf1c7ff).into()), + terminal_ansi_black: Some(rgba(0x1d2021ff).into()), + terminal_ansi_red: Some(rgba(0xfb4a35ff).into()), + terminal_ansi_green: Some(rgba(0xb8bb27ff).into()), + terminal_ansi_yellow: Some(rgba(0xf9bd30ff).into()), + terminal_ansi_blue: Some(rgba(0x83a598ff).into()), + terminal_ansi_magenta: Some(rgba(0xa89984ff).into()), + terminal_ansi_cyan: Some(rgba(0x8ec07cff).into()), + terminal_ansi_white: Some(rgba(0xfbf1c7ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0xb8bb27ff).into()), + deleted: Some(rgba(0xd0382bff).into()), + error: Some(rgba(0xfb4a35ff).into()), + modified: Some(rgba(0xf9bd30ff).into()), + success: Some(rgba(0xfbf1c7ff).into()), + warning: Some(rgba(0xf9bd30ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0xd3869bff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0xa89984ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0xc7b798ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0xfabd2fff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xfe8019ff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0xb8bb26ff).into()), + ..Default::default() + }, + ), + ( + "function.builtin".into(), + UserHighlightStyle { + color: Some(rgba(0xfb4934ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x8d957eff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0xfb4934ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0xd3869bff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0xd3869bff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x717363ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xfbf1c7ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xebdbb2ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0xebdbb2ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xd5c4a1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xa89984ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xe5d5adff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xebdbb2ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xe5d5adff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0xb8bb26ff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0xc7b798ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0xfe8019ff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xd3869bff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x8ec07cff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xb8bb26ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0xfabd2fff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), ..Default::default() }, ), diff --git a/crates/theme2/src/themes/mod.rs b/crates/theme2/src/themes/mod.rs index aaf111703f..a0ab44c871 100644 --- a/crates/theme2/src/themes/mod.rs +++ b/crates/theme2/src/themes/mod.rs @@ -2,43 +2,37 @@ // Be careful when modifying it by hand. mod andromeda; +mod atelier; mod ayu; -mod dracula; mod gruvbox; -mod night_owl; -mod noctis; -mod nord; -mod palenight; +mod one; mod rose_pine; +mod sandcastle; mod solarized; -mod synthwave_84; +mod summercamp; pub use andromeda::*; +pub use atelier::*; pub use ayu::*; -pub use dracula::*; pub use gruvbox::*; -pub use night_owl::*; -pub use noctis::*; -pub use nord::*; -pub use palenight::*; +pub use one::*; pub use rose_pine::*; +pub use sandcastle::*; pub use solarized::*; -pub use synthwave_84::*; +pub use summercamp::*; use crate::UserThemeFamily; pub(crate) fn all_user_themes() -> Vec { vec![ andromeda(), + atelier(), ayu(), - dracula(), gruvbox(), - night_owl(), - noctis(), - nord(), - palenight(), + one(), rose_pine(), + sandcastle(), solarized(), - synthwave_84(), + summercamp(), ] } diff --git a/crates/theme2/src/themes/night_owl.rs b/crates/theme2/src/themes/night_owl.rs deleted file mode 100644 index 437f79d4c7..0000000000 --- a/crates/theme2/src/themes/night_owl.rs +++ /dev/null @@ -1,547 +0,0 @@ -// This file was generated by the `theme_importer`. -// Be careful when modifying it by hand. - -use gpui::rgba; - -#[allow(unused)] -use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, -}; - -pub fn night_owl() -> UserThemeFamily { - UserThemeFamily { - name: "Night Owl".into(), - author: "Sarah Drasner (sdras)".into(), - themes: vec![ - UserTheme { - name: "Night Owl".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x5f7e97ff).into()), - border_variant: Some(rgba(0x5f7e97ff).into()), - border_focused: Some(rgba(0x122d42ff).into()), - border_selected: Some(rgba(0x5f7e97ff).into()), - border_transparent: Some(rgba(0x5f7e97ff).into()), - border_disabled: Some(rgba(0x5f7e97ff).into()), - elevated_surface_background: Some(rgba(0x011627ff).into()), - surface_background: Some(rgba(0x011627ff).into()), - background: Some(rgba(0x011627ff).into()), - element_background: Some(rgba(0x7e57c2cc).into()), - element_hover: Some(rgba(0x011627ff).into()), - element_selected: Some(rgba(0x234d708c).into()), - drop_target_background: Some(rgba(0x011627ff).into()), - ghost_element_hover: Some(rgba(0x011627ff).into()), - ghost_element_selected: Some(rgba(0x234d708c).into()), - text: Some(rgba(0xd6deebff).into()), - text_muted: Some(rgba(0x5f7e97ff).into()), - status_bar_background: Some(rgba(0x011627ff).into()), - title_bar_background: Some(rgba(0x011627ff).into()), - toolbar_background: Some(rgba(0x011627ff).into()), - tab_bar_background: Some(rgba(0x011627ff).into()), - tab_inactive_background: Some(rgba(0x01111dff).into()), - tab_active_background: Some(rgba(0x0b2942ff).into()), - scrollbar_thumb_background: Some(rgba(0x084d8180).into()), - scrollbar_thumb_hover_background: Some(rgba(0x084d8180).into()), - scrollbar_thumb_border: Some(rgba(0x084d8180).into()), - scrollbar_track_background: Some(rgba(0x011627ff).into()), - editor_foreground: Some(rgba(0xd6deebff).into()), - editor_background: Some(rgba(0x011627ff).into()), - editor_gutter_background: Some(rgba(0x011627ff).into()), - editor_line_number: Some(rgba(0x4b6479ff).into()), - editor_active_line_number: Some(rgba(0xd6deebff).into()), - editor_wrap_guide: Some(rgba(0x5f7e97ff).into()), - editor_active_wrap_guide: Some(rgba(0x5f7e97ff).into()), - terminal_ansi_bright_black: Some(rgba(0x575656ff).into()), - terminal_ansi_bright_red: Some(rgba(0xef5350ff).into()), - terminal_ansi_bright_green: Some(rgba(0x22da6eff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffeb95ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x82aaffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xc792eaff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x7fdbcaff).into()), - terminal_ansi_bright_white: Some(rgba(0xffffffff).into()), - terminal_ansi_black: Some(rgba(0x011627ff).into()), - terminal_ansi_red: Some(rgba(0xef5350ff).into()), - terminal_ansi_green: Some(rgba(0x22da6eff).into()), - terminal_ansi_yellow: Some(rgba(0xc5e478ff).into()), - terminal_ansi_blue: Some(rgba(0x82aaffff).into()), - terminal_ansi_magenta: Some(rgba(0xc792eaff).into()), - terminal_ansi_cyan: Some(rgba(0x21c7a8ff).into()), - terminal_ansi_white: Some(rgba(0xffffffff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xffeb95cc).into()), - created: Some(rgba(0x9ccc65ff).into()), - deleted: Some(rgba(0xef5350ff).into()), - error: Some(rgba(0xef5350ff).into()), - hidden: Some(rgba(0x5f7e97ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x395a75ff).into()), - modified: Some(rgba(0xe2b93dff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xc5e478ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x637777ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x637777ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xcaece6ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xf78c6cff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0x7fdbcaff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x80cbc4ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0xecc48dff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0xecc48dff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0xecc48dff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0xecc48dff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xcaece6ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0xecc48dff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xc5e478ff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xc5e478ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0x7fdbcaff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Night Owl Light".into(), - appearance: Appearance::Light, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0xd9d9d9ff).into()), - border_variant: Some(rgba(0xd9d9d9ff).into()), - border_focused: Some(rgba(0x93a1a1ff).into()), - border_selected: Some(rgba(0xd9d9d9ff).into()), - border_transparent: Some(rgba(0xd9d9d9ff).into()), - border_disabled: Some(rgba(0xd9d9d9ff).into()), - elevated_surface_background: Some(rgba(0xf0f0f0ff).into()), - surface_background: Some(rgba(0xf0f0f0ff).into()), - background: Some(rgba(0xfbfbfbff).into()), - element_background: Some(rgba(0x2aa298ff).into()), - element_hover: Some(rgba(0xd3e8f8ff).into()), - element_selected: Some(rgba(0xd3e8f8ff).into()), - ghost_element_hover: Some(rgba(0xd3e8f8ff).into()), - ghost_element_selected: Some(rgba(0xd3e8f8ff).into()), - text: Some(rgba(0x403f53ff).into()), - text_muted: Some(rgba(0x403f53ff).into()), - status_bar_background: Some(rgba(0xf0f0f0ff).into()), - title_bar_background: Some(rgba(0xf0f0f0ff).into()), - toolbar_background: Some(rgba(0xfbfbfbff).into()), - tab_bar_background: Some(rgba(0xf0f0f0ff).into()), - tab_inactive_background: Some(rgba(0xf0f0f0ff).into()), - tab_active_background: Some(rgba(0xf6f6f6ff).into()), - scrollbar_track_background: Some(rgba(0xfbfbfbff).into()), - editor_foreground: Some(rgba(0x403f53ff).into()), - editor_background: Some(rgba(0xfbfbfbff).into()), - editor_gutter_background: Some(rgba(0xfbfbfbff).into()), - editor_line_number: Some(rgba(0x90a7b2ff).into()), - editor_active_line_number: Some(rgba(0x403f53ff).into()), - editor_wrap_guide: Some(rgba(0xd9d9d9ff).into()), - editor_active_wrap_guide: Some(rgba(0xd9d9d9ff).into()), - terminal_background: Some(rgba(0xf6f6f6ff).into()), - terminal_ansi_bright_black: Some(rgba(0x403f53ff).into()), - terminal_ansi_bright_red: Some(rgba(0xde3d3bff).into()), - terminal_ansi_bright_green: Some(rgba(0x08916aff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xdaaa01ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x288ed7ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xd6438aff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x2aa298ff).into()), - terminal_ansi_bright_white: Some(rgba(0xf0f0f0ff).into()), - terminal_ansi_black: Some(rgba(0x403f53ff).into()), - terminal_ansi_red: Some(rgba(0xde3d3bff).into()), - terminal_ansi_green: Some(rgba(0x08916aff).into()), - terminal_ansi_yellow: Some(rgba(0xe0af02ff).into()), - terminal_ansi_blue: Some(rgba(0x288ed7ff).into()), - terminal_ansi_magenta: Some(rgba(0xd6438aff).into()), - terminal_ansi_cyan: Some(rgba(0x2aa298ff).into()), - terminal_ansi_white: Some(rgba(0xf0f0f0ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - created: Some(rgba(0x49d0c5ff).into()), - deleted: Some(rgba(0xf76e6eff).into()), - error: Some(rgba(0x403f53ff).into()), - hidden: Some(rgba(0x403f53ff).into()), - hint: Some(rgba(0x969696ff).into()), - modified: Some(rgba(0x6fbef6ff).into()), - warning: Some(rgba(0xdaaa01ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x989fb1ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x989fb1ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0x994cc3ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0x994cc3ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xaa0982ff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0x0c969bff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x0c969bff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0x994cc3ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0x994cc3ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0x994cc3ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0x994cc3ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0x994cc3ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0x994cc3ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0x4876d6ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0x0c969bff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - ], - } -} diff --git a/crates/theme2/src/themes/noctis.rs b/crates/theme2/src/themes/noctis.rs deleted file mode 100644 index 55aea3d24c..0000000000 --- a/crates/theme2/src/themes/noctis.rs +++ /dev/null @@ -1,3110 +0,0 @@ -// This file was generated by the `theme_importer`. -// Be careful when modifying it by hand. - -use gpui::rgba; - -#[allow(unused)] -use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, -}; - -pub fn noctis() -> UserThemeFamily { - UserThemeFamily { - name: "Noctis".into(), - author: "Liviu Schera (liviuschera)".into(), - themes: vec![ - UserTheme { - name: "Noctis Azureus".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x1679b6ff).into()), - border_variant: Some(rgba(0x1679b6ff).into()), - border_focused: Some(rgba(0x09334eff).into()), - border_selected: Some(rgba(0x1679b6ff).into()), - border_transparent: Some(rgba(0x1679b6ff).into()), - border_disabled: Some(rgba(0x1679b6ff).into()), - elevated_surface_background: Some(rgba(0x09334eff).into()), - surface_background: Some(rgba(0x051b29ff).into()), - background: Some(rgba(0x07273bff).into()), - element_background: Some(rgba(0x007f99ff).into()), - element_hover: Some(rgba(0x00558a65).into()), - element_selected: Some(rgba(0x0c3f5fff).into()), - drop_target_background: Some(rgba(0x002a4dff).into()), - ghost_element_hover: Some(rgba(0x00558a65).into()), - ghost_element_selected: Some(rgba(0x0c3f5fff).into()), - text: Some(rgba(0xbecfdaff).into()), - text_muted: Some(rgba(0x9fb6c6ff).into()), - status_bar_background: Some(rgba(0x07273bff).into()), - title_bar_background: Some(rgba(0x07273bff).into()), - toolbar_background: Some(rgba(0x07273bff).into()), - tab_bar_background: Some(rgba(0x09334eff).into()), - tab_inactive_background: Some(rgba(0x09334eff).into()), - tab_active_background: Some(rgba(0x07273bff).into()), - scrollbar_thumb_background: Some(rgba(0x008ee633).into()), - scrollbar_thumb_hover_background: Some(rgba(0x008ee655).into()), - scrollbar_thumb_border: Some(rgba(0x008ee633).into()), - scrollbar_track_background: Some(rgba(0x07273bff).into()), - scrollbar_track_border: Some(rgba(0x07273bff).into()), - editor_foreground: Some(rgba(0xbecfdaff).into()), - editor_background: Some(rgba(0x07273bff).into()), - editor_gutter_background: Some(rgba(0x07273bff).into()), - editor_line_number: Some(rgba(0x4d6c80ff).into()), - editor_active_line_number: Some(rgba(0xbecfdaff).into()), - editor_wrap_guide: Some(rgba(0x1679b6ff).into()), - editor_active_wrap_guide: Some(rgba(0x1679b6ff).into()), - terminal_background: Some(rgba(0x051b29ff).into()), - terminal_ansi_bright_black: Some(rgba(0x475e6cff).into()), - terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), - terminal_ansi_bright_green: Some(rgba(0x60ebb1ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xe69533ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x60b6ebff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xe798b3ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x60dbebff).into()), - terminal_ansi_bright_white: Some(rgba(0xbecfdaff).into()), - terminal_ansi_black: Some(rgba(0x28353eff).into()), - terminal_ansi_red: Some(rgba(0xe66533ff).into()), - terminal_ansi_green: Some(rgba(0x49e9a6ff).into()), - terminal_ansi_yellow: Some(rgba(0xe4b781ff).into()), - terminal_ansi_blue: Some(rgba(0x49ace9ff).into()), - terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), - terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), - terminal_ansi_white: Some(rgba(0xaec3d0ff).into()), - link_text_hover: Some(rgba(0x49ace9ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xffc180ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xe34e1cff).into()), - error: Some(rgba(0xe34e1cff).into()), - hidden: Some(rgba(0x9fb6c6ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x5b788bff).into()), - modified: Some(rgba(0xffc180ff).into()), - warning: Some(rgba(0xffa857ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x5988a6ff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x5988a6ff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xd5971aff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xdf769bff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xbecfdaff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xbecfdaff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xbecfdaff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xbecfdaff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xbecfdaff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xbecfdaff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xd67e5cff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xe4b781ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Bordo".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x997582ff).into()), - border_variant: Some(rgba(0x997582ff).into()), - border_focused: Some(rgba(0x413036ff).into()), - border_selected: Some(rgba(0x997582ff).into()), - border_transparent: Some(rgba(0x997582ff).into()), - border_disabled: Some(rgba(0x997582ff).into()), - elevated_surface_background: Some(rgba(0x413036ff).into()), - surface_background: Some(rgba(0x272022ff).into()), - background: Some(rgba(0x322a2dff).into()), - element_background: Some(rgba(0x007f99ff).into()), - element_hover: Some(rgba(0x533641ff).into()), - element_selected: Some(rgba(0x5c2e3e99).into()), - drop_target_background: Some(rgba(0x38292eff).into()), - ghost_element_hover: Some(rgba(0x533641ff).into()), - ghost_element_selected: Some(rgba(0x5c2e3e99).into()), - text: Some(rgba(0xcbbec2ff).into()), - text_muted: Some(rgba(0xbbaab0ff).into()), - status_bar_background: Some(rgba(0x322a2dff).into()), - title_bar_background: Some(rgba(0x322a2dff).into()), - toolbar_background: Some(rgba(0x322a2dff).into()), - tab_bar_background: Some(rgba(0x413036ff).into()), - tab_inactive_background: Some(rgba(0x413036ff).into()), - tab_active_background: Some(rgba(0x322a2dff).into()), - scrollbar_thumb_background: Some(rgba(0xeb609133).into()), - scrollbar_thumb_hover_background: Some(rgba(0xeb609144).into()), - scrollbar_thumb_border: Some(rgba(0xeb609133).into()), - scrollbar_track_background: Some(rgba(0x322a2dff).into()), - scrollbar_track_border: Some(rgba(0x322a2dff).into()), - editor_foreground: Some(rgba(0xcbbec2ff).into()), - editor_background: Some(rgba(0x322a2dff).into()), - editor_gutter_background: Some(rgba(0x322a2dff).into()), - editor_line_number: Some(rgba(0x715b63ff).into()), - editor_active_line_number: Some(rgba(0xcbbec2ff).into()), - editor_wrap_guide: Some(rgba(0x997582ff).into()), - editor_active_wrap_guide: Some(rgba(0x997582ff).into()), - terminal_background: Some(rgba(0x272022ff).into()), - terminal_ansi_bright_black: Some(rgba(0x69545bff).into()), - terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), - terminal_ansi_bright_green: Some(rgba(0x60ebb1ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xe69533ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x60b6ebff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xe798b3ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x60dbebff).into()), - terminal_ansi_bright_white: Some(rgba(0xcbbec2ff).into()), - terminal_ansi_black: Some(rgba(0x47393eff).into()), - terminal_ansi_red: Some(rgba(0xe66533ff).into()), - terminal_ansi_green: Some(rgba(0x49e9a6ff).into()), - terminal_ansi_yellow: Some(rgba(0xe4b781ff).into()), - terminal_ansi_blue: Some(rgba(0x49ace9ff).into()), - terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), - terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), - terminal_ansi_white: Some(rgba(0xb9acb0ff).into()), - link_text_hover: Some(rgba(0xf18eb0ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xffc180ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xe34e1cff).into()), - error: Some(rgba(0xe34e1cff).into()), - hidden: Some(rgba(0xbbaab0ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x5b788bff).into()), - modified: Some(rgba(0xffc180ff).into()), - warning: Some(rgba(0xffa857ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x8b747cff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x8b747cff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xd5971aff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xdf769bff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xcbbec2ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xcbbec2ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xcbbec2ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xcbbec2ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xcbbec2ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xcbbec2ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xd67e5cff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xe4b781ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Hibernus".into(), - appearance: Appearance::Light, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x00c6e0ff).into()), - border_variant: Some(rgba(0x00c6e0ff).into()), - border_focused: Some(rgba(0xe0eff1ff).into()), - border_selected: Some(rgba(0x00c6e0ff).into()), - border_transparent: Some(rgba(0x00c6e0ff).into()), - border_disabled: Some(rgba(0x00c6e0ff).into()), - elevated_surface_background: Some(rgba(0xf4f6f6ff).into()), - surface_background: Some(rgba(0xe1eeefff).into()), - background: Some(rgba(0xf4f6f6ff).into()), - element_background: Some(rgba(0x099099ff).into()), - element_hover: Some(rgba(0xd1eafaff).into()), - element_selected: Some(rgba(0xb6e1e7ff).into()), - drop_target_background: Some(rgba(0xb2cacdff).into()), - ghost_element_hover: Some(rgba(0xd1eafaff).into()), - ghost_element_selected: Some(rgba(0xb6e1e7ff).into()), - text: Some(rgba(0x005661ff).into()), - text_muted: Some(rgba(0x71838eff).into()), - status_bar_background: Some(rgba(0xcaedf2ff).into()), - title_bar_background: Some(rgba(0xe7f2f3ff).into()), - toolbar_background: Some(rgba(0xf4f6f6ff).into()), - tab_bar_background: Some(rgba(0xcaedf2ff).into()), - tab_inactive_background: Some(rgba(0xcaedf2ff).into()), - tab_active_background: Some(rgba(0xf4f6f6ff).into()), - scrollbar_thumb_background: Some(rgba(0x6a90955b).into()), - scrollbar_thumb_hover_background: Some(rgba(0x0099ad62).into()), - scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), - scrollbar_track_background: Some(rgba(0xf4f6f6ff).into()), - scrollbar_track_border: Some(rgba(0xf4f6f6ff).into()), - editor_foreground: Some(rgba(0x005661ff).into()), - editor_background: Some(rgba(0xf4f6f6ff).into()), - editor_gutter_background: Some(rgba(0xf4f6f6ff).into()), - editor_line_number: Some(rgba(0xa0abacff).into()), - editor_active_line_number: Some(rgba(0x005661ff).into()), - editor_wrap_guide: Some(rgba(0x00c6e0ff).into()), - editor_active_wrap_guide: Some(rgba(0x00c6e0ff).into()), - terminal_background: Some(rgba(0xe1eeefff).into()), - terminal_ansi_bright_black: Some(rgba(0x004d57ff).into()), - terminal_ansi_bright_red: Some(rgba(0xff4000ff).into()), - terminal_ansi_bright_green: Some(rgba(0x00d17aff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xff8c00ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x0fa3ffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xff6b9fff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x00cbe6ff).into()), - terminal_ansi_bright_white: Some(rgba(0xbbc3c4ff).into()), - terminal_ansi_black: Some(rgba(0x003b42ff).into()), - terminal_ansi_red: Some(rgba(0xe34e1cff).into()), - terminal_ansi_green: Some(rgba(0x00b368ff).into()), - terminal_ansi_yellow: Some(rgba(0xf49725ff).into()), - terminal_ansi_blue: Some(rgba(0x0094f0ff).into()), - terminal_ansi_magenta: Some(rgba(0xff5792ff).into()), - terminal_ansi_cyan: Some(rgba(0x00bdd6ff).into()), - terminal_ansi_white: Some(rgba(0x8ca6a6ff).into()), - link_text_hover: Some(rgba(0x00c6e0ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xe9a149ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xff4000ff).into()), - error: Some(rgba(0xff4000ff).into()), - hidden: Some(rgba(0x71838eff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0xa8a28faa).into()), - modified: Some(rgba(0xe9a149ff).into()), - warning: Some(rgba(0xe07a52ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x5842ffff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x8ca6a6ff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x8ca6a6ff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xa88c00ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x0095a8ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x5842ffff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xff5792ff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x0095a8ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xb3694dff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xfa8900ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Lilac".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0xaea4f4ff).into()), - border_variant: Some(rgba(0xaea4f4ff).into()), - border_focused: Some(rgba(0xdedbf5ff).into()), - border_selected: Some(rgba(0xaea4f4ff).into()), - border_transparent: Some(rgba(0xaea4f4ff).into()), - border_disabled: Some(rgba(0xaea4f4ff).into()), - elevated_surface_background: Some(rgba(0xf2f1f8ff).into()), - surface_background: Some(rgba(0xe9e7f3ff).into()), - background: Some(rgba(0xf2f1f8ff).into()), - element_background: Some(rgba(0x8e80ffff).into()), - element_hover: Some(rgba(0xd2ccffff).into()), - element_selected: Some(rgba(0xbcb6e7ff).into()), - drop_target_background: Some(rgba(0xafaad4aa).into()), - ghost_element_hover: Some(rgba(0xd2ccffff).into()), - ghost_element_selected: Some(rgba(0xbcb6e7ff).into()), - text: Some(rgba(0x0c006bff).into()), - text_muted: Some(rgba(0x75718eff).into()), - status_bar_background: Some(rgba(0xe2dff6ff).into()), - title_bar_background: Some(rgba(0xedecf8ff).into()), - toolbar_background: Some(rgba(0xf2f1f8ff).into()), - tab_bar_background: Some(rgba(0xe2dff6ff).into()), - tab_inactive_background: Some(rgba(0xe2dff6ff).into()), - tab_active_background: Some(rgba(0xf2f1f8ff).into()), - scrollbar_thumb_background: Some(rgba(0x6a90955b).into()), - scrollbar_thumb_hover_background: Some(rgba(0x7060eb62).into()), - scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), - scrollbar_track_background: Some(rgba(0xf2f1f8ff).into()), - scrollbar_track_border: Some(rgba(0xf2f1f8ff).into()), - editor_foreground: Some(rgba(0x0c006bff).into()), - editor_background: Some(rgba(0xf2f1f8ff).into()), - editor_gutter_background: Some(rgba(0xf2f1f8ff).into()), - editor_line_number: Some(rgba(0x9d9ab1ff).into()), - editor_active_line_number: Some(rgba(0x0c006bff).into()), - editor_wrap_guide: Some(rgba(0xaea4f4ff).into()), - editor_active_wrap_guide: Some(rgba(0xaea4f4ff).into()), - terminal_background: Some(rgba(0xe9e7f3ff).into()), - terminal_ansi_bright_black: Some(rgba(0x0f0080ff).into()), - terminal_ansi_bright_red: Some(rgba(0xff4000ff).into()), - terminal_ansi_bright_green: Some(rgba(0x00d17aff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xff8c00ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x0fa3ffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xff6b9fff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x00cbe6ff).into()), - terminal_ansi_bright_white: Some(rgba(0xbbc3c4ff).into()), - terminal_ansi_black: Some(rgba(0x0c006bff).into()), - terminal_ansi_red: Some(rgba(0xe34e1cff).into()), - terminal_ansi_green: Some(rgba(0x00b368ff).into()), - terminal_ansi_yellow: Some(rgba(0xf49725ff).into()), - terminal_ansi_blue: Some(rgba(0x0094f0ff).into()), - terminal_ansi_magenta: Some(rgba(0xff5792ff).into()), - terminal_ansi_cyan: Some(rgba(0x00bdd6ff).into()), - terminal_ansi_white: Some(rgba(0x8ca6a6ff).into()), - link_text_hover: Some(rgba(0x00c6e0ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xe9a149ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xff4000ff).into()), - error: Some(rgba(0xff4000ff).into()), - hidden: Some(rgba(0x75718eff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0xa8a28faa).into()), - modified: Some(rgba(0xe9a149ff).into()), - warning: Some(rgba(0xe07a52ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x5842ffff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x9995b7ff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x9995b7ff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xa88c00ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x0095a8ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x5842ffff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xff5792ff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x0095a8ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0x0c006bff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0x0c006bff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0x0c006bff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0x0c006bff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0x0c006bff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x0c006bff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xb3694dff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xfa8900ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Lux".into(), - appearance: Appearance::Light, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x00c6e0ff).into()), - border_variant: Some(rgba(0x00c6e0ff).into()), - border_focused: Some(rgba(0xf2eddeff).into()), - border_selected: Some(rgba(0x00c6e0ff).into()), - border_transparent: Some(rgba(0x00c6e0ff).into()), - border_disabled: Some(rgba(0x00c6e0ff).into()), - elevated_surface_background: Some(rgba(0xfef8ecff).into()), - surface_background: Some(rgba(0xf6eddaff).into()), - background: Some(rgba(0xfef8ecff).into()), - element_background: Some(rgba(0x099099ff).into()), - element_hover: Some(rgba(0xd2f3f9ff).into()), - element_selected: Some(rgba(0xb6e1e7ff).into()), - drop_target_background: Some(rgba(0xcdcbb2ff).into()), - ghost_element_hover: Some(rgba(0xd2f3f9ff).into()), - ghost_element_selected: Some(rgba(0xb6e1e7ff).into()), - text: Some(rgba(0x005661ff).into()), - text_muted: Some(rgba(0x888477ff).into()), - status_bar_background: Some(rgba(0xf0e9d6ff).into()), - title_bar_background: Some(rgba(0xf9f1e1ff).into()), - toolbar_background: Some(rgba(0xfef8ecff).into()), - tab_bar_background: Some(rgba(0xf0e9d6ff).into()), - tab_inactive_background: Some(rgba(0xf0e9d6ff).into()), - tab_active_background: Some(rgba(0xfef8ecff).into()), - scrollbar_thumb_background: Some(rgba(0x6a90955b).into()), - scrollbar_thumb_hover_background: Some(rgba(0x0099ad62).into()), - scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), - scrollbar_track_background: Some(rgba(0xfef8ecff).into()), - scrollbar_track_border: Some(rgba(0xfef8ecff).into()), - editor_foreground: Some(rgba(0x005661ff).into()), - editor_background: Some(rgba(0xfef8ecff).into()), - editor_gutter_background: Some(rgba(0xfef8ecff).into()), - editor_line_number: Some(rgba(0xa0abacff).into()), - editor_active_line_number: Some(rgba(0x005661ff).into()), - editor_wrap_guide: Some(rgba(0x00c6e0ff).into()), - editor_active_wrap_guide: Some(rgba(0x00c6e0ff).into()), - terminal_background: Some(rgba(0xf6eddaff).into()), - terminal_ansi_bright_black: Some(rgba(0x004d57ff).into()), - terminal_ansi_bright_red: Some(rgba(0xff4000ff).into()), - terminal_ansi_bright_green: Some(rgba(0x00d17aff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xff8c00ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x0fa3ffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xff6b9fff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x00cbe6ff).into()), - terminal_ansi_bright_white: Some(rgba(0xbbc3c4ff).into()), - terminal_ansi_black: Some(rgba(0x003b42ff).into()), - terminal_ansi_red: Some(rgba(0xe34e1cff).into()), - terminal_ansi_green: Some(rgba(0x00b368ff).into()), - terminal_ansi_yellow: Some(rgba(0xf49725ff).into()), - terminal_ansi_blue: Some(rgba(0x0094f0ff).into()), - terminal_ansi_magenta: Some(rgba(0xff5792ff).into()), - terminal_ansi_cyan: Some(rgba(0x00bdd6ff).into()), - terminal_ansi_white: Some(rgba(0x8ca6a6ff).into()), - link_text_hover: Some(rgba(0x00c6e0ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xe9a149ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xff4000ff).into()), - error: Some(rgba(0xff4000ff).into()), - hidden: Some(rgba(0x888477ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0xa8a28faa).into()), - modified: Some(rgba(0xe9a149ff).into()), - warning: Some(rgba(0xe07a52ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x5842ffff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x8ca6a6ff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x8ca6a6ff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xa88c00ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x0095a8ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x5842ffff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xff5792ff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x0095a8ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x004d57ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x00b368ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x00bdd6ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xb3694dff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xfa8900ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe64100ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Minimus".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x496d83ff).into()), - border_variant: Some(rgba(0x496d83ff).into()), - border_focused: Some(rgba(0x202e37ff).into()), - border_selected: Some(rgba(0x496d83ff).into()), - border_transparent: Some(rgba(0x496d83ff).into()), - border_disabled: Some(rgba(0x496d83ff).into()), - elevated_surface_background: Some(rgba(0x202e37ff).into()), - surface_background: Some(rgba(0x0e1920ff).into()), - background: Some(rgba(0x1b2932ff).into()), - element_background: Some(rgba(0x2e616bff).into()), - element_hover: Some(rgba(0x00558aff).into()), - element_selected: Some(rgba(0x2c414eff).into()), - drop_target_background: Some(rgba(0x152837ff).into()), - ghost_element_hover: Some(rgba(0x00558aff).into()), - ghost_element_selected: Some(rgba(0x2c414eff).into()), - text: Some(rgba(0xc5cdd3ff).into()), - text_muted: Some(rgba(0x96a8b6ff).into()), - status_bar_background: Some(rgba(0x1b2932ff).into()), - title_bar_background: Some(rgba(0x1b2932ff).into()), - toolbar_background: Some(rgba(0x1b2932ff).into()), - tab_bar_background: Some(rgba(0x24333dff).into()), - tab_inactive_background: Some(rgba(0x202e37ff).into()), - tab_active_background: Some(rgba(0x1b2932ff).into()), - scrollbar_thumb_background: Some(rgba(0x3f7fa633).into()), - scrollbar_thumb_hover_background: Some(rgba(0x3f7fa655).into()), - scrollbar_thumb_border: Some(rgba(0x3f7fa633).into()), - scrollbar_track_background: Some(rgba(0x1b2932ff).into()), - scrollbar_track_border: Some(rgba(0x1b2932ff).into()), - editor_foreground: Some(rgba(0xc5cdd3ff).into()), - editor_background: Some(rgba(0x1b2932ff).into()), - editor_gutter_background: Some(rgba(0x1b2932ff).into()), - editor_line_number: Some(rgba(0x5d6e79ff).into()), - editor_active_line_number: Some(rgba(0xc5cdd3ff).into()), - editor_wrap_guide: Some(rgba(0x496d83ff).into()), - editor_active_wrap_guide: Some(rgba(0x496d83ff).into()), - terminal_background: Some(rgba(0x0e1920ff).into()), - terminal_ansi_bright_black: Some(rgba(0x425866ff).into()), - terminal_ansi_bright_red: Some(rgba(0xca8468ff).into()), - terminal_ansi_bright_green: Some(rgba(0x84c8abff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xd1aa7bff).into()), - terminal_ansi_bright_blue: Some(rgba(0x68a4caff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xc88da2ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x84c0c8ff).into()), - terminal_ansi_bright_white: Some(rgba(0xc5d1d3ff).into()), - terminal_ansi_black: Some(rgba(0x182a35ff).into()), - terminal_ansi_red: Some(rgba(0xc08872ff).into()), - terminal_ansi_green: Some(rgba(0x72c09fff).into()), - terminal_ansi_yellow: Some(rgba(0xc8a984ff).into()), - terminal_ansi_blue: Some(rgba(0x6196b8ff).into()), - terminal_ansi_magenta: Some(rgba(0xc28097ff).into()), - terminal_ansi_cyan: Some(rgba(0x72b7c0ff).into()), - terminal_ansi_white: Some(rgba(0xc5cdd3ff).into()), - link_text_hover: Some(rgba(0x5998c0ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xdfc09fff).into()), - created: Some(rgba(0xa0d4a8ff).into()), - deleted: Some(rgba(0xb96346ff).into()), - error: Some(rgba(0xb96346ff).into()), - hidden: Some(rgba(0x96a8b6ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x5b788bff).into()), - modified: Some(rgba(0xdfc09fff).into()), - warning: Some(rgba(0xffa857ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x7068b1ff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x5e7887ff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x5e7887ff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xa88c00ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xc37455ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x3f848dff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xc37455ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x72b7c0ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x72b7c0ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x72b7c0ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x7068b1ff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xc88da2ff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x3f848dff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xc5cdd3ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xc5cdd3ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xc5cdd3ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xc5cdd3ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xc5cdd3ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x72c09fff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xc5cdd3ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x72c09fff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x72c09fff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x72c09fff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xc37455ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x72c09fff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x72b7c0ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xbe856fff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xd3b692ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xc37455ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x0e6671ff).into()), - border_variant: Some(rgba(0x0e6671ff).into()), - border_focused: Some(rgba(0x073940ff).into()), - border_selected: Some(rgba(0x0e6671ff).into()), - border_transparent: Some(rgba(0x0e6671ff).into()), - border_disabled: Some(rgba(0x0e6671ff).into()), - elevated_surface_background: Some(rgba(0x073940ff).into()), - surface_background: Some(rgba(0x03191bff).into()), - background: Some(rgba(0x052529ff).into()), - element_background: Some(rgba(0x099099ff).into()), - element_hover: Some(rgba(0x0b515bff).into()), - element_selected: Some(rgba(0x0e6671ff).into()), - drop_target_background: Some(rgba(0x00404dff).into()), - ghost_element_hover: Some(rgba(0x0b515bff).into()), - ghost_element_selected: Some(rgba(0x0e6671ff).into()), - text: Some(rgba(0xb2cacdff).into()), - text_muted: Some(rgba(0x87a7abff).into()), - status_bar_background: Some(rgba(0x041d20ff).into()), - title_bar_background: Some(rgba(0x041d20ff).into()), - toolbar_background: Some(rgba(0x052529ff).into()), - tab_bar_background: Some(rgba(0x062e32ff).into()), - tab_inactive_background: Some(rgba(0x062e32ff).into()), - tab_active_background: Some(rgba(0x052529ff).into()), - scrollbar_thumb_background: Some(rgba(0x6a90955b).into()), - scrollbar_thumb_hover_background: Some(rgba(0x169fb162).into()), - scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), - scrollbar_track_background: Some(rgba(0x052529ff).into()), - scrollbar_track_border: Some(rgba(0x052529ff).into()), - editor_foreground: Some(rgba(0xb2cacdff).into()), - editor_background: Some(rgba(0x052529ff).into()), - editor_gutter_background: Some(rgba(0x052529ff).into()), - editor_line_number: Some(rgba(0x4e6b6eff).into()), - editor_active_line_number: Some(rgba(0xb2cacdff).into()), - editor_wrap_guide: Some(rgba(0x0e6671ff).into()), - editor_active_wrap_guide: Some(rgba(0x0e6671ff).into()), - terminal_background: Some(rgba(0x03191bff).into()), - terminal_ansi_bright_black: Some(rgba(0x47686cff).into()), - terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), - terminal_ansi_bright_green: Some(rgba(0x60ebb1ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xe69533ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x60b6ebff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xe798b3ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x60dbebff).into()), - terminal_ansi_bright_white: Some(rgba(0xc1d4d7ff).into()), - terminal_ansi_black: Some(rgba(0x324a4dff).into()), - terminal_ansi_red: Some(rgba(0xe66533ff).into()), - terminal_ansi_green: Some(rgba(0x49e9a6ff).into()), - terminal_ansi_yellow: Some(rgba(0xe4b781ff).into()), - terminal_ansi_blue: Some(rgba(0x49ace9ff).into()), - terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), - terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), - terminal_ansi_white: Some(rgba(0xb2cacdff).into()), - link_text_hover: Some(rgba(0x40d4e7ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xe4b781ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xe34e1cff).into()), - error: Some(rgba(0xe34e1cff).into()), - hidden: Some(rgba(0x87a7abff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x5b858bff).into()), - modified: Some(rgba(0xe0c184ff).into()), - warning: Some(rgba(0xffa487ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x5b858bff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x5b858bff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xd5971aff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xdf769bff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xd67e5cff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xe4b781ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Obscuro".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x0e6671ff).into()), - border_variant: Some(rgba(0x0e6671ff).into()), - border_focused: Some(rgba(0x062e32ff).into()), - border_selected: Some(rgba(0x0e6671ff).into()), - border_transparent: Some(rgba(0x0e6671ff).into()), - border_disabled: Some(rgba(0x0e6671ff).into()), - elevated_surface_background: Some(rgba(0x031417ff).into()), - surface_background: Some(rgba(0x020c0eff).into()), - background: Some(rgba(0x031417ff).into()), - element_background: Some(rgba(0x099099ff).into()), - element_hover: Some(rgba(0x0b515bff).into()), - element_selected: Some(rgba(0x0e6671ff).into()), - drop_target_background: Some(rgba(0x00404dff).into()), - ghost_element_hover: Some(rgba(0x0b515bff).into()), - ghost_element_selected: Some(rgba(0x0e6671ff).into()), - text: Some(rgba(0xb2cacdff).into()), - text_muted: Some(rgba(0x87a7abff).into()), - status_bar_background: Some(rgba(0x031417ff).into()), - title_bar_background: Some(rgba(0x031417ff).into()), - toolbar_background: Some(rgba(0x031417ff).into()), - tab_bar_background: Some(rgba(0x062e32ff).into()), - tab_inactive_background: Some(rgba(0x062e32ff).into()), - tab_active_background: Some(rgba(0x031417ff).into()), - scrollbar_thumb_background: Some(rgba(0x6a90955b).into()), - scrollbar_thumb_hover_background: Some(rgba(0x169fb162).into()), - scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), - scrollbar_track_background: Some(rgba(0x031417ff).into()), - scrollbar_track_border: Some(rgba(0x031417ff).into()), - editor_foreground: Some(rgba(0xb2cacdff).into()), - editor_background: Some(rgba(0x031417ff).into()), - editor_gutter_background: Some(rgba(0x031417ff).into()), - editor_line_number: Some(rgba(0x4e6b6eff).into()), - editor_active_line_number: Some(rgba(0xb2cacdff).into()), - editor_wrap_guide: Some(rgba(0x0e6671ff).into()), - editor_active_wrap_guide: Some(rgba(0x0e6671ff).into()), - terminal_background: Some(rgba(0x020c0eff).into()), - terminal_ansi_bright_black: Some(rgba(0x47686cff).into()), - terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), - terminal_ansi_bright_green: Some(rgba(0x60ebb1ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xe69533ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x60b6ebff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xe798b3ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x60dbebff).into()), - terminal_ansi_bright_white: Some(rgba(0xc1d4d7ff).into()), - terminal_ansi_black: Some(rgba(0x324a4dff).into()), - terminal_ansi_red: Some(rgba(0xe66533ff).into()), - terminal_ansi_green: Some(rgba(0x49e9a6ff).into()), - terminal_ansi_yellow: Some(rgba(0xe4b781ff).into()), - terminal_ansi_blue: Some(rgba(0x49ace9ff).into()), - terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), - terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), - terminal_ansi_white: Some(rgba(0xb2cacdff).into()), - link_text_hover: Some(rgba(0x40d4e7ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xe4b781ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xe34e1cff).into()), - error: Some(rgba(0xe34e1cff).into()), - hidden: Some(rgba(0x87a7abff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x647e82ff).into()), - modified: Some(rgba(0xe4b781ff).into()), - warning: Some(rgba(0xffa487ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x5b858bff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x5b858bff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xd5971aff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xdf769bff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xd67e5cff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xe4b781ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Sereno".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x0e6671ff).into()), - border_variant: Some(rgba(0x0e6671ff).into()), - border_focused: Some(rgba(0x062e32ff).into()), - border_selected: Some(rgba(0x0e6671ff).into()), - border_transparent: Some(rgba(0x0e6671ff).into()), - border_disabled: Some(rgba(0x0e6671ff).into()), - elevated_surface_background: Some(rgba(0x031417ff).into()), - surface_background: Some(rgba(0x020c0eff).into()), - background: Some(rgba(0x031417ff).into()), - element_background: Some(rgba(0x099099ff).into()), - element_hover: Some(rgba(0x0b515bff).into()), - element_selected: Some(rgba(0x0e6671ff).into()), - drop_target_background: Some(rgba(0x00404dff).into()), - ghost_element_hover: Some(rgba(0x0b515bff).into()), - ghost_element_selected: Some(rgba(0x0e6671ff).into()), - text: Some(rgba(0xb2cacdff).into()), - text_muted: Some(rgba(0x87a7abff).into()), - status_bar_background: Some(rgba(0x031417ff).into()), - title_bar_background: Some(rgba(0x031417ff).into()), - toolbar_background: Some(rgba(0x031417ff).into()), - tab_bar_background: Some(rgba(0x062e32ff).into()), - tab_inactive_background: Some(rgba(0x062e32ff).into()), - tab_active_background: Some(rgba(0x031417ff).into()), - scrollbar_thumb_background: Some(rgba(0x6a90955b).into()), - scrollbar_thumb_hover_background: Some(rgba(0x169fb162).into()), - scrollbar_thumb_border: Some(rgba(0x6a90955b).into()), - scrollbar_track_background: Some(rgba(0x031417ff).into()), - scrollbar_track_border: Some(rgba(0x031417ff).into()), - editor_foreground: Some(rgba(0xb2cacdff).into()), - editor_background: Some(rgba(0x031417ff).into()), - editor_gutter_background: Some(rgba(0x031417ff).into()), - editor_line_number: Some(rgba(0x4e6b6eff).into()), - editor_active_line_number: Some(rgba(0xb2cacdff).into()), - editor_wrap_guide: Some(rgba(0x0e6671ff).into()), - editor_active_wrap_guide: Some(rgba(0x0e6671ff).into()), - terminal_background: Some(rgba(0x020c0eff).into()), - terminal_ansi_bright_black: Some(rgba(0x47686cff).into()), - terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), - terminal_ansi_bright_green: Some(rgba(0x60ebb1ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xe69533ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x60b6ebff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xe798b3ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x60dbebff).into()), - terminal_ansi_bright_white: Some(rgba(0xc1d4d7ff).into()), - terminal_ansi_black: Some(rgba(0x324a4dff).into()), - terminal_ansi_red: Some(rgba(0xe66533ff).into()), - terminal_ansi_green: Some(rgba(0x49e9a6ff).into()), - terminal_ansi_yellow: Some(rgba(0xe4b781ff).into()), - terminal_ansi_blue: Some(rgba(0x49ace9ff).into()), - terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), - terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), - terminal_ansi_white: Some(rgba(0xb2cacdff).into()), - link_text_hover: Some(rgba(0x40d4e7ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xe4b781ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xe34e1cff).into()), - error: Some(rgba(0xe34e1cff).into()), - hidden: Some(rgba(0x87a7abff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x647e82ff).into()), - modified: Some(rgba(0xe4b781ff).into()), - warning: Some(rgba(0xffa487ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x5b858bff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x5b858bff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xd5971aff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xdf769bff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xb2cacdff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xd67e5cff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xe4b781ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Uva".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x6e67a8ff).into()), - border_variant: Some(rgba(0x6e67a8ff).into()), - border_focused: Some(rgba(0x2f2c49ff).into()), - border_selected: Some(rgba(0x6e67a8ff).into()), - border_transparent: Some(rgba(0x6e67a8ff).into()), - border_disabled: Some(rgba(0x6e67a8ff).into()), - elevated_surface_background: Some(rgba(0x2f2c49ff).into()), - surface_background: Some(rgba(0x1f1d30ff).into()), - background: Some(rgba(0x292640ff).into()), - element_background: Some(rgba(0x007f99ff).into()), - element_hover: Some(rgba(0x383866ff).into()), - element_selected: Some(rgba(0x332e5cff).into()), - drop_target_background: Some(rgba(0x202040ff).into()), - ghost_element_hover: Some(rgba(0x383866ff).into()), - ghost_element_selected: Some(rgba(0x332e5cff).into()), - text: Some(rgba(0xc5c2d6ff).into()), - text_muted: Some(rgba(0xa9a5c0ff).into()), - status_bar_background: Some(rgba(0x292640ff).into()), - title_bar_background: Some(rgba(0x292640ff).into()), - toolbar_background: Some(rgba(0x292640ff).into()), - tab_bar_background: Some(rgba(0x2f2c49ff).into()), - tab_inactive_background: Some(rgba(0x2f2c49ff).into()), - tab_active_background: Some(rgba(0x292640ff).into()), - scrollbar_thumb_background: Some(rgba(0x7060eb33).into()), - scrollbar_thumb_hover_background: Some(rgba(0x7060eb55).into()), - scrollbar_thumb_border: Some(rgba(0x7060eb33).into()), - scrollbar_track_background: Some(rgba(0x292640ff).into()), - scrollbar_track_border: Some(rgba(0x292640ff).into()), - editor_foreground: Some(rgba(0xc5c2d6ff).into()), - editor_background: Some(rgba(0x292640ff).into()), - editor_gutter_background: Some(rgba(0x292640ff).into()), - editor_line_number: Some(rgba(0x5c5973ff).into()), - editor_active_line_number: Some(rgba(0xc5c2d6ff).into()), - editor_wrap_guide: Some(rgba(0x6e67a8ff).into()), - editor_active_wrap_guide: Some(rgba(0x6e67a8ff).into()), - terminal_background: Some(rgba(0x1f1d30ff).into()), - terminal_ansi_bright_black: Some(rgba(0x504e65ff).into()), - terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), - terminal_ansi_bright_green: Some(rgba(0x60ebb1ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xe69533ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x60b6ebff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xe798b3ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x60dbebff).into()), - terminal_ansi_bright_white: Some(rgba(0xc5c2d6ff).into()), - terminal_ansi_black: Some(rgba(0x302f3dff).into()), - terminal_ansi_red: Some(rgba(0xe66533ff).into()), - terminal_ansi_green: Some(rgba(0x49e9a6ff).into()), - terminal_ansi_yellow: Some(rgba(0xe4b781ff).into()), - terminal_ansi_blue: Some(rgba(0x49ace9ff).into()), - terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), - terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), - terminal_ansi_white: Some(rgba(0xb6b3ccff).into()), - link_text_hover: Some(rgba(0x998ef1ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xffc180ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xe34e1cff).into()), - error: Some(rgba(0xe34e1cff).into()), - hidden: Some(rgba(0xa9a5c0ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x5b788bff).into()), - modified: Some(rgba(0xffc180ff).into()), - warning: Some(rgba(0xffa857ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x716c93ff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x716c93ff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xd5971aff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xdf769bff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xc5c2d6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xc5c2d6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xc5c2d6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xc5c2d6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xc5c2d6ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xc5c2d6ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xd67e5cff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xe4b781ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Noctis Viola".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x8767a8ff).into()), - border_variant: Some(rgba(0x8767a8ff).into()), - border_focused: Some(rgba(0x3d2e4dff).into()), - border_selected: Some(rgba(0x8767a8ff).into()), - border_transparent: Some(rgba(0x8767a8ff).into()), - border_disabled: Some(rgba(0x8767a8ff).into()), - elevated_surface_background: Some(rgba(0x3d2e4dff).into()), - surface_background: Some(rgba(0x291d35ff).into()), - background: Some(rgba(0x30243dff).into()), - element_background: Some(rgba(0x007f99ff).into()), - element_hover: Some(rgba(0x6a448dff).into()), - element_selected: Some(rgba(0x472e60ff).into()), - drop_target_background: Some(rgba(0x302040ff).into()), - ghost_element_hover: Some(rgba(0x6a448dff).into()), - ghost_element_selected: Some(rgba(0x472e60ff).into()), - text: Some(rgba(0xccbfd9ff).into()), - text_muted: Some(rgba(0xb3a5c0ff).into()), - status_bar_background: Some(rgba(0x30243dff).into()), - title_bar_background: Some(rgba(0x30243dff).into()), - toolbar_background: Some(rgba(0x30243dff).into()), - tab_bar_background: Some(rgba(0x3d2e4dff).into()), - tab_inactive_background: Some(rgba(0x3d2e4dff).into()), - tab_active_background: Some(rgba(0x30243dff).into()), - scrollbar_thumb_background: Some(rgba(0xa660eb33).into()), - scrollbar_thumb_hover_background: Some(rgba(0xa660eb55).into()), - scrollbar_thumb_border: Some(rgba(0xa660eb33).into()), - scrollbar_track_background: Some(rgba(0x30243dff).into()), - scrollbar_track_border: Some(rgba(0x30243dff).into()), - editor_foreground: Some(rgba(0xccbfd9ff).into()), - editor_background: Some(rgba(0x30243dff).into()), - editor_gutter_background: Some(rgba(0x30243dff).into()), - editor_line_number: Some(rgba(0x665973ff).into()), - editor_active_line_number: Some(rgba(0xccbfd9ff).into()), - editor_wrap_guide: Some(rgba(0x8767a8ff).into()), - editor_active_wrap_guide: Some(rgba(0x8767a8ff).into()), - terminal_background: Some(rgba(0x291d35ff).into()), - terminal_ansi_bright_black: Some(rgba(0x594e65ff).into()), - terminal_ansi_bright_red: Some(rgba(0xe97749ff).into()), - terminal_ansi_bright_green: Some(rgba(0x60ebb1ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xe69533ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x60b6ebff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xe798b3ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x60dbebff).into()), - terminal_ansi_bright_white: Some(rgba(0xccbfd9ff).into()), - terminal_ansi_black: Some(rgba(0x362f3dff).into()), - terminal_ansi_red: Some(rgba(0xe66533ff).into()), - terminal_ansi_green: Some(rgba(0x49e9a6ff).into()), - terminal_ansi_yellow: Some(rgba(0xe4b781ff).into()), - terminal_ansi_blue: Some(rgba(0x49ace9ff).into()), - terminal_ansi_magenta: Some(rgba(0xdf769bff).into()), - terminal_ansi_cyan: Some(rgba(0x49d6e9ff).into()), - terminal_ansi_white: Some(rgba(0xbfafcfff).into()), - link_text_hover: Some(rgba(0xbf8ef1ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xffc180ff).into()), - created: Some(rgba(0x8ce99aff).into()), - deleted: Some(rgba(0xe34e1cff).into()), - error: Some(rgba(0xe34e1cff).into()), - hidden: Some(rgba(0xb3a5c0ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x5b788bff).into()), - modified: Some(rgba(0xffc180ff).into()), - warning: Some(rgba(0xffa857ff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x7f659aff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x7f659aff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xd5971aff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0x7060ebff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0xdf769bff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x16a3b6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xccbfd9ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xccbfd9ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xccbfd9ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xccbfd9ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xccbfd9ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xccbfd9ff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0x49e9a6ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0x49d6e9ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xd67e5cff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xe4b781ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xe66533ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - ], - } -} diff --git a/crates/theme2/src/themes/nord.rs b/crates/theme2/src/themes/nord.rs deleted file mode 100644 index c44076c1f8..0000000000 --- a/crates/theme2/src/themes/nord.rs +++ /dev/null @@ -1,277 +0,0 @@ -// This file was generated by the `theme_importer`. -// Be careful when modifying it by hand. - -use gpui::rgba; - -#[allow(unused)] -use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, -}; - -pub fn nord() -> UserThemeFamily { - UserThemeFamily { - name: "Nord".into(), - author: "Sven Greb (svengreb)".into(), - themes: vec![UserTheme { - name: "Nord".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x3b4252ff).into()), - border_variant: Some(rgba(0x3b4252ff).into()), - border_focused: Some(rgba(0x3b4252ff).into()), - border_selected: Some(rgba(0x3b4252ff).into()), - border_transparent: Some(rgba(0x3b4252ff).into()), - border_disabled: Some(rgba(0x3b4252ff).into()), - elevated_surface_background: Some(rgba(0x3b4252ff).into()), - surface_background: Some(rgba(0x2e3440ff).into()), - background: Some(rgba(0x2e3440ff).into()), - element_background: Some(rgba(0x88c0d0ee).into()), - element_hover: Some(rgba(0x3b4252ff).into()), - element_selected: Some(rgba(0x88c0d0ff).into()), - drop_target_background: Some(rgba(0x88c0d099).into()), - ghost_element_hover: Some(rgba(0x3b4252ff).into()), - ghost_element_selected: Some(rgba(0x88c0d0ff).into()), - text: Some(rgba(0xd8dee9ff).into()), - text_muted: Some(rgba(0xd8dee966).into()), - status_bar_background: Some(rgba(0x3b4252ff).into()), - title_bar_background: Some(rgba(0x2e3440ff).into()), - toolbar_background: Some(rgba(0x2e3440ff).into()), - tab_bar_background: Some(rgba(0x2e3440ff).into()), - tab_inactive_background: Some(rgba(0x2e3440ff).into()), - tab_active_background: Some(rgba(0x3b4252ff).into()), - scrollbar_thumb_background: Some(rgba(0x434c5e99).into()), - scrollbar_thumb_hover_background: Some(rgba(0x434c5eaa).into()), - scrollbar_thumb_border: Some(rgba(0x434c5e99).into()), - scrollbar_track_background: Some(rgba(0x2e3440ff).into()), - scrollbar_track_border: Some(rgba(0x3b4252ff).into()), - editor_foreground: Some(rgba(0xd8dee9ff).into()), - editor_background: Some(rgba(0x2e3440ff).into()), - editor_gutter_background: Some(rgba(0x2e3440ff).into()), - editor_line_number: Some(rgba(0x4c566aff).into()), - editor_active_line_number: Some(rgba(0xd8dee9ff).into()), - editor_wrap_guide: Some(rgba(0x3b4252ff).into()), - editor_active_wrap_guide: Some(rgba(0x3b4252ff).into()), - terminal_background: Some(rgba(0x2e3440ff).into()), - terminal_ansi_bright_black: Some(rgba(0x4c566aff).into()), - terminal_ansi_bright_red: Some(rgba(0xbf616aff).into()), - terminal_ansi_bright_green: Some(rgba(0xa3be8cff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xebcb8bff).into()), - terminal_ansi_bright_blue: Some(rgba(0x81a1c1ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xb48eadff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x8fbcbbff).into()), - terminal_ansi_bright_white: Some(rgba(0xeceff4ff).into()), - terminal_ansi_black: Some(rgba(0x3b4252ff).into()), - terminal_ansi_red: Some(rgba(0xbf616aff).into()), - terminal_ansi_green: Some(rgba(0xa3be8cff).into()), - terminal_ansi_yellow: Some(rgba(0xebcb8bff).into()), - terminal_ansi_blue: Some(rgba(0x81a1c1ff).into()), - terminal_ansi_magenta: Some(rgba(0xb48eadff).into()), - terminal_ansi_cyan: Some(rgba(0x88c0d0ff).into()), - terminal_ansi_white: Some(rgba(0xe5e9f0ff).into()), - link_text_hover: Some(rgba(0x88c0d0ff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0x5e81acff).into()), - created: Some(rgba(0xa3be8cff).into()), - deleted: Some(rgba(0xbf616aff).into()), - error: Some(rgba(0xbf616aff).into()), - hidden: Some(rgba(0xd8dee966).into()), - hint: Some(rgba(0xd8dee9ff).into()), - ignored: Some(rgba(0xd8dee966).into()), - modified: Some(rgba(0xebcb8bff).into()), - warning: Some(rgba(0xebcb8bff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0x8fbcbbff).into()), - ..Default::default() - }, - ), - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x616e88ff).into()), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x616e88ff).into()), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x88c0d0ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xb48eadff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ( - "preproc".into(), - UserHighlightStyle { - color: Some(rgba(0x5e81acff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xeceff4ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xeceff4ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xeceff4ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xeceff4ff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0xa3be8cff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0xebcb8bff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0xa3be8cff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0xa3be8cff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0xa3be8cff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0xa3be8cff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0x8fbcbbff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0x81a1c1ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }], - } -} diff --git a/crates/theme2/src/themes/palenight.rs b/crates/theme2/src/themes/one.rs similarity index 50% rename from crates/theme2/src/themes/palenight.rs rename to crates/theme2/src/themes/one.rs index 2fceb8055e..089e3b3bcd 100644 --- a/crates/theme2/src/themes/palenight.rs +++ b/crates/theme2/src/themes/one.rs @@ -9,77 +9,68 @@ use crate::{ UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, }; -pub fn palenight() -> UserThemeFamily { +pub fn one() -> UserThemeFamily { UserThemeFamily { - name: "Palenight".into(), - author: "Olaolu Olawuyi (whizkydee)".into(), + name: "One".into(), + author: "Zed Industries".into(), themes: vec![ UserTheme { - name: "Palenight".into(), - appearance: Appearance::Dark, + name: "One Light".into(), + appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x282b3cff).into()), - border_variant: Some(rgba(0x282b3cff).into()), - border_focused: Some(rgba(0x282b3cff).into()), - border_selected: Some(rgba(0x282b3cff).into()), - border_transparent: Some(rgba(0x282b3cff).into()), - border_disabled: Some(rgba(0x282b3cff).into()), - elevated_surface_background: Some(rgba(0x292d3eff).into()), - surface_background: Some(rgba(0x292d3eff).into()), - background: Some(rgba(0x292d3eff).into()), - element_background: Some(rgba(0x7e57c2cc).into()), - element_hover: Some(rgba(0x0000001a).into()), - element_selected: Some(rgba(0x7e57c2ff).into()), - drop_target_background: Some(rgba(0x2e3245ff).into()), - ghost_element_hover: Some(rgba(0x0000001a).into()), - ghost_element_selected: Some(rgba(0x7e57c2ff).into()), - text: Some(rgba(0xffffffff).into()), - text_muted: Some(rgba(0x929ac9ff).into()), - status_bar_background: Some(rgba(0x282c3dff).into()), - title_bar_background: Some(rgba(0x292d3eff).into()), - toolbar_background: Some(rgba(0x292d3eff).into()), - tab_bar_background: Some(rgba(0x31364aff).into()), - tab_inactive_background: Some(rgba(0x31364aff).into()), - tab_active_background: Some(rgba(0x292d3eff).into()), - scrollbar_thumb_background: Some(rgba(0x694ca466).into()), - scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), - scrollbar_thumb_border: Some(rgba(0x694ca466).into()), - scrollbar_track_background: Some(rgba(0x292d3eff).into()), - editor_foreground: Some(rgba(0xbfc7d5ff).into()), - editor_background: Some(rgba(0x292d3eff).into()), - editor_gutter_background: Some(rgba(0x292d3eff).into()), - editor_line_number: Some(rgba(0x4c5374ff).into()), - editor_active_line_number: Some(rgba(0xbfc7d5ff).into()), - editor_wrap_guide: Some(rgba(0x282b3cff).into()), - editor_active_wrap_guide: Some(rgba(0x282b3cff).into()), - terminal_ansi_bright_black: Some(rgba(0x676e95ff).into()), - terminal_ansi_bright_red: Some(rgba(0xff5572ff).into()), - terminal_ansi_bright_green: Some(rgba(0xc3e88dff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffcb6bff).into()), - terminal_ansi_bright_blue: Some(rgba(0x82aaffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xc792eaff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x89ddffff).into()), - terminal_ansi_bright_white: Some(rgba(0xffffffff).into()), - terminal_ansi_black: Some(rgba(0x676e95ff).into()), - terminal_ansi_red: Some(rgba(0xff5572ff).into()), - terminal_ansi_green: Some(rgba(0xa9c77dff).into()), - terminal_ansi_yellow: Some(rgba(0xffcb6bff).into()), - terminal_ansi_blue: Some(rgba(0x82aaffff).into()), - terminal_ansi_magenta: Some(rgba(0xc792eaff).into()), - terminal_ansi_cyan: Some(rgba(0x89ddffff).into()), - terminal_ansi_white: Some(rgba(0xffffffff).into()), + border: Some(rgba(0xc9c9caff).into()), + border_variant: Some(rgba(0xc9c9caff).into()), + elevated_surface_background: Some(rgba(0xdcdcddff).into()), + background: Some(rgba(0xdcdcddff).into()), + panel_background: Some(rgba(0xebebecff).into()), + element_hover: Some(rgba(0xc9c9ca80).into()), + element_selected: Some(rgba(0xafafaf80).into()), + text: Some(rgba(0x7f8188ff).into()), + text_muted: Some(rgba(0xa7a7a8ff).into()), + status_bar_background: Some(rgba(0xdcdcddff).into()), + title_bar_background: Some(rgba(0xdcdcddff).into()), + toolbar_background: Some(rgba(0xfafafaff).into()), + tab_bar_background: Some(rgba(0xebebecff).into()), + tab_inactive_background: Some(rgba(0xebebecff).into()), + tab_active_background: Some(rgba(0xfafafaff).into()), + scrollbar_thumb_background: Some(rgba(0x383a414d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x383a414d).into()), + scrollbar_thumb_border: Some(rgba(0xeeeeeeff).into()), + scrollbar_track_border: Some(rgba(0xeeeeeeff).into()), + editor_foreground: Some(rgba(0x383a41ff).into()), + editor_background: Some(rgba(0xfafafaff).into()), + editor_gutter_background: Some(rgba(0xfafafaff).into()), + editor_line_number: Some(rgba(0x383a4159).into()), + editor_active_line_number: Some(rgba(0x383a41ff).into()), + editor_wrap_guide: Some(rgba(0x383a410d).into()), + editor_active_wrap_guide: Some(rgba(0x383a411a).into()), + terminal_background: Some(rgba(0xfafafaff).into()), + terminal_ansi_bright_black: Some(rgba(0xaaaaaaff).into()), + terminal_ansi_bright_red: Some(rgba(0xf0b0a4ff).into()), + terminal_ansi_bright_green: Some(rgba(0xb2cfa9ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xf1dfc1ff).into()), + terminal_ansi_bright_blue: Some(rgba(0xb5baf2ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xcea6d3ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0xa4bfdbff).into()), + terminal_ansi_bright_white: Some(rgba(0x383a41ff).into()), + terminal_ansi_black: Some(rgba(0xfafafaff).into()), + terminal_ansi_red: Some(rgba(0xd36151ff).into()), + terminal_ansi_green: Some(rgba(0x669f59ff).into()), + terminal_ansi_yellow: Some(rgba(0xdec184ff).into()), + terminal_ansi_blue: Some(rgba(0x5c79e2ff).into()), + terminal_ansi_magenta: Some(rgba(0x994fa6ff).into()), + terminal_ansi_cyan: Some(rgba(0x3b82b7ff).into()), + terminal_ansi_white: Some(rgba(0x383a41ff).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xffeb95cc).into()), - created: Some(rgba(0x9ccc65ff).into()), - deleted: Some(rgba(0xef5350ff).into()), - error: Some(rgba(0xef5350ff).into()), - hidden: Some(rgba(0x929ac9ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x69709890).into()), - modified: Some(rgba(0xe2b93dff).into()), + created: Some(rgba(0x84b278ff).into()), + deleted: Some(rgba(0xd36151ff).into()), + error: Some(rgba(0xd36151ff).into()), + modified: Some(rgba(0xdec184ff).into()), + success: Some(rgba(0x383a41ff).into()), + warning: Some(rgba(0xdec184ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -87,214 +78,278 @@ pub fn palenight() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0x5c79e2ff).into()), ..Default::default() }, ), ( "boolean".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0xad6f26ff).into()), ..Default::default() }, ), ( "comment".into(), UserHighlightStyle { - color: Some(rgba(0x697098ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0xa2a3a7ff).into()), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0x697098ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x7c7e86ff).into()), ..Default::default() }, ), ( "constant".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0x669f59ff).into()), ..Default::default() }, ), ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), + color: Some(rgba(0x5c79e2ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x383a41ff).into()), ..Default::default() }, ), ( "emphasis".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x5c79e2ff).into()), ..Default::default() }, ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0xad6f26ff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xd36050ff).into()), + ..Default::default() + }, + ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0x5b79e3ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x9295beff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "keyword".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0xa449abff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x5c79e2ff).into()), ..Default::default() }, ), ( "link_text".into(), UserHighlightStyle { - color: Some(rgba(0xff869aff).into()), + color: Some(rgba(0x5b79e3ff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), ( "link_uri".into(), UserHighlightStyle { - color: Some(rgba(0xff869aff).into()), + color: Some(rgba(0x3982b7ff).into()), ..Default::default() }, ), ( "number".into(), UserHighlightStyle { - color: Some(rgba(0xf78c6cff).into()), + color: Some(rgba(0xad6f26ff).into()), ..Default::default() }, ), ( "operator".into(), UserHighlightStyle { - color: Some(rgba(0x89ddffff).into()), + color: Some(rgba(0x3982b7ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x9c9fc7ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x383a41ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x383a41ff).into()), ..Default::default() }, ), ( "property".into(), UserHighlightStyle { - color: Some(rgba(0x80cbc4ff).into()), + color: Some(rgba(0xd36050ff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0x383a41ff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0x4d4f52ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0x4d4f52ff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0xd36050ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0xb92c46ff).into()), ..Default::default() }, ), ( "string".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0x659f58ff).into()), ..Default::default() }, ), ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0x7c7e86ff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0xad6f27ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0xad6f27ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0xad6f27ff).into()), ..Default::default() }, ), ( "tag".into(), UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), + color: Some(rgba(0x5c79e2ff).into()), ..Default::default() }, ), ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0x659f58ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xd36050ff).into()), + font_weight: Some(UserFontWeight(400.0)), ..Default::default() }, ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0x3982b7ff).into()), ..Default::default() }, ), ( "variable".into(), UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0x383a41ff).into()), ..Default::default() }, ), ( "variable.special".into(), UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), + color: Some(rgba(0xad6f26ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x5b79e3ff).into()), ..Default::default() }, ), @@ -303,71 +358,62 @@ pub fn palenight() -> UserThemeFamily { }, }, UserTheme { - name: "Palenight Operator".into(), + name: "One Dark".into(), appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x282b3cff).into()), - border_variant: Some(rgba(0x282b3cff).into()), - border_focused: Some(rgba(0x282b3cff).into()), - border_selected: Some(rgba(0x282b3cff).into()), - border_transparent: Some(rgba(0x282b3cff).into()), - border_disabled: Some(rgba(0x282b3cff).into()), - elevated_surface_background: Some(rgba(0x292d3eff).into()), - surface_background: Some(rgba(0x292d3eff).into()), - background: Some(rgba(0x292d3eff).into()), - element_background: Some(rgba(0x7e57c2cc).into()), - element_hover: Some(rgba(0x0000001a).into()), - element_selected: Some(rgba(0x7e57c2ff).into()), - drop_target_background: Some(rgba(0x2e3245ff).into()), - ghost_element_hover: Some(rgba(0x0000001a).into()), - ghost_element_selected: Some(rgba(0x7e57c2ff).into()), - text: Some(rgba(0xffffffff).into()), - text_muted: Some(rgba(0x929ac9ff).into()), - status_bar_background: Some(rgba(0x282c3dff).into()), - title_bar_background: Some(rgba(0x292d3eff).into()), - toolbar_background: Some(rgba(0x292d3eff).into()), - tab_bar_background: Some(rgba(0x31364aff).into()), - tab_inactive_background: Some(rgba(0x31364aff).into()), - tab_active_background: Some(rgba(0x292d3eff).into()), - scrollbar_thumb_background: Some(rgba(0x694ca466).into()), - scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), - scrollbar_thumb_border: Some(rgba(0x694ca466).into()), - scrollbar_track_background: Some(rgba(0x292d3eff).into()), - editor_foreground: Some(rgba(0xbfc7d5ff).into()), - editor_background: Some(rgba(0x292d3eff).into()), - editor_gutter_background: Some(rgba(0x292d3eff).into()), - editor_line_number: Some(rgba(0x4c5374ff).into()), - editor_active_line_number: Some(rgba(0xbfc7d5ff).into()), - editor_wrap_guide: Some(rgba(0x282b3cff).into()), - editor_active_wrap_guide: Some(rgba(0x282b3cff).into()), - terminal_ansi_bright_black: Some(rgba(0x676e95ff).into()), - terminal_ansi_bright_red: Some(rgba(0xff5572ff).into()), - terminal_ansi_bright_green: Some(rgba(0xc3e88dff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffcb6bff).into()), - terminal_ansi_bright_blue: Some(rgba(0x82aaffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xc792eaff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x89ddffff).into()), - terminal_ansi_bright_white: Some(rgba(0xffffffff).into()), - terminal_ansi_black: Some(rgba(0x676e95ff).into()), - terminal_ansi_red: Some(rgba(0xff5572ff).into()), - terminal_ansi_green: Some(rgba(0xa9c77dff).into()), - terminal_ansi_yellow: Some(rgba(0xffcb6bff).into()), - terminal_ansi_blue: Some(rgba(0x82aaffff).into()), - terminal_ansi_magenta: Some(rgba(0xc792eaff).into()), - terminal_ansi_cyan: Some(rgba(0x89ddffff).into()), - terminal_ansi_white: Some(rgba(0xffffffff).into()), + border: Some(rgba(0x464b57ff).into()), + border_variant: Some(rgba(0x464b57ff).into()), + elevated_surface_background: Some(rgba(0x3b414dff).into()), + background: Some(rgba(0x3b414dff).into()), + panel_background: Some(rgba(0x2f343eff).into()), + element_hover: Some(rgba(0x464b5780).into()), + element_selected: Some(rgba(0x4f545e80).into()), + text: Some(rgba(0x838994ff).into()), + text_muted: Some(rgba(0x545862ff).into()), + status_bar_background: Some(rgba(0x3b414dff).into()), + title_bar_background: Some(rgba(0x3b414dff).into()), + toolbar_background: Some(rgba(0x282c34ff).into()), + tab_bar_background: Some(rgba(0x2f343eff).into()), + tab_inactive_background: Some(rgba(0x2f343eff).into()), + tab_active_background: Some(rgba(0x282c34ff).into()), + scrollbar_thumb_background: Some(rgba(0xc8ccd44d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xc8ccd44d).into()), + scrollbar_thumb_border: Some(rgba(0x2e333cff).into()), + scrollbar_track_border: Some(rgba(0x2e333cff).into()), + editor_foreground: Some(rgba(0xacb2beff).into()), + editor_background: Some(rgba(0x282c34ff).into()), + editor_gutter_background: Some(rgba(0x282c34ff).into()), + editor_line_number: Some(rgba(0xc8ccd459).into()), + editor_active_line_number: Some(rgba(0xc8ccd4ff).into()), + editor_wrap_guide: Some(rgba(0xc8ccd40d).into()), + editor_active_wrap_guide: Some(rgba(0xc8ccd41a).into()), + terminal_background: Some(rgba(0x282c34ff).into()), + terminal_ansi_bright_black: Some(rgba(0x525661ff).into()), + terminal_ansi_bright_red: Some(rgba(0x673a3cff).into()), + terminal_ansi_bright_green: Some(rgba(0x4d6140ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x786441ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x385378ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x5e2b26ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x3a565bff).into()), + terminal_ansi_bright_white: Some(rgba(0xc8ccd4ff).into()), + terminal_ansi_black: Some(rgba(0x282c34ff).into()), + terminal_ansi_red: Some(rgba(0xd07277ff).into()), + terminal_ansi_green: Some(rgba(0xa1c181ff).into()), + terminal_ansi_yellow: Some(rgba(0xdec184ff).into()), + terminal_ansi_blue: Some(rgba(0x74ade8ff).into()), + terminal_ansi_magenta: Some(rgba(0xbe5046ff).into()), + terminal_ansi_cyan: Some(rgba(0x6fb4c0ff).into()), + terminal_ansi_white: Some(rgba(0xc8ccd4ff).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xffeb95cc).into()), - created: Some(rgba(0x9ccc65ff).into()), - deleted: Some(rgba(0xef5350ff).into()), - error: Some(rgba(0xef5350ff).into()), - hidden: Some(rgba(0x929ac9ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x69709890).into()), - modified: Some(rgba(0xe2b93dff).into()), + created: Some(rgba(0xa1c181ff).into()), + deleted: Some(rgba(0xa45a5eff).into()), + error: Some(rgba(0xd07277ff).into()), + modified: Some(rgba(0xdec184ff).into()), + success: Some(rgba(0xc8ccd4ff).into()), + warning: Some(rgba(0xdec184ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -375,502 +421,278 @@ pub fn palenight() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0x74ade8ff).into()), ..Default::default() }, ), ( "boolean".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0xc0966bff).into()), ..Default::default() }, ), ( "comment".into(), UserHighlightStyle { - color: Some(rgba(0x697098ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x5d636fff).into()), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0x697098ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x878e98ff).into()), ..Default::default() }, ), ( "constant".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0xdfc184ff).into()), ..Default::default() }, ), ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), + color: Some(rgba(0x74ade9ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xc8ccd4ff).into()), ..Default::default() }, ), ( "emphasis".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x74ade8ff).into()), ..Default::default() }, ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0xc0966bff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xd07277ff).into()), + ..Default::default() + }, + ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0x74ade9ff).into()), ..Default::default() }, ), ( - "keyword".into(), + "hint".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0xff869aff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0xff869aff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xf78c6cff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0x89ddffff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0x80cbc4ff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - ..Default::default() - }, - ), - ( - "string".into(), - UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), - ..Default::default() - }, - ), - ( - "string.escape".into(), - UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), - ..Default::default() - }, - ), - ( - "string.regex".into(), - UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), - ..Default::default() - }, - ), - ( - "string.special".into(), - UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), - ..Default::default() - }, - ), - ( - "string.special.symbol".into(), - UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), - ..Default::default() - }, - ), - ( - "text.literal".into(), - UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), - ..Default::default() - }, - ), - ], - }), - }, - }, - UserTheme { - name: "Palenight (Mild Contrast)".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border: Some(rgba(0x2c2f40ff).into()), - border_variant: Some(rgba(0x2c2f40ff).into()), - border_focused: Some(rgba(0x2c2f40ff).into()), - border_selected: Some(rgba(0x2c2f40ff).into()), - border_transparent: Some(rgba(0x2c2f40ff).into()), - border_disabled: Some(rgba(0x2c2f40ff).into()), - elevated_surface_background: Some(rgba(0x292d3eff).into()), - surface_background: Some(rgba(0x25293aff).into()), - background: Some(rgba(0x292d3eff).into()), - element_background: Some(rgba(0x7e57c2cc).into()), - element_hover: Some(rgba(0x0000001a).into()), - element_selected: Some(rgba(0x7e57c2ff).into()), - drop_target_background: Some(rgba(0x2e3245ff).into()), - ghost_element_hover: Some(rgba(0x0000001a).into()), - ghost_element_selected: Some(rgba(0x7e57c2ff).into()), - text: Some(rgba(0xffffffff).into()), - text_muted: Some(rgba(0x929ac9ff).into()), - status_bar_background: Some(rgba(0x25293aff).into()), - title_bar_background: Some(rgba(0x25293aff).into()), - toolbar_background: Some(rgba(0x292d3eff).into()), - tab_bar_background: Some(rgba(0x31364aff).into()), - tab_inactive_background: Some(rgba(0x31364aff).into()), - tab_active_background: Some(rgba(0x25293aff).into()), - scrollbar_thumb_background: Some(rgba(0x694ca466).into()), - scrollbar_thumb_hover_background: Some(rgba(0x694ca4cc).into()), - scrollbar_thumb_border: Some(rgba(0x694ca466).into()), - scrollbar_track_background: Some(rgba(0x292d3eff).into()), - editor_foreground: Some(rgba(0xbfc7d5ff).into()), - editor_background: Some(rgba(0x292d3eff).into()), - editor_gutter_background: Some(rgba(0x292d3eff).into()), - editor_line_number: Some(rgba(0x4c5374ff).into()), - editor_active_line_number: Some(rgba(0xbfc7d5ff).into()), - editor_wrap_guide: Some(rgba(0x2c2f40ff).into()), - editor_active_wrap_guide: Some(rgba(0x2c2f40ff).into()), - terminal_ansi_bright_black: Some(rgba(0x676e95ff).into()), - terminal_ansi_bright_red: Some(rgba(0xff5572ff).into()), - terminal_ansi_bright_green: Some(rgba(0xc3e88dff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xffcb6bff).into()), - terminal_ansi_bright_blue: Some(rgba(0x82aaffff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xc792eaff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x89ddffff).into()), - terminal_ansi_bright_white: Some(rgba(0xffffffff).into()), - terminal_ansi_black: Some(rgba(0x676e95ff).into()), - terminal_ansi_red: Some(rgba(0xff5572ff).into()), - terminal_ansi_green: Some(rgba(0xa9c77dff).into()), - terminal_ansi_yellow: Some(rgba(0xffcb6bff).into()), - terminal_ansi_blue: Some(rgba(0x82aaffff).into()), - terminal_ansi_magenta: Some(rgba(0xc792eaff).into()), - terminal_ansi_cyan: Some(rgba(0x89ddffff).into()), - terminal_ansi_white: Some(rgba(0xffffffff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - conflict: Some(rgba(0xffeb95cc).into()), - created: Some(rgba(0x9ccc65ff).into()), - deleted: Some(rgba(0xef5350ff).into()), - error: Some(rgba(0xef5350ff).into()), - hidden: Some(rgba(0x929ac9ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0x69709890).into()), - modified: Some(rgba(0xe2b93dff).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), - ..Default::default() - }, - ), - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x697098ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x697098ff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), - ..Default::default() - }, - ), - ( - "emphasis".into(), - UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "emphasis.strong".into(), - UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0x5b708aff).into()), font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( - "function".into(), + "keyword".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0xb478cfff).into()), ..Default::default() }, ), ( - "keyword".into(), + "label".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0x74ade8ff).into()), ..Default::default() }, ), ( "link_text".into(), UserHighlightStyle { - color: Some(rgba(0xff869aff).into()), + color: Some(rgba(0x74ade9ff).into()), + font_style: Some(UserFontStyle::Normal), ..Default::default() }, ), ( "link_uri".into(), UserHighlightStyle { - color: Some(rgba(0xff869aff).into()), + color: Some(rgba(0x6fb4c0ff).into()), ..Default::default() }, ), ( "number".into(), UserHighlightStyle { - color: Some(rgba(0xf78c6cff).into()), + color: Some(rgba(0xc0966bff).into()), ..Default::default() }, ), ( "operator".into(), UserHighlightStyle { - color: Some(rgba(0x89ddffff).into()), + color: Some(rgba(0x6fb4c0ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x5b6b88ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xc8ccd4ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xacb2beff).into()), ..Default::default() }, ), ( "property".into(), UserHighlightStyle { - color: Some(rgba(0x80cbc4ff).into()), + color: Some(rgba(0xd07277ff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0xacb2beff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0xb2b9c6ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0xb2b9c6ff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0xd07277ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0xc792eaff).into()), + color: Some(rgba(0xb1574bff).into()), ..Default::default() }, ), ( "string".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0xa1c181ff).into()), ..Default::default() }, ), ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0x82aaffff).into()), + color: Some(rgba(0x878e98ff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0xc0966bff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0xc0966bff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0xc0966bff).into()), ..Default::default() }, ), ( "tag".into(), UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), + color: Some(rgba(0x74ade8ff).into()), ..Default::default() }, ), ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0xc3e88dff).into()), + color: Some(rgba(0xa1c181ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xd07277ff).into()), + font_weight: Some(UserFontWeight(400.0)), ..Default::default() }, ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0x6fb4c0ff).into()), ..Default::default() }, ), ( "variable".into(), UserHighlightStyle { - color: Some(rgba(0xffcb6bff).into()), + color: Some(rgba(0xc8ccd4ff).into()), ..Default::default() }, ), ( "variable.special".into(), UserHighlightStyle { - color: Some(rgba(0xff5572ff).into()), + color: Some(rgba(0xc0966bff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x74ade9ff).into()), ..Default::default() }, ), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index a24c7ef80d..abefb32f4e 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -12,77 +12,65 @@ use crate::{ pub fn rose_pine() -> UserThemeFamily { UserThemeFamily { name: "Rosé Pine".into(), - author: "Rosé Pine".into(), + author: "Zed Industries".into(), themes: vec![ UserTheme { - name: "Rosé Pine".into(), - appearance: Appearance::Dark, + name: "Rosé Pine Dawn".into(), + appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x00000000).into()), - border_variant: Some(rgba(0x00000000).into()), - border_focused: Some(rgba(0x6e6a8633).into()), - border_selected: Some(rgba(0x00000000).into()), - border_transparent: Some(rgba(0x00000000).into()), - border_disabled: Some(rgba(0x00000000).into()), - elevated_surface_background: Some(rgba(0x1f1d2eff).into()), - surface_background: Some(rgba(0x1f1d2eff).into()), - background: Some(rgba(0x191724ff).into()), - element_background: Some(rgba(0xebbcbaff).into()), - element_hover: Some(rgba(0x6e6a861a).into()), - element_selected: Some(rgba(0x6e6a8633).into()), - drop_target_background: Some(rgba(0x1f1d2eff).into()), - ghost_element_hover: Some(rgba(0x6e6a861a).into()), - ghost_element_selected: Some(rgba(0x6e6a8633).into()), - text: Some(rgba(0xe0def4ff).into()), - text_muted: Some(rgba(0x908caaff).into()), - status_bar_background: Some(rgba(0x191724ff).into()), - title_bar_background: Some(rgba(0x191724ff).into()), - toolbar_background: Some(rgba(0x191724ff).into()), - tab_bar_background: Some(rgba(0x00000000).into()), - tab_inactive_background: Some(rgba(0x00000000).into()), - tab_active_background: Some(rgba(0x6e6a861a).into()), - scrollbar_thumb_background: Some(rgba(0x6e6a8633).into()), - scrollbar_thumb_hover_background: Some(rgba(0x6e6a8666).into()), - scrollbar_thumb_border: Some(rgba(0x6e6a8633).into()), - scrollbar_track_background: Some(rgba(0x191724ff).into()), - scrollbar_track_border: Some(rgba(0x6e6a8666).into()), - editor_foreground: Some(rgba(0xe0def4ff).into()), - editor_background: Some(rgba(0x191724ff).into()), - editor_gutter_background: Some(rgba(0x191724ff).into()), - editor_line_number: Some(rgba(0x908caaff).into()), - editor_active_line_number: Some(rgba(0xe0def4ff).into()), - editor_wrap_guide: Some(rgba(0x00000000).into()), - editor_active_wrap_guide: Some(rgba(0x00000000).into()), - terminal_ansi_bright_black: Some(rgba(0x908caaff).into()), - terminal_ansi_bright_red: Some(rgba(0xeb6f92ff).into()), - terminal_ansi_bright_green: Some(rgba(0x31748fff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xf6c177ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x9ccfd8ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xc4a7e7ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0xebbcbaff).into()), - terminal_ansi_bright_white: Some(rgba(0xe0def4ff).into()), - terminal_ansi_black: Some(rgba(0x26233aff).into()), - terminal_ansi_red: Some(rgba(0xeb6f92ff).into()), - terminal_ansi_green: Some(rgba(0x31748fff).into()), - terminal_ansi_yellow: Some(rgba(0xf6c177ff).into()), - terminal_ansi_blue: Some(rgba(0x9ccfd8ff).into()), - terminal_ansi_magenta: Some(rgba(0xc4a7e7ff).into()), - terminal_ansi_cyan: Some(rgba(0xebbcbaff).into()), - terminal_ansi_white: Some(rgba(0xe0def4ff).into()), - link_text_hover: Some(rgba(0xc4a7e7e6).into()), + border: Some(rgba(0xdcd6d5ff).into()), + border_variant: Some(rgba(0xdcd6d5ff).into()), + elevated_surface_background: Some(rgba(0xdcd8d8ff).into()), + background: Some(rgba(0xdcd8d8ff).into()), + panel_background: Some(rgba(0xfef9f2ff).into()), + element_hover: Some(rgba(0xdcd6d580).into()), + element_selected: Some(rgba(0xc1bac180).into()), + text: Some(rgba(0x706c8cff).into()), + text_muted: Some(rgba(0xb1abb5ff).into()), + status_bar_background: Some(rgba(0xdcd8d8ff).into()), + title_bar_background: Some(rgba(0xdcd8d8ff).into()), + toolbar_background: Some(rgba(0xfaf4edff).into()), + tab_bar_background: Some(rgba(0xfef9f2ff).into()), + tab_inactive_background: Some(rgba(0xfef9f2ff).into()), + tab_active_background: Some(rgba(0xfaf4edff).into()), + scrollbar_thumb_background: Some(rgba(0x5752794d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x5752794d).into()), + scrollbar_thumb_border: Some(rgba(0xfdf8f1ff).into()), + scrollbar_track_border: Some(rgba(0xfdf8f1ff).into()), + editor_foreground: Some(rgba(0x575279ff).into()), + editor_background: Some(rgba(0xfaf4edff).into()), + editor_gutter_background: Some(rgba(0xfaf4edff).into()), + editor_line_number: Some(rgba(0x57527959).into()), + editor_active_line_number: Some(rgba(0x575279ff).into()), + editor_wrap_guide: Some(rgba(0x5752790d).into()), + editor_active_wrap_guide: Some(rgba(0x5752791a).into()), + terminal_background: Some(rgba(0xfaf4edff).into()), + terminal_ansi_bright_black: Some(rgba(0xb8b2baff).into()), + terminal_ansi_bright_red: Some(rgba(0xdcb0bbff).into()), + terminal_ansi_bright_green: Some(rgba(0xa5d5c5ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xfccd9bff).into()), + terminal_ansi_bright_blue: Some(rgba(0xacc9ceff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xbcb1bdff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x97b1c0ff).into()), + terminal_ansi_bright_white: Some(rgba(0x575279ff).into()), + terminal_ansi_black: Some(rgba(0xfaf4edff).into()), + terminal_ansi_red: Some(rgba(0xb4647aff).into()), + terminal_ansi_green: Some(rgba(0x3eaa8eff).into()), + terminal_ansi_yellow: Some(rgba(0xe99d35ff).into()), + terminal_ansi_blue: Some(rgba(0x57949fff).into()), + terminal_ansi_magenta: Some(rgba(0x7c697fff).into()), + terminal_ansi_cyan: Some(rgba(0x2a6983ff).into()), + terminal_ansi_white: Some(rgba(0x575279ff).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xeb6f92ff).into()), - created: Some(rgba(0x9ccfd8ff).into()), - deleted: Some(rgba(0xeb6f92ff).into()), - error: Some(rgba(0xeb6f92ff).into()), - hidden: Some(rgba(0x908caaff).into()), - hint: Some(rgba(0x908caaff).into()), - ignored: Some(rgba(0x6e6a86ff).into()), - modified: Some(rgba(0xebbcbaff).into()), - warning: Some(rgba(0xf6c177ff).into()), + created: Some(rgba(0x6bbca3ff).into()), + deleted: Some(rgba(0xb4647aff).into()), + error: Some(rgba(0xb4647aff).into()), + modified: Some(rgba(0xe99d35ff).into()), + success: Some(rgba(0x575279ff).into()), + warning: Some(rgba(0xe99d35ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -90,186 +78,285 @@ pub fn rose_pine() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xc4a7e7ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x57949fff).into()), ..Default::default() }, ), ( "boolean".into(), UserHighlightStyle { - color: Some(rgba(0xebbcbaff).into()), + color: Some(rgba(0xd7827eff).into()), ..Default::default() }, ), ( "comment".into(), UserHighlightStyle { - color: Some(rgba(0x6e6a86ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x9893a5ff).into()), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0x6e6a86ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x6f6b8cff).into()), ..Default::default() }, ), ( "constant".into(), UserHighlightStyle { - color: Some(rgba(0x31748fff).into()), + color: Some(rgba(0x3eaa8eff).into()), ..Default::default() }, ), ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0x9ccfd8ff).into()), + color: Some(rgba(0x57949fff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0x575279ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x57949fff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x57949fff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0x907aa9ff).into()), ..Default::default() }, ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0xebbcbaff).into()), + color: Some(rgba(0xd7827eff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0xd7827eff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x7a92aaff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "keyword".into(), UserHighlightStyle { - color: Some(rgba(0x31748fff).into()), + color: Some(rgba(0x286983ff).into()), ..Default::default() }, ), ( "label".into(), UserHighlightStyle { - color: Some(rgba(0xebbcbaff).into()), + color: Some(rgba(0x57949fff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x56949fff).into()), + font_style: Some(UserFontStyle::Normal), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0xd7827eff).into()), ..Default::default() }, ), ( "number".into(), UserHighlightStyle { - color: Some(rgba(0xebbcbaff).into()), + color: Some(rgba(0x3eaa8eff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x286983ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0xa2acbeff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0x575279ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x575279ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x57949fff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0x797593ff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0x635e82ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0x635e82ff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0x635e82ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0x635e82ff).into()), ..Default::default() }, ), ( "string".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0xea9d34ff).into()), ..Default::default() }, ), ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0x6f6b8cff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0x907aa9ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0x907aa9ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0x907aa9ff).into()), ..Default::default() }, ), ( "tag".into(), UserHighlightStyle { - color: Some(rgba(0x9ccfd8ff).into()), + color: Some(rgba(0x56949fff).into()), ..Default::default() }, ), ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0x907aa9ff).into()), ..Default::default() }, ), ( "title".into(), UserHighlightStyle { - color: Some(rgba(0xebbcbaff).into()), + color: Some(rgba(0xea9d34ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0x9ccfd8ff).into()), + color: Some(rgba(0x56949fff).into()), + ..Default::default() + }, + ), + ( + "type.builtin".into(), + UserHighlightStyle { + color: Some(rgba(0x56949fff).into()), ..Default::default() }, ), ( "variable".into(), UserHighlightStyle { - color: Some(rgba(0xebbcbaff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x575279ff).into()), ..Default::default() }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0xe0def4ff).into()), + color: Some(rgba(0x57949fff).into()), ..Default::default() }, ), @@ -282,70 +369,58 @@ pub fn rose_pine() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x00000000).into()), - border_variant: Some(rgba(0x00000000).into()), - border_focused: Some(rgba(0x817c9c26).into()), - border_selected: Some(rgba(0x00000000).into()), - border_transparent: Some(rgba(0x00000000).into()), - border_disabled: Some(rgba(0x00000000).into()), - elevated_surface_background: Some(rgba(0x2a273fff).into()), - surface_background: Some(rgba(0x2a273fff).into()), - background: Some(rgba(0x232136ff).into()), - element_background: Some(rgba(0xea9a97ff).into()), - element_hover: Some(rgba(0x817c9c14).into()), - element_selected: Some(rgba(0x817c9c26).into()), - drop_target_background: Some(rgba(0x2a273fff).into()), - ghost_element_hover: Some(rgba(0x817c9c14).into()), - ghost_element_selected: Some(rgba(0x817c9c26).into()), - text: Some(rgba(0xe0def4ff).into()), - text_muted: Some(rgba(0x908caaff).into()), - status_bar_background: Some(rgba(0x232136ff).into()), - title_bar_background: Some(rgba(0x232136ff).into()), + border: Some(rgba(0x504c68ff).into()), + border_variant: Some(rgba(0x504c68ff).into()), + elevated_surface_background: Some(rgba(0x38354eff).into()), + background: Some(rgba(0x38354eff).into()), + panel_background: Some(rgba(0x28253cff).into()), + element_hover: Some(rgba(0x504c6880).into()), + element_selected: Some(rgba(0x45415d80).into()), + text: Some(rgba(0x85819eff).into()), + text_muted: Some(rgba(0x3a3653ff).into()), + status_bar_background: Some(rgba(0x38354eff).into()), + title_bar_background: Some(rgba(0x38354eff).into()), toolbar_background: Some(rgba(0x232136ff).into()), - tab_bar_background: Some(rgba(0x00000000).into()), - tab_inactive_background: Some(rgba(0x00000000).into()), - tab_active_background: Some(rgba(0x817c9c14).into()), - scrollbar_thumb_background: Some(rgba(0x817c9c26).into()), - scrollbar_thumb_hover_background: Some(rgba(0x817c9c4d).into()), - scrollbar_thumb_border: Some(rgba(0x817c9c26).into()), - scrollbar_track_background: Some(rgba(0x232136ff).into()), - scrollbar_track_border: Some(rgba(0x817c9c4d).into()), + tab_bar_background: Some(rgba(0x28253cff).into()), + tab_inactive_background: Some(rgba(0x28253cff).into()), + tab_active_background: Some(rgba(0x232136ff).into()), + scrollbar_thumb_background: Some(rgba(0xe0def44d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xe0def44d).into()), + scrollbar_thumb_border: Some(rgba(0x27243bff).into()), + scrollbar_track_border: Some(rgba(0x27243bff).into()), editor_foreground: Some(rgba(0xe0def4ff).into()), editor_background: Some(rgba(0x232136ff).into()), editor_gutter_background: Some(rgba(0x232136ff).into()), - editor_line_number: Some(rgba(0x908caaff).into()), + editor_line_number: Some(rgba(0xe0def459).into()), editor_active_line_number: Some(rgba(0xe0def4ff).into()), - editor_wrap_guide: Some(rgba(0x00000000).into()), - editor_active_wrap_guide: Some(rgba(0x00000000).into()), - terminal_ansi_bright_black: Some(rgba(0x908caaff).into()), - terminal_ansi_bright_red: Some(rgba(0xeb6f92ff).into()), - terminal_ansi_bright_green: Some(rgba(0x3e8fb0ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xf6c177ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x9ccfd8ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xc4a7e7ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0xea9a97ff).into()), + editor_wrap_guide: Some(rgba(0xe0def40d).into()), + editor_active_wrap_guide: Some(rgba(0xe0def41a).into()), + terminal_background: Some(rgba(0x232136ff).into()), + terminal_ansi_bright_black: Some(rgba(0x3f3b58ff).into()), + terminal_ansi_bright_red: Some(rgba(0x7e3647ff).into()), + terminal_ansi_bright_green: Some(rgba(0x31614fff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x8a653bff).into()), + terminal_ansi_bright_blue: Some(rgba(0x566c70ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x51414eff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x264654ff).into()), terminal_ansi_bright_white: Some(rgba(0xe0def4ff).into()), - terminal_ansi_black: Some(rgba(0x393552ff).into()), - terminal_ansi_red: Some(rgba(0xeb6f92ff).into()), - terminal_ansi_green: Some(rgba(0x3e8fb0ff).into()), - terminal_ansi_yellow: Some(rgba(0xf6c177ff).into()), - terminal_ansi_blue: Some(rgba(0x9ccfd8ff).into()), - terminal_ansi_magenta: Some(rgba(0xc4a7e7ff).into()), - terminal_ansi_cyan: Some(rgba(0xea9a97ff).into()), + terminal_ansi_black: Some(rgba(0x232136ff).into()), + terminal_ansi_red: Some(rgba(0xea6f92ff).into()), + terminal_ansi_green: Some(rgba(0x5dc2a3ff).into()), + terminal_ansi_yellow: Some(rgba(0xf5c177ff).into()), + terminal_ansi_blue: Some(rgba(0x9cced7ff).into()), + terminal_ansi_magenta: Some(rgba(0xa784a1ff).into()), + terminal_ansi_cyan: Some(rgba(0x3f8fb0ff).into()), terminal_ansi_white: Some(rgba(0xe0def4ff).into()), - link_text_hover: Some(rgba(0xc4a7e7e6).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xeb6f92ff).into()), - created: Some(rgba(0x9ccfd8ff).into()), - deleted: Some(rgba(0xeb6f92ff).into()), - error: Some(rgba(0xeb6f92ff).into()), - hidden: Some(rgba(0x908caaff).into()), - hint: Some(rgba(0x908caaff).into()), - ignored: Some(rgba(0x6e6a86ff).into()), - modified: Some(rgba(0xea9a97ff).into()), - warning: Some(rgba(0xf6c177ff).into()), + created: Some(rgba(0x5dc2a3ff).into()), + deleted: Some(rgba(0xbe5773ff).into()), + error: Some(rgba(0xea6f92ff).into()), + modified: Some(rgba(0xf5c177ff).into()), + success: Some(rgba(0xe0def4ff).into()), + warning: Some(rgba(0xf5c177ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -353,8 +428,7 @@ pub fn rose_pine() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0xc4a7e7ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x9cced7ff).into()), ..Default::default() }, ), @@ -369,29 +443,56 @@ pub fn rose_pine() -> UserThemeFamily { "comment".into(), UserHighlightStyle { color: Some(rgba(0x6e6a86ff).into()), - font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0x6e6a86ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x8682a0ff).into()), ..Default::default() }, ), ( "constant".into(), UserHighlightStyle { - color: Some(rgba(0x3e8fb0ff).into()), + color: Some(rgba(0x5dc2a3ff).into()), ..Default::default() }, ), ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0x9ccfd8ff).into()), + color: Some(rgba(0x9cced7ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xe0def4ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x9cced7ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x9cced7ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), @@ -402,6 +503,21 @@ pub fn rose_pine() -> UserThemeFamily { ..Default::default() }, ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0xea9a97ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x728aa2ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), ( "keyword".into(), UserHighlightStyle { @@ -411,6 +527,21 @@ pub fn rose_pine() -> UserThemeFamily { ), ( "label".into(), + UserHighlightStyle { + color: Some(rgba(0x9cced7ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x9ccfd8ff).into()), + font_style: Some(UserFontStyle::Normal), + ..Default::default() + }, + ), + ( + "link_uri".into(), UserHighlightStyle { color: Some(rgba(0xea9a97ff).into()), ..Default::default() @@ -419,7 +550,43 @@ pub fn rose_pine() -> UserThemeFamily { ( "number".into(), UserHighlightStyle { - color: Some(rgba(0xea9a97ff).into()), + color: Some(rgba(0x5dc2a3ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x3e8fb0ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x516b83ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xe0def4ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xe0def4ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x9cced7ff).into()), ..Default::default() }, ), @@ -433,28 +600,28 @@ pub fn rose_pine() -> UserThemeFamily { ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0xaeabc6ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0xaeabc6ff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0xaeabc6ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0x908caaff).into()), + color: Some(rgba(0xaeabc6ff).into()), ..Default::default() }, ), @@ -468,28 +635,28 @@ pub fn rose_pine() -> UserThemeFamily { ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0x8682a0ff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), @@ -503,14 +670,15 @@ pub fn rose_pine() -> UserThemeFamily { ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0xf6c177ff).into()), + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), ( "title".into(), UserHighlightStyle { - color: Some(rgba(0xea9a97ff).into()), + color: Some(rgba(0xf6c177ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), @@ -522,93 +690,87 @@ pub fn rose_pine() -> UserThemeFamily { }, ), ( - "variable".into(), + "type.builtin".into(), UserHighlightStyle { - color: Some(rgba(0xea9a97ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x9ccfd8ff).into()), ..Default::default() }, ), ( - "variable.special".into(), + "variable".into(), UserHighlightStyle { color: Some(rgba(0xe0def4ff).into()), ..Default::default() }, ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x9cced7ff).into()), + ..Default::default() + }, + ), ], }), }, }, UserTheme { - name: "Rosé Pine Dawn".into(), - appearance: Appearance::Light, + name: "Rosé Pine".into(), + appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x00000000).into()), - border_variant: Some(rgba(0x00000000).into()), - border_focused: Some(rgba(0x6e6a8614).into()), - border_selected: Some(rgba(0x00000000).into()), - border_transparent: Some(rgba(0x00000000).into()), - border_disabled: Some(rgba(0x00000000).into()), - elevated_surface_background: Some(rgba(0xfffaf3ff).into()), - surface_background: Some(rgba(0xfffaf3ff).into()), - background: Some(rgba(0xfaf4edff).into()), - element_background: Some(rgba(0xd7827eff).into()), - element_hover: Some(rgba(0x6e6a860d).into()), - element_selected: Some(rgba(0x6e6a8614).into()), - drop_target_background: Some(rgba(0xfffaf3ff).into()), - ghost_element_hover: Some(rgba(0x6e6a860d).into()), - ghost_element_selected: Some(rgba(0x6e6a8614).into()), - text: Some(rgba(0x575279ff).into()), - text_muted: Some(rgba(0x797593ff).into()), - status_bar_background: Some(rgba(0xfaf4edff).into()), - title_bar_background: Some(rgba(0xfaf4edff).into()), - toolbar_background: Some(rgba(0xfaf4edff).into()), - tab_bar_background: Some(rgba(0x00000000).into()), - tab_inactive_background: Some(rgba(0x00000000).into()), - tab_active_background: Some(rgba(0x6e6a860d).into()), - scrollbar_thumb_background: Some(rgba(0x6e6a8614).into()), - scrollbar_thumb_hover_background: Some(rgba(0x6e6a8626).into()), - scrollbar_thumb_border: Some(rgba(0x6e6a8614).into()), - scrollbar_track_background: Some(rgba(0xfaf4edff).into()), - scrollbar_track_border: Some(rgba(0x6e6a8626).into()), - editor_foreground: Some(rgba(0x575279ff).into()), - editor_background: Some(rgba(0xfaf4edff).into()), - editor_gutter_background: Some(rgba(0xfaf4edff).into()), - editor_line_number: Some(rgba(0x797593ff).into()), - editor_active_line_number: Some(rgba(0x575279ff).into()), - editor_wrap_guide: Some(rgba(0x00000000).into()), - editor_active_wrap_guide: Some(rgba(0x00000000).into()), - terminal_ansi_bright_black: Some(rgba(0x797593ff).into()), - terminal_ansi_bright_red: Some(rgba(0xb4637aff).into()), - terminal_ansi_bright_green: Some(rgba(0x286983ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xea9d34ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x56949fff).into()), - terminal_ansi_bright_magenta: Some(rgba(0x907aa9ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0xd7827eff).into()), - terminal_ansi_bright_white: Some(rgba(0x575279ff).into()), - terminal_ansi_black: Some(rgba(0xf2e9e1ff).into()), - terminal_ansi_red: Some(rgba(0xb4637aff).into()), - terminal_ansi_green: Some(rgba(0x286983ff).into()), - terminal_ansi_yellow: Some(rgba(0xea9d34ff).into()), - terminal_ansi_blue: Some(rgba(0x56949fff).into()), - terminal_ansi_magenta: Some(rgba(0x907aa9ff).into()), - terminal_ansi_cyan: Some(rgba(0xd7827eff).into()), - terminal_ansi_white: Some(rgba(0x575279ff).into()), - link_text_hover: Some(rgba(0x907aa9e6).into()), + border: Some(rgba(0x423f55ff).into()), + border_variant: Some(rgba(0x423f55ff).into()), + elevated_surface_background: Some(rgba(0x292739ff).into()), + background: Some(rgba(0x292739ff).into()), + panel_background: Some(rgba(0x1d1b2aff).into()), + element_hover: Some(rgba(0x423f5580).into()), + element_selected: Some(rgba(0x47445b80).into()), + text: Some(rgba(0x75718eff).into()), + text_muted: Some(rgba(0x3b384fff).into()), + status_bar_background: Some(rgba(0x292739ff).into()), + title_bar_background: Some(rgba(0x292739ff).into()), + toolbar_background: Some(rgba(0x191724ff).into()), + tab_bar_background: Some(rgba(0x1d1b2aff).into()), + tab_inactive_background: Some(rgba(0x1d1b2aff).into()), + tab_active_background: Some(rgba(0x191724ff).into()), + scrollbar_thumb_background: Some(rgba(0xe0def44d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xe0def44d).into()), + scrollbar_thumb_border: Some(rgba(0x1c1a29ff).into()), + scrollbar_track_border: Some(rgba(0x1c1a29ff).into()), + editor_foreground: Some(rgba(0xe0def4ff).into()), + editor_background: Some(rgba(0x191724ff).into()), + editor_gutter_background: Some(rgba(0x191724ff).into()), + editor_line_number: Some(rgba(0xe0def459).into()), + editor_active_line_number: Some(rgba(0xe0def4ff).into()), + editor_wrap_guide: Some(rgba(0xe0def40d).into()), + editor_active_wrap_guide: Some(rgba(0xe0def41a).into()), + terminal_background: Some(rgba(0x191724ff).into()), + terminal_ansi_bright_black: Some(rgba(0x403d55ff).into()), + terminal_ansi_bright_red: Some(rgba(0x7e3647ff).into()), + terminal_ansi_bright_green: Some(rgba(0x31614fff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x8a653bff).into()), + terminal_ansi_bright_blue: Some(rgba(0x566c70ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x4c3b47ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x203a46ff).into()), + terminal_ansi_bright_white: Some(rgba(0xe0def4ff).into()), + terminal_ansi_black: Some(rgba(0x191724ff).into()), + terminal_ansi_red: Some(rgba(0xea6f92ff).into()), + terminal_ansi_green: Some(rgba(0x5dc2a3ff).into()), + terminal_ansi_yellow: Some(rgba(0xf5c177ff).into()), + terminal_ansi_blue: Some(rgba(0x9cced7ff).into()), + terminal_ansi_magenta: Some(rgba(0x9d7691ff).into()), + terminal_ansi_cyan: Some(rgba(0x32748fff).into()), + terminal_ansi_white: Some(rgba(0xe0def4ff).into()), ..Default::default() }, status: StatusColorsRefinement { - conflict: Some(rgba(0xb4637aff).into()), - created: Some(rgba(0x56949fff).into()), - deleted: Some(rgba(0xb4637aff).into()), - error: Some(rgba(0xb4637aff).into()), - hidden: Some(rgba(0x797593ff).into()), - hint: Some(rgba(0x797593ff).into()), - ignored: Some(rgba(0x9893a5ff).into()), - modified: Some(rgba(0xd7827eff).into()), - warning: Some(rgba(0xea9d34ff).into()), + created: Some(rgba(0x5dc2a3ff).into()), + deleted: Some(rgba(0xbe5773ff).into()), + error: Some(rgba(0xea6f92ff).into()), + modified: Some(rgba(0xf5c177ff).into()), + success: Some(rgba(0xe0def4ff).into()), + warning: Some(rgba(0xf5c177ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -616,186 +778,285 @@ pub fn rose_pine() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0x907aa9ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x9cced7ff).into()), ..Default::default() }, ), ( "boolean".into(), UserHighlightStyle { - color: Some(rgba(0xd7827eff).into()), + color: Some(rgba(0xebbcbaff).into()), ..Default::default() }, ), ( "comment".into(), UserHighlightStyle { - color: Some(rgba(0x9893a5ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x6e6a86ff).into()), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0x9893a5ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x777390ff).into()), ..Default::default() }, ), ( "constant".into(), UserHighlightStyle { - color: Some(rgba(0x286983ff).into()), + color: Some(rgba(0x5dc2a3ff).into()), ..Default::default() }, ), ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0x56949fff).into()), + color: Some(rgba(0x9cced7ff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xe0def4ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x9cced7ff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x9cced7ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0xd7827eff).into()), + color: Some(rgba(0xebbcbaff).into()), + ..Default::default() + }, + ), + ( + "function.method".into(), + UserHighlightStyle { + color: Some(rgba(0xebbcbaff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x5e768cff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "keyword".into(), UserHighlightStyle { - color: Some(rgba(0x286983ff).into()), + color: Some(rgba(0x31748fff).into()), ..Default::default() }, ), ( "label".into(), UserHighlightStyle { - color: Some(rgba(0xd7827eff).into()), + color: Some(rgba(0x9cced7ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0x9ccfd8ff).into()), + font_style: Some(UserFontStyle::Normal), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0xebbcbaff).into()), ..Default::default() }, ), ( "number".into(), UserHighlightStyle { - color: Some(rgba(0xd7827eff).into()), + color: Some(rgba(0x5dc2a3ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0x31748fff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x556b81ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xe0def4ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xe0def4ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x9cced7ff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0x797593ff).into()), + color: Some(rgba(0x908caaff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0x797593ff).into()), + color: Some(rgba(0x9d99b6ff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0x797593ff).into()), + color: Some(rgba(0x9d99b6ff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0x797593ff).into()), + color: Some(rgba(0x9d99b6ff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0x797593ff).into()), + color: Some(rgba(0x9d99b6ff).into()), ..Default::default() }, ), ( "string".into(), UserHighlightStyle { - color: Some(rgba(0xea9d34ff).into()), + color: Some(rgba(0xf6c177ff).into()), ..Default::default() }, ), ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0xea9d34ff).into()), + color: Some(rgba(0x777390ff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0xea9d34ff).into()), + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0xea9d34ff).into()), + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0xea9d34ff).into()), + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), ( "tag".into(), UserHighlightStyle { - color: Some(rgba(0x56949fff).into()), + color: Some(rgba(0x9ccfd8ff).into()), ..Default::default() }, ), ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0xea9d34ff).into()), + color: Some(rgba(0xc4a7e6ff).into()), ..Default::default() }, ), ( "title".into(), UserHighlightStyle { - color: Some(rgba(0xd7827eff).into()), + color: Some(rgba(0xf6c177ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0x56949fff).into()), + color: Some(rgba(0x9ccfd8ff).into()), + ..Default::default() + }, + ), + ( + "type.builtin".into(), + UserHighlightStyle { + color: Some(rgba(0x9ccfd8ff).into()), ..Default::default() }, ), ( "variable".into(), UserHighlightStyle { - color: Some(rgba(0xd7827eff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0xe0def4ff).into()), ..Default::default() }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0x575279ff).into()), + color: Some(rgba(0x9cced7ff).into()), ..Default::default() }, ), diff --git a/crates/theme2/src/themes/sandcastle.rs b/crates/theme2/src/themes/sandcastle.rs new file mode 100644 index 0000000000..2ee42660e3 --- /dev/null +++ b/crates/theme2/src/themes/sandcastle.rs @@ -0,0 +1,353 @@ +// This file was generated by the `theme_importer`. +// Be careful when modifying it by hand. + +use gpui::rgba; + +#[allow(unused)] +use crate::{ + Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, + UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, +}; + +pub fn sandcastle() -> UserThemeFamily { + UserThemeFamily { + name: "Sandcastle".into(), + author: "Zed Industries".into(), + themes: vec![UserTheme { + name: "Sandcastle".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x3d4350ff).into()), + border_variant: Some(rgba(0x3d4350ff).into()), + elevated_surface_background: Some(rgba(0x333944ff).into()), + background: Some(rgba(0x333944ff).into()), + panel_background: Some(rgba(0x2b3039ff).into()), + element_hover: Some(rgba(0x3d435080).into()), + element_selected: Some(rgba(0x57535380).into()), + text: Some(rgba(0xa69782ff).into()), + text_muted: Some(rgba(0x645b54ff).into()), + status_bar_background: Some(rgba(0x333944ff).into()), + title_bar_background: Some(rgba(0x333944ff).into()), + toolbar_background: Some(rgba(0x282c34ff).into()), + tab_bar_background: Some(rgba(0x2b3039ff).into()), + tab_inactive_background: Some(rgba(0x2b3039ff).into()), + tab_active_background: Some(rgba(0x282c34ff).into()), + scrollbar_thumb_background: Some(rgba(0xfdf4c14d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xfdf4c14d).into()), + scrollbar_thumb_border: Some(rgba(0x2a2f38ff).into()), + scrollbar_track_border: Some(rgba(0x2a2f38ff).into()), + editor_foreground: Some(rgba(0xfdf4c1ff).into()), + editor_background: Some(rgba(0x282c34ff).into()), + editor_gutter_background: Some(rgba(0x282c34ff).into()), + editor_line_number: Some(rgba(0xfdf4c159).into()), + editor_active_line_number: Some(rgba(0xfdf4c1ff).into()), + editor_wrap_guide: Some(rgba(0xfdf4c10d).into()), + editor_active_wrap_guide: Some(rgba(0xfdf4c11a).into()), + terminal_background: Some(rgba(0x282c34ff).into()), + terminal_ansi_bright_black: Some(rgba(0x5e5753ff).into()), + terminal_ansi_bright_red: Some(rgba(0x57333dff).into()), + terminal_ansi_bright_green: Some(rgba(0x414f4aff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x4e3f22ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x2c4444ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x523a18ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x414f4aff).into()), + terminal_ansi_bright_white: Some(rgba(0xfdf4c1ff).into()), + terminal_ansi_black: Some(rgba(0x282c34ff).into()), + terminal_ansi_red: Some(rgba(0xb4637aff).into()), + terminal_ansi_green: Some(rgba(0x83a598ff).into()), + terminal_ansi_yellow: Some(rgba(0xa07e3bff).into()), + terminal_ansi_blue: Some(rgba(0x528b8bff).into()), + terminal_ansi_magenta: Some(rgba(0xa87323ff).into()), + terminal_ansi_cyan: Some(rgba(0x83a598ff).into()), + terminal_ansi_white: Some(rgba(0xfdf4c1ff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x83a598ff).into()), + deleted: Some(rgba(0x8d4f61ff).into()), + error: Some(rgba(0xb4637aff).into()), + modified: Some(rgba(0xa07e3bff).into()), + success: Some(rgba(0xfdf4c1ff).into()), + warning: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0xa89984ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0xa89984ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xfdf4c1ff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x727d68ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x5c6152ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xfdf4c1ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xfdf4c1ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xd5c5a1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xd5c5a1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xd5c5a1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xd5c5a1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xd5c5a1ff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0xa89984ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xa07e3bff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xfdf4c1ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x83a598ff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xfdf4c1ff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x528b8bff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }], + } +} diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index 8a5bf96c16..4b8f60a61d 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -12,64 +12,65 @@ use crate::{ pub fn solarized() -> UserThemeFamily { UserThemeFamily { name: "Solarized".into(), - author: "Ethan Schoonover (altercation)".into(), + author: "Zed Industries".into(), themes: vec![ UserTheme { - name: "Solarized Dark".into(), - appearance: Appearance::Dark, + name: "Solarized Light".into(), + appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x003847ff).into()), - border_variant: Some(rgba(0x003847ff).into()), - border_focused: Some(rgba(0x2aa19899).into()), - border_selected: Some(rgba(0x003847ff).into()), - border_transparent: Some(rgba(0x003847ff).into()), - border_disabled: Some(rgba(0x003847ff).into()), - elevated_surface_background: Some(rgba(0x00212bff).into()), - background: Some(rgba(0x002b36ff).into()), - element_background: Some(rgba(0x2aa19899).into()), - element_hover: Some(rgba(0x004454aa).into()), - element_selected: Some(rgba(0x005a6fff).into()), - drop_target_background: Some(rgba(0x00445488).into()), - ghost_element_hover: Some(rgba(0x004454aa).into()), - ghost_element_selected: Some(rgba(0x005a6fff).into()), - text: Some(rgba(0xbbbbbbff).into()), - text_muted: Some(rgba(0x93a1a1ff).into()), - status_bar_background: Some(rgba(0x00212bff).into()), - title_bar_background: Some(rgba(0x002c39ff).into()), - toolbar_background: Some(rgba(0x002b36ff).into()), - tab_bar_background: Some(rgba(0x004052ff).into()), - tab_inactive_background: Some(rgba(0x004052ff).into()), - tab_active_background: Some(rgba(0x002b37ff).into()), - scrollbar_track_background: Some(rgba(0x002b36ff).into()), - editor_foreground: Some(rgba(0xbbbbbbff).into()), - editor_background: Some(rgba(0x002b36ff).into()), - editor_gutter_background: Some(rgba(0x002b36ff).into()), - editor_line_number: Some(rgba(0x566c74ff).into()), - editor_wrap_guide: Some(rgba(0x003847ff).into()), - editor_active_wrap_guide: Some(rgba(0x003847ff).into()), - terminal_ansi_bright_black: Some(rgba(0x586e75ff).into()), - terminal_ansi_bright_red: Some(rgba(0xcb4b16ff).into()), - terminal_ansi_bright_green: Some(rgba(0x859900ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0x657b83ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x839496ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0x6c71c4ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x93a1a1ff).into()), - terminal_ansi_bright_white: Some(rgba(0x839496ff).into()), - terminal_ansi_black: Some(rgba(0x073642ff).into()), - terminal_ansi_red: Some(rgba(0xdc322fff).into()), - terminal_ansi_green: Some(rgba(0x859900ff).into()), - terminal_ansi_yellow: Some(rgba(0xb58900ff).into()), - terminal_ansi_blue: Some(rgba(0x268bd2ff).into()), - terminal_ansi_magenta: Some(rgba(0xd33682ff).into()), - terminal_ansi_cyan: Some(rgba(0x2aa198ff).into()), - terminal_ansi_white: Some(rgba(0x839496ff).into()), + border: Some(rgba(0x9faaa8ff).into()), + border_variant: Some(rgba(0x9faaa8ff).into()), + elevated_surface_background: Some(rgba(0xcfd0c4ff).into()), + background: Some(rgba(0xcfd0c4ff).into()), + panel_background: Some(rgba(0xf3eddaff).into()), + element_hover: Some(rgba(0x9faaa880).into()), + element_selected: Some(rgba(0x7f919480).into()), + text: Some(rgba(0x34555eff).into()), + text_muted: Some(rgba(0x788b8fff).into()), + status_bar_background: Some(rgba(0xcfd0c4ff).into()), + title_bar_background: Some(rgba(0xcfd0c4ff).into()), + toolbar_background: Some(rgba(0xfdf6e3ff).into()), + tab_bar_background: Some(rgba(0xf3eddaff).into()), + tab_inactive_background: Some(rgba(0xf3eddaff).into()), + tab_active_background: Some(rgba(0xfdf6e3ff).into()), + scrollbar_thumb_background: Some(rgba(0x002b364d).into()), + scrollbar_thumb_hover_background: Some(rgba(0x002b364d).into()), + scrollbar_thumb_border: Some(rgba(0xf5eedbff).into()), + scrollbar_track_border: Some(rgba(0xf5eedbff).into()), + editor_foreground: Some(rgba(0x002b36ff).into()), + editor_background: Some(rgba(0xfdf6e3ff).into()), + editor_gutter_background: Some(rgba(0xfdf6e3ff).into()), + editor_line_number: Some(rgba(0x002b3659).into()), + editor_active_line_number: Some(rgba(0x002b36ff).into()), + editor_wrap_guide: Some(rgba(0x002b360d).into()), + editor_active_wrap_guide: Some(rgba(0x002b361a).into()), + terminal_background: Some(rgba(0xfdf6e3ff).into()), + terminal_ansi_bright_black: Some(rgba(0x7b8e91ff).into()), + terminal_ansi_bright_red: Some(rgba(0xfaa091ff).into()), + terminal_ansi_bright_green: Some(rgba(0xc6cb8bff).into()), + terminal_ansi_bright_yellow: Some(rgba(0xe1c28aff).into()), + terminal_ansi_bright_blue: Some(rgba(0xa5c3e9ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0xf0a2bfff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x9fd0cbff).into()), + terminal_ansi_bright_white: Some(rgba(0x002b36ff).into()), + terminal_ansi_black: Some(rgba(0xfdf6e3ff).into()), + terminal_ansi_red: Some(rgba(0xdc3330ff).into()), + terminal_ansi_green: Some(rgba(0x859904ff).into()), + terminal_ansi_yellow: Some(rgba(0xb58904ff).into()), + terminal_ansi_blue: Some(rgba(0x298bd1ff).into()), + terminal_ansi_magenta: Some(rgba(0xd33882ff).into()), + terminal_ansi_cyan: Some(rgba(0x2ca198ff).into()), + terminal_ansi_white: Some(rgba(0x002b36ff).into()), ..Default::default() }, status: StatusColorsRefinement { - error: Some(rgba(0xffeaeaff).into()), - hidden: Some(rgba(0x93a1a1ff).into()), - hint: Some(rgba(0x969696ff).into()), + created: Some(rgba(0xa0ad46ff).into()), + deleted: Some(rgba(0xdc3330ff).into()), + error: Some(rgba(0xdc3330ff).into()), + modified: Some(rgba(0xb58904ff).into()), + success: Some(rgba(0x002b36ff).into()), + warning: Some(rgba(0xb58904ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -77,205 +78,271 @@ pub fn solarized() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0x93a1a1ff).into()), + color: Some(rgba(0x298bd1ff).into()), ..Default::default() }, ), ( "boolean".into(), UserHighlightStyle { - color: Some(rgba(0xb58900ff).into()), + color: Some(rgba(0x859904ff).into()), ..Default::default() }, ), ( "comment".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x30525bff).into()), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x30525bff).into()), ..Default::default() }, ), ( "constant".into(), UserHighlightStyle { - color: Some(rgba(0xb58900ff).into()), + color: Some(rgba(0x859904ff).into()), ..Default::default() }, ), ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0x268bd2ff).into()), + color: Some(rgba(0x298bd1ff).into()), ..Default::default() }, ), ( "embedded".into(), UserHighlightStyle { - color: Some(rgba(0x93a1a1ff).into()), + color: Some(rgba(0x002b36ff).into()), ..Default::default() }, ), ( "emphasis".into(), UserHighlightStyle { - color: Some(rgba(0xd33682ff).into()), + color: Some(rgba(0x298bd1ff).into()), ..Default::default() }, ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xd33682ff).into()), + color: Some(rgba(0x298bd1ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xcb4c18ff).into()), ..Default::default() }, ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0x839496ff).into()), + color: Some(rgba(0xb58904ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x5889a3ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "keyword".into(), UserHighlightStyle { - color: Some(rgba(0x859900ff).into()), + color: Some(rgba(0x298bd1ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x298bd1ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xcb4c18ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x859904ff).into()), ..Default::default() }, ), ( "number".into(), UserHighlightStyle { - color: Some(rgba(0xd33682ff).into()), + color: Some(rgba(0x859904ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xcb4c18ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x679aafff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), ( "preproc".into(), UserHighlightStyle { - color: Some(rgba(0xb58900ff).into()), + color: Some(rgba(0x002b36ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0x002b36ff).into()), ..Default::default() }, ), ( "property".into(), UserHighlightStyle { - color: Some(rgba(0x839496ff).into()), + color: Some(rgba(0x298bd1ff).into()), ..Default::default() }, ), ( "punctuation".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), + color: Some(rgba(0x05333eff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), + color: Some(rgba(0x05333eff).into()), ..Default::default() }, ), ( "punctuation.delimiter".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), + color: Some(rgba(0x05333eff).into()), ..Default::default() }, ), ( "punctuation.list_marker".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), + color: Some(rgba(0x05333eff).into()), ..Default::default() }, ), ( "punctuation.special".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), + color: Some(rgba(0x05333eff).into()), ..Default::default() }, ), ( "string".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4c18ff).into()), ..Default::default() }, ), ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0xcb4b16ff).into()), + color: Some(rgba(0x30525bff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4c18ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4c18ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4c18ff).into()), ..Default::default() }, ), ( "tag".into(), UserHighlightStyle { - color: Some(rgba(0x268bd2ff).into()), + color: Some(rgba(0x298bd1ff).into()), ..Default::default() }, ), ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4c18ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0x002b36ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0xb58900ff).into()), + color: Some(rgba(0x2ca198ff).into()), ..Default::default() }, ), ( "variable".into(), UserHighlightStyle { - color: Some(rgba(0x268bd2ff).into()), + color: Some(rgba(0x002b36ff).into()), ..Default::default() }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0x268bd2ff).into()), + color: Some(rgba(0x298bd1ff).into()), ..Default::default() }, ), @@ -284,59 +351,62 @@ pub fn solarized() -> UserThemeFamily { }, }, UserTheme { - name: "Solarized Light".into(), - appearance: Appearance::Light, + name: "Solarized Dark".into(), + appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xddd6c1ff).into()), - border_variant: Some(rgba(0xddd6c1ff).into()), - border_focused: Some(rgba(0xd3af86ff).into()), - border_selected: Some(rgba(0xddd6c1ff).into()), - border_transparent: Some(rgba(0xddd6c1ff).into()), - border_disabled: Some(rgba(0xddd6c1ff).into()), - elevated_surface_background: Some(rgba(0xeee8d5ff).into()), - background: Some(rgba(0xfdf6e3ff).into()), - element_background: Some(rgba(0xac9d57ff).into()), - element_hover: Some(rgba(0xdfca8844).into()), - element_selected: Some(rgba(0xdfca88ff).into()), - ghost_element_hover: Some(rgba(0xdfca8844).into()), - ghost_element_selected: Some(rgba(0xdfca88ff).into()), - text: Some(rgba(0x333333ff).into()), - text_muted: Some(rgba(0x586e75ff).into()), - status_bar_background: Some(rgba(0xeee8d5ff).into()), - title_bar_background: Some(rgba(0xeee8d5ff).into()), - toolbar_background: Some(rgba(0xfdf6e3ff).into()), - tab_bar_background: Some(rgba(0xd9d2c2ff).into()), - tab_inactive_background: Some(rgba(0xd3cbb7ff).into()), - tab_active_background: Some(rgba(0xfdf6e3ff).into()), - scrollbar_track_background: Some(rgba(0xfdf6e3ff).into()), - editor_foreground: Some(rgba(0x333333ff).into()), - editor_background: Some(rgba(0xfdf6e3ff).into()), - editor_gutter_background: Some(rgba(0xfdf6e3ff).into()), - editor_line_number: Some(rgba(0x9ca8a6ff).into()), - editor_wrap_guide: Some(rgba(0xddd6c1ff).into()), - editor_active_wrap_guide: Some(rgba(0xddd6c1ff).into()), - terminal_ansi_bright_black: Some(rgba(0x657b83ff).into()), - terminal_ansi_bright_red: Some(rgba(0xcb4b16ff).into()), - terminal_ansi_bright_green: Some(rgba(0x859900ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0x657b83ff).into()), - terminal_ansi_bright_blue: Some(rgba(0x839496ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0x6c71c4ff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x93a1a1ff).into()), - terminal_ansi_bright_white: Some(rgba(0xeee8d5ff).into()), - terminal_ansi_black: Some(rgba(0x657b83ff).into()), - terminal_ansi_red: Some(rgba(0xdc322fff).into()), - terminal_ansi_green: Some(rgba(0x859900ff).into()), - terminal_ansi_yellow: Some(rgba(0xb58900ff).into()), - terminal_ansi_blue: Some(rgba(0x268bd2ff).into()), - terminal_ansi_magenta: Some(rgba(0xd33682ff).into()), - terminal_ansi_cyan: Some(rgba(0x2aa198ff).into()), - terminal_ansi_white: Some(rgba(0xeee8d5ff).into()), + border: Some(rgba(0x2b4f58ff).into()), + border_variant: Some(rgba(0x2b4f58ff).into()), + elevated_surface_background: Some(rgba(0x083743ff).into()), + background: Some(rgba(0x083743ff).into()), + panel_background: Some(rgba(0x04313cff).into()), + element_hover: Some(rgba(0x2b4f5880).into()), + element_selected: Some(rgba(0x566d7480).into()), + text: Some(rgba(0x93a1a1ff).into()), + text_muted: Some(rgba(0x5f757dff).into()), + status_bar_background: Some(rgba(0x083743ff).into()), + title_bar_background: Some(rgba(0x083743ff).into()), + toolbar_background: Some(rgba(0x002b36ff).into()), + tab_bar_background: Some(rgba(0x04313cff).into()), + tab_inactive_background: Some(rgba(0x04313cff).into()), + tab_active_background: Some(rgba(0x002b36ff).into()), + scrollbar_thumb_background: Some(rgba(0xfdf6e34d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xfdf6e34d).into()), + scrollbar_thumb_border: Some(rgba(0x032f3bff).into()), + scrollbar_track_border: Some(rgba(0x032f3bff).into()), + editor_foreground: Some(rgba(0xfdf6e3ff).into()), + editor_background: Some(rgba(0x002b36ff).into()), + editor_gutter_background: Some(rgba(0x002b36ff).into()), + editor_line_number: Some(rgba(0xfdf6e359).into()), + editor_active_line_number: Some(rgba(0xfdf6e3ff).into()), + editor_wrap_guide: Some(rgba(0xfdf6e30d).into()), + editor_active_wrap_guide: Some(rgba(0xfdf6e31a).into()), + terminal_background: Some(rgba(0x002b36ff).into()), + terminal_ansi_bright_black: Some(rgba(0x5c7279ff).into()), + terminal_ansi_bright_red: Some(rgba(0x7d181cff).into()), + terminal_ansi_bright_green: Some(rgba(0x434a11ff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x5d4310ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x214465ff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x6f1f40ff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x204e4aff).into()), + terminal_ansi_bright_white: Some(rgba(0xfdf6e3ff).into()), + terminal_ansi_black: Some(rgba(0x002b36ff).into()), + terminal_ansi_red: Some(rgba(0xdc3330ff).into()), + terminal_ansi_green: Some(rgba(0x859904ff).into()), + terminal_ansi_yellow: Some(rgba(0xb58903ff).into()), + terminal_ansi_blue: Some(rgba(0x288bd1ff).into()), + terminal_ansi_magenta: Some(rgba(0xd33782ff).into()), + terminal_ansi_cyan: Some(rgba(0x2ca198ff).into()), + terminal_ansi_white: Some(rgba(0xfdf6e3ff).into()), ..Default::default() }, status: StatusColorsRefinement { - hidden: Some(rgba(0x586e75ff).into()), - hint: Some(rgba(0x969696ff).into()), + created: Some(rgba(0x859904ff).into()), + deleted: Some(rgba(0xb52727ff).into()), + error: Some(rgba(0xdc3330ff).into()), + modified: Some(rgba(0xb58903ff).into()), + success: Some(rgba(0xfdf6e3ff).into()), + warning: Some(rgba(0xb58903ff).into()), ..Default::default() }, syntax: Some(UserSyntaxTheme { @@ -344,170 +414,271 @@ pub fn solarized() -> UserThemeFamily { ( "attribute".into(), UserHighlightStyle { - color: Some(rgba(0x93a1a1ff).into()), + color: Some(rgba(0x288bd1ff).into()), ..Default::default() }, ), ( "boolean".into(), UserHighlightStyle { - color: Some(rgba(0xb58900ff).into()), + color: Some(rgba(0x859904ff).into()), ..Default::default() }, ), ( "comment".into(), UserHighlightStyle { - color: Some(rgba(0x93a1a1ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x99a5a4ff).into()), ..Default::default() }, ), ( "comment.doc".into(), UserHighlightStyle { - color: Some(rgba(0x93a1a1ff).into()), - font_style: Some(UserFontStyle::Italic), + color: Some(rgba(0x99a5a4ff).into()), ..Default::default() }, ), ( "constant".into(), UserHighlightStyle { - color: Some(rgba(0xb58900ff).into()), + color: Some(rgba(0x859904ff).into()), ..Default::default() }, ), ( "constructor".into(), UserHighlightStyle { - color: Some(rgba(0x268bd2ff).into()), + color: Some(rgba(0x288bd1ff).into()), ..Default::default() }, ), ( "embedded".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), + color: Some(rgba(0xfdf6e3ff).into()), ..Default::default() }, ), ( "emphasis".into(), UserHighlightStyle { - color: Some(rgba(0xd33682ff).into()), + color: Some(rgba(0x288bd1ff).into()), ..Default::default() }, ), ( "emphasis.strong".into(), UserHighlightStyle { - color: Some(rgba(0xd33682ff).into()), + color: Some(rgba(0x288bd1ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xcb4b17ff).into()), ..Default::default() }, ), ( "function".into(), UserHighlightStyle { - color: Some(rgba(0x657b83ff).into()), + color: Some(rgba(0xb58903ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x4f8297ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "keyword".into(), UserHighlightStyle { - color: Some(rgba(0x859900ff).into()), + color: Some(rgba(0x288bd1ff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x288bd1ff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xcb4b17ff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x859904ff).into()), ..Default::default() }, ), ( "number".into(), UserHighlightStyle { - color: Some(rgba(0xd33682ff).into()), + color: Some(rgba(0x859904ff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xcb4b17ff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x40728bff).into()), + font_style: Some(UserFontStyle::Italic), ..Default::default() }, ), ( "preproc".into(), UserHighlightStyle { - color: Some(rgba(0xb58900ff).into()), + color: Some(rgba(0xfdf6e3ff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xfdf6e3ff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x288bd1ff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xefe9d6ff).into()), ..Default::default() }, ), ( "punctuation.bracket".into(), UserHighlightStyle { - color: Some(rgba(0x93a1a1ff).into()), + color: Some(rgba(0xefe9d6ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xefe9d6ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xefe9d6ff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xefe9d6ff).into()), ..Default::default() }, ), ( "string".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4b17ff).into()), ..Default::default() }, ), ( "string.escape".into(), UserHighlightStyle { - color: Some(rgba(0xcb4b16ff).into()), + color: Some(rgba(0x99a5a4ff).into()), ..Default::default() }, ), ( "string.regex".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4b17ff).into()), ..Default::default() }, ), ( "string.special".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4b17ff).into()), ..Default::default() }, ), ( "string.special.symbol".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4b17ff).into()), ..Default::default() }, ), ( "tag".into(), UserHighlightStyle { - color: Some(rgba(0x268bd2ff).into()), + color: Some(rgba(0x288bd1ff).into()), ..Default::default() }, ), ( "text.literal".into(), UserHighlightStyle { - color: Some(rgba(0x2aa198ff).into()), + color: Some(rgba(0xcb4b17ff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xfdf6e3ff).into()), + font_weight: Some(UserFontWeight(700.0)), ..Default::default() }, ), ( "type".into(), UserHighlightStyle { - color: Some(rgba(0xb58900ff).into()), + color: Some(rgba(0x2ca198ff).into()), ..Default::default() }, ), ( "variable".into(), UserHighlightStyle { - color: Some(rgba(0x268bd2ff).into()), + color: Some(rgba(0xfdf6e3ff).into()), ..Default::default() }, ), ( - "variable.special".into(), + "variant".into(), UserHighlightStyle { - color: Some(rgba(0x268bd2ff).into()), + color: Some(rgba(0x288bd1ff).into()), ..Default::default() }, ), diff --git a/crates/theme2/src/themes/summercamp.rs b/crates/theme2/src/themes/summercamp.rs new file mode 100644 index 0000000000..f4b5b6ed63 --- /dev/null +++ b/crates/theme2/src/themes/summercamp.rs @@ -0,0 +1,353 @@ +// This file was generated by the `theme_importer`. +// Be careful when modifying it by hand. + +use gpui::rgba; + +#[allow(unused)] +use crate::{ + Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, + UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, +}; + +pub fn summercamp() -> UserThemeFamily { + UserThemeFamily { + name: "Summercamp".into(), + author: "Zed Industries".into(), + themes: vec![UserTheme { + name: "Summercamp".into(), + appearance: Appearance::Dark, + styles: UserThemeStylesRefinement { + colors: ThemeColorsRefinement { + border: Some(rgba(0x312d21ff).into()), + border_variant: Some(rgba(0x312d21ff).into()), + elevated_surface_background: Some(rgba(0x2a261cff).into()), + background: Some(rgba(0x2a261cff).into()), + panel_background: Some(rgba(0x231f16ff).into()), + element_hover: Some(rgba(0x312d2180).into()), + element_selected: Some(rgba(0x39342780).into()), + text: Some(rgba(0x736e55ff).into()), + text_muted: Some(rgba(0x3d382aff).into()), + status_bar_background: Some(rgba(0x2a261cff).into()), + title_bar_background: Some(rgba(0x2a261cff).into()), + toolbar_background: Some(rgba(0x1c1810ff).into()), + tab_bar_background: Some(rgba(0x231f16ff).into()), + tab_inactive_background: Some(rgba(0x231f16ff).into()), + tab_active_background: Some(rgba(0x1c1810ff).into()), + scrollbar_thumb_background: Some(rgba(0xf8f5de4d).into()), + scrollbar_thumb_hover_background: Some(rgba(0xf8f5de4d).into()), + scrollbar_thumb_border: Some(rgba(0x221e15ff).into()), + scrollbar_track_border: Some(rgba(0x221e15ff).into()), + editor_foreground: Some(rgba(0xf8f5deff).into()), + editor_background: Some(rgba(0x1c1810ff).into()), + editor_gutter_background: Some(rgba(0x1c1810ff).into()), + editor_line_number: Some(rgba(0xf8f5de59).into()), + editor_active_line_number: Some(rgba(0xf8f5deff).into()), + editor_wrap_guide: Some(rgba(0xf8f5de0d).into()), + editor_active_wrap_guide: Some(rgba(0xf8f5de1a).into()), + terminal_background: Some(rgba(0x1c1810ff).into()), + terminal_ansi_bright_black: Some(rgba(0x3b3627ff).into()), + terminal_ansi_bright_red: Some(rgba(0x7f2724ff).into()), + terminal_ansi_bright_green: Some(rgba(0x28842cff).into()), + terminal_ansi_bright_yellow: Some(rgba(0x8c9a10ff).into()), + terminal_ansi_bright_blue: Some(rgba(0x234b7fff).into()), + terminal_ansi_bright_magenta: Some(rgba(0x88487eff).into()), + terminal_ansi_bright_cyan: Some(rgba(0x298462ff).into()), + terminal_ansi_bright_white: Some(rgba(0xf8f5deff).into()), + terminal_ansi_black: Some(rgba(0x1c1810ff).into()), + terminal_ansi_red: Some(rgba(0xe35142ff).into()), + terminal_ansi_green: Some(rgba(0x5dea5aff).into()), + terminal_ansi_yellow: Some(rgba(0xf1fe29ff).into()), + terminal_ansi_blue: Some(rgba(0x499befff).into()), + terminal_ansi_magenta: Some(rgba(0xf59be6ff).into()), + terminal_ansi_cyan: Some(rgba(0x5beabcff).into()), + terminal_ansi_white: Some(rgba(0xf8f5deff).into()), + ..Default::default() + }, + status: StatusColorsRefinement { + created: Some(rgba(0x5dea5aff).into()), + deleted: Some(rgba(0xb93f36ff).into()), + error: Some(rgba(0xe35142ff).into()), + modified: Some(rgba(0xf1fe29ff).into()), + success: Some(rgba(0xf8f5deff).into()), + warning: Some(rgba(0xf1fe29ff).into()), + ..Default::default() + }, + syntax: Some(UserSyntaxTheme { + highlights: vec![ + ( + "attribute".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + ..Default::default() + }, + ), + ( + "boolean".into(), + UserHighlightStyle { + color: Some(rgba(0x5dea5aff).into()), + ..Default::default() + }, + ), + ( + "comment".into(), + UserHighlightStyle { + color: Some(rgba(0x777259ff).into()), + ..Default::default() + }, + ), + ( + "comment.doc".into(), + UserHighlightStyle { + color: Some(rgba(0x777259ff).into()), + ..Default::default() + }, + ), + ( + "constant".into(), + UserHighlightStyle { + color: Some(rgba(0x5dea5aff).into()), + ..Default::default() + }, + ), + ( + "constructor".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + ..Default::default() + }, + ), + ( + "embedded".into(), + UserHighlightStyle { + color: Some(rgba(0xf8f5deff).into()), + ..Default::default() + }, + ), + ( + "emphasis".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + ..Default::default() + }, + ), + ( + "emphasis.strong".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "enum".into(), + UserHighlightStyle { + color: Some(rgba(0xfaa11dff).into()), + ..Default::default() + }, + ), + ( + "function".into(), + UserHighlightStyle { + color: Some(rgba(0xf1fe29ff).into()), + ..Default::default() + }, + ), + ( + "hint".into(), + UserHighlightStyle { + color: Some(rgba(0x246e61ff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "keyword".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + ..Default::default() + }, + ), + ( + "label".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + ..Default::default() + }, + ), + ( + "link_text".into(), + UserHighlightStyle { + color: Some(rgba(0xfaa11dff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "link_uri".into(), + UserHighlightStyle { + color: Some(rgba(0x5dea5aff).into()), + ..Default::default() + }, + ), + ( + "number".into(), + UserHighlightStyle { + color: Some(rgba(0x5dea5aff).into()), + ..Default::default() + }, + ), + ( + "operator".into(), + UserHighlightStyle { + color: Some(rgba(0xfaa11dff).into()), + ..Default::default() + }, + ), + ( + "predictive".into(), + UserHighlightStyle { + color: Some(rgba(0x79434bff).into()), + font_style: Some(UserFontStyle::Italic), + ..Default::default() + }, + ), + ( + "preproc".into(), + UserHighlightStyle { + color: Some(rgba(0xf8f5deff).into()), + ..Default::default() + }, + ), + ( + "primary".into(), + UserHighlightStyle { + color: Some(rgba(0xf8f5deff).into()), + ..Default::default() + }, + ), + ( + "property".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + ..Default::default() + }, + ), + ( + "punctuation".into(), + UserHighlightStyle { + color: Some(rgba(0xbfbb9bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.bracket".into(), + UserHighlightStyle { + color: Some(rgba(0xbfbb9bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.delimiter".into(), + UserHighlightStyle { + color: Some(rgba(0xbfbb9bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.list_marker".into(), + UserHighlightStyle { + color: Some(rgba(0xbfbb9bff).into()), + ..Default::default() + }, + ), + ( + "punctuation.special".into(), + UserHighlightStyle { + color: Some(rgba(0xbfbb9bff).into()), + ..Default::default() + }, + ), + ( + "string".into(), + UserHighlightStyle { + color: Some(rgba(0xfaa11dff).into()), + ..Default::default() + }, + ), + ( + "string.escape".into(), + UserHighlightStyle { + color: Some(rgba(0x777259ff).into()), + ..Default::default() + }, + ), + ( + "string.regex".into(), + UserHighlightStyle { + color: Some(rgba(0xfaa11dff).into()), + ..Default::default() + }, + ), + ( + "string.special".into(), + UserHighlightStyle { + color: Some(rgba(0xfaa11dff).into()), + ..Default::default() + }, + ), + ( + "string.special.symbol".into(), + UserHighlightStyle { + color: Some(rgba(0xfaa11dff).into()), + ..Default::default() + }, + ), + ( + "tag".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + ..Default::default() + }, + ), + ( + "text.literal".into(), + UserHighlightStyle { + color: Some(rgba(0xfaa11dff).into()), + ..Default::default() + }, + ), + ( + "title".into(), + UserHighlightStyle { + color: Some(rgba(0xf8f5deff).into()), + font_weight: Some(UserFontWeight(700.0)), + ..Default::default() + }, + ), + ( + "type".into(), + UserHighlightStyle { + color: Some(rgba(0x5beabcff).into()), + ..Default::default() + }, + ), + ( + "variable".into(), + UserHighlightStyle { + color: Some(rgba(0xf8f5deff).into()), + ..Default::default() + }, + ), + ( + "variant".into(), + UserHighlightStyle { + color: Some(rgba(0x499befff).into()), + ..Default::default() + }, + ), + ], + }), + }, + }], + } +} diff --git a/crates/theme2/src/themes/synthwave_84.rs b/crates/theme2/src/themes/synthwave_84.rs deleted file mode 100644 index d7a0ef41a0..0000000000 --- a/crates/theme2/src/themes/synthwave_84.rs +++ /dev/null @@ -1,248 +0,0 @@ -// This file was generated by the `theme_importer`. -// Be careful when modifying it by hand. - -use gpui::rgba; - -#[allow(unused)] -use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, -}; - -pub fn synthwave_84() -> UserThemeFamily { - UserThemeFamily { - name: "Synthwave 84".into(), - author: "Robb Owen (robb0wen)".into(), - themes: vec![UserTheme { - name: "Synthwave 84".into(), - appearance: Appearance::Dark, - styles: UserThemeStylesRefinement { - colors: ThemeColorsRefinement { - border_focused: Some(rgba(0x1f212bff).into()), - elevated_surface_background: Some(rgba(0x232530ff).into()), - background: Some(rgba(0x262335ff).into()), - element_background: Some(rgba(0x614d85ff).into()), - element_hover: Some(rgba(0x37294d99).into()), - element_selected: Some(rgba(0xffffff20).into()), - drop_target_background: Some(rgba(0x34294f66).into()), - ghost_element_hover: Some(rgba(0x37294d99).into()), - ghost_element_selected: Some(rgba(0xffffff20).into()), - text: Some(rgba(0xffffffff).into()), - status_bar_background: Some(rgba(0x241b2fff).into()), - title_bar_background: Some(rgba(0x241b2fff).into()), - toolbar_background: Some(rgba(0x262335ff).into()), - tab_bar_background: Some(rgba(0x241b2fff).into()), - tab_inactive_background: Some(rgba(0x262335ff).into()), - tab_active_background: Some(rgba(0x262335ff).into()), - scrollbar_thumb_background: Some(rgba(0x9d8bca30).into()), - scrollbar_thumb_hover_background: Some(rgba(0x9d8bca50).into()), - scrollbar_thumb_border: Some(rgba(0x9d8bca30).into()), - scrollbar_track_background: Some(rgba(0x262335ff).into()), - scrollbar_track_border: Some(rgba(0x34294fb3).into()), - editor_background: Some(rgba(0x262335ff).into()), - editor_gutter_background: Some(rgba(0x262335ff).into()), - editor_line_number: Some(rgba(0xffffff73).into()), - terminal_ansi_bright_red: Some(rgba(0xfe4450ff).into()), - terminal_ansi_bright_green: Some(rgba(0x72f1b8ff).into()), - terminal_ansi_bright_yellow: Some(rgba(0xfede5dff).into()), - terminal_ansi_bright_blue: Some(rgba(0x03edf9ff).into()), - terminal_ansi_bright_magenta: Some(rgba(0xff7edbff).into()), - terminal_ansi_bright_cyan: Some(rgba(0x03edf9ff).into()), - terminal_ansi_red: Some(rgba(0xfe4450ff).into()), - terminal_ansi_green: Some(rgba(0x72f1b8ff).into()), - terminal_ansi_yellow: Some(rgba(0xf3e70fff).into()), - terminal_ansi_blue: Some(rgba(0x03edf9ff).into()), - terminal_ansi_magenta: Some(rgba(0xff7edbff).into()), - terminal_ansi_cyan: Some(rgba(0x03edf9ff).into()), - link_text_hover: Some(rgba(0xff7edbff).into()), - ..Default::default() - }, - status: StatusColorsRefinement { - created: Some(rgba(0x206d4bd6).into()), - deleted: Some(rgba(0xfa2e46a4).into()), - error: Some(rgba(0xfe4450ff).into()), - hint: Some(rgba(0x969696ff).into()), - ignored: Some(rgba(0xffffff59).into()), - modified: Some(rgba(0xb893ce8f).into()), - warning: Some(rgba(0x72f1b8bb).into()), - ..Default::default() - }, - syntax: Some(UserSyntaxTheme { - highlights: vec![ - ( - "attribute".into(), - UserHighlightStyle { - color: Some(rgba(0xfede5dff).into()), - ..Default::default() - }, - ), - ( - "boolean".into(), - UserHighlightStyle { - color: Some(rgba(0xf97e72ff).into()), - ..Default::default() - }, - ), - ( - "comment".into(), - UserHighlightStyle { - color: Some(rgba(0x848bbdff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "comment.doc".into(), - UserHighlightStyle { - color: Some(rgba(0x848bbdff).into()), - font_style: Some(UserFontStyle::Italic), - ..Default::default() - }, - ), - ( - "constant".into(), - UserHighlightStyle { - color: Some(rgba(0xf97e72ff).into()), - ..Default::default() - }, - ), - ( - "constructor".into(), - UserHighlightStyle { - color: Some(rgba(0x72f1b8ff).into()), - ..Default::default() - }, - ), - ( - "function".into(), - UserHighlightStyle { - color: Some(rgba(0x36f9f6ff).into()), - ..Default::default() - }, - ), - ( - "keyword".into(), - UserHighlightStyle { - color: Some(rgba(0xfede5dff).into()), - ..Default::default() - }, - ), - ( - "label".into(), - UserHighlightStyle { - color: Some(rgba(0xfe4450ff).into()), - ..Default::default() - }, - ), - ( - "link_text".into(), - UserHighlightStyle { - color: Some(rgba(0xdd5500ff).into()), - ..Default::default() - }, - ), - ( - "link_uri".into(), - UserHighlightStyle { - color: Some(rgba(0xdd5500ff).into()), - ..Default::default() - }, - ), - ( - "number".into(), - UserHighlightStyle { - color: Some(rgba(0xf97e72ff).into()), - ..Default::default() - }, - ), - ( - "operator".into(), - UserHighlightStyle { - color: Some(rgba(0xfede5dff).into()), - ..Default::default() - }, - ), - ( - "property".into(), - UserHighlightStyle { - color: Some(rgba(0xff7edbff).into()), - ..Default::default() - }, - ), - ( - "punctuation".into(), - UserHighlightStyle { - color: Some(rgba(0x36f9f6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.bracket".into(), - UserHighlightStyle { - color: Some(rgba(0x36f9f6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.delimiter".into(), - UserHighlightStyle { - color: Some(rgba(0x36f9f6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.list_marker".into(), - UserHighlightStyle { - color: Some(rgba(0x36f9f6ff).into()), - ..Default::default() - }, - ), - ( - "punctuation.special".into(), - UserHighlightStyle { - color: Some(rgba(0x36f9f6ff).into()), - ..Default::default() - }, - ), - ( - "tag".into(), - UserHighlightStyle { - color: Some(rgba(0x72f1b8ff).into()), - ..Default::default() - }, - ), - ( - "title".into(), - UserHighlightStyle { - color: Some(rgba(0xfe4450ff).into()), - ..Default::default() - }, - ), - ( - "type".into(), - UserHighlightStyle { - color: Some(rgba(0xfe4450ff).into()), - ..Default::default() - }, - ), - ( - "variable".into(), - UserHighlightStyle { - color: Some(rgba(0xff7edbff).into()), - ..Default::default() - }, - ), - ( - "variable.special".into(), - UserHighlightStyle { - color: Some(rgba(0xfe4450ff).into()), - font_weight: Some(UserFontWeight(700.0)), - ..Default::default() - }, - ), - ], - }), - }, - }], - } -} diff --git a/crates/theme_importer/src/main.rs b/crates/theme_importer/src/main.rs index e6cf8952d1..4072a59df8 100644 --- a/crates/theme_importer/src/main.rs +++ b/crates/theme_importer/src/main.rs @@ -73,10 +73,6 @@ pub struct ThemeMetadata { #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Args { - /// Whether to import Zed1 themes. - #[arg(long)] - zed1: bool, - /// Whether to warn when values are missing from the theme. #[arg(long)] warn_on_missing: bool, @@ -106,176 +102,87 @@ fn main() -> Result<()> { TermLogger::init(LevelFilter::Trace, log_config, TerminalMode::Mixed) .expect("could not initialize logger"); - log::info!("Loading themes source..."); - let vscode_themes_path = PathBuf::from_str(SOURCE_PATH)?; - if !vscode_themes_path.exists() { - return Err(anyhow!(format!( - "Couldn't find {}, make sure it exists", - SOURCE_PATH - ))); - } - let mut theme_families = Vec::new(); - for theme_family_dir in fs::read_dir(&vscode_themes_path)? { - let theme_family_dir = theme_family_dir?; + /// Whether VS Code themes should be imported. + /// + /// For the initial release of Zed2, we will just be using the Zed1 themes ported to Zed2. + const IMPORT_VS_CODE_THEMES: bool = false; - if !theme_family_dir.file_type()?.is_dir() { - continue; + if IMPORT_VS_CODE_THEMES { + log::info!("Loading themes source..."); + let vscode_themes_path = PathBuf::from_str(SOURCE_PATH)?; + if !vscode_themes_path.exists() { + return Err(anyhow!(format!( + "Couldn't find {}, make sure it exists", + SOURCE_PATH + ))); } - let theme_family_slug = theme_family_dir - .path() - .file_stem() - .ok_or(anyhow!("no file stem")) - .map(|stem| stem.to_string_lossy().to_string())?; + for theme_family_dir in fs::read_dir(&vscode_themes_path)? { + let theme_family_dir = theme_family_dir?; - let family_metadata_file = File::open(theme_family_dir.path().join("family.json")) - .context(format!( - "no `family.json` found for '{}'", - theme_family_slug - ))?; - - let license_file_path = theme_family_dir.path().join("LICENSE"); - - if !license_file_path.exists() { - log::info!("Skipping theme family '{}' because it does not have a LICENSE file. This theme will only be imported once a LICENSE file is provided.", theme_family_slug); - continue; - } - - let family_metadata: FamilyMetadata = serde_json::from_reader(family_metadata_file) - .context(format!( - "failed to parse `family.json` for '{theme_family_slug}'" - ))?; - - let mut themes = Vec::new(); - - for theme_metadata in family_metadata.themes { - log::info!("Converting '{}' theme", &theme_metadata.name); - - let theme_file_path = theme_family_dir.path().join(&theme_metadata.file_name); - - let theme_file = match File::open(&theme_file_path) { - Ok(file) => file, - Err(_) => { - log::info!("Failed to open file at path: {:?}", theme_file_path); - continue; - } - }; - - let theme_without_comments = StripComments::new(theme_file); - let vscode_theme: VsCodeTheme = serde_json::from_reader(theme_without_comments) - .context(format!("failed to parse theme {theme_file_path:?}"))?; - - let converter = VsCodeThemeConverter::new( - vscode_theme, - theme_metadata, - family_metadata.syntax.clone(), - ); - - let theme = converter.convert()?; - - themes.push(theme); - } - - let theme_family = UserThemeFamily { - name: family_metadata.name.into(), - author: family_metadata.author.into(), - themes, - }; - - theme_families.push(theme_family); - } - - if args.zed1 { - let zed1_themes_path = PathBuf::from_str("assets/themes")?; - - let zed1_theme_familes = [ - "Andromeda", - "Atelier", - "Ayu", - "Gruvbox", - "One", - "Rosé Pine", - "Sandcastle", - "Solarized", - "Summercamp", - ]; - - let mut zed1_themes_by_family: HashMap> = HashMap::from_iter( - zed1_theme_familes - .into_iter() - .map(|family| (family.to_string(), Vec::new())), - ); - - let platform = gpui1::platform::current::platform(); - let zed1_font_cache = Arc::new(gpui1::FontCache::new(platform.fonts())); - - let mut embedded_fonts = Vec::new(); - for font_path in Assets.list("fonts")? { - if font_path.ends_with(".ttf") { - let font_bytes = Assets.load(&font_path)?.to_vec(); - embedded_fonts.push(Arc::from(font_bytes)); - } - } - - platform.fonts().add_fonts(&embedded_fonts)?; - - for entry in fs::read_dir(&zed1_themes_path)? { - let entry = entry?; - - if entry.file_type()?.is_dir() { + if !theme_family_dir.file_type()?.is_dir() { continue; } - match entry.path().extension() { - None => continue, - Some(extension) => { - if extension != "json" { + let theme_family_slug = theme_family_dir + .path() + .file_stem() + .ok_or(anyhow!("no file stem")) + .map(|stem| stem.to_string_lossy().to_string())?; + + let family_metadata_file = File::open(theme_family_dir.path().join("family.json")) + .context(format!( + "no `family.json` found for '{}'", + theme_family_slug + ))?; + + let license_file_path = theme_family_dir.path().join("LICENSE"); + + if !license_file_path.exists() { + log::info!("Skipping theme family '{}' because it does not have a LICENSE file. This theme will only be imported once a LICENSE file is provided.", theme_family_slug); + continue; + } + + let family_metadata: FamilyMetadata = serde_json::from_reader(family_metadata_file) + .context(format!( + "failed to parse `family.json` for '{theme_family_slug}'" + ))?; + + let mut themes = Vec::new(); + + for theme_metadata in family_metadata.themes { + log::info!("Converting '{}' theme", &theme_metadata.name); + + let theme_file_path = theme_family_dir.path().join(&theme_metadata.file_name); + + let theme_file = match File::open(&theme_file_path) { + Ok(file) => file, + Err(_) => { + log::info!("Failed to open file at path: {:?}", theme_file_path); continue; } - } + }; + + let theme_without_comments = StripComments::new(theme_file); + let vscode_theme: VsCodeTheme = serde_json::from_reader(theme_without_comments) + .context(format!("failed to parse theme {theme_file_path:?}"))?; + + let converter = VsCodeThemeConverter::new( + vscode_theme, + theme_metadata, + family_metadata.syntax.clone(), + ); + + let theme = converter.convert()?; + + themes.push(theme); } - let theme_file_path = entry.path(); - - let theme_file = match File::open(&theme_file_path) { - Ok(file) => file, - Err(_) => { - log::info!("Failed to open file at path: {:?}", theme_file_path); - continue; - } - }; - - let theme_without_comments = StripComments::new(theme_file); - - let zed1_theme: Zed1Theme = - gpui1::fonts::with_font_cache(zed1_font_cache.clone(), || { - serde_json::from_reader(theme_without_comments) - .context(format!("failed to parse theme {theme_file_path:?}")) - })?; - - let theme_name = zed1_theme.meta.name.clone(); - - let converter = Zed1ThemeConverter::new(zed1_theme); - - let theme = converter.convert()?; - - let Some((_, themes_for_family)) = zed1_themes_by_family - .iter_mut() - .find(|(family, _)| theme_name.starts_with(*family)) - else { - log::warn!("No theme family found for '{}'.", theme_name); - continue; - }; - - themes_for_family.push(theme); - } - - for (family, themes) in zed1_themes_by_family { let theme_family = UserThemeFamily { - name: format!("{family} (Zed1)"), - author: "Zed Industries".to_string(), + name: family_metadata.name.into(), + author: family_metadata.author.into(), themes, }; @@ -283,6 +190,99 @@ fn main() -> Result<()> { } } + let zed1_themes_path = PathBuf::from_str("assets/themes")?; + + let zed1_theme_familes = [ + "Andromeda", + "Atelier", + "Ayu", + "Gruvbox", + "One", + "Rosé Pine", + "Sandcastle", + "Solarized", + "Summercamp", + ]; + + let mut zed1_themes_by_family: HashMap> = HashMap::from_iter( + zed1_theme_familes + .into_iter() + .map(|family| (family.to_string(), Vec::new())), + ); + + let platform = gpui1::platform::current::platform(); + let zed1_font_cache = Arc::new(gpui1::FontCache::new(platform.fonts())); + + let mut embedded_fonts = Vec::new(); + for font_path in Assets.list("fonts")? { + if font_path.ends_with(".ttf") { + let font_bytes = Assets.load(&font_path)?.to_vec(); + embedded_fonts.push(Arc::from(font_bytes)); + } + } + + platform.fonts().add_fonts(&embedded_fonts)?; + + for entry in fs::read_dir(&zed1_themes_path)? { + let entry = entry?; + + if entry.file_type()?.is_dir() { + continue; + } + + match entry.path().extension() { + None => continue, + Some(extension) => { + if extension != "json" { + continue; + } + } + } + + let theme_file_path = entry.path(); + + let theme_file = match File::open(&theme_file_path) { + Ok(file) => file, + Err(_) => { + log::info!("Failed to open file at path: {:?}", theme_file_path); + continue; + } + }; + + let theme_without_comments = StripComments::new(theme_file); + + let zed1_theme: Zed1Theme = gpui1::fonts::with_font_cache(zed1_font_cache.clone(), || { + serde_json::from_reader(theme_without_comments) + .context(format!("failed to parse theme {theme_file_path:?}")) + })?; + + let theme_name = zed1_theme.meta.name.clone(); + + let converter = Zed1ThemeConverter::new(zed1_theme); + + let theme = converter.convert()?; + + let Some((_, themes_for_family)) = zed1_themes_by_family + .iter_mut() + .find(|(family, _)| theme_name.starts_with(*family)) + else { + log::warn!("No theme family found for '{}'.", theme_name); + continue; + }; + + themes_for_family.push(theme); + } + + for (family, themes) in zed1_themes_by_family { + let theme_family = UserThemeFamily { + name: family, + author: "Zed Industries".to_string(), + themes, + }; + + theme_families.push(theme_family); + } + let themes_output_path = PathBuf::from_str(OUT_PATH)?; if !themes_output_path.exists() { diff --git a/crates/theme_importer/src/theme_printer.rs b/crates/theme_importer/src/theme_printer.rs index eb304ff90d..2116b5b670 100644 --- a/crates/theme_importer/src/theme_printer.rs +++ b/crates/theme_importer/src/theme_printer.rs @@ -160,6 +160,7 @@ impl<'a> Debug for ThemeColorsRefinementPrinter<'a> { ), ("surface_background", self.0.surface_background), ("background", self.0.background), + ("panel_background", self.0.panel_background), ("element_background", self.0.element_background), ("element_hover", self.0.element_hover), ("element_active", self.0.element_active), diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs index 1a5f7af8b7..0b932c83fb 100644 --- a/crates/theme_importer/src/zed1/converter.rs +++ b/crates/theme_importer/src/zed1/converter.rs @@ -53,7 +53,7 @@ impl Zed1ThemeConverter { let syntax_theme = self.convert_syntax_theme()?; Ok(UserTheme { - name: format!("{} (Zed1)", self.theme.meta.name), + name: self.theme.meta.name, appearance, styles: UserThemeStylesRefinement { colors: theme_colors_refinement, @@ -68,12 +68,16 @@ impl Zed1ThemeConverter { Some(zed1_color_to_hsla(color)) } - let diff_style = self.theme.editor.diff.clone(); + let diff_style = &self.theme.editor.diff; + let diagnostic_summary = &self.theme.workspace.status_bar.diagnostic_summary; Ok(StatusColorsRefinement { created: convert(diff_style.inserted), modified: convert(diff_style.modified), deleted: convert(diff_style.deleted), + success: convert(diagnostic_summary.icon_color_ok), + warning: convert(diagnostic_summary.icon_color_warning), + error: convert(diagnostic_summary.icon_color_error), ..Default::default() }) } @@ -83,11 +87,11 @@ impl Zed1ThemeConverter { Some(zed1_color_to_hsla(color)) } - let tab_bar = self.theme.workspace.tab_bar.clone(); - let active_tab = self.theme.workspace.tab_bar.tab_style(true, true).clone(); - let inactive_tab = self.theme.workspace.tab_bar.tab_style(true, false).clone(); - let toolbar = self.theme.workspace.toolbar.clone(); - let scrollbar = self.theme.editor.scrollbar.clone(); + let tab_bar = &self.theme.workspace.tab_bar; + let active_tab = &self.theme.workspace.tab_bar.tab_style(true, true); + let inactive_tab = &self.theme.workspace.tab_bar.tab_style(true, false); + let toolbar = &self.theme.workspace.toolbar; + let scrollbar = &self.theme.editor.scrollbar; let zed1_titlebar_border = convert(self.theme.titlebar.container.border.color); @@ -95,6 +99,12 @@ impl Zed1ThemeConverter { border: zed1_titlebar_border, border_variant: zed1_titlebar_border, background: convert(self.theme.workspace.background), + elevated_surface_background: self + .theme + .picker + .container + .background_color + .map(zed1_color_to_hsla), title_bar_background: self .theme .titlebar @@ -107,8 +117,38 @@ impl Zed1ThemeConverter { .status_bar .container .background_color + .map(zed1_color_to_hsla) + .or_else(|| { + self.theme + .titlebar + .container + .background_color + .map(zed1_color_to_hsla) + }), + panel_background: self + .theme + .project_panel + .container + .background_color + .map(zed1_color_to_hsla), + text: convert(self.theme.project_panel.entry.default_style().text.color), + text_muted: convert(active_tab.description.text.color), + element_hover: self + .theme + .picker + .item + .hovered + .as_ref() + .and_then(|hovered| hovered.container.background_color) + .map(zed1_color_to_hsla), + element_selected: self + .theme + .picker + .item + .active_state() + .container + .background_color .map(zed1_color_to_hsla), - text: convert(self.theme.editor.text_color), tab_bar_background: tab_bar.container.background_color.map(zed1_color_to_hsla), tab_active_background: active_tab .container diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 9c7ffc6e89..fbc8a1f878 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -537,6 +537,7 @@ impl Render for Dock { div() .flex() + .bg(cx.theme().colors().panel_background) .border_color(cx.theme().colors().border) .overflow_hidden() .map(|this| match self.position().axis() { From 9600337d8154ad733ffc052deb9537c1d1e4a6ff Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 23 Dec 2023 01:27:41 +0200 Subject: [PATCH 302/644] Properly color file labels in project panel --- crates/project_panel2/src/project_panel.rs | 13 +++++-------- crates/ui2/src/styles/color.rs | 2 ++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 1259fc1d61..2966c55f79 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -1364,16 +1364,15 @@ impl ProjectPanel { .map_or(false, |selection| selection.entry_id == entry_id); let width = self.width.unwrap_or(px(0.)); - let theme = cx.theme(); let filename_text_color = details .git_status .as_ref() .map(|status| match status { - GitFileStatus::Added => theme.status().created, - GitFileStatus::Modified => theme.status().modified, - GitFileStatus::Conflict => theme.status().conflict, + GitFileStatus::Added => Color::Created, + GitFileStatus::Modified => Color::Modified, + GitFileStatus::Conflict => Color::Conflict, }) - .unwrap_or(theme.status().info); + .unwrap_or(Color::Default); let file_name = details.filename.clone(); let icon = details.icon.clone(); @@ -1407,9 +1406,7 @@ impl ProjectPanel { if let (Some(editor), true) = (Some(&self.filename_editor), show_editor) { div().h_full().w_full().child(editor.clone()) } else { - div() - .text_color(filename_text_color) - .child(Label::new(file_name)) + div().child(Label::new(file_name).color(filename_text_color)) } .ml_1(), ) diff --git a/crates/ui2/src/styles/color.rs b/crates/ui2/src/styles/color.rs index 0769558acb..977a26dedc 100644 --- a/crates/ui2/src/styles/color.rs +++ b/crates/ui2/src/styles/color.rs @@ -13,6 +13,7 @@ pub enum Color { Hidden, Info, Modified, + Conflict, Muted, Placeholder, Player(u32), @@ -28,6 +29,7 @@ impl Color { Color::Muted => cx.theme().colors().text_muted, Color::Created => cx.theme().status().created, Color::Modified => cx.theme().status().modified, + Color::Conflict => cx.theme().status().conflict, Color::Deleted => cx.theme().status().deleted, Color::Disabled => cx.theme().colors().text_disabled, Color::Hidden => cx.theme().status().hidden, From 1ebfafc03d97b2b18da9e2c2105a289ed50b93f9 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 18:45:58 -0500 Subject: [PATCH 303/644] Map additional text colors from Zed1 themes (#3796) This PR maps additional text colors from the Zed1 themes to the Zed2 themes. Release Notes: - N/A --- crates/editor2/src/element.rs | 2 +- crates/theme2/src/themes/andromeda.rs | 3 + crates/theme2/src/themes/atelier.rs | 60 +++++++++++ crates/theme2/src/themes/ayu.rs | 9 ++ crates/theme2/src/themes/gruvbox.rs | 18 ++++ crates/theme2/src/themes/one.rs | 6 ++ crates/theme2/src/themes/rose_pine.rs | 9 ++ crates/theme2/src/themes/sandcastle.rs | 3 + crates/theme2/src/themes/solarized.rs | 6 ++ crates/theme2/src/themes/summercamp.rs | 3 + crates/theme_importer/src/zed1/converter.rs | 107 +++++++++----------- 11 files changed, 166 insertions(+), 60 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 9e1d8e641f..c897c0c2db 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -1724,7 +1724,7 @@ impl EditorElement { // Show the placeholder when the editor is empty if snapshot.is_empty() { let font_size = self.style.text.font_size.to_pixels(cx.rem_size()); - let placeholder_color = cx.theme().styles.colors.text_placeholder; + let placeholder_color = cx.theme().colors().text_placeholder; let placeholder_text = snapshot.placeholder_text(); let placeholder_lines = placeholder_text diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index 5affa63fb0..699abec491 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -27,6 +27,9 @@ pub fn andromeda() -> UserThemeFamily { element_selected: Some(rgba(0x383b4580).into()), text: Some(rgba(0xaca8aeff).into()), text_muted: Some(rgba(0x474a53ff).into()), + text_placeholder: Some(rgba(0x474a53ff).into()), + text_disabled: Some(rgba(0xf7f7f8ff).into()), + text_accent: Some(rgba(0x11a793ff).into()), status_bar_background: Some(rgba(0x262a33ff).into()), title_bar_background: Some(rgba(0x262a33ff).into()), toolbar_background: Some(rgba(0x1e2025ff).into()), diff --git a/crates/theme2/src/themes/atelier.rs b/crates/theme2/src/themes/atelier.rs index f1ec02cb75..1722521b03 100644 --- a/crates/theme2/src/themes/atelier.rs +++ b/crates/theme2/src/themes/atelier.rs @@ -28,6 +28,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x8b8a7880).into()), text: Some(rgba(0x61604fff).into()), text_muted: Some(rgba(0x878573ff).into()), + text_placeholder: Some(rgba(0x878573ff).into()), + text_disabled: Some(rgba(0x22221bff).into()), + text_accent: Some(rgba(0x38a166ff).into()), status_bar_background: Some(rgba(0xc5c4b9ff).into()), title_bar_background: Some(rgba(0xc5c4b9ff).into()), toolbar_background: Some(rgba(0xf4f3ecff).into()), @@ -385,6 +388,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x71696680).into()), text: Some(rgba(0xa79f9dff).into()), text_muted: Some(rgba(0x766e6bff).into()), + text_placeholder: Some(rgba(0x766e6bff).into()), + text_disabled: Some(rgba(0xf1efeeff).into()), + text_accent: Some(rgba(0x417ee6ff).into()), status_bar_background: Some(rgba(0x443c39ff).into()), title_bar_background: Some(rgba(0x443c39ff).into()), toolbar_background: Some(rgba(0x1b1918ff).into()), @@ -742,6 +748,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x7e8b8280).into()), text: Some(rgba(0x546259ff).into()), text_muted: Some(rgba(0x79877dff).into()), + text_placeholder: Some(rgba(0x79877dff).into()), + text_disabled: Some(rgba(0x171c19ff).into()), + text_accent: Some(rgba(0x488c90ff).into()), status_bar_background: Some(rgba(0xbcc5bfff).into()), title_bar_background: Some(rgba(0xbcc5bfff).into()), toolbar_background: Some(rgba(0xecf4eeff).into()), @@ -1099,6 +1108,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x605a6880).into()), text: Some(rgba(0x898591ff).into()), text_muted: Some(rgba(0x655f6dff).into()), + text_placeholder: Some(rgba(0x655f6dff).into()), + text_disabled: Some(rgba(0xefecf4ff).into()), + text_accent: Some(rgba(0x576ddaff).into()), status_bar_background: Some(rgba(0x3a353fff).into()), title_bar_background: Some(rgba(0x3a353fff).into()), toolbar_background: Some(rgba(0x19171cff).into()), @@ -1456,6 +1468,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x67665580).into()), text: Some(rgba(0x91907fff).into()), text_muted: Some(rgba(0x6c6b5aff).into()), + text_placeholder: Some(rgba(0x6c6b5aff).into()), + text_disabled: Some(rgba(0xf4f3ecff).into()), + text_accent: Some(rgba(0x37a166ff).into()), status_bar_background: Some(rgba(0x424136ff).into()), title_bar_background: Some(rgba(0x424136ff).into()), toolbar_background: Some(rgba(0x22221bff).into()), @@ -1813,6 +1828,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x666e8f80).into()), text: Some(rgba(0x959bb2ff).into()), text_muted: Some(rgba(0x6b7394ff).into()), + text_placeholder: Some(rgba(0x6b7394ff).into()), + text_disabled: Some(rgba(0xf5f7ffff).into()), + text_accent: Some(rgba(0x3e8fd0ff).into()), status_bar_background: Some(rgba(0x3e4769ff).into()), title_bar_background: Some(rgba(0x3e4769ff).into()), toolbar_background: Some(rgba(0x202746ff).into()), @@ -2170,6 +2188,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x8e94aa80).into()), text: Some(rgba(0x606889ff).into()), text_muted: Some(rgba(0x898fa5ff).into()), + text_placeholder: Some(rgba(0x898fa5ff).into()), + text_disabled: Some(rgba(0x202746ff).into()), + text_accent: Some(rgba(0x3f8fd0ff).into()), status_bar_background: Some(rgba(0xc2c6d9ff).into()), title_bar_background: Some(rgba(0xc2c6d9ff).into()), toolbar_background: Some(rgba(0xf5f7ffff).into()), @@ -2527,6 +2548,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x77746480).into()), text: Some(rgba(0xa4a08bff).into()), text_muted: Some(rgba(0x7c7968ff).into()), + text_placeholder: Some(rgba(0x7c7968ff).into()), + text_disabled: Some(rgba(0xfefbecff).into()), + text_accent: Some(rgba(0x6684e0ff).into()), status_bar_background: Some(rgba(0x45433bff).into()), title_bar_background: Some(rgba(0x45433bff).into()), toolbar_background: Some(rgba(0x20201dff).into()), @@ -2884,6 +2908,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x64776480).into()), text: Some(rgba(0x8ba48bff).into()), text_muted: Some(rgba(0x687c68ff).into()), + text_placeholder: Some(rgba(0x687c68ff).into()), + text_disabled: Some(rgba(0xf4fbf4ff).into()), + text_accent: Some(rgba(0x3e62f4ff).into()), status_bar_background: Some(rgba(0x3b453bff).into()), title_bar_background: Some(rgba(0x3b453bff).into()), toolbar_background: Some(rgba(0x131513ff).into()), @@ -3241,6 +3268,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x837e8b80).into()), text: Some(rgba(0x5a5462ff).into()), text_muted: Some(rgba(0x7e7987ff).into()), + text_placeholder: Some(rgba(0x7e7987ff).into()), + text_disabled: Some(rgba(0x19171cff).into()), + text_accent: Some(rgba(0x586ddaff).into()), status_bar_background: Some(rgba(0xbfbcc5ff).into()), title_bar_background: Some(rgba(0xbfbcc5ff).into()), toolbar_background: Some(rgba(0xefecf4ff).into()), @@ -3598,6 +3628,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x60585880).into()), text: Some(rgba(0x898383ff).into()), text_muted: Some(rgba(0x655d5dff).into()), + text_placeholder: Some(rgba(0x655d5dff).into()), + text_disabled: Some(rgba(0xf4ececff).into()), + text_accent: Some(rgba(0x7272caff).into()), status_bar_background: Some(rgba(0x3b3535ff).into()), title_bar_background: Some(rgba(0x3b3535ff).into()), toolbar_background: Some(rgba(0x1b1818ff).into()), @@ -3955,6 +3988,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x72647280).into()), text: Some(rgba(0xa99aa9ff).into()), text_muted: Some(rgba(0x776977ff).into()), + text_placeholder: Some(rgba(0x776977ff).into()), + text_disabled: Some(rgba(0xf7f3f7ff).into()), + text_accent: Some(rgba(0x526aebff).into()), status_bar_background: Some(rgba(0x433a43ff).into()), title_bar_background: Some(rgba(0x433a43ff).into()), toolbar_background: Some(rgba(0x1b181bff).into()), @@ -4312,6 +4348,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x57768580).into()), text: Some(rgba(0x7ca0b3ff).into()), text_muted: Some(rgba(0x5a7b8bff).into()), + text_placeholder: Some(rgba(0x5a7b8bff).into()), + text_disabled: Some(rgba(0xebf8ffff).into()), + text_accent: Some(rgba(0x277fadff).into()), status_bar_background: Some(rgba(0x33444dff).into()), title_bar_background: Some(rgba(0x33444dff).into()), toolbar_background: Some(rgba(0x161b1dff).into()), @@ -4669,6 +4708,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0xa1999680).into()), text: Some(rgba(0x6a6360ff).into()), text_muted: Some(rgba(0x9c9491ff).into()), + text_placeholder: Some(rgba(0x9c9491ff).into()), + text_disabled: Some(rgba(0x1b1918ff).into()), + text_accent: Some(rgba(0x417ee6ff).into()), status_bar_background: Some(rgba(0xcdc8c6ff).into()), title_bar_background: Some(rgba(0xcdc8c6ff).into()), toolbar_background: Some(rgba(0xf1efeeff).into()), @@ -5026,6 +5068,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x9e9a8580).into()), text: Some(rgba(0x706d5fff).into()), text_muted: Some(rgba(0x999580ff).into()), + text_placeholder: Some(rgba(0x999580ff).into()), + text_disabled: Some(rgba(0x20201dff).into()), + text_accent: Some(rgba(0x6784e0ff).into()), status_bar_background: Some(rgba(0xcecab4ff).into()), title_bar_background: Some(rgba(0xcecab4ff).into()), toolbar_background: Some(rgba(0xfefbecff).into()), @@ -5383,6 +5428,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x837c7c80).into()), text: Some(rgba(0x5a5252ff).into()), text_muted: Some(rgba(0x7e7777ff).into()), + text_placeholder: Some(rgba(0x7e7777ff).into()), + text_disabled: Some(rgba(0x1b1818ff).into()), + text_accent: Some(rgba(0x7372caff).into()), status_bar_background: Some(rgba(0xc1bbbbff).into()), title_bar_background: Some(rgba(0xc1bbbbff).into()), toolbar_background: Some(rgba(0xf4ececff).into()), @@ -5740,6 +5788,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x859e8580).into()), text: Some(rgba(0x5f705fff).into()), text_muted: Some(rgba(0x809980ff).into()), + text_placeholder: Some(rgba(0x809980ff).into()), + text_disabled: Some(rgba(0x131513ff).into()), + text_accent: Some(rgba(0x3f62f4ff).into()), status_bar_background: Some(rgba(0xb4ceb4ff).into()), title_bar_background: Some(rgba(0xb4ceb4ff).into()), toolbar_background: Some(rgba(0xf4fbf4ff).into()), @@ -6097,6 +6148,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x5a685f80).into()), text: Some(rgba(0x859188ff).into()), text_muted: Some(rgba(0x5f6d64ff).into()), + text_placeholder: Some(rgba(0x5f6d64ff).into()), + text_disabled: Some(rgba(0xecf4eeff).into()), + text_accent: Some(rgba(0x478c90ff).into()), status_bar_background: Some(rgba(0x353f39ff).into()), title_bar_background: Some(rgba(0x353f39ff).into()), toolbar_background: Some(rgba(0x171c19ff).into()), @@ -6454,6 +6508,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0xa394a380).into()), text: Some(rgba(0x6b5e6bff).into()), text_muted: Some(rgba(0x9e8f9eff).into()), + text_placeholder: Some(rgba(0x9e8f9eff).into()), + text_disabled: Some(rgba(0x1b181bff).into()), + text_accent: Some(rgba(0x526aebff).into()), status_bar_background: Some(rgba(0xc6b8c6ff).into()), title_bar_background: Some(rgba(0xc6b8c6ff).into()), toolbar_background: Some(rgba(0xf7f3f7ff).into()), @@ -6811,6 +6868,9 @@ pub fn atelier() -> UserThemeFamily { element_selected: Some(rgba(0x769aad80).into()), text: Some(rgba(0x526f7dff).into()), text_muted: Some(rgba(0x7195a8ff).into()), + text_placeholder: Some(rgba(0x7195a8ff).into()), + text_disabled: Some(rgba(0x161b1dff).into()), + text_accent: Some(rgba(0x277fadff).into()), status_bar_background: Some(rgba(0xa6cadcff).into()), title_bar_background: Some(rgba(0xa6cadcff).into()), toolbar_background: Some(rgba(0xebf8ffff).into()), diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index 4bd39894db..eb6ac40bce 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -28,6 +28,9 @@ pub fn ayu() -> UserThemeFamily { element_selected: Some(rgba(0x50515280).into()), text: Some(rgba(0x8a8986ff).into()), text_muted: Some(rgba(0x58595aff).into()), + text_placeholder: Some(rgba(0x58595aff).into()), + text_disabled: Some(rgba(0xbfbdb6ff).into()), + text_accent: Some(rgba(0x5ac2feff).into()), status_bar_background: Some(rgba(0x313337ff).into()), title_bar_background: Some(rgba(0x313337ff).into()), toolbar_background: Some(rgba(0x0d1017ff).into()), @@ -364,6 +367,9 @@ pub fn ayu() -> UserThemeFamily { element_selected: Some(rgba(0xc0c2c480).into()), text: Some(rgba(0x8c8f93ff).into()), text_muted: Some(rgba(0xb9bbbdff).into()), + text_placeholder: Some(rgba(0xb9bbbdff).into()), + text_disabled: Some(rgba(0x5c6166ff).into()), + text_accent: Some(rgba(0x3b9ee5ff).into()), status_bar_background: Some(rgba(0xdcdddeff).into()), title_bar_background: Some(rgba(0xdcdddeff).into()), toolbar_background: Some(rgba(0xfcfcfcff).into()), @@ -700,6 +706,9 @@ pub fn ayu() -> UserThemeFamily { element_selected: Some(rgba(0x63656a80).into()), text: Some(rgba(0x9a9a98ff).into()), text_muted: Some(rgba(0x6b6d71ff).into()), + text_placeholder: Some(rgba(0x6b6d71ff).into()), + text_disabled: Some(rgba(0xcccac2ff).into()), + text_accent: Some(rgba(0x73cffeff).into()), status_bar_background: Some(rgba(0x464a52ff).into()), title_bar_background: Some(rgba(0x464a52ff).into()), toolbar_background: Some(rgba(0x242936ff).into()), diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index e0b2e44101..2dcf717c47 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -28,6 +28,9 @@ pub fn gruvbox() -> UserThemeFamily { element_selected: Some(rgba(0xb5a68e80).into()), text: Some(rgba(0x5f5650ff).into()), text_muted: Some(rgba(0xad9e87ff).into()), + text_placeholder: Some(rgba(0xad9e87ff).into()), + text_disabled: Some(rgba(0x282828ff).into()), + text_accent: Some(rgba(0x0b6678ff).into()), status_bar_background: Some(rgba(0xd9c8a4ff).into()), title_bar_background: Some(rgba(0xd9c8a4ff).into()), toolbar_background: Some(rgba(0xf9f5d7ff).into()), @@ -371,6 +374,9 @@ pub fn gruvbox() -> UserThemeFamily { element_selected: Some(rgba(0x6e635a80).into()), text: Some(rgba(0xc5b597ff).into()), text_muted: Some(rgba(0x776b61ff).into()), + text_placeholder: Some(rgba(0x776b61ff).into()), + text_disabled: Some(rgba(0xfbf1c7ff).into()), + text_accent: Some(rgba(0x83a598ff).into()), status_bar_background: Some(rgba(0x4c4642ff).into()), title_bar_background: Some(rgba(0x4c4642ff).into()), toolbar_background: Some(rgba(0x32302fff).into()), @@ -714,6 +720,9 @@ pub fn gruvbox() -> UserThemeFamily { element_selected: Some(rgba(0xb5a68e80).into()), text: Some(rgba(0x5f5650ff).into()), text_muted: Some(rgba(0xad9e87ff).into()), + text_placeholder: Some(rgba(0xad9e87ff).into()), + text_disabled: Some(rgba(0x282828ff).into()), + text_accent: Some(rgba(0x0b6678ff).into()), status_bar_background: Some(rgba(0xd9c8a4ff).into()), title_bar_background: Some(rgba(0xd9c8a4ff).into()), toolbar_background: Some(rgba(0xfbf1c7ff).into()), @@ -1057,6 +1066,9 @@ pub fn gruvbox() -> UserThemeFamily { element_selected: Some(rgba(0x6e635a80).into()), text: Some(rgba(0xc5b597ff).into()), text_muted: Some(rgba(0x776b61ff).into()), + text_placeholder: Some(rgba(0x776b61ff).into()), + text_disabled: Some(rgba(0xfbf1c7ff).into()), + text_accent: Some(rgba(0x83a598ff).into()), status_bar_background: Some(rgba(0x4c4642ff).into()), title_bar_background: Some(rgba(0x4c4642ff).into()), toolbar_background: Some(rgba(0x282828ff).into()), @@ -1400,6 +1412,9 @@ pub fn gruvbox() -> UserThemeFamily { element_selected: Some(rgba(0xb5a68e80).into()), text: Some(rgba(0x5f5650ff).into()), text_muted: Some(rgba(0xad9e87ff).into()), + text_placeholder: Some(rgba(0xad9e87ff).into()), + text_disabled: Some(rgba(0x282828ff).into()), + text_accent: Some(rgba(0x0b6678ff).into()), status_bar_background: Some(rgba(0xd9c8a4ff).into()), title_bar_background: Some(rgba(0xd9c8a4ff).into()), toolbar_background: Some(rgba(0xf2e5bcff).into()), @@ -1743,6 +1758,9 @@ pub fn gruvbox() -> UserThemeFamily { element_selected: Some(rgba(0x6e635a80).into()), text: Some(rgba(0xc5b597ff).into()), text_muted: Some(rgba(0x776b61ff).into()), + text_placeholder: Some(rgba(0x776b61ff).into()), + text_disabled: Some(rgba(0xfbf1c7ff).into()), + text_accent: Some(rgba(0x83a598ff).into()), status_bar_background: Some(rgba(0x4c4642ff).into()), title_bar_background: Some(rgba(0x4c4642ff).into()), toolbar_background: Some(rgba(0x1d2021ff).into()), diff --git a/crates/theme2/src/themes/one.rs b/crates/theme2/src/themes/one.rs index 089e3b3bcd..3a20146be1 100644 --- a/crates/theme2/src/themes/one.rs +++ b/crates/theme2/src/themes/one.rs @@ -28,6 +28,9 @@ pub fn one() -> UserThemeFamily { element_selected: Some(rgba(0xafafaf80).into()), text: Some(rgba(0x7f8188ff).into()), text_muted: Some(rgba(0xa7a7a8ff).into()), + text_placeholder: Some(rgba(0xa7a7a8ff).into()), + text_disabled: Some(rgba(0x383a41ff).into()), + text_accent: Some(rgba(0x5c79e2ff).into()), status_bar_background: Some(rgba(0xdcdcddff).into()), title_bar_background: Some(rgba(0xdcdcddff).into()), toolbar_background: Some(rgba(0xfafafaff).into()), @@ -371,6 +374,9 @@ pub fn one() -> UserThemeFamily { element_selected: Some(rgba(0x4f545e80).into()), text: Some(rgba(0x838994ff).into()), text_muted: Some(rgba(0x545862ff).into()), + text_placeholder: Some(rgba(0x545862ff).into()), + text_disabled: Some(rgba(0xc8ccd4ff).into()), + text_accent: Some(rgba(0x74ade8ff).into()), status_bar_background: Some(rgba(0x3b414dff).into()), title_bar_background: Some(rgba(0x3b414dff).into()), toolbar_background: Some(rgba(0x282c34ff).into()), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index abefb32f4e..1dcf523a74 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -28,6 +28,9 @@ pub fn rose_pine() -> UserThemeFamily { element_selected: Some(rgba(0xc1bac180).into()), text: Some(rgba(0x706c8cff).into()), text_muted: Some(rgba(0xb1abb5ff).into()), + text_placeholder: Some(rgba(0xb1abb5ff).into()), + text_disabled: Some(rgba(0x575279ff).into()), + text_accent: Some(rgba(0x57949fff).into()), status_bar_background: Some(rgba(0xdcd8d8ff).into()), title_bar_background: Some(rgba(0xdcd8d8ff).into()), toolbar_background: Some(rgba(0xfaf4edff).into()), @@ -378,6 +381,9 @@ pub fn rose_pine() -> UserThemeFamily { element_selected: Some(rgba(0x45415d80).into()), text: Some(rgba(0x85819eff).into()), text_muted: Some(rgba(0x3a3653ff).into()), + text_placeholder: Some(rgba(0x3a3653ff).into()), + text_disabled: Some(rgba(0xe0def4ff).into()), + text_accent: Some(rgba(0x9cced7ff).into()), status_bar_background: Some(rgba(0x38354eff).into()), title_bar_background: Some(rgba(0x38354eff).into()), toolbar_background: Some(rgba(0x232136ff).into()), @@ -728,6 +734,9 @@ pub fn rose_pine() -> UserThemeFamily { element_selected: Some(rgba(0x47445b80).into()), text: Some(rgba(0x75718eff).into()), text_muted: Some(rgba(0x3b384fff).into()), + text_placeholder: Some(rgba(0x3b384fff).into()), + text_disabled: Some(rgba(0xe0def4ff).into()), + text_accent: Some(rgba(0x9cced7ff).into()), status_bar_background: Some(rgba(0x292739ff).into()), title_bar_background: Some(rgba(0x292739ff).into()), toolbar_background: Some(rgba(0x191724ff).into()), diff --git a/crates/theme2/src/themes/sandcastle.rs b/crates/theme2/src/themes/sandcastle.rs index 2ee42660e3..c0bd53b2d6 100644 --- a/crates/theme2/src/themes/sandcastle.rs +++ b/crates/theme2/src/themes/sandcastle.rs @@ -27,6 +27,9 @@ pub fn sandcastle() -> UserThemeFamily { element_selected: Some(rgba(0x57535380).into()), text: Some(rgba(0xa69782ff).into()), text_muted: Some(rgba(0x645b54ff).into()), + text_placeholder: Some(rgba(0x645b54ff).into()), + text_disabled: Some(rgba(0xfdf4c1ff).into()), + text_accent: Some(rgba(0x528b8bff).into()), status_bar_background: Some(rgba(0x333944ff).into()), title_bar_background: Some(rgba(0x333944ff).into()), toolbar_background: Some(rgba(0x282c34ff).into()), diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index 4b8f60a61d..e358537dfb 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -28,6 +28,9 @@ pub fn solarized() -> UserThemeFamily { element_selected: Some(rgba(0x7f919480).into()), text: Some(rgba(0x34555eff).into()), text_muted: Some(rgba(0x788b8fff).into()), + text_placeholder: Some(rgba(0x788b8fff).into()), + text_disabled: Some(rgba(0x002b36ff).into()), + text_accent: Some(rgba(0x298bd1ff).into()), status_bar_background: Some(rgba(0xcfd0c4ff).into()), title_bar_background: Some(rgba(0xcfd0c4ff).into()), toolbar_background: Some(rgba(0xfdf6e3ff).into()), @@ -364,6 +367,9 @@ pub fn solarized() -> UserThemeFamily { element_selected: Some(rgba(0x566d7480).into()), text: Some(rgba(0x93a1a1ff).into()), text_muted: Some(rgba(0x5f757dff).into()), + text_placeholder: Some(rgba(0x5f757dff).into()), + text_disabled: Some(rgba(0xfdf6e3ff).into()), + text_accent: Some(rgba(0x288bd1ff).into()), status_bar_background: Some(rgba(0x083743ff).into()), title_bar_background: Some(rgba(0x083743ff).into()), toolbar_background: Some(rgba(0x002b36ff).into()), diff --git a/crates/theme2/src/themes/summercamp.rs b/crates/theme2/src/themes/summercamp.rs index f4b5b6ed63..eab403fe79 100644 --- a/crates/theme2/src/themes/summercamp.rs +++ b/crates/theme2/src/themes/summercamp.rs @@ -27,6 +27,9 @@ pub fn summercamp() -> UserThemeFamily { element_selected: Some(rgba(0x39342780).into()), text: Some(rgba(0x736e55ff).into()), text_muted: Some(rgba(0x3d382aff).into()), + text_placeholder: Some(rgba(0x3d382aff).into()), + text_disabled: Some(rgba(0xf8f5deff).into()), + text_accent: Some(rgba(0x499befff).into()), status_bar_background: Some(rgba(0x2a261cff).into()), title_bar_background: Some(rgba(0x2a261cff).into()), toolbar_background: Some(rgba(0x1c1810ff).into()), diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs index 0b932c83fb..87318199cf 100644 --- a/crates/theme_importer/src/zed1/converter.rs +++ b/crates/theme_importer/src/zed1/converter.rs @@ -87,63 +87,52 @@ impl Zed1ThemeConverter { Some(zed1_color_to_hsla(color)) } + let picker = &self.theme.picker; + let title_bar = &self.theme.titlebar; + let status_bar = &self.theme.workspace.status_bar; + let project_panel = &self.theme.project_panel; let tab_bar = &self.theme.workspace.tab_bar; let active_tab = &self.theme.workspace.tab_bar.tab_style(true, true); let inactive_tab = &self.theme.workspace.tab_bar.tab_style(true, false); let toolbar = &self.theme.workspace.toolbar; + let editor = &self.theme.editor; let scrollbar = &self.theme.editor.scrollbar; + let terminal = &self.theme.terminal; - let zed1_titlebar_border = convert(self.theme.titlebar.container.border.color); + let title_bar_border = convert(title_bar.container.border.color); Ok(ThemeColorsRefinement { - border: zed1_titlebar_border, - border_variant: zed1_titlebar_border, + border: title_bar_border, + border_variant: title_bar_border, background: convert(self.theme.workspace.background), - elevated_surface_background: self - .theme - .picker - .container - .background_color - .map(zed1_color_to_hsla), - title_bar_background: self - .theme - .titlebar - .container - .background_color - .map(zed1_color_to_hsla), - status_bar_background: self - .theme - .workspace - .status_bar + elevated_surface_background: picker.container.background_color.map(zed1_color_to_hsla), + title_bar_background: title_bar.container.background_color.map(zed1_color_to_hsla), + status_bar_background: status_bar .container .background_color .map(zed1_color_to_hsla) - .or_else(|| { - self.theme - .titlebar - .container - .background_color - .map(zed1_color_to_hsla) - }), - panel_background: self - .theme - .project_panel + .or_else(|| title_bar.container.background_color.map(zed1_color_to_hsla)), + panel_background: project_panel .container .background_color .map(zed1_color_to_hsla), text: convert(self.theme.project_panel.entry.default_style().text.color), text_muted: convert(active_tab.description.text.color), - element_hover: self - .theme - .picker + text_accent: convert(status_bar.panel_buttons.button.active_state().icon_color), + text_disabled: convert(status_bar.panel_buttons.button.disabled_style().icon_color), + text_placeholder: picker + .empty_input_editor + .placeholder_text + .as_ref() + .map(|placeholder_text| placeholder_text.color) + .map(zed1_color_to_hsla), + element_hover: picker .item .hovered .as_ref() .and_then(|hovered| hovered.container.background_color) .map(zed1_color_to_hsla), - element_selected: self - .theme - .picker + element_selected: picker .item .active_state() .container @@ -159,13 +148,13 @@ impl Zed1ThemeConverter { .background_color .map(zed1_color_to_hsla), toolbar_background: toolbar.container.background_color.map(zed1_color_to_hsla), - editor_foreground: convert(self.theme.editor.text_color), - editor_background: convert(self.theme.editor.background), - editor_gutter_background: convert(self.theme.editor.gutter_background), - editor_line_number: convert(self.theme.editor.line_number), - editor_active_line_number: convert(self.theme.editor.line_number_active), - editor_wrap_guide: convert(self.theme.editor.wrap_guide), - editor_active_wrap_guide: convert(self.theme.editor.active_wrap_guide), + editor_foreground: convert(editor.text_color), + editor_background: convert(editor.background), + editor_gutter_background: convert(editor.gutter_background), + editor_line_number: convert(editor.line_number), + editor_active_line_number: convert(editor.line_number_active), + editor_wrap_guide: convert(editor.wrap_guide), + editor_active_wrap_guide: convert(editor.active_wrap_guide), scrollbar_track_background: scrollbar.track.background_color.map(zed1_color_to_hsla), scrollbar_track_border: convert(scrollbar.track.border.color), scrollbar_thumb_background: scrollbar.thumb.background_color.map(zed1_color_to_hsla), @@ -174,23 +163,23 @@ impl Zed1ThemeConverter { .thumb .background_color .map(zed1_color_to_hsla), - terminal_background: convert(self.theme.terminal.background), - terminal_ansi_bright_black: convert(self.theme.terminal.bright_black), - terminal_ansi_bright_red: convert(self.theme.terminal.bright_red), - terminal_ansi_bright_green: convert(self.theme.terminal.bright_green), - terminal_ansi_bright_yellow: convert(self.theme.terminal.bright_yellow), - terminal_ansi_bright_blue: convert(self.theme.terminal.bright_blue), - terminal_ansi_bright_magenta: convert(self.theme.terminal.bright_magenta), - terminal_ansi_bright_cyan: convert(self.theme.terminal.bright_cyan), - terminal_ansi_bright_white: convert(self.theme.terminal.bright_white), - terminal_ansi_black: convert(self.theme.terminal.black), - terminal_ansi_red: convert(self.theme.terminal.red), - terminal_ansi_green: convert(self.theme.terminal.green), - terminal_ansi_yellow: convert(self.theme.terminal.yellow), - terminal_ansi_blue: convert(self.theme.terminal.blue), - terminal_ansi_magenta: convert(self.theme.terminal.magenta), - terminal_ansi_cyan: convert(self.theme.terminal.cyan), - terminal_ansi_white: convert(self.theme.terminal.white), + terminal_background: convert(terminal.background), + terminal_ansi_bright_black: convert(terminal.bright_black), + terminal_ansi_bright_red: convert(terminal.bright_red), + terminal_ansi_bright_green: convert(terminal.bright_green), + terminal_ansi_bright_yellow: convert(terminal.bright_yellow), + terminal_ansi_bright_blue: convert(terminal.bright_blue), + terminal_ansi_bright_magenta: convert(terminal.bright_magenta), + terminal_ansi_bright_cyan: convert(terminal.bright_cyan), + terminal_ansi_bright_white: convert(terminal.bright_white), + terminal_ansi_black: convert(terminal.black), + terminal_ansi_red: convert(terminal.red), + terminal_ansi_green: convert(terminal.green), + terminal_ansi_yellow: convert(terminal.yellow), + terminal_ansi_blue: convert(terminal.blue), + terminal_ansi_magenta: convert(terminal.magenta), + terminal_ansi_cyan: convert(terminal.cyan), + terminal_ansi_white: convert(terminal.white), ..Default::default() }) } From ca7e5048177bf1fa8993d8684d6a9154321dff92 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Sat, 23 Dec 2023 00:49:51 +0100 Subject: [PATCH 304/644] titlebar: show "Share project" button only in local projects. (#3795) Fixes '"Share" button is shown even for remote projects'. Release Notes: - N/A --- crates/collab_ui2/src/collab_titlebar_item.rs | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 75c4cc5263..02c4446a9a 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -169,27 +169,31 @@ impl Render for CollabTitlebarItem { .pr_1() .when_some(room, |this, room| { let room = room.read(cx); - let is_shared = self.project.read(cx).is_shared(); + let project = self.project.read(cx); + let is_local = project.is_local(); + let is_shared = is_local && project.is_shared(); let is_muted = room.is_muted(cx); let is_deafened = room.is_deafened().unwrap_or(false); let is_screen_sharing = room.is_screen_sharing(); - this.child( - Button::new( - "toggle_sharing", - if is_shared { "Unshare" } else { "Share" }, + this.when(is_local, |this| { + this.child( + Button::new( + "toggle_sharing", + if is_shared { "Unshare" } else { "Share" }, + ) + .style(ButtonStyle::Subtle) + .on_click(cx.listener( + move |this, _, cx| { + if is_shared { + this.unshare_project(&Default::default(), cx); + } else { + this.share_project(&Default::default(), cx); + } + }, + )), ) - .style(ButtonStyle::Subtle) - .on_click(cx.listener( - move |this, _, cx| { - if is_shared { - this.unshare_project(&Default::default(), cx); - } else { - this.share_project(&Default::default(), cx); - } - }, - )), - ) + }) .child( IconButton::new("leave-call", ui::Icon::Exit) .style(ButtonStyle::Subtle) From c6f3f439c4128b3fff1569e27cb7bb6327aa5bf8 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 23 Dec 2023 01:55:40 +0200 Subject: [PATCH 305/644] Fix mouse listeners' z-index for editor --- crates/editor2/src/element.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 9e1d8e641f..f7feba9292 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2840,17 +2840,13 @@ impl Element for EditorElement { } self.paint_text(text_bounds, &mut layout, cx); + cx.with_z_index(0, |cx| { + self.paint_mouse_listeners(bounds, gutter_bounds, text_bounds, &layout, cx); + }); if !layout.blocks.is_empty() { cx.with_z_index(0, |cx| { cx.with_element_id(Some("editor_blocks"), |cx| { self.paint_blocks(bounds, &mut layout, cx); - self.paint_mouse_listeners( - bounds, - gutter_bounds, - text_bounds, - &layout, - cx, - ); }); }) } From 3213a860a6e702d4fc4c48359a441caf48269a22 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 18:56:17 -0500 Subject: [PATCH 306/644] Use extra small label for tab descriptions (#3797) This PR adjusts the size of the tab descriptions to use the extra small label size. This makes it easier to distinguish between the filename and the description: Screenshot 2023-12-22 at 6 49 11 PM It's also more in line with how things look in Zed1. Release Notes: - N/A --- crates/editor2/src/items.rs | 6 ++++- crates/ui2/src/components/button/button.rs | 2 +- .../src/components/button/toggle_button.rs | 2 +- crates/ui2/src/components/label/label_like.rs | 8 +++--- crates/ui2/src/styled_ext.rs | 25 +++++++++++-------- crates/ui2/src/styles/typography.rs | 16 +++++++++--- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index e0374d3d73..ddb5b25db2 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -603,7 +603,11 @@ impl Item for Editor { Color::Muted })) .when_some(description, |this, description| { - this.child(Label::new(description).color(Color::Muted)) + this.child( + Label::new(description) + .size(LabelSize::XSmall) + .color(Color::Muted), + ) }) .into_any_element() } diff --git a/crates/ui2/src/components/button/button.rs b/crates/ui2/src/components/button/button.rs index 406cd1f420..bc5d03d639 100644 --- a/crates/ui2/src/components/button/button.rs +++ b/crates/ui2/src/components/button/button.rs @@ -172,7 +172,7 @@ impl RenderOnce for Button { Label::new(label) .color(label_color) .size(self.label_size.unwrap_or_default()) - .line_height_style(LineHeightStyle::UILabel), + .line_height_style(LineHeightStyle::UiLabel), ) .when(!self.icon_position.is_some(), |this| { this.children(self.icon.map(|icon| { diff --git a/crates/ui2/src/components/button/toggle_button.rs b/crates/ui2/src/components/button/toggle_button.rs index 39a517111b..4a6ecdeb2f 100644 --- a/crates/ui2/src/components/button/toggle_button.rs +++ b/crates/ui2/src/components/button/toggle_button.rs @@ -122,7 +122,7 @@ impl RenderOnce for ToggleButton { .child( Label::new(self.label) .color(label_color) - .line_height_style(LineHeightStyle::UILabel), + .line_height_style(LineHeightStyle::UiLabel), ) } } diff --git a/crates/ui2/src/components/label/label_like.rs b/crates/ui2/src/components/label/label_like.rs index 72a48adea4..ebfbbecceb 100644 --- a/crates/ui2/src/components/label/label_like.rs +++ b/crates/ui2/src/components/label/label_like.rs @@ -8,14 +8,15 @@ pub enum LabelSize { #[default] Default, Small, + XSmall, } #[derive(Default, PartialEq, Copy, Clone)] pub enum LineHeightStyle { #[default] TextLabel, - /// Sets the line height to 1 - UILabel, + /// Sets the line height to 1. + UiLabel, } pub trait LabelCommon { @@ -92,8 +93,9 @@ impl RenderOnce for LabelLike { .map(|this| match self.size { LabelSize::Default => this.text_ui(), LabelSize::Small => this.text_ui_sm(), + LabelSize::XSmall => this.text_ui_xs(), }) - .when(self.line_height_style == LineHeightStyle::UILabel, |this| { + .when(self.line_height_style == LineHeightStyle::UiLabel, |this| { this.line_height(relative(1.)) }) .text_color(self.color.color(cx)) diff --git a/crates/ui2/src/styled_ext.rs b/crates/ui2/src/styled_ext.rs index 3358968c72..7e761f8f2c 100644 --- a/crates/ui2/src/styled_ext.rs +++ b/crates/ui2/src/styled_ext.rs @@ -3,7 +3,7 @@ use settings::Settings; use theme::ThemeSettings; use crate::prelude::*; -use crate::{ElevationIndex, UITextSize}; +use crate::{ElevationIndex, UiTextSize}; fn elevated(this: E, cx: &mut WindowContext, index: ElevationIndex) -> E { this.bg(cx.theme().colors().elevated_surface_background) @@ -44,10 +44,8 @@ pub trait StyledExt: Styled + Sized { self.flex().flex_col() } - fn text_ui_size(self, size: UITextSize) -> Self { - let size = size.rems(); - - self.text_size(size) + fn text_ui_size(self, size: UiTextSize) -> Self { + self.text_size(size.rems()) } /// The default size for UI text. @@ -58,9 +56,7 @@ pub trait StyledExt: Styled + Sized { /// /// Use [`text_ui_sm`] for regular-sized text. fn text_ui(self) -> Self { - let size = UITextSize::default().rems(); - - self.text_size(size) + self.text_size(UiTextSize::default().rems()) } /// The small size for UI text. @@ -71,9 +67,18 @@ pub trait StyledExt: Styled + Sized { /// /// Use [`text_ui`] for regular-sized text. fn text_ui_sm(self) -> Self { - let size = UITextSize::Small.rems(); + self.text_size(UiTextSize::Small.rems()) + } - self.text_size(size) + /// The extra small size for UI text. + /// + /// `0.625rem` or `10px` at the default scale of `1rem` = `16px`. + /// + /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. + /// + /// Use [`text_ui`] for regular-sized text. + fn text_ui_xs(self) -> Self { + self.text_size(UiTextSize::XSmall.rems()) } /// The font size for buffer text. diff --git a/crates/ui2/src/styles/typography.rs b/crates/ui2/src/styles/typography.rs index 18b2c4849a..4819791b02 100644 --- a/crates/ui2/src/styles/typography.rs +++ b/crates/ui2/src/styles/typography.rs @@ -1,7 +1,7 @@ use gpui::{rems, Rems}; #[derive(Debug, Default, Clone)] -pub enum UITextSize { +pub enum UiTextSize { /// The default size for UI text. /// /// `0.825rem` or `14px` at the default scale of `1rem` = `16px`. @@ -15,13 +15,21 @@ pub enum UITextSize { /// /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. Small, + + /// The extra small size for UI text. + /// + /// `0.625rem` or `10px` at the default scale of `1rem` = `16px`. + /// + /// Note: The absolute size of this text will change based on a user's `ui_scale` setting. + XSmall, } -impl UITextSize { +impl UiTextSize { pub fn rems(self) -> Rems { match self { - Self::Default => rems(0.875), - Self::Small => rems(0.75), + Self::Default => rems(14. / 16.), + Self::Small => rems(12. / 16.), + Self::XSmall => rems(10. / 16.), } } } From f03ee1ea244c86e83b4f10c4acddf69109556e64 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 19:18:04 -0500 Subject: [PATCH 307/644] Add spacing between tab bar buttons (#3799) This PR adds spacing between buttons in the tab bar. Release Notes: - N/A --- crates/workspace2/src/pane.rs | 41 ++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 7128288e7b..893c522222 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -377,6 +377,7 @@ impl Pane { can_split: true, render_tab_bar_buttons: Rc::new(move |pane, cx| { h_stack() + .gap_2() .child( IconButton::new("plus", Icon::Plus) .icon_size(IconSize::Small) @@ -1657,24 +1658,28 @@ impl Pane { TabBar::new("tab_bar") .track_scroll(self.tab_bar_scroll_handle.clone()) .start_child( - IconButton::new("navigate_backward", Icon::ArrowLeft) - .icon_size(IconSize::Small) - .on_click({ - let view = cx.view().clone(); - move |_, cx| view.update(cx, Self::navigate_backward) - }) - .disabled(!self.can_navigate_backward()) - .tooltip(|cx| Tooltip::for_action("Go Back", &GoBack, cx)), - ) - .start_child( - IconButton::new("navigate_forward", Icon::ArrowRight) - .icon_size(IconSize::Small) - .on_click({ - let view = cx.view().clone(); - move |_, cx| view.update(cx, Self::navigate_backward) - }) - .disabled(!self.can_navigate_forward()) - .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), + h_stack() + .gap_2() + .child( + IconButton::new("navigate_backward", Icon::ArrowLeft) + .icon_size(IconSize::Small) + .on_click({ + let view = cx.view().clone(); + move |_, cx| view.update(cx, Self::navigate_backward) + }) + .disabled(!self.can_navigate_backward()) + .tooltip(|cx| Tooltip::for_action("Go Back", &GoBack, cx)), + ) + .child( + IconButton::new("navigate_forward", Icon::ArrowRight) + .icon_size(IconSize::Small) + .on_click({ + let view = cx.view().clone(); + move |_, cx| view.update(cx, Self::navigate_backward) + }) + .disabled(!self.can_navigate_forward()) + .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), + ), ) .end_child({ let render_tab_buttons = self.render_tab_bar_buttons.clone(); From a1915ce6c437af87d1faf0124dd949d8dc08b4d0 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 23 Dec 2023 02:29:33 +0200 Subject: [PATCH 308/644] Add spacing to terminal tab bar buttons --- crates/terminal_view2/src/terminal_panel.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index c2fe5de014..044a9f3aa8 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -76,6 +76,7 @@ impl TerminalPanel { pane.set_can_navigate(false, cx); pane.set_render_tab_bar_buttons(cx, move |pane, cx| { h_stack() + .gap_2() .child( IconButton::new("plus", Icon::Plus) .icon_size(IconSize::Small) From 0e145a843507a6c61bfc82538d244ab6a1b0cb51 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 19:32:07 -0500 Subject: [PATCH 309/644] Make current call controls in title bar smaller (#3800) This PR adjusts the sizes of the current call controls in the title bar to be smaller. This matches the size of the other title bar items that are always present. Release Notes: - N/A --- crates/collab_ui2/src/collab_titlebar_item.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 02c4446a9a..6255e2b833 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -183,6 +183,7 @@ impl Render for CollabTitlebarItem { if is_shared { "Unshare" } else { "Share" }, ) .style(ButtonStyle::Subtle) + .label_size(LabelSize::Small) .on_click(cx.listener( move |this, _, cx| { if is_shared { @@ -197,6 +198,7 @@ impl Render for CollabTitlebarItem { .child( IconButton::new("leave-call", ui::Icon::Exit) .style(ButtonStyle::Subtle) + .icon_size(IconSize::Small) .on_click(move |_, cx| { ActiveCall::global(cx) .update(cx, |call, cx| call.hang_up(cx)) @@ -213,6 +215,7 @@ impl Render for CollabTitlebarItem { }, ) .style(ButtonStyle::Subtle) + .icon_size(IconSize::Small) .selected(is_muted) .on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)), ) @@ -226,6 +229,7 @@ impl Render for CollabTitlebarItem { }, ) .style(ButtonStyle::Subtle) + .icon_size(IconSize::Small) .selected(is_deafened) .tooltip(move |cx| { Tooltip::with_meta("Deafen Audio", None, "Mic will be muted", cx) @@ -235,6 +239,7 @@ impl Render for CollabTitlebarItem { .child( IconButton::new("screen-share", ui::Icon::Screen) .style(ButtonStyle::Subtle) + .icon_size(IconSize::Small) .selected(is_screen_sharing) .on_click(move |_, cx| { crate::toggle_screen_sharing(&Default::default(), cx) @@ -313,6 +318,7 @@ impl CollabTitlebarItem { Button::new("project_owner_trigger", host.github_login.clone()) .color(Color::Player(participant_index.0)) .style(ButtonStyle::Subtle) + .label_size(LabelSize::Small) .tooltip(move |cx| Tooltip::text("Toggle following", cx)), ), ) From d7b06620584ac782f689bea9344487330cadc623 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 22 Dec 2023 16:44:28 -0800 Subject: [PATCH 310/644] Maintain workspace's zoom state when opening/closing docks, activating panels --- crates/workspace2/src/dock.rs | 46 +++++++++++++++++++++-------- crates/workspace2/src/workspace2.rs | 12 ++------ 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index fbc8a1f878..928e03a692 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -192,21 +192,43 @@ pub struct PanelButtons { } impl Dock { - pub fn new(position: DockPosition, cx: &mut ViewContext<'_, Self>) -> Self { + pub fn new(position: DockPosition, cx: &mut ViewContext) -> View { let focus_handle = cx.focus_handle(); - let focus_subscription = cx.on_focus(&focus_handle, |dock, cx| { - if let Some(active_entry) = dock.panel_entries.get(dock.active_panel_index) { - active_entry.panel.focus_handle(cx).focus(cx) + + let dock = cx.build_view(|cx: &mut ViewContext| { + let focus_subscription = cx.on_focus(&focus_handle, |dock, cx| { + if let Some(active_entry) = dock.panel_entries.get(dock.active_panel_index) { + active_entry.panel.focus_handle(cx).focus(cx) + } + }); + Self { + position, + panel_entries: Default::default(), + active_panel_index: 0, + is_open: false, + focus_handle: focus_handle.clone(), + _focus_subscription: focus_subscription, } }); - Self { - position, - panel_entries: Default::default(), - active_panel_index: 0, - is_open: false, - focus_handle, - _focus_subscription: focus_subscription, - } + + cx.observe(&dock, move |workspace, dock, cx| { + if dock.read(cx).is_open() { + if let Some(panel) = dock.read(cx).active_panel() { + if panel.is_zoomed(cx) { + workspace.zoomed = Some(panel.to_any().downgrade()); + workspace.zoomed_position = Some(position); + return; + } + } + } + if workspace.zoomed_position == Some(position) { + workspace.zoomed = None; + workspace.zoomed_position = None; + } + }) + .detach(); + + dock } pub fn position(&self) -> DockPosition { diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index f4484c827e..61083ad269 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -586,9 +586,9 @@ impl Workspace { cx.emit(Event::WorkspaceCreated(weak_handle.clone())); - let left_dock = cx.build_view(|cx| Dock::new(DockPosition::Left, cx)); - let bottom_dock = cx.build_view(|cx| Dock::new(DockPosition::Bottom, cx)); - let right_dock = cx.build_view(|cx| Dock::new(DockPosition::Right, cx)); + let left_dock = Dock::new(DockPosition::Left, cx); + let bottom_dock = Dock::new(DockPosition::Bottom, cx); + let right_dock = Dock::new(DockPosition::Right, cx); let left_dock_buttons = cx.build_view(|cx| PanelButtons::new(left_dock.clone(), cx)); let bottom_dock_buttons = cx.build_view(|cx| PanelButtons::new(bottom_dock.clone(), cx)); let right_dock_buttons = cx.build_view(|cx| PanelButtons::new(right_dock.clone(), cx)); @@ -1616,7 +1616,6 @@ impl Workspace { for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { let mut focus_center = false; - let mut reveal_dock = false; let panel = dock.update(cx, |dock, cx| { dock.activate_panel(panel_index, cx); @@ -1625,12 +1624,7 @@ impl Workspace { if should_focus(&**panel, cx) { dock.set_open(true, cx); panel.focus_handle(cx).focus(cx); - reveal_dock = true; } else { - // todo!() - // if panel.is_zoomed(cx) { - // dock.set_open(false, cx); - // } focus_center = true; } } From 0746a10d9be20be72dc368b5112799e17347e83a Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 22 Dec 2023 19:56:06 -0500 Subject: [PATCH 311/644] Increase telemetry queue size --- crates/client/src/telemetry.rs | 2 +- crates/client2/src/telemetry.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 6d70de6138..5e97382d70 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -119,7 +119,7 @@ pub enum ClickhouseEvent { const MAX_QUEUE_LEN: usize = 1; #[cfg(not(debug_assertions))] -const MAX_QUEUE_LEN: usize = 10; +const MAX_QUEUE_LEN: usize = 50; #[cfg(debug_assertions)] const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index 71c4c33491..e1a7d3f41e 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -118,7 +118,7 @@ pub enum ClickhouseEvent { const MAX_QUEUE_LEN: usize = 1; #[cfg(not(debug_assertions))] -const MAX_QUEUE_LEN: usize = 10; +const MAX_QUEUE_LEN: usize = 50; #[cfg(debug_assertions)] const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); From 1989094e6dc064d19ad83b1b5f07af14c6876915 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 22 Dec 2023 19:57:13 -0500 Subject: [PATCH 312/644] Increase queue flush debounce time --- crates/client/src/telemetry.rs | 2 +- crates/client2/src/telemetry.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 5e97382d70..0118832fe0 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -125,7 +125,7 @@ const MAX_QUEUE_LEN: usize = 50; const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); #[cfg(not(debug_assertions))] -const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30); +const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(120); impl Telemetry { pub fn new(client: Arc, cx: &AppContext) -> Arc { diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index e1a7d3f41e..e27bc3a498 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -124,7 +124,7 @@ const MAX_QUEUE_LEN: usize = 50; const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); #[cfg(not(debug_assertions))] -const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(30); +const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(120); impl Telemetry { pub fn new(client: Arc, cx: &mut AppContext) -> Arc { From b1870af386a7d048cb89e6ecef8b5b29d83e1800 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 22 Dec 2023 20:23:55 -0500 Subject: [PATCH 313/644] Add project open event Give the caller of report_app_event() the choice of whether to immediately flush the queue or not. --- crates/client/src/telemetry.rs | 4 ++-- crates/client2/src/telemetry.rs | 6 +++--- crates/workspace/src/workspace.rs | 6 +++++- crates/workspace2/src/workspace2.rs | 6 +++++- crates/zed/src/main.rs | 2 +- crates/zed2/src/main.rs | 2 +- 6 files changed, 17 insertions(+), 9 deletions(-) diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 0118832fe0..49cb9843f0 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -340,18 +340,18 @@ impl Telemetry { self.report_clickhouse_event(event, telemetry_settings, false) } - // app_events are called at app open and app close, so flush is set to immediately send pub fn report_app_event( self: &Arc, telemetry_settings: TelemetrySettings, operation: &'static str, + immediate_flush: bool, ) { let event = ClickhouseEvent::App { operation, milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, true) + self.report_clickhouse_event(event, telemetry_settings, immediate_flush) } fn milliseconds_since_first_event(&self) -> i64 { diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index e27bc3a498..f02ff937e4 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -173,7 +173,7 @@ impl Telemetry { #[cfg(not(any(test, feature = "test-support")))] fn shutdown_telemetry(self: &Arc, cx: &mut AppContext) -> impl Future { let telemetry_settings = TelemetrySettings::get_global(cx).clone(); - self.report_app_event(telemetry_settings, "close"); + self.report_app_event(telemetry_settings, "close", true); Task::ready(()) } @@ -364,18 +364,18 @@ impl Telemetry { self.report_clickhouse_event(event, telemetry_settings, false) } - // app_events are called at app open and app close, so flush is set to immediately send pub fn report_app_event( self: &Arc, telemetry_settings: TelemetrySettings, operation: &'static str, + immediate_flush: bool, ) { let event = ClickhouseEvent::App { operation, milliseconds_since_first_event: self.milliseconds_since_first_event(), }; - self.report_clickhouse_event(event, telemetry_settings, true) + self.report_clickhouse_event(event, telemetry_settings, immediate_flush) } fn milliseconds_since_first_event(&self) -> i64 { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 455c27a57e..ee2a8ab104 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -14,7 +14,7 @@ use anyhow::{anyhow, Context, Result}; use call::ActiveCall; use client::{ proto::{self, PeerId}, - Client, Status, TypedEnvelope, UserStore, + Client, Status, TelemetrySettings, TypedEnvelope, UserStore, }; use collections::{hash_map, HashMap, HashSet}; use drag_and_drop::DragAndDrop; @@ -1462,6 +1462,10 @@ impl Workspace { } pub fn open(&mut self, _: &Open, cx: &mut ViewContext) -> Option>> { + let telemetry_settings = *settings::get::(cx); + self.client() + .telemetry() + .report_app_event(telemetry_settings, "open project", false); let mut paths = cx.prompt_for_paths(PathPromptOptions { files: true, directories: true, diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 61083ad269..0eb6425287 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -15,7 +15,7 @@ use anyhow::{anyhow, Context as _, Result}; use call::ActiveCall; use client::{ proto::{self, PeerId}, - Client, Status, TypedEnvelope, UserStore, + Client, Status, TelemetrySettings, TypedEnvelope, UserStore, }; use collections::{hash_map, HashMap, HashSet}; use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle}; @@ -1250,6 +1250,10 @@ impl Workspace { } pub fn open(&mut self, _: &Open, cx: &mut ViewContext) { + let telemetry_settings = TelemetrySettings::get_global(cx).clone(); + self.client() + .telemetry() + .report_app_event(telemetry_settings, "open project", false); let paths = cx.prompt_for_paths(PathPromptOptions { files: true, directories: true, diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 20b93ae6bb..04f468eb2f 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -174,7 +174,7 @@ fn main() { }; client .telemetry() - .report_app_event(telemetry_settings, event_operation); + .report_app_event(telemetry_settings, event_operation, true); let app_state = Arc::new(AppState { languages, diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 93643648b8..a885a81f79 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -184,7 +184,7 @@ fn main() { }; client .telemetry() - .report_app_event(telemetry_settings, event_operation); + .report_app_event(telemetry_settings, event_operation, true); let app_state = Arc::new(AppState { languages: languages.clone(), From e8a14b19715ba2ea06d6d84bbfba5080ffca33d6 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 21:10:53 -0500 Subject: [PATCH 314/644] Adjust color used for text --- crates/theme2/src/themes/andromeda.rs | 2 +- crates/theme2/src/themes/atelier.rs | 40 ++++++++++----------- crates/theme2/src/themes/ayu.rs | 6 ++-- crates/theme2/src/themes/gruvbox.rs | 12 +++---- crates/theme2/src/themes/one.rs | 4 +-- crates/theme2/src/themes/rose_pine.rs | 6 ++-- crates/theme2/src/themes/sandcastle.rs | 2 +- crates/theme2/src/themes/solarized.rs | 4 +-- crates/theme2/src/themes/summercamp.rs | 2 +- crates/theme_importer/src/zed1/converter.rs | 2 +- 10 files changed, 40 insertions(+), 40 deletions(-) diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index 699abec491..2130653e57 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -25,7 +25,7 @@ pub fn andromeda() -> UserThemeFamily { panel_background: Some(rgba(0x21242bff).into()), element_hover: Some(rgba(0x2b2f3980).into()), element_selected: Some(rgba(0x383b4580).into()), - text: Some(rgba(0xaca8aeff).into()), + text: Some(rgba(0xf7f7f8ff).into()), text_muted: Some(rgba(0x474a53ff).into()), text_placeholder: Some(rgba(0x474a53ff).into()), text_disabled: Some(rgba(0xf7f7f8ff).into()), diff --git a/crates/theme2/src/themes/atelier.rs b/crates/theme2/src/themes/atelier.rs index 1722521b03..869fa44c0d 100644 --- a/crates/theme2/src/themes/atelier.rs +++ b/crates/theme2/src/themes/atelier.rs @@ -26,7 +26,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xebeae3ff).into()), element_hover: Some(rgba(0x96958580).into()), element_selected: Some(rgba(0x8b8a7880).into()), - text: Some(rgba(0x61604fff).into()), + text: Some(rgba(0x22221bff).into()), text_muted: Some(rgba(0x878573ff).into()), text_placeholder: Some(rgba(0x878573ff).into()), text_disabled: Some(rgba(0x22221bff).into()), @@ -386,7 +386,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x27211eff).into()), element_hover: Some(rgba(0x665f5c80).into()), element_selected: Some(rgba(0x71696680).into()), - text: Some(rgba(0xa79f9dff).into()), + text: Some(rgba(0xf1efeeff).into()), text_muted: Some(rgba(0x766e6bff).into()), text_placeholder: Some(rgba(0x766e6bff).into()), text_disabled: Some(rgba(0xf1efeeff).into()), @@ -746,7 +746,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xe3ebe6ff).into()), element_hover: Some(rgba(0x8b968e80).into()), element_selected: Some(rgba(0x7e8b8280).into()), - text: Some(rgba(0x546259ff).into()), + text: Some(rgba(0x171c19ff).into()), text_muted: Some(rgba(0x79877dff).into()), text_placeholder: Some(rgba(0x79877dff).into()), text_disabled: Some(rgba(0x171c19ff).into()), @@ -1106,7 +1106,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x221f26ff).into()), element_hover: Some(rgba(0x56505e80).into()), element_selected: Some(rgba(0x605a6880).into()), - text: Some(rgba(0x898591ff).into()), + text: Some(rgba(0xefecf4ff).into()), text_muted: Some(rgba(0x655f6dff).into()), text_placeholder: Some(rgba(0x655f6dff).into()), text_disabled: Some(rgba(0xefecf4ff).into()), @@ -1466,7 +1466,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x2c2b23ff).into()), element_hover: Some(rgba(0x5d5c4c80).into()), element_selected: Some(rgba(0x67665580).into()), - text: Some(rgba(0x91907fff).into()), + text: Some(rgba(0xf4f3ecff).into()), text_muted: Some(rgba(0x6c6b5aff).into()), text_placeholder: Some(rgba(0x6c6b5aff).into()), text_disabled: Some(rgba(0xf4f3ecff).into()), @@ -1826,7 +1826,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x262f51ff).into()), element_hover: Some(rgba(0x5c648580).into()), element_selected: Some(rgba(0x666e8f80).into()), - text: Some(rgba(0x959bb2ff).into()), + text: Some(rgba(0xf5f7ffff).into()), text_muted: Some(rgba(0x6b7394ff).into()), text_placeholder: Some(rgba(0x6b7394ff).into()), text_disabled: Some(rgba(0xf5f7ffff).into()), @@ -2186,7 +2186,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xe5e8f5ff).into()), element_hover: Some(rgba(0x9a9fb680).into()), element_selected: Some(rgba(0x8e94aa80).into()), - text: Some(rgba(0x606889ff).into()), + text: Some(rgba(0x202746ff).into()), text_muted: Some(rgba(0x898fa5ff).into()), text_placeholder: Some(rgba(0x898fa5ff).into()), text_disabled: Some(rgba(0x202746ff).into()), @@ -2546,7 +2546,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x262622ff).into()), element_hover: Some(rgba(0x6c695c80).into()), element_selected: Some(rgba(0x77746480).into()), - text: Some(rgba(0xa4a08bff).into()), + text: Some(rgba(0xfefbecff).into()), text_muted: Some(rgba(0x7c7968ff).into()), text_placeholder: Some(rgba(0x7c7968ff).into()), text_disabled: Some(rgba(0xfefbecff).into()), @@ -2906,7 +2906,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x1f231fff).into()), element_hover: Some(rgba(0x5c6c5c80).into()), element_selected: Some(rgba(0x64776480).into()), - text: Some(rgba(0x8ba48bff).into()), + text: Some(rgba(0xf4fbf4ff).into()), text_muted: Some(rgba(0x687c68ff).into()), text_placeholder: Some(rgba(0x687c68ff).into()), text_disabled: Some(rgba(0xf4fbf4ff).into()), @@ -3266,7 +3266,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xe6e3ebff).into()), element_hover: Some(rgba(0x8f8b9680).into()), element_selected: Some(rgba(0x837e8b80).into()), - text: Some(rgba(0x5a5462ff).into()), + text: Some(rgba(0x19171cff).into()), text_muted: Some(rgba(0x7e7987ff).into()), text_placeholder: Some(rgba(0x7e7987ff).into()), text_disabled: Some(rgba(0x19171cff).into()), @@ -3626,7 +3626,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x252020ff).into()), element_hover: Some(rgba(0x564e4e80).into()), element_selected: Some(rgba(0x60585880).into()), - text: Some(rgba(0x898383ff).into()), + text: Some(rgba(0xf4ececff).into()), text_muted: Some(rgba(0x655d5dff).into()), text_placeholder: Some(rgba(0x655d5dff).into()), text_disabled: Some(rgba(0xf4ececff).into()), @@ -3986,7 +3986,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x252025ff).into()), element_hover: Some(rgba(0x675b6780).into()), element_selected: Some(rgba(0x72647280).into()), - text: Some(rgba(0xa99aa9ff).into()), + text: Some(rgba(0xf7f3f7ff).into()), text_muted: Some(rgba(0x776977ff).into()), text_placeholder: Some(rgba(0x776977ff).into()), text_disabled: Some(rgba(0xf7f3f7ff).into()), @@ -4346,7 +4346,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x1c2529ff).into()), element_hover: Some(rgba(0x4f6b7880).into()), element_selected: Some(rgba(0x57768580).into()), - text: Some(rgba(0x7ca0b3ff).into()), + text: Some(rgba(0xebf8ffff).into()), text_muted: Some(rgba(0x5a7b8bff).into()), text_placeholder: Some(rgba(0x5a7b8bff).into()), text_disabled: Some(rgba(0xebf8ffff).into()), @@ -4706,7 +4706,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xe9e6e4ff).into()), element_hover: Some(rgba(0xaaa3a180).into()), element_selected: Some(rgba(0xa1999680).into()), - text: Some(rgba(0x6a6360ff).into()), + text: Some(rgba(0x1b1918ff).into()), text_muted: Some(rgba(0x9c9491ff).into()), text_placeholder: Some(rgba(0x9c9491ff).into()), text_disabled: Some(rgba(0x1b1918ff).into()), @@ -5066,7 +5066,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xeeebd7ff).into()), element_hover: Some(rgba(0xa8a48e80).into()), element_selected: Some(rgba(0x9e9a8580).into()), - text: Some(rgba(0x706d5fff).into()), + text: Some(rgba(0x20201dff).into()), text_muted: Some(rgba(0x999580ff).into()), text_placeholder: Some(rgba(0x999580ff).into()), text_disabled: Some(rgba(0x20201dff).into()), @@ -5426,7 +5426,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xebe3e3ff).into()), element_hover: Some(rgba(0x8e898980).into()), element_selected: Some(rgba(0x837c7c80).into()), - text: Some(rgba(0x5a5252ff).into()), + text: Some(rgba(0x1b1818ff).into()), text_muted: Some(rgba(0x7e7777ff).into()), text_placeholder: Some(rgba(0x7e7777ff).into()), text_disabled: Some(rgba(0x1b1818ff).into()), @@ -5786,7 +5786,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xdaeedaff).into()), element_hover: Some(rgba(0x8ea88e80).into()), element_selected: Some(rgba(0x859e8580).into()), - text: Some(rgba(0x5f705fff).into()), + text: Some(rgba(0x131513ff).into()), text_muted: Some(rgba(0x809980ff).into()), text_placeholder: Some(rgba(0x809980ff).into()), text_disabled: Some(rgba(0x131513ff).into()), @@ -6146,7 +6146,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0x1f2621ff).into()), element_hover: Some(rgba(0x505e5580).into()), element_selected: Some(rgba(0x5a685f80).into()), - text: Some(rgba(0x859188ff).into()), + text: Some(rgba(0xecf4eeff).into()), text_muted: Some(rgba(0x5f6d64ff).into()), text_placeholder: Some(rgba(0x5f6d64ff).into()), text_disabled: Some(rgba(0xecf4eeff).into()), @@ -6506,7 +6506,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xe1d6e1ff).into()), element_hover: Some(rgba(0xad9dad80).into()), element_selected: Some(rgba(0xa394a380).into()), - text: Some(rgba(0x6b5e6bff).into()), + text: Some(rgba(0x1b181bff).into()), text_muted: Some(rgba(0x9e8f9eff).into()), text_placeholder: Some(rgba(0x9e8f9eff).into()), text_disabled: Some(rgba(0x1b181bff).into()), @@ -6866,7 +6866,7 @@ pub fn atelier() -> UserThemeFamily { panel_background: Some(rgba(0xcdeaf9ff).into()), element_hover: Some(rgba(0x80a4b680).into()), element_selected: Some(rgba(0x769aad80).into()), - text: Some(rgba(0x526f7dff).into()), + text: Some(rgba(0x161b1dff).into()), text_muted: Some(rgba(0x7195a8ff).into()), text_placeholder: Some(rgba(0x7195a8ff).into()), text_disabled: Some(rgba(0x161b1dff).into()), diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index eb6ac40bce..45b6cea310 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -26,7 +26,7 @@ pub fn ayu() -> UserThemeFamily { panel_background: Some(rgba(0x1f2127ff).into()), element_hover: Some(rgba(0x3f404380).into()), element_selected: Some(rgba(0x50515280).into()), - text: Some(rgba(0x8a8986ff).into()), + text: Some(rgba(0xbfbdb6ff).into()), text_muted: Some(rgba(0x58595aff).into()), text_placeholder: Some(rgba(0x58595aff).into()), text_disabled: Some(rgba(0xbfbdb6ff).into()), @@ -365,7 +365,7 @@ pub fn ayu() -> UserThemeFamily { panel_background: Some(rgba(0xececedff).into()), element_hover: Some(rgba(0xcfd1d280).into()), element_selected: Some(rgba(0xc0c2c480).into()), - text: Some(rgba(0x8c8f93ff).into()), + text: Some(rgba(0x5c6166ff).into()), text_muted: Some(rgba(0xb9bbbdff).into()), text_placeholder: Some(rgba(0xb9bbbdff).into()), text_disabled: Some(rgba(0x5c6166ff).into()), @@ -704,7 +704,7 @@ pub fn ayu() -> UserThemeFamily { panel_background: Some(rgba(0x353944ff).into()), element_hover: Some(rgba(0x53565d80).into()), element_selected: Some(rgba(0x63656a80).into()), - text: Some(rgba(0x9a9a98ff).into()), + text: Some(rgba(0xcccac2ff).into()), text_muted: Some(rgba(0x6b6d71ff).into()), text_placeholder: Some(rgba(0x6b6d71ff).into()), text_disabled: Some(rgba(0xcccac2ff).into()), diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 2dcf717c47..8b85ff2854 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -26,7 +26,7 @@ pub fn gruvbox() -> UserThemeFamily { panel_background: Some(rgba(0xecddb5ff).into()), element_hover: Some(rgba(0xc9b99a80).into()), element_selected: Some(rgba(0xb5a68e80).into()), - text: Some(rgba(0x5f5650ff).into()), + text: Some(rgba(0x282828ff).into()), text_muted: Some(rgba(0xad9e87ff).into()), text_placeholder: Some(rgba(0xad9e87ff).into()), text_disabled: Some(rgba(0x282828ff).into()), @@ -372,7 +372,7 @@ pub fn gruvbox() -> UserThemeFamily { panel_background: Some(rgba(0x3b3735ff).into()), element_hover: Some(rgba(0x5b534d80).into()), element_selected: Some(rgba(0x6e635a80).into()), - text: Some(rgba(0xc5b597ff).into()), + text: Some(rgba(0xfbf1c7ff).into()), text_muted: Some(rgba(0x776b61ff).into()), text_placeholder: Some(rgba(0x776b61ff).into()), text_disabled: Some(rgba(0xfbf1c7ff).into()), @@ -718,7 +718,7 @@ pub fn gruvbox() -> UserThemeFamily { panel_background: Some(rgba(0xecddb4ff).into()), element_hover: Some(rgba(0xc9b99a80).into()), element_selected: Some(rgba(0xb5a68e80).into()), - text: Some(rgba(0x5f5650ff).into()), + text: Some(rgba(0x282828ff).into()), text_muted: Some(rgba(0xad9e87ff).into()), text_placeholder: Some(rgba(0xad9e87ff).into()), text_disabled: Some(rgba(0x282828ff).into()), @@ -1064,7 +1064,7 @@ pub fn gruvbox() -> UserThemeFamily { panel_background: Some(rgba(0x3a3735ff).into()), element_hover: Some(rgba(0x5b534d80).into()), element_selected: Some(rgba(0x6e635a80).into()), - text: Some(rgba(0xc5b597ff).into()), + text: Some(rgba(0xfbf1c7ff).into()), text_muted: Some(rgba(0x776b61ff).into()), text_placeholder: Some(rgba(0x776b61ff).into()), text_disabled: Some(rgba(0xfbf1c7ff).into()), @@ -1410,7 +1410,7 @@ pub fn gruvbox() -> UserThemeFamily { panel_background: Some(rgba(0xecdcb3ff).into()), element_hover: Some(rgba(0xc9b99a80).into()), element_selected: Some(rgba(0xb5a68e80).into()), - text: Some(rgba(0x5f5650ff).into()), + text: Some(rgba(0x282828ff).into()), text_muted: Some(rgba(0xad9e87ff).into()), text_placeholder: Some(rgba(0xad9e87ff).into()), text_disabled: Some(rgba(0x282828ff).into()), @@ -1756,7 +1756,7 @@ pub fn gruvbox() -> UserThemeFamily { panel_background: Some(rgba(0x393634ff).into()), element_hover: Some(rgba(0x5b534d80).into()), element_selected: Some(rgba(0x6e635a80).into()), - text: Some(rgba(0xc5b597ff).into()), + text: Some(rgba(0xfbf1c7ff).into()), text_muted: Some(rgba(0x776b61ff).into()), text_placeholder: Some(rgba(0x776b61ff).into()), text_disabled: Some(rgba(0xfbf1c7ff).into()), diff --git a/crates/theme2/src/themes/one.rs b/crates/theme2/src/themes/one.rs index 3a20146be1..8de6c06de6 100644 --- a/crates/theme2/src/themes/one.rs +++ b/crates/theme2/src/themes/one.rs @@ -26,7 +26,7 @@ pub fn one() -> UserThemeFamily { panel_background: Some(rgba(0xebebecff).into()), element_hover: Some(rgba(0xc9c9ca80).into()), element_selected: Some(rgba(0xafafaf80).into()), - text: Some(rgba(0x7f8188ff).into()), + text: Some(rgba(0x383a41ff).into()), text_muted: Some(rgba(0xa7a7a8ff).into()), text_placeholder: Some(rgba(0xa7a7a8ff).into()), text_disabled: Some(rgba(0x383a41ff).into()), @@ -372,7 +372,7 @@ pub fn one() -> UserThemeFamily { panel_background: Some(rgba(0x2f343eff).into()), element_hover: Some(rgba(0x464b5780).into()), element_selected: Some(rgba(0x4f545e80).into()), - text: Some(rgba(0x838994ff).into()), + text: Some(rgba(0xc8ccd4ff).into()), text_muted: Some(rgba(0x545862ff).into()), text_placeholder: Some(rgba(0x545862ff).into()), text_disabled: Some(rgba(0xc8ccd4ff).into()), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index 1dcf523a74..5f8ed063a3 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -26,7 +26,7 @@ pub fn rose_pine() -> UserThemeFamily { panel_background: Some(rgba(0xfef9f2ff).into()), element_hover: Some(rgba(0xdcd6d580).into()), element_selected: Some(rgba(0xc1bac180).into()), - text: Some(rgba(0x706c8cff).into()), + text: Some(rgba(0x575279ff).into()), text_muted: Some(rgba(0xb1abb5ff).into()), text_placeholder: Some(rgba(0xb1abb5ff).into()), text_disabled: Some(rgba(0x575279ff).into()), @@ -379,7 +379,7 @@ pub fn rose_pine() -> UserThemeFamily { panel_background: Some(rgba(0x28253cff).into()), element_hover: Some(rgba(0x504c6880).into()), element_selected: Some(rgba(0x45415d80).into()), - text: Some(rgba(0x85819eff).into()), + text: Some(rgba(0xe0def4ff).into()), text_muted: Some(rgba(0x3a3653ff).into()), text_placeholder: Some(rgba(0x3a3653ff).into()), text_disabled: Some(rgba(0xe0def4ff).into()), @@ -732,7 +732,7 @@ pub fn rose_pine() -> UserThemeFamily { panel_background: Some(rgba(0x1d1b2aff).into()), element_hover: Some(rgba(0x423f5580).into()), element_selected: Some(rgba(0x47445b80).into()), - text: Some(rgba(0x75718eff).into()), + text: Some(rgba(0xe0def4ff).into()), text_muted: Some(rgba(0x3b384fff).into()), text_placeholder: Some(rgba(0x3b384fff).into()), text_disabled: Some(rgba(0xe0def4ff).into()), diff --git a/crates/theme2/src/themes/sandcastle.rs b/crates/theme2/src/themes/sandcastle.rs index c0bd53b2d6..9b6828d82f 100644 --- a/crates/theme2/src/themes/sandcastle.rs +++ b/crates/theme2/src/themes/sandcastle.rs @@ -25,7 +25,7 @@ pub fn sandcastle() -> UserThemeFamily { panel_background: Some(rgba(0x2b3039ff).into()), element_hover: Some(rgba(0x3d435080).into()), element_selected: Some(rgba(0x57535380).into()), - text: Some(rgba(0xa69782ff).into()), + text: Some(rgba(0xfdf4c1ff).into()), text_muted: Some(rgba(0x645b54ff).into()), text_placeholder: Some(rgba(0x645b54ff).into()), text_disabled: Some(rgba(0xfdf4c1ff).into()), diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index e358537dfb..7aece1c6c4 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -26,7 +26,7 @@ pub fn solarized() -> UserThemeFamily { panel_background: Some(rgba(0xf3eddaff).into()), element_hover: Some(rgba(0x9faaa880).into()), element_selected: Some(rgba(0x7f919480).into()), - text: Some(rgba(0x34555eff).into()), + text: Some(rgba(0x002b36ff).into()), text_muted: Some(rgba(0x788b8fff).into()), text_placeholder: Some(rgba(0x788b8fff).into()), text_disabled: Some(rgba(0x002b36ff).into()), @@ -365,7 +365,7 @@ pub fn solarized() -> UserThemeFamily { panel_background: Some(rgba(0x04313cff).into()), element_hover: Some(rgba(0x2b4f5880).into()), element_selected: Some(rgba(0x566d7480).into()), - text: Some(rgba(0x93a1a1ff).into()), + text: Some(rgba(0xfdf6e3ff).into()), text_muted: Some(rgba(0x5f757dff).into()), text_placeholder: Some(rgba(0x5f757dff).into()), text_disabled: Some(rgba(0xfdf6e3ff).into()), diff --git a/crates/theme2/src/themes/summercamp.rs b/crates/theme2/src/themes/summercamp.rs index eab403fe79..6d36acd2ed 100644 --- a/crates/theme2/src/themes/summercamp.rs +++ b/crates/theme2/src/themes/summercamp.rs @@ -25,7 +25,7 @@ pub fn summercamp() -> UserThemeFamily { panel_background: Some(rgba(0x231f16ff).into()), element_hover: Some(rgba(0x312d2180).into()), element_selected: Some(rgba(0x39342780).into()), - text: Some(rgba(0x736e55ff).into()), + text: Some(rgba(0xf8f5deff).into()), text_muted: Some(rgba(0x3d382aff).into()), text_placeholder: Some(rgba(0x3d382aff).into()), text_disabled: Some(rgba(0xf8f5deff).into()), diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs index 87318199cf..2ce98a497b 100644 --- a/crates/theme_importer/src/zed1/converter.rs +++ b/crates/theme_importer/src/zed1/converter.rs @@ -116,7 +116,7 @@ impl Zed1ThemeConverter { .container .background_color .map(zed1_color_to_hsla), - text: convert(self.theme.project_panel.entry.default_style().text.color), + text: convert(self.theme.collab_panel.channel_name.text.color), text_muted: convert(active_tab.description.text.color), text_accent: convert(status_bar.panel_buttons.button.active_state().icon_color), text_disabled: convert(status_bar.panel_buttons.button.disabled_style().icon_color), From 9cb613245e319d996f6918ed119bd4c2aef43c57 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 21:18:43 -0500 Subject: [PATCH 315/644] Adjust border colors --- crates/theme2/src/themes/andromeda.rs | 4 +- crates/theme2/src/themes/atelier.rs | 80 ++++++++++----------- crates/theme2/src/themes/ayu.rs | 12 ++-- crates/theme2/src/themes/gruvbox.rs | 24 +++---- crates/theme2/src/themes/one.rs | 8 +-- crates/theme2/src/themes/rose_pine.rs | 12 ++-- crates/theme2/src/themes/sandcastle.rs | 4 +- crates/theme2/src/themes/solarized.rs | 8 +-- crates/theme2/src/themes/summercamp.rs | 4 +- crates/theme_importer/src/zed1/converter.rs | 6 +- 10 files changed, 80 insertions(+), 82 deletions(-) diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index 2130653e57..a7cf529222 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -18,8 +18,8 @@ pub fn andromeda() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x2b2f39ff).into()), - border_variant: Some(rgba(0x2b2f39ff).into()), + border: Some(rgba(0x252931ff).into()), + border_variant: Some(rgba(0x21232aff).into()), elevated_surface_background: Some(rgba(0x262a33ff).into()), background: Some(rgba(0x262a33ff).into()), panel_background: Some(rgba(0x21242bff).into()), diff --git a/crates/theme2/src/themes/atelier.rs b/crates/theme2/src/themes/atelier.rs index 869fa44c0d..3a1f94c888 100644 --- a/crates/theme2/src/themes/atelier.rs +++ b/crates/theme2/src/themes/atelier.rs @@ -19,8 +19,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x969585ff).into()), - border_variant: Some(rgba(0x969585ff).into()), + border: Some(rgba(0xd1d0c6ff).into()), + border_variant: Some(rgba(0xedece5ff).into()), elevated_surface_background: Some(rgba(0xc5c4b9ff).into()), background: Some(rgba(0xc5c4b9ff).into()), panel_background: Some(rgba(0xebeae3ff).into()), @@ -379,8 +379,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x665f5cff).into()), - border_variant: Some(rgba(0x665f5cff).into()), + border: Some(rgba(0x3b3431ff).into()), + border_variant: Some(rgba(0x251f1dff).into()), elevated_surface_background: Some(rgba(0x443c39ff).into()), background: Some(rgba(0x443c39ff).into()), panel_background: Some(rgba(0x27211eff).into()), @@ -739,8 +739,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x8b968eff).into()), - border_variant: Some(rgba(0x8b968eff).into()), + border: Some(rgba(0xc8d1cbff).into()), + border_variant: Some(rgba(0xe5ede7ff).into()), elevated_surface_background: Some(rgba(0xbcc5bfff).into()), background: Some(rgba(0xbcc5bfff).into()), panel_background: Some(rgba(0xe3ebe6ff).into()), @@ -1099,8 +1099,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x56505eff).into()), - border_variant: Some(rgba(0x56505eff).into()), + border: Some(rgba(0x332f38ff).into()), + border_variant: Some(rgba(0x201e24ff).into()), elevated_surface_background: Some(rgba(0x3a353fff).into()), background: Some(rgba(0x3a353fff).into()), panel_background: Some(rgba(0x221f26ff).into()), @@ -1459,8 +1459,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x5d5c4cff).into()), - border_variant: Some(rgba(0x5d5c4cff).into()), + border: Some(rgba(0x3c3b31ff).into()), + border_variant: Some(rgba(0x2a2922ff).into()), elevated_surface_background: Some(rgba(0x424136ff).into()), background: Some(rgba(0x424136ff).into()), panel_background: Some(rgba(0x2c2b23ff).into()), @@ -1819,8 +1819,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x5c6485ff).into()), - border_variant: Some(rgba(0x5c6485ff).into()), + border: Some(rgba(0x363f62ff).into()), + border_variant: Some(rgba(0x252d4fff).into()), elevated_surface_background: Some(rgba(0x3e4769ff).into()), background: Some(rgba(0x3e4769ff).into()), panel_background: Some(rgba(0x262f51ff).into()), @@ -2179,8 +2179,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x9a9fb6ff).into()), - border_variant: Some(rgba(0x9a9fb6ff).into()), + border: Some(rgba(0xccd0e1ff).into()), + border_variant: Some(rgba(0xe9ebf7ff).into()), elevated_surface_background: Some(rgba(0xc2c6d9ff).into()), background: Some(rgba(0xc2c6d9ff).into()), panel_background: Some(rgba(0xe5e8f5ff).into()), @@ -2539,8 +2539,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x6c695cff).into()), - border_variant: Some(rgba(0x6c695cff).into()), + border: Some(rgba(0x3b3933ff).into()), + border_variant: Some(rgba(0x252521ff).into()), elevated_surface_background: Some(rgba(0x45433bff).into()), background: Some(rgba(0x45433bff).into()), panel_background: Some(rgba(0x262622ff).into()), @@ -2899,8 +2899,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x5c6c5cff).into()), - border_variant: Some(rgba(0x5c6c5cff).into()), + border: Some(rgba(0x333b33ff).into()), + border_variant: Some(rgba(0x1d201dff).into()), elevated_surface_background: Some(rgba(0x3b453bff).into()), background: Some(rgba(0x3b453bff).into()), panel_background: Some(rgba(0x1f231fff).into()), @@ -3259,8 +3259,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x8f8b96ff).into()), - border_variant: Some(rgba(0x8f8b96ff).into()), + border: Some(rgba(0xcbc8d1ff).into()), + border_variant: Some(rgba(0xe8e5edff).into()), elevated_surface_background: Some(rgba(0xbfbcc5ff).into()), background: Some(rgba(0xbfbcc5ff).into()), panel_background: Some(rgba(0xe6e3ebff).into()), @@ -3619,8 +3619,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x564e4eff).into()), - border_variant: Some(rgba(0x564e4eff).into()), + border: Some(rgba(0x352f2fff).into()), + border_variant: Some(rgba(0x231f1fff).into()), elevated_surface_background: Some(rgba(0x3b3535ff).into()), background: Some(rgba(0x3b3535ff).into()), panel_background: Some(rgba(0x252020ff).into()), @@ -3979,8 +3979,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x675b67ff).into()), - border_variant: Some(rgba(0x675b67ff).into()), + border: Some(rgba(0x393239ff).into()), + border_variant: Some(rgba(0x231e23ff).into()), elevated_surface_background: Some(rgba(0x433a43ff).into()), background: Some(rgba(0x433a43ff).into()), panel_background: Some(rgba(0x252025ff).into()), @@ -4339,8 +4339,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x4f6b78ff).into()), - border_variant: Some(rgba(0x4f6b78ff).into()), + border: Some(rgba(0x2c3b42ff).into()), + border_variant: Some(rgba(0x1b2327ff).into()), elevated_surface_background: Some(rgba(0x33444dff).into()), background: Some(rgba(0x33444dff).into()), panel_background: Some(rgba(0x1c2529ff).into()), @@ -4699,8 +4699,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xaaa3a1ff).into()), - border_variant: Some(rgba(0xaaa3a1ff).into()), + border: Some(rgba(0xd6d1cfff).into()), + border_variant: Some(rgba(0xebe8e6ff).into()), elevated_surface_background: Some(rgba(0xcdc8c6ff).into()), background: Some(rgba(0xcdc8c6ff).into()), panel_background: Some(rgba(0xe9e6e4ff).into()), @@ -5059,8 +5059,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xa8a48eff).into()), - border_variant: Some(rgba(0xa8a48eff).into()), + border: Some(rgba(0xd7d3beff).into()), + border_variant: Some(rgba(0xf2eedcff).into()), elevated_surface_background: Some(rgba(0xcecab4ff).into()), background: Some(rgba(0xcecab4ff).into()), panel_background: Some(rgba(0xeeebd7ff).into()), @@ -5419,8 +5419,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x8e8989ff).into()), - border_variant: Some(rgba(0x8e8989ff).into()), + border: Some(rgba(0xcfc7c7ff).into()), + border_variant: Some(rgba(0xede5e5ff).into()), elevated_surface_background: Some(rgba(0xc1bbbbff).into()), background: Some(rgba(0xc1bbbbff).into()), panel_background: Some(rgba(0xebe3e3ff).into()), @@ -5779,8 +5779,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x8ea88eff).into()), - border_variant: Some(rgba(0x8ea88eff).into()), + border: Some(rgba(0xbed7beff).into()), + border_variant: Some(rgba(0xdff0dfff).into()), elevated_surface_background: Some(rgba(0xb4ceb4ff).into()), background: Some(rgba(0xb4ceb4ff).into()), panel_background: Some(rgba(0xdaeedaff).into()), @@ -6139,8 +6139,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x505e55ff).into()), - border_variant: Some(rgba(0x505e55ff).into()), + border: Some(rgba(0x2f3832ff).into()), + border_variant: Some(rgba(0x1e2420ff).into()), elevated_surface_background: Some(rgba(0x353f39ff).into()), background: Some(rgba(0x353f39ff).into()), panel_background: Some(rgba(0x1f2621ff).into()), @@ -6499,8 +6499,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xad9dadff).into()), - border_variant: Some(rgba(0xad9dadff).into()), + border: Some(rgba(0xcdbecdff).into()), + border_variant: Some(rgba(0xe5dce5ff).into()), elevated_surface_background: Some(rgba(0xc6b8c6ff).into()), background: Some(rgba(0xc6b8c6ff).into()), panel_background: Some(rgba(0xe1d6e1ff).into()), @@ -6859,8 +6859,8 @@ pub fn atelier() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x80a4b6ff).into()), - border_variant: Some(rgba(0x80a4b6ff).into()), + border: Some(rgba(0xb0d3e5ff).into()), + border_variant: Some(rgba(0xd3edfaff).into()), elevated_surface_background: Some(rgba(0xa6cadcff).into()), background: Some(rgba(0xa6cadcff).into()), panel_background: Some(rgba(0xcdeaf9ff).into()), diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index 45b6cea310..deab32b812 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -19,8 +19,8 @@ pub fn ayu() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x3f4043ff).into()), - border_variant: Some(rgba(0x3f4043ff).into()), + border: Some(rgba(0x2d2f34ff).into()), + border_variant: Some(rgba(0x1b1e24ff).into()), elevated_surface_background: Some(rgba(0x313337ff).into()), background: Some(rgba(0x313337ff).into()), panel_background: Some(rgba(0x1f2127ff).into()), @@ -358,8 +358,8 @@ pub fn ayu() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xcfd1d2ff).into()), - border_variant: Some(rgba(0xcfd1d2ff).into()), + border: Some(rgba(0xdfe0e1ff).into()), + border_variant: Some(rgba(0xefeff0ff).into()), elevated_surface_background: Some(rgba(0xdcdddeff).into()), background: Some(rgba(0xdcdddeff).into()), panel_background: Some(rgba(0xececedff).into()), @@ -697,8 +697,8 @@ pub fn ayu() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x53565dff).into()), - border_variant: Some(rgba(0x53565dff).into()), + border: Some(rgba(0x43464fff).into()), + border_variant: Some(rgba(0x323641ff).into()), elevated_surface_background: Some(rgba(0x464a52ff).into()), background: Some(rgba(0x464a52ff).into()), panel_background: Some(rgba(0x353944ff).into()), diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 8b85ff2854..8512706fd4 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -19,8 +19,8 @@ pub fn gruvbox() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xc9b99aff).into()), - border_variant: Some(rgba(0xc9b99aff).into()), + border: Some(rgba(0xddcca7ff).into()), + border_variant: Some(rgba(0xefe2bcff).into()), elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), background: Some(rgba(0xd9c8a4ff).into()), panel_background: Some(rgba(0xecddb5ff).into()), @@ -365,8 +365,8 @@ pub fn gruvbox() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x5b534dff).into()), - border_variant: Some(rgba(0x5b534dff).into()), + border: Some(rgba(0x494340ff).into()), + border_variant: Some(rgba(0x393634ff).into()), elevated_surface_background: Some(rgba(0x4c4642ff).into()), background: Some(rgba(0x4c4642ff).into()), panel_background: Some(rgba(0x3b3735ff).into()), @@ -711,8 +711,8 @@ pub fn gruvbox() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xc9b99aff).into()), - border_variant: Some(rgba(0xc9b99aff).into()), + border: Some(rgba(0xddcca7ff).into()), + border_variant: Some(rgba(0xefe1b8ff).into()), elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), background: Some(rgba(0xd9c8a4ff).into()), panel_background: Some(rgba(0xecddb4ff).into()), @@ -1057,8 +1057,8 @@ pub fn gruvbox() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x5b534dff).into()), - border_variant: Some(rgba(0x5b534dff).into()), + border: Some(rgba(0x494340ff).into()), + border_variant: Some(rgba(0x373432ff).into()), elevated_surface_background: Some(rgba(0x4c4642ff).into()), background: Some(rgba(0x4c4642ff).into()), panel_background: Some(rgba(0x3a3735ff).into()), @@ -1403,8 +1403,8 @@ pub fn gruvbox() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xc9b99aff).into()), - border_variant: Some(rgba(0xc9b99aff).into()), + border: Some(rgba(0xddcca7ff).into()), + border_variant: Some(rgba(0xeddeb5ff).into()), elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), background: Some(rgba(0xd9c8a4ff).into()), panel_background: Some(rgba(0xecdcb3ff).into()), @@ -1749,8 +1749,8 @@ pub fn gruvbox() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x5b534dff).into()), - border_variant: Some(rgba(0x5b534dff).into()), + border: Some(rgba(0x494340ff).into()), + border_variant: Some(rgba(0x343130ff).into()), elevated_surface_background: Some(rgba(0x4c4642ff).into()), background: Some(rgba(0x4c4642ff).into()), panel_background: Some(rgba(0x393634ff).into()), diff --git a/crates/theme2/src/themes/one.rs b/crates/theme2/src/themes/one.rs index 8de6c06de6..dcd90bf1af 100644 --- a/crates/theme2/src/themes/one.rs +++ b/crates/theme2/src/themes/one.rs @@ -19,8 +19,8 @@ pub fn one() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xc9c9caff).into()), - border_variant: Some(rgba(0xc9c9caff).into()), + border: Some(rgba(0xdfdfe0ff).into()), + border_variant: Some(rgba(0xeeeeeeff).into()), elevated_surface_background: Some(rgba(0xdcdcddff).into()), background: Some(rgba(0xdcdcddff).into()), panel_background: Some(rgba(0xebebecff).into()), @@ -365,8 +365,8 @@ pub fn one() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x464b57ff).into()), - border_variant: Some(rgba(0x464b57ff).into()), + border: Some(rgba(0x363c46ff).into()), + border_variant: Some(rgba(0x2e333cff).into()), elevated_surface_background: Some(rgba(0x3b414dff).into()), background: Some(rgba(0x3b414dff).into()), panel_background: Some(rgba(0x2f343eff).into()), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index 5f8ed063a3..a08618ca6a 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -19,8 +19,8 @@ pub fn rose_pine() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0xdcd6d5ff).into()), - border_variant: Some(rgba(0xdcd6d5ff).into()), + border: Some(rgba(0xe5e0dfff).into()), + border_variant: Some(rgba(0xfdf8f1ff).into()), elevated_surface_background: Some(rgba(0xdcd8d8ff).into()), background: Some(rgba(0xdcd8d8ff).into()), panel_background: Some(rgba(0xfef9f2ff).into()), @@ -372,8 +372,8 @@ pub fn rose_pine() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x504c68ff).into()), - border_variant: Some(rgba(0x504c68ff).into()), + border: Some(rgba(0x322f48ff).into()), + border_variant: Some(rgba(0x27243bff).into()), elevated_surface_background: Some(rgba(0x38354eff).into()), background: Some(rgba(0x38354eff).into()), panel_background: Some(rgba(0x28253cff).into()), @@ -725,8 +725,8 @@ pub fn rose_pine() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x423f55ff).into()), - border_variant: Some(rgba(0x423f55ff).into()), + border: Some(rgba(0x232132ff).into()), + border_variant: Some(rgba(0x1c1a29ff).into()), elevated_surface_background: Some(rgba(0x292739ff).into()), background: Some(rgba(0x292739ff).into()), panel_background: Some(rgba(0x1d1b2aff).into()), diff --git a/crates/theme2/src/themes/sandcastle.rs b/crates/theme2/src/themes/sandcastle.rs index 9b6828d82f..38b6e04665 100644 --- a/crates/theme2/src/themes/sandcastle.rs +++ b/crates/theme2/src/themes/sandcastle.rs @@ -18,8 +18,8 @@ pub fn sandcastle() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x3d4350ff).into()), - border_variant: Some(rgba(0x3d4350ff).into()), + border: Some(rgba(0x313741ff).into()), + border_variant: Some(rgba(0x2a2f38ff).into()), elevated_surface_background: Some(rgba(0x333944ff).into()), background: Some(rgba(0x333944ff).into()), panel_background: Some(rgba(0x2b3039ff).into()), diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index 7aece1c6c4..a09ca0e0cc 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -19,8 +19,8 @@ pub fn solarized() -> UserThemeFamily { appearance: Appearance::Light, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x9faaa8ff).into()), - border_variant: Some(rgba(0x9faaa8ff).into()), + border: Some(rgba(0xdcdacbff).into()), + border_variant: Some(rgba(0xf5eedbff).into()), elevated_surface_background: Some(rgba(0xcfd0c4ff).into()), background: Some(rgba(0xcfd0c4ff).into()), panel_background: Some(rgba(0xf3eddaff).into()), @@ -358,8 +358,8 @@ pub fn solarized() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x2b4f58ff).into()), - border_variant: Some(rgba(0x2b4f58ff).into()), + border: Some(rgba(0x063541ff).into()), + border_variant: Some(rgba(0x032f3bff).into()), elevated_surface_background: Some(rgba(0x083743ff).into()), background: Some(rgba(0x083743ff).into()), panel_background: Some(rgba(0x04313cff).into()), diff --git a/crates/theme2/src/themes/summercamp.rs b/crates/theme2/src/themes/summercamp.rs index 6d36acd2ed..c27d8369c3 100644 --- a/crates/theme2/src/themes/summercamp.rs +++ b/crates/theme2/src/themes/summercamp.rs @@ -18,8 +18,8 @@ pub fn summercamp() -> UserThemeFamily { appearance: Appearance::Dark, styles: UserThemeStylesRefinement { colors: ThemeColorsRefinement { - border: Some(rgba(0x312d21ff).into()), - border_variant: Some(rgba(0x312d21ff).into()), + border: Some(rgba(0x29251bff).into()), + border_variant: Some(rgba(0x221e15ff).into()), elevated_surface_background: Some(rgba(0x2a261cff).into()), background: Some(rgba(0x2a261cff).into()), panel_background: Some(rgba(0x231f16ff).into()), diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs index 2ce98a497b..6543f21635 100644 --- a/crates/theme_importer/src/zed1/converter.rs +++ b/crates/theme_importer/src/zed1/converter.rs @@ -99,11 +99,9 @@ impl Zed1ThemeConverter { let scrollbar = &self.theme.editor.scrollbar; let terminal = &self.theme.terminal; - let title_bar_border = convert(title_bar.container.border.color); - Ok(ThemeColorsRefinement { - border: title_bar_border, - border_variant: title_bar_border, + border: convert(active_tab.container.border.color), + border_variant: convert(toolbar.container.border.color), background: convert(self.theme.workspace.background), elevated_surface_background: picker.container.background_color.map(zed1_color_to_hsla), title_bar_background: title_bar.container.background_color.map(zed1_color_to_hsla), From bdb89d470034fe41d4d6afda57375c3781dd8375 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 21:25:31 -0500 Subject: [PATCH 316/644] Render tab bar tools as muted --- crates/workspace2/src/pane.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 893c522222..bcf36dfe18 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -381,6 +381,7 @@ impl Pane { .child( IconButton::new("plus", Icon::Plus) .icon_size(IconSize::Small) + .icon_color(Color::Muted) .on_click(cx.listener(|pane, _, cx| { let menu = ContextMenu::build(cx, |menu, _| { menu.action("New File", NewFile.boxed_clone()) @@ -402,6 +403,7 @@ impl Pane { .child( IconButton::new("split", Icon::Split) .icon_size(IconSize::Small) + .icon_color(Color::Muted) .on_click(cx.listener(|pane, _, cx| { let menu = ContextMenu::build(cx, |menu, _| { menu.action("Split Right", SplitRight.boxed_clone()) @@ -422,6 +424,7 @@ impl Pane { let zoomed = pane.is_zoomed(); IconButton::new("toggle_zoom", Icon::Maximize) .icon_size(IconSize::Small) + .icon_color(Color::Muted) .selected(zoomed) .selected_icon(Icon::Minimize) .on_click(cx.listener(|pane, _, cx| { From 04d26353d281097b68556808812181c45927f1f5 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 21:25:45 -0500 Subject: [PATCH 317/644] Adjust muted text colors --- crates/theme2/src/themes/andromeda.rs | 2 +- crates/theme2/src/themes/atelier.rs | 40 ++++++++++----------- crates/theme2/src/themes/ayu.rs | 6 ++-- crates/theme2/src/themes/gruvbox.rs | 12 +++---- crates/theme2/src/themes/one.rs | 4 +-- crates/theme2/src/themes/rose_pine.rs | 6 ++-- crates/theme2/src/themes/sandcastle.rs | 2 +- crates/theme2/src/themes/solarized.rs | 4 +-- crates/theme2/src/themes/summercamp.rs | 2 +- crates/theme_importer/src/zed1/converter.rs | 2 +- 10 files changed, 40 insertions(+), 40 deletions(-) diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index a7cf529222..fd61f9b482 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -26,7 +26,7 @@ pub fn andromeda() -> UserThemeFamily { element_hover: Some(rgba(0x2b2f3980).into()), element_selected: Some(rgba(0x383b4580).into()), text: Some(rgba(0xf7f7f8ff).into()), - text_muted: Some(rgba(0x474a53ff).into()), + text_muted: Some(rgba(0xaca8aeff).into()), text_placeholder: Some(rgba(0x474a53ff).into()), text_disabled: Some(rgba(0xf7f7f8ff).into()), text_accent: Some(rgba(0x11a793ff).into()), diff --git a/crates/theme2/src/themes/atelier.rs b/crates/theme2/src/themes/atelier.rs index 3a1f94c888..6c942d5b4c 100644 --- a/crates/theme2/src/themes/atelier.rs +++ b/crates/theme2/src/themes/atelier.rs @@ -27,7 +27,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x96958580).into()), element_selected: Some(rgba(0x8b8a7880).into()), text: Some(rgba(0x22221bff).into()), - text_muted: Some(rgba(0x878573ff).into()), + text_muted: Some(rgba(0x61604fff).into()), text_placeholder: Some(rgba(0x878573ff).into()), text_disabled: Some(rgba(0x22221bff).into()), text_accent: Some(rgba(0x38a166ff).into()), @@ -387,7 +387,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x665f5c80).into()), element_selected: Some(rgba(0x71696680).into()), text: Some(rgba(0xf1efeeff).into()), - text_muted: Some(rgba(0x766e6bff).into()), + text_muted: Some(rgba(0xa79f9dff).into()), text_placeholder: Some(rgba(0x766e6bff).into()), text_disabled: Some(rgba(0xf1efeeff).into()), text_accent: Some(rgba(0x417ee6ff).into()), @@ -747,7 +747,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x8b968e80).into()), element_selected: Some(rgba(0x7e8b8280).into()), text: Some(rgba(0x171c19ff).into()), - text_muted: Some(rgba(0x79877dff).into()), + text_muted: Some(rgba(0x546259ff).into()), text_placeholder: Some(rgba(0x79877dff).into()), text_disabled: Some(rgba(0x171c19ff).into()), text_accent: Some(rgba(0x488c90ff).into()), @@ -1107,7 +1107,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x56505e80).into()), element_selected: Some(rgba(0x605a6880).into()), text: Some(rgba(0xefecf4ff).into()), - text_muted: Some(rgba(0x655f6dff).into()), + text_muted: Some(rgba(0x898591ff).into()), text_placeholder: Some(rgba(0x655f6dff).into()), text_disabled: Some(rgba(0xefecf4ff).into()), text_accent: Some(rgba(0x576ddaff).into()), @@ -1467,7 +1467,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x5d5c4c80).into()), element_selected: Some(rgba(0x67665580).into()), text: Some(rgba(0xf4f3ecff).into()), - text_muted: Some(rgba(0x6c6b5aff).into()), + text_muted: Some(rgba(0x91907fff).into()), text_placeholder: Some(rgba(0x6c6b5aff).into()), text_disabled: Some(rgba(0xf4f3ecff).into()), text_accent: Some(rgba(0x37a166ff).into()), @@ -1827,7 +1827,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x5c648580).into()), element_selected: Some(rgba(0x666e8f80).into()), text: Some(rgba(0xf5f7ffff).into()), - text_muted: Some(rgba(0x6b7394ff).into()), + text_muted: Some(rgba(0x959bb2ff).into()), text_placeholder: Some(rgba(0x6b7394ff).into()), text_disabled: Some(rgba(0xf5f7ffff).into()), text_accent: Some(rgba(0x3e8fd0ff).into()), @@ -2187,7 +2187,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x9a9fb680).into()), element_selected: Some(rgba(0x8e94aa80).into()), text: Some(rgba(0x202746ff).into()), - text_muted: Some(rgba(0x898fa5ff).into()), + text_muted: Some(rgba(0x606889ff).into()), text_placeholder: Some(rgba(0x898fa5ff).into()), text_disabled: Some(rgba(0x202746ff).into()), text_accent: Some(rgba(0x3f8fd0ff).into()), @@ -2547,7 +2547,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x6c695c80).into()), element_selected: Some(rgba(0x77746480).into()), text: Some(rgba(0xfefbecff).into()), - text_muted: Some(rgba(0x7c7968ff).into()), + text_muted: Some(rgba(0xa4a08bff).into()), text_placeholder: Some(rgba(0x7c7968ff).into()), text_disabled: Some(rgba(0xfefbecff).into()), text_accent: Some(rgba(0x6684e0ff).into()), @@ -2907,7 +2907,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x5c6c5c80).into()), element_selected: Some(rgba(0x64776480).into()), text: Some(rgba(0xf4fbf4ff).into()), - text_muted: Some(rgba(0x687c68ff).into()), + text_muted: Some(rgba(0x8ba48bff).into()), text_placeholder: Some(rgba(0x687c68ff).into()), text_disabled: Some(rgba(0xf4fbf4ff).into()), text_accent: Some(rgba(0x3e62f4ff).into()), @@ -3267,7 +3267,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x8f8b9680).into()), element_selected: Some(rgba(0x837e8b80).into()), text: Some(rgba(0x19171cff).into()), - text_muted: Some(rgba(0x7e7987ff).into()), + text_muted: Some(rgba(0x5a5462ff).into()), text_placeholder: Some(rgba(0x7e7987ff).into()), text_disabled: Some(rgba(0x19171cff).into()), text_accent: Some(rgba(0x586ddaff).into()), @@ -3627,7 +3627,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x564e4e80).into()), element_selected: Some(rgba(0x60585880).into()), text: Some(rgba(0xf4ececff).into()), - text_muted: Some(rgba(0x655d5dff).into()), + text_muted: Some(rgba(0x898383ff).into()), text_placeholder: Some(rgba(0x655d5dff).into()), text_disabled: Some(rgba(0xf4ececff).into()), text_accent: Some(rgba(0x7272caff).into()), @@ -3987,7 +3987,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x675b6780).into()), element_selected: Some(rgba(0x72647280).into()), text: Some(rgba(0xf7f3f7ff).into()), - text_muted: Some(rgba(0x776977ff).into()), + text_muted: Some(rgba(0xa99aa9ff).into()), text_placeholder: Some(rgba(0x776977ff).into()), text_disabled: Some(rgba(0xf7f3f7ff).into()), text_accent: Some(rgba(0x526aebff).into()), @@ -4347,7 +4347,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x4f6b7880).into()), element_selected: Some(rgba(0x57768580).into()), text: Some(rgba(0xebf8ffff).into()), - text_muted: Some(rgba(0x5a7b8bff).into()), + text_muted: Some(rgba(0x7ca0b3ff).into()), text_placeholder: Some(rgba(0x5a7b8bff).into()), text_disabled: Some(rgba(0xebf8ffff).into()), text_accent: Some(rgba(0x277fadff).into()), @@ -4707,7 +4707,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0xaaa3a180).into()), element_selected: Some(rgba(0xa1999680).into()), text: Some(rgba(0x1b1918ff).into()), - text_muted: Some(rgba(0x9c9491ff).into()), + text_muted: Some(rgba(0x6a6360ff).into()), text_placeholder: Some(rgba(0x9c9491ff).into()), text_disabled: Some(rgba(0x1b1918ff).into()), text_accent: Some(rgba(0x417ee6ff).into()), @@ -5067,7 +5067,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0xa8a48e80).into()), element_selected: Some(rgba(0x9e9a8580).into()), text: Some(rgba(0x20201dff).into()), - text_muted: Some(rgba(0x999580ff).into()), + text_muted: Some(rgba(0x706d5fff).into()), text_placeholder: Some(rgba(0x999580ff).into()), text_disabled: Some(rgba(0x20201dff).into()), text_accent: Some(rgba(0x6784e0ff).into()), @@ -5427,7 +5427,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x8e898980).into()), element_selected: Some(rgba(0x837c7c80).into()), text: Some(rgba(0x1b1818ff).into()), - text_muted: Some(rgba(0x7e7777ff).into()), + text_muted: Some(rgba(0x5a5252ff).into()), text_placeholder: Some(rgba(0x7e7777ff).into()), text_disabled: Some(rgba(0x1b1818ff).into()), text_accent: Some(rgba(0x7372caff).into()), @@ -5787,7 +5787,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x8ea88e80).into()), element_selected: Some(rgba(0x859e8580).into()), text: Some(rgba(0x131513ff).into()), - text_muted: Some(rgba(0x809980ff).into()), + text_muted: Some(rgba(0x5f705fff).into()), text_placeholder: Some(rgba(0x809980ff).into()), text_disabled: Some(rgba(0x131513ff).into()), text_accent: Some(rgba(0x3f62f4ff).into()), @@ -6147,7 +6147,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x505e5580).into()), element_selected: Some(rgba(0x5a685f80).into()), text: Some(rgba(0xecf4eeff).into()), - text_muted: Some(rgba(0x5f6d64ff).into()), + text_muted: Some(rgba(0x859188ff).into()), text_placeholder: Some(rgba(0x5f6d64ff).into()), text_disabled: Some(rgba(0xecf4eeff).into()), text_accent: Some(rgba(0x478c90ff).into()), @@ -6507,7 +6507,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0xad9dad80).into()), element_selected: Some(rgba(0xa394a380).into()), text: Some(rgba(0x1b181bff).into()), - text_muted: Some(rgba(0x9e8f9eff).into()), + text_muted: Some(rgba(0x6b5e6bff).into()), text_placeholder: Some(rgba(0x9e8f9eff).into()), text_disabled: Some(rgba(0x1b181bff).into()), text_accent: Some(rgba(0x526aebff).into()), @@ -6867,7 +6867,7 @@ pub fn atelier() -> UserThemeFamily { element_hover: Some(rgba(0x80a4b680).into()), element_selected: Some(rgba(0x769aad80).into()), text: Some(rgba(0x161b1dff).into()), - text_muted: Some(rgba(0x7195a8ff).into()), + text_muted: Some(rgba(0x526f7dff).into()), text_placeholder: Some(rgba(0x7195a8ff).into()), text_disabled: Some(rgba(0x161b1dff).into()), text_accent: Some(rgba(0x277fadff).into()), diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index deab32b812..bc2fe60b04 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -27,7 +27,7 @@ pub fn ayu() -> UserThemeFamily { element_hover: Some(rgba(0x3f404380).into()), element_selected: Some(rgba(0x50515280).into()), text: Some(rgba(0xbfbdb6ff).into()), - text_muted: Some(rgba(0x58595aff).into()), + text_muted: Some(rgba(0x8a8986ff).into()), text_placeholder: Some(rgba(0x58595aff).into()), text_disabled: Some(rgba(0xbfbdb6ff).into()), text_accent: Some(rgba(0x5ac2feff).into()), @@ -366,7 +366,7 @@ pub fn ayu() -> UserThemeFamily { element_hover: Some(rgba(0xcfd1d280).into()), element_selected: Some(rgba(0xc0c2c480).into()), text: Some(rgba(0x5c6166ff).into()), - text_muted: Some(rgba(0xb9bbbdff).into()), + text_muted: Some(rgba(0x8c8f93ff).into()), text_placeholder: Some(rgba(0xb9bbbdff).into()), text_disabled: Some(rgba(0x5c6166ff).into()), text_accent: Some(rgba(0x3b9ee5ff).into()), @@ -705,7 +705,7 @@ pub fn ayu() -> UserThemeFamily { element_hover: Some(rgba(0x53565d80).into()), element_selected: Some(rgba(0x63656a80).into()), text: Some(rgba(0xcccac2ff).into()), - text_muted: Some(rgba(0x6b6d71ff).into()), + text_muted: Some(rgba(0x9a9a98ff).into()), text_placeholder: Some(rgba(0x6b6d71ff).into()), text_disabled: Some(rgba(0xcccac2ff).into()), text_accent: Some(rgba(0x73cffeff).into()), diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 8512706fd4..3db69b5a54 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -27,7 +27,7 @@ pub fn gruvbox() -> UserThemeFamily { element_hover: Some(rgba(0xc9b99a80).into()), element_selected: Some(rgba(0xb5a68e80).into()), text: Some(rgba(0x282828ff).into()), - text_muted: Some(rgba(0xad9e87ff).into()), + text_muted: Some(rgba(0x5f5650ff).into()), text_placeholder: Some(rgba(0xad9e87ff).into()), text_disabled: Some(rgba(0x282828ff).into()), text_accent: Some(rgba(0x0b6678ff).into()), @@ -373,7 +373,7 @@ pub fn gruvbox() -> UserThemeFamily { element_hover: Some(rgba(0x5b534d80).into()), element_selected: Some(rgba(0x6e635a80).into()), text: Some(rgba(0xfbf1c7ff).into()), - text_muted: Some(rgba(0x776b61ff).into()), + text_muted: Some(rgba(0xc5b597ff).into()), text_placeholder: Some(rgba(0x776b61ff).into()), text_disabled: Some(rgba(0xfbf1c7ff).into()), text_accent: Some(rgba(0x83a598ff).into()), @@ -719,7 +719,7 @@ pub fn gruvbox() -> UserThemeFamily { element_hover: Some(rgba(0xc9b99a80).into()), element_selected: Some(rgba(0xb5a68e80).into()), text: Some(rgba(0x282828ff).into()), - text_muted: Some(rgba(0xad9e87ff).into()), + text_muted: Some(rgba(0x5f5650ff).into()), text_placeholder: Some(rgba(0xad9e87ff).into()), text_disabled: Some(rgba(0x282828ff).into()), text_accent: Some(rgba(0x0b6678ff).into()), @@ -1065,7 +1065,7 @@ pub fn gruvbox() -> UserThemeFamily { element_hover: Some(rgba(0x5b534d80).into()), element_selected: Some(rgba(0x6e635a80).into()), text: Some(rgba(0xfbf1c7ff).into()), - text_muted: Some(rgba(0x776b61ff).into()), + text_muted: Some(rgba(0xc5b597ff).into()), text_placeholder: Some(rgba(0x776b61ff).into()), text_disabled: Some(rgba(0xfbf1c7ff).into()), text_accent: Some(rgba(0x83a598ff).into()), @@ -1411,7 +1411,7 @@ pub fn gruvbox() -> UserThemeFamily { element_hover: Some(rgba(0xc9b99a80).into()), element_selected: Some(rgba(0xb5a68e80).into()), text: Some(rgba(0x282828ff).into()), - text_muted: Some(rgba(0xad9e87ff).into()), + text_muted: Some(rgba(0x5f5650ff).into()), text_placeholder: Some(rgba(0xad9e87ff).into()), text_disabled: Some(rgba(0x282828ff).into()), text_accent: Some(rgba(0x0b6678ff).into()), @@ -1757,7 +1757,7 @@ pub fn gruvbox() -> UserThemeFamily { element_hover: Some(rgba(0x5b534d80).into()), element_selected: Some(rgba(0x6e635a80).into()), text: Some(rgba(0xfbf1c7ff).into()), - text_muted: Some(rgba(0x776b61ff).into()), + text_muted: Some(rgba(0xc5b597ff).into()), text_placeholder: Some(rgba(0x776b61ff).into()), text_disabled: Some(rgba(0xfbf1c7ff).into()), text_accent: Some(rgba(0x83a598ff).into()), diff --git a/crates/theme2/src/themes/one.rs b/crates/theme2/src/themes/one.rs index dcd90bf1af..7ea2bbea87 100644 --- a/crates/theme2/src/themes/one.rs +++ b/crates/theme2/src/themes/one.rs @@ -27,7 +27,7 @@ pub fn one() -> UserThemeFamily { element_hover: Some(rgba(0xc9c9ca80).into()), element_selected: Some(rgba(0xafafaf80).into()), text: Some(rgba(0x383a41ff).into()), - text_muted: Some(rgba(0xa7a7a8ff).into()), + text_muted: Some(rgba(0x7f8188ff).into()), text_placeholder: Some(rgba(0xa7a7a8ff).into()), text_disabled: Some(rgba(0x383a41ff).into()), text_accent: Some(rgba(0x5c79e2ff).into()), @@ -373,7 +373,7 @@ pub fn one() -> UserThemeFamily { element_hover: Some(rgba(0x464b5780).into()), element_selected: Some(rgba(0x4f545e80).into()), text: Some(rgba(0xc8ccd4ff).into()), - text_muted: Some(rgba(0x545862ff).into()), + text_muted: Some(rgba(0x838994ff).into()), text_placeholder: Some(rgba(0x545862ff).into()), text_disabled: Some(rgba(0xc8ccd4ff).into()), text_accent: Some(rgba(0x74ade8ff).into()), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index a08618ca6a..e63e8f2ad8 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -27,7 +27,7 @@ pub fn rose_pine() -> UserThemeFamily { element_hover: Some(rgba(0xdcd6d580).into()), element_selected: Some(rgba(0xc1bac180).into()), text: Some(rgba(0x575279ff).into()), - text_muted: Some(rgba(0xb1abb5ff).into()), + text_muted: Some(rgba(0x706c8cff).into()), text_placeholder: Some(rgba(0xb1abb5ff).into()), text_disabled: Some(rgba(0x575279ff).into()), text_accent: Some(rgba(0x57949fff).into()), @@ -380,7 +380,7 @@ pub fn rose_pine() -> UserThemeFamily { element_hover: Some(rgba(0x504c6880).into()), element_selected: Some(rgba(0x45415d80).into()), text: Some(rgba(0xe0def4ff).into()), - text_muted: Some(rgba(0x3a3653ff).into()), + text_muted: Some(rgba(0x85819eff).into()), text_placeholder: Some(rgba(0x3a3653ff).into()), text_disabled: Some(rgba(0xe0def4ff).into()), text_accent: Some(rgba(0x9cced7ff).into()), @@ -733,7 +733,7 @@ pub fn rose_pine() -> UserThemeFamily { element_hover: Some(rgba(0x423f5580).into()), element_selected: Some(rgba(0x47445b80).into()), text: Some(rgba(0xe0def4ff).into()), - text_muted: Some(rgba(0x3b384fff).into()), + text_muted: Some(rgba(0x75718eff).into()), text_placeholder: Some(rgba(0x3b384fff).into()), text_disabled: Some(rgba(0xe0def4ff).into()), text_accent: Some(rgba(0x9cced7ff).into()), diff --git a/crates/theme2/src/themes/sandcastle.rs b/crates/theme2/src/themes/sandcastle.rs index 38b6e04665..3e66ce97c1 100644 --- a/crates/theme2/src/themes/sandcastle.rs +++ b/crates/theme2/src/themes/sandcastle.rs @@ -26,7 +26,7 @@ pub fn sandcastle() -> UserThemeFamily { element_hover: Some(rgba(0x3d435080).into()), element_selected: Some(rgba(0x57535380).into()), text: Some(rgba(0xfdf4c1ff).into()), - text_muted: Some(rgba(0x645b54ff).into()), + text_muted: Some(rgba(0xa69782ff).into()), text_placeholder: Some(rgba(0x645b54ff).into()), text_disabled: Some(rgba(0xfdf4c1ff).into()), text_accent: Some(rgba(0x528b8bff).into()), diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index a09ca0e0cc..61c3fc8539 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -27,7 +27,7 @@ pub fn solarized() -> UserThemeFamily { element_hover: Some(rgba(0x9faaa880).into()), element_selected: Some(rgba(0x7f919480).into()), text: Some(rgba(0x002b36ff).into()), - text_muted: Some(rgba(0x788b8fff).into()), + text_muted: Some(rgba(0x34555eff).into()), text_placeholder: Some(rgba(0x788b8fff).into()), text_disabled: Some(rgba(0x002b36ff).into()), text_accent: Some(rgba(0x298bd1ff).into()), @@ -366,7 +366,7 @@ pub fn solarized() -> UserThemeFamily { element_hover: Some(rgba(0x2b4f5880).into()), element_selected: Some(rgba(0x566d7480).into()), text: Some(rgba(0xfdf6e3ff).into()), - text_muted: Some(rgba(0x5f757dff).into()), + text_muted: Some(rgba(0x93a1a1ff).into()), text_placeholder: Some(rgba(0x5f757dff).into()), text_disabled: Some(rgba(0xfdf6e3ff).into()), text_accent: Some(rgba(0x288bd1ff).into()), diff --git a/crates/theme2/src/themes/summercamp.rs b/crates/theme2/src/themes/summercamp.rs index c27d8369c3..3540d824d2 100644 --- a/crates/theme2/src/themes/summercamp.rs +++ b/crates/theme2/src/themes/summercamp.rs @@ -26,7 +26,7 @@ pub fn summercamp() -> UserThemeFamily { element_hover: Some(rgba(0x312d2180).into()), element_selected: Some(rgba(0x39342780).into()), text: Some(rgba(0xf8f5deff).into()), - text_muted: Some(rgba(0x3d382aff).into()), + text_muted: Some(rgba(0x736e55ff).into()), text_placeholder: Some(rgba(0x3d382aff).into()), text_disabled: Some(rgba(0xf8f5deff).into()), text_accent: Some(rgba(0x499befff).into()), diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs index 6543f21635..d2f156246e 100644 --- a/crates/theme_importer/src/zed1/converter.rs +++ b/crates/theme_importer/src/zed1/converter.rs @@ -115,7 +115,7 @@ impl Zed1ThemeConverter { .background_color .map(zed1_color_to_hsla), text: convert(self.theme.collab_panel.channel_name.text.color), - text_muted: convert(active_tab.description.text.color), + text_muted: convert(tab_bar.pane_button.default_style().color), text_accent: convert(status_bar.panel_buttons.button.active_state().icon_color), text_disabled: convert(status_bar.panel_buttons.button.disabled_style().icon_color), text_placeholder: picker From 446c947ad1a20fd6916421aed72f7b91dd789845 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 21:33:57 -0500 Subject: [PATCH 318/644] Render breadcrumb using muted colors --- crates/breadcrumbs2/src/breadcrumbs.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/crates/breadcrumbs2/src/breadcrumbs.rs b/crates/breadcrumbs2/src/breadcrumbs.rs index 3b8ce1c6c5..e579c8ded0 100644 --- a/crates/breadcrumbs2/src/breadcrumbs.rs +++ b/crates/breadcrumbs2/src/breadcrumbs.rs @@ -53,12 +53,15 @@ impl Render for Breadcrumbs { }; let highlighted_segments = segments.into_iter().map(|segment| { + let mut text_style = cx.text_style(); + text_style.color = Color::Muted.color(cx); + StyledText::new(segment.text) - .with_highlights(&cx.text_style(), segment.highlights.unwrap_or_default()) + .with_highlights(&text_style, segment.highlights.unwrap_or_default()) .into_any() }); let breadcrumbs = Itertools::intersperse_with(highlighted_segments, || { - Label::new("›").into_any_element() + Label::new("›").color(Color::Muted).into_any_element() }); let editor = active_item From 14ed4a431644c8233f934d2b8f6d71f8332365a9 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 21:36:20 -0500 Subject: [PATCH 319/644] Render project panel entries as muted, unless selected --- crates/project_panel2/src/project_panel.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 2966c55f79..21a114c43c 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -1372,7 +1372,11 @@ impl ProjectPanel { GitFileStatus::Modified => Color::Modified, GitFileStatus::Conflict => Color::Conflict, }) - .unwrap_or(Color::Default); + .unwrap_or(if is_selected { + Color::Default + } else { + Color::Muted + }); let file_name = details.filename.clone(); let icon = details.icon.clone(); From e5148b4a1bdb296921c88979b252601ce01307b9 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 22:28:41 -0500 Subject: [PATCH 320/644] Assign player colors from the theme (#3805) This PR updates the `theme_importer` to pull in the player colors so that we can assign them based on the current theme. Release Notes: - N/A --- crates/theme2/src/registry.rs | 18 +- crates/theme2/src/styles/players.rs | 5 +- crates/theme2/src/themes/andromeda.rs | 47 +- crates/theme2/src/themes/atelier.rs | 845 +++++++++++++++++- crates/theme2/src/themes/ayu.rs | 131 ++- crates/theme2/src/themes/gruvbox.rs | 257 +++++- crates/theme2/src/themes/one.rs | 89 +- crates/theme2/src/themes/rose_pine.rs | 131 ++- crates/theme2/src/themes/sandcastle.rs | 47 +- crates/theme2/src/themes/solarized.rs | 89 +- crates/theme2/src/themes/summercamp.rs | 47 +- crates/theme2/src/user_theme.rs | 6 +- crates/theme_importer/src/main.rs | 5 +- crates/theme_importer/src/theme_printer.rs | 10 + crates/theme_importer/src/vscode/converter.rs | 1 + crates/theme_importer/src/zed1/converter.rs | 32 +- 16 files changed, 1730 insertions(+), 30 deletions(-) diff --git a/crates/theme2/src/registry.rs b/crates/theme2/src/registry.rs index ac94d93bcd..015814e3b2 100644 --- a/crates/theme2/src/registry.rs +++ b/crates/theme2/src/registry.rs @@ -49,9 +49,20 @@ impl ThemeRegistry { }; theme_colors.refine(&user_theme.styles.colors); - let mut status_colors = StatusColors::dark(); + let mut status_colors = match user_theme.appearance { + Appearance::Light => StatusColors::light(), + Appearance::Dark => StatusColors::dark(), + }; status_colors.refine(&user_theme.styles.status); + let mut player_colors = match user_theme.appearance { + Appearance::Light => PlayerColors::light(), + Appearance::Dark => PlayerColors::dark(), + }; + if let Some(player_colors_from_theme) = user_theme.styles.player { + player_colors = player_colors_from_theme; + } + let mut syntax_colors = match user_theme.appearance { Appearance::Light => SyntaxTheme::light(), Appearance::Dark => SyntaxTheme::dark(), @@ -82,10 +93,7 @@ impl ThemeRegistry { system: SystemColors::default(), colors: theme_colors, status: status_colors, - player: match user_theme.appearance { - Appearance::Light => PlayerColors::light(), - Appearance::Dark => PlayerColors::dark(), - }, + player: player_colors, syntax: Arc::new(syntax_colors), accents: Vec::new(), }, diff --git a/crates/theme2/src/styles/players.rs b/crates/theme2/src/styles/players.rs index e8bce8e578..9f9b837e47 100644 --- a/crates/theme2/src/styles/players.rs +++ b/crates/theme2/src/styles/players.rs @@ -1,8 +1,9 @@ use gpui::Hsla; +use serde_derive::Deserialize; use crate::{amber, blue, jade, lime, orange, pink, purple, red}; -#[derive(Debug, Clone, Copy, Default)] +#[derive(Debug, Clone, Copy, Deserialize, Default)] pub struct PlayerColor { pub cursor: Hsla, pub background: Hsla, @@ -15,7 +16,7 @@ pub struct PlayerColor { /// /// The rest of the default colors crisscross back and forth on the /// color wheel so that the colors are as distinct as possible. -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct PlayerColors(pub Vec); impl Default for PlayerColors { diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index fd61f9b482..67c18f88ad 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn andromeda() -> UserThemeFamily { @@ -75,6 +76,48 @@ pub fn andromeda() -> UserThemeFamily { warning: Some(rgba(0xfee56dff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x11a793ff).into(), + background: rgba(0x11a793ff).into(), + selection: rgba(0x11a7933d).into(), + }, + PlayerColor { + cursor: rgba(0xc74decff).into(), + background: rgba(0xc74decff).into(), + selection: rgba(0xc74dec3d).into(), + }, + PlayerColor { + cursor: rgba(0xf29c14ff).into(), + background: rgba(0xf29c14ff).into(), + selection: rgba(0xf29c143d).into(), + }, + PlayerColor { + cursor: rgba(0x8a3fa6ff).into(), + background: rgba(0x8a3fa6ff).into(), + selection: rgba(0x8a3fa63d).into(), + }, + PlayerColor { + cursor: rgba(0x09e7c6ff).into(), + background: rgba(0x09e7c6ff).into(), + selection: rgba(0x09e7c63d).into(), + }, + PlayerColor { + cursor: rgba(0xf82872ff).into(), + background: rgba(0xf82872ff).into(), + selection: rgba(0xf828723d).into(), + }, + PlayerColor { + cursor: rgba(0xfee56dff).into(), + background: rgba(0xfee56dff).into(), + selection: rgba(0xfee56d3d).into(), + }, + PlayerColor { + cursor: rgba(0x96df72ff).into(), + background: rgba(0x96df72ff).into(), + selection: rgba(0x96df723d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/themes/atelier.rs b/crates/theme2/src/themes/atelier.rs index 6c942d5b4c..d6681aa6b1 100644 --- a/crates/theme2/src/themes/atelier.rs +++ b/crates/theme2/src/themes/atelier.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn atelier() -> UserThemeFamily { @@ -76,6 +77,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xa59810ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x38a166ff).into(), + background: rgba(0x38a166ff).into(), + selection: rgba(0x38a1663d).into(), + }, + PlayerColor { + cursor: rgba(0x9d6c7cff).into(), + background: rgba(0x9d6c7cff).into(), + selection: rgba(0x9d6c7c3d).into(), + }, + PlayerColor { + cursor: rgba(0xae7315ff).into(), + background: rgba(0xae7315ff).into(), + selection: rgba(0xae73153d).into(), + }, + PlayerColor { + cursor: rgba(0x609182ff).into(), + background: rgba(0x609182ff).into(), + selection: rgba(0x6091823d).into(), + }, + PlayerColor { + cursor: rgba(0x5c9d49ff).into(), + background: rgba(0x5c9d49ff).into(), + selection: rgba(0x5c9d493d).into(), + }, + PlayerColor { + cursor: rgba(0xba6337ff).into(), + background: rgba(0xba6337ff).into(), + selection: rgba(0xba63373d).into(), + }, + PlayerColor { + cursor: rgba(0xa59810ff).into(), + background: rgba(0xa59810ff).into(), + selection: rgba(0xa598103d).into(), + }, + PlayerColor { + cursor: rgba(0x7d9728ff).into(), + background: rgba(0x7d9728ff).into(), + selection: rgba(0x7d97283d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -436,6 +479,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xc38419ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x417ee6ff).into(), + background: rgba(0x417ee6ff).into(), + selection: rgba(0x417ee63d).into(), + }, + PlayerColor { + cursor: rgba(0xc340f2ff).into(), + background: rgba(0xc340f2ff).into(), + selection: rgba(0xc340f23d).into(), + }, + PlayerColor { + cursor: rgba(0xdf5321ff).into(), + background: rgba(0xdf5321ff).into(), + selection: rgba(0xdf53213d).into(), + }, + PlayerColor { + cursor: rgba(0x6666e9ff).into(), + background: rgba(0x6666e9ff).into(), + selection: rgba(0x6666e93d).into(), + }, + PlayerColor { + cursor: rgba(0x3e97b8ff).into(), + background: rgba(0x3e97b8ff).into(), + selection: rgba(0x3e97b83d).into(), + }, + PlayerColor { + cursor: rgba(0xf22d40ff).into(), + background: rgba(0xf22d40ff).into(), + selection: rgba(0xf22d403d).into(), + }, + PlayerColor { + cursor: rgba(0xc38419ff).into(), + background: rgba(0xc38419ff).into(), + selection: rgba(0xc384193d).into(), + }, + PlayerColor { + cursor: rgba(0x7b9727ff).into(), + background: rgba(0x7b9727ff).into(), + selection: rgba(0x7b97273d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -796,6 +881,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xa07e3cff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x488c90ff).into(), + background: rgba(0x488c90ff).into(), + selection: rgba(0x488c903d).into(), + }, + PlayerColor { + cursor: rgba(0x867469ff).into(), + background: rgba(0x867469ff).into(), + selection: rgba(0x8674693d).into(), + }, + PlayerColor { + cursor: rgba(0x9f713dff).into(), + background: rgba(0x9f713dff).into(), + selection: rgba(0x9f713d3d).into(), + }, + PlayerColor { + cursor: rgba(0x56859bff).into(), + background: rgba(0x56859bff).into(), + selection: rgba(0x56859b3d).into(), + }, + PlayerColor { + cursor: rgba(0x1f9aa0ff).into(), + background: rgba(0x1f9aa0ff).into(), + selection: rgba(0x1f9aa03d).into(), + }, + PlayerColor { + cursor: rgba(0xb1623aff).into(), + background: rgba(0xb1623aff).into(), + selection: rgba(0xb1623a3d).into(), + }, + PlayerColor { + cursor: rgba(0xa07e3cff).into(), + background: rgba(0xa07e3cff).into(), + selection: rgba(0xa07e3c3d).into(), + }, + PlayerColor { + cursor: rgba(0x499963ff).into(), + background: rgba(0x499963ff).into(), + selection: rgba(0x4999633d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -1156,6 +1283,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xa06e3bff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x576ddaff).into(), + background: rgba(0x576ddaff).into(), + selection: rgba(0x576dda3d).into(), + }, + PlayerColor { + cursor: rgba(0xbf41bfff).into(), + background: rgba(0xbf41bfff).into(), + selection: rgba(0xbf41bf3d).into(), + }, + PlayerColor { + cursor: rgba(0xaa573cff).into(), + background: rgba(0xaa573cff).into(), + selection: rgba(0xaa573c3d).into(), + }, + PlayerColor { + cursor: rgba(0x955ae6ff).into(), + background: rgba(0x955ae6ff).into(), + selection: rgba(0x955ae63d).into(), + }, + PlayerColor { + cursor: rgba(0x3a8bc6ff).into(), + background: rgba(0x3a8bc6ff).into(), + selection: rgba(0x3a8bc63d).into(), + }, + PlayerColor { + cursor: rgba(0xbe4678ff).into(), + background: rgba(0xbe4678ff).into(), + selection: rgba(0xbe46783d).into(), + }, + PlayerColor { + cursor: rgba(0xa06e3bff).into(), + background: rgba(0xa06e3bff).into(), + selection: rgba(0xa06e3b3d).into(), + }, + PlayerColor { + cursor: rgba(0x2c9292ff).into(), + background: rgba(0x2c9292ff).into(), + selection: rgba(0x2c92923d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -1516,6 +1685,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xa59810ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x37a166ff).into(), + background: rgba(0x37a166ff).into(), + selection: rgba(0x37a1663d).into(), + }, + PlayerColor { + cursor: rgba(0x9d6c7cff).into(), + background: rgba(0x9d6c7cff).into(), + selection: rgba(0x9d6c7c3d).into(), + }, + PlayerColor { + cursor: rgba(0xae7315ff).into(), + background: rgba(0xae7315ff).into(), + selection: rgba(0xae73153d).into(), + }, + PlayerColor { + cursor: rgba(0x5f9182ff).into(), + background: rgba(0x5f9182ff).into(), + selection: rgba(0x5f91823d).into(), + }, + PlayerColor { + cursor: rgba(0x5b9d48ff).into(), + background: rgba(0x5b9d48ff).into(), + selection: rgba(0x5b9d483d).into(), + }, + PlayerColor { + cursor: rgba(0xba6237ff).into(), + background: rgba(0xba6237ff).into(), + selection: rgba(0xba62373d).into(), + }, + PlayerColor { + cursor: rgba(0xa59810ff).into(), + background: rgba(0xa59810ff).into(), + selection: rgba(0xa598103d).into(), + }, + PlayerColor { + cursor: rgba(0x7d9727ff).into(), + background: rgba(0x7d9727ff).into(), + selection: rgba(0x7d97273d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -1876,6 +2087,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xc08b31ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x3e8fd0ff).into(), + background: rgba(0x3e8fd0ff).into(), + selection: rgba(0x3e8fd03d).into(), + }, + PlayerColor { + cursor: rgba(0x9c637aff).into(), + background: rgba(0x9c637aff).into(), + selection: rgba(0x9c637a3d).into(), + }, + PlayerColor { + cursor: rgba(0xc76b2aff).into(), + background: rgba(0xc76b2aff).into(), + selection: rgba(0xc76b2a3d).into(), + }, + PlayerColor { + cursor: rgba(0x6679ccff).into(), + background: rgba(0x6679ccff).into(), + selection: rgba(0x6679cc3d).into(), + }, + PlayerColor { + cursor: rgba(0x25a2c9ff).into(), + background: rgba(0x25a2c9ff).into(), + selection: rgba(0x25a2c93d).into(), + }, + PlayerColor { + cursor: rgba(0xc94923ff).into(), + background: rgba(0xc94923ff).into(), + selection: rgba(0xc949233d).into(), + }, + PlayerColor { + cursor: rgba(0xc08b31ff).into(), + background: rgba(0xc08b31ff).into(), + selection: rgba(0xc08b313d).into(), + }, + PlayerColor { + cursor: rgba(0xac973aff).into(), + background: rgba(0xac973aff).into(), + selection: rgba(0xac973a3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -2236,6 +2489,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xc08b31ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x3f8fd0ff).into(), + background: rgba(0x3f8fd0ff).into(), + selection: rgba(0x3f8fd03d).into(), + }, + PlayerColor { + cursor: rgba(0x9c637aff).into(), + background: rgba(0x9c637aff).into(), + selection: rgba(0x9c637a3d).into(), + }, + PlayerColor { + cursor: rgba(0xc76b2aff).into(), + background: rgba(0xc76b2aff).into(), + selection: rgba(0xc76b2a3d).into(), + }, + PlayerColor { + cursor: rgba(0x6779ccff).into(), + background: rgba(0x6779ccff).into(), + selection: rgba(0x6779cc3d).into(), + }, + PlayerColor { + cursor: rgba(0x25a2c9ff).into(), + background: rgba(0x25a2c9ff).into(), + selection: rgba(0x25a2c93d).into(), + }, + PlayerColor { + cursor: rgba(0xc94a23ff).into(), + background: rgba(0xc94a23ff).into(), + selection: rgba(0xc94a233d).into(), + }, + PlayerColor { + cursor: rgba(0xc08b31ff).into(), + background: rgba(0xc08b31ff).into(), + selection: rgba(0xc08b313d).into(), + }, + PlayerColor { + cursor: rgba(0xac973aff).into(), + background: rgba(0xac973aff).into(), + selection: rgba(0xac973a3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -2596,6 +2891,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xae9515ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x6684e0ff).into(), + background: rgba(0x6684e0ff).into(), + selection: rgba(0x6684e03d).into(), + }, + PlayerColor { + cursor: rgba(0xd43652ff).into(), + background: rgba(0xd43652ff).into(), + selection: rgba(0xd436523d).into(), + }, + PlayerColor { + cursor: rgba(0xb65612ff).into(), + background: rgba(0xb65612ff).into(), + selection: rgba(0xb656123d).into(), + }, + PlayerColor { + cursor: rgba(0xb854d3ff).into(), + background: rgba(0xb854d3ff).into(), + selection: rgba(0xb854d33d).into(), + }, + PlayerColor { + cursor: rgba(0x21ad83ff).into(), + background: rgba(0x21ad83ff).into(), + selection: rgba(0x21ad833d).into(), + }, + PlayerColor { + cursor: rgba(0xd73837ff).into(), + background: rgba(0xd73837ff).into(), + selection: rgba(0xd738373d).into(), + }, + PlayerColor { + cursor: rgba(0xae9515ff).into(), + background: rgba(0xae9515ff).into(), + selection: rgba(0xae95153d).into(), + }, + PlayerColor { + cursor: rgba(0x60ac3aff).into(), + background: rgba(0x60ac3aff).into(), + selection: rgba(0x60ac3a3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -2956,6 +3293,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0x98981cff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x3e62f4ff).into(), + background: rgba(0x3e62f4ff).into(), + selection: rgba(0x3e62f43d).into(), + }, + PlayerColor { + cursor: rgba(0xe61cc3ff).into(), + background: rgba(0xe61cc3ff).into(), + selection: rgba(0xe61cc33d).into(), + }, + PlayerColor { + cursor: rgba(0x87711eff).into(), + background: rgba(0x87711eff).into(), + selection: rgba(0x87711e3d).into(), + }, + PlayerColor { + cursor: rgba(0xad2dedff).into(), + background: rgba(0xad2dedff).into(), + selection: rgba(0xad2ded3d).into(), + }, + PlayerColor { + cursor: rgba(0x1c99b3ff).into(), + background: rgba(0x1c99b3ff).into(), + selection: rgba(0x1c99b33d).into(), + }, + PlayerColor { + cursor: rgba(0xe61c3cff).into(), + background: rgba(0xe61c3cff).into(), + selection: rgba(0xe61c3c3d).into(), + }, + PlayerColor { + cursor: rgba(0x98981cff).into(), + background: rgba(0x98981cff).into(), + selection: rgba(0x98981c3d).into(), + }, + PlayerColor { + cursor: rgba(0x2ba32aff).into(), + background: rgba(0x2ba32aff).into(), + selection: rgba(0x2ba32a3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -3316,6 +3695,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xa06e3cff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x586ddaff).into(), + background: rgba(0x586ddaff).into(), + selection: rgba(0x586dda3d).into(), + }, + PlayerColor { + cursor: rgba(0xbf41bfff).into(), + background: rgba(0xbf41bfff).into(), + selection: rgba(0xbf41bf3d).into(), + }, + PlayerColor { + cursor: rgba(0xaa583dff).into(), + background: rgba(0xaa583dff).into(), + selection: rgba(0xaa583d3d).into(), + }, + PlayerColor { + cursor: rgba(0x955be6ff).into(), + background: rgba(0x955be6ff).into(), + selection: rgba(0x955be63d).into(), + }, + PlayerColor { + cursor: rgba(0x3b8bc6ff).into(), + background: rgba(0x3b8bc6ff).into(), + selection: rgba(0x3b8bc63d).into(), + }, + PlayerColor { + cursor: rgba(0xbe4778ff).into(), + background: rgba(0xbe4778ff).into(), + selection: rgba(0xbe47783d).into(), + }, + PlayerColor { + cursor: rgba(0xa06e3cff).into(), + background: rgba(0xa06e3cff).into(), + selection: rgba(0xa06e3c3d).into(), + }, + PlayerColor { + cursor: rgba(0x2c9292ff).into(), + background: rgba(0x2c9292ff).into(), + selection: rgba(0x2c92923d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -3676,6 +4097,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xa06e3bff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x7272caff).into(), + background: rgba(0x7272caff).into(), + selection: rgba(0x7272ca3d).into(), + }, + PlayerColor { + cursor: rgba(0xbd5187ff).into(), + background: rgba(0xbd5187ff).into(), + selection: rgba(0xbd51873d).into(), + }, + PlayerColor { + cursor: rgba(0xb45a3cff).into(), + background: rgba(0xb45a3cff).into(), + selection: rgba(0xb45a3c3d).into(), + }, + PlayerColor { + cursor: rgba(0x8464c4ff).into(), + background: rgba(0x8464c4ff).into(), + selection: rgba(0x8464c43d).into(), + }, + PlayerColor { + cursor: rgba(0x5485b6ff).into(), + background: rgba(0x5485b6ff).into(), + selection: rgba(0x5485b63d).into(), + }, + PlayerColor { + cursor: rgba(0xca4949ff).into(), + background: rgba(0xca4949ff).into(), + selection: rgba(0xca49493d).into(), + }, + PlayerColor { + cursor: rgba(0xa06e3bff).into(), + background: rgba(0xa06e3bff).into(), + selection: rgba(0xa06e3b3d).into(), + }, + PlayerColor { + cursor: rgba(0x4b8b8bff).into(), + background: rgba(0x4b8b8bff).into(), + selection: rgba(0x4b8b8b3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -4036,6 +4499,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xbb8a36ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x526aebff).into(), + background: rgba(0x526aebff).into(), + selection: rgba(0x526aeb3d).into(), + }, + PlayerColor { + cursor: rgba(0xcc34ccff).into(), + background: rgba(0xcc34ccff).into(), + selection: rgba(0xcc34cc3d).into(), + }, + PlayerColor { + cursor: rgba(0xa65927ff).into(), + background: rgba(0xa65927ff).into(), + selection: rgba(0xa659273d).into(), + }, + PlayerColor { + cursor: rgba(0x7b59c0ff).into(), + background: rgba(0x7b59c0ff).into(), + selection: rgba(0x7b59c03d).into(), + }, + PlayerColor { + cursor: rgba(0x189393ff).into(), + background: rgba(0x189393ff).into(), + selection: rgba(0x1893933d).into(), + }, + PlayerColor { + cursor: rgba(0xca402cff).into(), + background: rgba(0xca402cff).into(), + selection: rgba(0xca402c3d).into(), + }, + PlayerColor { + cursor: rgba(0xbb8a36ff).into(), + background: rgba(0xbb8a36ff).into(), + selection: rgba(0xbb8a363d).into(), + }, + PlayerColor { + cursor: rgba(0x918b3bff).into(), + background: rgba(0x918b3bff).into(), + selection: rgba(0x918b3b3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -4396,6 +4901,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0x8a8a11ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x277fadff).into(), + background: rgba(0x277fadff).into(), + selection: rgba(0x277fad3d).into(), + }, + PlayerColor { + cursor: rgba(0xb72ed2ff).into(), + background: rgba(0xb72ed2ff).into(), + selection: rgba(0xb72ed23d).into(), + }, + PlayerColor { + cursor: rgba(0x935c26ff).into(), + background: rgba(0x935c26ff).into(), + selection: rgba(0x935c263d).into(), + }, + PlayerColor { + cursor: rgba(0x6b6bb8ff).into(), + background: rgba(0x6b6bb8ff).into(), + selection: rgba(0x6b6bb83d).into(), + }, + PlayerColor { + cursor: rgba(0x2e8f6fff).into(), + background: rgba(0x2e8f6fff).into(), + selection: rgba(0x2e8f6f3d).into(), + }, + PlayerColor { + cursor: rgba(0xd22e72ff).into(), + background: rgba(0xd22e72ff).into(), + selection: rgba(0xd22e723d).into(), + }, + PlayerColor { + cursor: rgba(0x8a8a11ff).into(), + background: rgba(0x8a8a11ff).into(), + selection: rgba(0x8a8a113d).into(), + }, + PlayerColor { + cursor: rgba(0x568c3bff).into(), + background: rgba(0x568c3bff).into(), + selection: rgba(0x568c3b3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -4756,6 +5303,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xc3841aff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x417ee6ff).into(), + background: rgba(0x417ee6ff).into(), + selection: rgba(0x417ee63d).into(), + }, + PlayerColor { + cursor: rgba(0xc340f2ff).into(), + background: rgba(0xc340f2ff).into(), + selection: rgba(0xc340f23d).into(), + }, + PlayerColor { + cursor: rgba(0xdf5421ff).into(), + background: rgba(0xdf5421ff).into(), + selection: rgba(0xdf54213d).into(), + }, + PlayerColor { + cursor: rgba(0x6766e9ff).into(), + background: rgba(0x6766e9ff).into(), + selection: rgba(0x6766e93d).into(), + }, + PlayerColor { + cursor: rgba(0x3f97b8ff).into(), + background: rgba(0x3f97b8ff).into(), + selection: rgba(0x3f97b83d).into(), + }, + PlayerColor { + cursor: rgba(0xf22e41ff).into(), + background: rgba(0xf22e41ff).into(), + selection: rgba(0xf22e413d).into(), + }, + PlayerColor { + cursor: rgba(0xc3841aff).into(), + background: rgba(0xc3841aff).into(), + selection: rgba(0xc3841a3d).into(), + }, + PlayerColor { + cursor: rgba(0x7b9728ff).into(), + background: rgba(0x7b9728ff).into(), + selection: rgba(0x7b97283d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -5116,6 +5705,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xae9515ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x6784e0ff).into(), + background: rgba(0x6784e0ff).into(), + selection: rgba(0x6784e03d).into(), + }, + PlayerColor { + cursor: rgba(0xd43753ff).into(), + background: rgba(0xd43753ff).into(), + selection: rgba(0xd437533d).into(), + }, + PlayerColor { + cursor: rgba(0xb65713ff).into(), + background: rgba(0xb65713ff).into(), + selection: rgba(0xb657133d).into(), + }, + PlayerColor { + cursor: rgba(0xb855d3ff).into(), + background: rgba(0xb855d3ff).into(), + selection: rgba(0xb855d33d).into(), + }, + PlayerColor { + cursor: rgba(0x22ad83ff).into(), + background: rgba(0x22ad83ff).into(), + selection: rgba(0x22ad833d).into(), + }, + PlayerColor { + cursor: rgba(0xd73838ff).into(), + background: rgba(0xd73838ff).into(), + selection: rgba(0xd738383d).into(), + }, + PlayerColor { + cursor: rgba(0xae9515ff).into(), + background: rgba(0xae9515ff).into(), + selection: rgba(0xae95153d).into(), + }, + PlayerColor { + cursor: rgba(0x61ac3aff).into(), + background: rgba(0x61ac3aff).into(), + selection: rgba(0x61ac3a3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -5476,6 +6107,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xa06e3cff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x7372caff).into(), + background: rgba(0x7372caff).into(), + selection: rgba(0x7372ca3d).into(), + }, + PlayerColor { + cursor: rgba(0xbd5287ff).into(), + background: rgba(0xbd5287ff).into(), + selection: rgba(0xbd52873d).into(), + }, + PlayerColor { + cursor: rgba(0xb45b3dff).into(), + background: rgba(0xb45b3dff).into(), + selection: rgba(0xb45b3d3d).into(), + }, + PlayerColor { + cursor: rgba(0x8464c4ff).into(), + background: rgba(0x8464c4ff).into(), + selection: rgba(0x8464c43d).into(), + }, + PlayerColor { + cursor: rgba(0x5585b6ff).into(), + background: rgba(0x5585b6ff).into(), + selection: rgba(0x5585b63d).into(), + }, + PlayerColor { + cursor: rgba(0xca4a4aff).into(), + background: rgba(0xca4a4aff).into(), + selection: rgba(0xca4a4a3d).into(), + }, + PlayerColor { + cursor: rgba(0xa06e3cff).into(), + background: rgba(0xa06e3cff).into(), + selection: rgba(0xa06e3c3d).into(), + }, + PlayerColor { + cursor: rgba(0x4c8b8bff).into(), + background: rgba(0x4c8b8bff).into(), + selection: rgba(0x4c8b8b3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -5836,6 +6509,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0x98981dff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x3f62f4ff).into(), + background: rgba(0x3f62f4ff).into(), + selection: rgba(0x3f62f43d).into(), + }, + PlayerColor { + cursor: rgba(0xe61dc3ff).into(), + background: rgba(0xe61dc3ff).into(), + selection: rgba(0xe61dc33d).into(), + }, + PlayerColor { + cursor: rgba(0x87711fff).into(), + background: rgba(0x87711fff).into(), + selection: rgba(0x87711f3d).into(), + }, + PlayerColor { + cursor: rgba(0xad2dedff).into(), + background: rgba(0xad2dedff).into(), + selection: rgba(0xad2ded3d).into(), + }, + PlayerColor { + cursor: rgba(0x1d99b3ff).into(), + background: rgba(0x1d99b3ff).into(), + selection: rgba(0x1d99b33d).into(), + }, + PlayerColor { + cursor: rgba(0xe61c3dff).into(), + background: rgba(0xe61c3dff).into(), + selection: rgba(0xe61c3d3d).into(), + }, + PlayerColor { + cursor: rgba(0x98981dff).into(), + background: rgba(0x98981dff).into(), + selection: rgba(0x98981d3d).into(), + }, + PlayerColor { + cursor: rgba(0x2ba32bff).into(), + background: rgba(0x2ba32bff).into(), + selection: rgba(0x2ba32b3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -6196,6 +6911,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xa07e3bff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x478c90ff).into(), + background: rgba(0x478c90ff).into(), + selection: rgba(0x478c903d).into(), + }, + PlayerColor { + cursor: rgba(0x867469ff).into(), + background: rgba(0x867469ff).into(), + selection: rgba(0x8674693d).into(), + }, + PlayerColor { + cursor: rgba(0x9f713cff).into(), + background: rgba(0x9f713cff).into(), + selection: rgba(0x9f713c3d).into(), + }, + PlayerColor { + cursor: rgba(0x55859bff).into(), + background: rgba(0x55859bff).into(), + selection: rgba(0x55859b3d).into(), + }, + PlayerColor { + cursor: rgba(0x1e9aa0ff).into(), + background: rgba(0x1e9aa0ff).into(), + selection: rgba(0x1e9aa03d).into(), + }, + PlayerColor { + cursor: rgba(0xb16139ff).into(), + background: rgba(0xb16139ff).into(), + selection: rgba(0xb161393d).into(), + }, + PlayerColor { + cursor: rgba(0xa07e3bff).into(), + background: rgba(0xa07e3bff).into(), + selection: rgba(0xa07e3b3d).into(), + }, + PlayerColor { + cursor: rgba(0x489963ff).into(), + background: rgba(0x489963ff).into(), + selection: rgba(0x4899633d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -6556,6 +7313,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0xbb8a36ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x526aebff).into(), + background: rgba(0x526aebff).into(), + selection: rgba(0x526aeb3d).into(), + }, + PlayerColor { + cursor: rgba(0xcc35ccff).into(), + background: rgba(0xcc35ccff).into(), + selection: rgba(0xcc35cc3d).into(), + }, + PlayerColor { + cursor: rgba(0xa65a27ff).into(), + background: rgba(0xa65a27ff).into(), + selection: rgba(0xa65a273d).into(), + }, + PlayerColor { + cursor: rgba(0x7b5ac0ff).into(), + background: rgba(0x7b5ac0ff).into(), + selection: rgba(0x7b5ac03d).into(), + }, + PlayerColor { + cursor: rgba(0x199393ff).into(), + background: rgba(0x199393ff).into(), + selection: rgba(0x1993933d).into(), + }, + PlayerColor { + cursor: rgba(0xca412cff).into(), + background: rgba(0xca412cff).into(), + selection: rgba(0xca412c3d).into(), + }, + PlayerColor { + cursor: rgba(0xbb8a36ff).into(), + background: rgba(0xbb8a36ff).into(), + selection: rgba(0xbb8a363d).into(), + }, + PlayerColor { + cursor: rgba(0x918b3cff).into(), + background: rgba(0x918b3cff).into(), + selection: rgba(0x918b3c3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -6916,6 +7715,48 @@ pub fn atelier() -> UserThemeFamily { warning: Some(rgba(0x8a8a11ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x277fadff).into(), + background: rgba(0x277fadff).into(), + selection: rgba(0x277fad3d).into(), + }, + PlayerColor { + cursor: rgba(0xb72fd2ff).into(), + background: rgba(0xb72fd2ff).into(), + selection: rgba(0xb72fd23d).into(), + }, + PlayerColor { + cursor: rgba(0x935d26ff).into(), + background: rgba(0x935d26ff).into(), + selection: rgba(0x935d263d).into(), + }, + PlayerColor { + cursor: rgba(0x6c6bb8ff).into(), + background: rgba(0x6c6bb8ff).into(), + selection: rgba(0x6c6bb83d).into(), + }, + PlayerColor { + cursor: rgba(0x2f8f6fff).into(), + background: rgba(0x2f8f6fff).into(), + selection: rgba(0x2f8f6f3d).into(), + }, + PlayerColor { + cursor: rgba(0xd22f72ff).into(), + background: rgba(0xd22f72ff).into(), + selection: rgba(0xd22f723d).into(), + }, + PlayerColor { + cursor: rgba(0x8a8a11ff).into(), + background: rgba(0x8a8a11ff).into(), + selection: rgba(0x8a8a113d).into(), + }, + PlayerColor { + cursor: rgba(0x578c3cff).into(), + background: rgba(0x578c3cff).into(), + selection: rgba(0x578c3c3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index bc2fe60b04..4ea839eaa9 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn ayu() -> UserThemeFamily { @@ -76,6 +77,48 @@ pub fn ayu() -> UserThemeFamily { warning: Some(rgba(0xfeb454ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x5ac2feff).into(), + background: rgba(0x5ac2feff).into(), + selection: rgba(0x5ac2fe3d).into(), + }, + PlayerColor { + cursor: rgba(0x3abae5ff).into(), + background: rgba(0x3abae5ff).into(), + selection: rgba(0x3abae53d).into(), + }, + PlayerColor { + cursor: rgba(0xfe8f40ff).into(), + background: rgba(0xfe8f40ff).into(), + selection: rgba(0xfe8f403d).into(), + }, + PlayerColor { + cursor: rgba(0xd2a6feff).into(), + background: rgba(0xd2a6feff).into(), + selection: rgba(0xd2a6fe3d).into(), + }, + PlayerColor { + cursor: rgba(0x95e5cbff).into(), + background: rgba(0x95e5cbff).into(), + selection: rgba(0x95e5cb3d).into(), + }, + PlayerColor { + cursor: rgba(0xef7178ff).into(), + background: rgba(0xef7178ff).into(), + selection: rgba(0xef71783d).into(), + }, + PlayerColor { + cursor: rgba(0xfeb454ff).into(), + background: rgba(0xfeb454ff).into(), + selection: rgba(0xfeb4543d).into(), + }, + PlayerColor { + cursor: rgba(0xaad84cff).into(), + background: rgba(0xaad84cff).into(), + selection: rgba(0xaad84c3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -415,6 +458,48 @@ pub fn ayu() -> UserThemeFamily { warning: Some(rgba(0xf1ae4aff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x3b9ee5ff).into(), + background: rgba(0x3b9ee5ff).into(), + selection: rgba(0x3b9ee53d).into(), + }, + PlayerColor { + cursor: rgba(0x56b4d3ff).into(), + background: rgba(0x56b4d3ff).into(), + selection: rgba(0x56b4d33d).into(), + }, + PlayerColor { + cursor: rgba(0xf98d3fff).into(), + background: rgba(0xf98d3fff).into(), + selection: rgba(0xf98d3f3d).into(), + }, + PlayerColor { + cursor: rgba(0xa37accff).into(), + background: rgba(0xa37accff).into(), + selection: rgba(0xa37acc3d).into(), + }, + PlayerColor { + cursor: rgba(0x4dbf99ff).into(), + background: rgba(0x4dbf99ff).into(), + selection: rgba(0x4dbf993d).into(), + }, + PlayerColor { + cursor: rgba(0xef7271ff).into(), + background: rgba(0xef7271ff).into(), + selection: rgba(0xef72713d).into(), + }, + PlayerColor { + cursor: rgba(0xf1ae4aff).into(), + background: rgba(0xf1ae4aff).into(), + selection: rgba(0xf1ae4a3d).into(), + }, + PlayerColor { + cursor: rgba(0x86b305ff).into(), + background: rgba(0x86b305ff).into(), + selection: rgba(0x86b3053d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -754,6 +839,48 @@ pub fn ayu() -> UserThemeFamily { warning: Some(rgba(0xfed073ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x73cffeff).into(), + background: rgba(0x73cffeff).into(), + selection: rgba(0x73cffe3d).into(), + }, + PlayerColor { + cursor: rgba(0x5ccee5ff).into(), + background: rgba(0x5ccee5ff).into(), + selection: rgba(0x5ccee53d).into(), + }, + PlayerColor { + cursor: rgba(0xfead66ff).into(), + background: rgba(0xfead66ff).into(), + selection: rgba(0xfead663d).into(), + }, + PlayerColor { + cursor: rgba(0xdebffeff).into(), + background: rgba(0xdebffeff).into(), + selection: rgba(0xdebffe3d).into(), + }, + PlayerColor { + cursor: rgba(0x95e5cbff).into(), + background: rgba(0x95e5cbff).into(), + selection: rgba(0x95e5cb3d).into(), + }, + PlayerColor { + cursor: rgba(0xf18779ff).into(), + background: rgba(0xf18779ff).into(), + selection: rgba(0xf187793d).into(), + }, + PlayerColor { + cursor: rgba(0xfed073ff).into(), + background: rgba(0xfed073ff).into(), + selection: rgba(0xfed0733d).into(), + }, + PlayerColor { + cursor: rgba(0xd5fe80ff).into(), + background: rgba(0xd5fe80ff).into(), + selection: rgba(0xd5fe803d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 3db69b5a54..096afc7ee3 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn gruvbox() -> UserThemeFamily { @@ -76,6 +77,48 @@ pub fn gruvbox() -> UserThemeFamily { warning: Some(rgba(0xb57616ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x0b6678ff).into(), + background: rgba(0x0b6678ff).into(), + selection: rgba(0x0b66783d).into(), + }, + PlayerColor { + cursor: rgba(0x7c6f64ff).into(), + background: rgba(0x7c6f64ff).into(), + selection: rgba(0x7c6f643d).into(), + }, + PlayerColor { + cursor: rgba(0xaf3b05ff).into(), + background: rgba(0xaf3b05ff).into(), + selection: rgba(0xaf3b053d).into(), + }, + PlayerColor { + cursor: rgba(0x8f4071ff).into(), + background: rgba(0x8f4071ff).into(), + selection: rgba(0x8f40713d).into(), + }, + PlayerColor { + cursor: rgba(0x437b59ff).into(), + background: rgba(0x437b59ff).into(), + selection: rgba(0x437b593d).into(), + }, + PlayerColor { + cursor: rgba(0x9d0408ff).into(), + background: rgba(0x9d0408ff).into(), + selection: rgba(0x9d04083d).into(), + }, + PlayerColor { + cursor: rgba(0xb57616ff).into(), + background: rgba(0xb57616ff).into(), + selection: rgba(0xb576163d).into(), + }, + PlayerColor { + cursor: rgba(0x797410ff).into(), + background: rgba(0x797410ff).into(), + selection: rgba(0x7974103d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -422,6 +465,48 @@ pub fn gruvbox() -> UserThemeFamily { warning: Some(rgba(0xf9bd30ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x83a598ff).into(), + background: rgba(0x83a598ff).into(), + selection: rgba(0x83a5983d).into(), + }, + PlayerColor { + cursor: rgba(0xa89984ff).into(), + background: rgba(0xa89984ff).into(), + selection: rgba(0xa899843d).into(), + }, + PlayerColor { + cursor: rgba(0xfd801bff).into(), + background: rgba(0xfd801bff).into(), + selection: rgba(0xfd801b3d).into(), + }, + PlayerColor { + cursor: rgba(0xd3869bff).into(), + background: rgba(0xd3869bff).into(), + selection: rgba(0xd3869b3d).into(), + }, + PlayerColor { + cursor: rgba(0x8ec07cff).into(), + background: rgba(0x8ec07cff).into(), + selection: rgba(0x8ec07c3d).into(), + }, + PlayerColor { + cursor: rgba(0xfb4a35ff).into(), + background: rgba(0xfb4a35ff).into(), + selection: rgba(0xfb4a353d).into(), + }, + PlayerColor { + cursor: rgba(0xf9bd30ff).into(), + background: rgba(0xf9bd30ff).into(), + selection: rgba(0xf9bd303d).into(), + }, + PlayerColor { + cursor: rgba(0xb8bb27ff).into(), + background: rgba(0xb8bb27ff).into(), + selection: rgba(0xb8bb273d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -768,6 +853,48 @@ pub fn gruvbox() -> UserThemeFamily { warning: Some(rgba(0xb57616ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x0b6678ff).into(), + background: rgba(0x0b6678ff).into(), + selection: rgba(0x0b66783d).into(), + }, + PlayerColor { + cursor: rgba(0x7c6f64ff).into(), + background: rgba(0x7c6f64ff).into(), + selection: rgba(0x7c6f643d).into(), + }, + PlayerColor { + cursor: rgba(0xaf3b05ff).into(), + background: rgba(0xaf3b05ff).into(), + selection: rgba(0xaf3b053d).into(), + }, + PlayerColor { + cursor: rgba(0x8f4071ff).into(), + background: rgba(0x8f4071ff).into(), + selection: rgba(0x8f40713d).into(), + }, + PlayerColor { + cursor: rgba(0x437b59ff).into(), + background: rgba(0x437b59ff).into(), + selection: rgba(0x437b593d).into(), + }, + PlayerColor { + cursor: rgba(0x9d0408ff).into(), + background: rgba(0x9d0408ff).into(), + selection: rgba(0x9d04083d).into(), + }, + PlayerColor { + cursor: rgba(0xb57616ff).into(), + background: rgba(0xb57616ff).into(), + selection: rgba(0xb576163d).into(), + }, + PlayerColor { + cursor: rgba(0x797410ff).into(), + background: rgba(0x797410ff).into(), + selection: rgba(0x7974103d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -1114,6 +1241,48 @@ pub fn gruvbox() -> UserThemeFamily { warning: Some(rgba(0xf9bd30ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x83a598ff).into(), + background: rgba(0x83a598ff).into(), + selection: rgba(0x83a5983d).into(), + }, + PlayerColor { + cursor: rgba(0xa89984ff).into(), + background: rgba(0xa89984ff).into(), + selection: rgba(0xa899843d).into(), + }, + PlayerColor { + cursor: rgba(0xfd801bff).into(), + background: rgba(0xfd801bff).into(), + selection: rgba(0xfd801b3d).into(), + }, + PlayerColor { + cursor: rgba(0xd3869bff).into(), + background: rgba(0xd3869bff).into(), + selection: rgba(0xd3869b3d).into(), + }, + PlayerColor { + cursor: rgba(0x8ec07cff).into(), + background: rgba(0x8ec07cff).into(), + selection: rgba(0x8ec07c3d).into(), + }, + PlayerColor { + cursor: rgba(0xfb4a35ff).into(), + background: rgba(0xfb4a35ff).into(), + selection: rgba(0xfb4a353d).into(), + }, + PlayerColor { + cursor: rgba(0xf9bd30ff).into(), + background: rgba(0xf9bd30ff).into(), + selection: rgba(0xf9bd303d).into(), + }, + PlayerColor { + cursor: rgba(0xb8bb27ff).into(), + background: rgba(0xb8bb27ff).into(), + selection: rgba(0xb8bb273d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -1460,6 +1629,48 @@ pub fn gruvbox() -> UserThemeFamily { warning: Some(rgba(0xb57616ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x0b6678ff).into(), + background: rgba(0x0b6678ff).into(), + selection: rgba(0x0b66783d).into(), + }, + PlayerColor { + cursor: rgba(0x7c6f64ff).into(), + background: rgba(0x7c6f64ff).into(), + selection: rgba(0x7c6f643d).into(), + }, + PlayerColor { + cursor: rgba(0xaf3b05ff).into(), + background: rgba(0xaf3b05ff).into(), + selection: rgba(0xaf3b053d).into(), + }, + PlayerColor { + cursor: rgba(0x8f4071ff).into(), + background: rgba(0x8f4071ff).into(), + selection: rgba(0x8f40713d).into(), + }, + PlayerColor { + cursor: rgba(0x437b59ff).into(), + background: rgba(0x437b59ff).into(), + selection: rgba(0x437b593d).into(), + }, + PlayerColor { + cursor: rgba(0x9d0408ff).into(), + background: rgba(0x9d0408ff).into(), + selection: rgba(0x9d04083d).into(), + }, + PlayerColor { + cursor: rgba(0xb57616ff).into(), + background: rgba(0xb57616ff).into(), + selection: rgba(0xb576163d).into(), + }, + PlayerColor { + cursor: rgba(0x797410ff).into(), + background: rgba(0x797410ff).into(), + selection: rgba(0x7974103d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -1806,6 +2017,48 @@ pub fn gruvbox() -> UserThemeFamily { warning: Some(rgba(0xf9bd30ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x83a598ff).into(), + background: rgba(0x83a598ff).into(), + selection: rgba(0x83a5983d).into(), + }, + PlayerColor { + cursor: rgba(0xa89984ff).into(), + background: rgba(0xa89984ff).into(), + selection: rgba(0xa899843d).into(), + }, + PlayerColor { + cursor: rgba(0xfd801bff).into(), + background: rgba(0xfd801bff).into(), + selection: rgba(0xfd801b3d).into(), + }, + PlayerColor { + cursor: rgba(0xd3869bff).into(), + background: rgba(0xd3869bff).into(), + selection: rgba(0xd3869b3d).into(), + }, + PlayerColor { + cursor: rgba(0x8ec07cff).into(), + background: rgba(0x8ec07cff).into(), + selection: rgba(0x8ec07c3d).into(), + }, + PlayerColor { + cursor: rgba(0xfb4a35ff).into(), + background: rgba(0xfb4a35ff).into(), + selection: rgba(0xfb4a353d).into(), + }, + PlayerColor { + cursor: rgba(0xf9bd30ff).into(), + background: rgba(0xf9bd30ff).into(), + selection: rgba(0xf9bd303d).into(), + }, + PlayerColor { + cursor: rgba(0xb8bb27ff).into(), + background: rgba(0xb8bb27ff).into(), + selection: rgba(0xb8bb273d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/themes/one.rs b/crates/theme2/src/themes/one.rs index 7ea2bbea87..f4d53404fb 100644 --- a/crates/theme2/src/themes/one.rs +++ b/crates/theme2/src/themes/one.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn one() -> UserThemeFamily { @@ -76,6 +77,48 @@ pub fn one() -> UserThemeFamily { warning: Some(rgba(0xdec184ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x5c79e2ff).into(), + background: rgba(0x5c79e2ff).into(), + selection: rgba(0x5c79e23d).into(), + }, + PlayerColor { + cursor: rgba(0x994fa6ff).into(), + background: rgba(0x994fa6ff).into(), + selection: rgba(0x994fa63d).into(), + }, + PlayerColor { + cursor: rgba(0xad6f27ff).into(), + background: rgba(0xad6f27ff).into(), + selection: rgba(0xad6f273d).into(), + }, + PlayerColor { + cursor: rgba(0xa44aabff).into(), + background: rgba(0xa44aabff).into(), + selection: rgba(0xa44aab3d).into(), + }, + PlayerColor { + cursor: rgba(0x3b82b7ff).into(), + background: rgba(0x3b82b7ff).into(), + selection: rgba(0x3b82b73d).into(), + }, + PlayerColor { + cursor: rgba(0xd36151ff).into(), + background: rgba(0xd36151ff).into(), + selection: rgba(0xd361513d).into(), + }, + PlayerColor { + cursor: rgba(0xdec184ff).into(), + background: rgba(0xdec184ff).into(), + selection: rgba(0xdec1843d).into(), + }, + PlayerColor { + cursor: rgba(0x669f59ff).into(), + background: rgba(0x669f59ff).into(), + selection: rgba(0x669f593d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -422,6 +465,48 @@ pub fn one() -> UserThemeFamily { warning: Some(rgba(0xdec184ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x74ade8ff).into(), + background: rgba(0x74ade8ff).into(), + selection: rgba(0x74ade83d).into(), + }, + PlayerColor { + cursor: rgba(0xbe5046ff).into(), + background: rgba(0xbe5046ff).into(), + selection: rgba(0xbe50463d).into(), + }, + PlayerColor { + cursor: rgba(0xc0966bff).into(), + background: rgba(0xc0966bff).into(), + selection: rgba(0xc0966b3d).into(), + }, + PlayerColor { + cursor: rgba(0xb478cfff).into(), + background: rgba(0xb478cfff).into(), + selection: rgba(0xb478cf3d).into(), + }, + PlayerColor { + cursor: rgba(0x6fb4c0ff).into(), + background: rgba(0x6fb4c0ff).into(), + selection: rgba(0x6fb4c03d).into(), + }, + PlayerColor { + cursor: rgba(0xd07277ff).into(), + background: rgba(0xd07277ff).into(), + selection: rgba(0xd072773d).into(), + }, + PlayerColor { + cursor: rgba(0xdec184ff).into(), + background: rgba(0xdec184ff).into(), + selection: rgba(0xdec1843d).into(), + }, + PlayerColor { + cursor: rgba(0xa1c181ff).into(), + background: rgba(0xa1c181ff).into(), + selection: rgba(0xa1c1813d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index e63e8f2ad8..cc14268a0f 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn rose_pine() -> UserThemeFamily { @@ -76,6 +77,48 @@ pub fn rose_pine() -> UserThemeFamily { warning: Some(rgba(0xe99d35ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x57949fff).into(), + background: rgba(0x57949fff).into(), + selection: rgba(0x57949f3d).into(), + }, + PlayerColor { + cursor: rgba(0x7c697fff).into(), + background: rgba(0x7c697fff).into(), + selection: rgba(0x7c697f3d).into(), + }, + PlayerColor { + cursor: rgba(0x907aa9ff).into(), + background: rgba(0x907aa9ff).into(), + selection: rgba(0x907aa93d).into(), + }, + PlayerColor { + cursor: rgba(0x907aa9ff).into(), + background: rgba(0x907aa9ff).into(), + selection: rgba(0x907aa93d).into(), + }, + PlayerColor { + cursor: rgba(0x2a6983ff).into(), + background: rgba(0x2a6983ff).into(), + selection: rgba(0x2a69833d).into(), + }, + PlayerColor { + cursor: rgba(0xb4647aff).into(), + background: rgba(0xb4647aff).into(), + selection: rgba(0xb4647a3d).into(), + }, + PlayerColor { + cursor: rgba(0xe99d35ff).into(), + background: rgba(0xe99d35ff).into(), + selection: rgba(0xe99d353d).into(), + }, + PlayerColor { + cursor: rgba(0x3eaa8eff).into(), + background: rgba(0x3eaa8eff).into(), + selection: rgba(0x3eaa8e3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -429,6 +472,48 @@ pub fn rose_pine() -> UserThemeFamily { warning: Some(rgba(0xf5c177ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x9cced7ff).into(), + background: rgba(0x9cced7ff).into(), + selection: rgba(0x9cced73d).into(), + }, + PlayerColor { + cursor: rgba(0xa784a1ff).into(), + background: rgba(0xa784a1ff).into(), + selection: rgba(0xa784a13d).into(), + }, + PlayerColor { + cursor: rgba(0xc4a7e6ff).into(), + background: rgba(0xc4a7e6ff).into(), + selection: rgba(0xc4a7e63d).into(), + }, + PlayerColor { + cursor: rgba(0xc4a7e6ff).into(), + background: rgba(0xc4a7e6ff).into(), + selection: rgba(0xc4a7e63d).into(), + }, + PlayerColor { + cursor: rgba(0x3f8fb0ff).into(), + background: rgba(0x3f8fb0ff).into(), + selection: rgba(0x3f8fb03d).into(), + }, + PlayerColor { + cursor: rgba(0xea6f92ff).into(), + background: rgba(0xea6f92ff).into(), + selection: rgba(0xea6f923d).into(), + }, + PlayerColor { + cursor: rgba(0xf5c177ff).into(), + background: rgba(0xf5c177ff).into(), + selection: rgba(0xf5c1773d).into(), + }, + PlayerColor { + cursor: rgba(0x5dc2a3ff).into(), + background: rgba(0x5dc2a3ff).into(), + selection: rgba(0x5dc2a33d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -782,6 +867,48 @@ pub fn rose_pine() -> UserThemeFamily { warning: Some(rgba(0xf5c177ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x9cced7ff).into(), + background: rgba(0x9cced7ff).into(), + selection: rgba(0x9cced73d).into(), + }, + PlayerColor { + cursor: rgba(0x9d7691ff).into(), + background: rgba(0x9d7691ff).into(), + selection: rgba(0x9d76913d).into(), + }, + PlayerColor { + cursor: rgba(0xc4a7e6ff).into(), + background: rgba(0xc4a7e6ff).into(), + selection: rgba(0xc4a7e63d).into(), + }, + PlayerColor { + cursor: rgba(0xc4a7e6ff).into(), + background: rgba(0xc4a7e6ff).into(), + selection: rgba(0xc4a7e63d).into(), + }, + PlayerColor { + cursor: rgba(0x32748fff).into(), + background: rgba(0x32748fff).into(), + selection: rgba(0x32748f3d).into(), + }, + PlayerColor { + cursor: rgba(0xea6f92ff).into(), + background: rgba(0xea6f92ff).into(), + selection: rgba(0xea6f923d).into(), + }, + PlayerColor { + cursor: rgba(0xf5c177ff).into(), + background: rgba(0xf5c177ff).into(), + selection: rgba(0xf5c1773d).into(), + }, + PlayerColor { + cursor: rgba(0x5dc2a3ff).into(), + background: rgba(0x5dc2a3ff).into(), + selection: rgba(0x5dc2a33d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/themes/sandcastle.rs b/crates/theme2/src/themes/sandcastle.rs index 3e66ce97c1..ddcd06bec5 100644 --- a/crates/theme2/src/themes/sandcastle.rs +++ b/crates/theme2/src/themes/sandcastle.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn sandcastle() -> UserThemeFamily { @@ -75,6 +76,48 @@ pub fn sandcastle() -> UserThemeFamily { warning: Some(rgba(0xa07e3bff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x528b8bff).into(), + background: rgba(0x528b8bff).into(), + selection: rgba(0x528b8b3d).into(), + }, + PlayerColor { + cursor: rgba(0xa87323ff).into(), + background: rgba(0xa87323ff).into(), + selection: rgba(0xa873233d).into(), + }, + PlayerColor { + cursor: rgba(0xa07e3bff).into(), + background: rgba(0xa07e3bff).into(), + selection: rgba(0xa07e3b3d).into(), + }, + PlayerColor { + cursor: rgba(0xd75f5fff).into(), + background: rgba(0xd75f5fff).into(), + selection: rgba(0xd75f5f3d).into(), + }, + PlayerColor { + cursor: rgba(0x83a598ff).into(), + background: rgba(0x83a598ff).into(), + selection: rgba(0x83a5983d).into(), + }, + PlayerColor { + cursor: rgba(0xb4637aff).into(), + background: rgba(0xb4637aff).into(), + selection: rgba(0xb4637a3d).into(), + }, + PlayerColor { + cursor: rgba(0xa07e3bff).into(), + background: rgba(0xa07e3bff).into(), + selection: rgba(0xa07e3b3d).into(), + }, + PlayerColor { + cursor: rgba(0x83a598ff).into(), + background: rgba(0x83a598ff).into(), + selection: rgba(0x83a5983d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index 61c3fc8539..7bf383e854 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn solarized() -> UserThemeFamily { @@ -76,6 +77,48 @@ pub fn solarized() -> UserThemeFamily { warning: Some(rgba(0xb58904ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x298bd1ff).into(), + background: rgba(0x298bd1ff).into(), + selection: rgba(0x298bd13d).into(), + }, + PlayerColor { + cursor: rgba(0xd33882ff).into(), + background: rgba(0xd33882ff).into(), + selection: rgba(0xd338823d).into(), + }, + PlayerColor { + cursor: rgba(0xcb4c18ff).into(), + background: rgba(0xcb4c18ff).into(), + selection: rgba(0xcb4c183d).into(), + }, + PlayerColor { + cursor: rgba(0x6d71c4ff).into(), + background: rgba(0x6d71c4ff).into(), + selection: rgba(0x6d71c43d).into(), + }, + PlayerColor { + cursor: rgba(0x2ca198ff).into(), + background: rgba(0x2ca198ff).into(), + selection: rgba(0x2ca1983d).into(), + }, + PlayerColor { + cursor: rgba(0xdc3330ff).into(), + background: rgba(0xdc3330ff).into(), + selection: rgba(0xdc33303d).into(), + }, + PlayerColor { + cursor: rgba(0xb58904ff).into(), + background: rgba(0xb58904ff).into(), + selection: rgba(0xb589043d).into(), + }, + PlayerColor { + cursor: rgba(0x859904ff).into(), + background: rgba(0x859904ff).into(), + selection: rgba(0x8599043d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( @@ -415,6 +458,48 @@ pub fn solarized() -> UserThemeFamily { warning: Some(rgba(0xb58903ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x288bd1ff).into(), + background: rgba(0x288bd1ff).into(), + selection: rgba(0x288bd13d).into(), + }, + PlayerColor { + cursor: rgba(0xd33782ff).into(), + background: rgba(0xd33782ff).into(), + selection: rgba(0xd337823d).into(), + }, + PlayerColor { + cursor: rgba(0xcb4b17ff).into(), + background: rgba(0xcb4b17ff).into(), + selection: rgba(0xcb4b173d).into(), + }, + PlayerColor { + cursor: rgba(0x6c71c4ff).into(), + background: rgba(0x6c71c4ff).into(), + selection: rgba(0x6c71c43d).into(), + }, + PlayerColor { + cursor: rgba(0x2ca198ff).into(), + background: rgba(0x2ca198ff).into(), + selection: rgba(0x2ca1983d).into(), + }, + PlayerColor { + cursor: rgba(0xdc3330ff).into(), + background: rgba(0xdc3330ff).into(), + selection: rgba(0xdc33303d).into(), + }, + PlayerColor { + cursor: rgba(0xb58903ff).into(), + background: rgba(0xb58903ff).into(), + selection: rgba(0xb589033d).into(), + }, + PlayerColor { + cursor: rgba(0x859904ff).into(), + background: rgba(0x859904ff).into(), + selection: rgba(0x8599043d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/themes/summercamp.rs b/crates/theme2/src/themes/summercamp.rs index 3540d824d2..64f51231ae 100644 --- a/crates/theme2/src/themes/summercamp.rs +++ b/crates/theme2/src/themes/summercamp.rs @@ -5,8 +5,9 @@ use gpui::rgba; #[allow(unused)] use crate::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, + UserThemeStylesRefinement, }; pub fn summercamp() -> UserThemeFamily { @@ -75,6 +76,48 @@ pub fn summercamp() -> UserThemeFamily { warning: Some(rgba(0xf1fe29ff).into()), ..Default::default() }, + player: Some(PlayerColors(vec![ + PlayerColor { + cursor: rgba(0x499befff).into(), + background: rgba(0x499befff).into(), + selection: rgba(0x499bef3d).into(), + }, + PlayerColor { + cursor: rgba(0xf59be6ff).into(), + background: rgba(0xf59be6ff).into(), + selection: rgba(0xf59be63d).into(), + }, + PlayerColor { + cursor: rgba(0xfaa11dff).into(), + background: rgba(0xfaa11dff).into(), + selection: rgba(0xfaa11d3d).into(), + }, + PlayerColor { + cursor: rgba(0xfe8080ff).into(), + background: rgba(0xfe8080ff).into(), + selection: rgba(0xfe80803d).into(), + }, + PlayerColor { + cursor: rgba(0x5beabcff).into(), + background: rgba(0x5beabcff).into(), + selection: rgba(0x5beabc3d).into(), + }, + PlayerColor { + cursor: rgba(0xe35142ff).into(), + background: rgba(0xe35142ff).into(), + selection: rgba(0xe351423d).into(), + }, + PlayerColor { + cursor: rgba(0xf1fe29ff).into(), + background: rgba(0xf1fe29ff).into(), + selection: rgba(0xf1fe293d).into(), + }, + PlayerColor { + cursor: rgba(0x5dea5aff).into(), + background: rgba(0x5dea5aff).into(), + selection: rgba(0x5dea5a3d).into(), + }, + ])), syntax: Some(UserSyntaxTheme { highlights: vec![ ( diff --git a/crates/theme2/src/user_theme.rs b/crates/theme2/src/user_theme.rs index e42b7b2905..d34f066c3b 100644 --- a/crates/theme2/src/user_theme.rs +++ b/crates/theme2/src/user_theme.rs @@ -1,4 +1,7 @@ -use crate::{Appearance, StatusColors, StatusColorsRefinement, ThemeColors, ThemeColorsRefinement}; +use crate::{ + Appearance, PlayerColors, StatusColors, StatusColorsRefinement, ThemeColors, + ThemeColorsRefinement, +}; use gpui::{FontStyle, FontWeight, Hsla}; use refineable::Refineable; use serde::Deserialize; @@ -24,6 +27,7 @@ pub struct UserThemeStyles { pub colors: ThemeColors, #[refineable] pub status: StatusColors, + pub player: PlayerColors, pub syntax: UserSyntaxTheme, } diff --git a/crates/theme_importer/src/main.rs b/crates/theme_importer/src/main.rs index 4072a59df8..19644c9816 100644 --- a/crates/theme_importer/src/main.rs +++ b/crates/theme_importer/src/main.rs @@ -316,8 +316,9 @@ fn main() -> Result<()> { #[allow(unused)] use crate::{{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserHighlightStyle, UserSyntaxTheme, - UserTheme, UserThemeFamily, UserThemeStylesRefinement, UserFontWeight, UserFontStyle + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeFamily, UserThemeStylesRefinement, + UserFontWeight, UserFontStyle }}; pub fn {theme_family_slug}() -> UserThemeFamily {{ diff --git a/crates/theme_importer/src/theme_printer.rs b/crates/theme_importer/src/theme_printer.rs index 2116b5b670..54f99e3b4c 100644 --- a/crates/theme_importer/src/theme_printer.rs +++ b/crates/theme_importer/src/theme_printer.rs @@ -107,6 +107,16 @@ impl<'a> Debug for UserThemeStylesRefinementPrinter<'a> { f.debug_struct("UserThemeStylesRefinement") .field("colors", &ThemeColorsRefinementPrinter(&self.0.colors)) .field("status", &StatusColorsRefinementPrinter(&self.0.status)) + .field( + "player", + &OptionPrinter( + &self + .0 + .player + .as_ref() + .map(|player_colors| PlayerColorsPrinter(player_colors)), + ), + ) .field( "syntax", &OptionPrinter( diff --git a/crates/theme_importer/src/vscode/converter.rs b/crates/theme_importer/src/vscode/converter.rs index 41534d0d0e..13297a91aa 100644 --- a/crates/theme_importer/src/vscode/converter.rs +++ b/crates/theme_importer/src/vscode/converter.rs @@ -61,6 +61,7 @@ impl VsCodeThemeConverter { styles: UserThemeStylesRefinement { colors: theme_colors_refinements, status: status_color_refinements, + player: None, syntax: Some(syntax_theme), }, }) diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs index d2f156246e..385ad43350 100644 --- a/crates/theme_importer/src/zed1/converter.rs +++ b/crates/theme_importer/src/zed1/converter.rs @@ -3,8 +3,9 @@ use gpui::{Hsla, Rgba}; use gpui1::color::Color as Zed1Color; use gpui1::fonts::HighlightStyle as Zed1HighlightStyle; use theme::{ - Appearance, StatusColorsRefinement, ThemeColorsRefinement, UserFontStyle, UserFontWeight, - UserHighlightStyle, UserSyntaxTheme, UserTheme, UserThemeStylesRefinement, + Appearance, PlayerColor, PlayerColors, StatusColorsRefinement, ThemeColorsRefinement, + UserFontStyle, UserFontWeight, UserHighlightStyle, UserSyntaxTheme, UserTheme, + UserThemeStylesRefinement, }; use theme1::Theme as Zed1Theme; @@ -50,6 +51,7 @@ impl Zed1ThemeConverter { let status_colors_refinement = self.convert_status_colors()?; let theme_colors_refinement = self.convert_theme_colors()?; + let player_colors = self.convert_player_colors()?; let syntax_theme = self.convert_syntax_theme()?; Ok(UserTheme { @@ -58,6 +60,7 @@ impl Zed1ThemeConverter { styles: UserThemeStylesRefinement { colors: theme_colors_refinement, status: status_colors_refinement, + player: Some(player_colors), syntax: Some(syntax_theme), }, }) @@ -82,6 +85,31 @@ impl Zed1ThemeConverter { }) } + fn convert_player_colors(&self) -> Result { + let player_one = self.theme.editor.selection; + + let mut player_colors = vec![PlayerColor { + cursor: zed1_color_to_hsla(player_one.cursor), + selection: zed1_color_to_hsla(player_one.selection), + background: zed1_color_to_hsla(player_one.cursor), + }]; + + for index in 1..8 { + let player = self + .theme + .editor + .selection_style_for_room_participant(index); + + player_colors.push(PlayerColor { + cursor: zed1_color_to_hsla(player.cursor), + selection: zed1_color_to_hsla(player.selection), + background: zed1_color_to_hsla(player.cursor), + }); + } + + Ok(PlayerColors(player_colors)) + } + fn convert_theme_colors(&self) -> Result { fn convert(color: Zed1Color) -> Option { Some(zed1_color_to_hsla(color)) From 698460ea897723bf23253e6e6411f70168844258 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Fri, 22 Dec 2023 23:06:30 -0500 Subject: [PATCH 321/644] Style inlay hints (#3806) This PR styles the inlay hints after the changes to the themes. Release Notes: - N/A --- crates/editor2/src/editor.rs | 4 ---- crates/theme2/src/themes/andromeda.rs | 1 + crates/theme2/src/themes/atelier.rs | 20 ++++++++++++++++++++ crates/theme2/src/themes/ayu.rs | 3 +++ crates/theme2/src/themes/gruvbox.rs | 6 ++++++ crates/theme2/src/themes/one.rs | 2 ++ crates/theme2/src/themes/rose_pine.rs | 3 +++ crates/theme2/src/themes/sandcastle.rs | 1 + crates/theme2/src/themes/solarized.rs | 2 ++ crates/theme2/src/themes/summercamp.rs | 1 + crates/theme_importer/src/zed1/converter.rs | 2 ++ 11 files changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index 943ddf47bd..d3ee41b11f 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -7676,12 +7676,10 @@ impl Editor { inlays_style: HighlightStyle { color: Some(cx.theme().status().hint), font_weight: Some(FontWeight::BOLD), - fade_out: Some(0.6), ..HighlightStyle::default() }, suggestions_style: HighlightStyle { color: Some(cx.theme().status().predictive), - fade_out: Some(0.6), ..HighlightStyle::default() }, }, @@ -9348,12 +9346,10 @@ impl Render for Editor { inlays_style: HighlightStyle { color: Some(cx.theme().status().hint), font_weight: Some(FontWeight::BOLD), - fade_out: Some(0.6), ..HighlightStyle::default() }, suggestions_style: HighlightStyle { color: Some(cx.theme().status().predictive), - fade_out: Some(0.6), ..HighlightStyle::default() }, }, diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index 67c18f88ad..0a9b977d21 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -71,6 +71,7 @@ pub fn andromeda() -> UserThemeFamily { created: Some(rgba(0x96df72ff).into()), deleted: Some(rgba(0xcd1d5aff).into()), error: Some(rgba(0xf82872ff).into()), + hint: Some(rgba(0x618399ff).into()), modified: Some(rgba(0xfee56dff).into()), success: Some(rgba(0xf7f7f8ff).into()), warning: Some(rgba(0xfee56dff).into()), diff --git a/crates/theme2/src/themes/atelier.rs b/crates/theme2/src/themes/atelier.rs index d6681aa6b1..e5c2e49d5b 100644 --- a/crates/theme2/src/themes/atelier.rs +++ b/crates/theme2/src/themes/atelier.rs @@ -72,6 +72,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x98ab54ff).into()), deleted: Some(rgba(0xba6337ff).into()), error: Some(rgba(0xba6337ff).into()), + hint: Some(rgba(0x768962ff).into()), modified: Some(rgba(0xa59810ff).into()), success: Some(rgba(0x22221bff).into()), warning: Some(rgba(0xa59810ff).into()), @@ -474,6 +475,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x7b9727ff).into()), deleted: Some(rgba(0xc82234ff).into()), error: Some(rgba(0xf22d40ff).into()), + hint: Some(rgba(0xa87187ff).into()), modified: Some(rgba(0xc38419ff).into()), success: Some(rgba(0xf1efeeff).into()), warning: Some(rgba(0xc38419ff).into()), @@ -876,6 +878,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x6fae80ff).into()), deleted: Some(rgba(0xb1623aff).into()), error: Some(rgba(0xb1623aff).into()), + hint: Some(rgba(0x66847cff).into()), modified: Some(rgba(0xa07e3cff).into()), success: Some(rgba(0x171c19ff).into()), warning: Some(rgba(0xa07e3cff).into()), @@ -1278,6 +1281,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x2c9292ff).into()), deleted: Some(rgba(0x953a5fff).into()), error: Some(rgba(0xbe4678ff).into()), + hint: Some(rgba(0x716998ff).into()), modified: Some(rgba(0xa06e3bff).into()), success: Some(rgba(0xefecf4ff).into()), warning: Some(rgba(0xa06e3bff).into()), @@ -1680,6 +1684,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x7d9727ff).into()), deleted: Some(rgba(0x934e2dff).into()), error: Some(rgba(0xba6237ff).into()), + hint: Some(rgba(0x70825bff).into()), modified: Some(rgba(0xa59810ff).into()), success: Some(rgba(0xf4f3ecff).into()), warning: Some(rgba(0xa59810ff).into()), @@ -2082,6 +2087,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0xac973aff).into()), deleted: Some(rgba(0xa33a1eff).into()), error: Some(rgba(0xc94923ff).into()), + hint: Some(rgba(0x6d82a6ff).into()), modified: Some(rgba(0xc08b31ff).into()), success: Some(rgba(0xf5f7ffff).into()), warning: Some(rgba(0xc08b31ff).into()), @@ -2484,6 +2490,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0xbfab61ff).into()), deleted: Some(rgba(0xc94a23ff).into()), error: Some(rgba(0xc94a23ff).into()), + hint: Some(rgba(0x7087b2ff).into()), modified: Some(rgba(0xc08b31ff).into()), success: Some(rgba(0x202746ff).into()), warning: Some(rgba(0xc08b31ff).into()), @@ -2886,6 +2893,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x60ac3aff).into()), deleted: Some(rgba(0xaf2c2eff).into()), error: Some(rgba(0xd73837ff).into()), + hint: Some(rgba(0xb17272ff).into()), modified: Some(rgba(0xae9515ff).into()), success: Some(rgba(0xfefbecff).into()), warning: Some(rgba(0xae9515ff).into()), @@ -3288,6 +3296,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x2ba32aff).into()), deleted: Some(rgba(0xbd1331ff).into()), error: Some(rgba(0xe61c3cff).into()), + hint: Some(rgba(0x008b9fff).into()), modified: Some(rgba(0x98981cff).into()), success: Some(rgba(0xf4fbf4ff).into()), warning: Some(rgba(0x98981cff).into()), @@ -3690,6 +3699,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x5fa8a7ff).into()), deleted: Some(rgba(0xbe4778ff).into()), error: Some(rgba(0xbe4778ff).into()), + hint: Some(rgba(0x786e9dff).into()), modified: Some(rgba(0xa06e3cff).into()), success: Some(rgba(0x19171cff).into()), warning: Some(rgba(0xa06e3cff).into()), @@ -4092,6 +4102,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x4b8b8bff).into()), deleted: Some(rgba(0xa23b3bff).into()), error: Some(rgba(0xca4949ff).into()), + hint: Some(rgba(0x8a647aff).into()), modified: Some(rgba(0xa06e3bff).into()), success: Some(rgba(0xf4ececff).into()), warning: Some(rgba(0xa06e3bff).into()), @@ -4494,6 +4505,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x918b3bff).into()), deleted: Some(rgba(0xa43424ff).into()), error: Some(rgba(0xca402cff).into()), + hint: Some(rgba(0x8d70a8ff).into()), modified: Some(rgba(0xbb8a36ff).into()), success: Some(rgba(0xf7f3f7ff).into()), warning: Some(rgba(0xbb8a36ff).into()), @@ -4896,6 +4908,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x568c3bff).into()), deleted: Some(rgba(0xa9275aff).into()), error: Some(rgba(0xd22e72ff).into()), + hint: Some(rgba(0x52809aff).into()), modified: Some(rgba(0x8a8a11ff).into()), success: Some(rgba(0xebf8ffff).into()), warning: Some(rgba(0x8a8a11ff).into()), @@ -5298,6 +5311,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x97ab54ff).into()), deleted: Some(rgba(0xf22e41ff).into()), error: Some(rgba(0xf22e41ff).into()), + hint: Some(rgba(0xa67287ff).into()), modified: Some(rgba(0xc3841aff).into()), success: Some(rgba(0x1b1918ff).into()), warning: Some(rgba(0xc3841aff).into()), @@ -5700,6 +5714,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x83bd62ff).into()), deleted: Some(rgba(0xd73838ff).into()), error: Some(rgba(0xd73838ff).into()), + hint: Some(rgba(0xb37979ff).into()), modified: Some(rgba(0xae9515ff).into()), success: Some(rgba(0x20201dff).into()), warning: Some(rgba(0xae9515ff).into()), @@ -6102,6 +6117,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x70a2a1ff).into()), deleted: Some(rgba(0xca4a4aff).into()), error: Some(rgba(0xca4a4aff).into()), + hint: Some(rgba(0x916a80ff).into()), modified: Some(rgba(0xa06e3cff).into()), success: Some(rgba(0x1b1818ff).into()), warning: Some(rgba(0xa06e3cff).into()), @@ -6504,6 +6520,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x61b656ff).into()), deleted: Some(rgba(0xe61c3dff).into()), error: Some(rgba(0xe61c3dff).into()), + hint: Some(rgba(0x008fa1ff).into()), modified: Some(rgba(0x98981dff).into()), success: Some(rgba(0x131513ff).into()), warning: Some(rgba(0x98981dff).into()), @@ -6906,6 +6923,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x489963ff).into()), deleted: Some(rgba(0x8b4d2fff).into()), error: Some(rgba(0xb16139ff).into()), + hint: Some(rgba(0x607e76ff).into()), modified: Some(rgba(0xa07e3bff).into()), success: Some(rgba(0xecf4eeff).into()), warning: Some(rgba(0xa07e3bff).into()), @@ -7308,6 +7326,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0xa8a161ff).into()), deleted: Some(rgba(0xca412cff).into()), error: Some(rgba(0xca412cff).into()), + hint: Some(rgba(0x8c70a6ff).into()), modified: Some(rgba(0xbb8a36ff).into()), success: Some(rgba(0x1b181bff).into()), warning: Some(rgba(0xbb8a36ff).into()), @@ -7710,6 +7729,7 @@ pub fn atelier() -> UserThemeFamily { created: Some(rgba(0x78a361ff).into()), deleted: Some(rgba(0xd22f72ff).into()), error: Some(rgba(0xd22f72ff).into()), + hint: Some(rgba(0x5a87a0ff).into()), modified: Some(rgba(0x8a8a11ff).into()), success: Some(rgba(0x161b1dff).into()), warning: Some(rgba(0x8a8a11ff).into()), diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index 4ea839eaa9..7c0eb70108 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -72,6 +72,7 @@ pub fn ayu() -> UserThemeFamily { created: Some(rgba(0xaad84cff).into()), deleted: Some(rgba(0xc3595fff).into()), error: Some(rgba(0xef7178ff).into()), + hint: Some(rgba(0x638c81ff).into()), modified: Some(rgba(0xfeb454ff).into()), success: Some(rgba(0xbfbdb6ff).into()), warning: Some(rgba(0xfeb454ff).into()), @@ -453,6 +454,7 @@ pub fn ayu() -> UserThemeFamily { created: Some(rgba(0xa1c24bff).into()), deleted: Some(rgba(0xef7271ff).into()), error: Some(rgba(0xef7271ff).into()), + hint: Some(rgba(0x8ca7c2ff).into()), modified: Some(rgba(0xf1ae4aff).into()), success: Some(rgba(0x5c6166ff).into()), warning: Some(rgba(0xf1ae4aff).into()), @@ -834,6 +836,7 @@ pub fn ayu() -> UserThemeFamily { created: Some(rgba(0xd5fe80ff).into()), deleted: Some(rgba(0xc46a60ff).into()), error: Some(rgba(0xf18779ff).into()), + hint: Some(rgba(0x7399a3ff).into()), modified: Some(rgba(0xfed073ff).into()), success: Some(rgba(0xcccac2ff).into()), warning: Some(rgba(0xfed073ff).into()), diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 096afc7ee3..8cc13fb177 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -72,6 +72,7 @@ pub fn gruvbox() -> UserThemeFamily { created: Some(rgba(0x958e43ff).into()), deleted: Some(rgba(0x9d0408ff).into()), error: Some(rgba(0x9d0408ff).into()), + hint: Some(rgba(0x677562ff).into()), modified: Some(rgba(0xb57616ff).into()), success: Some(rgba(0x282828ff).into()), warning: Some(rgba(0xb57616ff).into()), @@ -460,6 +461,7 @@ pub fn gruvbox() -> UserThemeFamily { created: Some(rgba(0xb8bb27ff).into()), deleted: Some(rgba(0xd0382bff).into()), error: Some(rgba(0xfb4a35ff).into()), + hint: Some(rgba(0x8d957eff).into()), modified: Some(rgba(0xf9bd30ff).into()), success: Some(rgba(0xfbf1c7ff).into()), warning: Some(rgba(0xf9bd30ff).into()), @@ -848,6 +850,7 @@ pub fn gruvbox() -> UserThemeFamily { created: Some(rgba(0x958e43ff).into()), deleted: Some(rgba(0x9d0408ff).into()), error: Some(rgba(0x9d0408ff).into()), + hint: Some(rgba(0x677562ff).into()), modified: Some(rgba(0xb57616ff).into()), success: Some(rgba(0x282828ff).into()), warning: Some(rgba(0xb57616ff).into()), @@ -1236,6 +1239,7 @@ pub fn gruvbox() -> UserThemeFamily { created: Some(rgba(0xb8bb27ff).into()), deleted: Some(rgba(0xd0382bff).into()), error: Some(rgba(0xfb4a35ff).into()), + hint: Some(rgba(0x8d957eff).into()), modified: Some(rgba(0xf9bd30ff).into()), success: Some(rgba(0xfbf1c7ff).into()), warning: Some(rgba(0xf9bd30ff).into()), @@ -1624,6 +1628,7 @@ pub fn gruvbox() -> UserThemeFamily { created: Some(rgba(0x958e43ff).into()), deleted: Some(rgba(0x9d0408ff).into()), error: Some(rgba(0x9d0408ff).into()), + hint: Some(rgba(0x677562ff).into()), modified: Some(rgba(0xb57616ff).into()), success: Some(rgba(0x282828ff).into()), warning: Some(rgba(0xb57616ff).into()), @@ -2012,6 +2017,7 @@ pub fn gruvbox() -> UserThemeFamily { created: Some(rgba(0xb8bb27ff).into()), deleted: Some(rgba(0xd0382bff).into()), error: Some(rgba(0xfb4a35ff).into()), + hint: Some(rgba(0x8d957eff).into()), modified: Some(rgba(0xf9bd30ff).into()), success: Some(rgba(0xfbf1c7ff).into()), warning: Some(rgba(0xf9bd30ff).into()), diff --git a/crates/theme2/src/themes/one.rs b/crates/theme2/src/themes/one.rs index f4d53404fb..e62ccbefdd 100644 --- a/crates/theme2/src/themes/one.rs +++ b/crates/theme2/src/themes/one.rs @@ -72,6 +72,7 @@ pub fn one() -> UserThemeFamily { created: Some(rgba(0x84b278ff).into()), deleted: Some(rgba(0xd36151ff).into()), error: Some(rgba(0xd36151ff).into()), + hint: Some(rgba(0x9295beff).into()), modified: Some(rgba(0xdec184ff).into()), success: Some(rgba(0x383a41ff).into()), warning: Some(rgba(0xdec184ff).into()), @@ -460,6 +461,7 @@ pub fn one() -> UserThemeFamily { created: Some(rgba(0xa1c181ff).into()), deleted: Some(rgba(0xa45a5eff).into()), error: Some(rgba(0xd07277ff).into()), + hint: Some(rgba(0x5b708aff).into()), modified: Some(rgba(0xdec184ff).into()), success: Some(rgba(0xc8ccd4ff).into()), warning: Some(rgba(0xdec184ff).into()), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index cc14268a0f..318767cb2b 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -72,6 +72,7 @@ pub fn rose_pine() -> UserThemeFamily { created: Some(rgba(0x6bbca3ff).into()), deleted: Some(rgba(0xb4647aff).into()), error: Some(rgba(0xb4647aff).into()), + hint: Some(rgba(0x7a92aaff).into()), modified: Some(rgba(0xe99d35ff).into()), success: Some(rgba(0x575279ff).into()), warning: Some(rgba(0xe99d35ff).into()), @@ -467,6 +468,7 @@ pub fn rose_pine() -> UserThemeFamily { created: Some(rgba(0x5dc2a3ff).into()), deleted: Some(rgba(0xbe5773ff).into()), error: Some(rgba(0xea6f92ff).into()), + hint: Some(rgba(0x728aa2ff).into()), modified: Some(rgba(0xf5c177ff).into()), success: Some(rgba(0xe0def4ff).into()), warning: Some(rgba(0xf5c177ff).into()), @@ -862,6 +864,7 @@ pub fn rose_pine() -> UserThemeFamily { created: Some(rgba(0x5dc2a3ff).into()), deleted: Some(rgba(0xbe5773ff).into()), error: Some(rgba(0xea6f92ff).into()), + hint: Some(rgba(0x5e768cff).into()), modified: Some(rgba(0xf5c177ff).into()), success: Some(rgba(0xe0def4ff).into()), warning: Some(rgba(0xf5c177ff).into()), diff --git a/crates/theme2/src/themes/sandcastle.rs b/crates/theme2/src/themes/sandcastle.rs index ddcd06bec5..5aa0398874 100644 --- a/crates/theme2/src/themes/sandcastle.rs +++ b/crates/theme2/src/themes/sandcastle.rs @@ -71,6 +71,7 @@ pub fn sandcastle() -> UserThemeFamily { created: Some(rgba(0x83a598ff).into()), deleted: Some(rgba(0x8d4f61ff).into()), error: Some(rgba(0xb4637aff).into()), + hint: Some(rgba(0x727d68ff).into()), modified: Some(rgba(0xa07e3bff).into()), success: Some(rgba(0xfdf4c1ff).into()), warning: Some(rgba(0xa07e3bff).into()), diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index 7bf383e854..c71ce54a2f 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -72,6 +72,7 @@ pub fn solarized() -> UserThemeFamily { created: Some(rgba(0xa0ad46ff).into()), deleted: Some(rgba(0xdc3330ff).into()), error: Some(rgba(0xdc3330ff).into()), + hint: Some(rgba(0x5889a3ff).into()), modified: Some(rgba(0xb58904ff).into()), success: Some(rgba(0x002b36ff).into()), warning: Some(rgba(0xb58904ff).into()), @@ -453,6 +454,7 @@ pub fn solarized() -> UserThemeFamily { created: Some(rgba(0x859904ff).into()), deleted: Some(rgba(0xb52727ff).into()), error: Some(rgba(0xdc3330ff).into()), + hint: Some(rgba(0x4f8297ff).into()), modified: Some(rgba(0xb58903ff).into()), success: Some(rgba(0xfdf6e3ff).into()), warning: Some(rgba(0xb58903ff).into()), diff --git a/crates/theme2/src/themes/summercamp.rs b/crates/theme2/src/themes/summercamp.rs index 64f51231ae..a849988f7b 100644 --- a/crates/theme2/src/themes/summercamp.rs +++ b/crates/theme2/src/themes/summercamp.rs @@ -71,6 +71,7 @@ pub fn summercamp() -> UserThemeFamily { created: Some(rgba(0x5dea5aff).into()), deleted: Some(rgba(0xb93f36ff).into()), error: Some(rgba(0xe35142ff).into()), + hint: Some(rgba(0x246e61ff).into()), modified: Some(rgba(0xf1fe29ff).into()), success: Some(rgba(0xf8f5deff).into()), warning: Some(rgba(0xf1fe29ff).into()), diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs index 385ad43350..a12d96054c 100644 --- a/crates/theme_importer/src/zed1/converter.rs +++ b/crates/theme_importer/src/zed1/converter.rs @@ -71,6 +71,7 @@ impl Zed1ThemeConverter { Some(zed1_color_to_hsla(color)) } + let editor = &self.theme.editor; let diff_style = &self.theme.editor.diff; let diagnostic_summary = &self.theme.workspace.status_bar.diagnostic_summary; @@ -81,6 +82,7 @@ impl Zed1ThemeConverter { success: convert(diagnostic_summary.icon_color_ok), warning: convert(diagnostic_summary.icon_color_warning), error: convert(diagnostic_summary.icon_color_error), + hint: editor.hint.color.map(zed1_color_to_hsla), ..Default::default() }) } From e839dc5ee62d2b86c18c0666c47b5fbb9127d62f Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 23 Dec 2023 21:53:08 +0200 Subject: [PATCH 322/644] Hide pane tab bar for 0 items, hide its end buttons for no focus --- crates/workspace2/src/pane.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index bcf36dfe18..ecbebcfa36 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -1684,9 +1684,11 @@ impl Pane { .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), ), ) - .end_child({ - let render_tab_buttons = self.render_tab_bar_buttons.clone(); - render_tab_buttons(self, cx) + .when(self.has_focus(cx), |tab_bar| { + tab_bar.end_child({ + let render_tab_buttons = self.render_tab_bar_buttons.clone(); + render_tab_buttons(self, cx) + }) }) .children( self.items @@ -1937,7 +1939,9 @@ impl Render for Pane { }) }), ) - .child(self.render_tab_bar(cx)) + .when(self.active_item().is_some(), |pane| { + pane.child(self.render_tab_bar(cx)) + }) .child({ let has_worktrees = self.project.read(cx).worktrees().next().is_some(); // main content From a249375f991eaaef2a2ea9d84d66112bacc602ae Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 23 Dec 2023 22:10:11 +0200 Subject: [PATCH 323/644] Do not show nav history buttons in terminal pane --- crates/terminal_view2/src/terminal_panel.rs | 1 + crates/workspace2/src/pane.rs | 56 ++++++++++++--------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index 044a9f3aa8..dd0c7d3999 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -74,6 +74,7 @@ impl TerminalPanel { ); pane.set_can_split(false, cx); pane.set_can_navigate(false, cx); + pane.display_nav_history_buttons(false); pane.set_render_tab_bar_buttons(cx, move |pane, cx| { h_stack() .gap_2() diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index ecbebcfa36..bdb95deb56 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -187,6 +187,7 @@ pub struct Pane { render_tab_bar_buttons: Rc) -> AnyElement>, _subscriptions: Vec, tab_bar_scroll_handle: ScrollHandle, + display_nav_history_buttons: bool, } pub struct ItemNavHistory { @@ -439,6 +440,7 @@ impl Pane { }) .into_any_element() }), + display_nav_history_buttons: true, _subscriptions: subscriptions, } } @@ -1660,30 +1662,32 @@ impl Pane { fn render_tab_bar(&mut self, cx: &mut ViewContext<'_, Pane>) -> impl IntoElement { TabBar::new("tab_bar") .track_scroll(self.tab_bar_scroll_handle.clone()) - .start_child( - h_stack() - .gap_2() - .child( - IconButton::new("navigate_backward", Icon::ArrowLeft) - .icon_size(IconSize::Small) - .on_click({ - let view = cx.view().clone(); - move |_, cx| view.update(cx, Self::navigate_backward) - }) - .disabled(!self.can_navigate_backward()) - .tooltip(|cx| Tooltip::for_action("Go Back", &GoBack, cx)), - ) - .child( - IconButton::new("navigate_forward", Icon::ArrowRight) - .icon_size(IconSize::Small) - .on_click({ - let view = cx.view().clone(); - move |_, cx| view.update(cx, Self::navigate_backward) - }) - .disabled(!self.can_navigate_forward()) - .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), - ), - ) + .when(self.display_nav_history_buttons, |tab_bar| { + tab_bar.start_child( + h_stack() + .gap_2() + .child( + IconButton::new("navigate_backward", Icon::ArrowLeft) + .icon_size(IconSize::Small) + .on_click({ + let view = cx.view().clone(); + move |_, cx| view.update(cx, Self::navigate_backward) + }) + .disabled(!self.can_navigate_backward()) + .tooltip(|cx| Tooltip::for_action("Go Back", &GoBack, cx)), + ) + .child( + IconButton::new("navigate_forward", Icon::ArrowRight) + .icon_size(IconSize::Small) + .on_click({ + let view = cx.view().clone(); + move |_, cx| view.update(cx, Self::navigate_backward) + }) + .disabled(!self.can_navigate_forward()) + .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), + ), + ) + }) .when(self.has_focus(cx), |tab_bar| { tab_bar.end_child({ let render_tab_buttons = self.render_tab_bar_buttons.clone(); @@ -1851,6 +1855,10 @@ impl Pane { }) .log_err(); } + + pub fn display_nav_history_buttons(&mut self, display: bool) { + self.display_nav_history_buttons = display; + } } impl FocusableView for Pane { From 1096eeff3a428b41139cffbfb320ebe4f6fe1840 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 23 Dec 2023 22:33:52 +0200 Subject: [PATCH 324/644] Add a horizontal separator between history and query file finder matches --- crates/file_finder2/src/file_finder.rs | 9 +++++++++ crates/picker2/src/picker2.rs | 8 ++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 7410ed7658..8ca7d46f29 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -544,6 +544,15 @@ impl PickerDelegate for FileFinderDelegate { cx.notify(); } + fn separators_after_indices(&self) -> Vec { + let history_items = self.matches.history.len(); + if history_items == 0 { + Vec::new() + } else { + vec![history_items - 1] + } + } + fn update_matches( &mut self, raw_query: String, diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 8585d9e73b..3abdf953b3 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -5,7 +5,7 @@ use gpui::{ UniformListScrollHandle, View, ViewContext, WindowContext, }; use std::{cmp, sync::Arc}; -use ui::{prelude::*, v_stack, Color, Divider, Label, ListItem, ListItemSpacing}; +use ui::{prelude::*, v_stack, Color, Divider, Label, ListItem, ListItemSpacing, ListSeparator}; use workspace::ModalView; pub struct Picker { @@ -26,6 +26,9 @@ pub trait PickerDelegate: Sized + 'static { type ListItem: IntoElement; fn match_count(&self) -> usize; fn selected_index(&self) -> usize; + fn separators_after_indices(&self) -> Vec { + Vec::new() + } fn set_selected_index(&mut self, ix: usize, cx: &mut ViewContext>); fn placeholder_text(&self) -> Arc; @@ -266,6 +269,7 @@ impl Render for Picker { "candidates", self.delegate.match_count(), { + let separators_after_indices = self.delegate.separators_after_indices(); let selected_index = self.delegate.selected_index(); move |picker, visible_range, cx| { visible_range @@ -285,7 +289,7 @@ impl Render for Picker { ix, ix == selected_index, cx, - )) + )).when(separators_after_indices.contains(&ix), |picker| picker.child(ListSeparator)) }) .collect() } From 58c5720c3289ee5634e55670d3d80367f5298e0b Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Sat, 23 Dec 2023 17:23:50 -0500 Subject: [PATCH 325/644] Remove telemetry debounce time in zed 2 --- crates/client2/src/telemetry.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/crates/client2/src/telemetry.rs b/crates/client2/src/telemetry.rs index f02ff937e4..9587bd9a0b 100644 --- a/crates/client2/src/telemetry.rs +++ b/crates/client2/src/telemetry.rs @@ -28,7 +28,6 @@ struct TelemetryState { app_metadata: AppMetadata, architecture: &'static str, clickhouse_events_queue: Vec, - flush_clickhouse_events_task: Option>, log_file: Option, is_staff: Option, first_event_datetime: Option>, @@ -120,12 +119,6 @@ const MAX_QUEUE_LEN: usize = 1; #[cfg(not(debug_assertions))] const MAX_QUEUE_LEN: usize = 50; -#[cfg(debug_assertions)] -const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(1); - -#[cfg(not(debug_assertions))] -const DEBOUNCE_INTERVAL: Duration = Duration::from_secs(120); - impl Telemetry { pub fn new(client: Arc, cx: &mut AppContext) -> Arc { let release_channel = if cx.has_global::() { @@ -146,7 +139,6 @@ impl Telemetry { metrics_id: None, session_id: None, clickhouse_events_queue: Default::default(), - flush_clickhouse_events_task: Default::default(), log_file: None, is_staff: None, first_event_datetime: None, @@ -412,13 +404,6 @@ impl Telemetry { if immediate_flush || state.clickhouse_events_queue.len() >= MAX_QUEUE_LEN { drop(state); self.flush_clickhouse_events(); - } else { - let this = self.clone(); - let executor = self.executor.clone(); - state.flush_clickhouse_events_task = Some(self.executor.spawn(async move { - executor.timer(DEBOUNCE_INTERVAL).await; - this.flush_clickhouse_events(); - })); } } } @@ -439,7 +424,6 @@ impl Telemetry { let mut state = self.state.lock(); state.first_event_datetime = None; let mut events = mem::take(&mut state.clickhouse_events_queue); - state.flush_clickhouse_events_task.take(); drop(state); let this = self.clone(); From 81ed86128821fbaa6a0aca5a82957766cff9811d Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Sat, 23 Dec 2023 22:26:00 -0500 Subject: [PATCH 326/644] Migrate from device_id to installation_id key --- crates/zed/src/main.rs | 28 +++++++++++++++++++--------- crates/zed2/src/main.rs | 28 +++++++++++++++++++--------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 04f468eb2f..da8ff80c31 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -327,19 +327,29 @@ async fn authenticate(client: Arc, cx: &AsyncAppContext) -> Result<()> { } async fn installation_id() -> Result<(String, bool)> { - let legacy_key_name = "device_id"; - - if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp(legacy_key_name) { - Ok((installation_id, true)) - } else { - let installation_id = Uuid::new_v4().to_string(); + let legacy_key_name = "device_id".to_string(); + let key_name = "installation_id".to_string(); + // Migrate legacy key to new key + if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp(&legacy_key_name) { KEY_VALUE_STORE - .write_kvp(legacy_key_name.to_string(), installation_id.clone()) + .write_kvp(key_name, installation_id.clone()) .await?; - - Ok((installation_id, false)) + KEY_VALUE_STORE.delete_kvp(legacy_key_name).await?; + return Ok((installation_id, true)); } + + if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp(&key_name) { + return Ok((installation_id, true)); + } + + let installation_id = Uuid::new_v4().to_string(); + + KEY_VALUE_STORE + .write_kvp(key_name, installation_id.clone()) + .await?; + + Ok((installation_id, false)) } async fn restore_or_create_workspace(app_state: &Arc, mut cx: AsyncAppContext) { diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index a885a81f79..a24fb7377d 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -387,19 +387,29 @@ async fn authenticate(client: Arc, cx: &AsyncAppContext) -> Result<()> { } async fn installation_id() -> Result<(String, bool)> { - let legacy_key_name = "device_id"; - - if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp(legacy_key_name) { - Ok((installation_id, true)) - } else { - let installation_id = Uuid::new_v4().to_string(); + let legacy_key_name = "device_id".to_string(); + let key_name = "installation_id".to_string(); + // Migrate legacy key to new key + if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp(&legacy_key_name) { KEY_VALUE_STORE - .write_kvp(legacy_key_name.to_string(), installation_id.clone()) + .write_kvp(key_name, installation_id.clone()) .await?; - - Ok((installation_id, false)) + KEY_VALUE_STORE.delete_kvp(legacy_key_name).await?; + return Ok((installation_id, true)); } + + if let Ok(Some(installation_id)) = KEY_VALUE_STORE.read_kvp(&key_name) { + return Ok((installation_id, true)); + } + + let installation_id = Uuid::new_v4().to_string(); + + KEY_VALUE_STORE + .write_kvp(key_name, installation_id.clone()) + .await?; + + Ok((installation_id, false)) } async fn restore_or_create_workspace(app_state: &Arc, mut cx: AsyncAppContext) { From 88d05fd8140fbb4c0fcd65457497827a8c5c6cf1 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 25 Dec 2023 03:36:54 -0500 Subject: [PATCH 327/644] Wire up journal --- crates/journal2/src/journal2.rs | 18 +++++++++++------- crates/zed2/src/main.rs | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/journal2/src/journal2.rs b/crates/journal2/src/journal2.rs index 20d520e36e..95ef17a358 100644 --- a/crates/journal2/src/journal2.rs +++ b/crates/journal2/src/journal2.rs @@ -1,6 +1,6 @@ use anyhow::Result; use chrono::{Datelike, Local, NaiveTime, Timelike}; -use gpui::AppContext; +use gpui::{actions, AppContext, ViewContext}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings2::Settings; @@ -9,11 +9,9 @@ use std::{ path::{Path, PathBuf}, sync::Arc, }; -use workspace2::AppState; -// use zed::AppState; +use workspace2::{AppState, Workspace}; -// todo!(); -// actions!(journal, [NewJournalEntry]); +actions!(journal, [NewJournalEntry]); #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct JournalSettings { @@ -55,8 +53,14 @@ impl settings2::Settings for JournalSettings { pub fn init(_: Arc, cx: &mut AppContext) { JournalSettings::register(cx); - // todo!() - // cx.add_global_action(move |_: &NewJournalEntry, cx| new_journal_entry(app_state.clone(), cx)); + cx.observe_new_views( + |workspace: &mut Workspace, _cx: &mut ViewContext| { + workspace.register_action(|workspace, _: &NewJournalEntry, cx| { + new_journal_entry(workspace.app_state().clone(), cx); + }); + }, + ) + .detach(); } pub fn new_journal_entry(app_state: Arc, cx: &mut AppContext) { diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index a24fb7377d..06eb432014 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -215,7 +215,7 @@ fn main() { vim::init(cx); terminal_view::init(cx); - // journal2::init(app_state.clone(), cx); + journal::init(app_state.clone(), cx); language_selector::init(cx); theme_selector::init(cx); language_tools::init(cx); From ada1da48ca512784902f4001def74c13bb8b29a3 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 25 Dec 2023 03:47:03 -0500 Subject: [PATCH 328/644] Remove already-implemented comment --- crates/zed2/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 06eb432014..a248e4537b 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -209,7 +209,6 @@ fn main() { project_symbols::init(cx); project_panel::init(Assets, cx); channel::init(&client, user_store.clone(), cx); - // diagnostics::init(cx); search::init(cx); semantic_index::init(fs.clone(), http.clone(), languages.clone(), cx); vim::init(cx); From 8f3ea6ccb3e498912b3d03395de5603c1b3f1ad0 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 25 Dec 2023 03:47:28 -0500 Subject: [PATCH 329/644] Remove silencing of warnings and fix warnings --- crates/zed2/src/main.rs | 5 +---- crates/zed2/src/open_listener.rs | 11 +++++------ 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index a248e4537b..f1fd168ffd 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -1,6 +1,3 @@ -#![allow(unused_variables, dead_code, unused_mut)] -// todo!() this is to make transition easier. - // Allow binary to be called Zed for a nice application menu when running executable directly #![allow(non_snake_case)] @@ -411,7 +408,7 @@ async fn installation_id() -> Result<(String, bool)> { Ok((installation_id, false)) } -async fn restore_or_create_workspace(app_state: &Arc, mut cx: AsyncAppContext) { +async fn restore_or_create_workspace(app_state: &Arc, cx: AsyncAppContext) { async_maybe!({ if let Some(location) = workspace::last_opened_workspace_paths().await { cx.update(|cx| workspace::open_paths(location.paths().as_ref(), app_state, None, cx))? diff --git a/crates/zed2/src/open_listener.rs b/crates/zed2/src/open_listener.rs index b45254f717..6db020a785 100644 --- a/crates/zed2/src/open_listener.rs +++ b/crates/zed2/src/open_listener.rs @@ -251,12 +251,11 @@ pub async fn handle_cli_connection( let wait = async move { if paths.is_empty() { let (done_tx, done_rx) = oneshot::channel(); - let _subscription = - workspace.update(&mut cx, |workspace, cx| { - cx.on_release(move |_, _, _| { - let _ = done_tx.send(()); - }) - }); + let _subscription = workspace.update(&mut cx, |_, cx| { + cx.on_release(move |_, _, _| { + let _ = done_tx.send(()); + }) + }); let _ = done_rx.await; } else { let _ = futures::future::try_join_all(item_release_futures) From 904358263caf3563b1e7ec2567f3ab6ea2f7c646 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 25 Dec 2023 12:23:44 +0100 Subject: [PATCH 330/644] Remove #[allow(unused)] annotations in zed2 crates (#3798) Release Notes: - N/A --- crates/copilot_button2/src/copilot_button.rs | 56 ++-- crates/editor2/src/blink_manager.rs | 3 +- crates/editor2/src/display_map.rs | 11 +- crates/editor2/src/display_map/block_map.rs | 2 +- crates/editor2/src/display_map/wrap_map.rs | 8 +- crates/editor2/src/editor.rs | 94 +++---- crates/editor2/src/editor_tests.rs | 264 +++++++++--------- crates/editor2/src/element.rs | 57 ++-- crates/editor2/src/hover_popover.rs | 10 +- crates/editor2/src/inlay_hint_cache.rs | 117 ++++---- crates/editor2/src/items.rs | 44 +-- crates/editor2/src/link_go_to_definition.rs | 2 +- crates/editor2/src/mouse_context_menu.rs | 8 +- crates/editor2/src/movement.rs | 4 +- crates/editor2/src/rust_analyzer_ext.rs | 4 +- crates/editor2/src/scroll.rs | 2 +- crates/editor2/src/scroll/actions.rs | 2 +- crates/editor2/src/scroll/autoscroll.rs | 12 +- .../editor2/src/test/editor_test_context.rs | 3 +- crates/workspace2/src/persistence.rs | 2 +- crates/zed2/src/open_listener.rs | 11 +- crates/zed2/src/zed2.rs | 13 +- 22 files changed, 358 insertions(+), 371 deletions(-) diff --git a/crates/copilot_button2/src/copilot_button.rs b/crates/copilot_button2/src/copilot_button.rs index d3a1c1e58c..2c8427732e 100644 --- a/crates/copilot_button2/src/copilot_button.rs +++ b/crates/copilot_button2/src/copilot_button.rs @@ -1,11 +1,10 @@ -#![allow(unused)] use anyhow::Result; use copilot::{Copilot, SignOut, Status}; use editor::{scroll::autoscroll::Autoscroll, Editor}; use fs::Fs; use gpui::{ - div, Action, AnchorCorner, AppContext, AsyncAppContext, AsyncWindowContext, Div, Entity, - ParentElement, Render, Subscription, View, ViewContext, WeakView, WindowContext, + div, Action, AnchorCorner, AppContext, AsyncWindowContext, Div, Entity, ParentElement, Render, + Subscription, View, ViewContext, WeakView, WindowContext, }; use language::{ language_settings::{self, all_language_settings, AllLanguageSettings}, @@ -17,10 +16,7 @@ use util::{paths, ResultExt}; use workspace::{ create_and_open_local_file, item::ItemHandle, - ui::{ - popover_menu, ButtonCommon, Clickable, ContextMenu, Icon, IconButton, IconSize, - PopoverMenu, Tooltip, - }, + ui::{popover_menu, ButtonCommon, Clickable, ContextMenu, Icon, IconButton, IconSize, Tooltip}, StatusItemView, Toast, Workspace, }; use zed_actions::OpenBrowser; @@ -71,27 +67,31 @@ impl Render for CopilotButton { return div().child( IconButton::new("copilot-error", icon) .icon_size(IconSize::Small) - .on_click(cx.listener(move |this, _, cx| { + .on_click(cx.listener(move |_, _, cx| { if let Some(workspace) = cx.window_handle().downcast::() { - workspace.update(cx, |workspace, cx| { - workspace.show_toast( - Toast::new( - COPILOT_ERROR_TOAST_ID, - format!("Copilot can't be started: {}", e), - ) - .on_click( - "Reinstall Copilot", - |cx| { - if let Some(copilot) = Copilot::global(cx) { - copilot - .update(cx, |copilot, cx| copilot.reinstall(cx)) - .detach(); - } - }, - ), - cx, - ); - }); + workspace + .update(cx, |workspace, cx| { + workspace.show_toast( + Toast::new( + COPILOT_ERROR_TOAST_ID, + format!("Copilot can't be started: {}", e), + ) + .on_click( + "Reinstall Copilot", + |cx| { + if let Some(copilot) = Copilot::global(cx) { + copilot + .update(cx, |copilot, cx| { + copilot.reinstall(cx) + }) + .detach(); + } + }, + ), + cx, + ); + }) + .ok(); } })) .tooltip(|cx| Tooltip::text("GitHub Copilot", cx)), @@ -134,7 +134,7 @@ impl CopilotButton { pub fn build_copilot_start_menu(&mut self, cx: &mut ViewContext) -> View { let fs = self.fs.clone(); - ContextMenu::build(cx, |menu, cx| { + ContextMenu::build(cx, |menu, _| { menu.entry("Sign In", None, initiate_sign_in).entry( "Disable Copilot", None, diff --git a/crates/editor2/src/blink_manager.rs b/crates/editor2/src/blink_manager.rs index 0fc748f48a..e3a8ce6293 100644 --- a/crates/editor2/src/blink_manager.rs +++ b/crates/editor2/src/blink_manager.rs @@ -67,7 +67,8 @@ impl BlinkManager { cx.spawn(|this, mut cx| async move { Timer::after(interval).await; if let Some(this) = this.upgrade() { - this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx)); + this.update(&mut cx, |this, cx| this.blink_cursors(epoch, cx)) + .ok(); } }) .detach(); diff --git a/crates/editor2/src/display_map.rs b/crates/editor2/src/display_map.rs index 60975a7a5c..6298c80d2f 100644 --- a/crates/editor2/src/display_map.rs +++ b/crates/editor2/src/display_map.rs @@ -12,10 +12,7 @@ use crate::{ pub use block_map::{BlockMap, BlockPoint}; use collections::{BTreeMap, HashMap, HashSet}; use fold_map::FoldMap; -use gpui::{ - Font, FontId, HighlightStyle, Hsla, LineLayout, Model, ModelContext, Pixels, ShapedLine, - TextRun, UnderlineStyle, WrappedLine, -}; +use gpui::{Font, HighlightStyle, Hsla, LineLayout, Model, ModelContext, Pixels, UnderlineStyle}; use inlay_map::InlayMap; use language::{ language_settings::language_settings, OffsetUtf16, Point, Subscription as BufferSubscription, @@ -24,7 +21,7 @@ use lsp::DiagnosticSeverity; use std::{any::TypeId, borrow::Cow, fmt::Debug, num::NonZeroU32, ops::Range, sync::Arc}; use sum_tree::{Bias, TreeMap}; use tab_map::TabMap; -use theme::{StatusColors, SyntaxTheme, Theme}; + use wrap_map::WrapMap; pub use block_map::{ @@ -1018,7 +1015,7 @@ pub mod tests { .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) .unwrap_or(10); - let test_platform = &cx.test_platform; + let _test_platform = &cx.test_platform; let mut tab_size = rng.gen_range(1..=4); let buffer_start_excerpt_header_height = rng.gen_range(1..=5); let excerpt_header_height = rng.gen_range(1..=5); @@ -1280,7 +1277,7 @@ pub mod tests { let editor = cx.editor.clone(); let window = cx.window.clone(); - cx.update_window(window, |_, cx| { + _ = cx.update_window(window, |_, cx| { let text_layout_details = editor.update(cx, |editor, cx| editor.text_layout_details(cx)); diff --git a/crates/editor2/src/display_map/block_map.rs b/crates/editor2/src/display_map/block_map.rs index cc0095bca9..6eb0d05bfe 100644 --- a/crates/editor2/src/display_map/block_map.rs +++ b/crates/editor2/src/display_map/block_map.rs @@ -1185,7 +1185,7 @@ mod tests { fn test_blocks_on_wrapped_lines(cx: &mut gpui::TestAppContext) { cx.update(|cx| init_test(cx)); - let font_id = cx.text_system().font_id(&font("Helvetica")).unwrap(); + let _font_id = cx.text_system().font_id(&font("Helvetica")).unwrap(); let text = "one two three\nfour five six\nseven eight"; diff --git a/crates/editor2/src/display_map/wrap_map.rs b/crates/editor2/src/display_map/wrap_map.rs index 6a47a435a3..4ef6a13c69 100644 --- a/crates/editor2/src/display_map/wrap_map.rs +++ b/crates/editor2/src/display_map/wrap_map.rs @@ -197,7 +197,8 @@ impl WrapMap { this.background_task = None; this.flush_edits(cx); cx.notify(); - }); + }) + .ok(); })); } } @@ -277,7 +278,8 @@ impl WrapMap { this.background_task = None; this.flush_edits(cx); cx.notify(); - }); + }) + .ok(); })); } } @@ -1057,7 +1059,7 @@ mod tests { }; let tab_size = NonZeroU32::new(rng.gen_range(1..=4)).unwrap(); let font = font("Helvetica"); - let font_id = text_system.font_id(&font).unwrap(); + let _font_id = text_system.font_id(&font).unwrap(); let font_size = px(14.0); log::info!("Tab size: {}", tab_size); diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index d3ee41b11f..c9fb2fa181 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -1,4 +1,3 @@ -#![allow(unused)] mod blink_manager; pub mod display_map; mod editor_settings; @@ -42,11 +41,10 @@ use git::diff_hunk_to_display; use gpui::{ actions, div, impl_actions, point, prelude::*, px, relative, rems, size, uniform_list, Action, AnyElement, AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context, - DispatchPhase, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontFeatures, - FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, InteractiveText, KeyContext, Model, - MouseButton, ParentElement, Pixels, Render, RenderOnce, SharedString, Styled, StyledText, - Subscription, Task, TextRun, TextStyle, UniformListScrollHandle, View, ViewContext, - VisualContext, WeakView, WhiteSpace, WindowContext, + DispatchPhase, ElementId, EventEmitter, FocusHandle, FocusableView, FontStyle, FontWeight, + HighlightStyle, Hsla, InputHandler, InteractiveText, KeyContext, Model, MouseButton, + ParentElement, Pixels, Render, SharedString, Styled, StyledText, Subscription, Task, TextStyle, + UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WhiteSpace, WindowContext, }; use highlight_matching_bracket::refresh_matching_bracket_highlights; use hover_popover::{hide_hover, HoverState}; @@ -61,7 +59,7 @@ use language::{ LanguageRegistry, LanguageServerName, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId, }; -use lazy_static::lazy_static; + use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState}; use lsp::{DiagnosticSeverity, LanguageServerId}; use mouse_context_menu::MouseContextMenu; @@ -72,7 +70,7 @@ pub use multi_buffer::{ ToPoint, }; use ordered_float::OrderedFloat; -use parking_lot::{Mutex, RwLock}; +use parking_lot::RwLock; use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction}; use rand::prelude::*; use rpc::proto::{self, *}; @@ -99,19 +97,11 @@ use std::{ pub use sum_tree::Bias; use sum_tree::TreeMap; use text::{OffsetUtf16, Rope}; -use theme::{ - ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings, -}; -use ui::{ - h_stack, v_stack, ButtonSize, ButtonStyle, HighlightedLabel, Icon, IconButton, Popover, Tooltip, -}; +use theme::{ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, ThemeColors, ThemeSettings}; +use ui::{h_stack, ButtonSize, ButtonStyle, Icon, IconButton, Popover, Tooltip}; use ui::{prelude::*, IconSize}; use util::{post_inc, RangeExt, ResultExt, TryFutureExt}; -use workspace::{ - item::{Item, ItemEvent, ItemHandle}, - searchable::SearchEvent, - ItemNavHistory, Pane, SplitDirection, ViewId, Workspace, -}; +use workspace::{searchable::SearchEvent, ItemNavHistory, Pane, SplitDirection, ViewId, Workspace}; const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500); const MAX_LINE_LEN: usize = 1024; @@ -439,7 +429,7 @@ pub fn init(cx: &mut AppContext) { workspace::register_followable_item::(cx); workspace::register_deserializable_item::(cx); cx.observe_new_views( - |workspace: &mut Workspace, cx: &mut ViewContext| { + |workspace: &mut Workspace, _cx: &mut ViewContext| { workspace.register_action(Editor::new_file); workspace.register_action(Editor::new_file_in_direction); }, @@ -1216,7 +1206,7 @@ impl CompletionsMenu { cx.view().clone(), "completions", matches.len(), - move |editor, range, cx| { + move |_editor, range, cx| { let start_ix = range.start; let completions_guard = completions.read(); @@ -1271,7 +1261,7 @@ impl CompletionsMenu { }) .on_mouse_down( MouseButton::Left, - cx.listener(move |editor, event, cx| { + cx.listener(move |editor, _event, cx| { cx.stop_propagation(); editor .confirm_completion( @@ -1414,7 +1404,7 @@ impl CodeActionsMenu { fn render( &self, mut cursor_position: DisplayPoint, - style: &EditorStyle, + _style: &EditorStyle, max_height: Pixels, cx: &mut ViewContext, ) -> (DisplayPoint, AnyElement) { @@ -1425,7 +1415,7 @@ impl CodeActionsMenu { cx.view().clone(), "code_actions_menu", self.actions.len(), - move |this, range, cx| { + move |_this, range, cx| { actions[range.clone()] .iter() .enumerate() @@ -3418,9 +3408,11 @@ impl Editor { Some(cx.spawn(|editor, mut cx| async move { if let Some(transaction) = on_type_formatting.await? { if push_to_client_history { - buffer.update(&mut cx, |buffer, _| { - buffer.push_transaction(transaction, Instant::now()); - }); + buffer + .update(&mut cx, |buffer, _| { + buffer.push_transaction(transaction, Instant::now()); + }) + .ok(); } editor.update(&mut cx, |editor, cx| { editor.refresh_document_highlights(cx); @@ -4226,7 +4218,7 @@ impl Editor { pub fn render_code_actions_indicator( &self, - style: &EditorStyle, + _style: &EditorStyle, is_active: bool, cx: &mut ViewContext, ) -> Option { @@ -4236,7 +4228,7 @@ impl Editor { .icon_size(IconSize::Small) .icon_color(Color::Muted) .selected(is_active) - .on_click(cx.listener(|editor, e, cx| { + .on_click(cx.listener(|editor, _e, cx| { editor.toggle_code_actions( &ToggleCodeActions { deployed_from_indicator: true, @@ -4253,10 +4245,10 @@ impl Editor { pub fn render_fold_indicators( &self, fold_data: Vec>, - style: &EditorStyle, + _style: &EditorStyle, gutter_hovered: bool, - line_height: Pixels, - gutter_margin: Pixels, + _line_height: Pixels, + _gutter_margin: Pixels, cx: &mut ViewContext, ) -> Vec> { fold_data @@ -4267,7 +4259,7 @@ impl Editor { .map(|(fold_status, buffer_row, active)| { (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| { IconButton::new(ix as usize, ui::Icon::ChevronDown) - .on_click(cx.listener(move |editor, e, cx| match fold_status { + .on_click(cx.listener(move |editor, _e, cx| match fold_status { FoldStatus::Folded => { editor.unfold_at(&UnfoldAt { buffer_row }, cx); } @@ -7379,11 +7371,13 @@ impl Editor { .filter_map(|location| location.transpose()) .collect::>() .context("location tasks")?; - workspace.update(&mut cx, |workspace, cx| { - Self::open_locations_in_multibuffer( - workspace, locations, replica_id, title, split, cx, - ) - }); + workspace + .update(&mut cx, |workspace, cx| { + Self::open_locations_in_multibuffer( + workspace, locations, replica_id, title, split, cx, + ) + }) + .ok(); anyhow::Ok(()) }) @@ -7832,15 +7826,17 @@ impl Editor { transaction = format.log_err().fuse() => transaction, }; - buffer.update(&mut cx, |buffer, cx| { - if let Some(transaction) = transaction { - if !buffer.is_singleton() { - buffer.push_transaction(&transaction.0, cx); + buffer + .update(&mut cx, |buffer, cx| { + if let Some(transaction) = transaction { + if !buffer.is_singleton() { + buffer.push_transaction(&transaction.0, cx); + } } - } - cx.notify(); - }); + cx.notify(); + }) + .ok(); Ok(()) }) @@ -9119,7 +9115,7 @@ impl Editor { let listener = Arc::new(listener); self.editor_actions.push(Box::new(move |cx| { - let view = cx.view().clone(); + let _view = cx.view().clone(); let cx = cx.window_context(); let listener = listener.clone(); cx.on_action(TypeId::of::(), move |action, phase, cx| { @@ -9289,7 +9285,7 @@ pub enum EditorEvent { impl EventEmitter for Editor {} impl FocusableView for Editor { - fn focus_handle(&self, cx: &AppContext) -> FocusHandle { + fn focus_handle(&self, _cx: &AppContext) -> FocusHandle { self.focus_handle.clone() } } @@ -9329,7 +9325,7 @@ impl Render for Editor { let background = match self.mode { EditorMode::SingleLine => cx.theme().system().transparent, - EditorMode::AutoHeight { max_lines } => cx.theme().system().transparent, + EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent, EditorMode::Full => cx.theme().colors().editor_background, }; @@ -9719,7 +9715,7 @@ impl InvalidationRegion for SnippetState { } } -pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock { +pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> RenderBlock { let (text_without_backticks, code_ranges) = highlight_diagnostic_message(&diagnostic); Arc::new(move |cx: &mut BlockContext| { diff --git a/crates/editor2/src/editor_tests.rs b/crates/editor2/src/editor_tests.rs index 2548fc40a4..563913bbe1 100644 --- a/crates/editor2/src/editor_tests.rs +++ b/crates/editor2/src/editor_tests.rs @@ -12,7 +12,7 @@ use futures::StreamExt; use gpui::{ div, serde_json::{self, json}, - Div, Flatten, TestAppContext, VisualTestContext, WindowBounds, WindowOptions, + TestAppContext, VisualTestContext, WindowBounds, WindowOptions, }; use indoc::indoc; use language::{ @@ -77,7 +77,7 @@ fn test_edit_events(cx: &mut TestAppContext) { assert_eq!(mem::take(&mut *events.borrow_mut()), []); // Mutating editor 1 will emit an `Edited` event only for that editor. - editor1.update(cx, |editor, cx| editor.insert("X", cx)); + _ = editor1.update(cx, |editor, cx| editor.insert("X", cx)); assert_eq!( mem::take(&mut *events.borrow_mut()), [ @@ -88,7 +88,7 @@ fn test_edit_events(cx: &mut TestAppContext) { ); // Mutating editor 2 will emit an `Edited` event only for that editor. - editor2.update(cx, |editor, cx| editor.delete(&Delete, cx)); + _ = editor2.update(cx, |editor, cx| editor.delete(&Delete, cx)); assert_eq!( mem::take(&mut *events.borrow_mut()), [ @@ -99,7 +99,7 @@ fn test_edit_events(cx: &mut TestAppContext) { ); // Undoing on editor 1 will emit an `Edited` event only for that editor. - editor1.update(cx, |editor, cx| editor.undo(&Undo, cx)); + _ = editor1.update(cx, |editor, cx| editor.undo(&Undo, cx)); assert_eq!( mem::take(&mut *events.borrow_mut()), [ @@ -110,7 +110,7 @@ fn test_edit_events(cx: &mut TestAppContext) { ); // Redoing on editor 1 will emit an `Edited` event only for that editor. - editor1.update(cx, |editor, cx| editor.redo(&Redo, cx)); + _ = editor1.update(cx, |editor, cx| editor.redo(&Redo, cx)); assert_eq!( mem::take(&mut *events.borrow_mut()), [ @@ -121,7 +121,7 @@ fn test_edit_events(cx: &mut TestAppContext) { ); // Undoing on editor 2 will emit an `Edited` event only for that editor. - editor2.update(cx, |editor, cx| editor.undo(&Undo, cx)); + _ = editor2.update(cx, |editor, cx| editor.undo(&Undo, cx)); assert_eq!( mem::take(&mut *events.borrow_mut()), [ @@ -132,7 +132,7 @@ fn test_edit_events(cx: &mut TestAppContext) { ); // Redoing on editor 2 will emit an `Edited` event only for that editor. - editor2.update(cx, |editor, cx| editor.redo(&Redo, cx)); + _ = editor2.update(cx, |editor, cx| editor.redo(&Redo, cx)); assert_eq!( mem::take(&mut *events.borrow_mut()), [ @@ -143,7 +143,7 @@ fn test_edit_events(cx: &mut TestAppContext) { ); // No event is emitted when the mutation is a no-op. - editor2.update(cx, |editor, cx| { + _ = editor2.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges([0..0])); editor.backspace(&Backspace, cx); @@ -161,7 +161,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) { let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let editor = cx.add_window(|cx| build_editor(buffer.clone(), cx)); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.start_transaction_at(now, cx); editor.change_selections(None, cx, |s| s.select_ranges([2..4])); @@ -181,7 +181,7 @@ fn test_undo_redo_with_selection_restoration(cx: &mut TestAppContext) { editor.change_selections(None, cx, |s| s.select_ranges([2..2])); // Simulate an edit in another editor - buffer.update(cx, |buffer, cx| { + _ = buffer.update(cx, |buffer, cx| { buffer.start_transaction_at(now, cx); buffer.edit([(0..1, "a")], None, cx); buffer.edit([(1..1, "b")], None, cx); @@ -334,7 +334,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { build_editor(buffer, cx) }); - editor.update(cx, |view, cx| { + _ = editor.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx); }); assert_eq!( @@ -344,7 +344,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { [DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)] ); - editor.update(cx, |view, cx| { + _ = editor.update(cx, |view, cx| { view.update_selection( DisplayPoint::new(3, 3), 0, @@ -360,7 +360,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { [DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)] ); - editor.update(cx, |view, cx| { + _ = editor.update(cx, |view, cx| { view.update_selection( DisplayPoint::new(1, 1), 0, @@ -376,7 +376,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)] ); - editor.update(cx, |view, cx| { + _ = editor.update(cx, |view, cx| { view.end_selection(cx); view.update_selection( DisplayPoint::new(3, 3), @@ -393,7 +393,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { [DisplayPoint::new(2, 2)..DisplayPoint::new(1, 1)] ); - editor.update(cx, |view, cx| { + _ = editor.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx); view.update_selection( DisplayPoint::new(0, 0), @@ -413,7 +413,7 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) { ] ); - editor.update(cx, |view, cx| { + _ = editor.update(cx, |view, cx| { view.end_selection(cx); }); @@ -434,7 +434,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx); assert_eq!( view.selections.display_ranges(cx), @@ -442,7 +442,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.update_selection( DisplayPoint::new(3, 3), 0, @@ -455,7 +455,7 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.cancel(&Cancel, cx); view.update_selection( DisplayPoint::new(1, 1), @@ -490,7 +490,7 @@ fn test_clone(cx: &mut TestAppContext) { build_editor(buffer, cx) }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges(selection_ranges.clone())); editor.fold_ranges( [ @@ -557,7 +557,7 @@ async fn test_navigation_history(cx: &mut TestAppContext) { .update(cx, |workspace, _| workspace.active_pane().clone()) .unwrap(); - workspace.update(cx, |v, cx| { + _ = workspace.update(cx, |_v, cx| { cx.build_view(|cx| { let buffer = MultiBuffer::build_simple(&sample_text(300, 5, 'a'), cx); let mut editor = build_editor(buffer.clone(), cx); @@ -671,7 +671,7 @@ fn test_cancel(cx: &mut TestAppContext) { build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx); view.update_selection( DisplayPoint::new(1, 1), @@ -698,7 +698,7 @@ fn test_cancel(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.cancel(&Cancel, cx); assert_eq!( view.selections.display_ranges(cx), @@ -706,7 +706,7 @@ fn test_cancel(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.cancel(&Cancel, cx); assert_eq!( view.selections.display_ranges(cx), @@ -744,7 +744,7 @@ fn test_fold_action(cx: &mut TestAppContext) { build_editor(buffer.clone(), cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([DisplayPoint::new(8, 0)..DisplayPoint::new(12, 0)]); }); @@ -812,7 +812,7 @@ fn test_move_cursor(cx: &mut TestAppContext) { let buffer = cx.update(|cx| MultiBuffer::build_simple(&sample_text(6, 6, 'a'), cx)); let view = cx.add_window(|cx| build_editor(buffer.clone(), cx)); - buffer.update(cx, |buffer, cx| { + _ = buffer.update(cx, |buffer, cx| { buffer.edit( vec![ (Point::new(1, 0)..Point::new(1, 0), "\t"), @@ -822,7 +822,7 @@ fn test_move_cursor(cx: &mut TestAppContext) { cx, ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { assert_eq!( view.selections.display_ranges(cx), &[DisplayPoint::new(0, 0)..DisplayPoint::new(0, 0)] @@ -893,7 +893,7 @@ fn test_move_cursor_multibyte(cx: &mut TestAppContext) { assert_eq!('ⓐ'.len_utf8(), 3); assert_eq!('α'.len_utf8(), 2); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.fold_ranges( vec![ Point::new(0, 6)..Point::new(0, 12), @@ -1006,7 +1006,7 @@ fn test_move_cursor_different_line_lengths(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple("ⓐⓑⓒⓓⓔ\nabcd\nαβγ\nabcd\nⓐⓑⓒⓓⓔ\n", cx); build_editor(buffer.clone(), cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([empty_range(0, "ⓐⓑⓒⓓⓔ".len())]); }); @@ -1056,7 +1056,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple("abc\n def", cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1), @@ -1065,7 +1065,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { }); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx); assert_eq!( view.selections.display_ranges(cx), @@ -1076,7 +1076,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx); assert_eq!( view.selections.display_ranges(cx), @@ -1087,7 +1087,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_to_beginning_of_line(&MoveToBeginningOfLine, cx); assert_eq!( view.selections.display_ranges(cx), @@ -1098,7 +1098,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_to_end_of_line(&MoveToEndOfLine, cx); assert_eq!( view.selections.display_ranges(cx), @@ -1110,7 +1110,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { }); // Moving to the end of line again is a no-op. - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_to_end_of_line(&MoveToEndOfLine, cx); assert_eq!( view.selections.display_ranges(cx), @@ -1121,7 +1121,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_left(&MoveLeft, cx); view.select_to_beginning_of_line( &SelectToBeginningOfLine { @@ -1138,7 +1138,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_to_beginning_of_line( &SelectToBeginningOfLine { stop_at_soft_wraps: true, @@ -1154,7 +1154,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_to_beginning_of_line( &SelectToBeginningOfLine { stop_at_soft_wraps: true, @@ -1170,7 +1170,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_to_end_of_line( &SelectToEndOfLine { stop_at_soft_wraps: true, @@ -1186,7 +1186,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.delete_to_end_of_line(&DeleteToEndOfLine, cx); assert_eq!(view.display_text(cx), "ab\n de"); assert_eq!( @@ -1198,7 +1198,7 @@ fn test_beginning_end_of_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.delete_to_beginning_of_line(&DeleteToBeginningOfLine, cx); assert_eq!(view.display_text(cx), "\n"); assert_eq!( @@ -1219,7 +1219,7 @@ fn test_prev_next_word_boundary(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple("use std::str::{foo, bar}\n\n {baz.qux()}", cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 11)..DisplayPoint::new(0, 11), @@ -1273,7 +1273,7 @@ fn test_prev_next_word_bounds_with_soft_wrap(cx: &mut TestAppContext) { build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.set_wrap_width(Some(140.0.into()), cx); assert_eq!( view.display_text(cx), @@ -1714,7 +1714,7 @@ fn test_delete_to_word_boundary(cx: &mut TestAppContext) { build_editor(buffer.clone(), cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ // an empty selection - the preceding word fragment is deleted @@ -1727,7 +1727,7 @@ fn test_delete_to_word_boundary(cx: &mut TestAppContext) { assert_eq!(view.buffer.read(cx).read(cx).text(), "e two te four"); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ // an empty selection - the following word fragment is deleted @@ -1750,7 +1750,7 @@ fn test_newline(cx: &mut TestAppContext) { build_editor(buffer.clone(), cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 2)..DisplayPoint::new(0, 2), @@ -1793,7 +1793,7 @@ fn test_newline_with_old_selections(cx: &mut TestAppContext) { editor }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { // Edit the buffer directly, deleting ranges surrounding the editor's selections editor.buffer.update(cx, |buffer, cx| { buffer.edit( @@ -2003,7 +2003,7 @@ fn test_insert_with_old_selections(cx: &mut TestAppContext) { editor }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { // Edit the buffer directly, deleting ranges surrounding the editor's selections editor.buffer.update(cx, |buffer, cx| { buffer.edit([(2..5, ""), (10..13, ""), (18..21, "")], None, cx); @@ -2514,7 +2514,7 @@ fn test_delete_line(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 1)..DisplayPoint::new(0, 1), @@ -2537,7 +2537,7 @@ fn test_delete_line(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([DisplayPoint::new(2, 0)..DisplayPoint::new(0, 1)]) }); @@ -2946,7 +2946,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1), @@ -2972,7 +2972,7 @@ fn test_duplicate_line(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple("abc\ndef\nghi\n", cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 1)..DisplayPoint::new(1, 1), @@ -2999,7 +2999,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.fold_ranges( vec![ Point::new(0, 2)..Point::new(1, 2), @@ -3038,7 +3038,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_line_down(&MoveLineDown, cx); assert_eq!( view.display_text(cx), @@ -3055,7 +3055,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_line_down(&MoveLineDown, cx); assert_eq!( view.display_text(cx), @@ -3072,7 +3072,7 @@ fn test_move_line_up_down(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.move_line_up(&MoveLineUp, cx); assert_eq!( view.display_text(cx), @@ -3098,7 +3098,7 @@ fn test_move_line_up_down_with_blocks(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple(&sample_text(10, 5, 'a'), cx); build_editor(buffer, cx) }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let snapshot = editor.buffer.read(cx).snapshot(cx); editor.insert_blocks( [BlockProperties { @@ -3420,7 +3420,7 @@ fn test_select_all(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple("abc\nde\nfgh", cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_all(&SelectAll, cx); assert_eq!( view.selections.display_ranges(cx), @@ -3437,7 +3437,7 @@ fn test_select_line(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple(&sample_text(6, 5, 'a'), cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1), @@ -3456,7 +3456,7 @@ fn test_select_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_line(&SelectLine, cx); assert_eq!( view.selections.display_ranges(cx), @@ -3467,7 +3467,7 @@ fn test_select_line(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_line(&SelectLine, cx); assert_eq!( view.selections.display_ranges(cx), @@ -3484,7 +3484,7 @@ fn test_split_selection_into_lines(cx: &mut TestAppContext) { let buffer = MultiBuffer::build_simple(&sample_text(9, 5, 'a'), cx); build_editor(buffer, cx) }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.fold_ranges( vec![ Point::new(0, 2)..Point::new(1, 2), @@ -3505,7 +3505,7 @@ fn test_split_selection_into_lines(cx: &mut TestAppContext) { assert_eq!(view.display_text(cx), "aa⋯bbb\nccc⋯eeee\nfffff\nggggg\n⋯i"); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.split_selection_into_lines(&SplitSelectionIntoLines, cx); assert_eq!( view.display_text(cx), @@ -3522,7 +3522,7 @@ fn test_split_selection_into_lines(cx: &mut TestAppContext) { ); }); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([DisplayPoint::new(5, 0)..DisplayPoint::new(0, 1)]) }); @@ -3916,7 +3916,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { view.condition::(&cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 25)..DisplayPoint::new(0, 25), @@ -3935,7 +3935,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { ] ); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx); }); assert_eq!( @@ -3946,7 +3946,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { ] ); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx); }); assert_eq!( @@ -3955,7 +3955,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { ); // Trying to expand the selected syntax node one more time has no effect. - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_larger_syntax_node(&SelectLargerSyntaxNode, cx); }); assert_eq!( @@ -3963,7 +3963,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { &[DisplayPoint::new(5, 0)..DisplayPoint::new(0, 0)] ); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx); }); assert_eq!( @@ -3974,7 +3974,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { ] ); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx); }); assert_eq!( @@ -3986,7 +3986,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { ] ); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx); }); assert_eq!( @@ -3999,7 +3999,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { ); // Trying to shrink the selected syntax node one more time has no effect. - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.select_smaller_syntax_node(&SelectSmallerSyntaxNode, cx); }); assert_eq!( @@ -4013,7 +4013,7 @@ async fn test_select_larger_smaller_syntax_node(cx: &mut gpui::TestAppContext) { // Ensure that we keep expanding the selection if the larger selection starts or ends within // a fold. - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.fold_ranges( vec![ Point::new(0, 21)..Point::new(0, 24), @@ -4082,7 +4082,7 @@ async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) { .condition::(cx, |editor, cx| !editor.buffer.read(cx).is_parsing(cx)) .await; - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges([5..5, 8..8, 9..9])); editor.newline(&Newline, cx); assert_eq!(editor.text(cx), "fn a(\n \n) {\n \n}\n"); @@ -4646,7 +4646,7 @@ async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) { view.condition::(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 0)..DisplayPoint::new(0, 1), @@ -4797,7 +4797,7 @@ async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) { .condition::(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| { s.select_ranges([ Point::new(0, 1)..Point::new(0, 1), @@ -4883,9 +4883,9 @@ async fn test_snippets(cx: &mut gpui::TestAppContext) { ); let buffer = cx.update(|cx| MultiBuffer::build_simple(&text, cx)); - let (editor, mut cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); + let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let snippet = Snippet::parse("f(${1:one}, ${2:two}, ${1:three})$0").unwrap(); editor @@ -5003,7 +5003,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; - project.update(cx, |project, _| project.languages().add(Arc::new(language))); + _ = project.update(cx, |project, _| project.languages().add(Arc::new(language))); let buffer = project .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx)) .await @@ -5014,7 +5014,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); - editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); + _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); assert!(cx.read(|cx| editor.is_dirty(cx))); let save = editor @@ -5035,7 +5035,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { .next() .await; cx.executor().start_waiting(); - let x = save.await; + let _x = save.await; assert_eq!( editor.update(cx, |editor, cx| editor.text(cx)), @@ -5043,7 +5043,7 @@ async fn test_document_format_during_save(cx: &mut gpui::TestAppContext) { ); assert!(!cx.read(|cx| editor.is_dirty(cx))); - editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); + _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); assert!(cx.read(|cx| editor.is_dirty(cx))); // Ensure we can still save even if formatting hangs. @@ -5122,7 +5122,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; - project.update(cx, |project, _| project.languages().add(Arc::new(language))); + _ = project.update(cx, |project, _| project.languages().add(Arc::new(language))); let buffer = project .update(cx, |project, cx| project.open_local_buffer("/file.rs", cx)) .await @@ -5133,7 +5133,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); - editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); + _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); assert!(cx.read(|cx| editor.is_dirty(cx))); let save = editor @@ -5161,7 +5161,7 @@ async fn test_range_format_during_save(cx: &mut gpui::TestAppContext) { ); assert!(!cx.read(|cx| editor.is_dirty(cx))); - editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); + _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); assert!(cx.read(|cx| editor.is_dirty(cx))); // Ensure we can still save even if formatting hangs. @@ -5247,7 +5247,7 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) { fs.insert_file("/file.rs", Default::default()).await; let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; - project.update(cx, |project, _| { + _ = project.update(cx, |project, _| { project.languages().add(Arc::new(language)); }); let buffer = project @@ -5260,7 +5260,7 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) { let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); - editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); + _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); let format = editor .update(cx, |editor, cx| { @@ -5288,7 +5288,7 @@ async fn test_document_format_manual_trigger(cx: &mut gpui::TestAppContext) { "one, two\nthree\n" ); - editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); + _ = editor.update(cx, |editor, cx| editor.set_text("one\ntwo\nthree\n", cx)); // Ensure we don't lock if formatting hangs. fake_server.handle_request::(move |params, _| async move { assert_eq!( @@ -5627,7 +5627,7 @@ async fn test_completion(cx: &mut gpui::TestAppContext) { handle_resolve_completion_request(&mut cx, None).await; apply_additional_edits.await.unwrap(); - cx.update(|cx| { + _ = cx.update(|cx| { cx.update_global::(|settings, cx| { settings.update_user_settings::(cx, |settings| { settings.show_completions_on_input = Some(false); @@ -6046,7 +6046,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) { }); let (view, cx) = cx.add_window_view(|cx| build_editor(multibuffer, cx)); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { assert_eq!(view.text(cx), "aaaa\nbbbb"); view.change_selections(None, cx, |s| { s.select_ranges([ @@ -6116,7 +6116,7 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) { }); let (view, cx) = cx.add_window_view(|cx| build_editor(multibuffer, cx)); - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { let (expected_text, selection_ranges) = marked_text_ranges( indoc! {" aaaa @@ -6210,7 +6210,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) { }); // Refreshing selections is a no-op when excerpts haven't changed. - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.refresh()); assert_eq!( editor.selections.ranges(cx), @@ -6221,10 +6221,10 @@ fn test_refresh_selections(cx: &mut TestAppContext) { ); }); - multibuffer.update(cx, |multibuffer, cx| { + _ = multibuffer.update(cx, |multibuffer, cx| { multibuffer.remove_excerpts([excerpt1_id.unwrap()], cx); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { // Removing an excerpt causes the first selection to become degenerate. assert_eq!( editor.selections.ranges(cx), @@ -6289,10 +6289,10 @@ fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) { editor }); - multibuffer.update(cx, |multibuffer, cx| { + _ = multibuffer.update(cx, |multibuffer, cx| { multibuffer.remove_excerpts([excerpt1_id.unwrap()], cx); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( editor.selections.ranges(cx), [Point::new(0, 0)..Point::new(0, 0)] @@ -6356,7 +6356,7 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) { view.condition::(cx, |view, cx| !view.buffer.read(cx).is_parsing(cx)) .await; - view.update(cx, |view, cx| { + _ = view.update(cx, |view, cx| { view.change_selections(None, cx, |s| { s.select_display_ranges([ DisplayPoint::new(0, 2)..DisplayPoint::new(0, 3), @@ -6393,7 +6393,7 @@ fn test_highlighted_ranges(cx: &mut TestAppContext) { build_editor(buffer.clone(), cx) }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { struct Type1; struct Type2; @@ -6498,7 +6498,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { let is_still_following = Rc::new(RefCell::new(true)); let follower_edit_event_count = Rc::new(RefCell::new(0)); let pending_update = Rc::new(RefCell::new(None)); - follower.update(cx, { + _ = follower.update(cx, { let update = pending_update.clone(); let is_still_following = is_still_following.clone(); let follower_edit_event_count = follower_edit_event_count.clone(); @@ -6515,7 +6515,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { cx.subscribe( &follower.root_view(cx).unwrap(), - move |_, _, event: &EditorEvent, cx| { + move |_, _, event: &EditorEvent, _cx| { if matches!(Editor::to_follow_event(event), Some(FollowEvent::Unfollow)) { *is_still_following.borrow_mut() = false; } @@ -6530,7 +6530,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { }); // Update the selections only - leader.update(cx, |leader, cx| { + _ = leader.update(cx, |leader, cx| { leader.change_selections(None, cx, |s| s.select_ranges([1..1])); }); follower @@ -6540,14 +6540,14 @@ async fn test_following(cx: &mut gpui::TestAppContext) { .unwrap() .await .unwrap(); - follower.update(cx, |follower, cx| { + _ = follower.update(cx, |follower, cx| { assert_eq!(follower.selections.ranges(cx), vec![1..1]); }); assert_eq!(*is_still_following.borrow(), true); assert_eq!(*follower_edit_event_count.borrow(), 0); // Update the scroll position only - leader.update(cx, |leader, cx| { + _ = leader.update(cx, |leader, cx| { leader.set_scroll_position(gpui::Point::new(1.5, 3.5), cx); }); follower @@ -6568,7 +6568,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) { // Update the selections and scroll position. The follower's scroll position is updated // via autoscroll, not via the leader's exact scroll position. - leader.update(cx, |leader, cx| { + _ = leader.update(cx, |leader, cx| { leader.change_selections(None, cx, |s| s.select_ranges([0..0])); leader.request_autoscroll(Autoscroll::newest(), cx); leader.set_scroll_position(gpui::Point::new(1.5, 3.5), cx); @@ -6580,14 +6580,14 @@ async fn test_following(cx: &mut gpui::TestAppContext) { .unwrap() .await .unwrap(); - follower.update(cx, |follower, cx| { + _ = follower.update(cx, |follower, cx| { assert_eq!(follower.scroll_position(cx), gpui::Point::new(1.5, 0.0)); assert_eq!(follower.selections.ranges(cx), vec![0..0]); }); assert_eq!(*is_still_following.borrow(), true); // Creating a pending selection that precedes another selection - leader.update(cx, |leader, cx| { + _ = leader.update(cx, |leader, cx| { leader.change_selections(None, cx, |s| s.select_ranges([1..1])); leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx); }); @@ -6598,13 +6598,13 @@ async fn test_following(cx: &mut gpui::TestAppContext) { .unwrap() .await .unwrap(); - follower.update(cx, |follower, cx| { + _ = follower.update(cx, |follower, cx| { assert_eq!(follower.selections.ranges(cx), vec![0..0, 1..1]); }); assert_eq!(*is_still_following.borrow(), true); // Extend the pending selection so that it surrounds another selection - leader.update(cx, |leader, cx| { + _ = leader.update(cx, |leader, cx| { leader.extend_selection(DisplayPoint::new(0, 2), 1, cx); }); follower @@ -6614,12 +6614,12 @@ async fn test_following(cx: &mut gpui::TestAppContext) { .unwrap() .await .unwrap(); - follower.update(cx, |follower, cx| { + _ = follower.update(cx, |follower, cx| { assert_eq!(follower.selections.ranges(cx), vec![0..2]); }); // Scrolling locally breaks the follow - follower.update(cx, |follower, cx| { + _ = follower.update(cx, |follower, cx| { let top_anchor = follower.buffer().read(cx).read(cx).anchor_after(0); follower.set_scroll_anchor( ScrollAnchor { @@ -6695,7 +6695,7 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) { }); // Insert some excerpts. - leader.update(cx, |leader, cx| { + _ = leader.update(cx, |leader, cx| { leader.buffer.update(cx, |multibuffer, cx| { let excerpt_ids = multibuffer.push_excerpts( buffer_1.clone(), @@ -6771,7 +6771,7 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) { ); // Remove some excerpts. - leader.update(cx, |leader, cx| { + _ = leader.update(cx, |leader, cx| { leader.buffer.update(cx, |multibuffer, cx| { let excerpt_ids = multibuffer.excerpt_ids(); multibuffer.remove_excerpts([excerpt_ids[1], excerpt_ids[2]], cx); @@ -6814,8 +6814,8 @@ async fn go_to_prev_overlapping_diagnostic( } "}); - cx.update(|cx| { - project.update(cx, |project, cx| { + _ = cx.update(|cx| { + _ = project.update(cx, |project, cx| { project .update_diagnostics( LanguageServerId(0), @@ -7113,7 +7113,7 @@ async fn test_copilot(executor: BackgroundExecutor, cx: &mut gpui::TestAppContex init_test(cx, |_| {}); let (copilot, copilot_lsp) = Copilot::fake(cx); - cx.update(|cx| cx.set_global(copilot)); + _ = cx.update(|cx| cx.set_global(copilot)); let mut cx = EditorLspTestContext::new_rust( lsp::ServerCapabilities { completion_provider: Some(lsp::CompletionOptions { @@ -7366,7 +7366,7 @@ async fn test_copilot_completion_invalidation( init_test(cx, |_| {}); let (copilot, copilot_lsp) = Copilot::fake(cx); - cx.update(|cx| cx.set_global(copilot)); + _ = cx.update(|cx| cx.set_global(copilot)); let mut cx = EditorLspTestContext::new_rust( lsp::ServerCapabilities { completion_provider: Some(lsp::CompletionOptions { @@ -7430,7 +7430,7 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T init_test(cx, |_| {}); let (copilot, copilot_lsp) = Copilot::fake(cx); - cx.update(|cx| cx.set_global(copilot)); + _ = cx.update(|cx| cx.set_global(copilot)); let buffer_1 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n")); let buffer_2 = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "c = 3\nd = 4\n")); @@ -7465,7 +7465,7 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T }], vec![], ); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { // Ensure copilot suggestions are shown for the first excerpt. editor.change_selections(None, cx, |s| { s.select_ranges([Point::new(1, 5)..Point::new(1, 5)]) @@ -7473,7 +7473,7 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T editor.next_copilot_suggestion(&Default::default(), cx); }); executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert!(editor.has_active_copilot_suggestion(cx)); assert_eq!( editor.display_text(cx), @@ -7491,7 +7491,7 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T }], vec![], ); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { // Move to another excerpt, ensuring the suggestion gets cleared. editor.change_selections(None, cx, |s| { s.select_ranges([Point::new(4, 5)..Point::new(4, 5)]) @@ -7515,7 +7515,7 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T // Ensure the new suggestion is displayed when the debounce timeout expires. executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert!(editor.has_active_copilot_suggestion(cx)); assert_eq!( editor.display_text(cx), @@ -7535,7 +7535,7 @@ async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui }); let (copilot, copilot_lsp) = Copilot::fake(cx); - cx.update(|cx| cx.set_global(copilot)); + _ = cx.update(|cx| cx.set_global(copilot)); let fs = FakeFs::new(cx.executor()); fs.insert_tree( @@ -7594,7 +7594,7 @@ async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui }) }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |selections| { selections.select_ranges([Point::new(0, 0)..Point::new(0, 0)]) }); @@ -7604,7 +7604,7 @@ async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui executor.advance_clock(COPILOT_DEBOUNCE_TIMEOUT); assert!(copilot_requests.try_next().is_err()); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| { s.select_ranges([Point::new(2, 0)..Point::new(2, 0)]) }); @@ -7659,7 +7659,7 @@ async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) { ) .await; let project = Project::test(fs, ["/a".as_ref()], cx).await; - project.update(cx, |project, _| project.languages().add(Arc::new(language))); + _ = project.update(cx, |project, _| project.languages().add(Arc::new(language))); let workspace = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let cx = &mut VisualTestContext::from_window(*workspace, cx); @@ -7717,7 +7717,7 @@ async fn test_on_type_formatting_not_triggered(cx: &mut gpui::TestAppContext) { cx.executor().run_until_parked(); - buffer.update(cx, |buffer, _| { + _ = buffer.update(cx, |buffer, _| { assert_eq!( buffer.text(), "fn main() { let a = {5}; }", @@ -7770,7 +7770,7 @@ async fn test_language_server_restart_due_to_settings_change(cx: &mut gpui::Test ) .await; let project = Project::test(fs, ["/a".as_ref()], cx).await; - project.update(cx, |project, _| project.languages().add(Arc::new(language))); + _ = project.update(cx, |project, _| project.languages().add(Arc::new(language))); let _window = cx.add_window(|cx| Workspace::test_new(project.clone(), cx)); let _buffer = project .update(cx, |project, cx| { @@ -8082,7 +8082,7 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) { let project = Project::test(fs, ["/file.rs".as_ref()], cx).await; let prettier_format_suffix = project::TEST_PRETTIER_FORMAT_SUFFIX; - project.update(cx, |project, _| { + _ = project.update(cx, |project, _| { project.languages().add(Arc::new(language)); }); let buffer = project @@ -8093,7 +8093,7 @@ async fn test_document_format_with_prettier(cx: &mut gpui::TestAppContext) { let buffer_text = "one\ntwo\nthree\n"; let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx)); let (editor, cx) = cx.add_window_view(|cx| build_editor(buffer, cx)); - editor.update(cx, |editor, cx| editor.set_text(buffer_text, cx)); + _ = editor.update(cx, |editor, cx| editor.set_text(buffer_text, cx)); editor .update(cx, |editor, cx| { @@ -8244,7 +8244,7 @@ pub(crate) fn update_test_language_settings( cx: &mut TestAppContext, f: impl Fn(&mut AllLanguageSettingsContent), ) { - cx.update(|cx| { + _ = cx.update(|cx| { cx.update_global(|store: &mut SettingsStore, cx| { store.update_user_settings::(cx, f); }); @@ -8255,7 +8255,7 @@ pub(crate) fn update_test_project_settings( cx: &mut TestAppContext, f: impl Fn(&mut ProjectSettings), ) { - cx.update(|cx| { + _ = cx.update(|cx| { cx.update_global(|store: &mut SettingsStore, cx| { store.update_user_settings::(cx, f); }); @@ -8263,7 +8263,7 @@ pub(crate) fn update_test_project_settings( } pub(crate) fn init_test(cx: &mut TestAppContext, f: fn(&mut AllLanguageSettingsContent)) { - cx.update(|cx| { + _ = cx.update(|cx| { let store = SettingsStore::test(cx); cx.set_global(store); theme::init(theme::LoadThemes::JustBase, cx); diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 568adce556..eb9f4106ea 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -16,24 +16,23 @@ use crate::{ mouse_context_menu, scroll::scroll_amount::ScrollAmount, CursorShape, DisplayPoint, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, - HalfPageDown, HalfPageUp, LineDown, LineUp, MoveDown, OpenExcerpts, PageDown, PageUp, Point, - SelectPhase, Selection, SoftWrap, ToPoint, MAX_LINE_LEN, + HalfPageDown, HalfPageUp, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, SelectPhase, + Selection, SoftWrap, ToPoint, MAX_LINE_LEN, }; use anyhow::Result; use collections::{BTreeMap, HashMap}; use git::diff::DiffHunkStatus; use gpui::{ div, fill, outline, overlay, point, px, quad, relative, size, transparent_black, Action, - AnchorCorner, AnyElement, AsyncWindowContext, AvailableSpace, BorrowWindow, Bounds, - ContentMask, Corners, CursorStyle, DispatchPhase, Edges, Element, ElementId, - ElementInputHandler, Entity, EntityId, Hsla, InteractiveBounds, InteractiveElement, - IntoElement, LineLayout, ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, - MouseUpEvent, ParentElement, Pixels, RenderOnce, ScrollWheelEvent, ShapedLine, SharedString, - Size, StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun, TextStyle, View, - ViewContext, WeakView, WindowContext, WrappedLine, + AnchorCorner, AnyElement, AvailableSpace, BorrowWindow, Bounds, ContentMask, Corners, + CursorStyle, DispatchPhase, Edges, Element, ElementInputHandler, Hsla, InteractiveBounds, + InteractiveElement, IntoElement, ModifiersChangedEvent, MouseButton, MouseDownEvent, + MouseMoveEvent, MouseUpEvent, ParentElement, Pixels, ScrollWheelEvent, ShapedLine, + SharedString, Size, StackingOrder, StatefulInteractiveElement, Style, Styled, TextRun, + TextStyle, View, ViewContext, WindowContext, }; use itertools::Itertools; -use language::{language_settings::ShowWhitespaceSetting, Language}; +use language::language_settings::ShowWhitespaceSetting; use multi_buffer::Anchor; use project::{ project_settings::{GitGutterSetting, ProjectSettings}, @@ -52,15 +51,11 @@ use std::{ }; use sum_tree::Bias; use theme::{ActiveTheme, PlayerColor}; -use ui::{ - h_stack, ButtonLike, ButtonStyle, Disclosure, IconButton, IconElement, IconSize, Label, Tooltip, -}; -use ui::{prelude::*, Icon}; +use ui::prelude::*; +use ui::{h_stack, ButtonLike, ButtonStyle, IconButton, Label, Tooltip}; use util::ResultExt; use workspace::item::Item; -enum FoldMarkers {} - struct SelectionLayout { head: DisplayPoint, cursor_shape: CursorShape, @@ -732,7 +727,7 @@ impl EditorElement { ix as f32 * line_height - (scroll_top % line_height), ); - line.paint(line_origin, line_height, cx); + line.paint(line_origin, line_height, cx).log_err(); } } @@ -2687,11 +2682,13 @@ impl LineWithInvisibles { let line_height = layout.position_map.line_height; let line_y = line_height * row as f32 - layout.position_map.scroll_position.y; - self.line.paint( - content_origin + gpui::point(-layout.position_map.scroll_position.x, line_y), - line_height, - cx, - ); + self.line + .paint( + content_origin + gpui::point(-layout.position_map.scroll_position.x, line_y), + line_height, + cx, + ) + .log_err(); self.draw_invisibles( &selection_ranges, @@ -2746,7 +2743,7 @@ impl LineWithInvisibles { continue; } } - invisible_symbol.paint(origin, line_height, cx); + invisible_symbol.paint(origin, line_height, cx).log_err(); } } } @@ -3090,7 +3087,9 @@ impl Cursor { cx.paint_quad(cursor); if let Some(block_text) = &self.block_text { - block_text.paint(self.origin + origin, self.line_height, cx); + block_text + .paint(self.origin + origin, self.line_height, cx) + .log_err(); } } @@ -3251,7 +3250,7 @@ mod tests { editor_tests::{init_test, update_test_language_settings}, Editor, MultiBuffer, }; - use gpui::{EmptyView, TestAppContext}; + use gpui::TestAppContext; use language::language_settings; use log::info; use std::{num::NonZeroU32, sync::Arc}; @@ -3432,7 +3431,7 @@ mod tests { let editor = window.root(cx).unwrap(); let style = cx.update(|cx| editor.read(cx).style().unwrap().clone()); let mut element = EditorElement::new(&editor, style); - let state = window.update(cx, |editor, cx| { + let _state = window.update(cx, |editor, cx| { editor.cursor_shape = CursorShape::Block; editor.change_selections(None, cx, |s| { s.select_display_ranges([ @@ -3504,7 +3503,7 @@ mod tests { .unwrap(); let mut element = EditorElement::new(&editor, style); - let mut state = cx + let state = cx .update_window(window.into(), |_, cx| { element.compute_layout( Bounds { @@ -3768,17 +3767,15 @@ fn compute_auto_height_layout( .width; let mut snapshot = editor.snapshot(cx); - let gutter_padding; let gutter_width; let gutter_margin; if snapshot.show_gutter { let descent = cx.text_system().descent(font_id, font_size); let gutter_padding_factor = 3.5; - gutter_padding = (em_width * gutter_padding_factor).round(); + let gutter_padding = (em_width * gutter_padding_factor).round(); gutter_width = max_line_number_width + gutter_padding * 2.0; gutter_margin = -descent; } else { - gutter_padding = Pixels::ZERO; gutter_width = Pixels::ZERO; gutter_margin = Pixels::ZERO; }; diff --git a/crates/editor2/src/hover_popover.rs b/crates/editor2/src/hover_popover.rs index 3a53a1bd1d..ca2fc4e9b2 100644 --- a/crates/editor2/src/hover_popover.rs +++ b/crates/editor2/src/hover_popover.rs @@ -6,12 +6,12 @@ use crate::{ }; use futures::FutureExt; use gpui::{ - actions, div, px, AnyElement, AppContext, CursorStyle, InteractiveElement, IntoElement, Model, - MouseButton, ParentElement, Pixels, SharedString, Size, StatefulInteractiveElement, Styled, - Task, ViewContext, WeakView, + actions, div, px, AnyElement, CursorStyle, InteractiveElement, IntoElement, Model, MouseButton, + ParentElement, Pixels, SharedString, Size, StatefulInteractiveElement, Styled, Task, + ViewContext, WeakView, }; use language::{markdown, Bias, DiagnosticEntry, Language, LanguageRegistry, ParsedMarkdown}; -use lsp::DiagnosticSeverity; + use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart, Project}; use settings::Settings; use std::{ops::Range, sync::Arc, time::Duration}; @@ -869,7 +869,7 @@ mod tests { let editor = cx.add_window(|cx| Editor::single_line(cx)); editor - .update(cx, |editor, cx| { + .update(cx, |editor, _cx| { let style = editor.style.clone().unwrap(); struct Row { diff --git a/crates/editor2/src/inlay_hint_cache.rs b/crates/editor2/src/inlay_hint_cache.rs index aab985ff90..aac9e54cf3 100644 --- a/crates/editor2/src/inlay_hint_cache.rs +++ b/crates/editor2/src/inlay_hint_cache.rs @@ -1203,7 +1203,7 @@ pub mod tests { ExcerptRange, }; use futures::StreamExt; - use gpui::{Context, TestAppContext, View, WindowHandle}; + use gpui::{Context, TestAppContext, WindowHandle}; use itertools::Itertools; use language::{ language_settings::AllLanguageSettingsContent, FakeLspAdapter, Language, LanguageConfig, @@ -1214,7 +1214,6 @@ pub mod tests { use serde_json::json; use settings::SettingsStore; use text::{Point, ToPoint}; - use workspace::Workspace; use crate::editor_tests::update_test_language_settings; @@ -1273,7 +1272,7 @@ pub mod tests { cx.executor().run_until_parked(); let mut edits_made = 1; - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["0".to_string()]; assert_eq!( expected_hints, @@ -1292,13 +1291,13 @@ pub mod tests { ); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges([13..13])); editor.handle_input("some change", cx); edits_made += 1; }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["0".to_string(), "1".to_string()]; assert_eq!( expected_hints, @@ -1323,7 +1322,7 @@ pub mod tests { .expect("inlay refresh request failed"); edits_made += 1; cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["0".to_string(), "1".to_string(), "2".to_string()]; assert_eq!( expected_hints, @@ -1383,7 +1382,7 @@ pub mod tests { cx.executor().run_until_parked(); let mut edits_made = 1; - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["0".to_string()]; assert_eq!( expected_hints, @@ -1414,7 +1413,7 @@ pub mod tests { }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["0".to_string()]; assert_eq!( expected_hints, @@ -1438,7 +1437,7 @@ pub mod tests { cx.executor().run_until_parked(); edits_made += 1; - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["1".to_string()]; assert_eq!( expected_hints, @@ -1543,7 +1542,7 @@ pub mod tests { .next() .await; cx.executor().run_until_parked(); - rs_editor.update(cx, |editor, cx| { + _ = rs_editor.update(cx, |editor, cx| { let expected_hints = vec!["0".to_string()]; assert_eq!( expected_hints, @@ -1594,7 +1593,7 @@ pub mod tests { .next() .await; cx.executor().run_until_parked(); - md_editor.update(cx, |editor, cx| { + _ = md_editor.update(cx, |editor, cx| { let expected_hints = vec!["0".to_string()]; assert_eq!( expected_hints, @@ -1605,12 +1604,12 @@ pub mod tests { assert_eq!(editor.inlay_hint_cache().version, 1); }); - rs_editor.update(cx, |editor, cx| { + _ = rs_editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges([13..13])); editor.handle_input("some rs change", cx); }); cx.executor().run_until_parked(); - rs_editor.update(cx, |editor, cx| { + _ = rs_editor.update(cx, |editor, cx| { let expected_hints = vec!["1".to_string()]; assert_eq!( expected_hints, @@ -1624,7 +1623,7 @@ pub mod tests { "Every time hint cache changes, cache version should be incremented" ); }); - md_editor.update(cx, |editor, cx| { + _ = md_editor.update(cx, |editor, cx| { let expected_hints = vec!["0".to_string()]; assert_eq!( expected_hints, @@ -1635,12 +1634,12 @@ pub mod tests { assert_eq!(editor.inlay_hint_cache().version, 1); }); - md_editor.update(cx, |editor, cx| { + _ = md_editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges([13..13])); editor.handle_input("some md change", cx); }); cx.executor().run_until_parked(); - md_editor.update(cx, |editor, cx| { + _ = md_editor.update(cx, |editor, cx| { let expected_hints = vec!["1".to_string()]; assert_eq!( expected_hints, @@ -1650,7 +1649,7 @@ pub mod tests { assert_eq!(expected_hints, visible_hint_labels(editor, cx)); assert_eq!(editor.inlay_hint_cache().version, 2); }); - rs_editor.update(cx, |editor, cx| { + _ = rs_editor.update(cx, |editor, cx| { let expected_hints = vec!["1".to_string()]; assert_eq!( expected_hints, @@ -1725,7 +1724,7 @@ pub mod tests { cx.executor().run_until_parked(); let mut edits_made = 1; - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( lsp_request_count.load(Ordering::Relaxed), 1, @@ -1760,7 +1759,7 @@ pub mod tests { .await .expect("inlay refresh request failed"); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( lsp_request_count.load(Ordering::Relaxed), 2, @@ -1832,7 +1831,7 @@ pub mod tests { }) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( lsp_request_count.load(Ordering::Relaxed), 2, @@ -1876,7 +1875,7 @@ pub mod tests { }) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( lsp_request_count.load(Ordering::Relaxed), 2, @@ -1906,7 +1905,7 @@ pub mod tests { .await .expect("inlay refresh request failed"); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( lsp_request_count.load(Ordering::Relaxed), 2, @@ -1932,7 +1931,7 @@ pub mod tests { }) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( lsp_request_count.load(Ordering::Relaxed), 3, @@ -1968,7 +1967,7 @@ pub mod tests { .await .expect("inlay refresh request failed"); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( lsp_request_count.load(Ordering::Relaxed), 4, @@ -2035,7 +2034,7 @@ pub mod tests { "initial change #2", "initial change #3", ] { - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges([13..13])); editor.handle_input(change_after_opening, cx); }); @@ -2044,7 +2043,7 @@ pub mod tests { cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let current_text = editor.text(cx); for change in &expected_changes { assert!( @@ -2079,7 +2078,7 @@ pub mod tests { expected_changes.push(async_later_change); let task_editor = editor.clone(); edits.push(cx.spawn(|mut cx| async move { - task_editor.update(&mut cx, |editor, cx| { + _ = task_editor.update(&mut cx, |editor, cx| { editor.change_selections(None, cx, |s| s.select_ranges([13..13])); editor.handle_input(async_later_change, cx); }); @@ -2088,7 +2087,7 @@ pub mod tests { let _ = future::join_all(edits).await; cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let current_text = editor.text(cx); for change in &expected_changes { assert!( @@ -2246,7 +2245,7 @@ pub mod tests { lsp::Position::new(initial_visible_range.end.row * 2, 2); let mut expected_invisible_query_start = lsp_initial_visible_range.end; expected_invisible_query_start.character += 1; - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let ranges = lsp_request_ranges.lock().drain(..).collect::>(); assert_eq!(ranges.len(), 2, "When scroll is at the edge of a big document, its visible part and the same range further should be queried in order, but got: {ranges:?}"); @@ -2273,7 +2272,7 @@ pub mod tests { ); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.scroll_screen(&ScrollAmount::Page(1.0), cx); editor.scroll_screen(&ScrollAmount::Page(1.0), cx); }); @@ -2343,7 +2342,7 @@ pub mod tests { }) .unwrap(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(Some(Autoscroll::center()), cx, |s| { s.select_ranges([selection_in_cached_range..selection_in_cached_range]) }); @@ -2352,7 +2351,7 @@ pub mod tests { INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS + 100, )); cx.executor().run_until_parked(); - editor.update(cx, |_, _| { + _ = editor.update(cx, |_, _| { let ranges = lsp_request_ranges .lock() .drain(..) @@ -2362,14 +2361,14 @@ pub mod tests { assert_eq!(lsp_request_count.load(Ordering::Acquire), 4); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.handle_input("++++more text++++", cx); }); cx.executor().advance_clock(Duration::from_millis( INVISIBLE_RANGES_HINTS_REQUEST_DELAY_MILLIS + 100, )); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let mut ranges = lsp_request_ranges.lock().drain(..).collect::>(); ranges.sort_by_key(|r| r.start); @@ -2597,7 +2596,7 @@ pub mod tests { .await; cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec![ "main hint #0".to_string(), "main hint #1".to_string(), @@ -2615,7 +2614,7 @@ pub mod tests { assert_eq!(editor.inlay_hint_cache().version, expected_hints.len(), "Every visible excerpt hints should bump the verison"); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(Some(Autoscroll::Next), cx, |s| { s.select_ranges([Point::new(4, 0)..Point::new(4, 0)]) }); @@ -2627,7 +2626,7 @@ pub mod tests { }); }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec![ "main hint #0".to_string(), "main hint #1".to_string(), @@ -2646,7 +2645,7 @@ pub mod tests { "Due to every excerpt having one hint, we update cache per new excerpt scrolled"); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(Some(Autoscroll::Next), cx, |s| { s.select_ranges([Point::new(100, 0)..Point::new(100, 0)]) }); @@ -2677,13 +2676,13 @@ pub mod tests { expected_hints.len() }).unwrap(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(Some(Autoscroll::Next), cx, |s| { s.select_ranges([Point::new(4, 0)..Point::new(4, 0)]) }); }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec![ "main hint #0".to_string(), "main hint #1".to_string(), @@ -2705,7 +2704,7 @@ pub mod tests { }); editor_edited.store(true, Ordering::Release); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| { // TODO if this gets set to hint boundary (e.g. 56) we sometimes get an extra cache version bump, why? s.select_ranges([Point::new(57, 0)..Point::new(57, 0)]) @@ -2713,7 +2712,7 @@ pub mod tests { editor.handle_input("++++more text++++", cx); }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec![ "main hint(edited) #0".to_string(), "main hint(edited) #1".to_string(), @@ -2895,7 +2894,7 @@ pub mod tests { .await; cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( vec!["main hint #0".to_string(), "other hint #0".to_string()], cached_hint_labels(editor), @@ -2912,13 +2911,13 @@ pub mod tests { ); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.buffer().update(cx, |multibuffer, cx| { multibuffer.remove_excerpts(buffer_2_excerpts, cx) }) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert_eq!( vec!["main hint #0".to_string()], cached_hint_labels(editor), @@ -2944,7 +2943,7 @@ pub mod tests { }) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["main hint #0".to_string()]; assert_eq!( expected_hints, @@ -3041,13 +3040,13 @@ pub mod tests { .await; cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.change_selections(None, cx, |s| { s.select_ranges([Point::new(10, 0)..Point::new(10, 0)]) }) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["1".to_string()]; assert_eq!(expected_hints, cached_hint_labels(editor)); assert_eq!(expected_hints, visible_hint_labels(editor, cx)); @@ -3068,7 +3067,7 @@ pub mod tests { let (file_with_hints, editor, fake_server) = prepare_test_objects(cx).await; - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx) }); cx.executor().start_waiting(); @@ -3099,7 +3098,7 @@ pub mod tests { .next() .await; cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["1".to_string()]; assert_eq!( expected_hints, @@ -3114,11 +3113,11 @@ pub mod tests { ); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert!( cached_hint_labels(editor).is_empty(), "Should clear hints after 2nd toggle" @@ -3136,7 +3135,7 @@ pub mod tests { }) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["2".to_string()]; assert_eq!( expected_hints, @@ -3147,11 +3146,11 @@ pub mod tests { assert_eq!(editor.inlay_hint_cache().version, 3); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert!( cached_hint_labels(editor).is_empty(), "Should clear hints after enabling in settings and a 3rd toggle" @@ -3160,11 +3159,11 @@ pub mod tests { assert_eq!(editor.inlay_hint_cache().version, 4); }); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { editor.toggle_inlay_hints(&crate::ToggleInlayHints, cx) }); cx.executor().run_until_parked(); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { let expected_hints = vec!["3".to_string()]; assert_eq!( expected_hints, @@ -3223,7 +3222,7 @@ pub mod tests { .await; let project = Project::test(fs, ["/a".as_ref()], cx).await; - project.update(cx, |project, _| project.languages().add(Arc::new(language))); + _ = project.update(cx, |project, _| project.languages().add(Arc::new(language))); let buffer = project .update(cx, |project, cx| { project.open_local_buffer("/a/main.rs", cx) @@ -3235,7 +3234,7 @@ pub mod tests { let fake_server = fake_servers.next().await.unwrap(); let editor = cx.add_window(|cx| Editor::for_buffer(buffer, Some(project), cx)); - editor.update(cx, |editor, cx| { + _ = editor.update(cx, |editor, cx| { assert!(cached_hint_labels(editor).is_empty()); assert!(visible_hint_labels(editor, cx).is_empty()); assert_eq!(editor.inlay_hint_cache().version, 0); diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index ddb5b25db2..b10b891d0d 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -1,17 +1,15 @@ use crate::{ editor_settings::SeedQuerySetting, link_go_to_definition::hide_link_definition, - movement::surrounding_word, persistence::DB, scroll::ScrollAnchor, Anchor, Autoscroll, Editor, - EditorEvent, EditorSettings, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, - NavigationData, ToPoint as _, + persistence::DB, scroll::ScrollAnchor, Anchor, Autoscroll, Editor, EditorEvent, EditorSettings, + ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, NavigationData, ToPoint as _, }; use anyhow::{anyhow, Context as _, Result}; use collections::HashSet; use futures::future::try_join_all; use gpui::{ - div, point, AnyElement, AppContext, AsyncAppContext, AsyncWindowContext, Context, Div, Entity, - EntityId, EventEmitter, FocusHandle, IntoElement, Model, ParentElement, Pixels, Render, - SharedString, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, - WindowContext, + div, point, AnyElement, AppContext, AsyncWindowContext, Context, Div, Entity, EntityId, + EventEmitter, IntoElement, Model, ParentElement, Pixels, Render, SharedString, Styled, + Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use language::{ proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, CharKind, OffsetRangeExt, @@ -20,7 +18,7 @@ use language::{ use project::{search::SearchQuery, FormatTrigger, Item as _, Project, ProjectPath}; use rpc::proto::{self, update_view, PeerId}; use settings::Settings; -use smallvec::SmallVec; + use std::fmt::Write; use std::{ borrow::Cow, @@ -581,7 +579,7 @@ impl Item for Editor { } fn tab_content(&self, detail: Option, selected: bool, cx: &WindowContext) -> AnyElement { - let theme = cx.theme(); + let _theme = cx.theme(); let description = detail.and_then(|detail| { let path = path_for_buffer(&self.buffer, detail, false, cx)?; @@ -697,12 +695,14 @@ impl Item for Editor { })? .await?; for buffer in clean_buffers { - buffer.update(&mut cx, |buffer, cx| { - let version = buffer.saved_version().clone(); - let fingerprint = buffer.saved_version_fingerprint(); - let mtime = buffer.saved_mtime(); - buffer.did_save(version, fingerprint, mtime, cx); - }); + buffer + .update(&mut cx, |buffer, cx| { + let version = buffer.saved_version().clone(); + let fingerprint = buffer.saved_version_fingerprint(); + let mtime = buffer.saved_mtime(); + buffer.did_save(version, fingerprint, mtime, cx); + }) + .ok(); } } @@ -742,13 +742,15 @@ impl Item for Editor { this.update(&mut cx, |editor, cx| { editor.request_autoscroll(Autoscroll::fit(), cx) })?; - buffer.update(&mut cx, |buffer, cx| { - if let Some(transaction) = transaction { - if !buffer.is_singleton() { - buffer.push_transaction(&transaction.0, cx); + buffer + .update(&mut cx, |buffer, cx| { + if let Some(transaction) = transaction { + if !buffer.is_singleton() { + buffer.push_transaction(&transaction.0, cx); + } } - } - }); + }) + .ok(); Ok(()) }) } diff --git a/crates/editor2/src/link_go_to_definition.rs b/crates/editor2/src/link_go_to_definition.rs index ef17127797..42f502daed 100644 --- a/crates/editor2/src/link_go_to_definition.rs +++ b/crates/editor2/src/link_go_to_definition.rs @@ -618,7 +618,7 @@ mod tests { test::editor_lsp_test_context::EditorLspTestContext, }; use futures::StreamExt; - use gpui::{Modifiers, ModifiersChangedEvent, View}; + use gpui::{Modifiers, ModifiersChangedEvent}; use indoc::indoc; use language::language_settings::InlayHintSettings; use lsp::request::{GotoDefinition, GotoTypeDefinition}; diff --git a/crates/editor2/src/mouse_context_menu.rs b/crates/editor2/src/mouse_context_menu.rs index e6c0fc1111..24f3b22a5c 100644 --- a/crates/editor2/src/mouse_context_menu.rs +++ b/crates/editor2/src/mouse_context_menu.rs @@ -36,7 +36,7 @@ pub fn deploy_context_menu( s.set_pending_display_range(point..point, SelectMode::Character); }); - let context_menu = ui::ContextMenu::build(cx, |menu, cx| { + let context_menu = ui::ContextMenu::build(cx, |menu, _cx| { menu.action("Rename Symbol", Box::new(Rename)) .action("Go to Definition", Box::new(GoToDefinition)) .action("Go to Type Definition", Box::new(GoToTypeDefinition)) @@ -53,7 +53,7 @@ pub fn deploy_context_menu( let context_menu_focus = context_menu.focus_handle(cx); cx.focus(&context_menu_focus); - let _subscription = cx.subscribe(&context_menu, move |this, _, event: &DismissEvent, cx| { + let _subscription = cx.subscribe(&context_menu, move |this, _, _event: &DismissEvent, cx| { this.mouse_context_menu.take(); if context_menu_focus.contains_focused(cx) { this.focus(cx); @@ -97,7 +97,7 @@ mod tests { do_wˇork(); } "}); - cx.editor(|editor, app| assert!(editor.mouse_context_menu.is_none())); + cx.editor(|editor, _app| assert!(editor.mouse_context_menu.is_none())); cx.update_editor(|editor, cx| deploy_context_menu(editor, Default::default(), point, cx)); cx.assert_editor_state(indoc! {" @@ -105,6 +105,6 @@ mod tests { do_wˇork(); } "}); - cx.editor(|editor, app| assert!(editor.mouse_context_menu.is_some())); + cx.editor(|editor, _app| assert!(editor.mouse_context_menu.is_some())); } } diff --git a/crates/editor2/src/movement.rs b/crates/editor2/src/movement.rs index ab25bb8499..8190586968 100644 --- a/crates/editor2/src/movement.rs +++ b/crates/editor2/src/movement.rs @@ -2,7 +2,7 @@ use super::{Bias, DisplayPoint, DisplaySnapshot, SelectionGoal, ToDisplayPoint}; use crate::{char_kind, CharKind, EditorStyle, ToOffset, ToPoint}; use gpui::{px, Pixels, TextSystem}; use language::Point; -use serde::de::IntoDeserializer; + use std::{ops::Range, sync::Arc}; #[derive(Debug, PartialEq)] @@ -757,7 +757,7 @@ mod tests { let mut cx = EditorTestContext::new(cx).await; let editor = cx.editor.clone(); let window = cx.window.clone(); - cx.update_window(window, |_, cx| { + _ = cx.update_window(window, |_, cx| { let text_layout_details = editor.update(cx, |editor, cx| editor.text_layout_details(cx)); diff --git a/crates/editor2/src/rust_analyzer_ext.rs b/crates/editor2/src/rust_analyzer_ext.rs index 0ebf242504..a4e68ff837 100644 --- a/crates/editor2/src/rust_analyzer_ext.rs +++ b/crates/editor2/src/rust_analyzer_ext.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use anyhow::Context as _; -use gpui::{Context, Model, View, ViewContext, VisualContext, WindowContext}; +use gpui::{Context, View, ViewContext, VisualContext, WindowContext}; use language::Language; use multi_buffer::MultiBuffer; use project::lsp_ext_command::ExpandMacro; @@ -91,7 +91,7 @@ pub fn expand_macro_recursively( cx, ) }); - cx.spawn(|editor, mut cx| async move { + cx.spawn(|_editor, mut cx| async move { let macro_expansion = expand_macro_task.await.context("expand macro")?; if macro_expansion.is_empty() { log::info!("Empty macro expansion for position {position:?}"); diff --git a/crates/editor2/src/scroll.rs b/crates/editor2/src/scroll.rs index 208dcc0dd3..0798870f76 100644 --- a/crates/editor2/src/scroll.rs +++ b/crates/editor2/src/scroll.rs @@ -9,7 +9,7 @@ use crate::{ Anchor, DisplayPoint, Editor, EditorEvent, EditorMode, InlayHintRefreshReason, MultiBufferSnapshot, ToPoint, }; -use gpui::{point, px, AppContext, Entity, Pixels, Styled, Task, ViewContext}; +use gpui::{point, px, AppContext, Entity, Pixels, Task, ViewContext}; use language::{Bias, Point}; use std::{ cmp::Ordering, diff --git a/crates/editor2/src/scroll/actions.rs b/crates/editor2/src/scroll/actions.rs index 9a1e54f5e4..21a4258f6f 100644 --- a/crates/editor2/src/scroll/actions.rs +++ b/crates/editor2/src/scroll/actions.rs @@ -3,7 +3,7 @@ use crate::{ Autoscroll, Bias, Editor, EditorMode, NextScreen, ScrollAnchor, ScrollCursorBottom, ScrollCursorCenter, ScrollCursorTop, }; -use gpui::{actions, AppContext, Point, ViewContext}; +use gpui::{Point, ViewContext}; impl Editor { pub fn next_screen(&mut self, _: &NextScreen, cx: &mut ViewContext) { diff --git a/crates/editor2/src/scroll/autoscroll.rs b/crates/editor2/src/scroll/autoscroll.rs index 9315d5c099..ba70739942 100644 --- a/crates/editor2/src/scroll/autoscroll.rs +++ b/crates/editor2/src/scroll/autoscroll.rs @@ -61,7 +61,7 @@ impl Editor { display_map.max_point().row() as f32 }; if scroll_position.y > max_scroll_top { - scroll_position.y = (max_scroll_top); + scroll_position.y = max_scroll_top; self.set_scroll_position(scroll_position, cx); } @@ -143,24 +143,24 @@ impl Editor { let needs_scroll_down = target_bottom >= end_row; if needs_scroll_up && !needs_scroll_down { - scroll_position.y = (target_top); + scroll_position.y = target_top; self.set_scroll_position_internal(scroll_position, local, true, cx); } if !needs_scroll_up && needs_scroll_down { - scroll_position.y = (target_bottom - visible_lines); + scroll_position.y = target_bottom - visible_lines; self.set_scroll_position_internal(scroll_position, local, true, cx); } } AutoscrollStrategy::Center => { - scroll_position.y = ((target_top - margin).max(0.0)); + scroll_position.y = (target_top - margin).max(0.0); self.set_scroll_position_internal(scroll_position, local, true, cx); } AutoscrollStrategy::Top => { - scroll_position.y = ((target_top).max(0.0)); + scroll_position.y = (target_top).max(0.0); self.set_scroll_position_internal(scroll_position, local, true, cx); } AutoscrollStrategy::Bottom => { - scroll_position.y = ((target_bottom - visible_lines).max(0.0)); + scroll_position.y = (target_bottom - visible_lines).max(0.0); self.set_scroll_position_internal(scroll_position, local, true, cx); } } diff --git a/crates/editor2/src/test/editor_test_context.rs b/crates/editor2/src/test/editor_test_context.rs index 0b6fb69d71..bd5acb9945 100644 --- a/crates/editor2/src/test/editor_test_context.rs +++ b/crates/editor2/src/test/editor_test_context.rs @@ -4,8 +4,7 @@ use crate::{ use collections::BTreeMap; use futures::Future; use gpui::{ - AnyWindowHandle, AppContext, ForegroundExecutor, Keystroke, ModelContext, View, ViewContext, - VisualTestContext, WindowHandle, + AnyWindowHandle, AppContext, Keystroke, ModelContext, View, ViewContext, VisualTestContext, }; use indoc::indoc; use itertools::Itertools; diff --git a/crates/workspace2/src/persistence.rs b/crates/workspace2/src/persistence.rs index 1abb06dccf..5358ee3f4c 100644 --- a/crates/workspace2/src/persistence.rs +++ b/crates/workspace2/src/persistence.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] +//#![allow(dead_code)] pub mod model; diff --git a/crates/zed2/src/open_listener.rs b/crates/zed2/src/open_listener.rs index b45254f717..6db020a785 100644 --- a/crates/zed2/src/open_listener.rs +++ b/crates/zed2/src/open_listener.rs @@ -251,12 +251,11 @@ pub async fn handle_cli_connection( let wait = async move { if paths.is_empty() { let (done_tx, done_rx) = oneshot::channel(); - let _subscription = - workspace.update(&mut cx, |workspace, cx| { - cx.on_release(move |_, _, _| { - let _ = done_tx.send(()); - }) - }); + let _subscription = workspace.update(&mut cx, |_, cx| { + cx.on_release(move |_, _, _| { + let _ = done_tx.send(()); + }) + }); let _ = done_rx.await; } else { let _ = futures::future::try_join_all(item_release_futures) diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index aa21a3e995..4abc81cf37 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -1,6 +1,3 @@ -#![allow(unused_variables, unused_mut)] -//todo!() - mod app_menus; mod assets; pub mod languages; @@ -37,9 +34,8 @@ use util::{ use uuid::Uuid; use workspace::Pane; use workspace::{ - create_and_open_local_file, dock::PanelHandle, - notifications::simple_message_notification::MessageNotification, open_new, AppState, NewFile, - NewWindow, Workspace, WorkspaceSettings, + create_and_open_local_file, notifications::simple_message_notification::MessageNotification, + open_new, AppState, NewFile, NewWindow, Workspace, WorkspaceSettings, }; use zed_actions::{OpenBrowser, OpenSettings, OpenZedURL, Quit}; @@ -184,7 +180,6 @@ pub fn initialize_workspace(app_state: Arc, cx: &mut AppContext) { )?; workspace_handle.update(&mut cx, |workspace, cx| { - let project_panel_position = project_panel.position(cx); workspace.add_panel(project_panel, cx); workspace.add_panel(terminal_panel, cx); workspace.add_panel(assistant_panel, cx); @@ -473,7 +468,7 @@ fn quit(_: &mut Workspace, _: &Quit, cx: &mut gpui::ViewContext) { }) .log_err(); - if let (true, Some(window)) = (should_confirm, workspace_windows.first().copied()) { + if let (true, Some(_)) = (should_confirm, workspace_windows.first().copied()) { let answer = cx .update(|_, cx| { cx.prompt( @@ -484,7 +479,7 @@ fn quit(_: &mut Workspace, _: &Quit, cx: &mut gpui::ViewContext) { }) .log_err(); - if let Some(mut answer) = answer { + if let Some(answer) = answer { let answer = answer.await.ok(); if answer != Some(0) { return Ok(()); From 12fe64b1774a7650440be1da3f3ceae96041f8f8 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 25 Dec 2023 07:02:19 -0500 Subject: [PATCH 331/644] Fix more warnings --- crates/zed2/src/main.rs | 91 +++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index f1fd168ffd..8ddce12f99 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -250,7 +250,7 @@ fn main() { cx: &mut AppContext, ) { let task = workspace::open_paths(&paths, &app_state, None, cx); - cx.spawn(|cx| async move { + cx.spawn(|_| async move { if let Some((_window, results)) = task.await.log_err() { for result in results { if let Some(Err(e)) = result { @@ -311,53 +311,48 @@ fn main() { } let app_state = app_state.clone(); - let closure_client = client.clone(); - cx.spawn(move |mut cx| { - let client = closure_client.clone(); - async move { - while let Some(request) = open_rx.next().await { - match request { - OpenRequest::Paths { paths } => { - cx.update(|cx| open_paths_and_log_errs(&paths, &app_state, cx)) - .ok(); - } - OpenRequest::CliConnection { connection } => { - let app_state = app_state.clone(); - cx.spawn(move |cx| { - handle_cli_connection(connection, app_state.clone(), cx) - }) - .detach(); - } - OpenRequest::JoinChannel { channel_id } => { - let app_state = app_state.clone(); - cx.update(|mut cx| { - cx.spawn(|cx| async move { - cx.update(|cx| { - workspace::join_channel(channel_id, app_state, None, cx) - })? - .await?; - anyhow::Ok(()) - }) - .detach_and_log_err(&mut cx); - }) - .log_err(); - } - OpenRequest::OpenChannelNotes { channel_id } => { - let app_state = app_state.clone(); - let open_notes_task = cx.spawn(|mut cx| async move { - let workspace_window = - workspace::get_any_active_workspace(app_state, cx.clone()) - .await?; - let _ = workspace_window - .update(&mut cx, |_, cx| { - ChannelView::open(channel_id, cx.view().clone(), cx) - })? - .await?; + cx.spawn(move |cx| async move { + while let Some(request) = open_rx.next().await { + match request { + OpenRequest::Paths { paths } => { + cx.update(|cx| open_paths_and_log_errs(&paths, &app_state, cx)) + .ok(); + } + OpenRequest::CliConnection { connection } => { + let app_state = app_state.clone(); + cx.spawn(move |cx| { + handle_cli_connection(connection, app_state.clone(), cx) + }) + .detach(); + } + OpenRequest::JoinChannel { channel_id } => { + let app_state = app_state.clone(); + cx.update(|mut cx| { + cx.spawn(|cx| async move { + cx.update(|cx| { + workspace::join_channel(channel_id, app_state, None, cx) + })? + .await?; anyhow::Ok(()) - }); - cx.update(|cx| open_notes_task.detach_and_log_err(cx)) - .log_err(); - } + }) + .detach_and_log_err(&mut cx); + }) + .log_err(); + } + OpenRequest::OpenChannelNotes { channel_id } => { + let app_state = app_state.clone(); + let open_notes_task = cx.spawn(|mut cx| async move { + let workspace_window = + workspace::get_any_active_workspace(app_state, cx.clone()).await?; + let _ = workspace_window + .update(&mut cx, |_, cx| { + ChannelView::open(channel_id, cx.view().clone(), cx) + })? + .await?; + anyhow::Ok(()) + }); + cx.update(|cx| open_notes_task.detach_and_log_err(cx)) + .log_err(); } } } @@ -773,7 +768,7 @@ async fn watch_languages(fs: Arc, languages: Arc) fn watch_file_types(fs: Arc, cx: &mut AppContext) { use std::time::Duration; - cx.spawn(|mut cx| async move { + cx.spawn(|cx| async move { let mut events = fs .watch( "assets/icons/file_icons/file_types.json".as_ref(), From ee57658abe86a55b2f267cb4c853a90d500bef17 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Mon, 25 Dec 2023 13:30:27 +0100 Subject: [PATCH 332/644] Fix up superfluous mod declaration --- crates/zed2/src/main.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/zed2/src/main.rs b/crates/zed2/src/main.rs index 8ddce12f99..2fbb9c101d 100644 --- a/crates/zed2/src/main.rs +++ b/crates/zed2/src/main.rs @@ -53,8 +53,6 @@ use zed2::{ OpenListener, OpenRequest, }; -mod open_listener; - fn main() { menu::init(); zed_actions::init(); From 16626592dba30f9572e8957221ef5eff33673f86 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:23:08 +0100 Subject: [PATCH 333/644] Remove allow unused from gpui2, vim2 tests and terminal_view2 (#3813) Release Notes: - N/A --- crates/gpui2/src/color.rs | 2 -- crates/terminal_view2/src/terminal_element.rs | 14 +++----------- crates/terminal_view2/src/terminal_view.rs | 15 ++++----------- .../test/neovim_backed_binding_test_context.rs | 3 --- .../vim2/src/test/neovim_backed_test_context.rs | 5 +---- crates/vim2/src/test/vim_test_context.rs | 3 --- 6 files changed, 8 insertions(+), 34 deletions(-) diff --git a/crates/gpui2/src/color.rs b/crates/gpui2/src/color.rs index 44a0e917be..d5514d900f 100644 --- a/crates/gpui2/src/color.rs +++ b/crates/gpui2/src/color.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - use anyhow::bail; use serde::de::{self, Deserialize, Deserializer, Visitor}; use std::fmt; diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index eb7348b935..fc87ac45bd 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -248,14 +248,8 @@ impl TerminalElement { { let cell_text = cell.c.to_string(); if !is_blank(&cell) { - let cell_style = TerminalElement::cell_style( - &cell, - fg, - theme, - text_style, - text_system, - hyperlink, - ); + let cell_style = + TerminalElement::cell_style(&cell, fg, theme, text_style, hyperlink); let layout_cell = text_system .shape_line( @@ -315,7 +309,6 @@ impl TerminalElement { // bg: terminal::alacritty_terminal::ansi::Color, colors: &Theme, text_style: &TextStyle, - text_system: &TextSystem, hyperlink: Option<(HighlightStyle, &RangeInclusive)>, ) -> TextRun { let flags = indexed.cell.flags; @@ -392,7 +385,6 @@ impl TerminalElement { let font_size = font_size.map_or(buffer_font_size, |size| theme::adjusted_font_size(size, cx)); - let settings = ThemeSettings::get_global(cx); let theme = cx.theme().clone(); let link_style = HighlightStyle { @@ -898,7 +890,7 @@ impl PlatformInputHandler for TerminalInputHandler { None } - fn text_for_range(&mut self, range_utf16: std::ops::Range) -> Option { + fn text_for_range(&mut self, _: std::ops::Range) -> Option { None } diff --git a/crates/terminal_view2/src/terminal_view.rs b/crates/terminal_view2/src/terminal_view.rs index f82a43959b..6d18d6f8f9 100644 --- a/crates/terminal_view2/src/terminal_view.rs +++ b/crates/terminal_view2/src/terminal_view.rs @@ -1,6 +1,3 @@ -#![allow(unused_variables)] -//todo!(remove) - mod persistence; pub mod terminal_element; pub mod terminal_panel; @@ -68,11 +65,9 @@ pub fn init(cx: &mut AppContext) { register_deserializable_item::(cx); - cx.observe_new_views( - |workspace: &mut Workspace, cx: &mut ViewContext| { - workspace.register_action(TerminalView::deploy); - }, - ) + cx.observe_new_views(|workspace: &mut Workspace, _| { + workspace.register_action(TerminalView::deploy); + }) .detach(); } @@ -141,7 +136,6 @@ impl TerminalView { workspace_id: WorkspaceId, cx: &mut ViewContext, ) -> Self { - let view_id = cx.entity_id(); cx.observe(&terminal, |_, _, cx| cx.notify()).detach(); cx.subscribe(&terminal, move |this, _, event, cx| match event { Event::Wakeup => { @@ -308,7 +302,7 @@ impl TerminalView { position: gpui::Point, cx: &mut ViewContext, ) { - let context_menu = ContextMenu::build(cx, |menu, cx| { + let context_menu = ContextMenu::build(cx, |menu, _| { menu.action("Clear", Box::new(Clear)) .action("Close", Box::new(CloseActiveItem { save_intent: None })) }); @@ -628,7 +622,6 @@ impl Render for TerminalView { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let terminal_handle = self.terminal.clone(); - let self_id = cx.entity_id(); let focused = self.focus_handle.is_focused(cx); div() diff --git a/crates/vim2/src/test/neovim_backed_binding_test_context.rs b/crates/vim2/src/test/neovim_backed_binding_test_context.rs index 3b97cb2b16..15fce99aad 100644 --- a/crates/vim2/src/test/neovim_backed_binding_test_context.rs +++ b/crates/vim2/src/test/neovim_backed_binding_test_context.rs @@ -1,6 +1,3 @@ -#![allow(unused)] -// todo!() - use std::ops::{Deref, DerefMut}; use crate::state::Mode; diff --git a/crates/vim2/src/test/neovim_backed_test_context.rs b/crates/vim2/src/test/neovim_backed_test_context.rs index 21455de552..7380537655 100644 --- a/crates/vim2/src/test/neovim_backed_test_context.rs +++ b/crates/vim2/src/test/neovim_backed_test_context.rs @@ -1,8 +1,5 @@ -#![allow(unused)] -// todo!() - use editor::{scroll::VERTICAL_SCROLL_MARGIN, test::editor_test_context::ContextHandle}; -use gpui::{point, px, rems, size, Context}; +use gpui::{px, size, Context}; use indoc::indoc; use settings::SettingsStore; use std::{ diff --git a/crates/vim2/src/test/vim_test_context.rs b/crates/vim2/src/test/vim_test_context.rs index 3956964480..47afc20785 100644 --- a/crates/vim2/src/test/vim_test_context.rs +++ b/crates/vim2/src/test/vim_test_context.rs @@ -1,6 +1,3 @@ -#![allow(unused)] -// todo!() - use std::ops::{Deref, DerefMut}; use editor::test::{ From af6f4678900f3eb6f5732ada8ae5e03db2a44a0b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 26 Dec 2023 13:49:00 +0200 Subject: [PATCH 334/644] Avoid trailing separators in file finder --- crates/file_finder2/src/file_finder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 8ca7d46f29..69deba6d2c 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -546,7 +546,7 @@ impl PickerDelegate for FileFinderDelegate { fn separators_after_indices(&self) -> Vec { let history_items = self.matches.history.len(); - if history_items == 0 { + if history_items == 0 || self.matches.search.is_empty() { Vec::new() } else { vec![history_items - 1] From f27c63bb5424f2633e4c5ff71b1a08bb34d68cc4 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 26 Dec 2023 14:09:29 +0200 Subject: [PATCH 335/644] Fix color-related terminal todo! --- crates/project2/src/terminals.rs | 1 - crates/project2/src/worktree.rs | 1 - crates/terminal2/src/terminal2.rs | 113 ++++++++++++++++-- crates/terminal_view2/src/terminal_element.rs | 111 ++--------------- 4 files changed, 110 insertions(+), 116 deletions(-) diff --git a/crates/project2/src/terminals.rs b/crates/project2/src/terminals.rs index 1bf69aa8b5..a816c0ddb2 100644 --- a/crates/project2/src/terminals.rs +++ b/crates/project2/src/terminals.rs @@ -37,7 +37,6 @@ impl Project { Some(settings.blinking.clone()), settings.alternate_scroll, window, - |_, _| todo!("color_for_index"), ) .map(|builder| { let terminal_handle = cx.build_model(|cx| builder.subscribe(cx)); diff --git a/crates/project2/src/worktree.rs b/crates/project2/src/worktree.rs index a5cb322cb5..22b3cd8c65 100644 --- a/crates/project2/src/worktree.rs +++ b/crates/project2/src/worktree.rs @@ -2184,7 +2184,6 @@ impl LocalSnapshot { ignore_stack } - #[allow(dead_code)] // todo!("remove this when we use it") #[cfg(test)] pub(crate) fn expanded_entries(&self) -> impl Iterator { self.entries_by_path diff --git a/crates/terminal2/src/terminal2.rs b/crates/terminal2/src/terminal2.rs index 9d3c00d81f..b15bd7c6d6 100644 --- a/crates/terminal2/src/terminal2.rs +++ b/crates/terminal2/src/terminal2.rs @@ -35,6 +35,7 @@ use procinfo::LocalProcessInfo; use serde::{Deserialize, Serialize}; use settings::Settings; use terminal_settings::{AlternateScroll, Shell, TerminalBlink, TerminalSettings}; +use theme::{ActiveTheme, Theme}; use util::truncate_and_trailoff; use std::{ @@ -50,9 +51,9 @@ use std::{ use thiserror::Error; use gpui::{ - actions, px, AnyWindowHandle, AppContext, Bounds, ClipboardItem, EventEmitter, Hsla, Keystroke, - ModelContext, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels, - Point, ScrollWheelEvent, Size, Task, TouchPhase, + actions, black, px, red, AnyWindowHandle, AppContext, Bounds, ClipboardItem, EventEmitter, + Hsla, Keystroke, ModelContext, Modifiers, MouseButton, MouseDownEvent, MouseMoveEvent, + MouseUpEvent, Pixels, Point, Rgba, ScrollWheelEvent, Size, Task, TouchPhase, }; use crate::mappings::{colors::to_alac_rgb, keys::to_esc_str}; @@ -299,7 +300,6 @@ impl TerminalBuilder { blink_settings: Option, alternate_scroll: AlternateScroll, window: AnyWindowHandle, - color_for_index: impl Fn(usize, &mut AppContext) -> Hsla + Send + Sync + 'static, ) -> Result { let pty_config = { let alac_shell = match shell.clone() { @@ -405,7 +405,6 @@ impl TerminalBuilder { selection_phase: SelectionPhase::Ended, cmd_pressed: false, hovered_word: false, - color_for_index: Box::new(color_for_index), }; Ok(TerminalBuilder { @@ -562,8 +561,6 @@ pub struct Terminal { selection_phase: SelectionPhase, cmd_pressed: bool, hovered_word: bool, - // An implementation of the 8 bit ANSI color palette - color_for_index: Box Hsla + Send + Sync + 'static>, } impl Terminal { @@ -646,8 +643,9 @@ impl Terminal { ) { match event { InternalEvent::ColorRequest(index, format) => { - let color = term.colors()[*index] - .unwrap_or_else(|| to_alac_rgb((self.color_for_index)(*index, cx))); + let color = term.colors()[*index].unwrap_or_else(|| { + to_alac_rgb(get_color_at_index(*index, cx.theme().as_ref())) + }); self.write_to_pty(format(color)) } InternalEvent::Resize(mut new_size) => { @@ -1418,6 +1416,90 @@ fn content_index_for_mouse(pos: Point, size: &TerminalSize) -> usize { clamped_row * size.columns() + clamped_col } +///Converts an 8 bit ANSI color to it's GPUI equivalent. +///Accepts usize for compatibility with the alacritty::Colors interface, +///Other than that use case, should only be called with values in the [0,255] range +pub fn get_color_at_index(index: usize, theme: &Theme) -> Hsla { + let colors = theme.colors(); + + match index { + //0-15 are the same as the named colors above + 0 => colors.terminal_ansi_black, + 1 => colors.terminal_ansi_red, + 2 => colors.terminal_ansi_green, + 3 => colors.terminal_ansi_yellow, + 4 => colors.terminal_ansi_blue, + 5 => colors.terminal_ansi_magenta, + 6 => colors.terminal_ansi_cyan, + 7 => colors.terminal_ansi_white, + 8 => colors.terminal_ansi_bright_black, + 9 => colors.terminal_ansi_bright_red, + 10 => colors.terminal_ansi_bright_green, + 11 => colors.terminal_ansi_bright_yellow, + 12 => colors.terminal_ansi_bright_blue, + 13 => colors.terminal_ansi_bright_magenta, + 14 => colors.terminal_ansi_bright_cyan, + 15 => colors.terminal_ansi_bright_white, + //16-231 are mapped to their RGB colors on a 0-5 range per channel + 16..=231 => { + let (r, g, b) = rgb_for_index(&(index as u8)); //Split the index into it's ANSI-RGB components + let step = (u8::MAX as f32 / 5.).floor() as u8; //Split the RGB range into 5 chunks, with floor so no overflow + rgba_color(r * step, g * step, b * step) //Map the ANSI-RGB components to an RGB color + } + //232-255 are a 24 step grayscale from black to white + 232..=255 => { + let i = index as u8 - 232; //Align index to 0..24 + let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks + rgba_color(i * step, i * step, i * step) //Map the ANSI-grayscale components to the RGB-grayscale + } + //For compatibility with the alacritty::Colors interface + 256 => colors.text, + 257 => colors.background, + 258 => theme.players().local().cursor, + + // todo!(more colors) + 259 => red(), //style.dim_black, + 260 => red(), //style.dim_red, + 261 => red(), //style.dim_green, + 262 => red(), //style.dim_yellow, + 263 => red(), //style.dim_blue, + 264 => red(), //style.dim_magenta, + 265 => red(), //style.dim_cyan, + 266 => red(), //style.dim_white, + 267 => red(), //style.bright_foreground, + 268 => colors.terminal_ansi_black, //'Dim Background', non-standard color + + _ => black(), + } +} + +///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube +///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit). +/// +///Wikipedia gives a formula for calculating the index for a given color: +/// +///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5) +/// +///This function does the reverse, calculating the r, g, and b components from a given index. +fn rgb_for_index(i: &u8) -> (u8, u8, u8) { + debug_assert!((&16..=&231).contains(&i)); + let i = i - 16; + let r = (i - (i % 36)) / 36; + let g = ((i % 36) - (i % 6)) / 6; + let b = (i % 36) % 6; + (r, g, b) +} + +pub fn rgba_color(r: u8, g: u8, b: u8) -> Hsla { + Rgba { + r: (r as f32 / 255.) as f32, + g: (g as f32 / 255.) as f32, + b: (b as f32 / 255.) as f32, + a: 1., + } + .into() +} + #[cfg(test)] mod tests { use alacritty_terminal::{ @@ -1427,7 +1509,18 @@ mod tests { use gpui::{point, size, Pixels}; use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng}; - use crate::{content_index_for_mouse, IndexedCell, TerminalContent, TerminalSize}; + use crate::{ + content_index_for_mouse, rgb_for_index, IndexedCell, TerminalContent, TerminalSize, + }; + + #[test] + fn test_rgb_for_index() { + //Test every possible value in the color cube + for i in 16..=231 { + let (r, g, b) = rgb_for_index(&(i as u8)); + assert_eq!(i, 16 + 36 * r + 6 * g + b); + } + } #[test] fn test_mouse_to_cell_test() { diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index fc87ac45bd..dcadc04e21 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -1,12 +1,11 @@ use editor::{Cursor, HighlightedRange, HighlightedRangeLine}; use gpui::{ - black, div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace, + div, fill, point, px, red, relative, AnyElement, AsyncWindowContext, AvailableSpace, BorrowWindow, Bounds, DispatchPhase, Element, ElementId, ExternalPaths, FocusHandle, Font, FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState, Interactivity, IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, - Pixels, PlatformInputHandler, Point, Rgba, ShapedLine, StatefulInteractiveElement, - StyleRefinement, Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, - WindowContext, + Pixels, PlatformInputHandler, Point, ShapedLine, StatefulInteractiveElement, StyleRefinement, + Styled, TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext, }; use itertools::Itertools; use language::CursorShape; @@ -1048,108 +1047,12 @@ fn convert_color(fg: &terminal::alacritty_terminal::ansi::Color, theme: &Theme) NamedColor::DimForeground => red(), }, //'True' colors - terminal::alacritty_terminal::ansi::Color::Spec(rgb) => rgba_color(rgb.r, rgb.g, rgb.b), + terminal::alacritty_terminal::ansi::Color::Spec(rgb) => { + terminal::rgba_color(rgb.r, rgb.g, rgb.b) + } //8 bit, indexed colors terminal::alacritty_terminal::ansi::Color::Indexed(i) => { - get_color_at_index(&(*i as usize), theme) - } - } -} - -///Converts an 8 bit ANSI color to it's GPUI equivalent. -///Accepts usize for compatibility with the alacritty::Colors interface, -///Other than that use case, should only be called with values in the [0,255] range -pub fn get_color_at_index(index: &usize, theme: &Theme) -> Hsla { - let colors = theme.colors(); - - match index { - //0-15 are the same as the named colors above - 0 => colors.terminal_ansi_black, - 1 => colors.terminal_ansi_red, - 2 => colors.terminal_ansi_green, - 3 => colors.terminal_ansi_yellow, - 4 => colors.terminal_ansi_blue, - 5 => colors.terminal_ansi_magenta, - 6 => colors.terminal_ansi_cyan, - 7 => colors.terminal_ansi_white, - 8 => colors.terminal_ansi_bright_black, - 9 => colors.terminal_ansi_bright_red, - 10 => colors.terminal_ansi_bright_green, - 11 => colors.terminal_ansi_bright_yellow, - 12 => colors.terminal_ansi_bright_blue, - 13 => colors.terminal_ansi_bright_magenta, - 14 => colors.terminal_ansi_bright_cyan, - 15 => colors.terminal_ansi_bright_white, - //16-231 are mapped to their RGB colors on a 0-5 range per channel - 16..=231 => { - let (r, g, b) = rgb_for_index(&(*index as u8)); //Split the index into it's ANSI-RGB components - let step = (u8::MAX as f32 / 5.).floor() as u8; //Split the RGB range into 5 chunks, with floor so no overflow - rgba_color(r * step, g * step, b * step) //Map the ANSI-RGB components to an RGB color - } - //232-255 are a 24 step grayscale from black to white - 232..=255 => { - let i = *index as u8 - 232; //Align index to 0..24 - let step = (u8::MAX as f32 / 24.).floor() as u8; //Split the RGB grayscale values into 24 chunks - rgba_color(i * step, i * step, i * step) //Map the ANSI-grayscale components to the RGB-grayscale - } - //For compatibility with the alacritty::Colors interface - 256 => colors.text, - 257 => colors.background, - 258 => theme.players().local().cursor, - - // todo!(more colors) - 259 => red(), //style.dim_black, - 260 => red(), //style.dim_red, - 261 => red(), //style.dim_green, - 262 => red(), //style.dim_yellow, - 263 => red(), //style.dim_blue, - 264 => red(), //style.dim_magenta, - 265 => red(), //style.dim_cyan, - 266 => red(), //style.dim_white, - 267 => red(), //style.bright_foreground, - 268 => colors.terminal_ansi_black, //'Dim Background', non-standard color - - _ => black(), - } -} - -///Generates the rgb channels in [0, 5] for a given index into the 6x6x6 ANSI color cube -///See: [8 bit ansi color](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit). -/// -///Wikipedia gives a formula for calculating the index for a given color: -/// -///index = 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5) -/// -///This function does the reverse, calculating the r, g, and b components from a given index. -fn rgb_for_index(i: &u8) -> (u8, u8, u8) { - debug_assert!((&16..=&231).contains(&i)); - let i = i - 16; - let r = (i - (i % 36)) / 36; - let g = ((i % 36) - (i % 6)) / 6; - let b = (i % 36) % 6; - (r, g, b) -} - -fn rgba_color(r: u8, g: u8, b: u8) -> Hsla { - Rgba { - r: (r as f32 / 255.) as f32, - g: (g as f32 / 255.) as f32, - b: (b as f32 / 255.) as f32, - a: 1., - } - .into() -} - -#[cfg(test)] -mod tests { - use crate::terminal_element::rgb_for_index; - - #[test] - fn test_rgb_for_index() { - //Test every possible value in the color cube - for i in 16..=231 { - let (r, g, b) = rgb_for_index(&(i as u8)); - assert_eq!(i, 16 + 36 * r + 6 * g + b); + terminal::get_color_at_index(*i as usize, theme) } } } From 937f237c8ffd31ac9cc53b6b4f998aa1ab9e97d1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 26 Dec 2023 14:58:29 +0200 Subject: [PATCH 336/644] Add breadcrumbs to the multibuffer editor The breadcrumbs are not being open on the fisrt time, for some reason. --- crates/breadcrumbs2/src/breadcrumbs.rs | 58 ++++++++------------------ 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/crates/breadcrumbs2/src/breadcrumbs.rs b/crates/breadcrumbs2/src/breadcrumbs.rs index e579c8ded0..da7182ec2c 100644 --- a/crates/breadcrumbs2/src/breadcrumbs.rs +++ b/crates/breadcrumbs2/src/breadcrumbs.rs @@ -11,10 +11,6 @@ use workspace::{ ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, }; -pub enum Event { - UpdateLocation, -} - pub struct Breadcrumbs { pane_focused: bool, active_item: Option>, @@ -31,7 +27,6 @@ impl Breadcrumbs { } } -impl EventEmitter for Breadcrumbs {} impl EventEmitter for Breadcrumbs {} impl Render for Breadcrumbs { @@ -39,15 +34,9 @@ impl Render for Breadcrumbs { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let element = h_stack().text_ui(); - - let Some(active_item) = &self - .active_item - .as_ref() - .filter(|item| item.downcast::().is_some()) - else { + let Some(active_item) = self.active_item.as_ref() else { return element; }; - let Some(segments) = active_item.breadcrumbs(cx.theme(), cx) else { return element; }; @@ -64,21 +53,24 @@ impl Render for Breadcrumbs { Label::new("›").color(Color::Muted).into_any_element() }); - let editor = active_item + let breadcrumbs_stack = h_stack().gap_1().children(breadcrumbs); + match active_item .downcast::() - .map(|editor| editor.downgrade()); - - element.child( - ButtonLike::new("toggle outline view") - .style(ButtonStyle::Subtle) - .child(h_stack().gap_1().children(breadcrumbs)) - .on_click(move |_, cx| { - if let Some(editor) = editor.as_ref().and_then(|editor| editor.upgrade()) { - outline::toggle(editor, &outline::Toggle, cx) - } - }) - .tooltip(|cx| Tooltip::for_action("Show symbol outline", &outline::Toggle, cx)), - ) + .map(|editor| editor.downgrade()) + { + Some(editor) => element.child( + ButtonLike::new("toggle outline view") + .child(breadcrumbs_stack) + .style(ButtonStyle::Subtle) + .on_click(move |_, cx| { + if let Some(editor) = editor.upgrade() { + outline::toggle(editor, &outline::Toggle, cx) + } + }) + .tooltip(|cx| Tooltip::for_action("Show symbol outline", &outline::Toggle, cx)), + ), + None => element.child(breadcrumbs_stack), + } } } @@ -97,7 +89,6 @@ impl ToolbarItemView for Breadcrumbs { Box::new(move |event, cx| { if let ItemEvent::UpdateBreadcrumbs = event { this.update(cx, |_, cx| { - cx.emit(Event::UpdateLocation); cx.notify(); }) .ok(); @@ -111,19 +102,6 @@ impl ToolbarItemView for Breadcrumbs { } } - // fn location_for_event( - // &self, - // _: &Event, - // current_location: ToolbarItemLocation, - // cx: &AppContext, - // ) -> ToolbarItemLocation { - // if let Some(active_item) = self.active_item.as_ref() { - // active_item.breadcrumb_location(cx) - // } else { - // current_location - // } - // } - fn pane_focus_update(&mut self, pane_focused: bool, _: &mut ViewContext) { self.pane_focused = pane_focused; } From 5cfd4b06b956616b559b1b1a125385948ab40bb2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Dec 2023 10:46:25 -0700 Subject: [PATCH 337/644] Use correct terminal background color --- crates/terminal_view2/src/terminal_element.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index dcadc04e21..55da76383a 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -438,7 +438,7 @@ impl TerminalElement { let search_matches = self.terminal.read(cx).matches.clone(); - let background_color = theme.colors().background; + let background_color = theme.colors().terminal_background; let last_hovered_word = self.terminal.update(cx, |terminal, cx| { terminal.set_size(dimensions); From ddd6f0806b4fdb14d1c74737bfc5bc0afc55eae2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Dec 2023 11:08:43 -0700 Subject: [PATCH 338/644] Render cursor text with the terminal's background color --- crates/terminal_view2/src/terminal_element.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index 55da76383a..e5dd8472fe 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -287,8 +287,8 @@ impl TerminalElement { text_fragment.width }; - //Cursor should always surround as much of the text as possible, - //hence when on pixel boundaries round the origin down and the width up + // Cursor should always surround as much of the text as possible, + // hence when on pixel boundaries round the origin down and the width up Some(( point( (cursor_point.col() as f32 * size.cell_width()).floor(), @@ -301,7 +301,7 @@ impl TerminalElement { } } - ///Convert the Alacritty cell styles to GPUI text styles and background color + /// Convert the Alacritty cell styles to GPUI text styles and background color fn cell_style( indexed: &IndexedCell, fg: terminal::alacritty_terminal::ansi::Color, @@ -498,13 +498,6 @@ impl TerminalElement { let cursor_point = DisplayCursor::from(cursor.point, *display_offset); let cursor_text = { let str_trxt = cursor_char.to_string(); - - let color = if self.focused { - theme.players().local().background - } else { - theme.players().local().cursor - }; - let len = str_trxt.len(); cx.text_system() .shape_line( @@ -513,7 +506,7 @@ impl TerminalElement { &[TextRun { len, font: text_style.font(), - color, + color: theme.colors().terminal_background, background_color: None, underline: Default::default(), }], From a2b0f14dc166f279cba3cdad63f1fbbd50292a8f Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Dec 2023 11:23:12 -0700 Subject: [PATCH 339/644] Rename size to dimensions for consistency --- crates/terminal_view2/src/terminal_element.rs | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index e5dd8472fe..cb46f742f6 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -34,7 +34,7 @@ pub struct LayoutState { relative_highlighted_ranges: Vec<(RangeInclusive, Hsla)>, cursor: Option, background_color: Hsla, - size: TerminalSize, + dimensions: TerminalSize, mode: TermMode, display_offset: usize, hyperlink_tooltip: Option, @@ -86,12 +86,12 @@ impl LayoutCell { let point = self.point; Point::new( - (origin.x + point.column as f32 * layout.size.cell_width).floor(), - origin.y + point.line as f32 * layout.size.line_height, + (origin.x + point.column as f32 * layout.dimensions.cell_width).floor(), + origin.y + point.line as f32 * layout.dimensions.line_height, ) }; - self.text.paint(pos, layout.size.line_height, cx).ok(); + self.text.paint(pos, layout.dimensions.line_height, cx).ok(); } } @@ -123,13 +123,13 @@ impl LayoutRect { let position = { let alac_point = self.point; point( - (origin.x + alac_point.column as f32 * layout.size.cell_width).floor(), - origin.y + alac_point.line as f32 * layout.size.line_height, + (origin.x + alac_point.column as f32 * layout.dimensions.cell_width).floor(), + origin.y + alac_point.line as f32 * layout.dimensions.line_height, ) }; let size = point( - (layout.size.cell_width * self.num_of_cells as f32).ceil(), - layout.size.line_height, + (layout.dimensions.cell_width * self.num_of_cells as f32).ceil(), + layout.dimensions.line_height, ) .into(); @@ -545,7 +545,7 @@ impl TerminalElement { cells, cursor, background_color, - size: dimensions, + dimensions, rects, relative_highlighted_ranges, mode: *mode, @@ -808,11 +808,11 @@ impl Element for TerminalElement { { let hr = HighlightedRange { start_y, //Need to change this - line_height: layout.size.line_height, + line_height: layout.dimensions.line_height, lines: highlighted_range_lines, color: color.clone(), //Copied from editor. TODO: move to theme or something - corner_radius: 0.15 * layout.size.line_height, + corner_radius: 0.15 * layout.dimensions.line_height, }; hr.paint(bounds, cx); } @@ -969,21 +969,24 @@ fn to_highlighted_range_lines( AlacPoint::new(range.end().line + layout.display_offset, range.end().column); // Step 2. Clamp range to viewport, and return None if it doesn't overlap - if unclamped_end.line.0 < 0 || unclamped_start.line.0 > layout.size.num_lines() as i32 { + if unclamped_end.line.0 < 0 || unclamped_start.line.0 > layout.dimensions.num_lines() as i32 { return None; } let clamped_start_line = unclamped_start.line.0.max(0) as usize; - let clamped_end_line = unclamped_end.line.0.min(layout.size.num_lines() as i32) as usize; + let clamped_end_line = unclamped_end + .line + .0 + .min(layout.dimensions.num_lines() as i32) as usize; //Convert the start of the range to pixels - let start_y = origin.y + clamped_start_line as f32 * layout.size.line_height; + let start_y = origin.y + clamped_start_line as f32 * layout.dimensions.line_height; // Step 3. Expand ranges that cross lines into a collection of single-line ranges. // (also convert to pixels) let mut highlighted_range_lines = Vec::new(); for line in clamped_start_line..=clamped_end_line { let mut line_start = 0; - let mut line_end = layout.size.columns(); + let mut line_end = layout.dimensions.columns(); if line == clamped_start_line { line_start = unclamped_start.column.0 as usize; @@ -993,8 +996,8 @@ fn to_highlighted_range_lines( } highlighted_range_lines.push(HighlightedRangeLine { - start_x: origin.x + line_start as f32 * layout.size.cell_width, - end_x: origin.x + line_end as f32 * layout.size.cell_width, + start_x: origin.x + line_start as f32 * layout.dimensions.cell_width, + end_x: origin.x + line_end as f32 * layout.dimensions.cell_width, }); } From 02f7e681a77628f18939f1418ea89c22801caf88 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 27 Dec 2023 11:58:26 -0700 Subject: [PATCH 340/644] Import elevated surface color from hover popover --- crates/theme2/src/themes/andromeda.rs | 2 +- crates/theme2/src/themes/atelier.rs | 40 ++++++++++----------- crates/theme2/src/themes/ayu.rs | 6 ++-- crates/theme2/src/themes/gruvbox.rs | 12 +++---- crates/theme2/src/themes/one.rs | 4 +-- crates/theme2/src/themes/rose_pine.rs | 6 ++-- crates/theme2/src/themes/sandcastle.rs | 2 +- crates/theme2/src/themes/solarized.rs | 4 +-- crates/theme2/src/themes/summercamp.rs | 2 +- crates/theme_importer/src/zed1/converter.rs | 6 +++- 10 files changed, 44 insertions(+), 40 deletions(-) diff --git a/crates/theme2/src/themes/andromeda.rs b/crates/theme2/src/themes/andromeda.rs index 0a9b977d21..2e5b2578a0 100644 --- a/crates/theme2/src/themes/andromeda.rs +++ b/crates/theme2/src/themes/andromeda.rs @@ -21,7 +21,7 @@ pub fn andromeda() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x252931ff).into()), border_variant: Some(rgba(0x21232aff).into()), - elevated_surface_background: Some(rgba(0x262a33ff).into()), + elevated_surface_background: Some(rgba(0x21242bff).into()), background: Some(rgba(0x262a33ff).into()), panel_background: Some(rgba(0x21242bff).into()), element_hover: Some(rgba(0x2b2f3980).into()), diff --git a/crates/theme2/src/themes/atelier.rs b/crates/theme2/src/themes/atelier.rs index e5c2e49d5b..1d069dd2be 100644 --- a/crates/theme2/src/themes/atelier.rs +++ b/crates/theme2/src/themes/atelier.rs @@ -22,7 +22,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xd1d0c6ff).into()), border_variant: Some(rgba(0xedece5ff).into()), - elevated_surface_background: Some(rgba(0xc5c4b9ff).into()), + elevated_surface_background: Some(rgba(0xebeae3ff).into()), background: Some(rgba(0xc5c4b9ff).into()), panel_background: Some(rgba(0xebeae3ff).into()), element_hover: Some(rgba(0x96958580).into()), @@ -425,7 +425,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x3b3431ff).into()), border_variant: Some(rgba(0x251f1dff).into()), - elevated_surface_background: Some(rgba(0x443c39ff).into()), + elevated_surface_background: Some(rgba(0x27211eff).into()), background: Some(rgba(0x443c39ff).into()), panel_background: Some(rgba(0x27211eff).into()), element_hover: Some(rgba(0x665f5c80).into()), @@ -828,7 +828,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xc8d1cbff).into()), border_variant: Some(rgba(0xe5ede7ff).into()), - elevated_surface_background: Some(rgba(0xbcc5bfff).into()), + elevated_surface_background: Some(rgba(0xe3ebe6ff).into()), background: Some(rgba(0xbcc5bfff).into()), panel_background: Some(rgba(0xe3ebe6ff).into()), element_hover: Some(rgba(0x8b968e80).into()), @@ -1231,7 +1231,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x332f38ff).into()), border_variant: Some(rgba(0x201e24ff).into()), - elevated_surface_background: Some(rgba(0x3a353fff).into()), + elevated_surface_background: Some(rgba(0x221f26ff).into()), background: Some(rgba(0x3a353fff).into()), panel_background: Some(rgba(0x221f26ff).into()), element_hover: Some(rgba(0x56505e80).into()), @@ -1634,7 +1634,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x3c3b31ff).into()), border_variant: Some(rgba(0x2a2922ff).into()), - elevated_surface_background: Some(rgba(0x424136ff).into()), + elevated_surface_background: Some(rgba(0x2c2b23ff).into()), background: Some(rgba(0x424136ff).into()), panel_background: Some(rgba(0x2c2b23ff).into()), element_hover: Some(rgba(0x5d5c4c80).into()), @@ -2037,7 +2037,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x363f62ff).into()), border_variant: Some(rgba(0x252d4fff).into()), - elevated_surface_background: Some(rgba(0x3e4769ff).into()), + elevated_surface_background: Some(rgba(0x262f51ff).into()), background: Some(rgba(0x3e4769ff).into()), panel_background: Some(rgba(0x262f51ff).into()), element_hover: Some(rgba(0x5c648580).into()), @@ -2440,7 +2440,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xccd0e1ff).into()), border_variant: Some(rgba(0xe9ebf7ff).into()), - elevated_surface_background: Some(rgba(0xc2c6d9ff).into()), + elevated_surface_background: Some(rgba(0xe5e8f5ff).into()), background: Some(rgba(0xc2c6d9ff).into()), panel_background: Some(rgba(0xe5e8f5ff).into()), element_hover: Some(rgba(0x9a9fb680).into()), @@ -2843,7 +2843,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x3b3933ff).into()), border_variant: Some(rgba(0x252521ff).into()), - elevated_surface_background: Some(rgba(0x45433bff).into()), + elevated_surface_background: Some(rgba(0x262622ff).into()), background: Some(rgba(0x45433bff).into()), panel_background: Some(rgba(0x262622ff).into()), element_hover: Some(rgba(0x6c695c80).into()), @@ -3246,7 +3246,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x333b33ff).into()), border_variant: Some(rgba(0x1d201dff).into()), - elevated_surface_background: Some(rgba(0x3b453bff).into()), + elevated_surface_background: Some(rgba(0x1f231fff).into()), background: Some(rgba(0x3b453bff).into()), panel_background: Some(rgba(0x1f231fff).into()), element_hover: Some(rgba(0x5c6c5c80).into()), @@ -3649,7 +3649,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xcbc8d1ff).into()), border_variant: Some(rgba(0xe8e5edff).into()), - elevated_surface_background: Some(rgba(0xbfbcc5ff).into()), + elevated_surface_background: Some(rgba(0xe6e3ebff).into()), background: Some(rgba(0xbfbcc5ff).into()), panel_background: Some(rgba(0xe6e3ebff).into()), element_hover: Some(rgba(0x8f8b9680).into()), @@ -4052,7 +4052,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x352f2fff).into()), border_variant: Some(rgba(0x231f1fff).into()), - elevated_surface_background: Some(rgba(0x3b3535ff).into()), + elevated_surface_background: Some(rgba(0x252020ff).into()), background: Some(rgba(0x3b3535ff).into()), panel_background: Some(rgba(0x252020ff).into()), element_hover: Some(rgba(0x564e4e80).into()), @@ -4455,7 +4455,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x393239ff).into()), border_variant: Some(rgba(0x231e23ff).into()), - elevated_surface_background: Some(rgba(0x433a43ff).into()), + elevated_surface_background: Some(rgba(0x252025ff).into()), background: Some(rgba(0x433a43ff).into()), panel_background: Some(rgba(0x252025ff).into()), element_hover: Some(rgba(0x675b6780).into()), @@ -4858,7 +4858,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x2c3b42ff).into()), border_variant: Some(rgba(0x1b2327ff).into()), - elevated_surface_background: Some(rgba(0x33444dff).into()), + elevated_surface_background: Some(rgba(0x1c2529ff).into()), background: Some(rgba(0x33444dff).into()), panel_background: Some(rgba(0x1c2529ff).into()), element_hover: Some(rgba(0x4f6b7880).into()), @@ -5261,7 +5261,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xd6d1cfff).into()), border_variant: Some(rgba(0xebe8e6ff).into()), - elevated_surface_background: Some(rgba(0xcdc8c6ff).into()), + elevated_surface_background: Some(rgba(0xe9e6e4ff).into()), background: Some(rgba(0xcdc8c6ff).into()), panel_background: Some(rgba(0xe9e6e4ff).into()), element_hover: Some(rgba(0xaaa3a180).into()), @@ -5664,7 +5664,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xd7d3beff).into()), border_variant: Some(rgba(0xf2eedcff).into()), - elevated_surface_background: Some(rgba(0xcecab4ff).into()), + elevated_surface_background: Some(rgba(0xeeebd7ff).into()), background: Some(rgba(0xcecab4ff).into()), panel_background: Some(rgba(0xeeebd7ff).into()), element_hover: Some(rgba(0xa8a48e80).into()), @@ -6067,7 +6067,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xcfc7c7ff).into()), border_variant: Some(rgba(0xede5e5ff).into()), - elevated_surface_background: Some(rgba(0xc1bbbbff).into()), + elevated_surface_background: Some(rgba(0xebe3e3ff).into()), background: Some(rgba(0xc1bbbbff).into()), panel_background: Some(rgba(0xebe3e3ff).into()), element_hover: Some(rgba(0x8e898980).into()), @@ -6470,7 +6470,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xbed7beff).into()), border_variant: Some(rgba(0xdff0dfff).into()), - elevated_surface_background: Some(rgba(0xb4ceb4ff).into()), + elevated_surface_background: Some(rgba(0xdaeedaff).into()), background: Some(rgba(0xb4ceb4ff).into()), panel_background: Some(rgba(0xdaeedaff).into()), element_hover: Some(rgba(0x8ea88e80).into()), @@ -6873,7 +6873,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x2f3832ff).into()), border_variant: Some(rgba(0x1e2420ff).into()), - elevated_surface_background: Some(rgba(0x353f39ff).into()), + elevated_surface_background: Some(rgba(0x1f2621ff).into()), background: Some(rgba(0x353f39ff).into()), panel_background: Some(rgba(0x1f2621ff).into()), element_hover: Some(rgba(0x505e5580).into()), @@ -7276,7 +7276,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xcdbecdff).into()), border_variant: Some(rgba(0xe5dce5ff).into()), - elevated_surface_background: Some(rgba(0xc6b8c6ff).into()), + elevated_surface_background: Some(rgba(0xe1d6e1ff).into()), background: Some(rgba(0xc6b8c6ff).into()), panel_background: Some(rgba(0xe1d6e1ff).into()), element_hover: Some(rgba(0xad9dad80).into()), @@ -7679,7 +7679,7 @@ pub fn atelier() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xb0d3e5ff).into()), border_variant: Some(rgba(0xd3edfaff).into()), - elevated_surface_background: Some(rgba(0xa6cadcff).into()), + elevated_surface_background: Some(rgba(0xcdeaf9ff).into()), background: Some(rgba(0xa6cadcff).into()), panel_background: Some(rgba(0xcdeaf9ff).into()), element_hover: Some(rgba(0x80a4b680).into()), diff --git a/crates/theme2/src/themes/ayu.rs b/crates/theme2/src/themes/ayu.rs index 7c0eb70108..d4c1d0fbe5 100644 --- a/crates/theme2/src/themes/ayu.rs +++ b/crates/theme2/src/themes/ayu.rs @@ -22,7 +22,7 @@ pub fn ayu() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x2d2f34ff).into()), border_variant: Some(rgba(0x1b1e24ff).into()), - elevated_surface_background: Some(rgba(0x313337ff).into()), + elevated_surface_background: Some(rgba(0x1f2127ff).into()), background: Some(rgba(0x313337ff).into()), panel_background: Some(rgba(0x1f2127ff).into()), element_hover: Some(rgba(0x3f404380).into()), @@ -404,7 +404,7 @@ pub fn ayu() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xdfe0e1ff).into()), border_variant: Some(rgba(0xefeff0ff).into()), - elevated_surface_background: Some(rgba(0xdcdddeff).into()), + elevated_surface_background: Some(rgba(0xececedff).into()), background: Some(rgba(0xdcdddeff).into()), panel_background: Some(rgba(0xececedff).into()), element_hover: Some(rgba(0xcfd1d280).into()), @@ -786,7 +786,7 @@ pub fn ayu() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x43464fff).into()), border_variant: Some(rgba(0x323641ff).into()), - elevated_surface_background: Some(rgba(0x464a52ff).into()), + elevated_surface_background: Some(rgba(0x353944ff).into()), background: Some(rgba(0x464a52ff).into()), panel_background: Some(rgba(0x353944ff).into()), element_hover: Some(rgba(0x53565d80).into()), diff --git a/crates/theme2/src/themes/gruvbox.rs b/crates/theme2/src/themes/gruvbox.rs index 8cc13fb177..148264933f 100644 --- a/crates/theme2/src/themes/gruvbox.rs +++ b/crates/theme2/src/themes/gruvbox.rs @@ -22,7 +22,7 @@ pub fn gruvbox() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xddcca7ff).into()), border_variant: Some(rgba(0xefe2bcff).into()), - elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), + elevated_surface_background: Some(rgba(0xecddb5ff).into()), background: Some(rgba(0xd9c8a4ff).into()), panel_background: Some(rgba(0xecddb5ff).into()), element_hover: Some(rgba(0xc9b99a80).into()), @@ -411,7 +411,7 @@ pub fn gruvbox() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x494340ff).into()), border_variant: Some(rgba(0x393634ff).into()), - elevated_surface_background: Some(rgba(0x4c4642ff).into()), + elevated_surface_background: Some(rgba(0x3b3735ff).into()), background: Some(rgba(0x4c4642ff).into()), panel_background: Some(rgba(0x3b3735ff).into()), element_hover: Some(rgba(0x5b534d80).into()), @@ -800,7 +800,7 @@ pub fn gruvbox() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xddcca7ff).into()), border_variant: Some(rgba(0xefe1b8ff).into()), - elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), + elevated_surface_background: Some(rgba(0xecddb4ff).into()), background: Some(rgba(0xd9c8a4ff).into()), panel_background: Some(rgba(0xecddb4ff).into()), element_hover: Some(rgba(0xc9b99a80).into()), @@ -1189,7 +1189,7 @@ pub fn gruvbox() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x494340ff).into()), border_variant: Some(rgba(0x373432ff).into()), - elevated_surface_background: Some(rgba(0x4c4642ff).into()), + elevated_surface_background: Some(rgba(0x3a3735ff).into()), background: Some(rgba(0x4c4642ff).into()), panel_background: Some(rgba(0x3a3735ff).into()), element_hover: Some(rgba(0x5b534d80).into()), @@ -1578,7 +1578,7 @@ pub fn gruvbox() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xddcca7ff).into()), border_variant: Some(rgba(0xeddeb5ff).into()), - elevated_surface_background: Some(rgba(0xd9c8a4ff).into()), + elevated_surface_background: Some(rgba(0xecdcb3ff).into()), background: Some(rgba(0xd9c8a4ff).into()), panel_background: Some(rgba(0xecdcb3ff).into()), element_hover: Some(rgba(0xc9b99a80).into()), @@ -1967,7 +1967,7 @@ pub fn gruvbox() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x494340ff).into()), border_variant: Some(rgba(0x343130ff).into()), - elevated_surface_background: Some(rgba(0x4c4642ff).into()), + elevated_surface_background: Some(rgba(0x393634ff).into()), background: Some(rgba(0x4c4642ff).into()), panel_background: Some(rgba(0x393634ff).into()), element_hover: Some(rgba(0x5b534d80).into()), diff --git a/crates/theme2/src/themes/one.rs b/crates/theme2/src/themes/one.rs index e62ccbefdd..4a0d54648a 100644 --- a/crates/theme2/src/themes/one.rs +++ b/crates/theme2/src/themes/one.rs @@ -22,7 +22,7 @@ pub fn one() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xdfdfe0ff).into()), border_variant: Some(rgba(0xeeeeeeff).into()), - elevated_surface_background: Some(rgba(0xdcdcddff).into()), + elevated_surface_background: Some(rgba(0xebebecff).into()), background: Some(rgba(0xdcdcddff).into()), panel_background: Some(rgba(0xebebecff).into()), element_hover: Some(rgba(0xc9c9ca80).into()), @@ -411,7 +411,7 @@ pub fn one() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x363c46ff).into()), border_variant: Some(rgba(0x2e333cff).into()), - elevated_surface_background: Some(rgba(0x3b414dff).into()), + elevated_surface_background: Some(rgba(0x2f343eff).into()), background: Some(rgba(0x3b414dff).into()), panel_background: Some(rgba(0x2f343eff).into()), element_hover: Some(rgba(0x464b5780).into()), diff --git a/crates/theme2/src/themes/rose_pine.rs b/crates/theme2/src/themes/rose_pine.rs index 318767cb2b..48e315ae80 100644 --- a/crates/theme2/src/themes/rose_pine.rs +++ b/crates/theme2/src/themes/rose_pine.rs @@ -22,7 +22,7 @@ pub fn rose_pine() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xe5e0dfff).into()), border_variant: Some(rgba(0xfdf8f1ff).into()), - elevated_surface_background: Some(rgba(0xdcd8d8ff).into()), + elevated_surface_background: Some(rgba(0xfef9f2ff).into()), background: Some(rgba(0xdcd8d8ff).into()), panel_background: Some(rgba(0xfef9f2ff).into()), element_hover: Some(rgba(0xdcd6d580).into()), @@ -418,7 +418,7 @@ pub fn rose_pine() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x322f48ff).into()), border_variant: Some(rgba(0x27243bff).into()), - elevated_surface_background: Some(rgba(0x38354eff).into()), + elevated_surface_background: Some(rgba(0x28253cff).into()), background: Some(rgba(0x38354eff).into()), panel_background: Some(rgba(0x28253cff).into()), element_hover: Some(rgba(0x504c6880).into()), @@ -814,7 +814,7 @@ pub fn rose_pine() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x232132ff).into()), border_variant: Some(rgba(0x1c1a29ff).into()), - elevated_surface_background: Some(rgba(0x292739ff).into()), + elevated_surface_background: Some(rgba(0x1d1b2aff).into()), background: Some(rgba(0x292739ff).into()), panel_background: Some(rgba(0x1d1b2aff).into()), element_hover: Some(rgba(0x423f5580).into()), diff --git a/crates/theme2/src/themes/sandcastle.rs b/crates/theme2/src/themes/sandcastle.rs index 5aa0398874..184a6751de 100644 --- a/crates/theme2/src/themes/sandcastle.rs +++ b/crates/theme2/src/themes/sandcastle.rs @@ -21,7 +21,7 @@ pub fn sandcastle() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x313741ff).into()), border_variant: Some(rgba(0x2a2f38ff).into()), - elevated_surface_background: Some(rgba(0x333944ff).into()), + elevated_surface_background: Some(rgba(0x2b3039ff).into()), background: Some(rgba(0x333944ff).into()), panel_background: Some(rgba(0x2b3039ff).into()), element_hover: Some(rgba(0x3d435080).into()), diff --git a/crates/theme2/src/themes/solarized.rs b/crates/theme2/src/themes/solarized.rs index c71ce54a2f..0fd20760c2 100644 --- a/crates/theme2/src/themes/solarized.rs +++ b/crates/theme2/src/themes/solarized.rs @@ -22,7 +22,7 @@ pub fn solarized() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0xdcdacbff).into()), border_variant: Some(rgba(0xf5eedbff).into()), - elevated_surface_background: Some(rgba(0xcfd0c4ff).into()), + elevated_surface_background: Some(rgba(0xf3eddaff).into()), background: Some(rgba(0xcfd0c4ff).into()), panel_background: Some(rgba(0xf3eddaff).into()), element_hover: Some(rgba(0x9faaa880).into()), @@ -404,7 +404,7 @@ pub fn solarized() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x063541ff).into()), border_variant: Some(rgba(0x032f3bff).into()), - elevated_surface_background: Some(rgba(0x083743ff).into()), + elevated_surface_background: Some(rgba(0x04313cff).into()), background: Some(rgba(0x083743ff).into()), panel_background: Some(rgba(0x04313cff).into()), element_hover: Some(rgba(0x2b4f5880).into()), diff --git a/crates/theme2/src/themes/summercamp.rs b/crates/theme2/src/themes/summercamp.rs index a849988f7b..987c64e9f2 100644 --- a/crates/theme2/src/themes/summercamp.rs +++ b/crates/theme2/src/themes/summercamp.rs @@ -21,7 +21,7 @@ pub fn summercamp() -> UserThemeFamily { colors: ThemeColorsRefinement { border: Some(rgba(0x29251bff).into()), border_variant: Some(rgba(0x221e15ff).into()), - elevated_surface_background: Some(rgba(0x2a261cff).into()), + elevated_surface_background: Some(rgba(0x231f16ff).into()), background: Some(rgba(0x2a261cff).into()), panel_background: Some(rgba(0x231f16ff).into()), element_hover: Some(rgba(0x312d2180).into()), diff --git a/crates/theme_importer/src/zed1/converter.rs b/crates/theme_importer/src/zed1/converter.rs index a12d96054c..01381b2257 100644 --- a/crates/theme_importer/src/zed1/converter.rs +++ b/crates/theme_importer/src/zed1/converter.rs @@ -133,7 +133,11 @@ impl Zed1ThemeConverter { border: convert(active_tab.container.border.color), border_variant: convert(toolbar.container.border.color), background: convert(self.theme.workspace.background), - elevated_surface_background: picker.container.background_color.map(zed1_color_to_hsla), + elevated_surface_background: editor + .hover_popover + .container + .background_color + .map(zed1_color_to_hsla), title_bar_background: title_bar.container.background_color.map(zed1_color_to_hsla), status_bar_background: status_bar .container From e932f4cf47e67e7372b0b91dfa32fc3c54b6a558 Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Thu, 28 Dec 2023 19:22:43 +0100 Subject: [PATCH 341/644] Bump Rust to 1.75 (#3815) **This PR also bumps wasmtime version from 0.38 to 2.0 as 0.38 does not build with Rust 1.75**. I did not test the plugin runtime as (AFAIK) we intend to deprecate it; also, wasmtime's most recent version is 16.0, so it'd make sense to bump the version at some point anyways. I did not bump the version to 16.0 straight away as that'd require code changes in `plugin_runtime`. Release Notes: - N/A --- Cargo.lock | 507 +++++++++++------- Dockerfile | 2 +- crates/collab2/src/tests.rs | 1 - crates/gpui/src/util.rs | 1 - crates/language/src/buffer.rs | 2 +- crates/language2/src/buffer.rs | 2 +- crates/plugin_runtime/Cargo.toml | 8 +- .../ui2/src/components/button/button_like.rs | 1 + crates/ui2/src/ui2.rs | 3 +- rust-toolchain.toml | 2 +- 10 files changed, 320 insertions(+), 209 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 01230cd805..7256782e31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1303,40 +1303,39 @@ dependencies = [ [[package]] name = "cap-fs-ext" -version = "0.24.4" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54b86398b5852ddd45784b1d9b196b98beb39171821bad4b8b44534a1e87927" +checksum = "0b0e103ce36d217d568903ad27b14ec2238ecb5d65bad2e756a8f3c0d651506e" dependencies = [ "cap-primitives", "cap-std", - "io-lifetimes 0.5.3", - "winapi 0.3.9", + "io-lifetimes 0.7.5", + "windows-sys 0.36.1", ] [[package]] name = "cap-primitives" -version = "0.24.4" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8fca3e81fae1d91a36e9784ca22a39ef623702b5f7904d89dc31f10184a178" +checksum = "af3f336aa91cce16033ed3c94ac91d98956c49b420e6d6cd0dd7d0e386a57085" dependencies = [ "ambient-authority", - "errno 0.2.8", "fs-set-times", "io-extras", - "io-lifetimes 0.5.3", + "io-lifetimes 0.7.5", "ipnet", "maybe-owned", - "rustix 0.33.7", - "winapi 0.3.9", + "rustix 0.35.16", "winapi-util", + "windows-sys 0.36.1", "winx", ] [[package]] name = "cap-rand" -version = "0.24.4" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3b27294116983d706f4c8168f6d10c84f9f5daed0c28bc7d0296cf16bcf971" +checksum = "d14b9606aa9550d34651bc481443203bc014237bdb992d201d2afa62d2ec6dea" dependencies = [ "ambient-authority", "rand 0.8.5", @@ -1344,26 +1343,26 @@ dependencies = [ [[package]] name = "cap-std" -version = "0.24.4" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2247568946095c7765ad2b441a56caffc08027734c634a6d5edda648f04e32eb" +checksum = "c9d6e70b626eceac9d6fc790fe2d72cc3f2f7bc3c35f467690c54a526b0f56db" dependencies = [ "cap-primitives", "io-extras", - "io-lifetimes 0.5.3", + "io-lifetimes 0.7.5", "ipnet", - "rustix 0.33.7", + "rustix 0.35.16", ] [[package]] name = "cap-time-ext" -version = "0.24.4" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50472b6ebc302af0401fa3fb939694cd8ff00e0d4c9182001e434fc822ab83a" +checksum = "c3a0524f7c4cff2ea547ae2b652bf7a348fd3e48f76556dc928d8b45ab2f1d50" dependencies = [ "cap-primitives", "once_cell", - "rustix 0.33.7", + "rustix 0.35.16", "winx", ] @@ -2367,19 +2366,21 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "749d0d6022c9038dccf480bdde2a38d435937335bf2bb0f14e815d94517cdce8" +checksum = "593b398dd0c5b1e2e3a9c3dae8584e287894ea84e361949ad506376e99196265" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94370cc7b37bf652ccd8bb8f09bd900997f7ccf97520edfc75554bb5c4abbea" +checksum = "afc0d8faabd099ea15ab33d49d150e5572c04cfeb95d675fd41286739b754629" dependencies = [ + "arrayvec 0.7.4", + "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", @@ -2394,33 +2395,33 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a3cea8fdab90e44018c5b9a1dfd460d8ee265ac354337150222a354628bdb6" +checksum = "1ac1669e42579476f001571d6ba4b825fac686282c97b88b18f8e34242066a81" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac72f76f2698598951ab26d8c96eaa854810e693e7dd52523958b5909fde6b2" +checksum = "e2a1b1eef9640ab72c1e7b583ac678083855a509da34b4b4378bd99954127c20" [[package]] name = "cranelift-entity" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09eaeacfcd2356fe0e66b295e8f9d59fdd1ac3ace53ba50de14d628ec902f72d" +checksum = "eea4e17c3791fd8134640b26242a9ddbd7c67db78f0bad98cb778bf563ef81a0" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba69c9980d5ffd62c18a2bde927855fcd7c8dc92f29feaf8636052662cbd99c" +checksum = "fca1474b5302348799656d43a40eacd716a3b46169405a3af812832c9edf77b4" dependencies = [ "cranelift-codegen", "log", @@ -2430,15 +2431,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2920dc1e05cac40304456ed3301fde2c09bd6a9b0210bcfa2f101398d628d5b" +checksum = "77aa537f020ea43483100153278e7215d41695bdcef9eea6642d122675f64249" [[package]] name = "cranelift-native" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04dfa45f9b2a6f587c564d6b63388e00cd6589d2df6ea2758cf79e1a13285e6" +checksum = "8bdc6b65241a95b7d8eafbf4e114c082e49b80162a2dcd9c6bcc5989c3310c9e" dependencies = [ "cranelift-codegen", "libc", @@ -2447,9 +2448,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.85.3" +version = "0.89.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31a46513ae6f26f3f267d8d75b5373d555fbbd1e68681f348d99df43f747ec54" +checksum = "4eb6359f606a1c80ccaa04fae9dbbb504615ec7a49b6c212b341080fff7a65dd" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -3092,12 +3093,12 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ "humantime", - "is-terminal 0.4.9", + "is-terminal 0.4.10", "log", "regex", "termcolor", @@ -3325,7 +3326,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84f2e425d9790201ba4af4630191feac6dcc98765b118d4d18e91d23c2353866" dependencies = [ - "env_logger 0.10.0", + "env_logger 0.10.1", "log", ] @@ -3550,13 +3551,13 @@ dependencies = [ [[package]] name = "fs-set-times" -version = "0.15.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df62ee66ee2d532ea8d567b5a3f0d03ecd64636b98bad5be1e93dcc918b92aa" +checksum = "a267b6a9304912e018610d53fe07115d8b530b160e85db4d2d3a59f3ddde1aec" dependencies = [ - "io-lifetimes 0.5.3", - "rustix 0.33.7", - "winapi 0.3.9", + "io-lifetimes 0.7.5", + "rustix 0.35.16", + "windows-sys 0.36.1", ] [[package]] @@ -4142,15 +4143,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.6", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -4545,22 +4537,22 @@ dependencies = [ [[package]] name = "io-extras" -version = "0.13.2" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c937cc9891c12eaa8c63ad347e4a288364b1328b924886970b47a14ab8f8f8" +checksum = "4a5d8c2ab5becd8720e30fd25f8fa5500d8dc3fceadd8378f05859bd7b46fc49" dependencies = [ - "io-lifetimes 0.5.3", - "winapi 0.3.9", + "io-lifetimes 0.7.5", + "windows-sys 0.36.1", ] [[package]] name = "io-lifetimes" -version = "0.5.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec58677acfea8a15352d42fc87d11d63596ade9239e0a7c9352914417515dbe6" +checksum = "59ce5ef949d49ee85593fc4d3f3f95ad61657076395cbbce23e2121fc5542074" dependencies = [ "libc", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -4610,25 +4602,25 @@ checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "is-terminal" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c89a757e762896bdbdfadf2860d0f8b0cea5e363d8cf3e7bdfeb63d1d976352" +checksum = "0d508111813f9af3afd2f92758f77e4ed2cc9371b642112c6a48d22eb73105c5" dependencies = [ "hermit-abi 0.2.6", - "io-lifetimes 0.5.3", - "rustix 0.33.7", - "winapi 0.3.9", + "io-lifetimes 0.7.5", + "rustix 0.35.16", + "windows-sys 0.36.1", ] [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ "hermit-abi 0.3.3", - "rustix 0.38.14", - "windows-sys 0.48.0", + "rustix 0.38.21", + "windows-sys 0.52.0", ] [[package]] @@ -4683,10 +4675,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] -name = "ittapi-rs" -version = "0.2.0" +name = "ittapi" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f712648a1ad72fbfb7adc2772c331e8d90f022f8cf30cbabefba2878dd3172b0" +checksum = "25a5c0b993601cad796222ea076565c5d9f337d35592f8622c753724f06d7271" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7b5e473765060536a660eed127f758cf1a810c73e49063264959c60d1727d9" dependencies = [ "cc", ] @@ -5144,9 +5147,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.0.42" +version = "0.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5284f00d480e1c39af34e72f8ad60b94f47007e3481cd3b731c1d67190ddc7b7" +checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" [[package]] name = "linux-raw-sys" @@ -5156,9 +5159,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.7" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lipsum" @@ -5428,11 +5431,11 @@ checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "memfd" -version = "0.4.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6627dc657574b49d6ad27105ed671822be56e0d2547d413bfbf3e8d8fa92e7a" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" dependencies = [ - "libc", + "rustix 0.38.21", ] [[package]] @@ -5628,12 +5631,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "more-asserts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" - [[package]] name = "multi_buffer" version = "0.1.0" @@ -6168,12 +6165,12 @@ dependencies = [ [[package]] name = "object" -version = "0.28.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "crc32fast", - "hashbrown 0.11.2", + "hashbrown 0.12.3", "indexmap 1.9.3", "memchr", ] @@ -7534,9 +7531,9 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.2.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a8d23b35d7177df3b9d31ed8a9ab4bf625c668be77a319d4f5efd4a5257701c" +checksum = "91b2eab54204ea0117fe9a060537e0b07a4e72f7c7d182361ecc346cab2240e5" dependencies = [ "fxhash", "log", @@ -7588,18 +7585,6 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" -[[package]] -name = "region" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" -dependencies = [ - "bitflags 1.3.2", - "libc", - "mach", - "winapi 0.3.9", -] - [[package]] name = "remove_dir_all" version = "0.5.3" @@ -8019,18 +8004,18 @@ dependencies = [ [[package]] name = "rustix" -version = "0.33.7" +version = "0.35.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938a344304321a9da4973b9ff4f9f8db9caf4597dfd9dda6a60b523340a0fff0" +checksum = "5363f616a5244fd47fc1dd0a0b24c28a5c0154f5010c16332a7ad6f78f2e8b62" dependencies = [ "bitflags 1.3.2", "errno 0.2.8", - "io-lifetimes 0.5.3", + "io-lifetimes 0.7.5", "itoa", "libc", - "linux-raw-sys 0.0.42", + "linux-raw-sys 0.0.46", "once_cell", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] @@ -8049,14 +8034,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.14" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ "bitflags 2.4.1", "errno 0.3.3", "libc", - "linux-raw-sys 0.4.7", + "linux-raw-sys 0.4.12", "windows-sys 0.48.0", ] @@ -9521,17 +9506,17 @@ dependencies = [ [[package]] name = "system-interface" -version = "0.20.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e09bb3fb4e02ec4b87e182ea9718fadbc0fa3e50085b40a9af9690572b67f9e" +checksum = "92adbaf536f5aff6986e1e62ba36cee72b1718c5153eee08b9e728ddde3f6029" dependencies = [ "atty", "bitflags 1.3.2", "cap-fs-ext", "cap-std", - "io-lifetimes 0.5.3", - "rustix 0.33.7", - "winapi 0.3.9", + "io-lifetimes 0.7.5", + "rustix 0.35.16", + "windows-sys 0.36.1", "winx", ] @@ -9571,9 +9556,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.11" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempdir" @@ -9594,7 +9579,7 @@ dependencies = [ "cfg-if 1.0.0", "fastrand 2.0.0", "redox_syscall 0.3.5", - "rustix 0.38.14", + "rustix 0.38.21", "windows-sys 0.48.0", ] @@ -11101,9 +11086,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi-cap-std-sync" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f086c5026d2fc3b268d138e65373f46422cc810f46d6e0776859c5027cb18728" +checksum = "c4b4953999c746173c263b81e9e5e3e335ff47face7187ba2a5ecc91c716e6f3" dependencies = [ "anyhow", "async-trait", @@ -11113,32 +11098,32 @@ dependencies = [ "cap-time-ext", "fs-set-times", "io-extras", - "io-lifetimes 0.5.3", - "is-terminal 0.1.0", - "lazy_static", - "rustix 0.33.7", + "io-lifetimes 0.7.5", + "is-terminal 0.3.0", + "once_cell", + "rustix 0.35.16", "system-interface", "tracing", "wasi-common", - "winapi 0.3.9", + "windows-sys 0.36.1", ] [[package]] name = "wasi-common" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8844fede1c3787cc08853872f47e8bd91f6c939c7406bc7a5dba496b260c08" +checksum = "d47faf4f76ebfdeb1f3346a949c6fbf2f2471afc68280b00c76d6c02221d80ad" dependencies = [ "anyhow", "bitflags 1.3.2", "cap-rand", "cap-std", "io-extras", - "rustix 0.33.7", + "rustix 0.35.16", "thiserror", "tracing", "wiggle", - "winapi 0.3.9", + "windows-sys 0.36.1", ] [[package]] @@ -11209,43 +11194,40 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" -version = "0.33.1" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39de0723a53d3c8f54bed106cfbc0d06b3e4d945c5c5022115a61e3b29183ae" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" dependencies = [ "leb128", ] [[package]] name = "wasmparser" -version = "0.85.0" +version = "0.92.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570460c58b21e9150d2df0eaaedbb7816c34bcec009ae0dcc976e40ba81463e7" +checksum = "7da34cec2a8c23db906cdf8b26e988d7a7f0d549eb5d51299129647af61a1b37" dependencies = [ "indexmap 1.9.3", ] [[package]] name = "wasmtime" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f50eadf868ab6a04b7b511460233377d0bfbb92e417b2f6a98b98fef2e098f5" +checksum = "743d37c265fa134a76de653c7e66be22590eaccd03da13cee99f3ac7a59cb826" dependencies = [ "anyhow", "async-trait", - "backtrace", "bincode", "cfg-if 1.0.0", "indexmap 1.9.3", - "lazy_static", "libc", "log", - "object 0.28.4", + "object 0.29.0", "once_cell", "paste", "psm", "rayon", - "region", "serde", "target-lexicon", "wasmparser", @@ -11256,14 +11238,23 @@ dependencies = [ "wasmtime-jit", "wasmtime-runtime", "wat", - "winapi 0.3.9", + "windows-sys 0.36.1", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de327cf46d5218315957138131ed904621e6f99018aa2da508c0dcf0c65f1bf2" +dependencies = [ + "cfg-if 1.0.0", ] [[package]] name = "wasmtime-cache" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1df23c642e1376892f3b72f311596976979cbf8b85469680cdd3a8a063d12a2" +checksum = "42bd53d27df1076100519b680b45d8209aed62b4bbaf0913732810cb216f7b2b" dependencies = [ "anyhow", "base64 0.13.1", @@ -11271,19 +11262,19 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.33.7", + "rustix 0.35.16", "serde", "sha2 0.9.9", "toml 0.5.11", - "winapi 0.3.9", + "windows-sys 0.36.1", "zstd", ] [[package]] name = "wasmtime-cranelift" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f264ff6b4df247d15584f2f53d009fbc90032cfdc2605b52b961bffc71b6eccd" +checksum = "017c3605ccce867b3ba7f71d95e5652acc22b9dc2971ad6a6f9df4a8d7af2648" dependencies = [ "anyhow", "cranelift-codegen", @@ -11293,8 +11284,7 @@ dependencies = [ "cranelift-wasm", "gimli 0.26.2", "log", - "more-asserts", - "object 0.28.4", + "object 0.29.0", "target-lexicon", "thiserror", "wasmparser", @@ -11303,17 +11293,16 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "839d2820e4b830f4b9e7aa08d4c0acabf4a5036105d639f6dfa1c6891c73bdc6" +checksum = "6aec5c1f81aab9bb35997113c171b6bb9093afc90e3757c55e0c08dc9ac612e4" dependencies = [ "anyhow", "cranelift-entity", "gimli 0.26.2", "indexmap 1.9.3", "log", - "more-asserts", - "object 0.28.4", + "object 0.29.0", "serde", "target-lexicon", "thiserror", @@ -11323,20 +11312,22 @@ dependencies = [ [[package]] name = "wasmtime-fiber" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3248be3c4911233535356025f6562193614a40155ee9094bb6a2b43f0dc82803" +checksum = "1075aa43857086ef89afbe87602fe2dae98ad212582e722b6d3d2676bb5ee141" dependencies = [ "cc", - "rustix 0.33.7", - "winapi 0.3.9", + "cfg-if 1.0.0", + "rustix 0.35.16", + "wasmtime-asm-macros", + "windows-sys 0.36.1", ] [[package]] name = "wasmtime-jit" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef0a0bcbfa18b946d890078ba0e1bc76bcc53eccfb40806c0020ec29dcd1bd49" +checksum = "08c683893dbba3986aa71582a5332b87157fb95d34098de2e5f077c7f078726d" dependencies = [ "addr2line 0.17.0", "anyhow", @@ -11344,40 +11335,38 @@ dependencies = [ "cfg-if 1.0.0", "cpp_demangle", "gimli 0.26.2", - "ittapi-rs", + "ittapi", "log", - "object 0.28.4", - "region", + "object 0.29.0", "rustc-demangle", - "rustix 0.33.7", + "rustix 0.35.16", "serde", "target-lexicon", "thiserror", "wasmtime-environ", "wasmtime-jit-debug", "wasmtime-runtime", - "winapi 0.3.9", + "windows-sys 0.36.1", ] [[package]] name = "wasmtime-jit-debug" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4779d976206c458edd643d1ac622b6c37e4a0800a8b1d25dfbf245ac2f2cac" +checksum = "b2f8f15a81292eec468c79a4f887a37a3d02eb0c610f34ddbec607d3e9022f18" dependencies = [ - "lazy_static", - "object 0.28.4", - "rustix 0.33.7", + "object 0.29.0", + "once_cell", + "rustix 0.35.16", ] [[package]] name = "wasmtime-runtime" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7eb6ffa169eb5dcd18ac9473c817358cd57bc62c244622210566d473397954a" +checksum = "09af6238c962e8220424c815a7b1a9a6d0ba0694f0ab0ae12a6cda1923935a0d" dependencies = [ "anyhow", - "backtrace", "cc", "cfg-if 1.0.0", "indexmap 1.9.3", @@ -11386,22 +11375,22 @@ dependencies = [ "mach", "memfd", "memoffset 0.6.5", - "more-asserts", + "paste", "rand 0.8.5", - "region", - "rustix 0.33.7", + "rustix 0.35.16", "thiserror", + "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-fiber", "wasmtime-jit-debug", - "winapi 0.3.9", + "windows-sys 0.36.1", ] [[package]] name = "wasmtime-types" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d932b0ac5336f7308d869703dd225610a6a3aeaa8e968c52b43eed96cefb1c2" +checksum = "5dc3dd9521815984b35d6362f79e6b9c72475027cd1c71c44eb8df8fbf33a9fb" dependencies = [ "cranelift-entity", "serde", @@ -11411,9 +11400,9 @@ dependencies = [ [[package]] name = "wasmtime-wasi" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b68b7d77fb6f2975a6fe6cc4d0015d6b0cebb65c39fce1dd4cc00880dbf7789c" +checksum = "a3bba5cc0a940cef3fbbfa7291c7e5fe0f7ec6fb2efa7bd1504032ed6202a1c0" dependencies = [ "anyhow", "wasi-cap-std-sync", @@ -11433,9 +11422,9 @@ dependencies = [ [[package]] name = "wast" -version = "65.0.1" +version = "69.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd8c1cbadf94a0b0d1071c581d3cfea1b7ed5192c79808dd15406e508dd0afb" +checksum = "c1ee37317321afde358e4d7593745942c48d6d17e0e6e943704de9bbee121e7a" dependencies = [ "leb128", "memchr", @@ -11445,11 +11434,11 @@ dependencies = [ [[package]] name = "wat" -version = "1.0.73" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3209e35eeaf483714f4c6be93f4a03e69aad5f304e3fa66afa7cb90fe1c8051f" +checksum = "aeb338ee8dee4d4cd05e6426683f21c5087dc7cfc8903e839ccf48d43332da3c" dependencies = [ - "wast 65.0.1", + "wast 69.0.1", ] [[package]] @@ -11556,7 +11545,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.14", + "rustix 0.38.21", ] [[package]] @@ -11567,9 +11556,9 @@ checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" [[package]] name = "wiggle" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67dadac11343d2aabc8a906a0db0aaf7cb5046ec3d6fffccdaf2847dccdef8d6" +checksum = "211ef4d238fd83bbe6f1bc57f3e2e20dc8b1f999188be252e7a535b696c6f84f" dependencies = [ "anyhow", "async-trait", @@ -11582,9 +11571,9 @@ dependencies = [ [[package]] name = "wiggle-generate" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63a1dccd6b3fbd9a27417f5d30ce9aa3ee9cf529aad453abbf88a49c5d605b79" +checksum = "63feec26b2fc3708c7a63316949ca75dd96988f03a17e4cb8d533dc62587ada4" dependencies = [ "anyhow", "heck 0.4.1", @@ -11597,9 +11586,9 @@ dependencies = [ [[package]] name = "wiggle-macro" -version = "0.38.3" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c368d57d9560c34deaa67e06b0953ccf65edb906c525e5a2c866c849b48ec2" +checksum = "494dc2646618c2b7fb0ec5e1d27dbac5ca31194c00a64698a4b5b35a83d80c21" dependencies = [ "proc-macro2", "quote", @@ -11668,6 +11657,34 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -11686,6 +11703,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -11716,6 +11742,21 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -11728,6 +11769,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -11740,6 +11793,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -11752,6 +11817,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -11764,6 +11841,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -11776,6 +11865,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -11788,6 +11883,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -11800,6 +11907,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.5.15" @@ -11821,13 +11934,13 @@ dependencies = [ [[package]] name = "winx" -version = "0.31.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d5973cb8cd94a77d03ad7e23bbe14889cb29805da1cec0e4aff75e21aebded" +checksum = "b7b01e010390eb263a4518c8cebf86cb67469d1511c00b749a47b64c39e8054d" dependencies = [ "bitflags 1.3.2", - "io-lifetimes 0.5.3", - "winapi 0.3.9", + "io-lifetimes 0.7.5", + "windows-sys 0.36.1", ] [[package]] diff --git a/Dockerfile b/Dockerfile index f3d0b601b9..ed6e4fac8e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax = docker/dockerfile:1.2 -FROM rust:1.73-bullseye as builder +FROM rust:1.75-bullseye as builder WORKDIR app COPY . . diff --git a/crates/collab2/src/tests.rs b/crates/collab2/src/tests.rs index a669f260db..53d42505bd 100644 --- a/crates/collab2/src/tests.rs +++ b/crates/collab2/src/tests.rs @@ -13,7 +13,6 @@ mod random_project_collaboration_tests; mod randomized_test_helpers; mod test_server; -pub use crate as collab2; pub use randomized_test_helpers::{ run_randomized_test, save_randomized_test_plan, RandomizedTest, TestError, UserTestPlan, }; diff --git a/crates/gpui/src/util.rs b/crates/gpui/src/util.rs index dc857b4c66..9e59c387e8 100644 --- a/crates/gpui/src/util.rs +++ b/crates/gpui/src/util.rs @@ -1,6 +1,5 @@ use smol::future::FutureExt; use std::{future::Future, time::Duration}; -pub use util::*; pub fn post_inc(value: &mut usize) -> usize { let prev = *value; diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 7feffbf3ed..c7126d7e8a 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -2,7 +2,7 @@ pub use crate::{ diagnostic_set::DiagnosticSet, highlight_map::{HighlightId, HighlightMap}, markdown::ParsedMarkdown, - proto, BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, PLAIN_TEXT, + proto, Grammar, Language, LanguageRegistry, }; use crate::{ diagnostic_set::{DiagnosticEntry, DiagnosticGroup}, diff --git a/crates/language2/src/buffer.rs b/crates/language2/src/buffer.rs index 26ee93adef..f56b24bb6a 100644 --- a/crates/language2/src/buffer.rs +++ b/crates/language2/src/buffer.rs @@ -2,7 +2,7 @@ pub use crate::{ diagnostic_set::DiagnosticSet, highlight_map::{HighlightId, HighlightMap}, markdown::ParsedMarkdown, - proto, BracketPair, Grammar, Language, LanguageConfig, LanguageRegistry, PLAIN_TEXT, + proto, Grammar, Language, LanguageRegistry, }; use crate::{ diagnostic_set::{DiagnosticEntry, DiagnosticGroup}, diff --git a/crates/plugin_runtime/Cargo.toml b/crates/plugin_runtime/Cargo.toml index 04337741c4..ddb66068ae 100644 --- a/crates/plugin_runtime/Cargo.toml +++ b/crates/plugin_runtime/Cargo.toml @@ -5,9 +5,9 @@ edition = "2021" publish = false [dependencies] -wasmtime = "0.38" -wasmtime-wasi = "0.38" -wasi-common = "0.38" +wasmtime = "2.0" +wasmtime-wasi = "2.0" +wasi-common = "2.0" anyhow.workspace = true serde.workspace = true serde_derive.workspace = true @@ -17,4 +17,4 @@ pollster = "0.2.5" smol.workspace = true [build-dependencies] -wasmtime = { version = "0.38", features = ["all-arch"] } +wasmtime = { version = "2.0", features = ["all-arch"] } diff --git a/crates/ui2/src/components/button/button_like.rs b/crates/ui2/src/components/button/button_like.rs index 44e18e850d..13d4f360f2 100644 --- a/crates/ui2/src/components/button/button_like.rs +++ b/crates/ui2/src/components/button/button_like.rs @@ -199,6 +199,7 @@ impl ButtonStyle { } } + #[allow(unused)] pub(crate) fn disabled(self, cx: &mut WindowContext) -> ButtonLikeStyles { match self { ButtonStyle::Filled => ButtonLikeStyles { diff --git a/crates/ui2/src/ui2.rs b/crates/ui2/src/ui2.rs index 5c79199100..b34e66dbda 100644 --- a/crates/ui2/src/ui2.rs +++ b/crates/ui2/src/ui2.rs @@ -28,7 +28,6 @@ pub use components::*; pub use disableable::*; pub use fixed::*; pub use prelude::*; -pub use selectable::*; + pub use styled_ext::*; pub use styles::*; -pub use visible_on_hover::*; diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 38d54d7aed..79d2d20a7a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.73" +channel = "1.75" components = [ "rustfmt" ] targets = [ "x86_64-apple-darwin", "aarch64-apple-darwin", "wasm32-wasi" ] From ce8cc50ae50d68ead523d8a1232a20d828c863b5 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 28 Dec 2023 23:45:30 +0200 Subject: [PATCH 342/644] Remove `async_trait` from the only trait that allows it now --- crates/fs/src/repository.rs | 2 -- crates/fs2/src/repository.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/crates/fs/src/repository.rs b/crates/fs/src/repository.rs index 4637a7f754..cf5c65105c 100644 --- a/crates/fs/src/repository.rs +++ b/crates/fs/src/repository.rs @@ -23,7 +23,6 @@ pub struct Branch { pub unix_timestamp: Option, } -#[async_trait::async_trait] pub trait GitRepository: Send { fn reload_index(&self); fn load_index_text(&self, relative_file_path: &Path) -> Option; @@ -248,7 +247,6 @@ impl FakeGitRepository { } } -#[async_trait::async_trait] impl GitRepository for FakeGitRepository { fn reload_index(&self) {} diff --git a/crates/fs2/src/repository.rs b/crates/fs2/src/repository.rs index 4637a7f754..cf5c65105c 100644 --- a/crates/fs2/src/repository.rs +++ b/crates/fs2/src/repository.rs @@ -23,7 +23,6 @@ pub struct Branch { pub unix_timestamp: Option, } -#[async_trait::async_trait] pub trait GitRepository: Send { fn reload_index(&self); fn load_index_text(&self, relative_file_path: &Path) -> Option; @@ -248,7 +247,6 @@ impl FakeGitRepository { } } -#[async_trait::async_trait] impl GitRepository for FakeGitRepository { fn reload_index(&self) {} From 21f0409e3bf2cb760fa045e9630ee2f936924f90 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 28 Dec 2023 10:23:12 -0700 Subject: [PATCH 343/644] Fix anti-aliasing artifacts in borders Previously, we changed borders to be drawn after content, so they are no longer part of the same quads as the background. In our change, we gave the background quad a transparent black border and the border quads transparent black backgrounds. However, this caused the other channels to blend toward that black color before becoming fully transparent, causing them to become darker. In this PR, I source the "placeholder" color by duplicating the values for the other channels and only adjust the alpha down to zero. --- crates/gpui2/src/style.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/gpui2/src/style.rs b/crates/gpui2/src/style.rs index c281818c0f..7f6af4fd21 100644 --- a/crates/gpui2/src/style.rs +++ b/crates/gpui2/src/style.rs @@ -386,12 +386,14 @@ impl Style { let background_color = self.background.as_ref().and_then(Fill::color); if background_color.map_or(false, |color| !color.is_transparent()) { cx.with_z_index(1, |cx| { + let mut border_color = background_color.unwrap_or_default(); + border_color.a = 0.; cx.paint_quad(quad( bounds, self.corner_radii.to_pixels(bounds.size, rem_size), background_color.unwrap_or_default(), Edges::default(), - Hsla::transparent_black(), + border_color, )); }); } @@ -426,10 +428,12 @@ impl Style { bottom_bounds.upper_right(), ); + let mut background = self.border_color.unwrap_or_default(); + background.a = 0.; let quad = quad( bounds, corner_radii, - Hsla::transparent_black(), + background, border_widths, self.border_color.unwrap_or_default(), ); From 1c13c3a24357c92db8879db05ed998c38f15e2e0 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 30 Dec 2023 01:10:48 +0200 Subject: [PATCH 344/644] Use `ghost_element_background` for avatar background color Also add a couple todo!()s on top of the comments --- crates/theme2/src/styles/colors.rs | 1 + crates/theme2/src/theme2.rs | 1 + crates/ui2/src/components/avatar.rs | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/theme2/src/styles/colors.rs b/crates/theme2/src/styles/colors.rs index ff7163ccdc..0b548c5a74 100644 --- a/crates/theme2/src/styles/colors.rs +++ b/crates/theme2/src/styles/colors.rs @@ -129,6 +129,7 @@ pub struct ThemeColors { /// The border color of the scrollbar track. pub scrollbar_track_border: Hsla, // /// The opacity of the scrollbar status marks, like diagnostic states and git status. + // todo!() // pub scrollbar_status_opacity: Hsla, // === diff --git a/crates/theme2/src/theme2.rs b/crates/theme2/src/theme2.rs index 7b60802e75..fc6253d010 100644 --- a/crates/theme2/src/theme2.rs +++ b/crates/theme2/src/theme2.rs @@ -73,6 +73,7 @@ impl ActiveTheme for AppContext { } } +// todo!() // impl<'a> ActiveTheme for WindowContext<'a> { // fn theme(&self) -> &Arc { // &ThemeSettings::get_global(self.app()).active_theme diff --git a/crates/ui2/src/components/avatar.rs b/crates/ui2/src/components/avatar.rs index 0ab6ce2d85..793872cd8a 100644 --- a/crates/ui2/src/components/avatar.rs +++ b/crates/ui2/src/components/avatar.rs @@ -37,8 +37,7 @@ impl RenderOnce for Avatar { .child( self.image .size(size) - // todo!(Pull the avatar fallback background from the theme.) - .bg(gpui::red()), + .bg(cx.theme().colors().ghost_element_background), ) .children(self.is_available.map(|is_free| { // HACK: non-integer sizes result in oval indicators. From 83923fd6d574e210d7afcd795528974d45e8f1b2 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sun, 31 Dec 2023 08:33:40 -0700 Subject: [PATCH 345/644] Clean up Element API and start on docs --- .../src/activity_indicator.rs | 4 +- crates/assistant2/src/assistant_panel.rs | 12 +- .../auto_update2/src/update_notification.rs | 4 +- crates/breadcrumbs2/src/breadcrumbs.rs | 4 +- crates/collab_ui2/src/channel_view.rs | 4 +- crates/collab_ui2/src/chat_panel.rs | 4 +- .../src/chat_panel/message_editor.rs | 4 +- crates/collab_ui2/src/collab_panel.rs | 8 +- .../src/collab_panel/channel_modal.rs | 4 +- .../src/collab_panel/contact_finder.rs | 4 +- crates/collab_ui2/src/collab_titlebar_item.rs | 4 +- crates/collab_ui2/src/face_pile.rs | 4 +- crates/collab_ui2/src/notification_panel.rs | 6 +- .../incoming_call_notification.rs | 4 +- .../project_shared_notification.rs | 4 +- .../command_palette2/src/command_palette.rs | 4 +- crates/copilot2/src/sign_in.rs | 4 +- crates/copilot_button2/src/copilot_button.rs | 4 +- crates/diagnostics2/src/diagnostics.rs | 4 +- crates/diagnostics2/src/items.rs | 4 +- crates/diagnostics2/src/toolbar_controls.rs | 4 +- crates/editor2/src/editor.rs | 4 +- crates/editor2/src/element.rs | 2 +- crates/editor2/src/items.rs | 4 +- .../feedback2/src/deploy_feedback_button.rs | 4 +- crates/feedback2/src/feedback_modal.rs | 4 +- crates/file_finder2/src/file_finder.rs | 4 +- crates/go_to_line2/src/go_to_line.rs | 4 +- crates/gpui2/src/app/test_context.rs | 4 +- crates/gpui2/src/element.rs | 141 +++++++++++------- crates/gpui2/src/elements/canvas.rs | 2 +- crates/gpui2/src/elements/div.rs | 10 +- crates/gpui2/src/elements/img.rs | 2 +- crates/gpui2/src/elements/list.rs | 2 +- crates/gpui2/src/elements/overlay.rs | 2 +- crates/gpui2/src/elements/svg.rs | 2 +- crates/gpui2/src/elements/text.rs | 12 +- crates/gpui2/src/elements/uniform_list.rs | 2 +- crates/gpui2/src/interactive.rs | 8 +- crates/gpui2/src/view.rs | 14 +- crates/gpui2_macros/src/derive_render.rs | 4 +- .../src/active_buffer_language.rs | 2 +- .../src/language_selector.rs | 4 +- crates/language_tools2/src/lsp_log.rs | 8 +- .../language_tools2/src/syntax_tree_view.rs | 6 +- crates/outline2/src/outline.rs | 4 +- crates/picker2/src/picker2.rs | 4 +- crates/project_panel2/src/project_panel.rs | 8 +- .../quick_action_bar2/src/quick_action_bar.rs | 8 +- .../src/highlighted_workspace_location.rs | 4 +- .../recent_projects2/src/recent_projects.rs | 4 +- crates/search2/src/buffer_search.rs | 4 +- crates/search2/src/project_search.rs | 8 +- crates/story/src/story.rs | 12 +- .../src/stories/auto_height_editor.rs | 4 +- crates/storybook2/src/stories/cursor.rs | 4 +- crates/storybook2/src/stories/focus.rs | 4 +- crates/storybook2/src/stories/kitchen_sink.rs | 4 +- .../storybook2/src/stories/overflow_scroll.rs | 4 +- crates/storybook2/src/stories/picker.rs | 4 +- crates/storybook2/src/stories/scroll.rs | 4 +- crates/storybook2/src/stories/text.rs | 4 +- .../storybook2/src/stories/viewport_units.rs | 4 +- crates/storybook2/src/stories/z_index.rs | 8 +- crates/storybook2/src/storybook2.rs | 4 +- crates/terminal_view2/src/terminal_element.rs | 2 +- crates/terminal_view2/src/terminal_panel.rs | 4 +- crates/terminal_view2/src/terminal_view.rs | 4 +- crates/theme_selector2/src/theme_selector.rs | 4 +- crates/ui2/src/components/avatar.rs | 4 +- crates/ui2/src/components/button/button.rs | 4 +- .../ui2/src/components/button/button_icon.rs | 4 +- .../ui2/src/components/button/button_like.rs | 4 +- .../ui2/src/components/button/icon_button.rs | 4 +- .../src/components/button/toggle_button.rs | 4 +- crates/ui2/src/components/checkbox.rs | 4 +- crates/ui2/src/components/context_menu.rs | 4 +- crates/ui2/src/components/disclosure.rs | 4 +- crates/ui2/src/components/divider.rs | 4 +- crates/ui2/src/components/icon.rs | 4 +- crates/ui2/src/components/indicator.rs | 4 +- crates/ui2/src/components/keybinding.rs | 12 +- .../src/components/label/highlighted_label.rs | 4 +- crates/ui2/src/components/label/label.rs | 4 +- crates/ui2/src/components/label/label_like.rs | 4 +- crates/ui2/src/components/list/list.rs | 4 +- crates/ui2/src/components/list/list_header.rs | 4 +- crates/ui2/src/components/list/list_item.rs | 4 +- .../ui2/src/components/list/list_separator.rs | 4 +- .../src/components/list/list_sub_header.rs | 4 +- crates/ui2/src/components/popover.rs | 4 +- crates/ui2/src/components/popover_menu.rs | 2 +- crates/ui2/src/components/right_click_menu.rs | 2 +- crates/ui2/src/components/stories/avatar.rs | 4 +- crates/ui2/src/components/stories/button.rs | 4 +- crates/ui2/src/components/stories/checkbox.rs | 4 +- .../src/components/stories/context_menu.rs | 4 +- .../ui2/src/components/stories/disclosure.rs | 4 +- crates/ui2/src/components/stories/icon.rs | 4 +- .../ui2/src/components/stories/icon_button.rs | 4 +- .../ui2/src/components/stories/keybinding.rs | 4 +- crates/ui2/src/components/stories/label.rs | 4 +- crates/ui2/src/components/stories/list.rs | 4 +- .../ui2/src/components/stories/list_header.rs | 4 +- .../ui2/src/components/stories/list_item.rs | 4 +- crates/ui2/src/components/stories/tab.rs | 4 +- crates/ui2/src/components/stories/tab_bar.rs | 4 +- .../src/components/stories/toggle_button.rs | 4 +- crates/ui2/src/components/tab.rs | 4 +- crates/ui2/src/components/tab_bar.rs | 4 +- crates/ui2/src/components/tooltip.rs | 4 +- crates/vcs_menu2/src/lib.rs | 4 +- crates/vim2/src/mode_indicator.rs | 2 +- crates/welcome2/src/base_keymap_picker.rs | 4 +- crates/welcome2/src/welcome.rs | 4 +- crates/workspace2/src/dock.rs | 12 +- crates/workspace2/src/item.rs | 4 +- crates/workspace2/src/modal_layer.rs | 4 +- crates/workspace2/src/notifications.rs | 4 +- crates/workspace2/src/pane.rs | 8 +- crates/workspace2/src/pane_group.rs | 2 +- crates/workspace2/src/shared_screen.rs | 4 +- crates/workspace2/src/status_bar.rs | 4 +- crates/workspace2/src/toolbar.rs | 4 +- crates/workspace2/src/workspace2.rs | 6 +- 125 files changed, 370 insertions(+), 335 deletions(-) diff --git a/crates/activity_indicator2/src/activity_indicator.rs b/crates/activity_indicator2/src/activity_indicator.rs index 2b7846cd8d..1332aa8018 100644 --- a/crates/activity_indicator2/src/activity_indicator.rs +++ b/crates/activity_indicator2/src/activity_indicator.rs @@ -304,9 +304,9 @@ impl ActivityIndicator { impl EventEmitter for ActivityIndicator {} impl Render for ActivityIndicator { - type Element = Stateful
; + type Output = Stateful
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let content = self.content_to_render(cx); let mut result = h_stack() diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs index bcfb5f0fbc..b04d99842c 100644 --- a/crates/assistant2/src/assistant_panel.rs +++ b/crates/assistant2/src/assistant_panel.rs @@ -1101,9 +1101,9 @@ fn build_api_key_editor(cx: &mut ViewContext) -> View { } impl Render for AssistantPanel { - type Element = Focusable
; + type Output = Focusable
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { if let Some(api_key_editor) = self.api_key_editor.clone() { v_stack() .on_action(cx.listener(AssistantPanel::save_credentials)) @@ -2513,9 +2513,9 @@ impl ConversationEditor { impl EventEmitter for ConversationEditor {} impl Render for ConversationEditor { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { div() .key_context("ConversationEditor") .capture_action(cx.listener(ConversationEditor::cancel_last_assist)) @@ -2618,9 +2618,9 @@ struct InlineAssistant { impl EventEmitter for InlineAssistant {} impl Render for InlineAssistant { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let measurements = self.measurements.get(); h_stack() .w_full() diff --git a/crates/auto_update2/src/update_notification.rs b/crates/auto_update2/src/update_notification.rs index 8bb08912b0..7bbbcab0fe 100644 --- a/crates/auto_update2/src/update_notification.rs +++ b/crates/auto_update2/src/update_notification.rs @@ -13,9 +13,9 @@ pub struct UpdateNotification { impl EventEmitter for UpdateNotification {} impl Render for UpdateNotification { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Output { let app_name = cx.global::().display_name(); v_stack() diff --git a/crates/breadcrumbs2/src/breadcrumbs.rs b/crates/breadcrumbs2/src/breadcrumbs.rs index da7182ec2c..77ee22493f 100644 --- a/crates/breadcrumbs2/src/breadcrumbs.rs +++ b/crates/breadcrumbs2/src/breadcrumbs.rs @@ -30,9 +30,9 @@ impl Breadcrumbs { impl EventEmitter for Breadcrumbs {} impl Render for Breadcrumbs { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let element = h_stack().text_ui(); let Some(active_item) = self.active_item.as_ref() else { return element; diff --git a/crates/collab_ui2/src/channel_view.rs b/crates/collab_ui2/src/channel_view.rs index 0fbe625fe0..9ba8d506c9 100644 --- a/crates/collab_ui2/src/channel_view.rs +++ b/crates/collab_ui2/src/channel_view.rs @@ -222,9 +222,9 @@ impl ChannelView { impl EventEmitter for ChannelView {} impl Render for ChannelView { - type Element = AnyView; + type Output = AnyView; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { self.editor.clone().into() } } diff --git a/crates/collab_ui2/src/chat_panel.rs b/crates/collab_ui2/src/chat_panel.rs index 03e9cfbb4a..17046587a1 100644 --- a/crates/collab_ui2/src/chat_panel.rs +++ b/crates/collab_ui2/src/chat_panel.rs @@ -549,9 +549,9 @@ impl ChatPanel { impl EventEmitter for ChatPanel {} impl Render for ChatPanel { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { div() .full() .child(if self.client.user_id().is_some() { diff --git a/crates/collab_ui2/src/chat_panel/message_editor.rs b/crates/collab_ui2/src/chat_panel/message_editor.rs index 0b9d0be0b4..908f57f2d6 100644 --- a/crates/collab_ui2/src/chat_panel/message_editor.rs +++ b/crates/collab_ui2/src/chat_panel/message_editor.rs @@ -196,9 +196,9 @@ impl MessageEditor { } impl Render for MessageEditor { - type Element = AnyView; + type Output = AnyView; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { self.editor.to_any() } } diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 8fd90af45b..24057f096d 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -2263,9 +2263,9 @@ fn render_tree_branch(is_last: bool, cx: &mut WindowContext) -> impl IntoElement } impl Render for CollabPanel { - type Element = Focusable
; + type Output = Focusable
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { v_stack() .key_context("CollabPanel") .on_action(cx.listener(CollabPanel::cancel)) @@ -2453,9 +2453,9 @@ struct DraggedChannelView { } impl Render for DraggedChannelView { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone(); h_stack() .font(ui_font) diff --git a/crates/collab_ui2/src/collab_panel/channel_modal.rs b/crates/collab_ui2/src/collab_panel/channel_modal.rs index d68aa32e9b..47d142f01e 100644 --- a/crates/collab_ui2/src/collab_panel/channel_modal.rs +++ b/crates/collab_ui2/src/collab_panel/channel_modal.rs @@ -142,9 +142,9 @@ impl FocusableView for ChannelModal { } impl Render for ChannelModal { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let channel_store = self.channel_store.read(cx); let Some(channel) = channel_store.channel_for_id(self.channel_id) else { return div(); diff --git a/crates/collab_ui2/src/collab_panel/contact_finder.rs b/crates/collab_ui2/src/collab_panel/contact_finder.rs index a38d22c096..8368e176b3 100644 --- a/crates/collab_ui2/src/collab_panel/contact_finder.rs +++ b/crates/collab_ui2/src/collab_panel/contact_finder.rs @@ -35,7 +35,7 @@ impl ContactFinder { } impl Render for ContactFinder { - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { v_stack() .elevation_3(cx) .child( @@ -52,7 +52,7 @@ impl Render for ContactFinder { .w(rems(34.)) } - type Element = Div; + type Output = Div; } pub struct ContactFinderDelegate { diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index 6255e2b833..2ab2e3f3e2 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -56,9 +56,9 @@ pub struct CollabTitlebarItem { } impl Render for CollabTitlebarItem { - type Element = Stateful
; + type Output = Stateful
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let room = ActiveCall::global(cx).read(cx).room().cloned(); let current_user = self.user_store.read(cx).current_user(); let client = self.client.clone(); diff --git a/crates/collab_ui2/src/face_pile.rs b/crates/collab_ui2/src/face_pile.rs index fd675127e4..1c0d8100d8 100644 --- a/crates/collab_ui2/src/face_pile.rs +++ b/crates/collab_ui2/src/face_pile.rs @@ -9,9 +9,9 @@ pub struct FacePile { } impl RenderOnce for FacePile { - type Rendered = Div; + type Output = Div; - fn render(self, _: &mut WindowContext) -> Self::Rendered { + fn render(self, _: &mut WindowContext) -> Self::Output { let player_count = self.faces.len(); let player_list = self.faces.into_iter().enumerate().map(|(ix, player)| { let isnt_last = ix < player_count - 1; diff --git a/crates/collab_ui2/src/notification_panel.rs b/crates/collab_ui2/src/notification_panel.rs index 4b2f38de9b..11e88d8b59 100644 --- a/crates/collab_ui2/src/notification_panel.rs +++ b/crates/collab_ui2/src/notification_panel.rs @@ -540,7 +540,7 @@ impl NotificationPanel { } impl Render for NotificationPanel { - type Element = Div; + type Output = Div; fn render(&mut self, cx: &mut ViewContext) -> Div { v_stack() @@ -706,9 +706,9 @@ impl NotificationToast { } impl Render for NotificationToast { - type Element = Stateful
; + type Output = Stateful
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let user = self.actor.clone(); h_stack() diff --git a/crates/collab_ui2/src/notifications/incoming_call_notification.rs b/crates/collab_ui2/src/notifications/incoming_call_notification.rs index d5bdf4ff44..dea6fc9359 100644 --- a/crates/collab_ui2/src/notifications/incoming_call_notification.rs +++ b/crates/collab_ui2/src/notifications/incoming_call_notification.rs @@ -117,9 +117,9 @@ impl IncomingCallNotification { } impl Render for IncomingCallNotification { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { // TODO: Is there a better place for us to initialize the font? let (ui_font, ui_font_size) = { let theme_settings = ThemeSettings::get_global(cx); diff --git a/crates/collab_ui2/src/notifications/project_shared_notification.rs b/crates/collab_ui2/src/notifications/project_shared_notification.rs index 707e961423..fc7cc2b2d0 100644 --- a/crates/collab_ui2/src/notifications/project_shared_notification.rs +++ b/crates/collab_ui2/src/notifications/project_shared_notification.rs @@ -120,9 +120,9 @@ impl ProjectSharedNotification { } impl Render for ProjectSharedNotification { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { // TODO: Is there a better place for us to initialize the font? let (ui_font, ui_font_size) = { let theme_settings = ThemeSettings::get_global(cx); diff --git a/crates/command_palette2/src/command_palette.rs b/crates/command_palette2/src/command_palette.rs index 05891bc0f1..ae23c0b966 100644 --- a/crates/command_palette2/src/command_palette.rs +++ b/crates/command_palette2/src/command_palette.rs @@ -83,9 +83,9 @@ impl FocusableView for CommandPalette { } impl Render for CommandPalette { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { v_stack().w(rems(34.)).child(self.picker.clone()) } } diff --git a/crates/copilot2/src/sign_in.rs b/crates/copilot2/src/sign_in.rs index 4fa93ffcf8..22e10fbdc3 100644 --- a/crates/copilot2/src/sign_in.rs +++ b/crates/copilot2/src/sign_in.rs @@ -181,9 +181,9 @@ impl CopilotCodeVerification { } impl Render for CopilotCodeVerification { - type Element = Stateful
; + type Output = Stateful
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let prompt = match &self.status { Status::SigningIn { prompt: Some(prompt), diff --git a/crates/copilot_button2/src/copilot_button.rs b/crates/copilot_button2/src/copilot_button.rs index 2c8427732e..0c62a3c489 100644 --- a/crates/copilot_button2/src/copilot_button.rs +++ b/crates/copilot_button2/src/copilot_button.rs @@ -34,9 +34,9 @@ pub struct CopilotButton { } impl Render for CopilotButton { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let all_language_settings = all_language_settings(None, cx); if !all_language_settings.copilot.feature_enabled { return div(); diff --git a/crates/diagnostics2/src/diagnostics.rs b/crates/diagnostics2/src/diagnostics.rs index 8103231ede..dfecdfed51 100644 --- a/crates/diagnostics2/src/diagnostics.rs +++ b/crates/diagnostics2/src/diagnostics.rs @@ -91,9 +91,9 @@ struct DiagnosticGroupState { impl EventEmitter for ProjectDiagnosticsEditor {} impl Render for ProjectDiagnosticsEditor { - type Element = Focusable
; + type Output = Focusable
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let child = if self.path_states.is_empty() { div() .bg(cx.theme().colors().editor_background) diff --git a/crates/diagnostics2/src/items.rs b/crates/diagnostics2/src/items.rs index cc598ba90c..5901b6803d 100644 --- a/crates/diagnostics2/src/items.rs +++ b/crates/diagnostics2/src/items.rs @@ -21,9 +21,9 @@ pub struct DiagnosticIndicator { } impl Render for DiagnosticIndicator { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let diagnostic_indicator = match (self.summary.error_count, self.summary.warning_count) { (0, 0) => h_stack().child( IconElement::new(Icon::Check) diff --git a/crates/diagnostics2/src/toolbar_controls.rs b/crates/diagnostics2/src/toolbar_controls.rs index 1a604b76c8..1446029194 100644 --- a/crates/diagnostics2/src/toolbar_controls.rs +++ b/crates/diagnostics2/src/toolbar_controls.rs @@ -9,9 +9,9 @@ pub struct ToolbarControls { } impl Render for ToolbarControls { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let include_warnings = self .editor .as_ref() diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index c9fb2fa181..817744a47f 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -9291,9 +9291,9 @@ impl FocusableView for Editor { } impl Render for Editor { - type Element = EditorElement; + type Output = EditorElement; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let settings = ThemeSettings::get_global(cx); let text_style = match self.mode { EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle { diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index eb9f4106ea..da7428a8e0 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -2757,7 +2757,7 @@ enum Invisible { impl Element for EditorElement { type State = (); - fn layout( + fn request_layout( &mut self, _element_state: Option, cx: &mut gpui::WindowContext, diff --git a/crates/editor2/src/items.rs b/crates/editor2/src/items.rs index b10b891d0d..349b3140fe 100644 --- a/crates/editor2/src/items.rs +++ b/crates/editor2/src/items.rs @@ -1193,9 +1193,9 @@ impl CursorPosition { } impl Render for CursorPosition { - type Element = Div; + type Output = Div; - fn render(&mut self, _: &mut ViewContext) -> Self::Element { + fn render(&mut self, _: &mut ViewContext) -> Self::Output { div().when_some(self.position, |el, position| { let mut text = format!( "{}{FILE_ROW_COLUMN_DELIMITER}{}", diff --git a/crates/feedback2/src/deploy_feedback_button.rs b/crates/feedback2/src/deploy_feedback_button.rs index 926a5d791e..9a112c25db 100644 --- a/crates/feedback2/src/deploy_feedback_button.rs +++ b/crates/feedback2/src/deploy_feedback_button.rs @@ -17,9 +17,9 @@ impl DeployFeedbackButton { } impl Render for DeployFeedbackButton { - type Element = AnyElement; + type Output = AnyElement; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let is_open = self .workspace .upgrade() diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index d22d5d908b..94e051f247 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -396,9 +396,9 @@ impl FeedbackModal { } impl Render for FeedbackModal { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { self.update_submission_state(cx); let submit_button_text = if self.awaiting_submission() { diff --git a/crates/file_finder2/src/file_finder.rs b/crates/file_finder2/src/file_finder.rs index 69deba6d2c..4676d91f72 100644 --- a/crates/file_finder2/src/file_finder.rs +++ b/crates/file_finder2/src/file_finder.rs @@ -118,9 +118,9 @@ impl FocusableView for FileFinder { } } impl Render for FileFinder { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { v_stack().w(rems(34.)).child(self.picker.clone()) } } diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index 02fcd47716..97118dad66 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -153,9 +153,9 @@ impl GoToLine { } impl Render for GoToLine { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { div() .elevation_2(cx) .key_context("GoToLine") diff --git a/crates/gpui2/src/app/test_context.rs b/crates/gpui2/src/app/test_context.rs index c77ec29bdf..3aa09d2189 100644 --- a/crates/gpui2/src/app/test_context.rs +++ b/crates/gpui2/src/app/test_context.rs @@ -733,9 +733,9 @@ impl AnyWindowHandle { pub struct EmptyView {} impl Render for EmptyView { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut crate::ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut crate::ViewContext) -> Self::Output { div() } } diff --git a/crates/gpui2/src/element.rs b/crates/gpui2/src/element.rs index 4201123a10..442b5b3ac5 100644 --- a/crates/gpui2/src/element.rs +++ b/crates/gpui2/src/element.rs @@ -6,23 +6,61 @@ use derive_more::{Deref, DerefMut}; pub(crate) use smallvec::SmallVec; use std::{any::Any, fmt::Debug}; -pub trait Render: 'static + Sized { - type Element: Element + 'static; +/// Elements describe the contents of a window for a given frame. +/// Like HTML elements, elements form a tree and participate in layout. +/// In GPUI, elements are single-use objects that do not outlive a single frame. +/// Elements are associated with state. +/// If the element has an identifier, the element's state persists across frames in which the element appears. +/// If the element is anonymous, the state only persists across from layout request to paint in is referred to as "frame state". +/// A potential improvement would be to separate this temporary frame state from persistent element state at the type level, and request element state from the context with an id. /cc @as-cii\ +/// To render the contents of a window, we first walk over the tree of elements recursively via [request_layout], giving each an opportunity to register with the layout engine. +/// Then we compute the requested layout and use the computed bounds to paint the element tree recursively with [paint]. +/// You can implement this trait yourself for performance or other special situations, but you'll typically compose existing elements such as `Div`, `Img`, etc. +pub trait Element: 'static + IntoElement { + /// State that is carried from [request_layout] to [paint] for anonymous elements, and between frames for elements that have an id. + type State: 'static; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element; + /// Recursively register this element and all its descendants with the layout engine. + /// If this element has an id, you'll receive the [State] from the previous frame if an element with this id existed in that frame. + /// Return the [LayoutId] you requested from the engine and whatever state you want to carry over to [paint], and also the next frame if this element has an id. + fn request_layout( + &mut self, + state: Option, + cx: &mut WindowContext, + ) -> (LayoutId, Self::State); + + /// Recursively paint this element by populating the current frame's [Scene] with geometric primitives such as quads, sprites, paths, etc. + /// Receives the state from layout, and potentially the previous frame if this element has an id. + fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext); + + /// Convert into a dynamically-typed [AnyElement]. + /// Before an element can be painted, it must be converted into an [AnyElement]. + /// It's also useful in situations where you need to own an element, but don't care about its specific type. + fn into_any(self) -> AnyElement { + AnyElement::new(self) + } } +/// Implemented by any type that can be converted into an element. pub trait IntoElement: Sized { - type Element: Element + 'static; + /// The specific type of element into which the implementing type is converted. + type Element: Element; + /// The [ElementId] of self once converted into an [Element]. + /// If present, the resulting element's state will be carried across frames. fn element_id(&self) -> Option; + /// Convert self into a type that implements [Element]. fn into_element(self) -> Self::Element; + /// Convert self into a dynamically-typed [AnyElement]. fn into_any_element(self) -> AnyElement { self.into_element().into_any() } + /// Convert into an element, then draw in the current window at the given origin. + /// The provided available space is provided to the layout engine to determine the size of the root element. + /// Once the element is drawn, its associated element staet is yielded to the given callback. fn draw_and_update_state( self, origin: Point, @@ -54,6 +92,7 @@ pub trait IntoElement: Sized { } } + /// Convert self to another type by calling the given closure. Useful in rendering code. fn map(self, f: impl FnOnce(Self) -> U) -> U where Self: Sized, @@ -62,6 +101,7 @@ pub trait IntoElement: Sized { f(self) } + /// Conditionally chain onto self with the given closure. Useful in rendering code. fn when(self, condition: bool, then: impl FnOnce(Self) -> Self) -> Self where Self: Sized, @@ -69,6 +109,8 @@ pub trait IntoElement: Sized { self.map(|this| if condition { then(this) } else { this }) } + /// Conditionally chain onto self with the given closure if the given option is Some. + /// The contents of the option are provided to the closure. fn when_some(self, option: Option, then: impl FnOnce(Self, T) -> Self) -> Self where Self: Sized, @@ -83,35 +125,46 @@ pub trait IntoElement: Sized { } } -pub trait Element: 'static + IntoElement { - type State: 'static; +pub trait Render: 'static + Sized { + type Output: IntoElement; - fn layout( - &mut self, - state: Option, - cx: &mut WindowContext, - ) -> (LayoutId, Self::State); - - fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext); - - fn into_any(self) -> AnyElement { - AnyElement::new(self) - } + fn render(&mut self, cx: &mut ViewContext) -> Self::Output; } pub trait RenderOnce: 'static { - type Rendered: IntoElement; + type Output: IntoElement; - fn render(self, cx: &mut WindowContext) -> Self::Rendered; + fn render(self, cx: &mut WindowContext) -> Self::Output; +} + +pub trait ParentElement { + fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; + + fn child(mut self, child: impl IntoElement) -> Self + where + Self: Sized, + { + self.children_mut().push(child.into_element().into_any()); + self + } + + fn children(mut self, children: impl IntoIterator) -> Self + where + Self: Sized, + { + self.children_mut() + .extend(children.into_iter().map(|child| child.into_any_element())); + self + } } pub struct Component { component: Option, } -pub struct CompositeElementState { - rendered_element: Option<::Element>, - rendered_element_state: Option<<::Element as Element>::State>, +pub struct ComponentState { + rendered_element: Option<::Element>, + rendered_element_state: Option<<::Element as Element>::State>, } impl Component { @@ -123,9 +176,9 @@ impl Component { } impl Element for Component { - type State = CompositeElementState; + type State = ComponentState; - fn layout( + fn request_layout( &mut self, state: Option, cx: &mut WindowContext, @@ -133,16 +186,16 @@ impl Element for Component { let mut element = self.component.take().unwrap().render(cx).into_element(); if let Some(element_id) = element.element_id() { let layout_id = - cx.with_element_state(element_id, |state, cx| element.layout(state, cx)); - let state = CompositeElementState { + cx.with_element_state(element_id, |state, cx| element.request_layout(state, cx)); + let state = ComponentState { rendered_element: Some(element), rendered_element_state: None, }; (layout_id, state) } else { let (layout_id, state) = - element.layout(state.and_then(|s| s.rendered_element_state), cx); - let state = CompositeElementState { + element.request_layout(state.and_then(|s| s.rendered_element_state), cx); + let state = ComponentState { rendered_element: Some(element), rendered_element_state: Some(state), }; @@ -183,27 +236,6 @@ impl IntoElement for Component { #[derive(Deref, DerefMut, Default, Clone, Debug, Eq, PartialEq, Hash)] pub struct GlobalElementId(SmallVec<[ElementId; 32]>); -pub trait ParentElement { - fn children_mut(&mut self) -> &mut SmallVec<[AnyElement; 2]>; - - fn child(mut self, child: impl IntoElement) -> Self - where - Self: Sized, - { - self.children_mut().push(child.into_element().into_any()); - self - } - - fn children(mut self, children: impl IntoIterator) -> Self - where - Self: Sized, - { - self.children_mut() - .extend(children.into_iter().map(|child| child.into_any_element())); - self - } -} - trait ElementObject { fn element_id(&self) -> Option; @@ -262,11 +294,14 @@ impl DrawableElement { let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id() { let layout_id = cx.with_element_state(id, |element_state, cx| { - self.element.as_mut().unwrap().layout(element_state, cx) + self.element + .as_mut() + .unwrap() + .request_layout(element_state, cx) }); (layout_id, None) } else { - let (layout_id, frame_state) = self.element.as_mut().unwrap().layout(None, cx); + let (layout_id, frame_state) = self.element.as_mut().unwrap().request_layout(None, cx); (layout_id, Some(frame_state)) }; @@ -454,7 +489,7 @@ impl AnyElement { impl Element for AnyElement { type State = (); - fn layout( + fn request_layout( &mut self, _: Option, cx: &mut WindowContext, @@ -502,7 +537,7 @@ impl IntoElement for () { impl Element for () { type State = (); - fn layout( + fn request_layout( &mut self, _state: Option, cx: &mut WindowContext, diff --git a/crates/gpui2/src/elements/canvas.rs b/crates/gpui2/src/elements/canvas.rs index d04c65811f..767417ae40 100644 --- a/crates/gpui2/src/elements/canvas.rs +++ b/crates/gpui2/src/elements/canvas.rs @@ -29,7 +29,7 @@ impl IntoElement for Canvas { impl Element for Canvas { type State = Style; - fn layout( + fn request_layout( &mut self, _: Option, cx: &mut WindowContext, diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index fc129b4f1d..512cc56bb2 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -768,7 +768,7 @@ impl ParentElement for Div { impl Element for Div { type State = DivState; - fn layout( + fn request_layout( &mut self, element_state: Option, cx: &mut WindowContext, @@ -1818,12 +1818,12 @@ where { type State = E::State; - fn layout( + fn request_layout( &mut self, state: Option, cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - self.element.layout(state, cx) + self.element.request_layout(state, cx) } fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { @@ -1892,12 +1892,12 @@ where { type State = E::State; - fn layout( + fn request_layout( &mut self, state: Option, cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - self.element.layout(state, cx) + self.element.request_layout(state, cx) } fn paint(&mut self, bounds: Bounds, state: &mut Self::State, cx: &mut WindowContext) { diff --git a/crates/gpui2/src/elements/img.rs b/crates/gpui2/src/elements/img.rs index ab7b8d9140..650b5b666b 100644 --- a/crates/gpui2/src/elements/img.rs +++ b/crates/gpui2/src/elements/img.rs @@ -71,7 +71,7 @@ impl Img { impl Element for Img { type State = InteractiveElementState; - fn layout( + fn request_layout( &mut self, element_state: Option, cx: &mut WindowContext, diff --git a/crates/gpui2/src/elements/list.rs b/crates/gpui2/src/elements/list.rs index a0467aaaa3..364b610eee 100644 --- a/crates/gpui2/src/elements/list.rs +++ b/crates/gpui2/src/elements/list.rs @@ -302,7 +302,7 @@ pub struct ListOffset { impl Element for List { type State = (); - fn layout( + fn request_layout( &mut self, _state: Option, cx: &mut crate::WindowContext, diff --git a/crates/gpui2/src/elements/overlay.rs b/crates/gpui2/src/elements/overlay.rs index 5b72019f17..b5d8b53c7f 100644 --- a/crates/gpui2/src/elements/overlay.rs +++ b/crates/gpui2/src/elements/overlay.rs @@ -60,7 +60,7 @@ impl ParentElement for Overlay { impl Element for Overlay { type State = OverlayState; - fn layout( + fn request_layout( &mut self, _: Option, cx: &mut WindowContext, diff --git a/crates/gpui2/src/elements/svg.rs b/crates/gpui2/src/elements/svg.rs index 9ca9baf470..5ea7f9bd78 100644 --- a/crates/gpui2/src/elements/svg.rs +++ b/crates/gpui2/src/elements/svg.rs @@ -26,7 +26,7 @@ impl Svg { impl Element for Svg { type State = InteractiveElementState; - fn layout( + fn request_layout( &mut self, element_state: Option, cx: &mut WindowContext, diff --git a/crates/gpui2/src/elements/text.rs b/crates/gpui2/src/elements/text.rs index 7716d81536..91ec8045ad 100644 --- a/crates/gpui2/src/elements/text.rs +++ b/crates/gpui2/src/elements/text.rs @@ -12,7 +12,7 @@ use util::ResultExt; impl Element for &'static str { type State = TextState; - fn layout( + fn request_layout( &mut self, _: Option, cx: &mut WindowContext, @@ -42,7 +42,7 @@ impl IntoElement for &'static str { impl Element for SharedString { type State = TextState; - fn layout( + fn request_layout( &mut self, _: Option, cx: &mut WindowContext, @@ -118,7 +118,7 @@ impl StyledText { impl Element for StyledText { type State = TextState; - fn layout( + fn request_layout( &mut self, _: Option, cx: &mut WindowContext, @@ -331,7 +331,7 @@ impl InteractiveText { impl Element for InteractiveText { type State = InteractiveTextState; - fn layout( + fn request_layout( &mut self, state: Option, cx: &mut WindowContext, @@ -340,14 +340,14 @@ impl Element for InteractiveText { mouse_down_index, .. }) = state { - let (layout_id, text_state) = self.text.layout(None, cx); + let (layout_id, text_state) = self.text.request_layout(None, cx); let element_state = InteractiveTextState { text_state, mouse_down_index, }; (layout_id, element_state) } else { - let (layout_id, text_state) = self.text.layout(None, cx); + let (layout_id, text_state) = self.text.request_layout(None, cx); let element_state = InteractiveTextState { text_state, mouse_down_index: Rc::default(), diff --git a/crates/gpui2/src/elements/uniform_list.rs b/crates/gpui2/src/elements/uniform_list.rs index e38a37f90d..390a10021e 100644 --- a/crates/gpui2/src/elements/uniform_list.rs +++ b/crates/gpui2/src/elements/uniform_list.rs @@ -116,7 +116,7 @@ pub struct UniformListState { impl Element for UniformList { type State = UniformListState; - fn layout( + fn request_layout( &mut self, state: Option, cx: &mut WindowContext, diff --git a/crates/gpui2/src/interactive.rs b/crates/gpui2/src/interactive.rs index 58ee849aad..7a4c3d013f 100644 --- a/crates/gpui2/src/interactive.rs +++ b/crates/gpui2/src/interactive.rs @@ -205,9 +205,9 @@ impl ExternalPaths { } impl Render for ExternalPaths { - type Element = Div; + type Output = Div; - fn render(&mut self, _: &mut ViewContext) -> Self::Element { + fn render(&mut self, _: &mut ViewContext) -> Self::Output { div() // Intentionally left empty because the platform will render icons for the dragged files } } @@ -305,9 +305,9 @@ mod test { actions!(test, [TestAction]); impl Render for TestView { - type Element = Stateful
; + type Output = Stateful
; - fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Output { div().id("testview").child( div() .key_context("parent") diff --git a/crates/gpui2/src/view.rs b/crates/gpui2/src/view.rs index 1b4c2b6346..afa08f9213 100644 --- a/crates/gpui2/src/view.rs +++ b/crates/gpui2/src/view.rs @@ -81,12 +81,12 @@ impl View { impl Element for View { type State = Option; - fn layout( + fn request_layout( &mut self, _state: Option, cx: &mut WindowContext, ) -> (LayoutId, Self::State) { - let mut element = self.update(cx, |view, cx| view.render(cx).into_any()); + let mut element = self.update(cx, |view, cx| view.render(cx).into_any_element()); let layout_id = element.layout(cx); (layout_id, Some(element)) } @@ -229,7 +229,7 @@ impl From> for AnyView { impl Element for AnyView { type State = Option; - fn layout( + fn request_layout( &mut self, _state: Option, cx: &mut WindowContext, @@ -317,22 +317,22 @@ where T: 'static + FnMut(&mut WindowContext) -> E, E: 'static + Send + Element, { - type Element = E; + type Output = E; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { (self)(cx) } } mod any_view { - use crate::{AnyElement, AnyView, Element, LayoutId, Render, WindowContext}; + use crate::{AnyElement, AnyView, IntoElement, LayoutId, Render, WindowContext}; pub(crate) fn layout( view: &AnyView, cx: &mut WindowContext, ) -> (LayoutId, AnyElement) { let view = view.clone().downcast::().unwrap(); - let mut element = view.update(cx, |view, cx| view.render(cx).into_any()); + let mut element = view.update(cx, |view, cx| view.render(cx).into_any_element()); let layout_id = element.layout(cx); (layout_id, element) } diff --git a/crates/gpui2_macros/src/derive_render.rs b/crates/gpui2_macros/src/derive_render.rs index 3983a572f0..2695d4a7c5 100644 --- a/crates/gpui2_macros/src/derive_render.rs +++ b/crates/gpui2_macros/src/derive_render.rs @@ -11,9 +11,9 @@ pub fn derive_render(input: TokenStream) -> TokenStream { impl #impl_generics gpui::Render for #type_name #type_generics #where_clause { - type Element = (); + type Output = (); - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { () } } diff --git a/crates/language_selector2/src/active_buffer_language.rs b/crates/language_selector2/src/active_buffer_language.rs index 48224198a2..21f7bf233d 100644 --- a/crates/language_selector2/src/active_buffer_language.rs +++ b/crates/language_selector2/src/active_buffer_language.rs @@ -38,7 +38,7 @@ impl ActiveBufferLanguage { } impl Render for ActiveBufferLanguage { - type Element = Div; + type Output = Div; fn render(&mut self, cx: &mut ViewContext) -> Div { div().when_some(self.active_language.as_ref(), |el, active_language| { diff --git a/crates/language_selector2/src/language_selector.rs b/crates/language_selector2/src/language_selector.rs index 3da8649c6e..16c661b6fb 100644 --- a/crates/language_selector2/src/language_selector.rs +++ b/crates/language_selector2/src/language_selector.rs @@ -67,9 +67,9 @@ impl LanguageSelector { } impl Render for LanguageSelector { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { v_stack().w(rems(34.)).child(self.picker.clone()) } } diff --git a/crates/language_tools2/src/lsp_log.rs b/crates/language_tools2/src/lsp_log.rs index 310726e4a5..00f1e86e5f 100644 --- a/crates/language_tools2/src/lsp_log.rs +++ b/crates/language_tools2/src/lsp_log.rs @@ -595,9 +595,9 @@ fn log_contents(lines: &VecDeque) -> String { } impl Render for LspLogView { - type Element = EditorElement; + type Output = EditorElement; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { self.editor.update(cx, |editor, cx| editor.render(cx)) } } @@ -709,9 +709,9 @@ impl ToolbarItemView for LspLogToolbarItemView { } impl Render for LspLogToolbarItemView { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let Some(log_view) = self.log_view.clone() else { return div(); }; diff --git a/crates/language_tools2/src/syntax_tree_view.rs b/crates/language_tools2/src/syntax_tree_view.rs index e4ee4b0cfb..1794b45337 100644 --- a/crates/language_tools2/src/syntax_tree_view.rs +++ b/crates/language_tools2/src/syntax_tree_view.rs @@ -305,9 +305,9 @@ impl SyntaxTreeView { } impl Render for SyntaxTreeView { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext<'_, Self>) -> Self::Output { let settings = ThemeSettings::get_global(cx); let line_height = cx .text_style() @@ -507,7 +507,7 @@ fn format_node_range(node: Node) -> String { } impl Render for SyntaxTreeToolbarItemView { - type Element = PopoverMenu; + type Output = PopoverMenu; fn render(&mut self, cx: &mut ViewContext<'_, Self>) -> PopoverMenu { self.render_menu(cx) diff --git a/crates/outline2/src/outline.rs b/crates/outline2/src/outline.rs index ba67f33b25..2f29534b6e 100644 --- a/crates/outline2/src/outline.rs +++ b/crates/outline2/src/outline.rs @@ -57,9 +57,9 @@ impl EventEmitter for OutlineView {} impl ModalView for OutlineView {} impl Render for OutlineView { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { v_stack().w(rems(34.)).child(self.picker.clone()) } } diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index 3abdf953b3..6632c13ddf 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -228,9 +228,9 @@ impl EventEmitter for Picker {} impl ModalView for Picker {} impl Render for Picker { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let picker_editor = h_stack() .overflow_hidden() .flex_none() diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 21a114c43c..c0dfe995f6 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -1480,9 +1480,9 @@ impl ProjectPanel { } impl Render for ProjectPanel { - type Element = Focusable>; + type Output = Focusable>; - fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Output { let has_worktree = self.visible_entries.len() != 0; if has_worktree { @@ -1548,9 +1548,9 @@ impl Render for ProjectPanel { } impl Render for DraggedProjectEntryView { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let settings = ProjectPanelSettings::get_global(cx); let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone(); h_stack() diff --git a/crates/quick_action_bar2/src/quick_action_bar.rs b/crates/quick_action_bar2/src/quick_action_bar.rs index 3eba0e60ec..686804e9d9 100644 --- a/crates/quick_action_bar2/src/quick_action_bar.rs +++ b/crates/quick_action_bar2/src/quick_action_bar.rs @@ -36,9 +36,9 @@ impl QuickActionBar { } impl Render for QuickActionBar { - type Element = Stateful
; + type Output = Stateful
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let Some(editor) = self.active_editor() else { return div().id("empty quick action bar"); }; @@ -138,9 +138,9 @@ impl QuickActionBarButton { } impl RenderOnce for QuickActionBarButton { - type Rendered = IconButton; + type Output = IconButton; - fn render(self, _: &mut WindowContext) -> Self::Rendered { + fn render(self, _: &mut WindowContext) -> Self::Output { let tooltip = self.tooltip.clone(); let action = self.action.boxed_clone(); diff --git a/crates/recent_projects2/src/highlighted_workspace_location.rs b/crates/recent_projects2/src/highlighted_workspace_location.rs index a4057d2f4b..2df4409a5f 100644 --- a/crates/recent_projects2/src/highlighted_workspace_location.rs +++ b/crates/recent_projects2/src/highlighted_workspace_location.rs @@ -43,9 +43,9 @@ impl HighlightedText { } impl RenderOnce for HighlightedText { - type Rendered = HighlightedLabel; + type Output = HighlightedLabel; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { HighlightedLabel::new(self.text, self.highlight_positions) } } diff --git a/crates/recent_projects2/src/recent_projects.rs b/crates/recent_projects2/src/recent_projects.rs index 2d6f4bf0e3..6b62d185ed 100644 --- a/crates/recent_projects2/src/recent_projects.rs +++ b/crates/recent_projects2/src/recent_projects.rs @@ -103,9 +103,9 @@ impl FocusableView for RecentProjects { } impl Render for RecentProjects { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { v_stack() .w(rems(self.rem_width)) .child(self.picker.clone()) diff --git a/crates/search2/src/buffer_search.rs b/crates/search2/src/buffer_search.rs index 4972908e0d..a5522cec89 100644 --- a/crates/search2/src/buffer_search.rs +++ b/crates/search2/src/buffer_search.rs @@ -101,9 +101,9 @@ impl BufferSearchBar { impl EventEmitter for BufferSearchBar {} impl EventEmitter for BufferSearchBar {} impl Render for BufferSearchBar { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { if self.dismissed { return div(); } diff --git a/crates/search2/src/project_search.rs b/crates/search2/src/project_search.rs index 9a654c9bf4..167299ba2d 100644 --- a/crates/search2/src/project_search.rs +++ b/crates/search2/src/project_search.rs @@ -279,9 +279,9 @@ pub enum ViewEvent { impl EventEmitter for ProjectSearchView {} impl Render for ProjectSearchView { - type Element = AnyElement; + type Output = AnyElement; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { if self.has_matches() { div() .flex_1() @@ -1494,9 +1494,9 @@ impl ProjectSearchBar { } impl Render for ProjectSearchBar { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let Some(search) = self.active_project_search.clone() else { return div(); }; diff --git a/crates/story/src/story.rs b/crates/story/src/story.rs index 3419af95b0..1a3e84c0d9 100644 --- a/crates/story/src/story.rs +++ b/crates/story/src/story.rs @@ -74,9 +74,9 @@ impl ParentElement for StoryContainer { } impl RenderOnce for StoryContainer { - type Rendered = Stateful
; + type Output = Stateful
; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { div() .size_full() .flex() @@ -294,9 +294,9 @@ impl StoryItem { } impl RenderOnce for StoryItem { - type Rendered = Div; + type Output = Div; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { div() .my_2() .flex() @@ -358,9 +358,9 @@ impl StorySection { } impl RenderOnce for StorySection { - type Rendered = Div; + type Output = Div; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { let children: SmallVec<[AnyElement; 2]> = SmallVec::from_iter(Itertools::intersperse_with( self.children.into_iter(), || Story::divider().into_any_element(), diff --git a/crates/storybook2/src/stories/auto_height_editor.rs b/crates/storybook2/src/stories/auto_height_editor.rs index 2f3089a4e6..d4fda251d7 100644 --- a/crates/storybook2/src/stories/auto_height_editor.rs +++ b/crates/storybook2/src/stories/auto_height_editor.rs @@ -22,9 +22,9 @@ impl AutoHeightEditorStory { } impl Render for AutoHeightEditorStory { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { div() .size_full() .bg(white()) diff --git a/crates/storybook2/src/stories/cursor.rs b/crates/storybook2/src/stories/cursor.rs index 7d4cf8145a..af8d7440a0 100644 --- a/crates/storybook2/src/stories/cursor.rs +++ b/crates/storybook2/src/stories/cursor.rs @@ -5,9 +5,9 @@ use ui::prelude::*; pub struct CursorStory; impl Render for CursorStory { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { let all_cursors: [(&str, Box) -> Stateful
>); 19] = [ ( "cursor_default", diff --git a/crates/storybook2/src/stories/focus.rs b/crates/storybook2/src/stories/focus.rs index a3a8845947..8ee10b6570 100644 --- a/crates/storybook2/src/stories/focus.rs +++ b/crates/storybook2/src/stories/focus.rs @@ -57,9 +57,9 @@ impl FocusStory { } impl Render for FocusStory { - type Element = Focusable>; + type Output = Focusable>; - fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Output { let theme = cx.theme(); let color_1 = theme.status().created; let color_2 = theme.status().modified; diff --git a/crates/storybook2/src/stories/kitchen_sink.rs b/crates/storybook2/src/stories/kitchen_sink.rs index 271285cc2f..d659827990 100644 --- a/crates/storybook2/src/stories/kitchen_sink.rs +++ b/crates/storybook2/src/stories/kitchen_sink.rs @@ -14,9 +14,9 @@ impl KitchenSinkStory { } impl Render for KitchenSinkStory { - type Element = Stateful
; + type Output = Stateful
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let component_stories = ComponentStory::iter() .map(|selector| selector.story(cx)) .collect::>(); diff --git a/crates/storybook2/src/stories/overflow_scroll.rs b/crates/storybook2/src/stories/overflow_scroll.rs index 631b851304..6adc6576ac 100644 --- a/crates/storybook2/src/stories/overflow_scroll.rs +++ b/crates/storybook2/src/stories/overflow_scroll.rs @@ -6,9 +6,9 @@ use ui::prelude::*; pub struct OverflowScrollStory; impl Render for OverflowScrollStory { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { Story::container() .child(Story::title("Overflow Scroll")) .child(Story::label("`overflow_x_scroll`")) diff --git a/crates/storybook2/src/stories/picker.rs b/crates/storybook2/src/stories/picker.rs index edaaaa70bd..85985c5ae3 100644 --- a/crates/storybook2/src/stories/picker.rs +++ b/crates/storybook2/src/stories/picker.rs @@ -202,9 +202,9 @@ impl PickerStory { } impl Render for PickerStory { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Output { div() .bg(cx.theme().styles.colors.background) .size_full() diff --git a/crates/storybook2/src/stories/scroll.rs b/crates/storybook2/src/stories/scroll.rs index 300aae1144..8d8543304d 100644 --- a/crates/storybook2/src/stories/scroll.rs +++ b/crates/storybook2/src/stories/scroll.rs @@ -11,9 +11,9 @@ impl ScrollStory { } impl Render for ScrollStory { - type Element = Stateful
; + type Output = Stateful
; - fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Output { let theme = cx.theme(); let color_1 = theme.status().created; let color_2 = theme.status().modified; diff --git a/crates/storybook2/src/stories/text.rs b/crates/storybook2/src/stories/text.rs index 99d722988d..b044f7ce9a 100644 --- a/crates/storybook2/src/stories/text.rs +++ b/crates/storybook2/src/stories/text.rs @@ -14,9 +14,9 @@ impl TextStory { } impl Render for TextStory { - type Element = Component; + type Output = Component; - fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut gpui::ViewContext) -> Self::Output { StoryContainer::new("Text Story", "crates/storybook2/src/stories/text.rs") .children( vec![ diff --git a/crates/storybook2/src/stories/viewport_units.rs b/crates/storybook2/src/stories/viewport_units.rs index 8a95a6b66c..746f385ab5 100644 --- a/crates/storybook2/src/stories/viewport_units.rs +++ b/crates/storybook2/src/stories/viewport_units.rs @@ -6,9 +6,9 @@ use ui::prelude::*; pub struct ViewportUnitsStory; impl Render for ViewportUnitsStory { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { Story::container().child( div() .flex() diff --git a/crates/storybook2/src/stories/z_index.rs b/crates/storybook2/src/stories/z_index.rs index 9579b8c7fc..1f7141fbfd 100644 --- a/crates/storybook2/src/stories/z_index.rs +++ b/crates/storybook2/src/stories/z_index.rs @@ -7,9 +7,9 @@ use ui::prelude::*; pub struct ZIndexStory; impl Render for ZIndexStory { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { Story::container().child(Story::title("z-index")).child( div() .flex() @@ -82,9 +82,9 @@ struct ZIndexExample { } impl RenderOnce for ZIndexExample { - type Rendered = Div; + type Output = Div; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { div() .relative() .size_full() diff --git a/crates/storybook2/src/storybook2.rs b/crates/storybook2/src/storybook2.rs index 523e93cf52..4fdf65f673 100644 --- a/crates/storybook2/src/storybook2.rs +++ b/crates/storybook2/src/storybook2.rs @@ -113,9 +113,9 @@ impl StoryWrapper { } impl Render for StoryWrapper { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { div() .flex() .flex_col() diff --git a/crates/terminal_view2/src/terminal_element.rs b/crates/terminal_view2/src/terminal_element.rs index cb46f742f6..8be10f9469 100644 --- a/crates/terminal_view2/src/terminal_element.rs +++ b/crates/terminal_view2/src/terminal_element.rs @@ -750,7 +750,7 @@ impl TerminalElement { impl Element for TerminalElement { type State = InteractiveElementState; - fn layout( + fn request_layout( &mut self, element_state: Option, cx: &mut WindowContext<'_>, diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index dd0c7d3999..746c2480c0 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -329,9 +329,9 @@ impl TerminalPanel { impl EventEmitter for TerminalPanel {} impl Render for TerminalPanel { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { div().size_full().child(self.pane.clone()) } } diff --git a/crates/terminal_view2/src/terminal_view.rs b/crates/terminal_view2/src/terminal_view.rs index 6d18d6f8f9..231de1444a 100644 --- a/crates/terminal_view2/src/terminal_view.rs +++ b/crates/terminal_view2/src/terminal_view.rs @@ -617,9 +617,9 @@ impl TerminalView { } impl Render for TerminalView { - type Element = Focusable
; + type Output = Focusable
; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { let terminal_handle = self.terminal.clone(); let focused = self.focus_handle.is_focused(cx); diff --git a/crates/theme_selector2/src/theme_selector.rs b/crates/theme_selector2/src/theme_selector.rs index ae067ce87c..240742025e 100644 --- a/crates/theme_selector2/src/theme_selector.rs +++ b/crates/theme_selector2/src/theme_selector.rs @@ -67,9 +67,9 @@ impl FocusableView for ThemeSelector { } impl Render for ThemeSelector { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { v_stack().w(rems(34.)).child(self.picker.clone()) } } diff --git a/crates/ui2/src/components/avatar.rs b/crates/ui2/src/components/avatar.rs index 793872cd8a..257e46989b 100644 --- a/crates/ui2/src/components/avatar.rs +++ b/crates/ui2/src/components/avatar.rs @@ -16,9 +16,9 @@ pub struct Avatar { } impl RenderOnce for Avatar { - type Rendered = Div; + type Output = Div; - fn render(mut self, cx: &mut WindowContext) -> Self::Rendered { + fn render(mut self, cx: &mut WindowContext) -> Self::Output { if self.image.style().corner_radii.top_left.is_none() { self = self.shape(Shape::Circle); } diff --git a/crates/ui2/src/components/button/button.rs b/crates/ui2/src/components/button/button.rs index bc5d03d639..2ad12919fb 100644 --- a/crates/ui2/src/components/button/button.rs +++ b/crates/ui2/src/components/button/button.rs @@ -136,9 +136,9 @@ impl ButtonCommon for Button { } impl RenderOnce for Button { - type Rendered = ButtonLike; + type Output = ButtonLike; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { let is_disabled = self.base.disabled; let is_selected = self.base.selected; diff --git a/crates/ui2/src/components/button/button_icon.rs b/crates/ui2/src/components/button/button_icon.rs index 3b2c703938..a82aa14e6e 100644 --- a/crates/ui2/src/components/button/button_icon.rs +++ b/crates/ui2/src/components/button/button_icon.rs @@ -63,9 +63,9 @@ impl Selectable for ButtonIcon { } impl RenderOnce for ButtonIcon { - type Rendered = IconElement; + type Output = IconElement; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { let icon = self .selected_icon .filter(|_| self.selected) diff --git a/crates/ui2/src/components/button/button_like.rs b/crates/ui2/src/components/button/button_like.rs index 13d4f360f2..0f304ae15d 100644 --- a/crates/ui2/src/components/button/button_like.rs +++ b/crates/ui2/src/components/button/button_like.rs @@ -363,9 +363,9 @@ impl ParentElement for ButtonLike { } impl RenderOnce for ButtonLike { - type Rendered = Stateful
; + type Output = Stateful
; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { self.base .h_flex() .id(self.id.clone()) diff --git a/crates/ui2/src/components/button/icon_button.rs b/crates/ui2/src/components/button/icon_button.rs index 3a53bb6cb0..9dcb0c04d4 100644 --- a/crates/ui2/src/components/button/icon_button.rs +++ b/crates/ui2/src/components/button/icon_button.rs @@ -106,9 +106,9 @@ impl VisibleOnHover for IconButton { } impl RenderOnce for IconButton { - type Rendered = ButtonLike; + type Output = ButtonLike; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { let is_disabled = self.base.disabled; let is_selected = self.base.selected; diff --git a/crates/ui2/src/components/button/toggle_button.rs b/crates/ui2/src/components/button/toggle_button.rs index 4a6ecdeb2f..7ac642011f 100644 --- a/crates/ui2/src/components/button/toggle_button.rs +++ b/crates/ui2/src/components/button/toggle_button.rs @@ -99,9 +99,9 @@ impl ButtonCommon for ToggleButton { } impl RenderOnce for ToggleButton { - type Rendered = ButtonLike; + type Output = ButtonLike; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { let is_disabled = self.base.disabled; let is_selected = self.base.selected; diff --git a/crates/ui2/src/components/checkbox.rs b/crates/ui2/src/components/checkbox.rs index 51e38a38f4..fd92e96946 100644 --- a/crates/ui2/src/components/checkbox.rs +++ b/crates/ui2/src/components/checkbox.rs @@ -19,9 +19,9 @@ pub struct Checkbox { } impl RenderOnce for Checkbox { - type Rendered = gpui::Stateful
; + type Output = gpui::Stateful
; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { let group_id = format!("checkbox_group_{:?}", self.id); let icon = match self.checked { diff --git a/crates/ui2/src/components/context_menu.rs b/crates/ui2/src/components/context_menu.rs index 6df6a29096..3ea5e9bc5f 100644 --- a/crates/ui2/src/components/context_menu.rs +++ b/crates/ui2/src/components/context_menu.rs @@ -232,9 +232,9 @@ impl ContextMenuItem { } impl Render for ContextMenu { - type Element = Div; + type Output = Div; - fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, cx: &mut ViewContext) -> Self::Output { div().elevation_2(cx).flex().flex_row().child( v_stack() .min_w(px(200.)) diff --git a/crates/ui2/src/components/disclosure.rs b/crates/ui2/src/components/disclosure.rs index 729023986d..663fba30ca 100644 --- a/crates/ui2/src/components/disclosure.rs +++ b/crates/ui2/src/components/disclosure.rs @@ -28,9 +28,9 @@ impl Disclosure { } impl RenderOnce for Disclosure { - type Rendered = IconButton; + type Output = IconButton; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { IconButton::new( self.id, match self.is_open { diff --git a/crates/ui2/src/components/divider.rs b/crates/ui2/src/components/divider.rs index 20744d6c48..dd30ce0ec5 100644 --- a/crates/ui2/src/components/divider.rs +++ b/crates/ui2/src/components/divider.rs @@ -31,9 +31,9 @@ pub struct Divider { } impl RenderOnce for Divider { - type Rendered = Div; + type Output = Div; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { div() .map(|this| match self.direction { DividerDirection::Horizontal => { diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index a168f97a50..b0eed86250 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -196,9 +196,9 @@ pub struct IconElement { } impl RenderOnce for IconElement { - type Rendered = Svg; + type Output = Svg; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { svg() .size(self.size.rems()) .flex_none() diff --git a/crates/ui2/src/components/indicator.rs b/crates/ui2/src/components/indicator.rs index 4a94650dfc..f3dc62d20f 100644 --- a/crates/ui2/src/components/indicator.rs +++ b/crates/ui2/src/components/indicator.rs @@ -45,9 +45,9 @@ impl Indicator { } impl RenderOnce for Indicator { - type Rendered = Div; + type Output = Div; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { div() .flex_none() .map(|this| match self.style { diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index 8314f607fe..f0de9891a7 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -11,9 +11,9 @@ pub struct KeyBinding { } impl RenderOnce for KeyBinding { - type Rendered = Div; + type Output = Div; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { h_stack() .flex_none() .gap_2() @@ -91,9 +91,9 @@ pub struct Key { } impl RenderOnce for Key { - type Rendered = Div; + type Output = Div; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { let single_char = self.key.len() == 1; div() @@ -125,9 +125,9 @@ pub struct KeyIcon { } impl RenderOnce for KeyIcon { - type Rendered = Div; + type Output = Div; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { div() .w(rems(14. / 16.)) .child(IconElement::new(self.icon).size(IconSize::Small)) diff --git a/crates/ui2/src/components/label/highlighted_label.rs b/crates/ui2/src/components/label/highlighted_label.rs index a7fbb0d816..08dfbe2391 100644 --- a/crates/ui2/src/components/label/highlighted_label.rs +++ b/crates/ui2/src/components/label/highlighted_label.rs @@ -46,9 +46,9 @@ impl LabelCommon for HighlightedLabel { } impl RenderOnce for HighlightedLabel { - type Rendered = LabelLike; + type Output = LabelLike; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { let highlight_color = cx.theme().colors().text_accent; let mut highlight_indices = self.highlight_indices.iter().copied().peekable(); diff --git a/crates/ui2/src/components/label/label.rs b/crates/ui2/src/components/label/label.rs index 8272340888..888cd506d7 100644 --- a/crates/ui2/src/components/label/label.rs +++ b/crates/ui2/src/components/label/label.rs @@ -40,9 +40,9 @@ impl LabelCommon for Label { } impl RenderOnce for Label { - type Rendered = LabelLike; + type Output = LabelLike; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { self.base.child(self.label) } } diff --git a/crates/ui2/src/components/label/label_like.rs b/crates/ui2/src/components/label/label_like.rs index ebfbbecceb..54e383eb48 100644 --- a/crates/ui2/src/components/label/label_like.rs +++ b/crates/ui2/src/components/label/label_like.rs @@ -76,9 +76,9 @@ impl ParentElement for LabelLike { } impl RenderOnce for LabelLike { - type Rendered = Div; + type Output = Div; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { div() .when(self.strikethrough, |this| { this.relative().child( diff --git a/crates/ui2/src/components/list/list.rs b/crates/ui2/src/components/list/list.rs index fdfe256bd6..23ebd8427c 100644 --- a/crates/ui2/src/components/list/list.rs +++ b/crates/ui2/src/components/list/list.rs @@ -46,9 +46,9 @@ impl ParentElement for List { } impl RenderOnce for List { - type Rendered = Div; + type Output = Div; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { v_stack().w_full().py_1().children(self.header).map(|this| { match (self.children.is_empty(), self.toggle) { (false, _) => this.children(self.children), diff --git a/crates/ui2/src/components/list/list_header.rs b/crates/ui2/src/components/list/list_header.rs index 0c07867c6d..9726ed2c2b 100644 --- a/crates/ui2/src/components/list/list_header.rs +++ b/crates/ui2/src/components/list/list_header.rs @@ -76,9 +76,9 @@ impl Selectable for ListHeader { } impl RenderOnce for ListHeader { - type Rendered = Stateful
; + type Output = Stateful
; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { h_stack() .id(self.label.clone()) .w_full() diff --git a/crates/ui2/src/components/list/list_item.rs b/crates/ui2/src/components/list/list_item.rs index 6295e2940d..403c24b8e5 100644 --- a/crates/ui2/src/components/list/list_item.rs +++ b/crates/ui2/src/components/list/list_item.rs @@ -147,9 +147,9 @@ impl ParentElement for ListItem { } impl RenderOnce for ListItem { - type Rendered = Stateful
; + type Output = Stateful
; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { h_stack() .id(self.id) .w_full() diff --git a/crates/ui2/src/components/list/list_separator.rs b/crates/ui2/src/components/list/list_separator.rs index 346b13ddaa..d7afb0ed93 100644 --- a/crates/ui2/src/components/list/list_separator.rs +++ b/crates/ui2/src/components/list/list_separator.rs @@ -6,9 +6,9 @@ use crate::prelude::*; pub struct ListSeparator; impl RenderOnce for ListSeparator { - type Rendered = Div; + type Output = Div; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { div() .h_px() .w_full() diff --git a/crates/ui2/src/components/list/list_sub_header.rs b/crates/ui2/src/components/list/list_sub_header.rs index 07a99dabe5..9f49587a45 100644 --- a/crates/ui2/src/components/list/list_sub_header.rs +++ b/crates/ui2/src/components/list/list_sub_header.rs @@ -26,9 +26,9 @@ impl ListSubHeader { } impl RenderOnce for ListSubHeader { - type Rendered = Div; + type Output = Div; - fn render(self, _cx: &mut WindowContext) -> Self::Rendered { + fn render(self, _cx: &mut WindowContext) -> Self::Output { h_stack().flex_1().w_full().relative().py_1().child( div() .h_6() diff --git a/crates/ui2/src/components/popover.rs b/crates/ui2/src/components/popover.rs index 91713bc307..7d888ed3aa 100644 --- a/crates/ui2/src/components/popover.rs +++ b/crates/ui2/src/components/popover.rs @@ -41,9 +41,9 @@ pub struct Popover { } impl RenderOnce for Popover { - type Rendered = Div; + type Output = Div; - fn render(self, cx: &mut WindowContext) -> Self::Rendered { + fn render(self, cx: &mut WindowContext) -> Self::Output { div() .flex() .gap_1() diff --git a/crates/ui2/src/components/popover_menu.rs b/crates/ui2/src/components/popover_menu.rs index 1a02dd526e..3cc925e0b5 100644 --- a/crates/ui2/src/components/popover_menu.rs +++ b/crates/ui2/src/components/popover_menu.rs @@ -130,7 +130,7 @@ pub struct PopoverMenuState { impl Element for PopoverMenu { type State = PopoverMenuState; - fn layout( + fn request_layout( &mut self, element_state: Option, cx: &mut WindowContext, diff --git a/crates/ui2/src/components/right_click_menu.rs b/crates/ui2/src/components/right_click_menu.rs index a3a454d652..81f553a6a2 100644 --- a/crates/ui2/src/components/right_click_menu.rs +++ b/crates/ui2/src/components/right_click_menu.rs @@ -60,7 +60,7 @@ pub struct MenuHandleState { impl Element for RightClickMenu { type State = MenuHandleState; - fn layout( + fn request_layout( &mut self, element_state: Option, cx: &mut WindowContext, diff --git a/crates/ui2/src/components/stories/avatar.rs b/crates/ui2/src/components/stories/avatar.rs index 09adfe480a..3b40f07c89 100644 --- a/crates/ui2/src/components/stories/avatar.rs +++ b/crates/ui2/src/components/stories/avatar.rs @@ -7,9 +7,9 @@ use crate::Avatar; pub struct AvatarStory; impl Render for AvatarStory { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { Story::container() .child(Story::title_for::()) .child(Story::label("Default")) diff --git a/crates/ui2/src/components/stories/button.rs b/crates/ui2/src/components/stories/button.rs index 9fe4f55dcb..8066f77353 100644 --- a/crates/ui2/src/components/stories/button.rs +++ b/crates/ui2/src/components/stories/button.rs @@ -7,9 +7,9 @@ use crate::{Button, ButtonStyle}; pub struct ButtonStory; impl Render for ButtonStory { - type Element = Div; + type Output = Div; - fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { + fn render(&mut self, _cx: &mut ViewContext) -> Self::Output { Story::container() .child(Story::title_for::