mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-17 23:56:55 +00:00
zed2: Position terminal context menu, wire up dismis, and unbork context menu (#3561)
Release Notes: - N/A
This commit is contained in:
commit
40b219f861
3 changed files with 56 additions and 64 deletions
|
@ -5,7 +5,7 @@ use gpui::{
|
|||
FontStyle, FontWeight, HighlightStyle, Hsla, InteractiveElement, InteractiveElementState,
|
||||
IntoElement, LayoutId, Model, ModelContext, ModifiersChangedEvent, MouseButton, Pixels,
|
||||
PlatformInputHandler, Point, Rgba, ShapedLine, Size, StatefulInteractiveElement, Styled,
|
||||
TextRun, TextStyle, TextSystem, UnderlineStyle, View, WhiteSpace, WindowContext,
|
||||
TextRun, TextStyle, TextSystem, UnderlineStyle, WhiteSpace, WindowContext,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use language::CursorShape;
|
||||
|
@ -27,8 +27,6 @@ use ui::Tooltip;
|
|||
use std::mem;
|
||||
use std::{fmt::Debug, ops::RangeInclusive};
|
||||
|
||||
use crate::TerminalView;
|
||||
|
||||
///The information generated during layout that is necessary for painting
|
||||
pub struct LayoutState {
|
||||
cells: Vec<LayoutCell>,
|
||||
|
@ -149,7 +147,6 @@ impl LayoutRect {
|
|||
///We need to keep a reference to the view for mouse events, do we need it for any other terminal stuff, or can we move that to connection?
|
||||
pub struct TerminalElement {
|
||||
terminal: Model<Terminal>,
|
||||
terminal_view: View<TerminalView>,
|
||||
focus: FocusHandle,
|
||||
focused: bool,
|
||||
cursor_visible: bool,
|
||||
|
@ -168,7 +165,6 @@ impl StatefulInteractiveElement for TerminalElement {}
|
|||
impl TerminalElement {
|
||||
pub fn new(
|
||||
terminal: Model<Terminal>,
|
||||
terminal_view: View<TerminalView>,
|
||||
focus: FocusHandle,
|
||||
focused: bool,
|
||||
cursor_visible: bool,
|
||||
|
@ -176,7 +172,6 @@ impl TerminalElement {
|
|||
) -> TerminalElement {
|
||||
TerminalElement {
|
||||
terminal,
|
||||
terminal_view,
|
||||
focused,
|
||||
focus: focus.clone(),
|
||||
cursor_visible,
|
||||
|
@ -774,18 +769,11 @@ impl Element for TerminalElement {
|
|||
(layout_id, interactive_state)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
state: &mut Self::State,
|
||||
cx: &mut WindowContext<'_>,
|
||||
) {
|
||||
fn paint(self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext<'_>) {
|
||||
let mut layout = self.compute_layout(bounds, cx);
|
||||
|
||||
let theme = cx.theme();
|
||||
|
||||
let dispatch_context = self.terminal_view.read(cx).dispatch_context(cx);
|
||||
self.interactivity().key_context = Some(dispatch_context);
|
||||
cx.paint_quad(
|
||||
bounds,
|
||||
Default::default(),
|
||||
|
|
|
@ -9,9 +9,10 @@ pub mod terminal_panel;
|
|||
// use crate::terminal_element::TerminalElement;
|
||||
use editor::{scroll::autoscroll::Autoscroll, Editor};
|
||||
use gpui::{
|
||||
div, Action, AnyElement, AppContext, Div, EventEmitter, FocusEvent, FocusHandle, Focusable,
|
||||
FocusableElement, FocusableView, KeyContext, KeyDownEvent, Keystroke, Model, MouseButton,
|
||||
MouseDownEvent, Pixels, Render, Subscription, Task, View, VisualContext, WeakView,
|
||||
div, overlay, Action, AnyElement, AppContext, DismissEvent, Div, EventEmitter, FocusEvent,
|
||||
FocusHandle, Focusable, FocusableElement, FocusableView, KeyContext, KeyDownEvent, Keystroke,
|
||||
Model, MouseButton, MouseDownEvent, Pixels, Render, Styled, Subscription, Task, View,
|
||||
VisualContext, WeakView,
|
||||
};
|
||||
use language::Bias;
|
||||
use persistence::TERMINAL_DB;
|
||||
|
@ -81,7 +82,7 @@ pub struct TerminalView {
|
|||
has_new_content: bool,
|
||||
//Currently using iTerm bell, show bell emoji in tab until input is received
|
||||
has_bell: bool,
|
||||
context_menu: Option<View<ContextMenu>>,
|
||||
context_menu: Option<(View<ContextMenu>, gpui::Point<Pixels>, Subscription)>,
|
||||
blink_state: bool,
|
||||
blinking_on: bool,
|
||||
blinking_paused: bool,
|
||||
|
@ -312,14 +313,24 @@ impl TerminalView {
|
|||
position: gpui::Point<Pixels>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.context_menu = Some(ContextMenu::build(cx, |menu, cx| {
|
||||
let context_menu = ContextMenu::build(cx, |menu, cx| {
|
||||
menu.action("Clear", Box::new(Clear))
|
||||
.action("Close", Box::new(CloseActiveItem { save_intent: None }))
|
||||
}));
|
||||
// todo!(context menus)
|
||||
// self.context_menu
|
||||
// .show(position, AnchorCorner::TopLeft, menu_entries, cx);
|
||||
// cx.notify();
|
||||
});
|
||||
|
||||
cx.focus_view(&context_menu);
|
||||
let subscription =
|
||||
cx.subscribe(&context_menu, |this, _, _: &DismissEvent, cx| {
|
||||
if this.context_menu.as_ref().is_some_and(|context_menu| {
|
||||
context_menu.0.focus_handle(cx).contains_focused(cx)
|
||||
}) {
|
||||
cx.focus_self();
|
||||
}
|
||||
this.context_menu.take();
|
||||
cx.notify();
|
||||
});
|
||||
|
||||
self.context_menu = Some((context_menu, position, subscription));
|
||||
}
|
||||
|
||||
fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
|
||||
|
@ -621,7 +632,6 @@ impl Render for TerminalView {
|
|||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
let terminal_handle = self.terminal.clone();
|
||||
let this_view = cx.view().clone();
|
||||
|
||||
let self_id = cx.entity_id();
|
||||
let focused = self.focus_handle.is_focused(cx);
|
||||
|
@ -629,43 +639,41 @@ impl Render for TerminalView {
|
|||
div()
|
||||
.size_full()
|
||||
.relative()
|
||||
.child(
|
||||
div()
|
||||
.z_index(0)
|
||||
.absolute()
|
||||
.size_full()
|
||||
.on_key_down(cx.listener(Self::key_down))
|
||||
.on_action(cx.listener(TerminalView::send_text))
|
||||
.on_action(cx.listener(TerminalView::send_keystroke))
|
||||
.on_action(cx.listener(TerminalView::copy))
|
||||
.on_action(cx.listener(TerminalView::paste))
|
||||
.on_action(cx.listener(TerminalView::clear))
|
||||
.on_action(cx.listener(TerminalView::show_character_palette))
|
||||
.on_action(cx.listener(TerminalView::select_all))
|
||||
.child(TerminalElement::new(
|
||||
terminal_handle,
|
||||
this_view,
|
||||
self.focus_handle.clone(),
|
||||
focused,
|
||||
self.should_show_cursor(focused, cx),
|
||||
self.can_navigate_to_selected_word,
|
||||
))
|
||||
.on_mouse_down(
|
||||
MouseButton::Right,
|
||||
cx.listener(|this, event: &MouseDownEvent, cx| {
|
||||
this.deploy_context_menu(event.position, cx);
|
||||
cx.notify();
|
||||
}),
|
||||
),
|
||||
)
|
||||
.children(
|
||||
self.context_menu
|
||||
.clone()
|
||||
.map(|context_menu| div().z_index(1).absolute().child(context_menu)),
|
||||
)
|
||||
.track_focus(&self.focus_handle)
|
||||
.key_context(self.dispatch_context(cx))
|
||||
.on_action(cx.listener(TerminalView::send_text))
|
||||
.on_action(cx.listener(TerminalView::send_keystroke))
|
||||
.on_action(cx.listener(TerminalView::copy))
|
||||
.on_action(cx.listener(TerminalView::paste))
|
||||
.on_action(cx.listener(TerminalView::clear))
|
||||
.on_action(cx.listener(TerminalView::show_character_palette))
|
||||
.on_action(cx.listener(TerminalView::select_all))
|
||||
.on_focus_in(cx.listener(Self::focus_in))
|
||||
.on_focus_out(cx.listener(Self::focus_out))
|
||||
.on_key_down(cx.listener(Self::key_down))
|
||||
.on_mouse_down(
|
||||
MouseButton::Right,
|
||||
cx.listener(|this, event: &MouseDownEvent, cx| {
|
||||
this.deploy_context_menu(event.position, cx);
|
||||
cx.notify();
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
// TODO: Oddly this wrapper div is needed for TerminalElement to not steal events from the context menu
|
||||
div().size_full().child(TerminalElement::new(
|
||||
terminal_handle,
|
||||
self.focus_handle.clone(),
|
||||
focused,
|
||||
self.should_show_cursor(focused, cx),
|
||||
self.can_navigate_to_selected_word,
|
||||
)),
|
||||
)
|
||||
.children(self.context_menu.as_ref().map(|(menu, positon, _)| {
|
||||
overlay()
|
||||
.position(*positon)
|
||||
.anchor(gpui::AnchorCorner::TopLeft)
|
||||
.child(menu.clone())
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -239,7 +239,6 @@ impl Render for ContextMenu {
|
|||
action,
|
||||
} => {
|
||||
let handler = handler.clone();
|
||||
let dismiss = cx.listener(|_, _, cx| cx.emit(DismissEvent));
|
||||
|
||||
let label_element = if let Some(icon) = icon {
|
||||
h_stack()
|
||||
|
@ -263,10 +262,7 @@ impl Render for ContextMenu {
|
|||
})),
|
||||
)
|
||||
.selected(Some(ix) == self.selected_index)
|
||||
.on_click(move |event, cx| {
|
||||
handler(cx);
|
||||
dismiss(event, cx)
|
||||
})
|
||||
.on_click(move |_, cx| handler(cx))
|
||||
.into_any_element()
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue