improv(context_drawer): move title out of header row
This moves the title below the header row containing actions and the close button, allowing more room for the title and actions. Also makes actions an `Element` instead of a `Vec<Element>`, providing more flexibility for developers.
This commit is contained in:
parent
2299b46862
commit
b6c6d1cb7b
4 changed files with 60 additions and 91 deletions
|
|
@ -7,7 +7,7 @@ use crate::Element;
|
|||
|
||||
pub struct ContextDrawer<'a, Message: Clone + 'static> {
|
||||
pub title: Option<Cow<'a, str>>,
|
||||
pub header_actions: Vec<Element<'a, Message>>,
|
||||
pub actions: Option<Element<'a, Message>>,
|
||||
pub header: Option<Element<'a, Message>>,
|
||||
pub content: Element<'a, Message>,
|
||||
pub footer: Option<Element<'a, Message>>,
|
||||
|
|
@ -29,29 +29,28 @@ pub fn context_drawer<'a, Message: Clone + 'static>(
|
|||
) -> ContextDrawer<'a, Message> {
|
||||
ContextDrawer {
|
||||
title: None,
|
||||
actions: None,
|
||||
header: None,
|
||||
content: content.into(),
|
||||
header_actions: vec![],
|
||||
footer: None,
|
||||
on_close,
|
||||
header: None,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
||||
/// Set a context drawer header title
|
||||
/// Set a context drawer title
|
||||
pub fn title(mut self, title: impl Into<Cow<'a, str>>) -> Self {
|
||||
self.title = Some(title.into());
|
||||
self
|
||||
}
|
||||
/// App-specific actions at the start of the context drawer header
|
||||
pub fn header_actions(
|
||||
mut self,
|
||||
header_actions: impl IntoIterator<Item = Element<'a, Message>>,
|
||||
) -> Self {
|
||||
self.header_actions = header_actions.into_iter().collect();
|
||||
|
||||
/// App-specific actions at the top-left corner of the context drawer
|
||||
pub fn actions(mut self, actions: impl Into<Element<'a, Message>>) -> Self {
|
||||
self.actions = Some(actions.into());
|
||||
self
|
||||
}
|
||||
/// Non-scrolling elements placed below the context drawer title row
|
||||
|
||||
/// Elements placed above the context drawer scrollable
|
||||
pub fn header(mut self, header: impl Into<Element<'a, Message>>) -> Self {
|
||||
self.header = Some(header.into());
|
||||
self
|
||||
|
|
@ -64,20 +63,16 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
|||
}
|
||||
|
||||
pub fn map<Out: Clone + 'static>(
|
||||
mut self,
|
||||
self,
|
||||
on_message: fn(Message) -> Out,
|
||||
) -> ContextDrawer<'a, Out> {
|
||||
ContextDrawer {
|
||||
title: self.title,
|
||||
content: self.content.map(on_message),
|
||||
actions: self.actions.map(|el| el.map(on_message)),
|
||||
header: self.header.map(|el| el.map(on_message)),
|
||||
content: self.content.map(on_message),
|
||||
footer: self.footer.map(|el| el.map(on_message)),
|
||||
on_close: on_message(self.on_close),
|
||||
header_actions: self
|
||||
.header_actions
|
||||
.into_iter()
|
||||
.map(|el| el.map(on_message))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -603,7 +603,7 @@ impl<App: Application> ApplicationExt for App {
|
|||
widgets.push(
|
||||
crate::widget::context_drawer(
|
||||
context.title,
|
||||
context.header_actions,
|
||||
context.actions,
|
||||
context.header,
|
||||
context.footer,
|
||||
context.on_close,
|
||||
|
|
@ -640,7 +640,7 @@ impl<App: Application> ApplicationExt for App {
|
|||
widgets.push(
|
||||
crate::widget::ContextDrawer::new_inner(
|
||||
context.title,
|
||||
context.header_actions,
|
||||
context.actions,
|
||||
context.header,
|
||||
context.footer,
|
||||
context.content,
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ use crate::Element;
|
|||
/// An overlayed widget that attaches a toggleable context drawer to the view.
|
||||
pub fn context_drawer<'a, Message: Clone + 'static, Content, Drawer>(
|
||||
title: Option<Cow<'a, str>>,
|
||||
header_actions: Vec<Element<'a, Message>>,
|
||||
header_opt: Option<Element<'a, Message>>,
|
||||
footer_opt: Option<Element<'a, Message>>,
|
||||
actions: Option<Element<'a, Message>>,
|
||||
header: Option<Element<'a, Message>>,
|
||||
footer: Option<Element<'a, Message>>,
|
||||
on_close: Message,
|
||||
content: Content,
|
||||
drawer: Drawer,
|
||||
|
|
@ -28,13 +28,6 @@ where
|
|||
Drawer: Into<Element<'a, Message>>,
|
||||
{
|
||||
ContextDrawer::new(
|
||||
title,
|
||||
header_actions,
|
||||
header_opt,
|
||||
footer_opt,
|
||||
content,
|
||||
drawer,
|
||||
on_close,
|
||||
max_width,
|
||||
title, actions, header, footer, content, drawer, on_close, max_width,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use super::overlay::Overlay;
|
||||
use crate::widget::{LayerContainer, button, column, container, icon, row, scrollable, text};
|
||||
use crate::widget::{self, LayerContainer, button, column, container, icon, row, scrollable, text};
|
||||
use crate::{Apply, Element, Renderer, Theme, fl};
|
||||
use std::borrow::Cow;
|
||||
|
||||
|
|
@ -25,9 +25,9 @@ pub struct ContextDrawer<'a, Message> {
|
|||
impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
||||
pub fn new_inner<Drawer>(
|
||||
title: Option<Cow<'a, str>>,
|
||||
header_actions: Vec<Element<'a, Message>>,
|
||||
header_opt: Option<Element<'a, Message>>,
|
||||
footer_opt: Option<Element<'a, Message>>,
|
||||
actions: Option<Element<'a, Message>>,
|
||||
header: Option<Element<'a, Message>>,
|
||||
footer: Option<Element<'a, Message>>,
|
||||
drawer: Drawer,
|
||||
on_close: Message,
|
||||
max_width: f32,
|
||||
|
|
@ -38,7 +38,7 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
|||
#[inline(never)]
|
||||
fn inner<'a, Message: Clone + 'static>(
|
||||
title: Option<Cow<'a, str>>,
|
||||
header_actions: Vec<Element<'a, Message>>,
|
||||
actions_opt: Option<Element<'a, Message>>,
|
||||
header_opt: Option<Element<'a, Message>>,
|
||||
footer_opt: Option<Element<'a, Message>>,
|
||||
drawer: Element<'a, Message>,
|
||||
|
|
@ -53,68 +53,57 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
|||
..
|
||||
} = crate::theme::spacing();
|
||||
|
||||
let (horizontal_padding, title_portion, side_portion) = if max_width < 392.0 {
|
||||
(space_s, 1, 1)
|
||||
} else {
|
||||
(space_l, 2, 1)
|
||||
};
|
||||
let horizontal_padding = if max_width < 392.0 { space_s } else { space_l };
|
||||
|
||||
let title = title.map(|title| {
|
||||
text::heading(title)
|
||||
text::title4(title)
|
||||
.apply(container)
|
||||
.center_x(Length::FillPortion(title_portion))
|
||||
.padding([if actions_opt.is_some() { space_m } else { 0 }, 0, 0, 0])
|
||||
.width(Length::Fill)
|
||||
});
|
||||
|
||||
let (actions_width, close_width) = if title.is_some() {
|
||||
(
|
||||
Length::FillPortion(side_portion),
|
||||
Length::FillPortion(side_portion),
|
||||
)
|
||||
let actions = if let Some(actions) = actions_opt {
|
||||
actions
|
||||
.apply(container)
|
||||
.width(Length::Fill)
|
||||
.apply(Element::from)
|
||||
} else {
|
||||
(Length::Fill, Length::Shrink)
|
||||
widget::horizontal_space().apply(Element::from)
|
||||
};
|
||||
|
||||
let header_row = row::with_capacity(3)
|
||||
.width(Length::Fixed(480.0))
|
||||
let header_row = row::with_capacity(2)
|
||||
.align_y(Alignment::Center)
|
||||
.push(
|
||||
row::with_children(header_actions)
|
||||
.spacing(space_xxs)
|
||||
.width(actions_width),
|
||||
)
|
||||
.push_maybe(title)
|
||||
.push(actions)
|
||||
.push(
|
||||
button::text(fl!("close"))
|
||||
.trailing_icon(icon::from_name("go-next-symbolic"))
|
||||
.on_press(on_close)
|
||||
.apply(container)
|
||||
.width(close_width)
|
||||
.align_x(Alignment::End),
|
||||
.on_press(on_close),
|
||||
);
|
||||
let header = column::with_capacity(2)
|
||||
.width(Length::Fixed(480.0))
|
||||
let header_element =
|
||||
header_opt.map(|el| el.apply(container).padding([space_m, 0, 0, 0]));
|
||||
|
||||
let header = column::with_capacity(3)
|
||||
.align_x(Alignment::Center)
|
||||
.spacing(space_m)
|
||||
.padding([space_m, horizontal_padding])
|
||||
.push(header_row)
|
||||
.push_maybe(header_opt);
|
||||
.push_maybe(title)
|
||||
.push_maybe(header_element);
|
||||
let footer = footer_opt.map(|element| {
|
||||
container(element)
|
||||
.width(Length::Fixed(480.0))
|
||||
.align_y(Alignment::Center)
|
||||
.padding([space_xxs, horizontal_padding])
|
||||
});
|
||||
let pane = column::with_capacity(3)
|
||||
.push(header)
|
||||
.push(
|
||||
scrollable(container(drawer).padding([
|
||||
0,
|
||||
horizontal_padding,
|
||||
if footer.is_some() { 0 } else { space_l },
|
||||
horizontal_padding,
|
||||
]))
|
||||
.height(Length::Fill)
|
||||
.width(Length::Shrink),
|
||||
container(drawer)
|
||||
.padding([
|
||||
0,
|
||||
horizontal_padding,
|
||||
if footer.is_some() { 0 } else { space_l },
|
||||
horizontal_padding,
|
||||
])
|
||||
.apply(scrollable)
|
||||
.height(Length::Fill),
|
||||
)
|
||||
.push_maybe(footer);
|
||||
|
||||
|
|
@ -136,9 +125,9 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
|||
|
||||
inner(
|
||||
title,
|
||||
header_actions,
|
||||
header_opt,
|
||||
footer_opt,
|
||||
actions,
|
||||
header,
|
||||
footer,
|
||||
drawer.into(),
|
||||
on_close,
|
||||
max_width,
|
||||
|
|
@ -148,9 +137,9 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
|||
/// Creates an empty [`ContextDrawer`].
|
||||
pub fn new<Content, Drawer>(
|
||||
title: Option<Cow<'a, str>>,
|
||||
header_actions: Vec<Element<'a, Message>>,
|
||||
header_opt: Option<Element<'a, Message>>,
|
||||
footer_opt: Option<Element<'a, Message>>,
|
||||
actions: Option<Element<'a, Message>>,
|
||||
header: Option<Element<'a, Message>>,
|
||||
footer: Option<Element<'a, Message>>,
|
||||
content: Content,
|
||||
drawer: Drawer,
|
||||
on_close: Message,
|
||||
|
|
@ -160,15 +149,7 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
|||
Content: Into<Element<'a, Message>>,
|
||||
Drawer: Into<Element<'a, Message>>,
|
||||
{
|
||||
let drawer = Self::new_inner(
|
||||
title,
|
||||
header_actions,
|
||||
header_opt,
|
||||
footer_opt,
|
||||
drawer,
|
||||
on_close,
|
||||
max_width,
|
||||
);
|
||||
let drawer = Self::new_inner(title, actions, header, footer, drawer, on_close, max_width);
|
||||
|
||||
ContextDrawer {
|
||||
id: None,
|
||||
|
|
@ -188,7 +169,7 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
|
|||
/// Map the message type of the context drawer to another
|
||||
#[inline]
|
||||
pub fn map<Out: Clone + 'static>(
|
||||
mut self,
|
||||
self,
|
||||
on_message: fn(Message) -> Out,
|
||||
) -> ContextDrawer<'a, Out> {
|
||||
ContextDrawer {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue