From 74ae0e8a17c0121ea69e882c01fe542001922dbe Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Mon, 22 Sep 2025 08:28:29 -0500 Subject: [PATCH] fixing up the presenter and editor more --- src/main.rs | 146 ++++++++++++++++++++++++++++++++++++++++-- src/ui/presenter.rs | 31 ++------- src/ui/song_editor.rs | 2 +- todo.org | 4 ++ 4 files changed, 148 insertions(+), 35 deletions(-) diff --git a/src/main.rs b/src/main.rs index fe94c0f..eaf69d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,26 +9,30 @@ use cosmic::app::{Core, Settings, Task}; use cosmic::iced::alignment::Vertical; use cosmic::iced::keyboard::{Key, Modifiers}; use cosmic::iced::window::{Mode, Position}; -use cosmic::iced::{self, event, window, Length, Point}; +use cosmic::iced::{self, event, window, Color, Length, Point}; use cosmic::iced_futures::Subscription; +use cosmic::iced_runtime::dnd::DndAction; use cosmic::iced_widget::{column, row, stack}; use cosmic::theme; use cosmic::widget::dnd_destination::dnd_destination; +use cosmic::widget::menu::key_bind::Modifier; +use cosmic::widget::menu::{ItemWidth, KeyBind}; use cosmic::widget::nav_bar::nav_bar_style; use cosmic::widget::tooltip::Position as TPosition; -use cosmic::widget::Container; use cosmic::widget::{ - button, horizontal_space, mouse_area, nav_bar, search_input, - tooltip, vertical_space, Space, + button, dnd_source, horizontal_space, mouse_area, nav_bar, + search_input, tooltip, vertical_space, RcElementWrapper, Space, }; use cosmic::widget::{container, text}; use cosmic::widget::{icon, slider}; +use cosmic::widget::{menu, Container}; use cosmic::{executor, Application, ApplicationExt, Element}; use crisp::types::Value; use lisp::parse_lisp; use miette::{miette, Result}; use rayon::prelude::*; use resvg::usvg::fontdb; +use std::collections::HashMap; use std::fs::read_to_string; use std::path::PathBuf; use std::sync::Arc; @@ -119,6 +123,7 @@ struct App { search_id: cosmic::widget::Id, library_dragged_item: Option, fontdb: Arc, + menu_keys: HashMap, } #[derive(Debug, Clone)] @@ -147,6 +152,35 @@ enum Message { CloseSearch, UpdateSearchResults(Vec), OpenEditor(ServiceItem), + New, + Open, + OpenFile(PathBuf), + Save(Option), + SaveAs, + OpenSettings, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum MenuAction { + New, + Save, + SaveAs, + Open, + OpenSettings, +} + +impl menu::Action for MenuAction { + type Message = Message; + + fn message(&self) -> Self::Message { + match self { + MenuAction::New => Message::New, + MenuAction::Save => Message::Save(None), + MenuAction::SaveAs => Message::SaveAs, + MenuAction::Open => Message::Open, + MenuAction::OpenSettings => Message::OpenSettings, + } + } } const HEADER_SPACE: u16 = 6; @@ -230,6 +264,28 @@ impl cosmic::Application for App { // nav_model.insert().text(item.title()).data(item.clone()); // } + let mut menu_keys = HashMap::new(); + menu_keys.insert( + KeyBind { + modifiers: vec![Modifier::Ctrl], + key: Key::Character("s".into()), + }, + MenuAction::Save, + ); + menu_keys.insert( + KeyBind { + modifiers: vec![Modifier::Ctrl], + key: Key::Character("o".into()), + }, + MenuAction::Open, + ); + menu_keys.insert( + KeyBind { + modifiers: vec![Modifier::Ctrl], + key: Key::Character(".".into()), + }, + MenuAction::OpenSettings, + ); // nav_model.activate_position(0); let mut app = Self { presenter, @@ -251,6 +307,7 @@ impl cosmic::Application for App { current_item: (0, 0), library_dragged_item: None, fontdb: Arc::clone(&fontdb), + menu_keys, }; let mut batch = vec![]; @@ -270,7 +327,46 @@ impl cosmic::Application for App { } fn header_start(&self) -> Vec> { - vec![] + let file_menu = menu::Tree::with_children( + Into::>::into(menu::root("File")), + menu::items( + &self.menu_keys, + vec![ + menu::Item::Button("New", None, MenuAction::New), + menu::Item::Button( + "Open", + None, + MenuAction::Open, + ), + menu::Item::Button( + "Save", + None, + MenuAction::Save, + ), + menu::Item::Button( + "Save As", + None, + MenuAction::SaveAs, + ), + ], + ), + ); + let settings_menu = menu::Tree::with_children( + Into::>::into(menu::root("Settings")), + menu::items( + &self.menu_keys, + vec![menu::Item::Button( + "Open Settings", + None, + MenuAction::OpenSettings, + )], + ), + ); + let menu_bar = + menu::bar::(vec![file_menu, settings_menu]) + .item_width(ItemWidth::Static(250)) + .main_offset(10); + vec![menu_bar.into()] } fn header_center(&self) -> Vec> { @@ -978,6 +1074,34 @@ impl cosmic::Application for App { ServiceItemKind::Content(_slide) => todo!(), } } + Message::New => { + debug!("new file"); + Task::none() + } + Message::Open => { + debug!("Open file"); + Task::none() + } + Message::OpenFile(file) => { + debug!(?file, "opening file"); + Task::none() + } + Message::Save(file) => { + let Some(file) = file else { + debug!("saving current"); + return Task::none(); + }; + debug!(?file, "saving new file"); + Task::none() + } + Message::SaveAs => { + debug!("saving as a file"); + Task::none() + } + Message::OpenSettings => { + debug!("Opening settings"); + Task::none() + } } } @@ -1237,6 +1361,15 @@ where } } match (key, modifiers) { + (Key::Character(k), Modifiers::CTRL) if k == *"s" => { + self.update(Message::Save(None)) + } + (Key::Character(k), Modifiers::CTRL) if k == *"o" => { + self.update(Message::Open) + } + (Key::Character(k), Modifiers::CTRL) if k == *"." => { + self.update(Message::OpenSettings) + } (Key::Character(k), Modifiers::CTRL) if k == *"k" || k == *"f" => { @@ -1306,8 +1439,7 @@ where // .icon_size(cosmic::theme::spacing().space_l) .class(cosmic::theme::style::Button::HeaderBar) // .spacing(cosmic::theme::spacing().space_l) - // .padding(cosmic::theme::spacing().space_m) - // .height(cosmic::theme::spacing().space_xxxl) + .height(cosmic::theme::spacing().space_xl) .width(Length::Fill) .on_press(Message::ChangeServiceItem(index)); let tooltip = tooltip(button, diff --git a/src/ui/presenter.rs b/src/ui/presenter.rs index 6c6b327..136d8fe 100644 --- a/src/ui/presenter.rs +++ b/src/ui/presenter.rs @@ -399,21 +399,11 @@ impl Presenter { } pub fn view(&self) -> Element { - slide_view( - self.current_slide.clone(), - &self.video, - false, - true, - ) + slide_view(&self.current_slide, &self.video, false, true) } pub fn view_preview(&self) -> Element { - slide_view( - self.current_slide.clone(), - &self.video, - false, - false, - ) + slide_view(&self.current_slide, &self.video, false, false) } pub fn preview_bar(&self) -> Element { @@ -423,19 +413,6 @@ impl Presenter { let mut slides = vec![]; item.slides.iter().enumerate().for_each( |(slide_index, slide)| { - let font_name = slide.font().into_boxed_str(); - let family = - Family::Name(Box::leak(font_name)); - let weight = Weight::Normal; - let stretch = Stretch::Normal; - let style = Style::Normal; - let font = Font { - family, - weight, - stretch, - style, - }; - let is_current_slide = (item_index, slide_index) == ( @@ -444,7 +421,7 @@ impl Presenter { ); let container = slide_view( - slide.clone(), + &slide, &self.video, true, false, @@ -705,7 +682,7 @@ fn scale_font(font_size: f32, width: f32) -> f32 { } pub(crate) fn slide_view<'a>( - slide: Slide, + slide: &'a Slide, video: &'a Option