Lay out title text dynamically in TitleBar
This commit is contained in:
parent
ac7816e8ca
commit
3cfe6e428b
5 changed files with 144 additions and 47 deletions
|
|
@ -8,10 +8,15 @@
|
||||||
//!
|
//!
|
||||||
//! [`pane_grid` example]: https://github.com/hecrj/iced/tree/0.1/examples/pane_grid
|
//! [`pane_grid` example]: https://github.com/hecrj/iced/tree/0.1/examples/pane_grid
|
||||||
//! [`PaneGrid`]: type.PaneGrid.html
|
//! [`PaneGrid`]: type.PaneGrid.html
|
||||||
use crate::{Backend, Primitive, Renderer};
|
use crate::backend::{self, Backend};
|
||||||
|
use crate::{Primitive, Renderer};
|
||||||
use iced_native::mouse;
|
use iced_native::mouse;
|
||||||
use iced_native::pane_grid;
|
use iced_native::pane_grid;
|
||||||
use iced_native::{Element, Layout, Point, Rectangle, Vector};
|
use iced_native::text;
|
||||||
|
use iced_native::{
|
||||||
|
Element, HorizontalAlignment, Layout, Point, Rectangle, Vector,
|
||||||
|
VerticalAlignment,
|
||||||
|
};
|
||||||
|
|
||||||
pub use iced_native::pane_grid::{
|
pub use iced_native::pane_grid::{
|
||||||
Axis, Configuration, Content, Direction, DragEvent, Focus, KeyPressEvent,
|
Axis, Configuration, Content, Direction, DragEvent, Focus, KeyPressEvent,
|
||||||
|
|
@ -29,7 +34,7 @@ pub type PaneGrid<'a, Message, Backend> =
|
||||||
|
|
||||||
impl<B> pane_grid::Renderer for Renderer<B>
|
impl<B> pane_grid::Renderer for Renderer<B>
|
||||||
where
|
where
|
||||||
B: Backend,
|
B: Backend + backend::Text,
|
||||||
{
|
{
|
||||||
fn draw<Message>(
|
fn draw<Message>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
@ -189,17 +194,28 @@ where
|
||||||
defaults: &Self::Defaults,
|
defaults: &Self::Defaults,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
style_sheet: &Self::Style,
|
style_sheet: &Self::Style,
|
||||||
title: (&Element<'_, Message, Self>, Layout<'_>),
|
title: &str,
|
||||||
|
title_size: u16,
|
||||||
|
title_font: Self::Font,
|
||||||
|
title_bounds: Rectangle,
|
||||||
controls: Option<(&Element<'_, Message, Self>, Layout<'_>)>,
|
controls: Option<(&Element<'_, Message, Self>, Layout<'_>)>,
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
) -> Self::Output {
|
) -> Self::Output {
|
||||||
let style = style_sheet.style();
|
let style = style_sheet.style();
|
||||||
let (title, title_layout) = title;
|
|
||||||
|
|
||||||
let background = crate::widget::container::background(bounds, &style);
|
let background = crate::widget::container::background(bounds, &style);
|
||||||
|
|
||||||
let (title_primitive, _) =
|
let (title_primitive, _) = text::Renderer::draw(
|
||||||
title.draw(self, defaults, title_layout, cursor_position);
|
self,
|
||||||
|
defaults,
|
||||||
|
title_bounds,
|
||||||
|
title,
|
||||||
|
title_size,
|
||||||
|
title_font,
|
||||||
|
None,
|
||||||
|
HorizontalAlignment::Left,
|
||||||
|
VerticalAlignment::Top,
|
||||||
|
);
|
||||||
|
|
||||||
if let Some((controls, controls_layout)) = controls {
|
if let Some((controls, controls_layout)) = controls {
|
||||||
let (controls_primitive, controls_interaction) =
|
let (controls_primitive, controls_interaction) =
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
button, checkbox, column, container, progress_bar, radio, row, scrollable,
|
button, checkbox, column, container, pane_grid, progress_bar, radio, row,
|
||||||
slider, text, text_input, Color, Element, Font, HorizontalAlignment,
|
scrollable, slider, text, text_input, Color, Element, Font,
|
||||||
Layout, Point, Rectangle, Renderer, Size, VerticalAlignment,
|
HorizontalAlignment, Layout, Point, Rectangle, Renderer, Size,
|
||||||
|
VerticalAlignment,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A renderer that does nothing.
|
/// A renderer that does nothing.
|
||||||
|
|
@ -241,3 +242,44 @@ impl container::Renderer for Null {
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl pane_grid::Renderer for Null {
|
||||||
|
fn draw<Message>(
|
||||||
|
&mut self,
|
||||||
|
_defaults: &Self::Defaults,
|
||||||
|
_content: &[(pane_grid::Pane, pane_grid::Content<'_, Message, Self>)],
|
||||||
|
_dragging: Option<(pane_grid::Pane, Point)>,
|
||||||
|
_resizing: Option<pane_grid::Axis>,
|
||||||
|
_layout: Layout<'_>,
|
||||||
|
_cursor_position: Point,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_pane<Message>(
|
||||||
|
&mut self,
|
||||||
|
_defaults: &Self::Defaults,
|
||||||
|
_bounds: Rectangle,
|
||||||
|
_style: &Self::Style,
|
||||||
|
_title_bar: Option<(
|
||||||
|
&pane_grid::TitleBar<'_, Message, Self>,
|
||||||
|
Layout<'_>,
|
||||||
|
)>,
|
||||||
|
_body: (&Element<'_, Message, Self>, Layout<'_>),
|
||||||
|
_cursor_position: Point,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_title_bar<Message>(
|
||||||
|
&mut self,
|
||||||
|
_defaults: &Self::Defaults,
|
||||||
|
_bounds: Rectangle,
|
||||||
|
_style: &Self::Style,
|
||||||
|
_title: &str,
|
||||||
|
_title_size: u16,
|
||||||
|
_title_font: Self::Font,
|
||||||
|
_title_bounds: Rectangle,
|
||||||
|
_controls: Option<(&Element<'_, Message, Self>, Layout<'_>)>,
|
||||||
|
_cursor_position: Point,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ pub use state::{Focus, State};
|
||||||
pub use title_bar::TitleBar;
|
pub use title_bar::TitleBar;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
container, keyboard, layout, mouse, row, Clipboard, Element, Event, Hasher,
|
container, keyboard, layout, mouse, row, text, Clipboard, Element, Event,
|
||||||
Layout, Length, Point, Rectangle, Size, Widget,
|
Hasher, Layout, Length, Point, Rectangle, Size, Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A collection of panes distributed using either vertical or horizontal splits
|
/// A collection of panes distributed using either vertical or horizontal splits
|
||||||
|
|
@ -86,7 +86,7 @@ use crate::{
|
||||||
/// [`PaneGrid`]: struct.PaneGrid.html
|
/// [`PaneGrid`]: struct.PaneGrid.html
|
||||||
/// [`State`]: struct.State.html
|
/// [`State`]: struct.State.html
|
||||||
#[allow(missing_debug_implementations)]
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct PaneGrid<'a, Message, Renderer: container::Renderer> {
|
pub struct PaneGrid<'a, Message, Renderer: self::Renderer> {
|
||||||
state: &'a mut state::Internal,
|
state: &'a mut state::Internal,
|
||||||
pressed_modifiers: &'a mut keyboard::ModifiersState,
|
pressed_modifiers: &'a mut keyboard::ModifiersState,
|
||||||
elements: Vec<(Pane, Content<'a, Message, Renderer>)>,
|
elements: Vec<(Pane, Content<'a, Message, Renderer>)>,
|
||||||
|
|
@ -101,7 +101,7 @@ pub struct PaneGrid<'a, Message, Renderer: container::Renderer> {
|
||||||
|
|
||||||
impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer>
|
impl<'a, Message, Renderer> PaneGrid<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: container::Renderer,
|
Renderer: self::Renderer,
|
||||||
{
|
{
|
||||||
/// Creates a [`PaneGrid`] with the given [`State`] and view function.
|
/// Creates a [`PaneGrid`] with the given [`State`] and view function.
|
||||||
///
|
///
|
||||||
|
|
@ -646,7 +646,9 @@ where
|
||||||
///
|
///
|
||||||
/// [`PaneGrid`]: struct.PaneGrid.html
|
/// [`PaneGrid`]: struct.PaneGrid.html
|
||||||
/// [renderer]: ../../renderer/index.html
|
/// [renderer]: ../../renderer/index.html
|
||||||
pub trait Renderer: crate::Renderer + container::Renderer + Sized {
|
pub trait Renderer:
|
||||||
|
crate::Renderer + container::Renderer + text::Renderer + Sized
|
||||||
|
{
|
||||||
/// Draws a [`PaneGrid`].
|
/// Draws a [`PaneGrid`].
|
||||||
///
|
///
|
||||||
/// It receives:
|
/// It receives:
|
||||||
|
|
@ -694,7 +696,10 @@ pub trait Renderer: crate::Renderer + container::Renderer + Sized {
|
||||||
defaults: &Self::Defaults,
|
defaults: &Self::Defaults,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
style: &Self::Style,
|
style: &Self::Style,
|
||||||
title: (&Element<'_, Message, Self>, Layout<'_>),
|
title: &str,
|
||||||
|
title_size: u16,
|
||||||
|
title_font: Self::Font,
|
||||||
|
title_bounds: Rectangle,
|
||||||
controls: Option<(&Element<'_, Message, Self>, Layout<'_>)>,
|
controls: Option<(&Element<'_, Message, Self>, Layout<'_>)>,
|
||||||
cursor_position: Point,
|
cursor_position: Point,
|
||||||
) -> Self::Output;
|
) -> Self::Output;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::{Clipboard, Element, Event, Hasher, Layout, Point, Size, Vector};
|
||||||
/// The content of a [`Pane`].
|
/// The content of a [`Pane`].
|
||||||
///
|
///
|
||||||
/// [`Pane`]: struct.Pane.html
|
/// [`Pane`]: struct.Pane.html
|
||||||
pub struct Content<'a, Message, Renderer: container::Renderer> {
|
pub struct Content<'a, Message, Renderer: pane_grid::Renderer> {
|
||||||
title_bar: Option<TitleBar<'a, Message, Renderer>>,
|
title_bar: Option<TitleBar<'a, Message, Renderer>>,
|
||||||
body: Element<'a, Message, Renderer>,
|
body: Element<'a, Message, Renderer>,
|
||||||
style: Renderer::Style,
|
style: Renderer::Style,
|
||||||
|
|
@ -14,7 +14,7 @@ pub struct Content<'a, Message, Renderer: container::Renderer> {
|
||||||
|
|
||||||
impl<'a, Message, Renderer> Content<'a, Message, Renderer>
|
impl<'a, Message, Renderer> Content<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: container::Renderer,
|
Renderer: pane_grid::Renderer,
|
||||||
{
|
{
|
||||||
pub fn new(body: impl Into<Element<'a, Message, Renderer>>) -> Self {
|
pub fn new(body: impl Into<Element<'a, Message, Renderer>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -43,7 +43,7 @@ where
|
||||||
|
|
||||||
impl<'a, Message, Renderer> Content<'a, Message, Renderer>
|
impl<'a, Message, Renderer> Content<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: pane_grid::Renderer + container::Renderer,
|
Renderer: pane_grid::Renderer,
|
||||||
{
|
{
|
||||||
pub fn draw(
|
pub fn draw(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::container;
|
|
||||||
use crate::layout;
|
use crate::layout;
|
||||||
use crate::pane_grid;
|
use crate::pane_grid;
|
||||||
use crate::{Clipboard, Element, Event, Layout, Point, Size};
|
use crate::{Clipboard, Element, Event, Layout, Point, Rectangle, Size};
|
||||||
|
|
||||||
pub struct TitleBar<'a, Message, Renderer: container::Renderer> {
|
pub struct TitleBar<'a, Message, Renderer: pane_grid::Renderer> {
|
||||||
title: Element<'a, Message, Renderer>,
|
title: String,
|
||||||
|
title_size: Option<u16>,
|
||||||
controls: Option<Element<'a, Message, Renderer>>,
|
controls: Option<Element<'a, Message, Renderer>>,
|
||||||
padding: u16,
|
padding: u16,
|
||||||
style: Renderer::Style,
|
style: Renderer::Style,
|
||||||
|
|
@ -12,17 +12,29 @@ pub struct TitleBar<'a, Message, Renderer: container::Renderer> {
|
||||||
|
|
||||||
impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer>
|
impl<'a, Message, Renderer> TitleBar<'a, Message, Renderer>
|
||||||
where
|
where
|
||||||
Renderer: container::Renderer,
|
Renderer: pane_grid::Renderer,
|
||||||
{
|
{
|
||||||
pub fn new(title: impl Into<Element<'a, Message, Renderer>>) -> Self {
|
pub fn new(title: impl Into<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
title: title.into(),
|
title: title.into(),
|
||||||
|
title_size: None,
|
||||||
controls: None,
|
controls: None,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
style: Renderer::Style::default(),
|
style: Renderer::Style::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the size of the title of the [`TitleBar`].
|
||||||
|
///
|
||||||
|
/// [`TitleBar`]: struct.Text.html
|
||||||
|
pub fn title_size(mut self, size: u16) -> Self {
|
||||||
|
self.title_size = Some(size);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the controls of the [`TitleBar`].
|
||||||
|
///
|
||||||
|
/// [`TitleBar`]: struct.TitleBar.html
|
||||||
pub fn controls(
|
pub fn controls(
|
||||||
mut self,
|
mut self,
|
||||||
controls: impl Into<Element<'a, Message, Renderer>>,
|
controls: impl Into<Element<'a, Message, Renderer>>,
|
||||||
|
|
@ -68,24 +80,38 @@ where
|
||||||
let title_layout = children.next().unwrap();
|
let title_layout = children.next().unwrap();
|
||||||
let controls_layout = children.next().unwrap();
|
let controls_layout = children.next().unwrap();
|
||||||
|
|
||||||
|
let (title_bounds, controls) = if show_controls {
|
||||||
|
(title_layout.bounds(), Some((controls, controls_layout)))
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
Rectangle {
|
||||||
|
width: padded.bounds().width,
|
||||||
|
..title_layout.bounds()
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
renderer.draw_title_bar(
|
renderer.draw_title_bar(
|
||||||
defaults,
|
defaults,
|
||||||
layout.bounds(),
|
layout.bounds(),
|
||||||
&self.style,
|
&self.style,
|
||||||
(&self.title, title_layout),
|
&self.title,
|
||||||
if show_controls {
|
self.title_size.unwrap_or(Renderer::DEFAULT_SIZE),
|
||||||
Some((controls, controls_layout))
|
Renderer::Font::default(),
|
||||||
} else {
|
title_bounds,
|
||||||
None
|
controls,
|
||||||
},
|
|
||||||
cursor_position,
|
cursor_position,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
renderer.draw_title_bar(
|
renderer.draw_title_bar::<()>(
|
||||||
defaults,
|
defaults,
|
||||||
layout.bounds(),
|
layout.bounds(),
|
||||||
&self.style,
|
&self.style,
|
||||||
(&self.title, padded),
|
&self.title,
|
||||||
|
self.title_size.unwrap_or(Renderer::DEFAULT_SIZE),
|
||||||
|
Renderer::Font::default(),
|
||||||
|
padded.bounds(),
|
||||||
None,
|
None,
|
||||||
cursor_position,
|
cursor_position,
|
||||||
)
|
)
|
||||||
|
|
@ -122,39 +148,47 @@ where
|
||||||
) -> layout::Node {
|
) -> layout::Node {
|
||||||
let padding = f32::from(self.padding);
|
let padding = f32::from(self.padding);
|
||||||
let limits = limits.pad(padding);
|
let limits = limits.pad(padding);
|
||||||
|
let max_size = limits.max();
|
||||||
|
|
||||||
let node = if let Some(controls) = &self.controls {
|
let title_size = self.title_size.unwrap_or(Renderer::DEFAULT_SIZE);
|
||||||
let max_size = limits.max();
|
let title_font = Renderer::Font::default();
|
||||||
|
|
||||||
|
let (title_width, title_height) = renderer.measure(
|
||||||
|
&self.title,
|
||||||
|
title_size,
|
||||||
|
title_font,
|
||||||
|
Size::new(f32::INFINITY, max_size.height),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut node = if let Some(controls) = &self.controls {
|
||||||
let mut controls_layout = controls
|
let mut controls_layout = controls
|
||||||
.layout(renderer, &layout::Limits::new(Size::ZERO, max_size));
|
.layout(renderer, &layout::Limits::new(Size::ZERO, max_size));
|
||||||
|
|
||||||
let controls_size = controls_layout.size();
|
let controls_size = controls_layout.size();
|
||||||
let space_before_controls = max_size.width - controls_size.width;
|
let space_before_controls = max_size.width - controls_size.width;
|
||||||
|
|
||||||
let mut title_layout = self.title.layout(
|
let mut title_layout = layout::Node::new(Size::new(
|
||||||
renderer,
|
title_width.min(space_before_controls),
|
||||||
&layout::Limits::new(
|
title_height,
|
||||||
Size::ZERO,
|
));
|
||||||
Size::new(space_before_controls, max_size.height),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
title_layout.move_to(Point::new(padding, padding));
|
|
||||||
controls_layout
|
|
||||||
.move_to(Point::new(space_before_controls + padding, padding));
|
|
||||||
|
|
||||||
let title_size = title_layout.size();
|
let title_size = title_layout.size();
|
||||||
let height = title_size.height.max(controls_size.height);
|
let height = title_size.height.max(controls_size.height);
|
||||||
|
|
||||||
|
title_layout
|
||||||
|
.move_to(Point::new(0.0, (height - title_size.height) / 2.0));
|
||||||
|
controls_layout.move_to(Point::new(space_before_controls, 0.0));
|
||||||
|
|
||||||
layout::Node::with_children(
|
layout::Node::with_children(
|
||||||
Size::new(max_size.width, height),
|
Size::new(max_size.width, height),
|
||||||
vec![title_layout, controls_layout],
|
vec![title_layout, controls_layout],
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
self.title.layout(renderer, &limits)
|
layout::Node::new(Size::new(title_width, title_height))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
node.move_to(Point::new(padding, padding));
|
||||||
|
|
||||||
layout::Node::with_children(node.size().pad(padding), vec![node])
|
layout::Node::with_children(node.size().pad(padding), vec![node])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue