From e2b72c4ef69dc9ebb09c79a23ec3924773119cc2 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Tue, 23 Sep 2025 12:57:12 -0500 Subject: [PATCH] better draggable code --- src/main.rs | 101 +++++++++++++++++++++------------------------------- todo.org | 1 + 2 files changed, 42 insertions(+), 60 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7a7a63e..f58808e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,6 +48,7 @@ use ui::EditorMode; use crate::core::kinds::ServiceItemKind; use crate::ui::text_svg::{self}; +use crate::ui::widgets::draggable; pub mod core; pub mod lisp; @@ -112,6 +113,7 @@ struct App { presenter: Presenter, windows: Vec, service: Vec, + selected_items: Vec, current_item: (usize, usize), hovered_item: Option, presentation_open: bool, @@ -146,6 +148,8 @@ enum Message { None, EditorToggle(bool), ChangeServiceItem(usize), + SelectServiceItem(usize), + AddSelectServiceItem(usize), HoveredServiceItem(Option), AddServiceItem(usize, ServiceItem), AddServiceItemDrop(usize), @@ -302,6 +306,7 @@ impl cosmic::Application for App { core, nav_model, service: items, + selected_items: vec![], file: PathBuf::default(), windows, presentation_open: false, @@ -1007,6 +1012,14 @@ impl cosmic::Application for App { self.hovered_item = index; Task::none() } + Message::SelectServiceItem(index) => { + self.selected_items = vec![index]; + Task::none() + } + Message::AddSelectServiceItem(index) => { + self.selected_items.push(index); + Task::none() + } Message::ChangeServiceItem(index) => { if let Some((index, item)) = self .service @@ -1448,7 +1461,10 @@ where |hovered_index| { index == hovered_index }, - ) { + ) || self + .selected_items + .contains(&index) + { t.cosmic().button.hover.into() } else { t.cosmic().button.base.into() @@ -1464,35 +1480,11 @@ where index, ))) .on_exit(Message::HoveredServiceItem(None)) - .on_double_press(Message::None) + .on_double_press(Message::ChangeServiceItem( + index, + )) .on_drag(Message::None) - .on_press(Message::ChangeServiceItem(index)); - // let button = button::standard(item.title.clone()) - // .leading_icon({ - // match item.kind { - // core::kinds::ServiceItemKind::Song(_) => { - // icon::from_name("folder-music-symbolic") - // }, - // core::kinds::ServiceItemKind::Video(_) => { - // icon::from_name("folder-videos-symbolic") - // }, - // core::kinds::ServiceItemKind::Image(_) => { - // icon::from_name("folder-pictures-symbolic") - // }, - // core::kinds::ServiceItemKind::Presentation(_) => { - // icon::from_name("x-office-presentation-symbolic") - // }, - // core::kinds::ServiceItemKind::Content(_) => { - // icon::from_name("x-office-presentation-symbolic") - // }, - // } - // }) - // // .icon_size(cosmic::theme::spacing().space_l) - // .class(cosmic::theme::style::Button::HeaderBar) - // // .spacing(cosmic::theme::spacing().space_l) - // .height(cosmic::theme::spacing().space_xl) - // .width(Length::Fill) - // .on_press(Message::ChangeServiceItem(index)); + .on_release(Message::SelectServiceItem(index)); let tooltip = tooltip( mouse_area, text::body(item.kind.to_string()), @@ -1501,10 +1493,7 @@ where .gap(cosmic::theme::spacing().space_xs); dnd_destination( tooltip, - vec![ - "application/service-item".into(), - "video/mp4".into(), - ], + vec!["application/service-item".into()], ) .data_received_for::(move |item| { if let Some(item) = item { @@ -1531,15 +1520,26 @@ where .center() .width(Length::Fill), iced::widget::horizontal_rule(1), - ui::widgets::draggable::column::column(list).spacing(10).on_drag(|event| { - match event { - ui::widgets::draggable::DragEvent::Picked { index } => Message::None, - ui::widgets::draggable::DragEvent::Dropped { index, target_index, drop_position } => Message::ReorderService(index, target_index), - ui::widgets::draggable::DragEvent::Canceled { index } => Message::None, + draggable::column::column(list).spacing(10).on_drag( + |event| { + match event { + draggable::DragEvent::Picked { .. } => { + Message::None + } + draggable::DragEvent::Dropped { + index, + target_index, + .. + } => Message::ReorderService( + index, + target_index, + ), + draggable::DragEvent::Canceled { .. } => { + Message::None + } + } } - }), - // column(list).spacing(10), - // service::service(&self.service), + ), dnd_destination( vertical_space().width(Length::Fill), vec!["application/service-item".into()] @@ -1570,22 +1570,3 @@ where container.center(Length::FillPortion(2)).into() } } - -#[cfg(test)] -mod test { - - fn test_slide() -> String { - let slide = r#"(slide (image :source "./somehting.jpg" :fill cover - (text "Something cooler" :font-size 50)))"#; - String::from(slide) - } - // #[test] - // fn test_lisp() { - // let slide = test_slide(); - // if let Ok(data) = lexpr::parse::from_str_elisp(slide.as_str()) { - // assert_eq!(slide, data) - // } else { - // assert!(false) - // } - // } -} diff --git a/todo.org b/todo.org index cf2f7bb..29b539e 100644 --- a/todo.org +++ b/todo.org @@ -2,6 +2,7 @@ * TODO [#A] Add removal and reordering of service_items +Reordering is finished * TODO Add OBS integration This will be based on each slide having the ability to activate an OBS scene when it is active. * TODO Move text_generation function to be asynchronous so that UI doesn't lock up during song editing.