@@ -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);
}
}
}
@@ -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)]
@@ -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),