adding base for drag n drop

This commit is contained in:
Chris Cochrun 2025-02-18 16:43:39 -06:00
parent f79e61f2ed
commit 1ce365fc04
8 changed files with 139 additions and 49 deletions

View file

@ -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;
}

View file

@ -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<Value> for Image {

View file

@ -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<Value> for Presentation {

View file

@ -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<dyn ServiceTrait>,
}
impl TryFrom<(Vec<u8>, String)> for ServiceItem {
type Error = miette::Error;
fn try_from(
value: (Vec<u8>, String),
) -> std::result::Result<Self, Self::Error> {
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<std::borrow::Cow<'static, [u8]>> {
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()

View file

@ -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 {

View file

@ -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<Value> for Video {

View file

@ -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<String>),
DndDrop(Entity, Option<ServiceItem>, DndAction),
OpenWindow,
CloseWindow(Option<window::Id>),
WindowOpened(window::Id, Option<Point>),
@ -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::Message> {
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()
}
}
}

View file

@ -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::<Message, ServiceItem>::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)
}