From 7cdece4857caee93f3dd6af3319a976165895c72 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Tue, 7 Nov 2023 15:27:08 -0700 Subject: [PATCH] Beautiful go to line modal Co-authored-by: Julia Co-authored-by: Marshall --- crates/editor2/src/editor.rs | 68 +++++++++++------ crates/go_to_line2/src/go_to_line.rs | 110 +++++++++++++++++---------- crates/theme2/src/theme2.rs | 8 +- crates/workspace2/src/modal_layer.rs | 23 +----- 4 files changed, 126 insertions(+), 83 deletions(-) diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index c63c531cebddcfa1f807ee5460a54b1976d9c175..10831995ff303d72d6687926d4b6b2a485721b72 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -36,10 +36,10 @@ pub use element::{ use futures::FutureExt; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, div, px, relative, AnyElement, AppContext, BackgroundExecutor, Context, - DispatchContext, Div, Element, Entity, EventEmitter, FocusHandle, FontStyle, FontWeight, Hsla, - Model, Pixels, Render, Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext, - WeakView, WindowContext, + actions, div, hsla, px, relative, rems, AnyElement, AppContext, BackgroundExecutor, Context, + DispatchContext, Div, Element, Entity, EventEmitter, FocusHandle, FontFeatures, FontStyle, + FontWeight, Hsla, Model, Pixels, Render, Styled, Subscription, Task, TextStyle, View, + ViewContext, VisualContext, WeakView, WindowContext, }; use highlight_matching_bracket::refresh_matching_bracket_highlights; use hover_popover::{hide_hover, HoverState}; @@ -2162,14 +2162,14 @@ impl Editor { // self.collaboration_hub = Some(hub); // } - // pub fn set_placeholder_text( - // &mut self, - // placeholder_text: impl Into>, - // cx: &mut ViewContext, - // ) { - // self.placeholder_text = Some(placeholder_text.into()); - // cx.notify(); - // } + pub fn set_placeholder_text( + &mut self, + placeholder_text: impl Into>, + cx: &mut ViewContext, + ) { + self.placeholder_text = Some(placeholder_text.into()); + cx.notify(); + } // pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext) { // self.cursor_shape = cursor_shape; @@ -9365,18 +9365,42 @@ impl Render for Editor { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { let settings = ThemeSettings::get_global(cx); - let text_style = TextStyle { - color: cx.theme().colors().text, - font_family: settings.buffer_font.family.clone(), - font_features: settings.buffer_font.features, - font_size: settings.buffer_font_size.into(), - font_weight: FontWeight::NORMAL, - font_style: FontStyle::Normal, - line_height: relative(settings.buffer_line_height.value()), - underline: None, + let text_style = match self.mode { + EditorMode::SingleLine => { + TextStyle { + color: cx.theme().colors().text, + font_family: "Zed Sans".into(), // todo!() + font_features: FontFeatures::default(), + font_size: rems(1.0).into(), + font_weight: FontWeight::NORMAL, + font_style: FontStyle::Normal, + line_height: relative(1.3).into(), // TODO relative(settings.buffer_line_height.value()), + underline: None, + } + } + + EditorMode::AutoHeight { max_lines } => todo!(), + + EditorMode::Full => TextStyle { + color: cx.theme().colors().text, + font_family: settings.buffer_font.family.clone(), + font_features: settings.buffer_font.features, + font_size: settings.buffer_font_size.into(), + font_weight: FontWeight::NORMAL, + font_style: FontStyle::Normal, + line_height: relative(settings.buffer_line_height.value()), + underline: None, + }, + }; + + let background = match self.mode { + EditorMode::SingleLine => cx.theme().system().transparent, + EditorMode::AutoHeight { max_lines } => cx.theme().system().transparent, + EditorMode::Full => cx.theme().colors().editor_background, }; + EditorElement::new(EditorStyle { - background: cx.theme().colors().editor_background, + background, local_player: cx.theme().players().local(), text: text_style, scrollbar_width: px(12.), diff --git a/crates/go_to_line2/src/go_to_line.rs b/crates/go_to_line2/src/go_to_line.rs index d280f31de2ef8acf7b83f72ffd37b959fe5b34a0..fc0b7432c7b3eed48135e2551d7be5710168bae2 100644 --- a/crates/go_to_line2/src/go_to_line.rs +++ b/crates/go_to_line2/src/go_to_line.rs @@ -1,15 +1,11 @@ +use editor::Editor; use gpui::{ - actions, div, px, red, AppContext, Div, ParentElement, Render, Styled, ViewContext, - VisualContext, -}; -use ui::modal; -use editor::{scroll::autoscroll::Autoscroll, Editor}; -use gpui::{ - actions, div, px, red, AppContext, Div, EventEmitter, ParentElement, Render, Styled, View, + actions, div, AppContext, Div, EventEmitter, ParentElement, Render, SharedString, Styled, View, ViewContext, VisualContext, }; -use text::{Bias, Point}; -use ui::modal; +use text::Point; +use theme::ActiveTheme; +use ui::{h_stack, modal, v_stack, Label, LabelColor}; use util::paths::FILE_ROW_COLUMN_DELIMITER; use workspace::ModalRegistry; @@ -33,6 +29,7 @@ pub fn init(cx: &mut AppContext) { pub struct GoToLine { line_editor: View, + #[allow(unused)] // todo!() active_editor: View, } @@ -46,7 +43,11 @@ impl EventEmitter for GoToLine { impl GoToLine { pub fn new(active_editor: View, cx: &mut ViewContext) -> Self { - let line_editor = cx.build_view(|cx| Editor::single_line(cx)); + let line_editor = cx.build_view(|cx| { + let mut editor = Editor::single_line(cx); + editor.set_placeholder_text("Find something", cx); + editor + }); cx.subscribe(&line_editor, Self::on_line_editor_event) .detach(); @@ -65,26 +66,27 @@ impl GoToLine { match event { editor::Event::Blurred => cx.emit(Event::Dismissed), editor::Event::BufferEdited { .. } => { - if let Some(point) = self.point_from_query(cx) { - // todo!() - // self.active_editor.update(cx, |active_editor, cx| { - // let snapshot = active_editor.snapshot(cx).display_snapshot; - // let point = snapshot.buffer_snapshot.clip_point(point, Bias::Left); - // let display_point = point.to_display_point(&snapshot); - // let row = display_point.row(); - // active_editor.highlight_rows(Some(row..row + 1)); - // active_editor.request_autoscroll(Autoscroll::center(), cx); - // }); - cx.notify(); - } + // if let Some(point) = self.point_from_query(cx) { + // todo!() + // self.active_editor.update(cx, |active_editor, cx| { + // let snapshot = active_editor.snapshot(cx).display_snapshot; + // let point = snapshot.buffer_snapshot.clip_point(point, Bias::Left); + // let display_point = point.to_display_point(&snapshot); + // let row = display_point.row(); + // active_editor.highlight_rows(Some(row..row + 1)); + // active_editor.request_autoscroll(Autoscroll::center(), cx); + // }); + // cx.notify(); + // } } _ => {} } } + #[allow(unused)] fn point_from_query(&self, cx: &ViewContext) -> Option { // todo!() - let line_editor = "2:2"; //self.line_editor.read(cx).text(cx); + let line_editor = self.line_editor.read(cx).text(cx); let mut components = line_editor .splitn(2, FILE_ROW_COLUMN_DELIMITER) .map(str::trim) @@ -97,22 +99,26 @@ impl GoToLine { )) } - fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext) { - cx.emit(Event::Dismissed); - } - - fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext) { - if let Some(point) = self.point_from_query(cx) { - self.active_editor.update(cx, |active_editor, cx| { - let snapshot = active_editor.snapshot(cx).display_snapshot; - let point = snapshot.buffer_snapshot.clip_point(point, Bias::Left); - active_editor.change_selections(Some(Autoscroll::center()), cx, |s| { - s.select_ranges([point..point]) - }); - }); - } - - cx.emit(Event::Dismissed); + // fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext) { + // cx.emit(Event::Dismissed); + // } + + // fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext) { + // if let Some(point) = self.point_from_query(cx) { + // self.active_editor.update(cx, |active_editor, cx| { + // let snapshot = active_editor.snapshot(cx).display_snapshot; + // let point = snapshot.buffer_snapshot.clip_point(point, Bias::Left); + // active_editor.change_selections(Some(Autoscroll::center()), cx, |s| { + // s.select_ranges([point..point]) + // }); + // }); + // } + + // cx.emit(Event::Dismissed); + // } + + fn status_text(&self) -> SharedString { + "Default text".into() } } @@ -120,7 +126,31 @@ impl Render for GoToLine { type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - modal(cx).child(self.line_editor.clone()).child("blah blah") + modal(cx).w_96().child( + v_stack() + .px_1() + .pt_0p5() + .gap_px() + .child( + v_stack() + .py_0p5() + .px_1() + .child(div().px_1().py_0p5().child(self.line_editor.clone())), + ) + .child( + div() + .h_px() + .w_full() + .bg(cx.theme().colors().element_background), + ) + .child( + h_stack() + .justify_between() + .px_2() + .py_1() + .child(Label::new(self.status_text()).color(LabelColor::Muted)), + ), + ) } } diff --git a/crates/theme2/src/theme2.rs b/crates/theme2/src/theme2.rs index 88db3c55f47cf859fa5475745c270064d09d120a..33a977f695b945d197fcf2b4bf62ce53b322f156 100644 --- a/crates/theme2/src/theme2.rs +++ b/crates/theme2/src/theme2.rs @@ -63,7 +63,13 @@ pub struct Theme { } impl Theme { - /// Returns the [`ThemeColors`] for the theme. + /// Returns the [`SystemColors`] for the theme. + #[inline(always)] + pub fn system(&self) -> &SystemColors { + &self.styles.system + } + + /// Returns the [`PlayerColors`] for the theme. #[inline(always)] pub fn players(&self) -> &PlayerColors { &self.styles.player diff --git a/crates/workspace2/src/modal_layer.rs b/crates/workspace2/src/modal_layer.rs index 298e5646b7d9049064700c2d1b64b8dd10710fb0..c69354f87b54bf0ad005c2a6247ad9b9b263254e 100644 --- a/crates/workspace2/src/modal_layer.rs +++ b/crates/workspace2/src/modal_layer.rs @@ -1,7 +1,7 @@ use std::{any::TypeId, sync::Arc}; use gpui::{ - div, hsla, px, red, AnyView, AppContext, Component, DispatchPhase, Div, ParentElement, Render, + div, px, AnyView, AppContext, Component, DispatchPhase, Div, ParentElement, Render, StatelessInteractive, Styled, View, ViewContext, }; use ui::v_stack; @@ -72,21 +72,8 @@ impl ModalLayer { Self { open_modal: None } } - // Workspace - // - ModalLayer parent - // - - container - // - - - modal - // - - - content of the modal - // - - content of the workspace - - // app - // workspace - // container some layer that contains all modals and is 100% wide and high - // modal (this has a shadow, some witdht) - // whatever - pub fn render(&self, workspace: &Workspace, cx: &ViewContext) -> Div { - let mut parent = div().relative().bg(red()).size_full(); + let mut parent = div().relative().size_full(); for (_, action) in cx.global::().registered_modals.iter() { parent = (action)(parent); @@ -104,11 +91,7 @@ impl ModalLayer { .z_index(400); // transparent layer - let container2 = v_stack() - .bg(hsla(0.5, 0.5, 0.5, 0.5)) - .h(px(0.0)) - .relative() - .top_20(); + let container2 = v_stack().h(px(0.0)).relative().top_20(); parent.child(container1.child(container2.child(open_modal.clone()))) })