diff --git a/src/core/content.rs b/src/core/content.rs index ed617de..45c6e21 100644 --- a/src/core/content.rs +++ b/src/core/content.rs @@ -1,6 +1,7 @@ -use super::kinds::ServiceItemKind; +use super::{kinds::ServiceItemKind, service_items::ServiceItem}; pub trait Content { fn title(&self) -> String; fn kind(&self) -> ServiceItemKind; + fn to_service_item(&self) -> ServiceItem; } diff --git a/src/core/images.rs b/src/core/images.rs index 1379650..7608a13 100644 --- a/src/core/images.rs +++ b/src/core/images.rs @@ -30,6 +30,10 @@ impl Content for Image { fn kind(&self) -> ServiceItemKind { ServiceItemKind::Image(self.clone()) } + + fn to_service_item(&self) -> super::service_items::ServiceItem { + self.into() + } } impl From for Image { diff --git a/src/core/presentations.rs b/src/core/presentations.rs index 21c5df8..089f54f 100644 --- a/src/core/presentations.rs +++ b/src/core/presentations.rs @@ -44,6 +44,10 @@ impl Content for Presentation { fn kind(&self) -> ServiceItemKind { ServiceItemKind::Presentation(self.clone()) } + + fn to_service_item(&self) -> super::service_items::ServiceItem { + self.into() + } } impl From for Presentation { diff --git a/src/core/service_items.rs b/src/core/service_items.rs index 7e8d9dc..70c1e6b 100644 --- a/src/core/service_items.rs +++ b/src/core/service_items.rs @@ -1,7 +1,9 @@ +use std::borrow::Cow; use std::ops::Deref; +use cosmic::iced::clipboard::mime::{AllowedMimeTypes, AsMimeTypes}; use crisp::types::{Keyword, Symbol, Value}; -use miette::Result; +use miette::{miette, Result}; use tracing::{debug, error}; use crate::Slide; @@ -22,6 +24,48 @@ pub struct ServiceItem { // pub item: Box, } +impl TryFrom<(Vec, String)> for ServiceItem { + type Error = miette::Error; + + fn try_from( + value: (Vec, String), + ) -> std::result::Result { + let sto = value.0.to_owned(); + let song = Song { + title: "Death Was Arrested".to_string(), + ..Default::default() + }; + debug!(?value); + Ok(Self::from(&song)) + } +} + +impl AllowedMimeTypes for ServiceItem { + fn allowed() -> Cow<'static, [String]> { + Cow::from(vec!["application/service-item".to_string()]) + } +} + +impl AsMimeTypes for ServiceItem { + fn available(&self) -> std::borrow::Cow<'static, [String]> { + debug!(?self); + Cow::from(vec!["application/service-item".to_string()]) + } + + fn as_bytes( + &self, + mime_type: &str, + ) -> Option> { + todo!(); + debug!(?self); + debug!(mime_type); + Some(Cow::from( + r#"(slide :background (image :source "~/pics/frodo.jpg" :fit fill) + (text "This is frodo" :font-size 70))"#.to_string().into_bytes() + )) + } +} + impl ServiceItem { pub fn title(&self) -> String { self.title.clone() diff --git a/src/core/songs.rs b/src/core/songs.rs index 6ee5a89..efe0deb 100644 --- a/src/core/songs.rs +++ b/src/core/songs.rs @@ -44,6 +44,10 @@ impl Content for Song { fn kind(&self) -> ServiceItemKind { ServiceItemKind::Song(self.clone()) } + + fn to_service_item(&self) -> super::service_items::ServiceItem { + self.into() + } } impl ServiceTrait for Song { diff --git a/src/core/videos.rs b/src/core/videos.rs index 0bbaa57..42cc616 100644 --- a/src/core/videos.rs +++ b/src/core/videos.rs @@ -35,6 +35,10 @@ impl Content for Video { fn kind(&self) -> ServiceItemKind { ServiceItemKind::Video(self.clone()) } + + fn to_service_item(&self) -> super::service_items::ServiceItem { + self.into() + } } impl From for Video { diff --git a/src/main.rs b/src/main.rs index 22f3618..f30f6ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use clap::{command, Parser}; use core::service_items::{ServiceItem, ServiceItemModel}; use cosmic::app::context_drawer::ContextDrawer; use cosmic::app::{Core, Settings, Task}; +use cosmic::iced::clipboard::dnd::DndAction; use cosmic::iced::keyboard::{Key, Modifiers}; use cosmic::iced::window::{Mode, Position}; use cosmic::iced::{self, event, window, Length, Padding, Point}; @@ -9,7 +10,9 @@ use cosmic::iced_futures::Subscription; use cosmic::iced_widget::{column, row}; use cosmic::prelude::ElementExt; use cosmic::prelude::*; +use cosmic::widget::dnd_destination::DragId; use cosmic::widget::nav_bar::nav_bar_style; +use cosmic::widget::segmented_button::Entity; use cosmic::widget::tooltip::Position as TPosition; use cosmic::widget::{ button, nav_bar, text, tooltip, DndSource, Id, Space, @@ -100,8 +103,8 @@ enum Message { Present(presenter::Message), Library(library::Message), File(PathBuf), - DndEnter(ServiceItem), - DndDrop(ServiceItem), + DndEnter(Entity, Vec), + DndDrop(Entity, Option, DndAction), OpenWindow, CloseWindow(Option), WindowOpened(window::Id, Option), @@ -110,6 +113,7 @@ enum Message { Quit, Key(Key, Modifiers), None, + DndLeave(Entity), } impl cosmic::Application for App { @@ -217,9 +221,21 @@ impl cosmic::Application for App { cosmic::app::cosmic::Message::NavBar(id), ) }) - // .on_dnd_drop(|entity, data, idk| { - // cosmic::app::Message::Cosmic(Message::DndDrop(entity)) - // }) + .on_dnd_drop(|entity, data, action| { + debug!(?entity); + debug!(?data); + debug!(?action); + cosmic::app::Message::App(Message::DndDrop( + entity, data, action, + )) + }) + .on_dnd_enter(|entity, data| { + cosmic::app::Message::App(Message::DndEnter(entity, data)) + }) + .on_dnd_leave(|entity| { + cosmic::app::Message::App(Message::DndLeave(entity)) + }) + .drag_id(DragId::new()) .on_context(|id| { cosmic::app::Message::Cosmic( cosmic::app::cosmic::Message::NavBarContext(id), @@ -253,7 +269,7 @@ impl cosmic::Application for App { id: nav_bar::Id, ) -> Task { self.nav_model.activate(id); - debug!(?id); + // debug!(?id); self.update_title() } @@ -503,13 +519,26 @@ impl cosmic::Application for App { } } Message::Quit => cosmic::iced::exit(), - Message::DndEnter(service_item) => todo!(), - Message::DndDrop(service_item) => todo!(), + Message::DndEnter(entity, data) => { + debug!(?entity); + debug!(?data); + Task::none() + } + Message::DndDrop(entity, service_item, action) => { + debug!(?entity); + debug!(?service_item); + debug!(?action); + Task::none() + } Message::AddLibrary(library) => { self.library = Some(library); Task::none() } Message::None => Task::none(), + Message::DndLeave(entity) => { + // debug!(?entity); + Task::none() + } } } diff --git a/src/ui/library.rs b/src/ui/library.rs index 6d00b71..e52c489 100644 --- a/src/ui/library.rs +++ b/src/ui/library.rs @@ -3,7 +3,7 @@ use cosmic::{ iced_widget::{column, row as rowm, text as textm}, widget::{ container, horizontal_space, icon, mouse_area, responsive, - row, scrollable, text, Container, Space, + row, scrollable, text, Container, DndSource, Space, }, Element, Task, }; @@ -14,6 +14,7 @@ use crate::core::{ images::Image, model::{get_db, LibraryKind, Model}, presentations::Presentation, + service_items::ServiceItem, songs::Song, videos::Video, }; @@ -204,54 +205,53 @@ impl Library { .on_enter(Message::HoverLibrary(Some(model.kind))) .on_exit(Message::HoverLibrary(None)); let mut dragged_item = None; - let lib_container = if self.library_open == Some(model.kind) { - let items = scrollable( - column({ - model.items.iter().enumerate().map( + let lib_container = + if self.library_open == Some(model.kind) { + let items = scrollable( + column({ + model.items.iter().enumerate().map( |(index, item)| { - mouse_area( - self.single_item(index, item, model), - ) - .on_drag({ - dragged_item = - Some(self.single_item( + let service_item = item.to_service_item(); + DndSource::::new( + mouse_area( + self.single_item( index, item, model, - )); - Message::DragItem(Some(( + ), + ) + .on_enter(Message::HoverItem(Some(( model.kind, index as i32, - ))) + )))) + .on_exit(Message::HoverItem(None)) + .on_press(Message::SelectItem(Some( + (model.kind, index as i32), + ))), + ) + .drag_content(move || { + service_item.to_owned() }) - .on_enter(Message::HoverItem(Some(( - model.kind, - index as i32, - )))) - .on_exit(Message::HoverItem(None)) - .on_press(Message::SelectItem(Some(( - model.kind, - index as i32, + .on_start(Some(Message::DragItem(Some( + (model.kind, index as i32), )))) .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( + }) + .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)) - }; + )) + }) + } else { + Container::new(Space::new(0, 0)) + }; (column![button, lib_container].into(), dragged_item) }