Implement reactive-rendering for canvas
This commit is contained in:
parent
a84b328dcc
commit
920596ed6f
9 changed files with 243 additions and 141 deletions
|
|
@ -57,8 +57,9 @@ impl Example {
|
|||
|
||||
mod bezier {
|
||||
use iced::mouse;
|
||||
use iced::widget::canvas::event::{self, Event};
|
||||
use iced::widget::canvas::{self, Canvas, Frame, Geometry, Path, Stroke};
|
||||
use iced::widget::canvas::{
|
||||
self, Canvas, Event, Frame, Geometry, Path, Stroke,
|
||||
};
|
||||
use iced::{Element, Fill, Point, Rectangle, Renderer, Theme};
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -96,48 +97,47 @@ mod bezier {
|
|||
event: Event,
|
||||
bounds: Rectangle,
|
||||
cursor: mouse::Cursor,
|
||||
) -> (event::Status, Option<Curve>) {
|
||||
let Some(cursor_position) = cursor.position_in(bounds) else {
|
||||
return (event::Status::Ignored, None);
|
||||
};
|
||||
) -> Option<canvas::Action<Curve>> {
|
||||
let cursor_position = cursor.position_in(bounds)?;
|
||||
|
||||
match event {
|
||||
Event::Mouse(mouse_event) => {
|
||||
let message = match mouse_event {
|
||||
mouse::Event::ButtonPressed(mouse::Button::Left) => {
|
||||
match *state {
|
||||
None => {
|
||||
*state = Some(Pending::One {
|
||||
from: cursor_position,
|
||||
});
|
||||
Event::Mouse(mouse::Event::ButtonPressed(
|
||||
mouse::Button::Left,
|
||||
)) => Some(
|
||||
match *state {
|
||||
None => {
|
||||
*state = Some(Pending::One {
|
||||
from: cursor_position,
|
||||
});
|
||||
|
||||
None
|
||||
}
|
||||
Some(Pending::One { from }) => {
|
||||
*state = Some(Pending::Two {
|
||||
from,
|
||||
to: cursor_position,
|
||||
});
|
||||
|
||||
None
|
||||
}
|
||||
Some(Pending::Two { from, to }) => {
|
||||
*state = None;
|
||||
|
||||
Some(Curve {
|
||||
from,
|
||||
to,
|
||||
control: cursor_position,
|
||||
})
|
||||
}
|
||||
}
|
||||
canvas::Action::request_redraw()
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
Some(Pending::One { from }) => {
|
||||
*state = Some(Pending::Two {
|
||||
from,
|
||||
to: cursor_position,
|
||||
});
|
||||
|
||||
(event::Status::Captured, message)
|
||||
canvas::Action::request_redraw()
|
||||
}
|
||||
Some(Pending::Two { from, to }) => {
|
||||
*state = None;
|
||||
|
||||
canvas::Action::publish(Curve {
|
||||
from,
|
||||
to,
|
||||
control: cursor_position,
|
||||
})
|
||||
}
|
||||
}
|
||||
.and_capture(),
|
||||
),
|
||||
Event::Mouse(mouse::Event::CursorMoved { .. })
|
||||
if state.is_some() =>
|
||||
{
|
||||
Some(canvas::Action::request_redraw())
|
||||
}
|
||||
_ => (event::Status::Ignored, None),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,8 +193,9 @@ mod grid {
|
|||
use iced::mouse;
|
||||
use iced::touch;
|
||||
use iced::widget::canvas;
|
||||
use iced::widget::canvas::event::{self, Event};
|
||||
use iced::widget::canvas::{Cache, Canvas, Frame, Geometry, Path, Text};
|
||||
use iced::widget::canvas::{
|
||||
Cache, Canvas, Event, Frame, Geometry, Path, Text,
|
||||
};
|
||||
use iced::{
|
||||
Color, Element, Fill, Point, Rectangle, Renderer, Size, Theme, Vector,
|
||||
};
|
||||
|
|
@ -383,14 +384,12 @@ mod grid {
|
|||
event: Event,
|
||||
bounds: Rectangle,
|
||||
cursor: mouse::Cursor,
|
||||
) -> (event::Status, Option<Message>) {
|
||||
) -> Option<canvas::Action<Message>> {
|
||||
if let Event::Mouse(mouse::Event::ButtonReleased(_)) = event {
|
||||
*interaction = Interaction::None;
|
||||
}
|
||||
|
||||
let Some(cursor_position) = cursor.position_in(bounds) else {
|
||||
return (event::Status::Ignored, None);
|
||||
};
|
||||
let cursor_position = cursor.position_in(bounds)?;
|
||||
|
||||
let cell = Cell::at(self.project(cursor_position, bounds.size()));
|
||||
let is_populated = self.state.contains(&cell);
|
||||
|
|
@ -413,7 +412,12 @@ mod grid {
|
|||
populate.or(unpopulate)
|
||||
};
|
||||
|
||||
(event::Status::Captured, message)
|
||||
Some(
|
||||
message
|
||||
.map(canvas::Action::publish)
|
||||
.unwrap_or(canvas::Action::request_redraw())
|
||||
.and_capture(),
|
||||
)
|
||||
}
|
||||
Event::Mouse(mouse_event) => match mouse_event {
|
||||
mouse::Event::ButtonPressed(button) => {
|
||||
|
|
@ -438,7 +442,12 @@ mod grid {
|
|||
_ => None,
|
||||
};
|
||||
|
||||
(event::Status::Captured, message)
|
||||
Some(
|
||||
message
|
||||
.map(canvas::Action::publish)
|
||||
.unwrap_or(canvas::Action::request_redraw())
|
||||
.and_capture(),
|
||||
)
|
||||
}
|
||||
mouse::Event::CursorMoved { .. } => {
|
||||
let message = match *interaction {
|
||||
|
|
@ -454,12 +463,14 @@ mod grid {
|
|||
Interaction::None => None,
|
||||
};
|
||||
|
||||
let event_status = match interaction {
|
||||
Interaction::None => event::Status::Ignored,
|
||||
_ => event::Status::Captured,
|
||||
};
|
||||
let action = message
|
||||
.map(canvas::Action::publish)
|
||||
.unwrap_or(canvas::Action::request_redraw());
|
||||
|
||||
(event_status, message)
|
||||
Some(match interaction {
|
||||
Interaction::None => action,
|
||||
_ => action.and_capture(),
|
||||
})
|
||||
}
|
||||
mouse::Event::WheelScrolled { delta } => match delta {
|
||||
mouse::ScrollDelta::Lines { y, .. }
|
||||
|
|
@ -496,18 +507,21 @@ mod grid {
|
|||
None
|
||||
};
|
||||
|
||||
(
|
||||
event::Status::Captured,
|
||||
Some(Message::Scaled(scaling, translation)),
|
||||
Some(
|
||||
canvas::Action::publish(Message::Scaled(
|
||||
scaling,
|
||||
translation,
|
||||
))
|
||||
.and_capture(),
|
||||
)
|
||||
} else {
|
||||
(event::Status::Captured, None)
|
||||
Some(canvas::Action::capture())
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => (event::Status::Ignored, None),
|
||||
_ => None,
|
||||
},
|
||||
_ => (event::Status::Ignored, None),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,8 @@
|
|||
//! computers like Microsoft Surface.
|
||||
use iced::mouse;
|
||||
use iced::touch;
|
||||
use iced::widget::canvas::event;
|
||||
use iced::widget::canvas::stroke::{self, Stroke};
|
||||
use iced::widget::canvas::{self, Canvas, Geometry};
|
||||
use iced::widget::canvas::{self, Canvas, Event, Geometry};
|
||||
use iced::{Color, Element, Fill, Point, Rectangle, Renderer, Theme};
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -56,25 +55,25 @@ impl canvas::Program<Message> for Multitouch {
|
|||
fn update(
|
||||
&self,
|
||||
_state: &mut Self::State,
|
||||
event: event::Event,
|
||||
event: Event,
|
||||
_bounds: Rectangle,
|
||||
_cursor: mouse::Cursor,
|
||||
) -> (event::Status, Option<Message>) {
|
||||
match event {
|
||||
event::Event::Touch(touch_event) => match touch_event {
|
||||
) -> Option<canvas::Action<Message>> {
|
||||
let message = match event {
|
||||
Event::Touch(
|
||||
touch::Event::FingerPressed { id, position }
|
||||
| touch::Event::FingerMoved { id, position } => (
|
||||
event::Status::Captured,
|
||||
Some(Message::FingerPressed { id, position }),
|
||||
),
|
||||
| touch::Event::FingerMoved { id, position },
|
||||
) => Some(Message::FingerPressed { id, position }),
|
||||
Event::Touch(
|
||||
touch::Event::FingerLifted { id, .. }
|
||||
| touch::Event::FingerLost { id, .. } => (
|
||||
event::Status::Captured,
|
||||
Some(Message::FingerLifted { id }),
|
||||
),
|
||||
},
|
||||
_ => (event::Status::Ignored, None),
|
||||
}
|
||||
| touch::Event::FingerLost { id, .. },
|
||||
) => Some(Message::FingerLifted { id }),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
message
|
||||
.map(canvas::Action::publish)
|
||||
.map(canvas::Action::and_capture)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
use iced::mouse;
|
||||
use iced::widget::canvas::event::{self, Event};
|
||||
use iced::widget::canvas::{self, Canvas, Geometry};
|
||||
use iced::widget::canvas::{self, Canvas, Event, Geometry};
|
||||
use iced::widget::{column, row, slider, text};
|
||||
use iced::{Center, Color, Fill, Point, Rectangle, Renderer, Size, Theme};
|
||||
|
||||
|
|
@ -80,26 +79,22 @@ impl canvas::Program<Message> for SierpinskiGraph {
|
|||
event: Event,
|
||||
bounds: Rectangle,
|
||||
cursor: mouse::Cursor,
|
||||
) -> (event::Status, Option<Message>) {
|
||||
let Some(cursor_position) = cursor.position_in(bounds) else {
|
||||
return (event::Status::Ignored, None);
|
||||
};
|
||||
) -> Option<canvas::Action<Message>> {
|
||||
let cursor_position = cursor.position_in(bounds)?;
|
||||
|
||||
match event {
|
||||
Event::Mouse(mouse_event) => {
|
||||
let message = match mouse_event {
|
||||
iced::mouse::Event::ButtonPressed(
|
||||
iced::mouse::Button::Left,
|
||||
) => Some(Message::PointAdded(cursor_position)),
|
||||
iced::mouse::Event::ButtonPressed(
|
||||
iced::mouse::Button::Right,
|
||||
) => Some(Message::PointRemoved),
|
||||
_ => None,
|
||||
};
|
||||
(event::Status::Captured, message)
|
||||
}
|
||||
_ => (event::Status::Ignored, None),
|
||||
Event::Mouse(mouse::Event::ButtonPressed(button)) => match button {
|
||||
mouse::Button::Left => Some(canvas::Action::publish(
|
||||
Message::PointAdded(cursor_position),
|
||||
)),
|
||||
mouse::Button::Right => {
|
||||
Some(canvas::Action::publish(Message::PointRemoved))
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
.map(canvas::Action::and_capture)
|
||||
}
|
||||
|
||||
fn draw(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue