debugger_ui: Preview thread state when using the dropdown (#28778)
This PR changes the thread list dropdown menu in the debugger UI to eagerly preview the state of a thread when selecting it, instead of waiting until confirming the selection. Release Notes: - N/A
This commit is contained in:
parent
90dec1d451
commit
42c3f4e7cf
3 changed files with 104 additions and 47 deletions
|
@ -768,7 +768,7 @@ impl RunningState {
|
||||||
DropdownMenu::new(
|
DropdownMenu::new(
|
||||||
("thread-list", self.session_id.0),
|
("thread-list", self.session_id.0),
|
||||||
selected_thread_name,
|
selected_thread_name,
|
||||||
ContextMenu::build(window, cx, move |mut this, _, _| {
|
ContextMenu::build_eager(window, cx, move |mut this, _, _| {
|
||||||
for (thread, _) in threads {
|
for (thread, _) in threads {
|
||||||
let state = state.clone();
|
let state = state.clone();
|
||||||
let thread_id = thread.id;
|
let thread_id = thread.id;
|
||||||
|
|
|
@ -1421,7 +1421,10 @@ impl Render for LspLogToolbarItemView {
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
ContextMenu::build(window, cx, |mut menu, _, _| {
|
ContextMenu::build(
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
|mut menu, window, cx| {
|
||||||
let log_view = log_view.clone();
|
let log_view = log_view.clone();
|
||||||
|
|
||||||
for (option, label) in [
|
for (option, label) in [
|
||||||
|
@ -1444,12 +1447,13 @@ impl Render for LspLogToolbarItemView {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if option == trace_level {
|
if option == trace_level {
|
||||||
menu.select_last();
|
menu.select_last(window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu
|
menu
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -1480,7 +1484,10 @@ impl Render for LspLogToolbarItemView {
|
||||||
})
|
})
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
ContextMenu::build(window, cx, |mut menu, _, _| {
|
ContextMenu::build(
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
|mut menu, window, cx| {
|
||||||
let log_view = log_view.clone();
|
let log_view = log_view.clone();
|
||||||
|
|
||||||
for (option, label) in [
|
for (option, label) in [
|
||||||
|
@ -1504,12 +1511,13 @@ impl Render for LspLogToolbarItemView {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if option == log_level {
|
if option == log_level {
|
||||||
menu.select_last();
|
menu.select_last(window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu
|
menu
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -135,6 +135,7 @@ pub struct ContextMenu {
|
||||||
clicked: bool,
|
clicked: bool,
|
||||||
_on_blur_subscription: Subscription,
|
_on_blur_subscription: Subscription,
|
||||||
keep_open_on_confirm: bool,
|
keep_open_on_confirm: bool,
|
||||||
|
eager: bool,
|
||||||
documentation_aside: Option<(usize, Rc<dyn Fn(&mut App) -> AnyElement>)>,
|
documentation_aside: Option<(usize, Rc<dyn Fn(&mut App) -> AnyElement>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +174,7 @@ impl ContextMenu {
|
||||||
clicked: false,
|
clicked: false,
|
||||||
_on_blur_subscription,
|
_on_blur_subscription,
|
||||||
keep_open_on_confirm: false,
|
keep_open_on_confirm: false,
|
||||||
|
eager: false,
|
||||||
documentation_aside: None,
|
documentation_aside: None,
|
||||||
},
|
},
|
||||||
window,
|
window,
|
||||||
|
@ -212,6 +214,40 @@ impl ContextMenu {
|
||||||
clicked: false,
|
clicked: false,
|
||||||
_on_blur_subscription,
|
_on_blur_subscription,
|
||||||
keep_open_on_confirm: true,
|
keep_open_on_confirm: true,
|
||||||
|
eager: false,
|
||||||
|
documentation_aside: None,
|
||||||
|
},
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_eager(
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut App,
|
||||||
|
f: impl FnOnce(Self, &mut Window, &mut Context<Self>) -> Self,
|
||||||
|
) -> Entity<Self> {
|
||||||
|
cx.new(|cx| {
|
||||||
|
let focus_handle = cx.focus_handle();
|
||||||
|
let _on_blur_subscription = cx.on_blur(
|
||||||
|
&focus_handle,
|
||||||
|
window,
|
||||||
|
|this: &mut ContextMenu, window, cx| this.cancel(&menu::Cancel, window, cx),
|
||||||
|
);
|
||||||
|
window.refresh();
|
||||||
|
f(
|
||||||
|
Self {
|
||||||
|
builder: None,
|
||||||
|
items: Default::default(),
|
||||||
|
focus_handle,
|
||||||
|
action_context: None,
|
||||||
|
selected_index: None,
|
||||||
|
delayed: false,
|
||||||
|
clicked: false,
|
||||||
|
_on_blur_subscription,
|
||||||
|
keep_open_on_confirm: false,
|
||||||
|
eager: true,
|
||||||
documentation_aside: None,
|
documentation_aside: None,
|
||||||
},
|
},
|
||||||
window,
|
window,
|
||||||
|
@ -249,6 +285,7 @@ impl ContextMenu {
|
||||||
|this: &mut ContextMenu, window, cx| this.cancel(&menu::Cancel, window, cx),
|
|this: &mut ContextMenu, window, cx| this.cancel(&menu::Cancel, window, cx),
|
||||||
),
|
),
|
||||||
keep_open_on_confirm: false,
|
keep_open_on_confirm: false,
|
||||||
|
eager: false,
|
||||||
documentation_aside: None,
|
documentation_aside: None,
|
||||||
},
|
},
|
||||||
window,
|
window,
|
||||||
|
@ -435,7 +472,10 @@ impl ContextMenu {
|
||||||
..
|
..
|
||||||
})
|
})
|
||||||
| ContextMenuItem::CustomEntry { handler, .. },
|
| ContextMenuItem::CustomEntry { handler, .. },
|
||||||
) = self.selected_index.and_then(|ix| self.items.get(ix))
|
) = self
|
||||||
|
.selected_index
|
||||||
|
.and_then(|ix| self.items.get(ix))
|
||||||
|
.filter(|_| !self.eager)
|
||||||
{
|
{
|
||||||
(handler)(context, window, cx)
|
(handler)(context, window, cx)
|
||||||
}
|
}
|
||||||
|
@ -452,24 +492,24 @@ impl ContextMenu {
|
||||||
cx.emit(DismissEvent);
|
cx.emit(DismissEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_first(&mut self, _: &SelectFirst, _: &mut Window, cx: &mut Context<Self>) {
|
fn select_first(&mut self, _: &SelectFirst, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if let Some(ix) = self.items.iter().position(|item| item.is_selectable()) {
|
if let Some(ix) = self.items.iter().position(|item| item.is_selectable()) {
|
||||||
self.select_index(ix);
|
self.select_index(ix, window, cx);
|
||||||
}
|
}
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_last(&mut self) -> Option<usize> {
|
pub fn select_last(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<usize> {
|
||||||
for (ix, item) in self.items.iter().enumerate().rev() {
|
for (ix, item) in self.items.iter().enumerate().rev() {
|
||||||
if item.is_selectable() {
|
if item.is_selectable() {
|
||||||
return self.select_index(ix);
|
return self.select_index(ix, window, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_select_last(&mut self, _: &SelectLast, _: &mut Window, cx: &mut Context<Self>) {
|
fn handle_select_last(&mut self, _: &SelectLast, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
if self.select_last().is_some() {
|
if self.select_last(window, cx).is_some() {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,7 +522,7 @@ impl ContextMenu {
|
||||||
} else {
|
} else {
|
||||||
for (ix, item) in self.items.iter().enumerate().skip(next_index) {
|
for (ix, item) in self.items.iter().enumerate().skip(next_index) {
|
||||||
if item.is_selectable() {
|
if item.is_selectable() {
|
||||||
self.select_index(ix);
|
self.select_index(ix, window, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -505,7 +545,7 @@ impl ContextMenu {
|
||||||
} else {
|
} else {
|
||||||
for (ix, item) in self.items.iter().enumerate().take(ix).rev() {
|
for (ix, item) in self.items.iter().enumerate().take(ix).rev() {
|
||||||
if item.is_selectable() {
|
if item.is_selectable() {
|
||||||
self.select_index(ix);
|
self.select_index(ix, window, cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -516,7 +556,13 @@ impl ContextMenu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_index(&mut self, ix: usize) -> Option<usize> {
|
fn select_index(
|
||||||
|
&mut self,
|
||||||
|
ix: usize,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> Option<usize> {
|
||||||
|
let context = self.action_context.as_ref();
|
||||||
self.documentation_aside = None;
|
self.documentation_aside = None;
|
||||||
let item = self.items.get(ix)?;
|
let item = self.items.get(ix)?;
|
||||||
if item.is_selectable() {
|
if item.is_selectable() {
|
||||||
|
@ -525,6 +571,9 @@ impl ContextMenu {
|
||||||
if let Some(callback) = &entry.documentation_aside {
|
if let Some(callback) = &entry.documentation_aside {
|
||||||
self.documentation_aside = Some((ix, callback.clone()));
|
self.documentation_aside = Some((ix, callback.clone()));
|
||||||
}
|
}
|
||||||
|
if self.eager && !entry.disabled {
|
||||||
|
(entry.handler)(context, window, cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(ix)
|
Some(ix)
|
||||||
|
@ -553,7 +602,7 @@ impl ContextMenu {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
self.select_index(ix);
|
self.select_index(ix, window, cx);
|
||||||
self.delayed = true;
|
self.delayed = true;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
let action = dispatched.boxed_clone();
|
let action = dispatched.boxed_clone();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue