Move navigation buttons to the tab bar.
Co-authored-by: Kyle <kyle@zed.dev>
This commit is contained in:
parent
b4f6d6eadc
commit
7d83d15bf3
4 changed files with 126 additions and 69 deletions
|
@ -295,6 +295,7 @@ pub struct TabBar {
|
||||||
pub inactive_pane: TabStyles,
|
pub inactive_pane: TabStyles,
|
||||||
pub dragged_tab: Tab,
|
pub dragged_tab: Tab,
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
|
pub nav_button: Interactive<IconButton>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TabBar {
|
impl TabBar {
|
||||||
|
@ -359,7 +360,6 @@ pub struct Toolbar {
|
||||||
pub container: ContainerStyle,
|
pub container: ContainerStyle,
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
pub item_spacing: f32,
|
pub item_spacing: f32,
|
||||||
pub nav_button: Interactive<IconButton>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
#[derive(Clone, Deserialize, Default, JsonSchema)]
|
||||||
|
|
|
@ -222,6 +222,56 @@ impl TabBarContextMenu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn nav_button<A: Action, F: 'static + Fn(&mut Pane, &mut ViewContext<Pane>)>(
|
||||||
|
svg_path: &'static str,
|
||||||
|
style: theme::Interactive<theme::IconButton>,
|
||||||
|
nav_button_height: f32,
|
||||||
|
tooltip_style: TooltipStyle,
|
||||||
|
enabled: bool,
|
||||||
|
on_click: F,
|
||||||
|
tooltip_action: A,
|
||||||
|
action_name: &str,
|
||||||
|
cx: &mut ViewContext<Pane>,
|
||||||
|
) -> AnyElement<Pane> {
|
||||||
|
MouseEventHandler::<A, _>::new(0, cx, |state, _| {
|
||||||
|
let style = if enabled {
|
||||||
|
style.style_for(state)
|
||||||
|
} else {
|
||||||
|
style.disabled_style()
|
||||||
|
};
|
||||||
|
Svg::new(svg_path)
|
||||||
|
.with_color(style.color)
|
||||||
|
.constrained()
|
||||||
|
.with_width(style.icon_width)
|
||||||
|
.aligned()
|
||||||
|
.contained()
|
||||||
|
.with_style(style.container)
|
||||||
|
.constrained()
|
||||||
|
.with_width(style.button_width)
|
||||||
|
.with_height(nav_button_height)
|
||||||
|
.aligned()
|
||||||
|
.top()
|
||||||
|
})
|
||||||
|
.with_cursor_style(if enabled {
|
||||||
|
CursorStyle::PointingHand
|
||||||
|
} else {
|
||||||
|
CursorStyle::default()
|
||||||
|
})
|
||||||
|
.on_click(MouseButton::Left, move |_, toolbar, cx| {
|
||||||
|
on_click(toolbar, cx)
|
||||||
|
})
|
||||||
|
.with_tooltip::<A>(
|
||||||
|
0,
|
||||||
|
action_name.to_string(),
|
||||||
|
Some(Box::new(tooltip_action)),
|
||||||
|
tooltip_style,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.contained()
|
||||||
|
.into_any_named("nav button")
|
||||||
|
}
|
||||||
|
|
||||||
impl Pane {
|
impl Pane {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
workspace: WeakViewHandle<Workspace>,
|
workspace: WeakViewHandle<Workspace>,
|
||||||
|
@ -236,6 +286,11 @@ impl Pane {
|
||||||
context_menu.update(cx, |menu, _| {
|
context_menu.update(cx, |menu, _| {
|
||||||
menu.set_position_mode(OverlayPositionMode::Local)
|
menu.set_position_mode(OverlayPositionMode::Local)
|
||||||
});
|
});
|
||||||
|
let theme = theme::current(cx).workspace.tab_bar.clone();
|
||||||
|
let mut border_for_nav_buttons = theme.tab_style(false, false).container.border.clone();
|
||||||
|
border_for_nav_buttons.left = false;
|
||||||
|
let nav_button_height = theme.height;
|
||||||
|
let button_style = theme.nav_button;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
items: Vec::new(),
|
items: Vec::new(),
|
||||||
|
@ -265,8 +320,59 @@ impl Pane {
|
||||||
has_focus: false,
|
has_focus: false,
|
||||||
can_drop: Rc::new(|_, _| true),
|
can_drop: Rc::new(|_, _| true),
|
||||||
can_split: true,
|
can_split: true,
|
||||||
render_tab_bar_buttons: Rc::new(|pane, cx| {
|
render_tab_bar_buttons: Rc::new(move |pane, cx| {
|
||||||
|
let tooltip_style = theme::current(cx).tooltip.clone();
|
||||||
Flex::row()
|
Flex::row()
|
||||||
|
.with_child(nav_button(
|
||||||
|
"icons/arrow_left_16.svg",
|
||||||
|
button_style.clone(),
|
||||||
|
nav_button_height,
|
||||||
|
tooltip_style.clone(),
|
||||||
|
pane.can_navigate_backward(),
|
||||||
|
{
|
||||||
|
move |pane, cx| {
|
||||||
|
if let Some(workspace) = pane.workspace.upgrade(cx) {
|
||||||
|
let pane = cx.weak_handle();
|
||||||
|
cx.window_context().defer(move |cx| {
|
||||||
|
workspace.update(cx, |workspace, cx| {
|
||||||
|
workspace.go_back(pane, cx).detach_and_log_err(cx)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
super::GoBack,
|
||||||
|
"Go Back",
|
||||||
|
cx,
|
||||||
|
))
|
||||||
|
.with_child(
|
||||||
|
nav_button(
|
||||||
|
"icons/arrow_right_16.svg",
|
||||||
|
button_style.clone(),
|
||||||
|
nav_button_height,
|
||||||
|
tooltip_style,
|
||||||
|
pane.can_navigate_forward(),
|
||||||
|
{
|
||||||
|
move |pane, cx| {
|
||||||
|
if let Some(workspace) = pane.workspace.upgrade(cx) {
|
||||||
|
let pane = cx.weak_handle();
|
||||||
|
cx.window_context().defer(move |cx| {
|
||||||
|
workspace.update(cx, |workspace, cx| {
|
||||||
|
workspace
|
||||||
|
.go_forward(pane, cx)
|
||||||
|
.detach_and_log_err(cx)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
super::GoForward,
|
||||||
|
"Go Forward",
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
.contained()
|
||||||
|
.with_border(border_for_nav_buttons),
|
||||||
|
)
|
||||||
// New menu
|
// New menu
|
||||||
.with_child(Self::render_tab_bar_button(
|
.with_child(Self::render_tab_bar_button(
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -118,76 +118,10 @@ impl View for Toolbar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let pane = self.pane.clone();
|
|
||||||
let mut enable_go_backward = false;
|
|
||||||
let mut enable_go_forward = false;
|
|
||||||
if let Some(pane) = pane.and_then(|pane| pane.upgrade(cx)) {
|
|
||||||
let pane = pane.read(cx);
|
|
||||||
enable_go_backward = pane.can_navigate_backward();
|
|
||||||
enable_go_forward = pane.can_navigate_forward();
|
|
||||||
}
|
|
||||||
|
|
||||||
let container_style = theme.container;
|
let container_style = theme.container;
|
||||||
let height = theme.height * primary_items_row_count as f32;
|
let height = theme.height * primary_items_row_count as f32;
|
||||||
let nav_button_height = theme.height;
|
|
||||||
let button_style = theme.nav_button;
|
|
||||||
let tooltip_style = theme::current(cx).tooltip.clone();
|
|
||||||
|
|
||||||
let mut primary_items = Flex::row();
|
let mut primary_items = Flex::row();
|
||||||
if self.can_navigate {
|
|
||||||
primary_items.add_child(nav_button(
|
|
||||||
"icons/arrow_left_16.svg",
|
|
||||||
button_style,
|
|
||||||
nav_button_height,
|
|
||||||
tooltip_style.clone(),
|
|
||||||
enable_go_backward,
|
|
||||||
spacing,
|
|
||||||
{
|
|
||||||
move |toolbar, cx| {
|
|
||||||
if let Some(pane) = toolbar.pane.as_ref().and_then(|pane| pane.upgrade(cx))
|
|
||||||
{
|
|
||||||
if let Some(workspace) = pane.read(cx).workspace().upgrade(cx) {
|
|
||||||
let pane = pane.downgrade();
|
|
||||||
cx.window_context().defer(move |cx| {
|
|
||||||
workspace.update(cx, |workspace, cx| {
|
|
||||||
workspace.go_back(pane, cx).detach_and_log_err(cx);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
super::GoBack,
|
|
||||||
"Go Back",
|
|
||||||
cx,
|
|
||||||
));
|
|
||||||
primary_items.add_child(nav_button(
|
|
||||||
"icons/arrow_right_16.svg",
|
|
||||||
button_style,
|
|
||||||
nav_button_height,
|
|
||||||
tooltip_style,
|
|
||||||
enable_go_forward,
|
|
||||||
spacing,
|
|
||||||
{
|
|
||||||
move |toolbar, cx| {
|
|
||||||
if let Some(pane) = toolbar.pane.as_ref().and_then(|pane| pane.upgrade(cx))
|
|
||||||
{
|
|
||||||
if let Some(workspace) = pane.read(cx).workspace().upgrade(cx) {
|
|
||||||
let pane = pane.downgrade();
|
|
||||||
cx.window_context().defer(move |cx| {
|
|
||||||
workspace.update(cx, |workspace, cx| {
|
|
||||||
workspace.go_forward(pane, cx).detach_and_log_err(cx);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
super::GoForward,
|
|
||||||
"Go Forward",
|
|
||||||
cx,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
primary_items.extend(primary_left_items);
|
primary_items.extend(primary_left_items);
|
||||||
primary_items.extend(primary_right_items);
|
primary_items.extend(primary_right_items);
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,23 @@ export default function tab_bar(): any {
|
||||||
bottom: false,
|
bottom: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
const nav_button = interactive({
|
||||||
|
base: {
|
||||||
|
color: foreground(theme.highest, "on"),
|
||||||
|
icon_width: 12,
|
||||||
|
button_width: 24,
|
||||||
|
corner_radius: 6,
|
||||||
|
},
|
||||||
|
state: {
|
||||||
|
hovered: {
|
||||||
|
color: foreground(theme.highest, "on", "hovered"),
|
||||||
|
background: background(theme.highest, "on", "hovered"),
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
color: foreground(theme.highest, "on", "disabled"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
const dragged_tab = {
|
const dragged_tab = {
|
||||||
...active_pane_active_tab,
|
...active_pane_active_tab,
|
||||||
background: with_opacity(tab.background, 0.9),
|
background: with_opacity(tab.background, 0.9),
|
||||||
|
@ -141,5 +157,6 @@ export default function tab_bar(): any {
|
||||||
right: false,
|
right: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
nav_button: nav_button
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue