ui and context menu for splitting presentations at an index

This commit is contained in:
Chris Cochrun 2025-10-17 16:13:13 -05:00
parent 6c92856c46
commit 2d5362a015

View file

@ -1,4 +1,8 @@
use std::{io, path::Path, path::PathBuf}; use std::{
collections::HashMap,
io,
path::{Path, PathBuf},
};
use crate::core::presentations::Presentation; use crate::core::presentations::Presentation;
use cosmic::{ use cosmic::{
@ -8,8 +12,9 @@ use cosmic::{
iced_widget::{column, row}, iced_widget::{column, row},
theme, theme,
widget::{ widget::{
self, Space, button, container, horizontal_space, icon, self, Space, button, container, context_menu,
image::Handle, mouse_area, scrollable, text, text_input, horizontal_space, icon, image::Handle, menu, mouse_area,
scrollable, text, text_input,
}, },
}; };
use miette::IntoDiagnostic; use miette::IntoDiagnostic;
@ -27,6 +32,7 @@ pub struct PresentationEditor {
title: String, title: String,
editing: bool, editing: bool,
hovered_slide: Option<i32>, hovered_slide: Option<i32>,
context_menu_id: Option<i32>,
} }
pub enum Action { pub enum Action {
@ -49,8 +55,27 @@ pub enum Message {
AddSlides(Option<Vec<Handle>>), AddSlides(Option<Vec<Handle>>),
ChangeSlide(usize), ChangeSlide(usize),
HoverSlide(Option<i32>), HoverSlide(Option<i32>),
ContextMenu(usize),
SplitBefore,
SplitAfter,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum MenuAction {
SplitBefore,
SplitAfter,
}
impl menu::Action for MenuAction {
type Message = Message;
fn message(&self) -> Self::Message {
match self {
MenuAction::SplitBefore => Message::SplitBefore,
MenuAction::SplitAfter => Message::SplitAfter,
}
}
}
impl PresentationEditor { impl PresentationEditor {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@ -63,6 +88,7 @@ impl PresentationEditor {
page_count: None, page_count: None,
slides: None, slides: None,
hovered_slide: None, hovered_slide: None,
context_menu_id: None,
} }
} }
pub fn update(&mut self, message: Message) -> Action { pub fn update(&mut self, message: Message) -> Action {
@ -227,6 +253,23 @@ impl PresentationEditor {
Message::HoverSlide(slide) => { Message::HoverSlide(slide) => {
self.hovered_slide = slide; self.hovered_slide = slide;
} }
Message::ContextMenu(index) => {
self.context_menu_id = Some(index as i32);
}
Message::SplitBefore => {
if let Some(index) = self.context_menu_id {
debug!("split before {index}");
} else {
error!("split before no index");
}
}
Message::SplitAfter => {
if let Some(index) = self.context_menu_id {
debug!("split after {index}");
} else {
error!("split after no index");
}
}
} }
Action::None Action::None
} }
@ -260,12 +303,15 @@ impl PresentationEditor {
cosmic::iced::Color::WHITE, cosmic::iced::Color::WHITE,
)) ))
}); });
container( let clickable_slide = container(
mouse_area(slide) mouse_area(slide)
.on_enter(Message::HoverSlide(Some( .on_enter(Message::HoverSlide(Some(
index as i32, index as i32,
))) )))
.on_exit(Message::HoverSlide(None)) .on_exit(Message::HoverSlide(None))
.on_right_press(Message::ContextMenu(
index,
))
.on_press(Message::ChangeSlide(index)), .on_press(Message::ChangeSlide(index)),
) )
.padding(theme::spacing().space_m) .padding(theme::spacing().space_m)
@ -282,18 +328,23 @@ impl PresentationEditor {
} else { } else {
theme::Container::Card theme::Container::Card
}, },
) );
.into() clickable_slide.into()
}) })
.collect() .collect()
} else { } else {
vec![horizontal_space().into()] vec![horizontal_space().into()]
}; };
let pages_column = container(scrollable( let pages_column = container(
self.context_menu(
scrollable(
column(pdf_pages) column(pdf_pages)
.spacing(theme::active().cosmic().space_xs()) .spacing(theme::active().cosmic().space_xs())
.padding(theme::spacing().space_xs), .padding(theme::spacing().space_xs),
)) )
.into(),
),
)
.class(theme::Container::Card); .class(theme::Container::Card);
let main_row = row![ let main_row = row![
pages_column, pages_column,
@ -339,6 +390,38 @@ impl PresentationEditor {
self.editing self.editing
} }
fn context_menu<'b>(
&self,
items: Element<'b, Message>,
) -> Element<'b, Message> {
if self.context_menu_id.is_some() {
let menu_items = vec![
menu::Item::Button(
"Spit Before",
None,
MenuAction::SplitBefore,
),
menu::Item::Button(
"Split After",
None,
MenuAction::SplitAfter,
),
];
let context_menu = context_menu(
items,
self.context_menu_id.map_or_else(
|| None,
|_| {
Some(menu::items(&HashMap::new(), menu_items))
},
),
);
Element::from(context_menu)
} else {
items
}
}
fn update_entire_presentation( fn update_entire_presentation(
&mut self, &mut self,
presentation: &Presentation, presentation: &Presentation,