diff --git a/src/core/content.rs b/src/core/content.rs new file mode 100644 index 0000000..ed617de --- /dev/null +++ b/src/core/content.rs @@ -0,0 +1,6 @@ +use super::kinds::ServiceItemKind; + +pub trait Content { + fn title(&self) -> String; + fn kind(&self) -> ServiceItemKind; +} diff --git a/src/core/images.rs b/src/core/images.rs index 0fa339c..1379650 100644 --- a/src/core/images.rs +++ b/src/core/images.rs @@ -1,6 +1,8 @@ use crate::{Background, Slide, SlideBuilder, TextAlignment}; use super::{ + content::Content, + kinds::ServiceItemKind, model::{get_db, LibraryKind, Model}, service_items::ServiceTrait, }; @@ -20,6 +22,16 @@ pub struct Image { pub path: PathBuf, } +impl Content for Image { + fn title(&self) -> String { + self.title.clone() + } + + fn kind(&self) -> ServiceItemKind { + ServiceItemKind::Image(self.clone()) + } +} + impl From for Image { fn from(value: Value) -> Self { Self::from(&value) diff --git a/src/core/mod.rs b/src/core/mod.rs index 0d33cc5..e23192e 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,3 +1,4 @@ +pub mod content; pub mod images; pub mod kinds; pub mod lisp; diff --git a/src/core/presentations.rs b/src/core/presentations.rs index a9ce0bc..21c5df8 100644 --- a/src/core/presentations.rs +++ b/src/core/presentations.rs @@ -10,6 +10,8 @@ use tracing::error; use crate::{Background, Slide, SlideBuilder, TextAlignment}; use super::{ + content::Content, + kinds::ServiceItemKind, model::{get_db, LibraryKind, Model}, service_items::ServiceTrait, }; @@ -34,6 +36,16 @@ pub struct Presentation { pub kind: PresKind, } +impl Content for Presentation { + fn title(&self) -> String { + self.title.clone() + } + + fn kind(&self) -> ServiceItemKind { + ServiceItemKind::Presentation(self.clone()) + } +} + impl From for Presentation { fn from(value: Value) -> Self { Self::from(&value) diff --git a/src/core/songs.rs b/src/core/songs.rs index 98c7ce2..6ee5a89 100644 --- a/src/core/songs.rs +++ b/src/core/songs.rs @@ -12,6 +12,8 @@ use tracing::{debug, error}; use crate::{core::slide, Slide, SlideBuilder}; use super::{ + content::Content, + kinds::ServiceItemKind, model::{get_db, LibraryKind, Model}, service_items::ServiceTrait, slide::{Background, TextAlignment}, @@ -34,6 +36,16 @@ pub struct Song { pub font_size: Option, } +impl Content for Song { + fn title(&self) -> String { + self.title.clone() + } + + fn kind(&self) -> ServiceItemKind { + ServiceItemKind::Song(self.clone()) + } +} + impl ServiceTrait for Song { fn title(&self) -> String { self.title.clone() diff --git a/src/core/videos.rs b/src/core/videos.rs index c75b99d..0bbaa57 100644 --- a/src/core/videos.rs +++ b/src/core/videos.rs @@ -1,6 +1,8 @@ use crate::{Background, SlideBuilder, TextAlignment}; use super::{ + content::Content, + kinds::ServiceItemKind, model::{get_db, LibraryKind, Model}, service_items::ServiceTrait, slide::Slide, @@ -25,6 +27,16 @@ pub struct Video { pub looping: bool, } +impl Content for Video { + fn title(&self) -> String { + self.title.clone() + } + + fn kind(&self) -> ServiceItemKind { + ServiceItemKind::Video(self.clone()) + } +} + impl From for Video { fn from(value: Value) -> Self { Self::from(&value) diff --git a/src/ui/library.rs b/src/ui/library.rs index 4ca70ff..738caa9 100644 --- a/src/ui/library.rs +++ b/src/ui/library.rs @@ -1,18 +1,20 @@ use cosmic::{ + font::default, iced::{ alignment::{Horizontal, Vertical}, Background, Border, Color, Length, }, - iced_widget::{column, text}, + iced_widget::{column, row as rowm, text as textm}, theme, widget::{ button, container, horizontal_space, icon, mouse_area, row, - Container, Space, + text, Column, Container, Space, }, Element, Task, }; use crate::core::{ + content::Content, images::Image, model::{get_db, LibraryKind, Model}, presentations::Presentation, @@ -86,31 +88,34 @@ impl Library { pub fn library_item<'a, T>( &'a self, model: &'a Model, - ) -> Element<'a, Message> { + ) -> Element<'a, Message> + where + T: Content, + { let mut row = row::().spacing(5); match &model.kind { LibraryKind::Song => { row = row - .push(text!("Songs").align_y(Vertical::Center)); + .push(textm!("Songs").align_y(Vertical::Center)); } LibraryKind::Video => { row = row - .push(text!("Videos").align_y(Vertical::Center)); + .push(textm!("Videos").align_y(Vertical::Center)); } LibraryKind::Image => { row = row - .push(text!("Images").align_y(Vertical::Center)); + .push(textm!("Images").align_y(Vertical::Center)); } LibraryKind::Presentation => { row = row.push( - text!("Presentations").align_y(Vertical::Center), + textm!("Presentations").align_y(Vertical::Center), ); } }; let item_count = model.items.len(); row = row.push(horizontal_space()); row = row - .push(text!("{}", item_count).align_y(Vertical::Center)); + .push(textm!("{}", item_count).align_y(Vertical::Center)); row = row.push( icon::from_name({ if self.library_open == Some(model.kind) { @@ -156,6 +161,68 @@ impl Library { }) .on_enter(Message::HoverLibrary(Some(model.kind))) .on_exit(Message::HoverLibrary(None)); - button.into() + let lib_container = if self.library_open == Some(model.kind) { + let items: Column = column({ + model.items.iter().map(|item| { + let text = + text::heading(elide_text(item.title(), 18)) + .center() + .wrapping(textm::Wrapping::None); + let icon = icon::from_name({ + match model.kind { + LibraryKind::Song => { + "folder-music-symbolic" + } + LibraryKind::Video => { + "folder-videos-symbolic" + } + LibraryKind::Image => { + "folder-pictures-symbolic" + } + LibraryKind::Presentation => { + "x-office-presentation-symbolic" + } + } + }); + Container::new(rowm![icon, text].spacing(10)) + .padding(5) + .width(Length::Fill) + .style(|t| { + container::Style::default() + .background(Background::Color( + t.cosmic().button.base.into(), + )) + .border(Border::default().rounded( + t.cosmic().corner_radii.radius_l, + )) + }) + .into() + }) + }) + .spacing(2) + .width(Length::Fill); + Container::new(items).padding(5).style(|t| { + container::Style::default() + .background(Background::Color( + t.cosmic().primary.base.into(), + )) + .border( + Border::default().rounded( + t.cosmic().corner_radii.radius_m, + ), + ) + }) + } else { + Container::new(Space::new(0, 0)) + }; + column![button, lib_container].into() + } +} + +fn elide_text(text: String, amount: usize) -> String { + if text.len() > amount { + format!("{}...", text.split_at(amount).0) + } else { + text } }