summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--examples/ggez/main.rs21
-rw-r--r--examples/ggez/renderer.rs26
-rw-r--r--examples/ggez/renderer/button.rs1
-rw-r--r--examples/ggez/renderer/debugger.rs30
-rw-r--r--examples/ggez/renderer/image.rs51
-rw-r--r--examples/ggez/renderer/text.rs17
-rw-r--r--examples/ggez/tour.rs381
-rw-r--r--examples/ggez/widget.rs3
-rw-r--r--examples/resources/Roboto-LICENSE202
-rw-r--r--examples/resources/Roboto-Regular.ttfbin0 -> 171272 bytes
-rw-r--r--examples/resources/ferris.pngbin0 -> 33061 bytes
-rw-r--r--src/lib.rs4
-rw-r--r--src/style.rs20
-rw-r--r--src/widget.rs6
-rw-r--r--src/widget/button.rs2
-rw-r--r--src/widget/checkbox.rs2
-rw-r--r--src/widget/column.rs10
-rw-r--r--src/widget/image.rs63
-rw-r--r--src/widget/progress_bar.rs2
-rw-r--r--src/widget/radio.rs2
-rw-r--r--src/widget/row.rs10
-rw-r--r--src/widget/slider.rs2
-rw-r--r--src/widget/text.rs18
24 files changed, 640 insertions, 235 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 82279f05..1c139e61 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,4 +19,4 @@ twox-hash = "1.5"
winit = { version = "0.20.0-alpha3", optional = true }
[dev-dependencies]
-ggez = { version = "0.5", git = "https://github.com/hecrj/ggez.git", branch = "font-cache" }
+ggez = { version = "0.5", git = "https://github.com/hecrj/ggez.git" }
diff --git a/examples/ggez/main.rs b/examples/ggez/main.rs
index 329bde81..0a6a2005 100644
--- a/examples/ggez/main.rs
+++ b/examples/ggez/main.rs
@@ -16,8 +16,8 @@ pub fn main() -> ggez::GameResult {
let (context, event_loop) = {
&mut ggez::ContextBuilder::new("iced", "ggez")
.window_mode(ggez::conf::WindowMode {
- width: 1280.0,
- height: 1024.0,
+ width: 850.0,
+ height: 850.0,
..ggez::conf::WindowMode::default()
})
.build()?
@@ -39,6 +39,7 @@ pub fn main() -> ggez::GameResult {
struct Game {
spritesheet: graphics::Image,
+ font: graphics::Font,
tour: Tour,
events: Vec<iced::Event>,
@@ -51,7 +52,8 @@ impl Game {
Ok(Game {
spritesheet: graphics::Image::new(context, "/ui.png").unwrap(),
- tour: Tour::new(),
+ font: graphics::Font::new(context, "/Roboto-Regular.ttf").unwrap(),
+ tour: Tour::new(context),
events: Vec::new(),
cache: Some(iced::Cache::default()),
@@ -126,7 +128,7 @@ impl event::EventHandler for Game {
}
fn draw(&mut self, context: &mut ggez::Context) -> ggez::GameResult {
- graphics::clear(context, [0.3, 0.3, 0.6, 1.0].into());
+ graphics::clear(context, graphics::WHITE);
let screen = graphics::screen_coordinates(context);
@@ -134,14 +136,17 @@ impl event::EventHandler for Game {
let layout = self.tour.layout();
let content = Column::new()
- .width(screen.w as u32)
- .height(screen.h as u32)
+ .width(screen.w as u16)
+ .height(screen.h as u16)
.align_items(iced::Align::Center)
.justify_content(iced::Justify::Center)
.push(layout);
- let renderer =
- &mut Renderer::new(context, self.spritesheet.clone());
+ let renderer = &mut Renderer::new(
+ context,
+ self.spritesheet.clone(),
+ self.font,
+ );
let mut ui = iced::UserInterface::build(
content,
diff --git a/examples/ggez/renderer.rs b/examples/ggez/renderer.rs
index ccf12aba..8746dd96 100644
--- a/examples/ggez/renderer.rs
+++ b/examples/ggez/renderer.rs
@@ -1,24 +1,38 @@
mod button;
mod checkbox;
+mod debugger;
+mod image;
mod radio;
mod slider;
mod text;
-use ggez::graphics::{self, spritebatch::SpriteBatch, Image};
+use ggez::graphics::{
+ self, spritebatch::SpriteBatch, Font, Image, MeshBuilder,
+};
use ggez::Context;
pub struct Renderer<'a> {
pub context: &'a mut Context,
pub sprites: SpriteBatch,
pub spritesheet: Image,
+ pub font: Font,
+ font_size: f32,
+ debug_mesh: Option<MeshBuilder>,
}
impl Renderer<'_> {
- pub fn new(context: &mut Context, spritesheet: Image) -> Renderer {
+ pub fn new(
+ context: &mut Context,
+ spritesheet: Image,
+ font: Font,
+ ) -> Renderer {
Renderer {
context,
sprites: SpriteBatch::new(spritesheet.clone()),
spritesheet,
+ font,
+ font_size: 20.0,
+ debug_mesh: None,
}
}
@@ -37,5 +51,13 @@ impl Renderer<'_> {
graphics::FilterMode::Linear,
)
.expect("Draw text");
+
+ if let Some(debug_mesh) = self.debug_mesh.take() {
+ let mesh =
+ debug_mesh.build(self.context).expect("Build debug mesh");
+
+ graphics::draw(self.context, &mesh, graphics::DrawParam::default())
+ .expect("Draw debug mesh");
+ }
}
}
diff --git a/examples/ggez/renderer/button.rs b/examples/ggez/renderer/button.rs
index fc3ea7ca..486e07ed 100644
--- a/examples/ggez/renderer/button.rs
+++ b/examples/ggez/renderer/button.rs
@@ -104,6 +104,7 @@ impl button::Renderer for Renderer<'_> {
let mut text = Text::new(TextFragment {
text: String::from(label),
+ font: Some(self.font),
scale: Some(Scale { x: 20.0, y: 20.0 }),
..Default::default()
});
diff --git a/examples/ggez/renderer/debugger.rs b/examples/ggez/renderer/debugger.rs
new file mode 100644
index 00000000..98124795
--- /dev/null
+++ b/examples/ggez/renderer/debugger.rs
@@ -0,0 +1,30 @@
+use super::Renderer;
+use ggez::graphics::{Color, DrawMode, MeshBuilder, Rect};
+
+impl iced::renderer::Debugger for Renderer<'_> {
+ type Color = Color;
+
+ fn explain(&mut self, layout: &iced::Layout<'_>, color: Color) {
+ let bounds = layout.bounds();
+
+ let mut debug_mesh =
+ self.debug_mesh.take().unwrap_or(MeshBuilder::new());
+
+ debug_mesh.rectangle(
+ DrawMode::stroke(1.0),
+ Rect {
+ x: bounds.x,
+ y: bounds.y,
+ w: bounds.width,
+ h: bounds.height,
+ },
+ color,
+ );
+
+ self.debug_mesh = Some(debug_mesh);
+
+ for child in layout.children() {
+ self.explain(&child, color);
+ }
+ }
+}
diff --git a/examples/ggez/renderer/image.rs b/examples/ggez/renderer/image.rs
new file mode 100644
index 00000000..c3ead5c9
--- /dev/null
+++ b/examples/ggez/renderer/image.rs
@@ -0,0 +1,51 @@
+use super::Renderer;
+
+use ggez::{graphics, nalgebra};
+use iced::image;
+
+impl image::Renderer<graphics::Image> for Renderer<'_> {
+ fn node(
+ &self,
+ style: iced::Style,
+ image: &graphics::Image,
+ width: Option<u16>,
+ height: Option<u16>,
+ _source: Option<iced::Rectangle<u16>>,
+ ) -> iced::Node {
+ let aspect_ratio = image.width() as f32 / image.height() as f32;
+
+ let style = match (width, height) {
+ (Some(width), Some(height)) => style.width(width).height(height),
+ (Some(width), None) => style
+ .width(width)
+ .height((width as f32 / aspect_ratio).round() as u16),
+ (None, Some(height)) => style
+ .height(height)
+ .width((height as f32 * aspect_ratio).round() as u16),
+ (None, None) => style.width(image.width()).height(image.height()),
+ };
+
+ iced::Node::new(style)
+ }
+
+ fn draw(
+ &mut self,
+ image: &graphics::Image,
+ bounds: iced::Rectangle,
+ _source: Option<iced::Rectangle<u16>>,
+ ) {
+ // We should probably use batches to draw images efficiently and keep
+ // draw side-effect free, but this is good enough for the example.
+ graphics::draw(
+ self.context,
+ image,
+ graphics::DrawParam::new()
+ .dest(nalgebra::Point2::new(bounds.x, bounds.y))
+ .scale(nalgebra::Vector2::new(
+ bounds.width / image.width() as f32,
+ bounds.height / image.height() as f32,
+ )),
+ )
+ .expect("Draw image");
+ }
+}
diff --git a/examples/ggez/renderer/text.rs b/examples/ggez/renderer/text.rs
index a6f782fc..ecf1481e 100644
--- a/examples/ggez/renderer/text.rs
+++ b/examples/ggez/renderer/text.rs
@@ -6,7 +6,13 @@ use std::cell::RefCell;
use std::f32;
impl text::Renderer<Color> for Renderer<'_> {
- fn node(&self, style: iced::Style, content: &str, size: f32) -> iced::Node {
+ fn node(
+ &self,
+ style: iced::Style,
+ content: &str,
+ size: Option<u16>,
+ ) -> iced::Node {
+ let font = self.font;
let font_cache = graphics::font_cache(self.context);
let content = String::from(content);
@@ -17,6 +23,7 @@ impl text::Renderer<Color> for Renderer<'_> {
// I noticed that the first measure is the one that matters in
// practice. Here, we use a RefCell to store the cached measurement.
let measure = RefCell::new(None);
+ let size = size.map(f32::from).unwrap_or(self.font_size);
iced::Node::with_measure(style, move |bounds| {
let mut measure = measure.borrow_mut();
@@ -35,6 +42,7 @@ impl text::Renderer<Color> for Renderer<'_> {
let mut text = Text::new(TextFragment {
text: content.clone(),
+ font: Some(font),
scale: Some(Scale { x: size, y: size }),
..Default::default()
});
@@ -71,13 +79,16 @@ impl text::Renderer<Color> for Renderer<'_> {
&mut self,
bounds: iced::Rectangle,
content: &str,
- size: f32,
+ size: Option<u16>,
color: Option<Color>,
horizontal_alignment: text::HorizontalAlignment,
_vertical_alignment: text::VerticalAlignment,
) {
+ let size = size.map(f32::from).unwrap_or(self.font_size);
+
let mut text = Text::new(TextFragment {
text: String::from(content),
+ font: Some(self.font),
scale: Some(Scale { x: size, y: size }),
..Default::default()
});
@@ -101,7 +112,7 @@ impl text::Renderer<Color> for Renderer<'_> {
x: bounds.x,
y: bounds.y,
},
- color,
+ color.or(Some(graphics::BLACK)),
);
}
}
diff --git a/examples/ggez/tour.rs b/examples/ggez/tour.rs
index 19982aa4..c2126675 100644
--- a/examples/ggez/tour.rs
+++ b/examples/ggez/tour.rs
@@ -1,22 +1,26 @@
use super::widget::{
- button, slider, Button, Checkbox, Column, Element, Radio, Row, Slider, Text,
+ button, slider, Button, Checkbox, Column, Element, Image, Radio, Row,
+ Slider, Text,
};
-use ggez::graphics::{Color, BLACK};
+use ggez::graphics::{self, Color, FilterMode, BLACK};
+use ggez::Context;
use iced::{text::HorizontalAlignment, Align};
pub struct Tour {
steps: Steps,
back_button: button::State,
next_button: button::State,
+ debug: bool,
}
impl Tour {
- pub fn new() -> Tour {
+ pub fn new(context: &mut Context) -> Tour {
Tour {
- steps: Steps::new(),
+ steps: Steps::new(context),
back_button: button::State::new(),
next_button: button::State::new(),
+ debug: false,
}
}
@@ -29,7 +33,7 @@ impl Tour {
self.steps.advance();
}
Message::StepMessage(step_msg) => {
- self.steps.update(step_msg);
+ self.steps.update(step_msg, &mut self.debug);
}
}
}
@@ -39,6 +43,7 @@ impl Tour {
steps,
back_button,
next_button,
+ ..
} = self;
let mut controls = Row::new();
@@ -59,12 +64,18 @@ impl Tour {
);
}
- Column::new()
+ let element: Element<_> = Column::new()
.max_width(500)
.spacing(20)
- .push(steps.layout().map(Message::StepMessage))
+ .push(steps.layout(self.debug).map(Message::StepMessage))
.push(controls)
- .into()
+ .into();
+
+ if self.debug {
+ element.explain(BLACK)
+ } else {
+ element
+ }
}
}
@@ -81,44 +92,52 @@ struct Steps {
}
impl Steps {
- fn new() -> Steps {
+ fn new(context: &mut Context) -> Steps {
Steps {
steps: vec![
Step::Welcome,
- Step::Buttons {
- primary: button::State::new(),
- secondary: button::State::new(),
- positive: button::State::new(),
- },
- Step::Checkbox { is_checked: false },
- Step::Radio { selection: None },
Step::Slider {
state: slider::State::new(),
value: 50,
},
+ Step::RowsAndColumns {
+ layout: Layout::Row,
+ spacing_slider: slider::State::new(),
+ spacing: 20,
+ },
Step::Text {
size_slider: slider::State::new(),
size: 30,
color_sliders: [slider::State::new(); 3],
color: BLACK,
},
- Step::RowsAndColumns {
- layout: Layout::Row,
- spacing_slider: slider::State::new(),
- spacing: 20,
+ Step::Radio { selection: None },
+ Step::Image {
+ ferris: {
+ let mut image =
+ graphics::Image::new(context, "/ferris.png")
+ .expect("Load ferris image");
+
+ image.set_filter(FilterMode::Linear);
+
+ image
+ },
+ width: 300,
+ slider: slider::State::new(),
},
+ Step::Debugger,
Step::End,
],
current: 0,
}
}
- fn update(&mut self, msg: StepMessage) {
- self.steps[self.current].update(msg);
+ fn update(&mut self, msg: StepMessage, debug: &mut bool) {
+ self.steps[self.current].update(msg, debug);
}
- fn layout(&mut self) -> Element<StepMessage> {
- self.steps[self.current].layout()
+ fn layout(&mut self, debug: bool) -> Element<StepMessage> {
+ self.steps[self.current].layout(debug)
}
fn advance(&mut self) {
@@ -145,52 +164,51 @@ impl Steps {
enum Step {
Welcome,
- Buttons {
- primary: button::State,
- secondary: button::State,
- positive: button::State,
- },
- Checkbox {
- is_checked: bool,
- },
- Radio {
- selection: Option<Language>,
- },
Slider {
state: slider::State,
value: u16,
},
+ RowsAndColumns {
+ layout: Layout,
+ spacing_slider: slider::State,
+ spacing: u16,
+ },
Text {
size_slider: slider::State,
size: u16,
color_sliders: [slider::State; 3],
color: Color,
},
- RowsAndColumns {
- layout: Layout,
- spacing_slider: slider::State,
- spacing: u16,
+ Radio {
+ selection: Option<Language>,
},
+ Image {
+ ferris: graphics::Image,
+ width: u16,
+ slider: slider::State,
+ },
+ Debugger,
End,
}
#[derive(Debug, Clone, Copy)]
pub enum StepMessage {
- CheckboxToggled(bool),
- LanguageSelected(Language),
SliderChanged(f32),
- TextSizeChanged(f32),
- TextColorChanged(Color),
LayoutChanged(Layout),
SpacingChanged(f32),
+ TextSizeChanged(f32),
+ TextColorChanged(Color),
+ LanguageSelected(Language),
+ ImageWidthChanged(f32),
+ DebugToggled(bool),
}
impl<'a> Step {
- fn update(&mut self, msg: StepMessage) {
+ fn update(&mut self, msg: StepMessage, debug: &mut bool) {
match msg {
- StepMessage::CheckboxToggled(value) => {
- if let Step::Checkbox { is_checked } = self {
- *is_checked = value;
+ StepMessage::DebugToggled(value) => {
+ if let Step::Debugger = self {
+ *debug = value;
}
}
StepMessage::LanguageSelected(language) => {
@@ -223,31 +241,30 @@ impl<'a> Step {
*spacing = new_spacing.round() as u16;
}
}
+ StepMessage::ImageWidthChanged(new_width) => {
+ if let Step::Image { width, .. } = self {
+ *width = new_width.round() as u16;
+ }
+ }
};
}
fn can_continue(&self) -> bool {
match self {
Step::Welcome => true,
- Step::Buttons { .. } => true,
- Step::Checkbox { is_checked } => *is_checked,
Step::Radio { selection } => *selection == Some(Language::Rust),
Step::Slider { .. } => true,
Step::Text { .. } => true,
+ Step::Image { .. } => true,
Step::RowsAndColumns { .. } => true,
+ Step::Debugger => true,
Step::End => false,
}
}
- fn layout(&mut self) -> Element<StepMessage> {
+ fn layout(&mut self, debug: bool) -> Element<StepMessage> {
match self {
Step::Welcome => Self::welcome().into(),
- Step::Buttons {
- primary,
- secondary,
- positive,
- } => Self::buttons(primary, secondary, positive).into(),
- Step::Checkbox { is_checked } => Self::checkbox(*is_checked).into(),
Step::Radio { selection } => Self::radio(*selection).into(),
Step::Slider { state, value } => Self::slider(state, *value).into(),
Step::Text {
@@ -256,6 +273,11 @@ impl<'a> Step {
color_sliders,
color,
} => Self::text(size_slider, *size, color_sliders, *color).into(),
+ Step::Image {
+ ferris,
+ width,
+ slider,
+ } => Self::image(ferris.clone(), *width, slider).into(),
Step::RowsAndColumns {
layout,
spacing_slider,
@@ -263,6 +285,7 @@ impl<'a> Step {
} => {
Self::rows_and_columns(*layout, spacing_slider, *spacing).into()
}
+ Step::Debugger => Self::debugger(debug).into(),
Step::End => Self::end().into(),
}
}
@@ -277,80 +300,26 @@ impl<'a> Step {
fn welcome() -> Column<'a, StepMessage> {
Self::container("Welcome!")
.push(Text::new(
- "This is a tour that introduces some of the features and \
- concepts related with UI development in Iced.",
+ "This a simple tour meant to showcase a bunch of widgets that \
+ can be easily implemented on top of Iced.",
))
.push(Text::new(
- "You will need to interact with the UI in order to reach the \
- end!",
- ))
- }
-
- fn buttons(
- primary: &'a mut button::State,
- secondary: &'a mut button::State,
- positive: &'a mut button::State,
- ) -> Column<'a, StepMessage> {
- Self::container("Button")
- .push(Text::new("A button can fire actions when clicked."))
- .push(Text::new(
- "As of now, there are 3 different types of buttons: \
- primary, secondary, and positive.",
- ))
- .push(Button::new(primary, "Primary"))
- .push(
- Button::new(secondary, "Secondary")
- .class(button::Class::Secondary),
- )
- .push(
- Button::new(positive, "Positive")
- .class(button::Class::Positive),
- )
- .push(Text::new(
- "Additional types will be added in the near future! Choose \
- each type smartly depending on the situation.",
+ "Iced is a renderer-agnostic GUI library for Rust focused on \
+ simplicity and type-safety. It is heavily inspired by Elm.",
))
- }
-
- fn checkbox(is_checked: bool) -> Column<'a, StepMessage> {
- Self::container("Checkbox")
.push(Text::new(
- "A box that can be checked. Useful to build toggle controls.",
- ))
- .push(Checkbox::new(
- is_checked,
- "Show \"Next\" button",
- StepMessage::CheckboxToggled,
+ "It was originally born as part of Coffee, an opinionated \
+ 2D game engine for Rust.",
))
.push(Text::new(
- "A checkbox always has a label, and both the checkbox and its \
- label can be clicked to toggle it.",
+ "Iced does not provide a built-in renderer. This example runs \
+ on a fairly simple renderer built on top of ggez, another \
+ game library.",
))
- }
-
- fn radio(selection: Option<Language>) -> Column<'a, StepMessage> {
- let question = Column::new()
- .padding(20)
- .spacing(10)
- .push(Text::new("Iced is written in..."))
- .push(Language::all().iter().cloned().fold(
- Column::new().padding(10).spacing(20),
- |choices, language| {
- choices.push(Radio::new(
- language,
- language.into(),
- selection,
- StepMessage::LanguageSelected,
- ))
- },
- ));
-
- Self::container("Radio button")
.push(Text::new(
- "A radio button is normally used to represent a choice. Like \
- a checkbox, it always has a label.",
+ "You will need to interact with the UI in order to reach the \
+ end!",
))
- .push(question)
}
fn slider(
@@ -378,55 +347,6 @@ impl<'a> Step {
)
}
- fn text(
- size_slider: &'a mut slider::State,
- size: u16,
- color_sliders: &'a mut [slider::State; 3],
- color: Color,
- ) -> Column<'a, StepMessage> {
- let size_section = Column::new()
- .padding(20)
- .spacing(20)
- .push(Text::new("You can change its size:"))
- .push(
- Text::new(&format!("This text is {} points", size)).size(size),
- )
- .push(Slider::new(
- size_slider,
- 10.0..=50.0,
- size as f32,
- StepMessage::TextSizeChanged,
- ));
-
- let [red, green, blue] = color_sliders;
- let color_section = Column::new()
- .padding(20)
- .spacing(20)
- .push(Text::new("And its color:"))
- .push(Text::new(&format!("{:?}", color)).color(color))
- .push(
- Row::new()
- .spacing(10)
- .push(Slider::new(red, 0.0..=1.0, color.r, move |r| {
- StepMessage::TextColorChanged(Color { r, ..color })
- }))
- .push(Slider::new(green, 0.0..=1.0, color.g, move |g| {
- StepMessage::TextColorChanged(Color { g, ..color })
- }))
- .push(Slider::new(blue, 0.0..=1.0, color.b, move |b| {
- StepMessage::TextColorChanged(Color { b, ..color })
- })),
- );
-
- Self::container("Text")
- .push(Text::new(
- "Text is probably the most essential widget for your UI. \
- It will try to adapt to the dimensions of its container.",
- ))
- .push(size_section)
- .push(color_section)
- }
-
fn rows_and_columns(
layout: Layout,
spacing_slider: &'a mut slider::State,
@@ -463,7 +383,7 @@ impl<'a> Step {
.spacing(10)
.push(Slider::new(
spacing_slider,
- 0.0..=100.0,
+ 0.0..=80.0,
spacing as f32,
StepMessage::SpacingChanged,
))
@@ -489,10 +409,127 @@ impl<'a> Step {
.push(spacing_section)
}
+ fn text(
+ size_slider: &'a mut slider::State,
+ size: u16,
+ color_sliders: &'a mut [slider::State; 3],
+ color: Color,
+ ) -> Column<'a, StepMessage> {
+ let size_section = Column::new()
+ .padding(20)
+ .spacing(20)
+ .push(Text::new("You can change its size:"))
+ .push(
+ Text::new(&format!("This text is {} pixels", size)).size(size),
+ )
+ .push(Slider::new(
+ size_slider,
+ 10.0..=70.0,
+ size as f32,
+ StepMessage::TextSizeChanged,
+ ));
+
+ let [red, green, blue] = color_sliders;
+ let color_section = Column::new()
+ .padding(20)
+ .spacing(20)
+ .push(Text::new("And its color:"))
+ .push(Text::new(&format!("{:?}", color)).color(color))
+ .push(
+ Row::new()
+ .spacing(10)
+ .push(Slider::new(red, 0.0..=1.0, color.r, move |r| {
+ StepMessage::TextColorChanged(Color { r, ..color })
+ }))
+ .push(Slider::new(green, 0.0..=1.0, color.g, move |g| {
+ StepMessage::TextColorChanged(Color { g, ..color })
+ }))
+ .push(Slider::new(blue, 0.0..=1.0, color.b, move |b| {
+ StepMessage::TextColorChanged(Color { b, ..color })
+ })),
+ );
+
+ Self::container("Text")
+ .push(Text::new(
+ "Text is probably the most essential widget for your UI. \
+ It will try to adapt to the dimensions of its container.",
+ ))
+ .push(size_section)
+ .push(color_section)
+ }
+
+ fn radio(selection: Option<Language>) -> Column<'a, StepMessage> {
+ let question = Column::new()
+ .padding(20)
+ .spacing(10)
+ .push(Text::new("Iced is written in...").size(24))
+ .push(Language::all().iter().cloned().fold(
+ Column::new().padding(10).spacing(20),
+ |choices, language| {
+ choices.push(Radio::new(
+ language,
+ language.into(),
+ selection,
+ StepMessage::LanguageSelected,
+ ))
+ },
+ ));
+
+ Self::container("Radio button")
+ .push(Text::new(
+ "A radio button is normally used to represent a choice... \
+ Surprise test!",
+ ))
+ .push(question)
+ .push(Text::new(
+ "Iced works very well with iterators! The list above is \
+ basically created by folding a column over the different \
+ choices, creating a radio button for each one of them!",
+ ))
+ }
+
+ fn image(
+ ferris: graphics::Image,
+ width: u16,
+ slider: &'a mut slider::State,
+ ) -> Column<'a, StepMessage> {
+ Self::container("Image")
+ .push(Text::new("An image that tries to keep its aspect ratio."))
+ .push(Image::new(ferris).width(width).align_self(Align::Center))
+ .push(Slider::new(
+ slider,
+ 100.0..=500.0,
+ width as f32,
+ StepMessage::ImageWidthChanged,
+ ))
+ .push(
+ Text::new(&format!("Width: {} px", width.to_string()))
+ .horizontal_alignment(HorizontalAlignment::Center),
+ )
+ }
+
+ fn debugger(debug: bool) -> Column<'a, StepMessage> {
+ Self::container("Debugger")
+ .push(Text::new(
+ "You can ask Iced to visually explain the layouting of the \
+ different elements comprising your UI!",
+ ))
+ .push(Text::new(
+ "Give it a shot! Check the following checkbox to be able to \
+ see element boundaries.",
+ ))
+ .push(Checkbox::new(
+ debug,
+ "Explain layout",
+ StepMessage::DebugToggled,
+ ))
+ .push(Text::new("Feel free to go back and take a look."))
+ }
+
fn end() -> Column<'a, StepMessage> {
Self::container("You reached the end!")
.push(Text::new(
- "This tour will be extended as more features are added.",
+ "This tour will be updated as more features are added.",
))
.push(Text::new("Make sure to keep an eye on it!"))
}
diff --git a/examples/ggez/widget.rs b/examples/ggez/widget.rs
index a5fcccc6..9a141c83 100644
--- a/examples/ggez/widget.rs
+++ b/examples/ggez/widget.rs
@@ -1,12 +1,13 @@
use super::Renderer;
-use ggez::graphics::Color;
+use ggez::graphics::{self, Color};
pub use iced::{button, slider, Button, Slider};
pub type Text = iced::Text<Color>;
pub type Checkbox<Message> = iced::Checkbox<Color, Message>;
pub type Radio<Message> = iced::Radio<Color, Message>;
+pub type Image = iced::Image<graphics::Image>;
pub type Column<'a, Message> = iced::Column<'a, Message, Renderer<'a>>;
pub type Row<'a, Message> = iced::Row<'a, Message, Renderer<'a>>;
diff --git a/examples/resources/Roboto-LICENSE b/examples/resources/Roboto-LICENSE
new file mode 100644
index 00000000..75b52484
--- /dev/null
+++ b/examples/resources/Roboto-LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/examples/resources/Roboto-Regular.ttf b/examples/resources/Roboto-Regular.ttf
new file mode 100644
index 00000000..2b6392ff
--- /dev/null
+++ b/examples/resources/Roboto-Regular.ttf
Binary files differ
diff --git a/examples/resources/ferris.png b/examples/resources/ferris.png
new file mode 100644
index 00000000..ebce1a14
--- /dev/null
+++ b/examples/resources/ferris.png
Binary files differ
diff --git a/src/lib.rs b/src/lib.rs
index 88a5e81e..c1c18b41 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -97,7 +97,7 @@
//! # }
//! #
//! # impl text::Renderer<[f32; 4]> for Renderer {
-//! # fn node(&self, style: Style, _content: &str, _size: f32) -> Node {
+//! # fn node(&self, style: Style, _content: &str, _size: Option<u16>) -> Node {
//! # Node::new(style)
//! # }
//! #
@@ -105,7 +105,7 @@
//! # &mut self,
//! # _bounds: Rectangle,
//! # _content: &str,
-//! # _size: f32,
+//! # _size: Option<u16>,
//! # _color: Option<[f32; 4]>,
//! # _horizontal_alignment: HorizontalAlignment,
//! # _vertical_alignment: VerticalAlignment,
diff --git a/src/style.rs b/src/style.rs
index 9e1f7df2..575ea366 100644
--- a/src/style.rs
+++ b/src/style.rs
@@ -11,7 +11,7 @@ impl Style {
/// Defines the width of a [`Node`] in pixels.
///
/// [`Node`]: struct.Node.html
- pub fn width(mut self, width: u32) -> Self {
+ pub fn width(mut self, width: u16) -> Self {
self.0.size.width = style::Dimension::Points(width as f32);
self
}
@@ -19,7 +19,7 @@ impl Style {
/// Defines the height of a [`Node`] in pixels.
///
/// [`Node`]: struct.Node.html
- pub fn height(mut self, height: u32) -> Self {
+ pub fn height(mut self, height: u16) -> Self {
self.0.size.height = style::Dimension::Points(height as f32);
self
}
@@ -27,7 +27,7 @@ impl Style {
/// Defines the minimum width of a [`Node`] in pixels.
///
/// [`Node`]: struct.Node.html
- pub fn min_width(mut self, min_width: u32) -> Self {
+ pub fn min_width(mut self, min_width: u16) -> Self {
self.0.min_size.width = style::Dimension::Points(min_width as f32);
self
}
@@ -35,7 +35,7 @@ impl Style {
/// Defines the maximum width of a [`Node`] in pixels.
///
/// [`Node`]: struct.Node.html
- pub fn max_width(mut self, max_width: u32) -> Self {
+ pub fn max_width(mut self, max_width: u16) -> Self {
self.0.max_size.width = style::Dimension::Points(max_width as f32);
self.fill_width()
}
@@ -43,16 +43,18 @@ impl Style {
/// Defines the minimum height of a [`Node`] in pixels.
///
/// [`Node`]: struct.Node.html
- pub fn min_height(mut self, min_height: u32) -> Self {
- self.0.min_size.height = style::Dimension::Points(min_height as f32);
+ pub fn min_height(mut self, min_height: u16) -> Self {
+ self.0.min_size.height =
+ style::Dimension::Points(f32::from(min_height));
self
}
/// Defines the maximum height of a [`Node`] in pixels.
///
/// [`Node`]: struct.Node.html
- pub fn max_height(mut self, max_height: u32) -> Self {
- self.0.max_size.height = style::Dimension::Points(max_height as f32);
+ pub fn max_height(mut self, max_height: u16) -> Self {
+ self.0.max_size.height =
+ style::Dimension::Points(f32::from(max_height));
self.fill_height()
}
@@ -100,7 +102,7 @@ impl Style {
/// Sets the padding of a [`Node`] in pixels.
///
/// [`Node`]: struct.Node.html
- pub fn padding(mut self, px: u32) -> Self {
+ pub fn padding(mut self, px: u16) -> Self {
self.0.padding = stretch::geometry::Rect {
start: style::Dimension::Points(px as f32),
end: style::Dimension::Points(px as f32),
diff --git a/src/widget.rs b/src/widget.rs
index b8ecb409..30606934 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -26,16 +26,16 @@ mod row;
pub mod button;
pub mod checkbox;
pub mod image;
-pub mod progress_bar;
+//pub mod progress_bar;
pub mod radio;
pub mod slider;
pub mod text;
pub use button::Button;
pub use checkbox::Checkbox;
-pub use image::Image;
pub use column::Column;
-pub use progress_bar::ProgressBar;
+pub use image::Image;
+//pub use progress_bar::ProgressBar;
pub use radio::Radio;
pub use row::Row;
pub use slider::Slider;
diff --git a/src/widget/button.rs b/src/widget/button.rs
index 14fd3852..abcdbfeb 100644
--- a/src/widget/button.rs
+++ b/src/widget/button.rs
@@ -83,7 +83,7 @@ impl<'a, Message> Button<'a, Message> {
/// Sets the width of the [`Button`] in pixels.
///
/// [`Button`]: struct.Button.html
- pub fn width(mut self, width: u32) -> Self {
+ pub fn width(mut self, width: u16) -> Self {
self.style = self.style.width(width);
self
}
diff --git a/src/widget/checkbox.rs b/src/widget/checkbox.rs
index 34d5df53..c60807fd 100644
--- a/src/widget/checkbox.rs
+++ b/src/widget/checkbox.rs
@@ -142,7 +142,7 @@ where
renderer,
text_bounds,
&self.label,
- 20.0,
+ None,
self.label_color,
text::HorizontalAlignment::Left,
text::VerticalAlignment::Top,
diff --git a/src/widget/column.rs b/src/widget/column.rs
index 903de897..ff754e98 100644
--- a/src/widget/column.rs
+++ b/src/widget/column.rs
@@ -55,7 +55,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
/// Sets the padding of the [`Column`] in pixels.
///
/// [`Column`]: struct.Column.html
- pub fn padding(mut self, px: u32) -> Self {
+ pub fn padding(mut self, px: u16) -> Self {
self.style = self.style.padding(px);
self
}
@@ -63,7 +63,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
/// Sets the width of the [`Column`] in pixels.
///
/// [`Column`]: struct.Column.html
- pub fn width(mut self, width: u32) -> Self {
+ pub fn width(mut self, width: u16) -> Self {
self.style = self.style.width(width);
self
}
@@ -71,7 +71,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
/// Sets the height of the [`Column`] in pixels.
///
/// [`Column`]: struct.Column.html
- pub fn height(mut self, height: u32) -> Self {
+ pub fn height(mut self, height: u16) -> Self {
self.style = self.style.height(height);
self
}
@@ -79,7 +79,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
/// Sets the maximum width of the [`Column`] in pixels.
///
/// [`Column`]: struct.Column.html
- pub fn max_width(mut self, max_width: u32) -> Self {
+ pub fn max_width(mut self, max_width: u16) -> Self {
self.style = self.style.max_width(max_width);
self
}
@@ -87,7 +87,7 @@ impl<'a, Message, Renderer> Column<'a, Message, Renderer> {
/// Sets the maximum height of the [`Column`] in pixels.
///
/// [`Column`]: struct.Column.html
- pub fn max_height(mut self, max_height: u32) -> Self {
+ pub fn max_height(mut self, max_height: u16) -> Self {
self.style = self.style.max_height(max_height);
self
}
diff --git a/src/widget/image.rs b/src/widget/image.rs
index 8cbcd02c..161dc963 100644
--- a/src/widget/image.rs
+++ b/src/widget/image.rs
@@ -1,7 +1,8 @@
//! Display images in your user interface.
use crate::{
- Element, Hasher, Layout, MouseCursor, Node, Point, Rectangle, Style, Widget,
+ Align, Element, Hasher, Layout, MouseCursor, Node, Point, Rectangle, Style,
+ Widget,
};
use std::hash::Hash;
@@ -25,6 +26,8 @@ use std::hash::Hash;
pub struct Image<I> {
image: I,
source: Option<Rectangle<u16>>,
+ width: Option<u16>,
+ height: Option<u16>,
style: Style,
}
@@ -32,6 +35,8 @@ impl<I> std::fmt::Debug for Image<I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Image")
.field("source", &self.source)
+ .field("width", &self.width)
+ .field("height", &self.height)
.field("style", &self.style)
.finish()
}
@@ -45,7 +50,9 @@ impl<I> Image<I> {
Image {
image,
source: None,
- style: Style::default().fill_width().fill_height(),
+ width: None,
+ height: None,
+ style: Style::default(),
}
}
@@ -60,16 +67,27 @@ impl<I> Image<I> {
/// Sets the width of the [`Image`] boundaries in pixels.
///
/// [`Image`]: struct.Image.html
- pub fn width(mut self, width: u32) -> Self {
- self.style = self.style.width(width);
+ pub fn width(mut self, width: u16) -> Self {
+ self.width = Some(width);
self
}
/// Sets the height of the [`Image`] boundaries in pixels.
///
/// [`Image`]: struct.Image.html
- pub fn height(mut self, height: u32) -> Self {
- self.style = self.style.height(height);
+ pub fn height(mut self, height: u16) -> Self {
+ self.height = Some(height);
+ self
+ }
+
+ /// Sets the alignment of the [`Image`] itself.
+ ///
+ /// This is useful if you want to override the default alignment given by
+ /// the parent container.
+ ///
+ /// [`Image`]: struct.Button.html
+ pub fn align_self(mut self, align: Align) -> Self {
+ self.style = self.style.align_self(align);
self
}
}
@@ -79,8 +97,14 @@ where
Renderer: self::Renderer<I>,
I: Clone,
{
- fn node(&self, _renderer: &Renderer) -> Node {
- Node::new(self.style)
+ fn node(&self, renderer: &Renderer) -> Node {
+ renderer.node(
+ self.style,
+ &self.image,
+ self.width,
+ self.height,
+ self.source,
+ )
}
fn draw(
@@ -89,13 +113,15 @@ where
layout: Layout<'_>,
_cursor_position: Point,
) -> MouseCursor {
- renderer.draw(layout.bounds(), self.image.clone(), self.source);
+ renderer.draw(&self.image, layout.bounds(), self.source);
MouseCursor::OutOfBounds
}
fn hash_layout(&self, state: &mut Hasher) {
self.style.hash(state);
+ self.width.hash(state);
+ self.height.hash(state);
}
}
@@ -107,6 +133,23 @@ where
/// [`Image`]: struct.Image.html
/// [renderer]: ../../renderer/index.html
pub trait Renderer<I> {
+ /// Creates a [`Node`] with the given [`Style`] for the provided [`Image`]
+ /// and its size.
+ ///
+ /// You should probably keep the original aspect ratio, if possible.
+ ///
+ /// [`Node`]: ../../struct.Node.html
+ /// [`Style`]: ../../struct.Style.html
+ /// [`Image`]: struct.Image.html
+ fn node(
+ &self,
+ style: Style,
+ image: &I,
+ width: Option<u16>,
+ height: Option<u16>,
+ source: Option<Rectangle<u16>>,
+ ) -> Node;
+
/// Draws an [`Image`].
///
/// It receives:
@@ -118,8 +161,8 @@ pub trait Renderer<I> {
/// [`Image`]: struct.Image.html
fn draw(
&mut self,
+ image: &I,
bounds: Rectangle<f32>,
- image: I,
source: Option<Rectangle<u16>>,
);
}
diff --git a/src/widget/progress_bar.rs b/src/widget/progress_bar.rs
index 645c7277..d4499160 100644
--- a/src/widget/progress_bar.rs
+++ b/src/widget/progress_bar.rs
@@ -47,7 +47,7 @@ impl ProgressBar {
/// Sets the width of the [`ProgressBar`] in pixels.
///
/// [`ProgressBar`]: struct.ProgressBar.html
- pub fn width(mut self, width: u32) -> Self {
+ pub fn width(mut self, width: u16) -> Self {
self.style = self.style.width(width);
self
}
diff --git a/src/widget/radio.rs b/src/widget/radio.rs
index a59d52aa..28353ef4 100644
--- a/src/widget/radio.rs
+++ b/src/widget/radio.rs
@@ -152,7 +152,7 @@ where
renderer,
text_bounds,
&self.label,
- 20.0,
+ None,
self.label_color,
text::HorizontalAlignment::Left,
text::VerticalAlignment::Top,
diff --git a/src/widget/row.rs b/src/widget/row.rs
index 7b7033a1..959528dc 100644
--- a/src/widget/row.rs
+++ b/src/widget/row.rs
@@ -52,7 +52,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
/// Sets the padding of the [`Row`] in pixels.
///
/// [`Row`]: struct.Row.html
- pub fn padding(mut self, px: u32) -> Self {
+ pub fn padding(mut self, px: u16) -> Self {
self.style = self.style.padding(px);
self
}
@@ -60,7 +60,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
/// Sets the width of the [`Row`] in pixels.
///
/// [`Row`]: struct.Row.html
- pub fn width(mut self, width: u32) -> Self {
+ pub fn width(mut self, width: u16) -> Self {
self.style = self.style.width(width);
self
}
@@ -68,7 +68,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
/// Sets the height of the [`Row`] in pixels.
///
/// [`Row`]: struct.Row.html
- pub fn height(mut self, height: u32) -> Self {
+ pub fn height(mut self, height: u16) -> Self {
self.style = self.style.height(height);
self
}
@@ -76,7 +76,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
/// Sets the maximum width of the [`Row`] in pixels.
///
/// [`Row`]: struct.Row.html
- pub fn max_width(mut self, max_width: u32) -> Self {
+ pub fn max_width(mut self, max_width: u16) -> Self {
self.style = self.style.max_width(max_width);
self
}
@@ -84,7 +84,7 @@ impl<'a, Message, Renderer> Row<'a, Message, Renderer> {
/// Sets the maximum height of the [`Row`] in pixels.
///
/// [`Row`]: struct.Row.html
- pub fn max_height(mut self, max_height: u32) -> Self {
+ pub fn max_height(mut self, max_height: u16) -> Self {
self.style = self.style.max_height(max_height);
self
}
diff --git a/src/widget/slider.rs b/src/widget/slider.rs
index c7adbb51..cdec9ec4 100644
--- a/src/widget/slider.rs
+++ b/src/widget/slider.rs
@@ -93,7 +93,7 @@ impl<'a, Message> Slider<'a, Message> {
/// Sets the width of the [`Slider`] in pixels.
///
/// [`Slider`]: struct.Slider.html
- pub fn width(mut self, width: u32) -> Self {
+ pub fn width(mut self, width: u16) -> Self {
self.style = self.style.width(width);
self
}
diff --git a/src/widget/text.rs b/src/widget/text.rs
index 7b62e5cb..59b599bb 100644
--- a/src/widget/text.rs
+++ b/src/widget/text.rs
@@ -30,7 +30,7 @@ use std::hash::Hash;
#[derive(Debug, Clone)]
pub struct Text<Color> {
content: String,
- size: u16,
+ size: Option<u16>,
color: Option<Color>,
style: Style,
horizontal_alignment: HorizontalAlignment,
@@ -44,7 +44,7 @@ impl<Color> Text<Color> {
pub fn new(label: &str) -> Self {
Text {
content: String::from(label),
- size: 20,
+ size: None,
color: None,
style: Style::default().fill_width(),
horizontal_alignment: HorizontalAlignment::Left,
@@ -56,7 +56,7 @@ impl<Color> Text<Color> {
///
/// [`Text`]: struct.Text.html
pub fn size(mut self, size: u16) -> Self {
- self.size = size;
+ self.size = Some(size);
self
}
@@ -71,7 +71,7 @@ impl<Color> Text<Color> {
/// Sets the width of the [`Text`] boundaries in pixels.
///
/// [`Text`]: struct.Text.html
- pub fn width(mut self, width: u32) -> Self {
+ pub fn width(mut self, width: u16) -> Self {
self.style = self.style.width(width);
self
}
@@ -79,7 +79,7 @@ impl<Color> Text<Color> {
/// Sets the height of the [`Text`] boundaries in pixels.
///
/// [`Text`]: struct.Text.html
- pub fn height(mut self, height: u32) -> Self {
+ pub fn height(mut self, height: u16) -> Self {
self.style = self.style.height(height);
self
}
@@ -112,7 +112,7 @@ where
Renderer: self::Renderer<Color>,
{
fn node(&self, renderer: &Renderer) -> Node {
- renderer.node(self.style, &self.content, f32::from(self.size))
+ renderer.node(self.style, &self.content, self.size)
}
fn draw(
@@ -124,7 +124,7 @@ where
renderer.draw(
layout.bounds(),
&self.content,
- f32::from(self.size),
+ self.size,
self.color,
self.horizontal_alignment,
self.vertical_alignment,
@@ -160,7 +160,7 @@ pub trait Renderer<Color> {
/// [`Style`]: ../../struct.Style.html
/// [`Text`]: struct.Text.html
/// [`Node::with_measure`]: ../../struct.Node.html#method.with_measure
- fn node(&self, style: Style, content: &str, size: f32) -> Node;
+ fn node(&self, style: Style, content: &str, size: Option<u16>) -> Node;
/// Draws a [`Text`] fragment.
///
@@ -179,7 +179,7 @@ pub trait Renderer<Color> {
&mut self,
bounds: Rectangle,
content: &str,
- size: f32,
+ size: Option<u16>,
color: Option<Color>,
horizontal_alignment: HorizontalAlignment,
vertical_alignment: VerticalAlignment,