This commit is contained in:
parent
8e7e6df35c
commit
1e1912d419
2 changed files with 179 additions and 48 deletions
137
src/main.rs
137
src/main.rs
|
|
@ -10,7 +10,8 @@ use cosmic::iced::alignment::Vertical;
|
|||
use cosmic::iced::keyboard::{Key, Modifiers};
|
||||
use cosmic::iced::window::{Mode, Position};
|
||||
use cosmic::iced::{
|
||||
self, event, window, Background as IcedBackground, Border, Length,
|
||||
self, event, window, Background as IcedBackground, Border, Color,
|
||||
Length,
|
||||
};
|
||||
use cosmic::iced_core::text::Wrapping;
|
||||
use cosmic::iced_futures::Subscription;
|
||||
|
|
@ -22,8 +23,9 @@ use cosmic::widget::menu::{ItemWidth, KeyBind};
|
|||
use cosmic::widget::nav_bar::nav_bar_style;
|
||||
use cosmic::widget::tooltip::Position as TPosition;
|
||||
use cosmic::widget::{
|
||||
button, horizontal_space, mouse_area, nav_bar, nav_bar_toggle,
|
||||
responsive, search_input, tooltip, vertical_space, Space,
|
||||
button, context_menu, horizontal_space, mouse_area, nav_bar,
|
||||
nav_bar_toggle, responsive, scrollable, search_input, tooltip,
|
||||
vertical_space, Space,
|
||||
};
|
||||
use cosmic::widget::{container, text};
|
||||
use cosmic::widget::{icon, slider};
|
||||
|
|
@ -129,6 +131,7 @@ struct App {
|
|||
library_dragged_item: Option<ServiceItem>,
|
||||
fontdb: Arc<fontdb::Database>,
|
||||
menu_keys: HashMap<KeyBind, MenuAction>,
|
||||
context_menu: Option<usize>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
@ -152,9 +155,11 @@ enum Message {
|
|||
AddSelectServiceItem(usize),
|
||||
HoveredServiceItem(Option<usize>),
|
||||
AddServiceItem(usize, ServiceItem),
|
||||
RemoveServiceItem(usize),
|
||||
AddServiceItemDrop(usize),
|
||||
AppendServiceItem(ServiceItem),
|
||||
ReorderService(usize, usize),
|
||||
ContextMenuItem(usize),
|
||||
SearchFocus,
|
||||
Search(String),
|
||||
CloseSearch,
|
||||
|
|
@ -175,6 +180,7 @@ enum MenuAction {
|
|||
SaveAs,
|
||||
Open,
|
||||
OpenSettings,
|
||||
DeleteItem(usize),
|
||||
}
|
||||
|
||||
impl menu::Action for MenuAction {
|
||||
|
|
@ -187,6 +193,9 @@ impl menu::Action for MenuAction {
|
|||
MenuAction::SaveAs => Message::SaveAs,
|
||||
MenuAction::Open => Message::Open,
|
||||
MenuAction::OpenSettings => Message::OpenSettings,
|
||||
MenuAction::DeleteItem(index) => {
|
||||
Message::RemoveServiceItem(*index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -324,6 +333,7 @@ impl cosmic::Application for App {
|
|||
fontdb: Arc::clone(&fontdb),
|
||||
menu_keys,
|
||||
hovered_item: None,
|
||||
context_menu: None,
|
||||
};
|
||||
|
||||
let mut batch = vec![];
|
||||
|
|
@ -1093,6 +1103,15 @@ impl cosmic::Application for App {
|
|||
self.presenter.update_items(self.service.clone());
|
||||
Task::none()
|
||||
}
|
||||
Message::RemoveServiceItem(index) => {
|
||||
self.service.remove(index);
|
||||
self.presenter.update_items(self.service.clone());
|
||||
Task::none()
|
||||
}
|
||||
Message::ContextMenuItem(index) => {
|
||||
self.context_menu = Some(index);
|
||||
Task::none()
|
||||
}
|
||||
Message::AddServiceItemDrop(index) => {
|
||||
if let Some(item) = &self.library_dragged_item {
|
||||
self.service.insert(index, item.clone());
|
||||
|
|
@ -1484,6 +1503,7 @@ where
|
|||
&item.title,
|
||||
size.width,
|
||||
))
|
||||
.align_y(Vertical::Center)
|
||||
.wrapping(Wrapping::None)
|
||||
.into()
|
||||
});
|
||||
|
|
@ -1492,6 +1512,7 @@ where
|
|||
.align_y(Vertical::Center)
|
||||
.spacing(cosmic::theme::spacing().space_xs),
|
||||
)
|
||||
.height(cosmic::theme::spacing().space_xl)
|
||||
.padding(cosmic::theme::spacing().space_s)
|
||||
.class(cosmic::theme::style::Container::Secondary)
|
||||
.style(move |t| {
|
||||
|
|
@ -1524,9 +1545,44 @@ where
|
|||
index,
|
||||
))
|
||||
.on_drag(Message::None)
|
||||
.on_right_press(Message::ContextMenuItem(index))
|
||||
.on_release(Message::SelectServiceItem(index));
|
||||
let single_item = if let Some(context_menu_item) =
|
||||
self.context_menu
|
||||
{
|
||||
if context_menu_item == index {
|
||||
let context_menu = context_menu(
|
||||
mouse_area,
|
||||
self.context_menu.map_or_else(
|
||||
|| None,
|
||||
|i| {
|
||||
if i == index {
|
||||
let menu =
|
||||
vec![menu::Item::Button(
|
||||
"Delete",
|
||||
None,
|
||||
MenuAction::DeleteItem(index),
|
||||
)];
|
||||
Some(menu::items(
|
||||
&HashMap::new(),
|
||||
menu,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
.close_on_escape(true);
|
||||
Element::from(context_menu)
|
||||
} else {
|
||||
Element::from(mouse_area)
|
||||
}
|
||||
} else {
|
||||
Element::from(mouse_area)
|
||||
};
|
||||
let tooltip = tooltip(
|
||||
mouse_area,
|
||||
single_item,
|
||||
text::body(item.kind.to_string()),
|
||||
TPosition::Right,
|
||||
)
|
||||
|
|
@ -1555,31 +1611,55 @@ where
|
|||
.into()
|
||||
});
|
||||
|
||||
let scrollable = scrollable(
|
||||
draggable::column::column(list)
|
||||
.spacing(10)
|
||||
.on_drag(|event| match event {
|
||||
draggable::DragEvent::Picked { .. } => {
|
||||
Message::None
|
||||
}
|
||||
draggable::DragEvent::Dropped {
|
||||
index,
|
||||
target_index,
|
||||
..
|
||||
} => Message::ReorderService(index, target_index),
|
||||
draggable::DragEvent::Canceled { .. } => {
|
||||
Message::None
|
||||
}
|
||||
})
|
||||
.style(|t| draggable::column::Style {
|
||||
scale: 1.05,
|
||||
moved_item_overlay: Color::from(
|
||||
t.cosmic().primary.base,
|
||||
)
|
||||
.scale_alpha(0.2)
|
||||
.into(),
|
||||
ghost_border: Border {
|
||||
width: 1.0,
|
||||
color: t.cosmic().secondary.base.into(),
|
||||
radius: t.cosmic().radius_m().into(),
|
||||
},
|
||||
ghost_background: Color::from(
|
||||
t.cosmic().secondary.base,
|
||||
)
|
||||
.scale_alpha(0.2)
|
||||
.into(),
|
||||
})
|
||||
.height(Length::Shrink),
|
||||
)
|
||||
.anchor_top()
|
||||
.height(Length::Fill);
|
||||
|
||||
let column = column![
|
||||
text::heading("Service List")
|
||||
.center()
|
||||
.width(Length::Fill),
|
||||
iced::widget::horizontal_rule(1),
|
||||
draggable::column::column(list).spacing(10).on_drag(
|
||||
|event| {
|
||||
match event {
|
||||
draggable::DragEvent::Picked { .. } => {
|
||||
Message::None
|
||||
}
|
||||
draggable::DragEvent::Dropped {
|
||||
index,
|
||||
target_index,
|
||||
..
|
||||
} => Message::ReorderService(
|
||||
index,
|
||||
target_index,
|
||||
),
|
||||
draggable::DragEvent::Canceled { .. } => {
|
||||
Message::None
|
||||
}
|
||||
}
|
||||
}
|
||||
),
|
||||
scrollable
|
||||
]
|
||||
.padding(10)
|
||||
.spacing(10);
|
||||
let container = Container::new(stack![
|
||||
dnd_destination(
|
||||
vertical_space().width(Length::Fill),
|
||||
vec!["application/service-item".into()]
|
||||
|
|
@ -1601,11 +1681,10 @@ where
|
|||
debug!(?item);
|
||||
Message::AppendServiceItem(item)
|
||||
}
|
||||
)
|
||||
]
|
||||
.padding(10)
|
||||
.spacing(10);
|
||||
let container = Container::new(column).style(nav_bar_style);
|
||||
),
|
||||
column
|
||||
])
|
||||
.style(nav_bar_style);
|
||||
|
||||
container.center(Length::FillPortion(2)).into()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ where
|
|||
}
|
||||
|
||||
fn diff(&mut self, tree: &mut Tree) {
|
||||
tree.diff_children(&mut self.children);
|
||||
tree.diff_children(self.children.as_mut_slice());
|
||||
}
|
||||
|
||||
fn size(&self) -> Size<Length> {
|
||||
|
|
@ -410,9 +410,14 @@ where
|
|||
.iter()
|
||||
.zip(&mut tree.children)
|
||||
.zip(layout.children())
|
||||
.for_each(|((child, state), layout)| {
|
||||
.for_each(|((child, state), c_layout)| {
|
||||
child.as_widget().operate(
|
||||
state, layout, renderer, operation,
|
||||
state,
|
||||
c_layout.with_virtual_offset(
|
||||
layout.virtual_offset(),
|
||||
),
|
||||
renderer,
|
||||
operation,
|
||||
);
|
||||
});
|
||||
},
|
||||
|
|
@ -557,11 +562,12 @@ where
|
|||
.iter_mut()
|
||||
.zip(&mut tree.children)
|
||||
.zip(layout.children())
|
||||
.map(|((child, state), layout)| {
|
||||
.map(|((child, state), c_layout)| {
|
||||
child.as_widget_mut().on_event(
|
||||
state,
|
||||
event.clone(),
|
||||
layout,
|
||||
c_layout
|
||||
.with_virtual_offset(layout.virtual_offset()),
|
||||
cursor,
|
||||
renderer,
|
||||
clipboard,
|
||||
|
|
@ -592,9 +598,14 @@ where
|
|||
.iter()
|
||||
.zip(&tree.children)
|
||||
.zip(layout.children())
|
||||
.map(|((child, state), layout)| {
|
||||
.map(|((child, state), c_layout)| {
|
||||
child.as_widget().mouse_interaction(
|
||||
state, layout, cursor, viewport, renderer,
|
||||
state,
|
||||
c_layout
|
||||
.with_virtual_offset(layout.virtual_offset()),
|
||||
cursor,
|
||||
viewport,
|
||||
renderer,
|
||||
)
|
||||
})
|
||||
.max()
|
||||
|
|
@ -606,7 +617,7 @@ where
|
|||
tree: &Tree,
|
||||
renderer: &mut Renderer,
|
||||
theme: &Theme,
|
||||
defaults: &renderer::Style,
|
||||
default_style: &renderer::Style,
|
||||
layout: Layout<'_>,
|
||||
cursor: mouse::Cursor,
|
||||
viewport: &Rectangle,
|
||||
|
|
@ -672,7 +683,7 @@ where
|
|||
state,
|
||||
renderer,
|
||||
theme,
|
||||
defaults,
|
||||
default_style,
|
||||
child_layout,
|
||||
cursor,
|
||||
viewport,
|
||||
|
|
@ -712,7 +723,7 @@ where
|
|||
state,
|
||||
renderer,
|
||||
theme,
|
||||
defaults,
|
||||
default_style,
|
||||
child_layout,
|
||||
cursor,
|
||||
viewport,
|
||||
|
|
@ -762,16 +773,35 @@ where
|
|||
}
|
||||
_ => {
|
||||
// Draw all children normally when not dragging
|
||||
for ((child, state), layout) in self
|
||||
.children
|
||||
.iter()
|
||||
.zip(&tree.children)
|
||||
.zip(layout.children())
|
||||
if let Some(clipped_viewport) =
|
||||
layout.bounds().intersection(viewport)
|
||||
{
|
||||
child.as_widget().draw(
|
||||
state, renderer, theme, defaults, layout,
|
||||
cursor, viewport,
|
||||
);
|
||||
let viewport = if self.clip {
|
||||
&clipped_viewport
|
||||
} else {
|
||||
viewport
|
||||
};
|
||||
for ((child, state), c_layout) in self
|
||||
.children
|
||||
.iter()
|
||||
.zip(&tree.children)
|
||||
.zip(layout.children())
|
||||
.filter(|(_, layout)| {
|
||||
layout.bounds().intersects(viewport)
|
||||
})
|
||||
{
|
||||
child.as_widget().draw(
|
||||
state,
|
||||
renderer,
|
||||
theme,
|
||||
default_style,
|
||||
c_layout.with_virtual_offset(
|
||||
layout.virtual_offset(),
|
||||
),
|
||||
cursor,
|
||||
viewport,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -792,6 +822,28 @@ where
|
|||
translation,
|
||||
)
|
||||
}
|
||||
|
||||
fn drag_destinations(
|
||||
&self,
|
||||
state: &Tree,
|
||||
layout: Layout<'_>,
|
||||
renderer: &Renderer,
|
||||
dnd_rectangles: &mut cosmic::iced_core::clipboard::DndDestinationRectangles,
|
||||
) {
|
||||
for ((e, c_layout), state) in self
|
||||
.children
|
||||
.iter()
|
||||
.zip(layout.children())
|
||||
.zip(state.children.iter())
|
||||
{
|
||||
e.as_widget().drag_destinations(
|
||||
state,
|
||||
c_layout.with_virtual_offset(layout.virtual_offset()),
|
||||
renderer,
|
||||
dnd_rectangles,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Message, Theme, Renderer>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue