deLyrium/src/file_select.rs

166 lines
4.3 KiB
Rust

use iced::canvas::event::Status;
use iced::Font;
use iced::canvas::Text;
use iced::canvas::Stroke;
use iced::Size;
use iced::Point;
use iced::canvas::Path;
use iced::canvas::Frame;
use iced::canvas::Geometry;
use iced::canvas::Cursor;
use iced::Element;
use crate::app::Message;
use iced::canvas::Program;
use iced::mouse;
use iced::Color;
use iced::Rectangle;
use iced::Length;
use iced::alignment::{Vertical, Horizontal};
use iced::widget::canvas::{self, Canvas};
/* RYGCBM
const COLORS: [Color; 6] = [
Color { r: 1., g: 0., b: 0., a: 1. },
Color { r: 1., g: 1., b: 0., a: 1. },
Color { r: 0., g: 1., b: 0., a: 1. },
Color { r: 0., g: 1., b: 1., a: 1. },
Color { r: 0., g: 0., b: 1., a: 1. },
Color { r: 1., g: 0., b: 1., a: 1. },
];*/
#[allow(clippy::eq_op)]
const COLORS: [Color; 6] = [
Color { r: 255./255., g: 129./255., b: 126./255., a: 1. },
Color { r: 239./255., g: 190./255., b: 125./255., a: 1. },
Color { r: 233./255., g: 236./255., b: 107./255., a: 1. },
Color { r: 119./255., g: 221./255., b: 119./255., a: 1. },
Color { r: 139./255., g: 211./255., b: 230./255., a: 1. },
Color { r: 177./255., g: 162./255., b: 202./255., a: 1. },
];
const MAX_TICKS: usize = 900;
const FONT_MR_PIXEL: Font = Font::External {
name: "Mister Pixel",
bytes: include_bytes!("../fonts/mister-pixel/mister-pixel.otf"),
};
pub fn view_fileselector(tick: usize) -> Element<'static, Message> {
Canvas::new(tick)
.width(Length::Fill)
.height(Length::Fill)
.into()
}
impl Program<Message> for usize {
fn draw(&self, bounds: Rectangle, _cursor: Cursor) -> Vec<Geometry> {
let tick = self;
let offset_per_index = MAX_TICKS / COLORS.len();
const TEXT_RECT_W: f32 = 350.;
const TEXT_RECT_H: f32 = 50.;
const RECT_RATIO: f32 = TEXT_RECT_W / TEXT_RECT_H;
let text_rect_scale = TEXT_RECT_W / bounds.width;
let text_rect: (Point, Size) = centered_rectangle(&bounds, RECT_RATIO, text_rect_scale);
let text_rect_far_point = Point {
x: text_rect.0.x + text_rect.1.width,
y: text_rect.0.y + text_rect.1.height,
};
let bound_far_point: Point = Point {
x: bounds.x + bounds.width,
y: bounds.y + bounds.height,
};
let mut frame = Frame::new(bounds.size());
frame.fill_rectangle(
Point::new(bounds.x, bounds.y),
Size::new(bounds.width, bounds.height),
Color::WHITE,
);
COLORS.iter()
.enumerate()
.map(|(index, color)| {
let size =
((tick + offset_per_index * index) % MAX_TICKS) as f32 /
MAX_TICKS as f32;
let top_left = interpolate(text_rect.0, Point::ORIGIN, size);
let far_corner = interpolate(text_rect_far_point, bound_far_point, size);
let rect_size = Size::new(far_corner.x - top_left.x, far_corner.y - top_left.y);
(Path::rectangle(top_left, rect_size), color)
})
.for_each(|(rect, color)|
frame.stroke(
&rect,
Stroke::default()
.with_color(*color)
.with_width(5.)
)
);
frame.fill_text(
Text {
content: String::from("select a song to start"),
horizontal_alignment: Horizontal::Center,
vertical_alignment: Vertical::Center,
size: 32.,
color: Color::WHITE,
font: FONT_MR_PIXEL,
position: Point::new(
bounds.x + bounds.width * 0.5,
bounds.y + bounds.height * 0.5,
),
}
);
frame.fill(
&Path::rectangle(text_rect.0, text_rect.1),
Color::BLACK,
);
frame.stroke(
&Path::rectangle(text_rect.0, text_rect.1),
Stroke::default()
.with_color(Color::BLACK)
.with_width(2.)
);
vec![frame.into_geometry()]
}
fn update(
&mut self,
event: canvas::Event,
_: Rectangle<f32>,
_: Cursor
) -> (Status, Option<Message>) {
match event {
canvas::Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) => {
(Status::Captured, Some(Message::PromptForFile))
},
_ => (Status::Ignored, None),
}
}
}
fn centered_rectangle(bounds: &Rectangle, ratio: f32, scale: f32) -> (Point, Size) {
let center_x = bounds.x + 0.5 * bounds.width;
let center_y = bounds.y + 0.5 * bounds.height;
let width = bounds.width * scale;
let height = width / ratio;
let top_x = center_x - width * 0.5;
let top_y = center_y - height * 0.5;
(
Point::new(top_x, top_y),
Size::new(width, height),
)
}
fn interpolate(from: Point, to: Point, amount: f32) -> Point {
Point {
x: from.x + amount * (to.x - from.x),
y: from.y + amount * (to.y - from.y),
}
}