getting closer

This commit is contained in:
Chris Cochrun 2026-04-03 11:23:13 -05:00
parent 679a2cafa5
commit ff2bfc4f86
13 changed files with 182 additions and 135 deletions

View file

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

View file

@ -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()

View file

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

View file

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

View file

@ -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");

View file

@ -121,10 +121,10 @@ impl<'a> Program<SlideWidget, cosmic::Theme, cosmic::Renderer>
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<SlideWidget>) {
) -> (&cosmic::event::Status, Option<SlideWidget>) {
match event {
canvas::Event::Mouse(event) => match event {
cosmic::iced::mouse::Event::CursorEntered => {
@ -157,8 +157,15 @@ impl<'a> Program<SlideWidget, cosmic::Theme, cosmic::Renderer>
},
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(

View file

@ -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<Message> {
self.song_slides.as_ref().map_or_else(
|| horizontal_space().into(),
|| space::horizontal().into(),
|slides| {
let slides: Vec<Element<Message>> = 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()

View file

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

View file

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

View file

@ -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::Element<'b, Message, Theme, Renderer>> {
overlay::from_children(
@ -816,6 +823,7 @@ where
tree,
layout,
renderer,
viewport,
translation,
)
}

View file

@ -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::Element<'b, Message, Theme, Renderer>> {
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<overlay::Element<'b, Message, Theme, Renderer>> {
self.row.overlay(tree, layout, renderer, translation)
self.row.overlay(
tree,
layout,
renderer,
viewport,
translation,
)
}
}

View file

@ -40,7 +40,7 @@ where
}
fn layout(
&self,
&mut self,
_tree: &mut widget::Tree,
_renderer: &Renderer,
_limits: &layout::Limits,

View file

@ -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<Message> = 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
}