In addition to draw a Quad, we can also draw texts in our widgets.
For example, suppose we would like to draw a string slice named CONTENT
.
struct MyWidgetWithText;
impl MyWidgetWithText {
const CONTENT: &'static str = " My Widget ";
fn new() -> Self {
Self
}
}
We use the Renderer's fill_text method to draw the text.
fn draw(
&self,
_state: &Tree,
renderer: &mut Renderer,
_theme: &Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor: mouse::Cursor,
viewport: &Rectangle,
) {
// ...
let bounds = layout.bounds();
renderer.fill_text(
Text {
content: Self::CONTENT,
bounds: bounds.size(),
size: renderer.default_size(),
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: Horizontal::Center,
vertical_alignment: Vertical::Center,
shaping: Shaping::default(),
},
bounds.center(),
Color::from_rgb(0.6, 0.8, 1.0),
*viewport,
);
}
The fill_text method needs the Renderer
type to implement iced::advanced::text::Renderer.
Thus we have to require this in our Widget implementation.
impl<Message, Renderer> Widget<Message, Theme, Renderer> for MyWidgetWithText
where
Renderer: iced::advanced::Renderer + iced::advanced::text::Renderer,
Since the requirement of the Renderer
type is changed, we have to change the requirement in From<MyWidgetWithText>
for Element, too.
impl<'a, Message, Renderer> From<MyWidgetWithText> for Element<'a, Message, Theme, Renderer>
where
Renderer: iced::advanced::Renderer + iced::advanced::text::Renderer,
The full code is as follows:
use iced::{
advanced::{
layout, mouse,
renderer::{self, Quad},
widget::Tree,
Layout, Text, Widget,
},
alignment::{Horizontal, Vertical},
widget::{
container,
text::{LineHeight, Shaping},
},
Border, Color, Element, Length, Rectangle, Sandbox, Settings, Shadow, Size, Theme,
};
fn main() -> iced::Result {
MyApp::run(Settings::default())
}
struct MyApp;
impl Sandbox for MyApp {
type Message = ();
fn new() -> Self {
Self
}
fn title(&self) -> String {
String::from("My App")
}
fn update(&mut self, _message: Self::Message) {}
fn view(&self) -> iced::Element<'_, Self::Message> {
container(MyWidgetWithText::new())
.width(Length::Fill)
.height(Length::Fill)
.center_x()
.center_y()
.into()
}
}
struct MyWidgetWithText;
impl MyWidgetWithText {
const CONTENT: &'static str = "My Widget";
fn new() -> Self {
Self
}
}
impl<Message, Renderer> Widget<Message, Theme, Renderer> for MyWidgetWithText
where
Renderer: iced::advanced::Renderer + iced::advanced::text::Renderer,
{
fn size(&self) -> Size<Length> {
Size {
width: Length::Shrink,
height: Length::Shrink,
}
}
fn layout(
&self,
_tree: &mut Tree,
_renderer: &Renderer,
_limits: &layout::Limits,
) -> layout::Node {
layout::Node::new([200, 100].into())
}
fn draw(
&self,
_state: &Tree,
renderer: &mut Renderer,
_theme: &Theme,
_style: &renderer::Style,
layout: Layout<'_>,
_cursor: mouse::Cursor,
viewport: &Rectangle,
) {
renderer.fill_quad(
Quad {
bounds: layout.bounds(),
border: Border {
color: Color::from_rgb(0.6, 0.8, 1.0),
width: 1.0,
radius: 10.0.into(),
},
shadow: Shadow::default(),
},
Color::from_rgb(0.0, 0.2, 0.4),
);
let bounds = layout.bounds();
renderer.fill_text(
Text {
content: Self::CONTENT,
bounds: bounds.size(),
size: renderer.default_size(),
line_height: LineHeight::default(),
font: renderer.default_font(),
horizontal_alignment: Horizontal::Center,
vertical_alignment: Vertical::Center,
shaping: Shaping::default(),
},
bounds.center(),
Color::from_rgb(0.6, 0.8, 1.0),
*viewport,
);
}
}
impl<'a, Message, Renderer> From<MyWidgetWithText> for Element<'a, Message, Theme, Renderer>
where
Renderer: iced::advanced::Renderer + iced::advanced::text::Renderer,
{
fn from(widget: MyWidgetWithText) -> Self {
Self::new(widget)
}
}
➡️ Next: Custom Background
📘 Back: Table of contents