Significantly optimize drag select performance
This commit is contained in:
parent
b7c9ed8dff
commit
7524487ba7
3 changed files with 89 additions and 88 deletions
|
|
@ -30,7 +30,7 @@ use cosmic::{
|
||||||
Alignment, Event, Length, Point, Rectangle, Size, Subscription,
|
Alignment, Event, Length, Point, Rectangle, Size, Subscription,
|
||||||
},
|
},
|
||||||
iced_runtime::clipboard,
|
iced_runtime::clipboard,
|
||||||
style, theme,
|
style, surface, theme,
|
||||||
widget::{
|
widget::{
|
||||||
self,
|
self,
|
||||||
dnd_destination::DragId,
|
dnd_destination::DragId,
|
||||||
|
|
@ -41,7 +41,6 @@ use cosmic::{
|
||||||
},
|
},
|
||||||
Application, ApplicationExt, Element,
|
Application, ApplicationExt, Element,
|
||||||
};
|
};
|
||||||
use cosmic::{iced::mouse::Event::CursorMoved, surface};
|
|
||||||
use mime_guess::Mime;
|
use mime_guess::Mime;
|
||||||
use notify_debouncer_full::{
|
use notify_debouncer_full::{
|
||||||
new_debouncer,
|
new_debouncer,
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use cosmic::{
|
||||||
self, event,
|
self, event,
|
||||||
futures::{self, SinkExt},
|
futures::{self, SinkExt},
|
||||||
keyboard::{Event as KeyEvent, Key, Modifiers},
|
keyboard::{Event as KeyEvent, Key, Modifiers},
|
||||||
mouse, stream, window, Alignment, Event, Length, Point, Size, Subscription,
|
stream, window, Alignment, Event, Length, Size, Subscription,
|
||||||
},
|
},
|
||||||
theme,
|
theme,
|
||||||
widget::{
|
widget::{
|
||||||
|
|
|
||||||
172
src/tab.rs
172
src/tab.rs
|
|
@ -2402,6 +2402,7 @@ pub struct Tab {
|
||||||
search_context: Option<SearchContext>,
|
search_context: Option<SearchContext>,
|
||||||
date_time_formatter: DateTimeFormatter,
|
date_time_formatter: DateTimeFormatter,
|
||||||
time_formatter: DateTimeFormatter,
|
time_formatter: DateTimeFormatter,
|
||||||
|
watch_drag: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
async fn calculate_dir_size(path: &Path, controller: Controller) -> Result<u64, String> {
|
||||||
|
|
@ -2512,6 +2513,7 @@ impl Tab {
|
||||||
search_context: None,
|
search_context: None,
|
||||||
date_time_formatter: date_time_formatter(config.military_time),
|
date_time_formatter: date_time_formatter(config.military_time),
|
||||||
time_formatter: time_formatter(config.military_time),
|
time_formatter: time_formatter(config.military_time),
|
||||||
|
watch_drag: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2881,6 +2883,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
Message::DragEnd => {
|
Message::DragEnd => {
|
||||||
self.clicked = None;
|
self.clicked = None;
|
||||||
|
self.watch_drag = true;
|
||||||
}
|
}
|
||||||
Message::DoubleClick(click_i_opt) => {
|
Message::DoubleClick(click_i_opt) => {
|
||||||
if let Some(clicked_item) = self
|
if let Some(clicked_item) = self
|
||||||
|
|
@ -3141,6 +3144,7 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::Drag(rect_opt) => {
|
Message::Drag(rect_opt) => {
|
||||||
|
self.watch_drag = false;
|
||||||
if let Some(rect) = rect_opt {
|
if let Some(rect) = rect_opt {
|
||||||
self.context_menu = None;
|
self.context_menu = None;
|
||||||
self.location_context_menu_index = None;
|
self.location_context_menu_index = None;
|
||||||
|
|
@ -3557,11 +3561,13 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::HighlightDeactivate(i) => {
|
Message::HighlightDeactivate(i) => {
|
||||||
|
self.watch_drag = true;
|
||||||
if let Some(item) = self.items_opt.as_mut().and_then(|f| f.get_mut(i)) {
|
if let Some(item) = self.items_opt.as_mut().and_then(|f| f.get_mut(i)) {
|
||||||
item.highlighted = false;
|
item.highlighted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::HighlightActivate(i) => {
|
Message::HighlightActivate(i) => {
|
||||||
|
self.watch_drag = true;
|
||||||
if let Some(item) = self.items_opt.as_mut().and_then(|f| f.get_mut(i)) {
|
if let Some(item) = self.items_opt.as_mut().and_then(|f| f.get_mut(i)) {
|
||||||
item.highlighted = true;
|
item.highlighted = true;
|
||||||
}
|
}
|
||||||
|
|
@ -3571,6 +3577,7 @@ impl Tab {
|
||||||
self.scroll_opt = Some(viewport.absolute_offset());
|
self.scroll_opt = Some(viewport.absolute_offset());
|
||||||
}
|
}
|
||||||
Message::ScrollTab(scroll_speed) => {
|
Message::ScrollTab(scroll_speed) => {
|
||||||
|
self.watch_drag = true;
|
||||||
commands.push(Command::Iced(
|
commands.push(Command::Iced(
|
||||||
scrollable::scroll_by(
|
scrollable::scroll_by(
|
||||||
self.scrollable_id.clone(),
|
self.scrollable_id.clone(),
|
||||||
|
|
@ -4579,7 +4586,6 @@ impl Tab {
|
||||||
|
|
||||||
pub fn grid_view(&self) -> (Option<Element<'static, Message>>, Element<Message>, bool) {
|
pub fn grid_view(&self) -> (Option<Element<'static, Message>>, Element<Message>, bool) {
|
||||||
let cosmic_theme::Spacing {
|
let cosmic_theme::Spacing {
|
||||||
space_m,
|
|
||||||
space_xxs,
|
space_xxs,
|
||||||
space_xxxs,
|
space_xxxs,
|
||||||
..
|
..
|
||||||
|
|
@ -4605,7 +4611,7 @@ impl Tab {
|
||||||
let (width, height) = match self.size_opt.get() {
|
let (width, height) = match self.size_opt.get() {
|
||||||
Some(size) => (
|
Some(size) => (
|
||||||
(size.width.floor() as usize)
|
(size.width.floor() as usize)
|
||||||
.saturating_sub(2 * (space_m as usize))
|
.saturating_sub(2 * (space_xxs as usize))
|
||||||
.max(item_width),
|
.max(item_width),
|
||||||
(size.height.floor() as usize).max(item_height),
|
(size.height.floor() as usize).max(item_height),
|
||||||
),
|
),
|
||||||
|
|
@ -4650,7 +4656,6 @@ impl Tab {
|
||||||
let mut drag_s_i = 0;
|
let mut drag_s_i = 0;
|
||||||
|
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
|
|
||||||
if let Some(items) = self.column_sort() {
|
if let Some(items) = self.column_sort() {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut col = 0;
|
let mut col = 0;
|
||||||
|
|
@ -4668,8 +4673,8 @@ impl Tab {
|
||||||
item.pos_opt.set(Some((row, col)));
|
item.pos_opt.set(Some((row, col)));
|
||||||
let item_rect = Rectangle::new(
|
let item_rect = Rectangle::new(
|
||||||
Point::new(
|
Point::new(
|
||||||
(col * (item_width + column_spacing as usize) + space_m as usize) as f32,
|
(col * (item_width + column_spacing as usize) + space_xxs as usize) as f32,
|
||||||
(row * (item_height + grid_spacing as usize)) as f32,
|
(row * (item_height + grid_spacing as usize) + space_xxs as usize) as f32,
|
||||||
),
|
),
|
||||||
Size::new(item_width as f32, item_height as f32),
|
Size::new(item_width as f32, item_height as f32),
|
||||||
);
|
);
|
||||||
|
|
@ -4831,40 +4836,37 @@ impl Tab {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
let drag_list = (!dnd_items.is_empty()).then(|| {
|
||||||
(!dnd_items.is_empty()).then(|| {
|
let mut dnd_grid = widget::grid()
|
||||||
let mut dnd_grid = widget::grid()
|
.column_spacing(column_spacing)
|
||||||
.column_spacing(column_spacing)
|
.row_spacing(grid_spacing)
|
||||||
.row_spacing(grid_spacing)
|
.padding(space_xxs.into());
|
||||||
.padding(space_xxs.into());
|
|
||||||
|
|
||||||
let mut dnd_item_i = 0;
|
let mut dnd_item_i = 0;
|
||||||
for r in drag_n_i..=drag_s_i {
|
for r in drag_n_i..=drag_s_i {
|
||||||
dnd_grid = dnd_grid.insert_row();
|
dnd_grid = dnd_grid.insert_row();
|
||||||
for c in drag_w_i..=drag_e_i {
|
for c in drag_w_i..=drag_e_i {
|
||||||
let Some((i, (row, col), item)) = dnd_items.get(dnd_item_i) else {
|
let Some((i, (row, col), item)) = dnd_items.get(dnd_item_i) else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
if *row == r && *col == c {
|
if *row == r && *col == c {
|
||||||
let buttons = vec![
|
let buttons = vec![
|
||||||
widget::button::custom(
|
widget::button::custom(
|
||||||
widget::icon::icon(item.icon_handle_grid.clone())
|
widget::icon::icon(item.icon_handle_grid.clone())
|
||||||
.content_fit(ContentFit::Contain)
|
.content_fit(ContentFit::Contain)
|
||||||
.size(icon_sizes.grid()),
|
.size(icon_sizes.grid()),
|
||||||
)
|
)
|
||||||
.on_press(Message::Click(Some(*i)))
|
.on_press(Message::Click(Some(*i)))
|
||||||
.padding(space_xxxs)
|
.padding(space_xxxs)
|
||||||
.class(button_style(
|
.class(button_style(
|
||||||
item.selected,
|
item.selected,
|
||||||
item.highlighted,
|
item.highlighted,
|
||||||
item.cut,
|
item.cut,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
)),
|
)),
|
||||||
widget::button::custom(widget::text::body(
|
widget::button::custom(widget::text::body(item.display_name.clone()))
|
||||||
item.display_name.clone(),
|
|
||||||
))
|
|
||||||
.id(item.button_id.clone())
|
.id(item.button_id.clone())
|
||||||
.on_press(Message::Click(Some(*i)))
|
.on_press(Message::Click(Some(*i)))
|
||||||
.padding([0, space_xxxs])
|
.padding([0, space_xxxs])
|
||||||
|
|
@ -4876,46 +4878,46 @@ impl Tab {
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
)),
|
)),
|
||||||
];
|
];
|
||||||
|
|
||||||
let mut column = widget::column::with_capacity(buttons.len())
|
let mut column = widget::column::with_capacity(buttons.len())
|
||||||
.align_x(Alignment::Center)
|
.align_x(Alignment::Center)
|
||||||
.height(Length::Fixed(item_height as f32))
|
.height(Length::Fixed(item_height as f32))
|
||||||
.width(Length::Fixed(item_width as f32));
|
.width(Length::Fixed(item_width as f32));
|
||||||
for button in buttons {
|
for button in buttons {
|
||||||
column = column.push(button)
|
column = column.push(button)
|
||||||
}
|
|
||||||
|
|
||||||
dnd_grid = dnd_grid.push(column);
|
|
||||||
dnd_item_i += 1;
|
|
||||||
} else {
|
|
||||||
dnd_grid = dnd_grid.push(
|
|
||||||
widget::container(Space::with_height(item_width as f32))
|
|
||||||
.height(Length::Fixed(item_height as f32)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dnd_grid = dnd_grid.push(column);
|
||||||
|
dnd_item_i += 1;
|
||||||
|
} else {
|
||||||
|
dnd_grid = dnd_grid.push(
|
||||||
|
widget::container(Space::with_height(item_width as f32))
|
||||||
|
.height(Length::Fixed(item_height as f32)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Element::from(dnd_grid)
|
}
|
||||||
}),
|
Element::from(dnd_grid)
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut mouse_area =
|
||||||
mouse_area::MouseArea::new(widget::column::with_children(children).width(Length::Fill))
|
mouse_area::MouseArea::new(widget::column::with_children(children).width(Length::Fill))
|
||||||
.on_press(|_| Message::Click(None))
|
.on_press(|_| Message::Click(None))
|
||||||
.on_auto_scroll(Message::AutoScroll)
|
.on_auto_scroll(Message::AutoScroll)
|
||||||
.on_drag(Message::Drag)
|
|
||||||
.on_drag_end(|_| Message::DragEnd)
|
.on_drag_end(|_| Message::DragEnd)
|
||||||
.show_drag_rect(self.mode.multiple())
|
.show_drag_rect(self.mode.multiple())
|
||||||
.on_release(|_| Message::ClickRelease(None))
|
.on_release(|_| Message::ClickRelease(None));
|
||||||
.into(),
|
if self.watch_drag {
|
||||||
true,
|
mouse_area = mouse_area.on_drag(Message::Drag);
|
||||||
)
|
}
|
||||||
|
|
||||||
|
(drag_list, mouse_area.into(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_view(&self) -> (Option<Element<'static, Message>>, Element<Message>, bool) {
|
pub fn list_view(&self) -> (Option<Element<'static, Message>>, Element<Message>, bool) {
|
||||||
let cosmic_theme::Spacing {
|
let cosmic_theme::Spacing {
|
||||||
space_m,
|
space_s, space_xxs, ..
|
||||||
space_s,
|
|
||||||
space_xxs,
|
|
||||||
..
|
|
||||||
} = theme::active().cosmic().spacing;
|
} = theme::active().cosmic().spacing;
|
||||||
|
|
||||||
let TabConfig {
|
let TabConfig {
|
||||||
|
|
@ -4964,12 +4966,6 @@ impl Tab {
|
||||||
hidden += 1;
|
hidden += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
item.pos_opt.set(Some((count, 0)));
|
|
||||||
let item_rect = Rectangle::new(
|
|
||||||
Point::new(space_m as f32, y),
|
|
||||||
Size::new(size.width - (2 * space_m) as f32, row_height as f32),
|
|
||||||
);
|
|
||||||
item.rect_opt.set(Some(item_rect));
|
|
||||||
|
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
children.push(
|
children.push(
|
||||||
|
|
@ -4980,6 +4976,13 @@ impl Tab {
|
||||||
y += 1.0;
|
y += 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item.pos_opt.set(Some((count, 0)));
|
||||||
|
let item_rect = Rectangle::new(
|
||||||
|
Point::new(space_s as f32, y),
|
||||||
|
Size::new(size.width - (2 * space_s) as f32, row_height as f32),
|
||||||
|
);
|
||||||
|
item.rect_opt.set(Some(item_rect));
|
||||||
|
|
||||||
// Only build elements if visible (for performance)
|
// Only build elements if visible (for performance)
|
||||||
let button_row = if item_rect.intersects(&visible_rect) {
|
let button_row = if item_rect.intersects(&visible_rect) {
|
||||||
let modified_text = match &item.metadata {
|
let modified_text = match &item.metadata {
|
||||||
|
|
@ -5279,21 +5282,20 @@ impl Tab {
|
||||||
let drag_col = (!drag_items.is_empty())
|
let drag_col = (!drag_items.is_empty())
|
||||||
.then(|| Element::from(widget::column::with_children(drag_items)));
|
.then(|| Element::from(widget::column::with_children(drag_items)));
|
||||||
|
|
||||||
(
|
let mut mouse_area = mouse_area::MouseArea::new(
|
||||||
drag_col,
|
widget::column::with_children(children).padding([0, space_s]),
|
||||||
mouse_area::MouseArea::new(
|
|
||||||
widget::column::with_children(children).padding([0, space_s]),
|
|
||||||
)
|
|
||||||
.with_id(Id::new("list-view"))
|
|
||||||
.on_press(|_| Message::Click(None))
|
|
||||||
.on_auto_scroll(Message::AutoScroll)
|
|
||||||
.on_drag(Message::Drag)
|
|
||||||
.on_drag_end(|_| Message::DragEnd)
|
|
||||||
.show_drag_rect(self.mode.multiple())
|
|
||||||
.on_release(|_| Message::ClickRelease(None))
|
|
||||||
.into(),
|
|
||||||
true,
|
|
||||||
)
|
)
|
||||||
|
.with_id(Id::new("list-view"))
|
||||||
|
.on_press(|_| Message::Click(None))
|
||||||
|
.on_auto_scroll(Message::AutoScroll)
|
||||||
|
.on_drag_end(|_| Message::DragEnd)
|
||||||
|
.show_drag_rect(self.mode.multiple())
|
||||||
|
.on_release(|_| Message::ClickRelease(None));
|
||||||
|
if self.watch_drag {
|
||||||
|
mouse_area = mouse_area.on_drag(Message::Drag);
|
||||||
|
}
|
||||||
|
|
||||||
|
(drag_col, mouse_area.into(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view_responsive(
|
pub fn view_responsive(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue