add app layout shell to the layout crate
This commit is contained in:
@@ -7,8 +7,8 @@ description = "Live preview of every component against the resolved system theme
|
||||
[dependencies]
|
||||
gpui = { workspace = true }
|
||||
gpui_platform = { workspace = true }
|
||||
gpui-native-core = { workspace = true }
|
||||
gpui-native-data = { workspace = true }
|
||||
gpui-native-core = { workspace = true, features = ["full"] }
|
||||
gpui-native-data = { workspace = true, features = ["full"] }
|
||||
gpui-native-layout = { workspace = true }
|
||||
gpui-native-icons = { workspace = true }
|
||||
gpui-native-theme = { workspace = true }
|
||||
|
||||
@@ -34,6 +34,7 @@ use gpui_native_data::sidebar::{Sidebar, SidebarEntry};
|
||||
use gpui_native_data::tabs::{Tab, Tabs};
|
||||
use gpui_native_data::tree::{Tree, TreeItem};
|
||||
use gpui_native_icons::{IconAssets, IconRole, icon};
|
||||
use gpui_native_layout::app_layout::{AppLayout, LayoutState};
|
||||
use gpui_native_layout::resize_handle::ResizeHandle;
|
||||
use gpui_native_theme::{ActiveTheme as _, Size, Theme};
|
||||
use gpui_platform::application;
|
||||
@@ -49,6 +50,8 @@ struct Gallery {
|
||||
password_state: Entity<InputState>,
|
||||
notes_state: Entity<InputState>,
|
||||
split_width: Pixels,
|
||||
layout_state: Entity<LayoutState>,
|
||||
shell_selection: Option<usize>,
|
||||
popover_open: bool,
|
||||
menu_open: bool,
|
||||
strategy: Option<Strategy>,
|
||||
@@ -144,6 +147,82 @@ fn tree_paths(nodes: &[GalleryNode]) -> Vec<Vec<usize>> {
|
||||
paths
|
||||
}
|
||||
|
||||
impl Gallery {
|
||||
/// The app shell demo: sidebars around a center region, toggles in the
|
||||
/// center demonstrating the `LayoutState` API.
|
||||
fn render_app_shell(&self, gallery: &Entity<Self>, cx: &App) -> impl IntoElement + use<> {
|
||||
let colors = cx.theme().colors;
|
||||
let state = self.layout_state.clone();
|
||||
let state_for_toggle = state.clone();
|
||||
|
||||
let toggle = |side: &'static str| {
|
||||
let state = state_for_toggle.clone();
|
||||
Button::new(SharedString::from(format!("gallery-shell-toggle-{side}")))
|
||||
.label(format!("Toggle {}", side))
|
||||
.variant(ButtonVariant::Secondary)
|
||||
.small()
|
||||
.on_click(move |_, _, cx| {
|
||||
state.update(cx, |state, cx| match side {
|
||||
"left" => {
|
||||
let visible = !state.is_left_sidebar_visible();
|
||||
state.set_left_sidebar_visible(visible, cx);
|
||||
}
|
||||
_ => {
|
||||
let visible = !state.is_right_sidebar_visible();
|
||||
state.set_right_sidebar_visible(visible, cx);
|
||||
}
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
let left_sidebar = Sidebar::new("gallery-shell-sidebar")
|
||||
.selected(self.shell_selection)
|
||||
.entries(|_, _| {
|
||||
vec![
|
||||
SidebarEntry::header("Repositories"),
|
||||
SidebarEntry::row("gpui-native-kit").icon(IconRole::Folder),
|
||||
SidebarEntry::row("signed").icon(IconRole::Folder),
|
||||
SidebarEntry::header("Explore"),
|
||||
SidebarEntry::row("Popular"),
|
||||
SidebarEntry::row("Recent"),
|
||||
]
|
||||
})
|
||||
.on_change({
|
||||
let gallery = gallery.clone();
|
||||
move |selection, _, cx| {
|
||||
gallery.update(cx, |gallery, _| gallery.shell_selection = selection);
|
||||
}
|
||||
});
|
||||
|
||||
let right_sidebar = v_flex()
|
||||
.gap_1()
|
||||
.p_2()
|
||||
.child("Details")
|
||||
.child("Signed by the author")
|
||||
.text_sm()
|
||||
.text_color(colors.muted_foreground);
|
||||
|
||||
let center = v_flex()
|
||||
.gap_2()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.size_full()
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(toggle("left"))
|
||||
.child(toggle("right")),
|
||||
)
|
||||
.child("Center \u{2014} the dock lands here (L3)")
|
||||
.text_color(colors.muted_foreground);
|
||||
|
||||
AppLayout::new("gallery-shell", state)
|
||||
.left_sidebar(left_sidebar)
|
||||
.center(center)
|
||||
.right_sidebar(right_sidebar)
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Gallery {
|
||||
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let theme = cx.theme();
|
||||
@@ -448,6 +527,41 @@ impl Render for Gallery {
|
||||
)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_2()
|
||||
.child(section_label(
|
||||
"layout · app shell \u{2014} NSWindow sidebar + inspector, WinUI SplitView shell",
|
||||
colors,
|
||||
))
|
||||
.child(
|
||||
div()
|
||||
.h(px(320.))
|
||||
.rounded(radius.control)
|
||||
.border_1()
|
||||
.border_color(colors.border)
|
||||
.overflow_hidden()
|
||||
.child(self.render_app_shell(&gallery, cx)),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(colors.muted_foreground)
|
||||
.child(format!(
|
||||
"left: {} · right: {} \u{2014} buttons toggle, seams resize",
|
||||
if self.layout_state.read(cx).is_left_sidebar_visible() {
|
||||
"on"
|
||||
} else {
|
||||
"off"
|
||||
},
|
||||
if self.layout_state.read(cx).is_right_sidebar_visible() {
|
||||
"on"
|
||||
} else {
|
||||
"off"
|
||||
},
|
||||
)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_2()
|
||||
@@ -1538,6 +1652,7 @@ fn main() {
|
||||
password_state.update(cx, |state, cx| state.set_password(true, cx));
|
||||
let notes_state = InputState::new(cx);
|
||||
notes_state.update(cx, |state, cx| state.set_multiline(true, cx));
|
||||
let layout_state = LayoutState::new(cx);
|
||||
let bounds = Bounds::centered(None, size(px(720.0), px(560.0)), cx);
|
||||
if let Err(err) = cx.open_window(
|
||||
WindowOptions {
|
||||
@@ -1577,6 +1692,8 @@ fn main() {
|
||||
password_state,
|
||||
notes_state,
|
||||
split_width: px(200.),
|
||||
layout_state,
|
||||
shell_selection: None,
|
||||
popover_open: false,
|
||||
menu_open: false,
|
||||
strategy: Some(Strategy::Curated),
|
||||
|
||||
Reference in New Issue
Block a user