//! 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::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; use iced::mouse; use iced::{Color, Element, Length, Rectangle, Size}; pub struct Circle { radius: f32, } impl Circle { pub fn new(radius: f32) -> Self { Self { radius } } } pub fn circle(radius: f32) -> Circle { Circle::new(radius) } impl Widget for Circle where Renderer: renderer::Renderer, { fn width(&self) -> Length { Length::Shrink } fn height(&self) -> Length { Length::Shrink } fn layout( &self, _tree: &widget::Tree, _renderer: &Renderer, _limits: &layout::Limits, ) -> layout::Node { layout::Node::new(Size::new(self.radius * 2.0, self.radius * 2.0)) } fn draw( &self, _state: &widget::Tree, renderer: &mut Renderer, _theme: &Renderer::Theme, _style: &renderer::Style, layout: Layout<'_>, _cursor: mouse::Cursor, _viewport: &Rectangle, ) { renderer.fill_quad( renderer::Quad { bounds: layout.bounds(), border_radius: self.radius.into(), border_width: 0.0, border_color: Color::TRANSPARENT, }, Color::BLACK, ); } } impl<'a, Message, Renderer> From for Element<'a, Message, Renderer> where Renderer: renderer::Renderer, { fn from(circle: Circle) -> Self { Self::new(circle) } } } use circle::circle; use iced::widget::{column, container, slider, text}; use iced::{Alignment, Element, Length, Sandbox, Settings}; pub fn main() -> iced::Result { Example::run(Settings::default()) } struct Example { radius: f32, } #[derive(Debug, Clone, Copy)] enum Message { RadiusChanged(f32), } impl Sandbox for Example { type Message = Message; fn new() -> Self { Example { radius: 50.0 } } fn title(&self) -> String { String::from("Custom widget - Iced") } fn update(&mut self, message: Message) { match message { Message::RadiusChanged(radius) => { self.radius = radius; } } } fn view(&self) -> Element { let content = column![ circle(self.radius), text(format!("Radius: {:.2}", self.radius)), slider(1.0..=100.0, self.radius, Message::RadiusChanged).step(0.01), ] .padding(20) .spacing(20) .max_width(500) .align_items(Alignment::Center); container(content) .width(Length::Fill) .height(Length::Fill) .center_x() .center_y() .into() } }