Draft basic styling for Container

This commit is contained in:
Héctor Ramón Jiménez 2019-12-31 11:36:54 +01:00
parent 8caa66be27
commit fb9cc0262b
6 changed files with 126 additions and 11 deletions

View File

@ -3,7 +3,7 @@ use std::hash::Hash;
use crate::{ use crate::{
layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point, layout, Align, Clipboard, Element, Event, Hasher, Layout, Length, Point,
Widget, Rectangle, Widget,
}; };
use std::u32; use std::u32;
@ -12,17 +12,21 @@ use std::u32;
/// ///
/// It is normally used for alignment purposes. /// It is normally used for alignment purposes.
#[allow(missing_debug_implementations)] #[allow(missing_debug_implementations)]
pub struct Container<'a, Message, Renderer> { pub struct Container<'a, Message, Renderer: self::Renderer> {
width: Length, width: Length,
height: Length, height: Length,
max_width: u32, max_width: u32,
max_height: u32, max_height: u32,
horizontal_alignment: Align, horizontal_alignment: Align,
vertical_alignment: Align, vertical_alignment: Align,
style: Renderer::Style,
content: Element<'a, Message, Renderer>, content: Element<'a, Message, Renderer>,
} }
impl<'a, Message, Renderer> Container<'a, Message, Renderer> { impl<'a, Message, Renderer> Container<'a, Message, Renderer>
where
Renderer: self::Renderer,
{
/// Creates an empty [`Container`]. /// Creates an empty [`Container`].
/// ///
/// [`Container`]: struct.Container.html /// [`Container`]: struct.Container.html
@ -37,6 +41,7 @@ impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
max_height: u32::MAX, max_height: u32::MAX,
horizontal_alignment: Align::Start, horizontal_alignment: Align::Start,
vertical_alignment: Align::Start, vertical_alignment: Align::Start,
style: Renderer::Style::default(),
content: content.into(), content: content.into(),
} }
} }
@ -78,7 +83,6 @@ impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
/// [`Container`]: struct.Container.html /// [`Container`]: struct.Container.html
pub fn center_x(mut self) -> Self { pub fn center_x(mut self) -> Self {
self.horizontal_alignment = Align::Center; self.horizontal_alignment = Align::Center;
self self
} }
@ -87,7 +91,14 @@ impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
/// [`Container`]: struct.Container.html /// [`Container`]: struct.Container.html
pub fn center_y(mut self) -> Self { pub fn center_y(mut self) -> Self {
self.vertical_alignment = Align::Center; self.vertical_alignment = Align::Center;
self
}
/// Sets the style the [`Container`].
///
/// [`Container`]: struct.Container.html
pub fn style(mut self, style: impl Into<Renderer::Style>) -> Self {
self.style = style.into();
self self
} }
} }
@ -95,7 +106,7 @@ impl<'a, Message, Renderer> Container<'a, Message, Renderer> {
impl<'a, Message, Renderer> Widget<Message, Renderer> impl<'a, Message, Renderer> Widget<Message, Renderer>
for Container<'a, Message, Renderer> for Container<'a, Message, Renderer>
where where
Renderer: crate::Renderer, Renderer: self::Renderer,
{ {
fn width(&self) -> Length { fn width(&self) -> Length {
self.width self.width
@ -151,11 +162,13 @@ where
layout: Layout<'_>, layout: Layout<'_>,
cursor_position: Point, cursor_position: Point,
) -> Renderer::Output { ) -> Renderer::Output {
self.content.draw( renderer.draw(
renderer,
defaults, defaults,
layout.children().next().unwrap(), layout.bounds(),
cursor_position, cursor_position,
&self.style,
&self.content,
layout.children().next().unwrap(),
) )
} }
@ -170,10 +183,27 @@ where
} }
} }
pub trait Renderer: crate::Renderer {
type Style: Default;
/// Draws a [`Container`].
///
/// [`Container`]: struct.Container.html
fn draw<Message>(
&mut self,
defaults: &Self::Defaults,
bounds: Rectangle,
cursor_position: Point,
style: &Self::Style,
content: &Element<'_, Message, Self>,
content_layout: Layout<'_>,
) -> Self::Output;
}
impl<'a, Message, Renderer> From<Container<'a, Message, Renderer>> impl<'a, Message, Renderer> From<Container<'a, Message, Renderer>>
for Element<'a, Message, Renderer> for Element<'a, Message, Renderer>
where where
Renderer: 'a + crate::Renderer, Renderer: 'a + self::Renderer,
Message: 'static, Message: 'static,
{ {
fn from( fn from(

View File

@ -1,6 +1,7 @@
mod button; mod button;
mod checkbox; mod checkbox;
mod column; mod column;
mod container;
mod image; mod image;
mod radio; mod radio;
mod row; mod row;

View File

@ -0,0 +1,46 @@
use crate::{container, defaults, Defaults, Primitive, Renderer};
use iced_native::{Element, Layout, Point, Rectangle};
impl iced_native::container::Renderer for Renderer {
type Style = Box<dyn container::StyleSheet>;
fn draw<Message>(
&mut self,
defaults: &Defaults,
bounds: Rectangle,
cursor_position: Point,
style_sheet: &Self::Style,
content: &Element<'_, Message, Self>,
content_layout: Layout<'_>,
) -> Self::Output {
let style = style_sheet.style();
let defaults = Defaults {
text: defaults::Text {
color: style.text_color.unwrap_or(defaults.text.color),
},
..*defaults
};
let (content, mouse_cursor) =
content.draw(self, &defaults, content_layout, cursor_position);
match style.background {
Some(background) => {
let quad = Primitive::Quad {
bounds,
background,
border_radius: style.border_radius,
};
(
Primitive::Group {
primitives: vec![quad, content],
},
mouse_cursor,
)
}
None => (content, mouse_cursor),
}
}
}

View File

@ -1 +1,2 @@
pub mod button; pub mod button;
pub mod container;

View File

@ -0,0 +1,37 @@
use iced_native::{Background, Color};
#[derive(Debug, Clone, Copy)]
pub struct Style {
pub text_color: Option<Color>,
pub background: Option<Background>,
pub border_radius: u16,
}
pub trait StyleSheet {
fn style(&self) -> Style {
Style {
text_color: None,
background: None,
border_radius: 0,
}
}
}
struct Default;
impl StyleSheet for Default {}
impl std::default::Default for Box<dyn StyleSheet> {
fn default() -> Self {
Box::new(Default)
}
}
impl<T> From<T> for Box<dyn StyleSheet>
where
T: 'static + StyleSheet,
{
fn from(style: T) -> Self {
Box::new(style)
}
}

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
conversion, container, conversion,
input::{keyboard, mouse}, input::{keyboard, mouse},
renderer::{Target, Windowed}, renderer::{Target, Windowed},
subscription, Cache, Clipboard, Command, Container, Debug, Element, Event, subscription, Cache, Clipboard, Command, Container, Debug, Element, Event,
@ -18,7 +18,7 @@ pub trait Application: Sized {
/// The renderer to use to draw the [`Application`]. /// The renderer to use to draw the [`Application`].
/// ///
/// [`Application`]: trait.Application.html /// [`Application`]: trait.Application.html
type Renderer: Windowed; type Renderer: Windowed + container::Renderer;
/// The type of __messages__ your [`Application`] will produce. /// The type of __messages__ your [`Application`] will produce.
/// ///