debugger: Improve focus states (#29469)
Closes #ISSUE Release Notes: - N/A *or* Added/Fixed/Improved ...
This commit is contained in:
parent
3fdbc3090d
commit
1e47dfce79
4 changed files with 34 additions and 13 deletions
|
@ -54,7 +54,7 @@ pub struct RunningState {
|
||||||
loaded_sources_list: Entity<LoadedSourceList>,
|
loaded_sources_list: Entity<LoadedSourceList>,
|
||||||
pub debug_terminal: Entity<DebugTerminal>,
|
pub debug_terminal: Entity<DebugTerminal>,
|
||||||
module_list: Entity<module_list::ModuleList>,
|
module_list: Entity<module_list::ModuleList>,
|
||||||
_console: Entity<Console>,
|
console: Entity<Console>,
|
||||||
breakpoint_list: Entity<BreakpointList>,
|
breakpoint_list: Entity<BreakpointList>,
|
||||||
panes: PaneGroup,
|
panes: PaneGroup,
|
||||||
active_pane: Option<Entity<Pane>>,
|
active_pane: Option<Entity<Pane>>,
|
||||||
|
@ -171,9 +171,10 @@ impl Render for SubView {
|
||||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
v_flex()
|
v_flex()
|
||||||
.size_full()
|
.size_full()
|
||||||
|
// Add border uncoditionally to prevent layout shifts on focus changes.
|
||||||
|
.border_1()
|
||||||
.when(self.pane_focus_handle.contains_focused(window, cx), |el| {
|
.when(self.pane_focus_handle.contains_focused(window, cx), |el| {
|
||||||
// TODO better way of showing focus?
|
el.border_color(cx.theme().colors().pane_focused_border)
|
||||||
el.border_1().border_color(gpui::red())
|
|
||||||
})
|
})
|
||||||
.child(self.inner.clone())
|
.child(self.inner.clone())
|
||||||
}
|
}
|
||||||
|
@ -315,12 +316,12 @@ pub(crate) fn new_debugger_pane(
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.bg(cx.theme().colors().tab_bar_background)
|
.bg(cx.theme().colors().tab_bar_background)
|
||||||
.border_b_1()
|
.border_b_1()
|
||||||
|
.px_2()
|
||||||
.border_color(cx.theme().colors().border)
|
.border_color(cx.theme().colors().border)
|
||||||
.track_focus(&focus_handle)
|
.track_focus(&focus_handle)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
.w_full()
|
.w_full()
|
||||||
.px_2()
|
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.h(Tab::container_height(cx))
|
.h(Tab::container_height(cx))
|
||||||
.drag_over::<DraggedTab>(|bar, _, _, cx| {
|
.drag_over::<DraggedTab>(|bar, _, _, cx| {
|
||||||
|
@ -336,6 +337,7 @@ pub(crate) fn new_debugger_pane(
|
||||||
let selected = active_pane_item
|
let selected = active_pane_item
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |active| active.item_id() == item.item_id());
|
.map_or(false, |active| active.item_id() == item.item_id());
|
||||||
|
let deemphasized = !pane.has_focus(window, cx);
|
||||||
let item_ = item.boxed_clone();
|
let item_ = item.boxed_clone();
|
||||||
div()
|
div()
|
||||||
.id(SharedString::from(format!(
|
.id(SharedString::from(format!(
|
||||||
|
@ -346,10 +348,17 @@ pub(crate) fn new_debugger_pane(
|
||||||
.rounded_md()
|
.rounded_md()
|
||||||
.cursor_pointer()
|
.cursor_pointer()
|
||||||
.map(|this| {
|
.map(|this| {
|
||||||
|
let theme = cx.theme();
|
||||||
if selected {
|
if selected {
|
||||||
this.bg(cx.theme().colors().tab_active_background)
|
let color = theme.colors().tab_active_background;
|
||||||
|
let color = if deemphasized {
|
||||||
|
color.opacity(0.5)
|
||||||
|
} else {
|
||||||
|
color
|
||||||
|
};
|
||||||
|
this.bg(color)
|
||||||
} else {
|
} else {
|
||||||
let hover_color = cx.theme().colors().element_hover;
|
let hover_color = theme.colors().element_hover;
|
||||||
this.hover(|style| style.bg(hover_color))
|
this.hover(|style| style.bg(hover_color))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -362,6 +371,7 @@ pub(crate) fn new_debugger_pane(
|
||||||
.child(item.tab_content(
|
.child(item.tab_content(
|
||||||
TabContentParams {
|
TabContentParams {
|
||||||
selected,
|
selected,
|
||||||
|
deemphasized,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
window,
|
window,
|
||||||
|
@ -395,7 +405,7 @@ pub(crate) fn new_debugger_pane(
|
||||||
IconName::Maximize
|
IconName::Maximize
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.icon_size(IconSize::Small)
|
.icon_size(IconSize::XSmall)
|
||||||
.on_click(cx.listener(move |pane, _, window, cx| {
|
.on_click(cx.listener(move |pane, _, window, cx| {
|
||||||
pane.toggle_zoom(&workspace::ToggleZoom, window, cx);
|
pane.toggle_zoom(&workspace::ToggleZoom, window, cx);
|
||||||
}))
|
}))
|
||||||
|
@ -585,7 +595,7 @@ impl RunningState {
|
||||||
panes,
|
panes,
|
||||||
active_pane: None,
|
active_pane: None,
|
||||||
module_list,
|
module_list,
|
||||||
_console: console,
|
console,
|
||||||
breakpoint_list,
|
breakpoint_list,
|
||||||
loaded_sources_list: loaded_source_list,
|
loaded_sources_list: loaded_source_list,
|
||||||
pane_close_subscriptions,
|
pane_close_subscriptions,
|
||||||
|
@ -629,11 +639,11 @@ impl RunningState {
|
||||||
) -> Box<dyn ItemHandle> {
|
) -> Box<dyn ItemHandle> {
|
||||||
match item_kind {
|
match item_kind {
|
||||||
DebuggerPaneItem::Console => {
|
DebuggerPaneItem::Console => {
|
||||||
let weak_console = self._console.clone().downgrade();
|
let weak_console = self.console.clone().downgrade();
|
||||||
|
|
||||||
Box::new(SubView::new(
|
Box::new(SubView::new(
|
||||||
self._console.focus_handle(cx),
|
self.console.focus_handle(cx),
|
||||||
self._console.clone().into(),
|
self.console.clone().into(),
|
||||||
item_kind,
|
item_kind,
|
||||||
Some(Box::new(move |cx| {
|
Some(Box::new(move |cx| {
|
||||||
weak_console
|
weak_console
|
||||||
|
@ -862,7 +872,7 @@ impl RunningState {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn console(&self) -> &Entity<Console> {
|
pub fn console(&self) -> &Entity<Console> {
|
||||||
&self._console
|
&self.console
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -395,6 +395,7 @@ impl PickerDelegate for TabSwitcherDelegate {
|
||||||
detail: Some(tab_match.detail),
|
detail: Some(tab_match.detail),
|
||||||
selected: true,
|
selected: true,
|
||||||
preview: tab_match.preview,
|
preview: tab_match.preview,
|
||||||
|
deemphasized: false,
|
||||||
};
|
};
|
||||||
let label = tab_match.item.tab_content(params, window, cx);
|
let label = tab_match.item.tab_content(params, window, cx);
|
||||||
|
|
||||||
|
|
|
@ -214,12 +214,20 @@ pub struct TabContentParams {
|
||||||
pub detail: Option<usize>,
|
pub detail: Option<usize>,
|
||||||
pub selected: bool,
|
pub selected: bool,
|
||||||
pub preview: bool,
|
pub preview: bool,
|
||||||
|
/// Tab content should be deemphasized when active pane does not have focus.
|
||||||
|
pub deemphasized: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TabContentParams {
|
impl TabContentParams {
|
||||||
/// Returns the text color to be used for the tab content.
|
/// Returns the text color to be used for the tab content.
|
||||||
pub fn text_color(&self) -> Color {
|
pub fn text_color(&self) -> Color {
|
||||||
if self.selected {
|
if self.deemphasized {
|
||||||
|
if self.selected {
|
||||||
|
Color::Muted
|
||||||
|
} else {
|
||||||
|
Color::Hidden
|
||||||
|
}
|
||||||
|
} else if self.selected {
|
||||||
Color::Default
|
Color::Default
|
||||||
} else {
|
} else {
|
||||||
Color::Muted
|
Color::Muted
|
||||||
|
|
|
@ -2147,6 +2147,7 @@ impl Pane {
|
||||||
detail: Some(detail),
|
detail: Some(detail),
|
||||||
selected: is_active,
|
selected: is_active,
|
||||||
preview: is_preview,
|
preview: is_preview,
|
||||||
|
deemphasized: !self.has_focus(window, cx),
|
||||||
},
|
},
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
|
@ -3687,6 +3688,7 @@ impl Render for DraggedTab {
|
||||||
detail: Some(self.detail),
|
detail: Some(self.detail),
|
||||||
selected: false,
|
selected: false,
|
||||||
preview: false,
|
preview: false,
|
||||||
|
deemphasized: false,
|
||||||
},
|
},
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue