T07b navigation places: nav item and group, navigation menu, back and forward history, table of contents with anchors, go to line; measuring canvases pinned to their parent
This commit is contained in:
21 files changed
+1548
-56
No files matched your search
+49
-40
@@ -1,17 +1,57 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use gpui::{
|
||||
App, ElementId, InteractiveElement, IntoElement, ParentElement, RenderOnce, SharedString,
|
||||
Styled, Window, div,
|
||||
App, Div, ElementId, InteractiveElement, IntoElement, ParentElement, RenderOnce, SharedString,
|
||||
Stateful, Styled, Window, div,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
forms::{Choice, Listing, listing},
|
||||
forms::{Choice, Listing, OnValue, listing},
|
||||
primitives::{Icon, IconName, tab_stop},
|
||||
theme::{ActiveTheme, ControlSize, IconSize, Radius},
|
||||
};
|
||||
|
||||
type OnValue = Rc<dyn Fn(&SharedString, &mut Window, &mut App)>;
|
||||
/// A small icon button that lists `rows`; picking one runs `on_pick`.
|
||||
pub(crate) fn list_button(
|
||||
id: &ElementId,
|
||||
icon: IconName,
|
||||
rows: Rc<Vec<Choice>>,
|
||||
selected: Option<&SharedString>,
|
||||
on_pick: impl Fn(&SharedString, &mut Window, &mut App) + 'static,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Stateful<Div> {
|
||||
let focus = tab_stop((id.clone(), "focus").into(), true, window, cx);
|
||||
let focused = focus.is_focused(window);
|
||||
let theme = cx.theme();
|
||||
let colors = &theme.colors;
|
||||
let trigger = div()
|
||||
.id((id.clone(), "button"))
|
||||
.track_focus(&focus)
|
||||
.relative()
|
||||
.flex()
|
||||
.flex_none()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.size(theme.control_height(ControlSize::Sm))
|
||||
.rounded(theme.radius(Radius::Md))
|
||||
.border_1()
|
||||
.border_color(if focused {
|
||||
colors.focus
|
||||
} else {
|
||||
gpui::transparent_black()
|
||||
})
|
||||
.cursor_pointer()
|
||||
.hover(|style| style.bg(colors.hover))
|
||||
.child(Icon::new(icon).size(IconSize::Sm).color(colors.fg_muted));
|
||||
let list = Listing {
|
||||
id,
|
||||
rows,
|
||||
selected,
|
||||
focused,
|
||||
};
|
||||
listing(list, trigger, on_pick, window, cx)
|
||||
}
|
||||
|
||||
/// A button that lists every tab, for a strip too narrow to show them all.
|
||||
#[derive(IntoElement)]
|
||||
@@ -53,43 +93,12 @@ impl RenderOnce for TabOverflowMenu {
|
||||
"tab overflow menu {:?} has no tabs",
|
||||
self.id
|
||||
);
|
||||
let focus = tab_stop((self.id.clone(), "focus").into(), true, window, cx);
|
||||
let focused = focus.is_focused(window);
|
||||
let theme = cx.theme();
|
||||
let colors = &theme.colors;
|
||||
let trigger = div()
|
||||
.id((self.id.clone(), "button"))
|
||||
.track_focus(&focus)
|
||||
.relative()
|
||||
.flex()
|
||||
.flex_none()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.size(theme.control_height(ControlSize::Sm))
|
||||
.rounded(theme.radius(Radius::Md))
|
||||
.border_1()
|
||||
.border_color(if focused {
|
||||
colors.focus
|
||||
} else {
|
||||
gpui::transparent_black()
|
||||
})
|
||||
.cursor_pointer()
|
||||
.hover(|style| style.bg(colors.hover))
|
||||
.child(
|
||||
Icon::new(IconName::ChevronDown)
|
||||
.size(IconSize::Sm)
|
||||
.color(colors.fg_muted),
|
||||
);
|
||||
let (id, on_select) = (self.id.clone(), self.on_select);
|
||||
let list = Listing {
|
||||
id: &self.id,
|
||||
rows: Rc::new(self.tabs),
|
||||
selected: self.selected.as_ref(),
|
||||
focused,
|
||||
};
|
||||
listing(
|
||||
list,
|
||||
trigger,
|
||||
list_button(
|
||||
&self.id,
|
||||
IconName::ChevronDown,
|
||||
Rc::new(self.tabs),
|
||||
self.selected.as_ref(),
|
||||
move |value, window, cx| {
|
||||
log::info!("tab overflow menu {id:?}: {value}");
|
||||
if let Some(on_select) = &on_select {
|
||||
|
||||
Reference in new issue
Block a user