summaryrefslogtreecommitdiffstats
path: root/examples/bezier_tool.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-01-20 06:27:01 +0100
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-01-20 06:27:01 +0100
commit7cea7371150e6de28032827519936008592f112d (patch)
tree3bfd82272094ef69493de622af6c9b06389a7c27 /examples/bezier_tool.rs
parent04086a90c9e933ebfb42de378054e1115b33529d (diff)
downloadiced-7cea7371150e6de28032827519936008592f112d.tar.gz
iced-7cea7371150e6de28032827519936008592f112d.tar.bz2
iced-7cea7371150e6de28032827519936008592f112d.zip
Package examples and remove `dev-dependencies`
Diffstat (limited to 'examples/bezier_tool.rs')
-rw-r--r--examples/bezier_tool.rs366
1 files changed, 0 insertions, 366 deletions
diff --git a/examples/bezier_tool.rs b/examples/bezier_tool.rs
deleted file mode 100644
index 043d265c..00000000
--- a/examples/bezier_tool.rs
+++ /dev/null
@@ -1,366 +0,0 @@
-//! This example showcases a simple native custom widget that renders arbitrary
-//! path with `lyon`.
-mod bezier {
- // 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::{
- input, layout, Clipboard, Color, Element, Event, Font, Hasher,
- HorizontalAlignment, Layout, Length, MouseCursor, Point, Size, Vector,
- VerticalAlignment, Widget,
- };
- use iced_wgpu::{
- triangle::{Mesh2D, Vertex2D},
- Defaults, Primitive, Renderer,
- };
- use lyon::tessellation::{
- basic_shapes, BuffersBuilder, StrokeAttributes, StrokeOptions,
- StrokeTessellator, VertexBuffers,
- };
- use std::sync::Arc;
-
- pub struct Bezier<'a, Message> {
- state: &'a mut State,
- curves: &'a [Curve],
- // [from, to, ctrl]
- on_click: Box<dyn Fn(Curve) -> Message>,
- }
-
- #[derive(Debug, Clone, Copy)]
- pub struct Curve {
- from: Point,
- to: Point,
- control: Point,
- }
-
- #[derive(Default)]
- pub struct State {
- pending: Option<Pending>,
- }
-
- enum Pending {
- One { from: Point },
- Two { from: Point, to: Point },
- }
-
- impl<'a, Message> Bezier<'a, Message> {
- pub fn new<F>(
- state: &'a mut State,
- curves: &'a [Curve],
- on_click: F,
- ) -> Self
- where
- F: 'static + Fn(Curve) -> Message,
- {
- Self {
- state,
- curves,
- on_click: Box::new(on_click),
- }
- }
- }
-
- impl<'a, Message> Widget<Message, Renderer> for Bezier<'a, Message> {
- fn width(&self) -> Length {
- Length::Fill
- }
-
- fn height(&self) -> Length {
- Length::Fill
- }
-
- fn layout(
- &self,
- _renderer: &Renderer,
- limits: &layout::Limits,
- ) -> layout::Node {
- let size = limits
- .height(Length::Fill)
- .width(Length::Fill)
- .resolve(Size::ZERO);
- layout::Node::new(size)
- }
-
- fn draw(
- &self,
- _renderer: &mut Renderer,
- defaults: &Defaults,
- layout: Layout<'_>,
- cursor_position: Point,
- ) -> (Primitive, MouseCursor) {
- let mut buffer: VertexBuffers<Vertex2D, u16> = VertexBuffers::new();
- let mut path_builder = lyon::path::Path::builder();
-
- let bounds = layout.bounds();
-
- // Draw rectangle border with lyon.
- basic_shapes::stroke_rectangle(
- &lyon::math::Rect::new(
- lyon::math::Point::new(bounds.x + 0.5, bounds.y + 0.5),
- lyon::math::Size::new(
- bounds.width - 1.0,
- bounds.height - 1.0,
- ),
- ),
- &StrokeOptions::default().with_line_width(1.0),
- &mut BuffersBuilder::new(
- &mut buffer,
- |pos: lyon::math::Point, _: StrokeAttributes| Vertex2D {
- position: pos.to_array(),
- color: [0.0, 0.0, 0.0, 1.0],
- },
- ),
- )
- .unwrap();
-
- for curve in self.curves {
- path_builder.move_to(lyon::math::Point::new(
- curve.from.x + bounds.x,
- curve.from.y + bounds.y,
- ));
-
- path_builder.quadratic_bezier_to(
- lyon::math::Point::new(
- curve.control.x + bounds.x,
- curve.control.y + bounds.y,
- ),
- lyon::math::Point::new(
- curve.to.x + bounds.x,
- curve.to.y + bounds.y,
- ),
- );
- }
-
- match self.state.pending {
- None => {}
- Some(Pending::One { from }) => {
- path_builder.move_to(lyon::math::Point::new(
- from.x + bounds.x,
- from.y + bounds.y,
- ));
- path_builder.line_to(lyon::math::Point::new(
- cursor_position.x,
- cursor_position.y,
- ));
- }
- Some(Pending::Two { from, to }) => {
- path_builder.move_to(lyon::math::Point::new(
- from.x + bounds.x,
- from.y + bounds.y,
- ));
- path_builder.quadratic_bezier_to(
- lyon::math::Point::new(
- cursor_position.x,
- cursor_position.y,
- ),
- lyon::math::Point::new(
- to.x + bounds.x,
- to.y + bounds.y,
- ),
- );
- }
- }
-
- let mut tessellator = StrokeTessellator::new();
-
- // Draw strokes with lyon.
- tessellator
- .tessellate(
- &path_builder.build(),
- &StrokeOptions::default().with_line_width(3.0),
- &mut BuffersBuilder::new(
- &mut buffer,
- |pos: lyon::math::Point, _: StrokeAttributes| {
- Vertex2D {
- position: pos.to_array(),
- color: [0.0, 0.0, 0.0, 1.0],
- }
- },
- ),
- )
- .unwrap();
-
- let mesh = Primitive::Mesh2D(Arc::new(Mesh2D {
- vertices: buffer.vertices,
- indices: buffer.indices,
- }));
-
- (
- Primitive::Clip {
- bounds,
- offset: Vector::new(0, 0),
- content: Box::new(
- if self.curves.is_empty()
- && self.state.pending.is_none()
- {
- let instructions = Primitive::Text {
- bounds,
- color: Color {
- a: defaults.text.color.a * 0.7,
- ..defaults.text.color
- },
- content: String::from(
- "Click to create bezier curves!",
- ),
- font: Font::Default,
- size: 30.0,
- horizontal_alignment:
- HorizontalAlignment::Center,
- vertical_alignment: VerticalAlignment::Center,
- };
-
- Primitive::Group {
- primitives: vec![mesh, instructions],
- }
- } else {
- mesh
- },
- ),
- },
- MouseCursor::OutOfBounds,
- )
- }
-
- fn hash_layout(&self, _state: &mut Hasher) {}
-
- fn on_event(
- &mut self,
- event: Event,
- layout: Layout<'_>,
- cursor_position: Point,
- messages: &mut Vec<Message>,
- _renderer: &Renderer,
- _clipboard: Option<&dyn Clipboard>,
- ) {
- let bounds = layout.bounds();
-
- if bounds.contains(cursor_position) {
- match event {
- Event::Mouse(input::mouse::Event::Input {
- state: input::ButtonState::Pressed,
- ..
- }) => {
- let new_point = Point::new(
- cursor_position.x - bounds.x,
- cursor_position.y - bounds.y,
- );
-
- match self.state.pending {
- None => {
- self.state.pending =
- Some(Pending::One { from: new_point });
- }
- Some(Pending::One { from }) => {
- self.state.pending = Some(Pending::Two {
- from,
- to: new_point,
- });
- }
- Some(Pending::Two { from, to }) => {
- self.state.pending = None;
-
- messages.push((self.on_click)(Curve {
- from,
- to,
- control: new_point,
- }));
- }
- }
- }
- _ => {}
- }
- }
- }
- }
-
- impl<'a, Message> Into<Element<'a, Message, Renderer>> for Bezier<'a, Message>
- where
- Message: 'static,
- {
- fn into(self) -> Element<'a, Message, Renderer> {
- Element::new(self)
- }
- }
-}
-
-use bezier::Bezier;
-use iced::{
- button, Align, Button, Column, Container, Element, Length, Sandbox,
- Settings, Text,
-};
-
-pub fn main() {
- Example::run(Settings::default())
-}
-
-#[derive(Default)]
-struct Example {
- bezier: bezier::State,
- curves: Vec<bezier::Curve>,
- button_state: button::State,
-}
-
-#[derive(Debug, Clone, Copy)]
-enum Message {
- AddCurve(bezier::Curve),
- Clear,
-}
-
-impl Sandbox for Example {
- type Message = Message;
-
- fn new() -> Self {
- Example::default()
- }
-
- fn title(&self) -> String {
- String::from("Bezier tool - Iced")
- }
-
- fn update(&mut self, message: Message) {
- match message {
- Message::AddCurve(curve) => {
- self.curves.push(curve);
- }
- Message::Clear => {
- self.bezier = bezier::State::default();
- self.curves.clear();
- }
- }
- }
-
- fn view(&mut self) -> Element<Message> {
- let content = Column::new()
- .padding(20)
- .spacing(20)
- .align_items(Align::Center)
- .push(
- Text::new("Bezier tool example")
- .width(Length::Shrink)
- .size(50),
- )
- .push(Bezier::new(
- &mut self.bezier,
- self.curves.as_slice(),
- Message::AddCurve,
- ))
- .push(
- Button::new(&mut self.button_state, Text::new("Clear"))
- .padding(8)
- .on_press(Message::Clear),
- );
-
- Container::new(content)
- .width(Length::Fill)
- .height(Length::Fill)
- .center_x()
- .center_y()
- .into()
- }
-}