danceinterpreter_rs/ui/
song_window.rs1use crate::Window;
2use crate::{DanceInterpreter, Message};
3use iced::Size;
4use iced::advanced::text::Shaping;
5use iced::alignment::{Horizontal, Vertical};
6use iced::widget::space::horizontal;
7use iced::widget::text::LineHeight;
8use iced::widget::{Text, column, image, row, stack};
9use iced::{Element, Length, window};
10
11pub struct SongWindow {
12 pub id: window::Id,
13 pub closed: bool,
14 pub size: Size,
15
16 pub enable_image: bool,
17 pub enable_next_dance: bool,
18 pub scale: f32,
19}
20
21impl Window for SongWindow {
22 fn new(id: window::Id) -> Self {
23 Self {
24 id,
25 closed: false,
26 size: Size::default(),
27
28 enable_image: true,
29 enable_next_dance: true,
30 scale: 1.0,
31 }
32 }
33
34 fn on_resize(&mut self, size: Size) {
35 self.size = size;
36 }
37
38 fn on_close(&mut self) {
39 self.closed = true;
40 }
41
42 fn is_closed(&self) -> bool {
43 self.closed
44 }
45}
46
47impl SongWindow {
48 pub fn view<'a>(&self, state: &'a DanceInterpreter) -> Element<'a, Message> {
49 let Some(song_info) = state.data_provider.get_current_song_info() else {
50 return horizontal().into();
51 };
52
53 let dance_size = self.size.height / 8.0 * self.scale;
54 let title_size = self.size.height / 20.0 * self.scale;
55 let artist_size = self.size.height / 25.0 * self.scale;
56 let next_dance_size = self.size.height / 25.0 * self.scale;
57 let next_dance_label_size = self.size.height / 30.0 * self.scale;
58
59 let dance_spacing = self.size.height / 35.0 * self.scale;
60 let song_spacing = self.size.height / 150.0 * self.scale;
61 let cover_spacing = self.size.height / 30.0 * self.scale;
62
63 let cover_height = LineHeight::default().to_absolute(title_size.into())
64 + song_spacing
65 + LineHeight::default().to_absolute(artist_size.into());
66
67 let text_dance = Text::new(&song_info.dance)
68 .size(dance_size)
69 .height(Length::Fill)
70 .align_y(Vertical::Bottom)
71 .shaping(Shaping::Advanced);
72
73 let column_title_artist = column![
74 Text::new(&song_info.title)
75 .size(title_size)
76 .shaping(Shaping::Advanced),
77 Text::new(&song_info.artist)
78 .size(artist_size)
79 .shaping(Shaping::Advanced),
80 ]
81 .spacing(song_spacing);
82
83 let row_bottom = (if self.enable_image {
84 if let Some(image_handle) = song_info.album_art.as_ref() {
85 row![
86 image(image_handle).height(cover_height),
87 column_title_artist
88 ]
89 } else {
90 row![column_title_artist]
91 }
92 } else {
93 row![column_title_artist]
94 })
95 .height(Length::Fill)
96 .align_y(Vertical::Top)
97 .spacing(cover_spacing);
98
99 let column_center = column![text_dance, row_bottom]
100 .width(Length::Fill)
101 .height(Length::Fill)
102 .align_x(Horizontal::Center)
103 .spacing(dance_spacing);
104
105 (if self.enable_next_dance {
106 if let Some(next_song_info) = state.data_provider.get_next_song_info() {
107 stack![
108 column_center,
109 row![
110 horizontal(),
111 column![
112 Text::new("Nächster Tanz")
113 .size(next_dance_label_size)
114 .height(Length::Fill)
115 .align_x(Horizontal::Right)
116 .align_y(Vertical::Bottom)
117 .shaping(Shaping::Advanced),
118 Text::new(&next_song_info.dance)
119 .size(next_dance_size)
120 .align_x(Horizontal::Right)
121 .align_y(Vertical::Bottom)
122 .shaping(Shaping::Advanced)
123 ]
124 .width(Length::Shrink)
125 .spacing(dance_spacing / 3.0)
126 ]
127 ]
128 } else {
129 stack![column_center]
130 }
131 } else {
132 stack![column_center]
133 })
134 .width(Length::Fill)
135 .height(Length::Fill)
136 .into()
137 }
138}