parent
a19826af2b
commit
a176408d81
11 changed files with 203 additions and 80 deletions
|
|
@ -505,7 +505,11 @@ pub fn open_new(
|
|||
}
|
||||
|
||||
impl Render for StoryWorkspace {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let sheet_layer = Root::render_sheet_layer(window, cx);
|
||||
let dialog_layer = Root::render_dialog_layer(window, cx);
|
||||
let notification_layer = Root::render_notification_layer(window, cx);
|
||||
|
||||
div()
|
||||
.id("story-workspace")
|
||||
.on_action(cx.listener(Self::on_action_add_panel))
|
||||
|
|
@ -517,6 +521,9 @@ impl Render for StoryWorkspace {
|
|||
.flex_col()
|
||||
.child(self.title_bar.clone())
|
||||
.child(self.dock_area.clone())
|
||||
.children(sheet_layer)
|
||||
.children(dialog_layer)
|
||||
.children(notification_layer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -409,8 +409,13 @@ pub fn open_new(
|
|||
}
|
||||
|
||||
impl Render for StoryTiles {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let sheet_layer = Root::render_sheet_layer(window, cx);
|
||||
let dialog_layer = Root::render_dialog_layer(window, cx);
|
||||
let notification_layer = Root::render_notification_layer(window, cx);
|
||||
|
||||
div()
|
||||
.font_family(".SystemUIFont")
|
||||
.relative()
|
||||
.size_full()
|
||||
.flex()
|
||||
|
|
@ -419,6 +424,9 @@ impl Render for StoryTiles {
|
|||
.text_color(cx.theme().foreground)
|
||||
.child(TitleBar::new().child(div().flex().items_center().child("Story Tiles")))
|
||||
.child(self.dock_area.clone())
|
||||
.children(sheet_layer)
|
||||
.children(dialog_layer)
|
||||
.children(notification_layer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ pub fn create_new_window_with_size<F, E>(
|
|||
let view = crate_view_fn(window, cx);
|
||||
let root = cx.new(|cx| StoryRoot::new(title.clone(), view, window, cx));
|
||||
|
||||
cx.new(|cx| Root::new(root.into(), window, cx).text_base())
|
||||
cx.new(|cx| Root::new(root.into(), window, cx))
|
||||
})
|
||||
.expect("failed to open window");
|
||||
|
||||
|
|
@ -261,13 +261,22 @@ impl StoryRoot {
|
|||
}
|
||||
|
||||
impl Render for StoryRoot {
|
||||
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
|
||||
div().size_full().child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(self.title_bar.clone())
|
||||
.child(div().flex_1().overflow_hidden().child(self.view.clone())),
|
||||
)
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let sheet_layer = Root::render_sheet_layer(window, cx);
|
||||
let dialog_layer = Root::render_dialog_layer(window, cx);
|
||||
let notification_layer = Root::render_notification_layer(window, cx);
|
||||
|
||||
div()
|
||||
.size_full()
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(self.title_bar.clone())
|
||||
.child(div().flex_1().overflow_hidden().child(self.view.clone())),
|
||||
)
|
||||
.children(sheet_layer)
|
||||
.children(dialog_layer)
|
||||
.children(notification_layer)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -324,8 +324,8 @@ impl Render for Notification {
|
|||
.child(
|
||||
h_flex()
|
||||
.absolute()
|
||||
.top_1p5()
|
||||
.right_1p5()
|
||||
.top_3p5()
|
||||
.right_3p5()
|
||||
.invisible()
|
||||
.group_hover("", |this| this.visible())
|
||||
.child(
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ use crate::{
|
|||
input::InputState,
|
||||
notification::{Notification, NotificationList},
|
||||
sheet::Sheet,
|
||||
window_border, ActiveTheme, Placement, StyledExt, TITLE_BAR_HEIGHT,
|
||||
window_border, ActiveTheme, Placement,
|
||||
};
|
||||
use gpui::{
|
||||
actions, canvas, div, prelude::FluentBuilder as _, AnyView, App, AppContext, Context,
|
||||
DefiniteLength, Entity, FocusHandle, InteractiveElement, IntoElement, KeyBinding,
|
||||
ParentElement as _, Render, StyleRefinement, Styled, Window,
|
||||
ParentElement as _, Render, Styled, Window,
|
||||
};
|
||||
use std::{any::TypeId, rc::Rc};
|
||||
|
||||
|
|
@ -210,7 +210,6 @@ impl WindowExt for Window {
|
|||
///
|
||||
/// It is used to manage the Sheet, Dialog, and Notification.
|
||||
pub struct Root {
|
||||
style: StyleRefinement,
|
||||
/// Used to store the focus handle of the previous view.
|
||||
/// When the Dialog, Sheet closes, we will focus back to the previous view.
|
||||
previous_focus_handle: Option<FocusHandle>,
|
||||
|
|
@ -238,7 +237,6 @@ pub(crate) struct ActiveDialog {
|
|||
impl Root {
|
||||
pub fn new(view: AnyView, window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
Self {
|
||||
style: StyleRefinement::default(),
|
||||
previous_focus_handle: None,
|
||||
active_sheet: None,
|
||||
active_dialogs: Vec::new(),
|
||||
|
|
@ -276,64 +274,64 @@ impl Root {
|
|||
}
|
||||
|
||||
// Render Notification layer.
|
||||
fn render_notification_layer(
|
||||
&mut self,
|
||||
_: &mut Window,
|
||||
_: &mut Context<Self>,
|
||||
pub fn render_notification_layer(
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Option<impl IntoElement> {
|
||||
let active_sheet_placement = self.active_sheet.clone().map(|d| d.placement);
|
||||
let root = window.root::<Root>()??;
|
||||
|
||||
let active_sheet_placement = root.read(cx).active_sheet.clone().map(|d| d.placement);
|
||||
|
||||
let (mt, mr) = match active_sheet_placement {
|
||||
Some(Placement::Right) => (None, self.sheet_size),
|
||||
Some(Placement::Top) => (self.sheet_size, None),
|
||||
Some(Placement::Right) => (None, root.read(cx).sheet_size),
|
||||
Some(Placement::Top) => (root.read(cx).sheet_size, None),
|
||||
_ => (None, None),
|
||||
};
|
||||
|
||||
Some(
|
||||
div()
|
||||
.absolute()
|
||||
.top(TITLE_BAR_HEIGHT)
|
||||
.top_0()
|
||||
.right_0()
|
||||
.when_some(mt, |this, offset| this.mt(offset))
|
||||
.when_some(mr, |this, offset| this.mr(offset))
|
||||
.child(self.notification.clone()),
|
||||
.child(root.read(cx).notification.clone()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Render the Sheet layer.
|
||||
fn render_sheet_layer(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<impl IntoElement> {
|
||||
let active_sheet = self.active_sheet.clone()?;
|
||||
let root = cx.entity();
|
||||
let mut sheet = Sheet::new(window, cx);
|
||||
sheet = (active_sheet.builder)(sheet, window, cx);
|
||||
sheet.focus_handle = active_sheet.focus_handle.clone();
|
||||
sheet.placement = active_sheet.placement;
|
||||
pub fn render_sheet_layer(window: &mut Window, cx: &mut App) -> Option<impl IntoElement> {
|
||||
let root = window.root::<Root>()??;
|
||||
|
||||
let size = sheet.size;
|
||||
if let Some(active_sheet) = root.read(cx).active_sheet.clone() {
|
||||
let mut sheet = Sheet::new(window, cx);
|
||||
sheet = (active_sheet.builder)(sheet, window, cx);
|
||||
sheet.focus_handle = active_sheet.focus_handle.clone();
|
||||
sheet.placement = active_sheet.placement;
|
||||
|
||||
Some(
|
||||
div().relative().child(sheet).child(
|
||||
canvas(
|
||||
move |_, _, cx| root.update(cx, |r, _| r.sheet_size = Some(size)),
|
||||
|_, _, _, _| {},
|
||||
)
|
||||
.absolute()
|
||||
.size_full(),
|
||||
),
|
||||
)
|
||||
let size = sheet.size;
|
||||
|
||||
return Some(
|
||||
div().relative().child(sheet).child(
|
||||
canvas(
|
||||
move |_, _, cx| root.update(cx, |r, _| r.sheet_size = Some(size)),
|
||||
|_, _, _, _| {},
|
||||
)
|
||||
.absolute()
|
||||
.size_full(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Render the Dialog layer.
|
||||
fn render_dialog_layer(
|
||||
&mut self,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) -> Option<impl IntoElement> {
|
||||
let active_dialogs = self.active_dialogs.clone();
|
||||
pub fn render_dialog_layer(window: &mut Window, cx: &mut App) -> Option<impl IntoElement> {
|
||||
let root = window.root::<Root>()??;
|
||||
|
||||
let active_dialogs = root.read(cx).active_dialogs.clone();
|
||||
|
||||
if active_dialogs.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
|
@ -387,12 +385,6 @@ impl Root {
|
|||
}
|
||||
}
|
||||
|
||||
impl Styled for Root {
|
||||
fn style(&mut self) -> &mut StyleRefinement {
|
||||
&mut self.style
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Root {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let base_font_size = cx.theme().font_size;
|
||||
|
|
@ -404,16 +396,12 @@ impl Render for Root {
|
|||
.key_context(CONTEXT)
|
||||
.on_action(cx.listener(Self::on_action_tab))
|
||||
.on_action(cx.listener(Self::on_action_tab_prev))
|
||||
.font_family(".SystemUIFont")
|
||||
.refine_style(&self.style)
|
||||
.bg(cx.theme().background)
|
||||
.text_color(cx.theme().foreground)
|
||||
.relative()
|
||||
.size_full()
|
||||
.child(self.view.clone())
|
||||
.children(self.render_sheet_layer(window, cx))
|
||||
.children(self.render_dialog_layer(window, cx))
|
||||
.children(self.render_notification_layer(window, cx)),
|
||||
.font_family(".SystemUIFont")
|
||||
.bg(cx.theme().background)
|
||||
.text_color(cx.theme().foreground)
|
||||
.child(self.view.clone()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,37 @@ use gpui_component::WindowExt;
|
|||
|
||||
## Usage
|
||||
|
||||
### Setup application root view for display of dialogs
|
||||
|
||||
You need to set up your application's root view to render the dialog layer. This is typically done in your main application struct's render method.
|
||||
|
||||
The [Root::render_dialog_layer](https://docs.rs/gpui-component/latest/gpui_component/struct.Root.html#method.render_dialog_layer) function handles rendering any active dialogs on top of your app content.
|
||||
|
||||
```rust
|
||||
use gpui_component::TitleBar;
|
||||
|
||||
struct MyApp {
|
||||
view: AnyView,
|
||||
}
|
||||
|
||||
impl Render for MyApp {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let dialog_layer = Root::render_dialog_layer(window, cx);
|
||||
|
||||
div()
|
||||
.size_full()
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(TitleBar::new())
|
||||
.child(div().flex_1().overflow_hidden().child(self.view.clone())),
|
||||
)
|
||||
// Render the dialog layer on top of the app content
|
||||
.children(dialog_layer)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Basic Dialog
|
||||
|
||||
```rust
|
||||
|
|
|
|||
|
|
@ -16,6 +16,38 @@ use gpui_component::WindowExt;
|
|||
|
||||
## Usage
|
||||
|
||||
### Setup application root view for display of notifications
|
||||
|
||||
You need to set up your application's root view to render the notification layer. This is typically done in your main application struct's render method.
|
||||
|
||||
The [Root::render_notification_layer](https://docs.rs/gpui-component/latest/gpui_component/struct.Root.html#method.render_notification_layer) function handles rendering any active modals on top of your app content.
|
||||
|
||||
```rust
|
||||
use gpui_component::TitleBar;
|
||||
|
||||
struct MyApp {
|
||||
view: AnyView,
|
||||
}
|
||||
|
||||
impl Render for MyApp {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let notification_layer = Root::render_notification_layer(window, cx);
|
||||
|
||||
|
||||
div()
|
||||
.size_full()
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(TitleBar::new())
|
||||
.child(div().flex_1().overflow_hidden().child(self.view.clone())),
|
||||
)
|
||||
// Render the notification layer on top of the app content
|
||||
.children(notification_layer)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Basic Notification
|
||||
|
||||
```rust
|
||||
|
|
|
|||
|
|
@ -10,11 +10,43 @@ A Sheet (also known as a sidebar or slide-out panel) is a navigation component t
|
|||
## Import
|
||||
|
||||
```rust
|
||||
use gpui_component::{WindowExt, Placement};
|
||||
use gpui_component::WindowExt;
|
||||
use gpui_component::Placement;
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Setup application root view for display of sheets
|
||||
|
||||
You need to set up your application's root view to render the sheet layer. This is typically done in your main application struct's render method.
|
||||
|
||||
The [Root::render_sheet_layer](https://docs.rs/gpui-component/latest/gpui_component/struct.Root.html#method.render_sheet_layer) function handles rendering any active modals on top of your app content.
|
||||
|
||||
```rust
|
||||
use gpui_component::TitleBar;
|
||||
|
||||
struct MyApp {
|
||||
view: AnyView,
|
||||
}
|
||||
|
||||
impl Render for MyApp {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let sheet_layer = Root::render_sheet_layer(window, cx);
|
||||
|
||||
div()
|
||||
.size_full()
|
||||
.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(TitleBar::new())
|
||||
.child(div().flex_1().overflow_hidden().child(self.view.clone())),
|
||||
)
|
||||
// Render the sheet layer on top of the app content
|
||||
.children(sheet_layer)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Basic Sheet
|
||||
|
||||
```rust
|
||||
|
|
|
|||
|
|
@ -30,19 +30,33 @@ fn main() {
|
|||
}
|
||||
```
|
||||
|
||||
## Setup base styles
|
||||
## Overlays
|
||||
|
||||
You can setup window level base styles by using `Styled` fluent method on [Root], then all child views will inherit these styles.
|
||||
We have dialogs, sheets, notifications, we need placement for them to show, so [Root] provides methods to render these overlays:
|
||||
|
||||
- [Root::render_dialog_layer](https://docs.rs/gpui-component/latest/gpui_component/struct.Root.html#method.render_dialog_layer) - Render the current opened modals.
|
||||
- [Root::render_sheet_layer](https://docs.rs/gpui-component/latest/gpui_component/struct.Root.html#method.render_sheet_layer) - Render the current opened drawers.
|
||||
- [Root::render_notification_layer](https://docs.rs/gpui-component/latest/gpui_component/struct.Root.html#method.render_notification_layer) - Render the notification list.
|
||||
|
||||
We can put these layers in the `render` method your first level view (Root > YourFirstView):
|
||||
|
||||
```rs
|
||||
Root::new(view.into(), window, cx)
|
||||
// This default is `.SystemUIFont` it will use system UI font.
|
||||
.font_family("Your Special Font")
|
||||
.text_sm()
|
||||
struct MyApp;
|
||||
|
||||
impl Render for MyApp {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.size_full()
|
||||
.child("My App Content")
|
||||
.children(Root::render_dialog_layer(cx))
|
||||
.children(Root::render_sheet_layer(cx))
|
||||
.children(Root::render_notification_layer(cx))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::tip
|
||||
Here the example we used `children` method, it because if there is no opened dialogs, sheets, notifications, these methods will return `None`, so GPUI will not render anything.
|
||||
:::
|
||||
|
||||
[Root]: https://docs.rs/gpui-component/latest/gpui_component/root/struct.Root.html
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ impl HelloWorld {
|
|||
}
|
||||
|
||||
impl Render for HelloWorld {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.bg(gpui::white())
|
||||
.size_full()
|
||||
|
|
@ -72,6 +72,8 @@ impl Render for HelloWorld {
|
|||
}),
|
||||
),
|
||||
)
|
||||
.children(Root::render_dialog_layer(window, cx))
|
||||
.children(Root::render_sheet_layer(window, cx))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ fn main() {
|
|||
|
||||
cx.open_window(window_options, |window, cx| {
|
||||
let view = cx.new(|_| Example);
|
||||
cx.new(|cx| Root::new(view.into(), window, cx).text_sm())
|
||||
cx.new(|cx| Root::new(view.into(), window, cx))
|
||||
})?;
|
||||
|
||||
Ok::<_, anyhow::Error>(())
|
||||
|
|
|
|||
Loading…
Reference in a new issue