Add basic styling

Antonio Scandurra created

Change summary

crates/ai/src/refactor.rs          | 53 ++++++++++++++++++++++---------
crates/theme/src/theme.rs          | 10 ++++++
styles/src/style_tree/assistant.ts | 16 +++++++++
3 files changed, 64 insertions(+), 15 deletions(-)

Detailed changes

crates/ai/src/refactor.rs 🔗

@@ -3,10 +3,10 @@ use collections::HashMap;
 use editor::{Editor, ToOffset};
 use futures::{channel::mpsc, SinkExt, StreamExt};
 use gpui::{
-    actions, elements::*, AnyViewHandle, AppContext, Entity, Task, View, ViewContext, ViewHandle,
-    WeakViewHandle,
+    actions, elements::*, platform::MouseButton, AnyViewHandle, AppContext, Entity, Task, View,
+    ViewContext, ViewHandle, WeakViewHandle,
 };
-use menu::Confirm;
+use menu::{Cancel, Confirm};
 use std::{env, sync::Arc};
 use util::TryFutureExt;
 use workspace::{Modal, Workspace};
@@ -17,6 +17,7 @@ pub fn init(cx: &mut AppContext) {
     cx.set_global(RefactoringAssistant::new());
     cx.add_action(RefactoringModal::deploy);
     cx.add_action(RefactoringModal::confirm);
+    cx.add_action(RefactoringModal::cancel);
 }
 
 pub struct RefactoringAssistant {
@@ -139,14 +140,18 @@ impl RefactoringAssistant {
     }
 }
 
+enum Event {
+    Dismissed,
+}
+
 struct RefactoringModal {
-    editor: WeakViewHandle<Editor>,
+    active_editor: WeakViewHandle<Editor>,
     prompt_editor: ViewHandle<Editor>,
     has_focus: bool,
 }
 
 impl Entity for RefactoringModal {
-    type Event = ();
+    type Event = Event;
 }
 
 impl View for RefactoringModal {
@@ -155,11 +160,24 @@ impl View for RefactoringModal {
     }
 
     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
-        ChildView::new(&self.prompt_editor, cx).into_any()
+        let theme = theme::current(cx);
+
+        ChildView::new(&self.prompt_editor, cx)
+            .constrained()
+            .with_width(theme.assistant.modal.width)
+            .contained()
+            .with_style(theme.assistant.modal.container)
+            .mouse::<Self>(0)
+            .on_click_out(MouseButton::Left, |_, _, cx| cx.emit(Event::Dismissed))
+            .on_click_out(MouseButton::Right, |_, _, cx| cx.emit(Event::Dismissed))
+            .aligned()
+            .right()
+            .into_any()
     }
 
-    fn focus_in(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {
+    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
         self.has_focus = true;
+        cx.focus(&self.prompt_editor);
     }
 
     fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext<Self>) {
@@ -173,29 +191,29 @@ impl Modal for RefactoringModal {
     }
 
     fn dismiss_on_event(event: &Self::Event) -> bool {
-        // TODO
-        false
+        matches!(event, Self::Event::Dismissed)
     }
 }
 
 impl RefactoringModal {
     fn deploy(workspace: &mut Workspace, _: &Refactor, cx: &mut ViewContext<Workspace>) {
-        if let Some(editor) = workspace
+        if let Some(active_editor) = workspace
             .active_item(cx)
             .and_then(|item| Some(item.downcast::<Editor>()?.downgrade()))
         {
             workspace.toggle_modal(cx, |_, cx| {
                 let prompt_editor = cx.add_view(|cx| {
                     let mut editor = Editor::auto_height(
-                        4,
-                        Some(Arc::new(|theme| theme.search.editor.input.clone())),
+                        theme::current(cx).assistant.modal.editor_max_lines,
+                        Some(Arc::new(|theme| theme.assistant.modal.editor.clone())),
                         cx,
                     );
-                    editor.set_text("Replace with if statement.", cx);
+                    editor
+                        .set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
                     editor
                 });
                 cx.add_view(|_| RefactoringModal {
-                    editor,
+                    active_editor,
                     prompt_editor,
                     has_focus: false,
                 })
@@ -203,12 +221,17 @@ impl RefactoringModal {
         }
     }
 
+    fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
+        cx.emit(Event::Dismissed);
+    }
+
     fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
-        if let Some(editor) = self.editor.upgrade(cx) {
+        if let Some(editor) = self.active_editor.upgrade(cx) {
             let prompt = self.prompt_editor.read(cx).text(cx);
             cx.update_global(|assistant: &mut RefactoringAssistant, cx| {
                 assistant.refactor(&editor, &prompt, cx);
             });
+            cx.emit(Event::Dismissed);
         }
     }
 }

crates/theme/src/theme.rs 🔗

@@ -1124,6 +1124,16 @@ pub struct AssistantStyle {
     pub api_key_editor: FieldEditor,
     pub api_key_prompt: ContainedText,
     pub saved_conversation: SavedConversation,
+    pub modal: ModalAssistantStyle,
+}
+
+#[derive(Clone, Deserialize, Default, JsonSchema)]
+pub struct ModalAssistantStyle {
+    #[serde(flatten)]
+    pub container: ContainerStyle,
+    pub width: f32,
+    pub editor_max_lines: usize,
+    pub editor: FieldEditor,
 }
 
 #[derive(Clone, Deserialize, Default, JsonSchema)]

styles/src/style_tree/assistant.ts 🔗

@@ -59,6 +59,22 @@ export default function assistant(): any {
             background: background(theme.highest),
             padding: { left: 12 },
         },
+        modal: {
+            background: background(theme.lowest),
+            border: border(theme.lowest),
+            shadow: theme.modal_shadow,
+            corner_radius: 12,
+            padding: { left: 12, right: 0, top: 12, bottom: 12 },
+            margin: { right: 12 },
+            width: 500,
+            editor_max_lines: 6,
+            editor: {
+                background: background(theme.lowest),
+                text: text(theme.lowest, "mono", "on"),
+                placeholder_text: text(theme.lowest, "sans", "on", "disabled"),
+                selection: theme.players[0],
+            }
+        },
         message_header: {
             margin: { bottom: 4, top: 4 },
             background: background(theme.highest),