adding a way for items to propagate to main app layer

If I am not mistaken, I may not need to do this.
There might be a way to make items appear by using the DndSource and
DndDrop modules. I hope that these essentially move the item to a
global level and then drop the data in some way to the nav_bar.
This commit is contained in:
Chris Cochrun 2025-02-13 22:39:26 -06:00
parent 2854aa536d
commit f79e61f2ed
2 changed files with 128 additions and 120 deletions

View file

@ -11,7 +11,9 @@ use cosmic::prelude::ElementExt;
use cosmic::prelude::*; use cosmic::prelude::*;
use cosmic::widget::nav_bar::nav_bar_style; use cosmic::widget::nav_bar::nav_bar_style;
use cosmic::widget::tooltip::Position as TPosition; use cosmic::widget::tooltip::Position as TPosition;
use cosmic::widget::{button, nav_bar, text, tooltip, Space}; use cosmic::widget::{
button, nav_bar, text, tooltip, DndSource, Id, Space,
};
use cosmic::widget::{icon, slider}; use cosmic::widget::{icon, slider};
use cosmic::{executor, Application, ApplicationExt, Element}; use cosmic::{executor, Application, ApplicationExt, Element};
use cosmic::{widget::Container, Theme}; use cosmic::{widget::Container, Theme};
@ -215,6 +217,9 @@ impl cosmic::Application for App {
cosmic::app::cosmic::Message::NavBar(id), cosmic::app::cosmic::Message::NavBar(id),
) )
}) })
// .on_dnd_drop(|entity, data, idk| {
// cosmic::app::Message::Cosmic(Message::DndDrop(entity))
// })
.on_context(|id| { .on_context(|id| {
cosmic::app::Message::Cosmic( cosmic::app::Message::Cosmic(
cosmic::app::cosmic::Message::NavBarContext(id), cosmic::app::cosmic::Message::NavBarContext(id),
@ -571,14 +576,22 @@ impl cosmic::Application for App {
] ]
.spacing(3); .spacing(3);
let mut drag_item = None;
let library = let library =
Container::new(if let Some(library) = &self.library { Container::new(if let Some(library) = &self.library {
library.view().map(|m| Message::Library(m)) let (view, item) = library.view();
drag_item = item;
view.map(|m| Message::Library(m))
} else { } else {
Space::new(0, 0).into() Space::new(0, 0).into()
}) })
.style(nav_bar_style) .style(nav_bar_style)
.center(Length::Fill); .center(Length::Fill);
// let dnd_source: DndSource<Message, _> = DndSource::with_id(
// drag_item.expect("errors").map(|m| Message::Library(m)),
// Id::new("item"),
// );
// let drag_handle = Container::new(Space::new(1, Length::Fill)) // let drag_handle = Container::new(Space::new(1, Length::Fill))
// .style(|t| nav_bar_style(t)); // .style(|t| nav_bar_style(t));
// let dragger = MouseArea::new(drag_handle) // let dragger = MouseArea::new(drag_handle)

View file

@ -29,6 +29,7 @@ pub(crate) struct Library {
selected_item: Option<(LibraryKind, i32)>, selected_item: Option<(LibraryKind, i32)>,
hovered_item: Option<(LibraryKind, i32)>, hovered_item: Option<(LibraryKind, i32)>,
dragged_item: Option<(LibraryKind, i32)>, dragged_item: Option<(LibraryKind, i32)>,
dragged_item_pos: Option<(usize, usize)>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -60,6 +61,7 @@ impl Library {
selected_item: None, selected_item: None,
hovered_item: None, hovered_item: None,
dragged_item: None, dragged_item: None,
dragged_item_pos: None,
} }
} }
@ -93,20 +95,42 @@ impl Library {
} }
} }
pub fn view(&self) -> Element<Message> { pub fn view(
&self,
) -> (Element<Message>, Option<Element<Message>>) {
let (song_library, song_dragged) =
self.library_item(&self.song_library);
let (image_library, image_dragged) =
self.library_item(&self.image_library);
let (video_library, video_dragged) =
self.library_item(&self.video_library);
let (presentation_library, presentation_dragged) =
self.library_item(&self.presentation_library);
let column = column![ let column = column![
self.library_item(&self.song_library), song_library,
self.library_item(&self.image_library), image_library,
self.library_item(&self.video_library), video_library,
self.library_item(&self.presentation_library), presentation_library,
]; ];
column.height(Length::Fill).spacing(5).into() let dragged_vector = vec![
song_dragged,
image_dragged,
video_dragged,
presentation_dragged,
];
let dragged = dragged_vector
.into_iter()
.filter(|x| x.is_some())
.next()
.unwrap_or(None);
(column.height(Length::Fill).spacing(5).into(), dragged)
} }
pub fn library_item<'a, T>( pub fn library_item<'a, T>(
&'a self, &'a self,
model: &'a Model<T>, model: &'a Model<T>,
) -> Element<'a, Message> ) -> (Element<'a, Message>, Option<Element<'a, Message>>)
where where
T: Content, T: Content,
{ {
@ -179,123 +203,25 @@ impl Library {
}) })
.on_enter(Message::HoverLibrary(Some(model.kind))) .on_enter(Message::HoverLibrary(Some(model.kind)))
.on_exit(Message::HoverLibrary(None)); .on_exit(Message::HoverLibrary(None));
let mut dragged_item = None;
let lib_container = if self.library_open == Some(model.kind) { let lib_container = if self.library_open == Some(model.kind) {
let items = scrollable( let items = scrollable(
column({ column({
model.items.iter().enumerate().map( model.items.iter().enumerate().map(
|(index, item)| { |(index, item)| {
let text =
Container::new(responsive(|size| {
text::heading(elide_text(
item.title(),
size.width,
))
.center()
.wrapping(textm::Wrapping::None)
.into()
}))
.center_y(25)
.center_x(Length::Fill);
let icon = icon::from_name({
match model.kind {
LibraryKind::Song => {
"folder-music-symbolic"
}
LibraryKind::Video => {
"folder-videos-symbolic"
}
LibraryKind::Image => {
"folder-pictures-symbolic"
}
LibraryKind::Presentation => {
"x-office-presentation-symbolic"
}
}
});
mouse_area( mouse_area(
Container::new( self.single_item(index, item, model),
rowm![
horizontal_space().width(0),
icon,
text
]
.spacing(10)
.align_y(Vertical::Center),
)
.padding(5)
.width(Length::Fill)
.style(move |t| {
container::Style::default()
.background(
Background::Color(
if let Some((
library,
selected,
)) =
self.selected_item
{
if model.kind
== library
&& selected
== index
as i32
{
t.cosmic()
.accent
.selected
.into()
} else {
t.cosmic()
.button
.base
.into()
}
} else if let Some(
(
library,
hovered,
),
) =
self.hovered_item
{
if model.kind
== library
&& hovered
== index
as i32
{
t.cosmic()
.button
.hover
.into()
} else {
t.cosmic()
.button
.base
.into()
}
} else {
t.cosmic()
.button
.base
.into()
},
),
)
.border(
Border::default()
.rounded(
t.cosmic()
.corner_radii
.radius_l,
),
)
}),
) )
.on_drag(Message::DragItem(Some(( .on_drag({
model.kind, dragged_item =
index as i32, Some(self.single_item(
)))) index, item, model,
));
Message::DragItem(Some((
model.kind,
index as i32,
)))
})
.on_enter(Message::HoverItem(Some(( .on_enter(Message::HoverItem(Some((
model.kind, model.kind,
index as i32, index as i32,
@ -326,7 +252,76 @@ impl Library {
} else { } else {
Container::new(Space::new(0, 0)) Container::new(Space::new(0, 0))
}; };
column![button, lib_container].into() (column![button, lib_container].into(), dragged_item)
}
fn single_item<'a, T>(
&'a self,
index: usize,
item: &'a T,
model: &'a Model<T>,
) -> Element<'a, Message>
where
T: Content,
{
let text = Container::new(responsive(|size| {
text::heading(elide_text(item.title(), size.width))
.center()
.wrapping(textm::Wrapping::None)
.into()
}))
.center_y(25)
.center_x(Length::Fill);
let icon = icon::from_name({
match model.kind {
LibraryKind::Song => "folder-music-symbolic",
LibraryKind::Video => "folder-videos-symbolic",
LibraryKind::Image => "folder-pictures-symbolic",
LibraryKind::Presentation => {
"x-office-presentation-symbolic"
}
}
});
Container::new(
rowm![horizontal_space().width(0), icon, text]
.spacing(10)
.align_y(Vertical::Center),
)
.padding(5)
.width(Length::Fill)
.style(move |t| {
container::Style::default()
.background(Background::Color(
if let Some((library, selected)) =
self.selected_item
{
if model.kind == library
&& selected == index as i32
{
t.cosmic().accent.selected.into()
} else {
t.cosmic().button.base.into()
}
} else if let Some((library, hovered)) =
self.hovered_item
{
if model.kind == library
&& hovered == index as i32
{
t.cosmic().button.hover.into()
} else {
t.cosmic().button.base.into()
}
} else {
t.cosmic().button.base.into()
},
))
.border(
Border::default()
.rounded(t.cosmic().corner_radii.radius_l),
)
})
.into()
} }
} }