Skip to content

Commit

Permalink
Add open_drawer_at to replace placement method in Drawer.
Browse files Browse the repository at this point in the history
  • Loading branch information
huacnlee committed Dec 24, 2024
1 parent d051ac6 commit 2230f68
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 22 deletions.
7 changes: 3 additions & 4 deletions crates/story/src/modal_story.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,8 @@ impl ModalStory {
};

let overlay = self.modal_overlay;
cx.open_drawer(move |this, cx| {
this.placement(placement)
.overlay(overlay)
cx.open_drawer_at(placement, move |this, cx| {
this.overlay(overlay)
.size(px(400.))
.title("Drawer Title")
.gap_4()
Expand Down Expand Up @@ -495,7 +494,7 @@ impl Render for ModalStory {

WebView::new(cx, webview)
});
webview.update(cx, |webview, _| {
webview.update(cx, |webview, cx| {
webview.load_url("https://github.com/explore");
});
cx.open_drawer(move |drawer, cx| {
Expand Down
13 changes: 1 addition & 12 deletions crates/ui/src/drawer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub fn init(cx: &mut AppContext) {
#[derive(IntoElement)]
pub struct Drawer {
pub(crate) focus_handle: FocusHandle,
placement: Placement,
pub(crate) placement: Placement,
size: DefiniteLength,
resizable: bool,
on_close: Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>,
Expand Down Expand Up @@ -81,17 +81,6 @@ impl Drawer {
self
}

/// Sets the placement of the drawer, default is `Placement::Right`.
pub fn placement(mut self, placement: Placement) -> Self {
self.placement = placement;
self
}

/// Sets the placement of the drawer, default is `Placement::Right`.
pub fn set_placement(&mut self, placement: Placement) {
self.placement = placement;
}

/// Sets whether the drawer is resizable, default is `true`.
pub fn resizable(mut self, resizable: bool) -> Self {
self.resizable = resizable;
Expand Down
65 changes: 59 additions & 6 deletions crates/ui/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ use crate::{
modal::Modal,
notification::{Notification, NotificationList},
theme::ActiveTheme,
Placement,
};
use gpui::{
div, AnyView, FocusHandle, InteractiveElement, IntoElement, ParentElement as _, Render, Styled,
View, ViewContext, VisualContext as _, WindowContext,
canvas, div, px, AnyView, Bounds, FocusHandle, InteractiveElement, IntoElement,
ParentElement as _, Pixels, Render, Styled, View, ViewContext, VisualContext as _,
WindowContext,
};
use std::{
ops::{Deref, DerefMut},
Expand All @@ -15,11 +17,16 @@ use std::{

/// Extension trait for [`WindowContext`] and [`ViewContext`] to add drawer functionality.
pub trait ContextModal: Sized {
/// Opens a Drawer.
/// Opens a Drawer at right placement.
fn open_drawer<F>(&mut self, build: F)
where
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static;

/// Opens a Drawer at the given placement.
fn open_drawer_at<F>(&mut self, placement: Placement, build: F)
where
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static;

/// Return true, if there is an active Drawer.
fn has_active_drawer(&self) -> bool;

Expand Down Expand Up @@ -49,6 +56,13 @@ pub trait ContextModal: Sized {

impl ContextModal for WindowContext<'_> {
fn open_drawer<F>(&mut self, build: F)
where
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static,
{
self.open_drawer_at(Placement::Right, build)
}

fn open_drawer_at<F>(&mut self, placement: Placement, build: F)
where
F: Fn(Drawer, &mut WindowContext) -> Drawer + 'static,
{
Expand All @@ -62,6 +76,7 @@ impl ContextModal for WindowContext<'_> {

root.active_drawer = Some(ActiveDrawer {
focus_handle,
placement,
builder: Rc::new(build),
});
cx.notify();
Expand Down Expand Up @@ -156,6 +171,13 @@ impl<V> ContextModal for ViewContext<'_, V> {
self.deref_mut().open_drawer(build)
}

fn open_drawer_at<F>(&mut self, placement: Placement, build: F)
where
F: Fn(Drawer, &mut WindowContexbuildt) -> Drawer + 'static,

Check failure on line 176 in crates/ui/src/root.rs

View workflow job for this annotation

GitHub Actions / Test

cannot find type `WindowContexbuildt` in this scope
{
self.deref_mut().open_drawer_at(placement, build)

Check failure on line 178 in crates/ui/src/root.rs

View workflow job for this annotation

GitHub Actions / Test

expected a `Fn(drawer::Drawer, &mut gpui::WindowContext<'_>)` closure, found `F`
}

fn has_active_modal(&self) -> bool {
self.deref().has_active_modal()
}
Expand Down Expand Up @@ -208,12 +230,14 @@ pub struct Root {
active_drawer: Option<ActiveDrawer>,
active_modals: Vec<ActiveModal>,
pub notification: View<NotificationList>,
drawer_bounds: Bounds<Pixels>,
view: AnyView,
}

#[derive(Clone)]
struct ActiveDrawer {
focus_handle: FocusHandle,
placement: Placement,
builder: Rc<dyn Fn(Drawer, &mut WindowContext) -> Drawer + 'static>,
}

Expand All @@ -230,6 +254,7 @@ impl Root {
active_drawer: None,
active_modals: Vec::new(),
notification: cx.new_view(NotificationList::new),
drawer_bounds: Bounds::default(),
view,
}
}
Expand Down Expand Up @@ -263,6 +288,14 @@ impl Root {
}
}

fn has_active_right_drawer(&self, cx: &WindowContext) -> bool {
if let Some(drawer) = Root::read(cx).active_drawer.as_ref() {
drawer.placement == Placement::Right
} else {
false
}
}

// Render Notification layer.
pub fn render_notification_layer(cx: &mut WindowContext) -> Option<impl IntoElement> {
let root = cx
Expand All @@ -271,7 +304,17 @@ impl Root {
.and_then(|w| w.root_view(cx).ok())
.expect("The window root view should be of type `ui::Root`.");

Some(div().child(root.read(cx).notification.clone()))
let right_offset = if root.read(cx).has_active_right_drawer(cx) {
root.read(cx).drawer_bounds.size.width
} else {
px(0.)
};

Some(
div()
.mr(right_offset)
.child(root.read(cx).notification.clone()),
)
}

/// Render the Drawer layer.
Expand All @@ -286,8 +329,18 @@ impl Root {
let mut drawer = Drawer::new(cx);
drawer = (active_drawer.builder)(drawer, cx);
drawer.focus_handle = active_drawer.focus_handle.clone();

return Some(div().child(drawer));
drawer.placement = active_drawer.placement;

return Some(
div().relative().child(drawer).child(
canvas(
move |bounds, cx| root.update(cx, |r, _| r.drawer_bounds = bounds),
|_, _, _| {},
)
.absolute()
.size_full(),
),
);
}

None
Expand Down

0 comments on commit 2230f68

Please sign in to comment.