diff options
author | 2019-12-07 05:47:14 +0100 | |
---|---|---|
committer | 2019-12-07 05:47:14 +0100 | |
commit | 749722fca6eb9c85901e80060583559317f2af79 (patch) | |
tree | 9387a78f1ffc24b083f9070c72e86b2d64b12a06 /examples | |
parent | 05a2a619c1c44a44f5ea7aab1446b37141393205 (diff) | |
download | iced-749722fca6eb9c85901e80060583559317f2af79.tar.gz iced-749722fca6eb9c85901e80060583559317f2af79.tar.bz2 iced-749722fca6eb9c85901e80060583559317f2af79.zip |
Add `custom_widget` example
It showcases how to build a simple native custom widget that draws a
circle.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/custom_widget.rs | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/examples/custom_widget.rs b/examples/custom_widget.rs new file mode 100644 index 00000000..d51753e2 --- /dev/null +++ b/examples/custom_widget.rs @@ -0,0 +1,149 @@ +//! This example showcases a simple native custom widget that draws a circle. +mod circle { + // For now, to implement a custom native widget you will need to add + // `iced_native` and `iced_wgpu` to your dependencies. + // + // Then, you simply need to define your widget type and implement the + // `iced_native::Widget` trait with the `iced_wgpu::Renderer`. + // + // Of course, you can choose to make the implementation renderer-agnostic, + // if you wish to, by creating your own `Renderer` trait, which could be + // implemented by `iced_wgpu` and other renderers. + use iced_native::{ + layout, Background, Color, Element, Hasher, Layout, Length, + MouseCursor, Point, Size, Widget, + }; + use iced_wgpu::{Primitive, Renderer}; + + pub struct Circle { + radius: u16, + } + + impl Circle { + pub fn new(radius: u16) -> Self { + Self { radius } + } + } + + impl<Message> Widget<Message, Renderer> for Circle { + fn width(&self) -> Length { + Length::Shrink + } + + fn height(&self) -> Length { + Length::Shrink + } + + fn layout( + &self, + _renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + let size = limits + .width(Length::Units(self.radius * 2)) + .height(Length::Units(self.radius * 2)) + .resolve(Size::ZERO); + + layout::Node::new(size) + } + + fn hash_layout(&self, state: &mut Hasher) { + use std::hash::Hash; + + self.radius.hash(state); + } + + fn draw( + &self, + _renderer: &mut Renderer, + layout: Layout<'_>, + _cursor_position: Point, + ) -> (Primitive, MouseCursor) { + let bounds = layout.bounds(); + + ( + Primitive::Quad { + bounds, + background: Background::Color(Color::BLACK), + border_radius: self.radius, + }, + MouseCursor::OutOfBounds, + ) + } + } + + impl<'a, Message> Into<Element<'a, Message, Renderer>> for Circle { + fn into(self) -> Element<'a, Message, Renderer> { + Element::new(self) + } + } +} + +use circle::Circle; +use iced::{ + slider, Align, Column, Container, Element, Length, Sandbox, Settings, + Slider, Text, +}; + +pub fn main() { + Example::run(Settings::default()) +} + +struct Example { + radius: u16, + slider: slider::State, +} + +#[derive(Debug, Clone, Copy)] +enum Message { + RadiusChanged(f32), +} + +impl Sandbox for Example { + type Message = Message; + + fn new() -> Self { + Example { + radius: 50, + slider: slider::State::new(), + } + } + + fn title(&self) -> String { + String::from("Custom widget - Iced") + } + + fn update(&mut self, message: Message) { + match message { + Message::RadiusChanged(radius) => { + self.radius = radius.round() as u16; + } + } + } + + fn view(&mut self) -> Element<Message> { + let content = Column::new() + .padding(20) + .spacing(20) + .max_width(500) + .align_items(Align::Center) + .push(Circle::new(self.radius)) + .push( + Text::new(format!("Radius: {}", self.radius.to_string())) + .width(Length::Shrink), + ) + .push(Slider::new( + &mut self.slider, + 1.0..=100.0, + f32::from(self.radius), + Message::RadiusChanged, + )); + + Container::new(content) + .width(Length::Fill) + .height(Length::Fill) + .center_x() + .center_y() + .into() + } +} |