zoom on time line
This commit is contained in:
@@ -17,12 +17,12 @@ mod gui;
|
|||||||
use gui::{load_file_view, music_view};
|
use gui::{load_file_view, music_view};
|
||||||
|
|
||||||
use iced::Font;
|
use iced::Font;
|
||||||
|
use iced::Theme;
|
||||||
use iced::{
|
use iced::{
|
||||||
Color, Event, Task,
|
Color, Event, Task,
|
||||||
event::{self, Status},
|
event::{self, Status},
|
||||||
keyboard::{Key, key::Named},
|
keyboard::{Key, key::Named},
|
||||||
};
|
};
|
||||||
use iced::Theme;
|
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
@@ -190,7 +190,6 @@ impl MyApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Message::ChangeDelta(f) => {
|
Message::ChangeDelta(f) => {
|
||||||
self.already_save = false;
|
|
||||||
self.current_delta = f;
|
self.current_delta = f;
|
||||||
self.music.fix_teta(self.current_delta);
|
self.music.fix_teta(self.current_delta);
|
||||||
// update the red dot on canvas
|
// update the red dot on canvas
|
||||||
|
|||||||
97
src/music.rs
97
src/music.rs
@@ -5,11 +5,14 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use kira::{AudioManager, sound::static_sound::StaticSoundData};
|
use kira::{AudioManager, sound::static_sound::StaticSoundData};
|
||||||
|
|
||||||
use iced::Vector;
|
|
||||||
use iced::event::Status;
|
use iced::event::Status;
|
||||||
use iced::mouse::Cursor;
|
use iced::mouse::Cursor;
|
||||||
use iced::widget::canvas::{Event, Geometry};
|
use iced::widget::canvas::{Event, Geometry};
|
||||||
use iced::{Size, mouse};
|
use iced::{
|
||||||
|
Size,
|
||||||
|
mouse::{self, ScrollDelta},
|
||||||
|
};
|
||||||
|
use iced::{Vector, keyboard};
|
||||||
|
|
||||||
use iced::widget::canvas;
|
use iced::widget::canvas;
|
||||||
use iced::widget::canvas::Stroke;
|
use iced::widget::canvas::Stroke;
|
||||||
@@ -175,13 +178,21 @@ impl Music {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
pub struct StateMusic {
|
||||||
|
mouse_left: bool,
|
||||||
|
ctrl: bool,
|
||||||
|
zoom: f32,
|
||||||
|
offset: f32,
|
||||||
|
}
|
||||||
|
|
||||||
impl canvas::Program<Message> for Music {
|
impl canvas::Program<Message> for Music {
|
||||||
// No internal state
|
// No internal state
|
||||||
type State = bool;
|
type State = StateMusic;
|
||||||
|
|
||||||
fn draw(
|
fn draw(
|
||||||
&self,
|
&self,
|
||||||
_state: &Self::State,
|
state: &Self::State,
|
||||||
renderer: &Renderer,
|
renderer: &Renderer,
|
||||||
_theme: &Theme,
|
_theme: &Theme,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
@@ -190,22 +201,26 @@ impl canvas::Program<Message> for Music {
|
|||||||
let mut geo_small_frame: Vec<Geometry> = vec![];
|
let mut geo_small_frame: Vec<Geometry> = vec![];
|
||||||
let mut geo_cursor: Vec<Geometry> = vec![];
|
let mut geo_cursor: Vec<Geometry> = vec![];
|
||||||
let frame = canvas::Frame::new(renderer, bounds.size());
|
let frame = canvas::Frame::new(renderer, bounds.size());
|
||||||
|
let global_width = bounds.width * state.zoom;
|
||||||
let mut toggle_color = true;
|
let mut toggle_color = true;
|
||||||
let padding = 8.;
|
let padding = 8.;
|
||||||
let w = bounds.width - (padding * 2.);
|
let w = global_width - (padding * 2.);
|
||||||
for (delta, polyframe) in &self.poly_frame {
|
for (delta, polyframe) in &self.poly_frame {
|
||||||
let x = delta / self.length * w + 8.;
|
let x = delta / self.length * w + 8. - state.offset;
|
||||||
let mut back_frame = canvas::Frame::new(
|
let mut back_frame = canvas::Frame::new(
|
||||||
renderer,
|
renderer,
|
||||||
Size {
|
Size {
|
||||||
width: bounds.width,
|
width: global_width.clamp(0.0, bounds.width),
|
||||||
height: bounds.height,
|
height: bounds.height,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
back_frame.fill_rectangle(
|
back_frame.fill_rectangle(
|
||||||
iced::Point { x: x, y: 0.0 },
|
iced::Point { x: x, y: 0.0 },
|
||||||
frame.size(),
|
Size {
|
||||||
|
width: global_width,
|
||||||
|
height: bounds.height,
|
||||||
|
},
|
||||||
if toggle_color {
|
if toggle_color {
|
||||||
Color::from_rgb8(27, 60, 83)
|
Color::from_rgb8(27, 60, 83)
|
||||||
} else {
|
} else {
|
||||||
@@ -217,7 +232,7 @@ impl canvas::Program<Message> for Music {
|
|||||||
let mut small_frame = canvas::Frame::new(
|
let mut small_frame = canvas::Frame::new(
|
||||||
renderer,
|
renderer,
|
||||||
Size {
|
Size {
|
||||||
width: bounds.width,
|
width: global_width.clamp(0.0, bounds.width),
|
||||||
height: bounds.height,
|
height: bounds.height,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -236,7 +251,7 @@ impl canvas::Program<Message> for Music {
|
|||||||
|
|
||||||
geo_small_frame.push(small_frame.into_geometry());
|
geo_small_frame.push(small_frame.into_geometry());
|
||||||
}
|
}
|
||||||
let x = self.current_delta / self.length * w + 8.;
|
let x = self.current_delta / self.length * w + 8. - state.offset;
|
||||||
let mut frame_cursor = canvas::Frame::new(renderer, bounds.size());
|
let mut frame_cursor = canvas::Frame::new(renderer, bounds.size());
|
||||||
frame_cursor.stroke_rectangle(
|
frame_cursor.stroke_rectangle(
|
||||||
iced::Point::new(x, 0.),
|
iced::Point::new(x, 0.),
|
||||||
@@ -251,8 +266,14 @@ impl canvas::Program<Message> for Music {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
frame_cursor.stroke_rectangle(
|
frame_cursor.stroke_rectangle(
|
||||||
iced::Point { x: 0.0, y: 0.0 },
|
iced::Point {
|
||||||
frame.size(),
|
x: -state.offset,
|
||||||
|
y: 0.0,
|
||||||
|
},
|
||||||
|
iced::Size {
|
||||||
|
width: global_width,
|
||||||
|
height: bounds.height,
|
||||||
|
},
|
||||||
Stroke {
|
Stroke {
|
||||||
width: 16.0,
|
width: 16.0,
|
||||||
style: Style::Solid(Color::from_rgb8(207, 74, 28)),
|
style: Style::Solid(Color::from_rgb8(207, 74, 28)),
|
||||||
@@ -276,12 +297,21 @@ impl canvas::Program<Message> for Music {
|
|||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
) -> (Status, Option<Message>) {
|
) -> (Status, Option<Message>) {
|
||||||
//eprintln!("event = {:?}", event);
|
//eprintln!("event = {:?}", event);
|
||||||
|
if let Event::Keyboard(keyboard_event) = &event {
|
||||||
|
match keyboard_event {
|
||||||
|
keyboard::Event::ModifiersChanged(m) => {
|
||||||
|
state.ctrl = m.control();
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
if let Event::Mouse(mouse_event) = event {
|
if let Event::Mouse(mouse_event) = event {
|
||||||
match mouse_event {
|
match mouse_event {
|
||||||
mouse::Event::ButtonPressed(mouse::Button::Left) => {
|
mouse::Event::ButtonPressed(mouse::Button::Left) => {
|
||||||
*state = true;
|
state.mouse_left = true;
|
||||||
if let Some(position) = cursor.position_in(bounds) {
|
if let Some(position) = cursor.position_in(bounds) {
|
||||||
let pos_x = (position.x - 8.0) / (bounds.width - 16.);
|
let pos_x =
|
||||||
|
(position.x + state.offset - 8.0) / (bounds.width * state.zoom - 16.);
|
||||||
let delta = (pos_x * self.length).clamp(0., self.length);
|
let delta = (pos_x * self.length).clamp(0., self.length);
|
||||||
return (
|
return (
|
||||||
Status::Captured,
|
Status::Captured,
|
||||||
@@ -289,19 +319,52 @@ impl canvas::Program<Message> for Music {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mouse::Event::ButtonReleased(mouse::Button::Left) => *state = false,
|
mouse::Event::ButtonReleased(mouse::Button::Left) => state.mouse_left = false,
|
||||||
mouse::Event::CursorMoved { position: _ } => {
|
mouse::Event::CursorMoved { position: _ } => {
|
||||||
if let Some(position) = cursor.position_in(bounds)
|
if let Some(position) = cursor.position_in(bounds)
|
||||||
&& *state
|
&& state.mouse_left
|
||||||
{
|
{
|
||||||
let pos_x = (position.x - 8.0) / (bounds.width - 16.);
|
let pos_x =
|
||||||
|
(position.x + state.offset - 8.0) / (bounds.width * state.zoom - 16.);
|
||||||
let delta = (pos_x * self.length).clamp(0., self.length);
|
let delta = (pos_x * self.length).clamp(0., self.length);
|
||||||
return (Status::Captured, Some(Message::ClickedOnTimeLine(delta)));
|
return (Status::Captured, Some(Message::ClickedOnTimeLine(delta)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mouse::Event::WheelScrolled { delta: d } => {
|
||||||
|
if state.ctrl {
|
||||||
|
match d {
|
||||||
|
ScrollDelta::Lines { x: _, y } => {
|
||||||
|
let before = bounds.width * state.zoom;
|
||||||
|
state.zoom += y / 10.;
|
||||||
|
state.offset = state.offset * (bounds.width * state.zoom) / before;
|
||||||
|
}
|
||||||
|
ScrollDelta::Pixels { x: _, y } => {
|
||||||
|
let before = bounds.width * state.zoom;
|
||||||
|
state.zoom += y / 10.;
|
||||||
|
state.offset = state.offset * (bounds.width * state.zoom) / before;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match d {
|
||||||
|
ScrollDelta::Lines { x: _, y } => {
|
||||||
|
state.offset -= y * 32. * state.zoom;
|
||||||
|
}
|
||||||
|
ScrollDelta::Pixels { x: _, y } => {
|
||||||
|
state.offset -= y * 32. * state.zoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
state.zoom = state.zoom.clamp(1.0, 10.);
|
||||||
|
if state.offset + bounds.width >= bounds.width * state.zoom {
|
||||||
|
state.offset = bounds.width * state.zoom - bounds.width
|
||||||
|
}
|
||||||
|
if state.offset <= 0. {
|
||||||
|
state.offset = 0.
|
||||||
|
}
|
||||||
|
|
||||||
(Status::Ignored, None)
|
(Status::Ignored, None)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user