From b05f29d7b5231f52668d9846f439f779451c61ef Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Fri, 3 Apr 2026 11:23:13 -0500 Subject: [PATCH] getting closer --- src/main.rs | 31 ++++++------ src/ui/library.rs | 34 ++++++------- src/ui/mod.rs | 2 +- src/ui/presentation_editor.rs | 10 ++-- src/ui/presenter.rs | 5 +- src/ui/slide_editor.rs | 13 +++-- src/ui/song_editor.rs | 28 ++++++----- src/ui/text_svg.rs | 8 ++- src/ui/video_editor.rs | 15 +++--- src/ui/widgets/draggable/column.rs | 66 +++++++++++++----------- src/ui/widgets/draggable/row.rs | 80 ++++++++++++++++++------------ src/ui/widgets/slide_text.rs | 2 +- src/ui/widgets/verse_editor.rs | 23 ++++----- 13 files changed, 182 insertions(+), 135 deletions(-) diff --git a/src/main.rs b/src/main.rs index 1eab2eb..529a654 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ use cosmic::iced::{ use cosmic::iced_core::text::Wrapping; use cosmic::iced_futures::Subscription; use cosmic::iced_widget::{column, row, stack}; +use cosmic::prelude::*; use cosmic::widget::dnd_destination::dnd_destination; use cosmic::widget::menu::key_bind::Modifier; use cosmic::widget::menu::{ItemWidth, KeyBind}; @@ -786,7 +787,9 @@ impl cosmic::Application for App { .center_x(Length::Fill) .align_top(Length::Fill); let mouse_stack = stack!( - Space::new(Length::Fill, Length::Fill) + Space::new() + .height(Length::Fill) + .width(Length::Fill) .apply(container) .style(|_| { container::background( @@ -846,7 +849,9 @@ impl cosmic::Application for App { .apply(container) .padding([space_xxl, space_xxxl * 2]); let mouse_stack = stack!( - Space::new(Length::Fill, Length::Fill) + Space::new() + .height(Length::Fill) + .width(Length::Fill) .apply(container) .style(|_| { container::background( @@ -1657,7 +1662,7 @@ impl cosmic::Application for App { ); let slide_preview = column![ - Space::with_height(Length::Fill), + Space::new().height(Length::Fill), Container::new( self.presenter.view_preview().map(Message::Present), ) @@ -1686,7 +1691,7 @@ impl cosmic::Application for App { row![] }) .center_x(Length::Fill), - Space::with_height(Length::Fill), + Space::new().height(Length::Fill) ] .spacing(3); @@ -1697,7 +1702,7 @@ impl cosmic::Application for App { let library = if self.library_open { Container::new( Container::new(self.library.as_ref().map_or_else( - || Element::from(Space::new(0, 0)), + || Element::from(Space::new()), |library| library.view().map(Message::Library), )) .style(nav_bar_style), @@ -1709,7 +1714,7 @@ impl cosmic::Application for App { }; let editor = self.editor_mode.as_ref().map_or_else( - || Element::from(Space::new(0, 0)), + || Element::from(Space::new()), |mode| match mode { EditorMode::Song => { self.song_editor.view().map(Message::SongEditor) @@ -1789,7 +1794,7 @@ impl cosmic::Application for App { if self.library_open { library.width(Length::FillPortion(1)) } else { - container(Space::new(0, 0)) + container(Space::new()) }, main_area.width(Length::FillPortion(4)) ] @@ -1916,11 +1921,9 @@ where ) => self.update(Message::Present( presenter::Message::PrevSlide, )), - (Key::Named(iced::keyboard::key::Named::Space), _) => { - self.update(Message::Present( - presenter::Message::NextSlide, - )) - } + (Key::Character(k), _) if k == *" " => self.update( + Message::Present(presenter::Message::NextSlide), + ), (Key::Character(k), _) if k == *"j" || k == *"l" => self .update(Message::Present( presenter::Message::NextSlide, @@ -2002,11 +2005,11 @@ where let color = t.cosmic().accent_color(); cosmic::iced_widget::rule::Style { color: color.into(), - width: 2, + snap: true, radius: t.cosmic().corner_radii.radius_xs.into(), fill_mode: cosmic::iced_widget::rule::FillMode::Full, } - } )); + } )).width(2); Container::new(column![divider, container].spacing(theme::spacing().space_s)) } else { container }; let mouse_area = mouse_area(visual_item) diff --git a/src/ui/library.rs b/src/ui/library.rs index c58e86d..553b19c 100644 --- a/src/ui/library.rs +++ b/src/ui/library.rs @@ -1361,8 +1361,8 @@ impl<'a> Library { error!(?e); Task::none() } else { - Task::future(self.db.acquire()).and_then( - move |db| { + Task::future(self.db.acquire()) + .and_then(move |db| { Task::perform( songs::remove_from_db( db, song.id, @@ -1371,11 +1371,11 @@ impl<'a> Library { if let Err(e) = r { error!(?e); } - Message::None + r.map(|_| Message::None) }, ) - }, - ) + }) + .map(|r| r.unwrap_or(Task::none())) } } else { Task::none() @@ -1392,8 +1392,8 @@ impl<'a> Library { error!(?e); Task::none() } else { - Task::future(self.db.acquire()).and_then( - move |db| { + Task::future(self.db.acquire()) + .and_then(move |db| { Task::perform( videos::remove_from_db( db, video.id, @@ -1405,8 +1405,8 @@ impl<'a> Library { Message::None }, ) - }, - ) + }) + .map(|r| r.unwrap_or(Task::none())) } } else { Task::none() @@ -1425,8 +1425,8 @@ impl<'a> Library { } else { debug!("let's remove {0}", image.id); debug!("let's remove {0}", image.title); - Task::future(self.db.acquire()).and_then( - move |db| { + Task::future(self.db.acquire()) + .and_then(move |db| { Task::perform( images::remove_from_db( db, image.id, @@ -1438,8 +1438,8 @@ impl<'a> Library { Message::None }, ) - }, - ) + }) + .map(|r| r.unwrap_or(Task::none())) } } else { Task::none() @@ -1457,8 +1457,8 @@ impl<'a> Library { error!(?e); Task::none() } else { - Task::future(self.db.acquire()).and_then( - move |db| { + Task::future(self.db.acquire()) + .and_then(move |db| { Task::perform( presentations::remove_from_db( db, @@ -1471,8 +1471,8 @@ impl<'a> Library { Message::None }, ) - }, - ) + }) + .map(|r| r.unwrap_or(Task::none())) } } else { Task::none() diff --git a/src/ui/mod.rs b/src/ui/mod.rs index d564aa2..7e55afe 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -5,7 +5,7 @@ pub mod image_editor; pub mod library; pub mod presentation_editor; pub mod presenter; -pub mod service; +// pub mod service; pub mod slide_editor; pub mod song_editor; pub mod text_svg; diff --git a/src/ui/presentation_editor.rs b/src/ui/presentation_editor.rs index 5dddddf..218a133 100644 --- a/src/ui/presentation_editor.rs +++ b/src/ui/presentation_editor.rs @@ -14,8 +14,10 @@ use cosmic::{ theme, widget::{ self, Space, button, container, context_menu, icon, - image::Handle, menu, mouse_area, scrollable, - space::horizontal, text, text_input, + image::Handle, + menu, mouse_area, scrollable, + space::{self, horizontal}, + text, text_input, }, }; use miette::{IntoDiagnostic, Result, miette}; @@ -421,7 +423,7 @@ impl PresentationEditor { let control_buttons = row![ button::standard("Previous Page") .on_press(Message::PrevPage), - horizontal_space(), + space::horizontal(), button::standard("Next Page").on_press(Message::NextPage), ]; let column = @@ -450,7 +452,7 @@ impl PresentationEditor { row![ text::body("Title:"), title_box, - horizontal_space(), + space::horizontal(), presentation_selector ] .align_y(Vertical::Center) diff --git a/src/ui/presenter.rs b/src/ui/presenter.rs index d8ab9c3..e51ba4d 100644 --- a/src/ui/presenter.rs +++ b/src/ui/presenter.rs @@ -455,7 +455,10 @@ impl Presenter { }; let mut tasks = vec![]; - tasks.push(scroll_to(self.scroll_id.clone(), offset)); + tasks.push(scroll_to( + self.scroll_id.clone(), + offset.into(), + )); if self.slide_action_map.is_some() { debug!("Found slide actions, running them"); diff --git a/src/ui/slide_editor.rs b/src/ui/slide_editor.rs index 576cddb..d5127d5 100644 --- a/src/ui/slide_editor.rs +++ b/src/ui/slide_editor.rs @@ -121,10 +121,10 @@ impl<'a> Program fn update( &self, _state: &mut Self::State, - event: canvas::Event, + event: &canvas::Event, bounds: cosmic::iced::Rectangle, _cursor: cosmic::iced_core::mouse::Cursor, - ) -> (canvas::event::Status, Option) { + ) -> (&cosmic::event::Status, Option) { match event { canvas::Event::Mouse(event) => match event { cosmic::iced::mouse::Event::CursorEntered => { @@ -157,8 +157,15 @@ impl<'a> Program }, canvas::Event::Touch(_event) => debug!("test"), canvas::Event::Keyboard(_event) => debug!("test"), + canvas::Event::Window(event) => todo!(), + canvas::Event::InputMethod(event) => todo!(), + canvas::Event::A11y(id, action_request) => todo!(), + canvas::Event::Dnd(dnd_event) => todo!(), + canvas::Event::PlatformSpecific(platform_specific) => { + todo!() + } } - (canvas::event::Status::Ignored, None) + (iced_core::event::Status::Ignored, None) } fn mouse_interaction( diff --git a/src/ui/song_editor.rs b/src/ui/song_editor.rs index ce664ad..d8ca986 100644 --- a/src/ui/song_editor.rs +++ b/src/ui/song_editor.rs @@ -36,7 +36,7 @@ use cosmic::{ dropdown, grid::{self}, icon, mouse_area, popover, progress_bar, scrollable, - space::horizontal, + space::{self, horizontal}, text, text_editor, text_input, tooltip, }, }; @@ -948,7 +948,7 @@ impl SongEditor { fn slide_preview(&self) -> Element { self.song_slides.as_ref().map_or_else( - || horizontal_space().into(), + || space::horizontal().into(), |slides| { let slides: Vec> = slides .iter() @@ -1108,7 +1108,7 @@ impl SongEditor { if let Some(hovered_chip) = self.hovered_dnd_verse_chip && index == hovered_chip { - let phantom_chip = horizontal_space().width(60).height(19) + let phantom_chip = space::horizontal().width(60).height(19) .apply(container) .padding( Padding::new(space_xxs.into()) @@ -1120,7 +1120,7 @@ impl SongEditor { .background(ContainerBackground::Color( Color::from(t.cosmic().secondary.base).scale_alpha(0.5) )) - .border(Border::default().rounded(space_m).width(2)) + .border(Border::default().rounded(space_m as u8).width(2)) }))); chip = row![ phantom_chip, @@ -1167,7 +1167,7 @@ impl SongEditor { let mut verse_order_row = if self.dragging_verse_chip { let ending_dnd_dest = dnd_destination( - horizontal_space().height(19), + space::horizontal().height(19), vec!["application/verse".into()], ) .on_enter(|_, _, _| { @@ -1214,7 +1214,7 @@ impl SongEditor { if self.editing_verse_order { Element::from(verse_options) } else { - Element::from(horizontal_space()) + Element::from(space::horizontal()) } ] .spacing(space_s), @@ -1237,7 +1237,7 @@ impl SongEditor { .spacing(5); let verse_list = self.verses.as_ref().map_or_else( - || Element::from(horizontal_space()), + || Element::from(space::horizontal()), |verse_list| { Element::from( column(verse_list.iter().enumerate().map( @@ -1348,7 +1348,7 @@ impl SongEditor { .on_close(Message::FontSelectorOpen(false)) .width(300), container(if self.font_selector_open { - Element::from(horizontal_space()) + Element::from(space::horizontal()) } else { Element::from( icon::from_name("arrow-down").size(space_m), @@ -1384,7 +1384,7 @@ impl SongEditor { .on_close(Message::FontSizeOpen(false)) .width(space_xxxl), container(if self.font_size_open { - Element::from(horizontal_space()) + Element::from(space::horizontal()) } else { Element::from( icon::from_name("arrow-down").size(space_m), @@ -1798,7 +1798,7 @@ impl SongEditor { shadow_tools_button, divider::vertical::default().height(space_l), text_alignment_popup, - horizontal_space(), + space::horizontal(), background_selector ] .align_y(Vertical::Center) @@ -1975,7 +1975,9 @@ fn verse_chip( )) .color(text_color) .border( - Border::default().rounded(space_m).width(2), + Border::default() + .rounded(space_m as u8) + .width(2), ) }))); let button = button::icon(icon::from_name("view-close")) @@ -2007,7 +2009,9 @@ fn verse_chip( )) .color(text_color) .border( - Border::default().rounded(space_m).width(2), + Border::default() + .rounded(space_m as u8) + .width(2), ) }))) .into() diff --git a/src/ui/text_svg.rs b/src/ui/text_svg.rs index 5a40efc..b70d9de 100644 --- a/src/ui/text_svg.rs +++ b/src/ui/text_svg.rs @@ -518,7 +518,13 @@ impl TextSvg { pub fn view<'a>(&self) -> Element<'a, Message> { self.handle.clone().map_or_else( - || Element::from(Space::new(Length::Fill, Length::Fill)), + || { + Element::from( + Space::new() + .height(Length::Fill) + .width(Length::Fill), + ) + }, |handle| { Image::new(handle) .content_fit(ContentFit::Cover) diff --git a/src/ui/video_editor.rs b/src/ui/video_editor.rs index 6295ed6..1e47e86 100644 --- a/src/ui/video_editor.rs +++ b/src/ui/video_editor.rs @@ -7,8 +7,9 @@ use cosmic::{ iced_widget::{column, row}, theme, widget::{ - Space, button, container, horizontal_space, icon, - progress_bar, text, text_input, + Space, button, container, icon, progress_bar, + space::{self, horizontal}, + text, text_input, }, }; use iced_video_player::{Video, VideoPlayer}; @@ -110,7 +111,7 @@ impl VideoEditor { pub fn view(&self) -> Element { let video_elements = self.video.as_ref().map_or_else( - || container(horizontal_space()), + || container(horizontal()), |video| { let play_button = button::icon(if video.paused() { icon::from_name("media-playback-start") @@ -122,8 +123,8 @@ impl VideoEditor { 0.0..=video.duration().as_secs_f32(), video.position().as_secs_f32(), ) - .height(cosmic::theme::spacing().space_s) - .width(Length::Fill); + .girth(cosmic::theme::spacing().space_s) + .length(Length::Fill); container( row![play_button, video_track] .align_y(Vertical::Center) @@ -135,7 +136,7 @@ impl VideoEditor { ); let video_player = self.video.as_ref().map_or_else( - || Element::from(Space::new(0, 0)), + || Element::from(Space::new()), |video| Element::from(VideoPlayer::new(video)), ); @@ -164,7 +165,7 @@ impl VideoEditor { row![ text::body("Title:"), title_box, - horizontal_space(), + space::horizontal(), video_selector ] .align_y(Vertical::Center) diff --git a/src/ui/widgets/draggable/column.rs b/src/ui/widgets/draggable/column.rs index c7b9695..96a6188 100644 --- a/src/ui/widgets/draggable/column.rs +++ b/src/ui/widgets/draggable/column.rs @@ -376,7 +376,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -392,44 +392,42 @@ where self.padding, self.spacing, self.align, - &self.children, + self.children.as_mut(), &mut tree.children, ) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation, ) { - operation.container( - None, - layout.bounds(), - &mut |operation| { - self.children - .iter() - .zip(&mut tree.children) - .zip(layout.children()) - .for_each(|((child, state), c_layout)| { - child.as_widget().operate( - state, - c_layout.with_virtual_offset( - layout.virtual_offset(), - ), - renderer, - operation, - ); - }); - }, - ); + operation.container(None, layout.bounds()); + + operation.traverse(&mut |operation| { + self.children + .iter_mut() + .zip(&mut tree.children) + .zip(layout.children()) + .for_each(|((child, state), c_layout)| { + child.as_widget_mut().operate( + state, + c_layout.with_virtual_offset( + layout.virtual_offset(), + ), + renderer, + operation, + ); + }); + }); } - fn on_event( + fn update( &mut self, tree: &mut Tree, - event: Event, + event: &Event, layout: Layout<'_>, cursor: mouse::Cursor, renderer: &Renderer, @@ -560,9 +558,9 @@ where .zip(&mut tree.children) .zip(layout.children()) .map(|((child, state), c_layout)| { - child.as_widget_mut().on_event( + child.as_widget_mut().update( state, - event.clone(), + &event.clone(), c_layout .with_virtual_offset(layout.virtual_offset()), cursor, @@ -572,7 +570,15 @@ where viewport, ) }) - .fold(event::Status::Ignored, event::Status::merge); + .fold( + event::Status::Ignored, + |arg0: cosmic::iced::event::Status, arg1: ()| { + event::Status::merge( + event::Status::Ignored, + arg0, /* cosmic::iced::event::Status */ + ) + }, + ); event::Status::merge(event_status, child_status) } @@ -807,8 +813,9 @@ where fn overlay<'b>( &'b mut self, tree: &'b mut Tree, - layout: Layout<'_>, + layout: Layout<'b>, renderer: &Renderer, + viewport: &Rectangle, translation: Vector, ) -> Option> { overlay::from_children( @@ -816,6 +823,7 @@ where tree, layout, renderer, + viewport, translation, ) } diff --git a/src/ui/widgets/draggable/row.rs b/src/ui/widgets/draggable/row.rs index 597def2..e98689a 100644 --- a/src/ui/widgets/draggable/row.rs +++ b/src/ui/widgets/draggable/row.rs @@ -371,7 +371,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -385,39 +385,36 @@ where self.padding, self.spacing, self.align, - &self.children, + &mut self.children, &mut tree.children, ) } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, operation: &mut dyn Operation, ) { - operation.container( - None, - layout.bounds(), - &mut |operation| { - self.children - .iter() - .zip(&mut tree.children) - .zip(layout.children()) - .for_each(|((child, state), layout)| { - child.as_widget().operate( - state, layout, renderer, operation, - ); - }); - }, - ); + operation.container(None, layout.bounds()); + operation.traverse(&mut |operation| { + self.children + .iter_mut() + .zip(&mut tree.children) + .zip(layout.children()) + .for_each(|((child, state), layout)| { + child + .as_widget_mut() + .operate(state, layout, renderer, operation); + }); + }); } - fn on_event( + fn update( &mut self, tree: &mut Tree, - event: Event, + event: &Event, layout: Layout<'_>, cursor: mouse::Cursor, renderer: &Renderer, @@ -548,9 +545,9 @@ where .zip(&mut tree.children) .zip(layout.children()) .map(|((child, state), layout)| { - child.as_widget_mut().on_event( + child.as_widget_mut().update( state, - event.clone(), + &event.clone(), layout, cursor, renderer, @@ -559,7 +556,15 @@ where viewport, ) }) - .fold(event::Status::Ignored, event::Status::merge); + .fold( + event::Status::Ignored, + |arg0: cosmic::iced::event::Status, arg1: ()| { + event::Status::merge( + event::Status::Ignored, + arg0, /* cosmic::iced::event::Status */ + ) + }, + ); event::Status::merge(event_status, child_status) } @@ -769,8 +774,9 @@ where fn overlay<'b>( &'b mut self, tree: &'b mut Tree, - layout: Layout<'_>, + layout: Layout<'b>, renderer: &Renderer, + viewport: &Rectangle, translation: Vector, ) -> Option> { overlay::from_children( @@ -778,6 +784,7 @@ where tree, layout, renderer, + viewport, translation, ) } @@ -833,7 +840,7 @@ where } fn layout( - &self, + &mut self, tree: &mut Tree, renderer: &Renderer, limits: &layout::Limits, @@ -875,8 +882,8 @@ where } }; - for (i, child) in self.row.children.iter().enumerate() { - let node = child.as_widget().layout( + for (i, child) in self.row.children.iter_mut().enumerate() { + let node = child.as_widget_mut().layout( &mut tree.children[i], renderer, &limits, @@ -927,7 +934,7 @@ where } fn operate( - &self, + &mut self, tree: &mut Tree, layout: Layout<'_>, renderer: &Renderer, @@ -936,10 +943,10 @@ where self.row.operate(tree, layout, renderer, operation); } - fn on_event( + fn update( &mut self, tree: &mut Tree, - event: Event, + event: &Event, layout: Layout<'_>, cursor: mouse::Cursor, renderer: &Renderer, @@ -947,7 +954,7 @@ where shell: &mut Shell<'_, Message>, viewport: &Rectangle, ) -> event::Status { - self.row.on_event( + self.row.update( tree, event, layout, cursor, renderer, clipboard, shell, viewport, ) @@ -984,11 +991,18 @@ where fn overlay<'b>( &'b mut self, tree: &'b mut Tree, - layout: Layout<'_>, + layout: Layout<'b>, renderer: &Renderer, + viewport: &Rectangle, translation: Vector, ) -> Option> { - self.row.overlay(tree, layout, renderer, translation) + self.row.overlay( + tree, + layout, + renderer, + viewport, + translation, + ) } } diff --git a/src/ui/widgets/slide_text.rs b/src/ui/widgets/slide_text.rs index 97d8165..308b54b 100644 --- a/src/ui/widgets/slide_text.rs +++ b/src/ui/widgets/slide_text.rs @@ -40,7 +40,7 @@ where } fn layout( - &self, + &mut self, _tree: &mut widget::Tree, _renderer: &Renderer, _limits: &layout::Limits, diff --git a/src/ui/widgets/verse_editor.rs b/src/ui/widgets/verse_editor.rs index 1d644af..d2b39c7 100644 --- a/src/ui/widgets/verse_editor.rs +++ b/src/ui/widgets/verse_editor.rs @@ -5,7 +5,8 @@ use cosmic::{ iced_widget::{column, row}, theme, widget::{ - button, combo_box, container, horizontal_space, icon, + button, combo_box, container, icon, + space::{self, horizontal}, text_editor, }, }; @@ -62,12 +63,12 @@ impl VerseEditor { let verse = self.verse_name; Action::UpdateVerse((verse, lyrics)) } - text_editor::Action::Scroll { pixels } => { + text_editor::Action::Scroll { lines } => { if self.content.line_count() > 6 { self.content.perform(action); Action::None } else { - Action::ScrollVerses(pixels) + Action::ScrollVerses(lines as f32) } } _ => { @@ -109,12 +110,12 @@ impl VerseEditor { ); let verse_title = - row![combo, horizontal_space(), delete_button]; + row![combo, space::horizontal(), delete_button]; let lyric: Element = if self.verse_name == VerseName::Blank { - horizontal_space().into() + space::horizontal().into() } else { text_editor(&self.content) .on_action(Message::UpdateLyric) @@ -131,15 +132,11 @@ impl VerseEditor { .into(), ), border: Border::default() - .rounded(space_s) + .rounded(space_s as u8) .width(2) .color( t.cosmic().bg_component_divider(), ), - icon: t - .cosmic() - .primary_component_color() - .into(), placeholder: neutral .with_alpha(0.7) .into(), @@ -147,13 +144,15 @@ impl VerseEditor { selection: t.cosmic().accent.base.into(), }; let hovered_border = Border::default() - .rounded(space_s) + .rounded(space_s as u8) .width(3) .color(t.cosmic().accent.hover); match s { text_editor::Status::Active => base_style, text_editor::Status::Hovered - | text_editor::Status::Focused => { + | text_editor::Status::Focused { + .. + } => { base_style.border = hovered_border; base_style }