From 536aad1270863437681584f5040c591eba5b3f8a Mon Sep 17 00:00:00 2001 From: Dukantic Date: Wed, 9 Jul 2025 11:18:15 +0200 Subject: [PATCH] timeline clickable --- src/main.rs | 32 +++++++++--------------------- src/message.rs | 22 ++++++++++++++++++++ src/music.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 29 deletions(-) create mode 100644 src/message.rs diff --git a/src/main.rs b/src/main.rs index 308637b..2174511 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,13 @@ mod polygon_draw; +use iced::widget::canvas::Program; use polygon_draw::Polygon; mod music; use music::Music; +mod message; +use message::Message; + mod utils; use utils::str_to_sec; @@ -38,28 +42,6 @@ fn main() -> iced::Result { .run_with(MyApp::new) } -#[derive(Debug, Clone)] -enum Message { - ButtonPressedIncrement, - ButtonPressedDecrement, - Tick, - AddPolygon(String), - ChangeTeta(usize, f32), - Remove(usize), - ChangeColor(usize, String), - ChangeSound(usize, String), - ToggleSavePanel, - Save, - Load, - FileNameChanged(String), - TogglePaused, - SetMusicLength, - LengthChange(String), - ChangeDelta(f32), - AddPoint, - RemovePoint, -} - struct MyApp { music: Music, time_last_frame: Instant, @@ -177,6 +159,9 @@ impl MyApp { Message::RemovePoint => { self.music.remove_point(self.current_delta); } + Message::ClickedOnTimeLine(f) => { + self.update(Message::ChangeDelta(f)); + } } } @@ -324,10 +309,11 @@ impl MyApp { ] .spacing(20), column![ + /* slider(0.0..=self.music.length, self.current_delta, move |f| { Message::ChangeDelta(f) }) - .step(&self.music.length / 10_000.), + .step(&self.music.length / 10_000.),*/ canvas(&self.music) .height(Length::FillPortion(1)) .width(Length::FillPortion(1)) diff --git a/src/message.rs b/src/message.rs new file mode 100644 index 0000000..6184463 --- /dev/null +++ b/src/message.rs @@ -0,0 +1,22 @@ +#[derive(Debug, Clone)] +pub enum Message { + ButtonPressedIncrement, + ButtonPressedDecrement, + Tick, + AddPolygon(String), + ChangeTeta(usize, f32), + Remove(usize), + ChangeColor(usize, String), + ChangeSound(usize, String), + ToggleSavePanel, + Save, + Load, + FileNameChanged(String), + TogglePaused, + SetMusicLength, + LengthChange(String), + ChangeDelta(f32), + AddPoint, + RemovePoint, + ClickedOnTimeLine(f32), +} diff --git a/src/music.rs b/src/music.rs index 0e431c7..35462f2 100644 --- a/src/music.rs +++ b/src/music.rs @@ -1,10 +1,15 @@ +use crate::message::Message; use crate::utils::string_to_polygon; use crate::{polygon_draw::*, utils::string_to_color}; use serde::{Deserialize, Serialize}; use kira::{AudioManager, sound::static_sound::StaticSoundData}; -use iced::mouse; +use iced::event::Status; +use iced::mouse::Cursor; +use iced::widget::canvas::Event; +use iced::{mouse, padding}; + use iced::widget::canvas; use iced::widget::canvas::Stroke; use iced::widget::canvas::Style; @@ -149,13 +154,13 @@ impl Music { self.find_poly_frame(delta).polygons.remove(i); } } -impl canvas::Program for Music { +impl canvas::Program for Music { // No internal state - type State = (); + type State = bool; fn draw( &self, - _state: &(), + _state: &Self::State, renderer: &Renderer, _theme: &Theme, bounds: Rectangle, @@ -166,7 +171,7 @@ impl canvas::Program for Music { let padding = 8.; let w = bounds.width - (padding * 2.); for (delta, _) in &self.poly_frame { - let x = delta / self.length * w + padding; + let x = delta / self.length * w + 8.; frame.fill_rectangle( iced::Point { x: x, y: 0.0 }, frame.size(), @@ -187,7 +192,7 @@ impl canvas::Program for Music { }, ); - let x = self.current_delta / self.length * w + padding; + let x = self.current_delta / self.length * w + 8.; frame.stroke_rectangle( iced::Point::new(x, 0.), iced::Size { @@ -204,4 +209,41 @@ impl canvas::Program for Music { // Then, we produce the geometry vec![frame.into_geometry()] } + fn update( + &self, + state: &mut Self::State, + event: Event, + bounds: Rectangle, + cursor: Cursor, + ) -> (Status, Option) { + //eprintln!("event = {:?}", event); + if let Event::Mouse(mouse_event) = event { + match mouse_event { + mouse::Event::ButtonPressed(mouse::Button::Left) => { + *state = true; + if let Some(position) = cursor.position_in(bounds) { + let pos_x = (position.x - 8.0) / (bounds.width - 16.); + let delta = (pos_x * self.length).clamp(0., self.length); + return ( + Status::Captured, + Some(crate::message::Message::ClickedOnTimeLine(delta)), + ); + } + } + mouse::Event::ButtonReleased(mouse::Button::Left) => *state = false, + mouse::Event::CursorMoved { position: _ } => { + if let Some(position) = cursor.position_in(bounds) + && *state + { + let pos_x = (position.x - 8.0) / (bounds.width - 16.); + let delta = (pos_x * self.length).clamp(0., self.length); + return (Status::Captured, Some(Message::ClickedOnTimeLine(delta))); + } + } + _ => {} + } + } + + (Status::Ignored, None) + } }