Handle drag-select with shift or ctrl pressed

This commit is contained in:
Jason Rodney Hansen 2024-05-26 22:03:43 -06:00 committed by Jeremy Soller
parent d756bdf2e9
commit 80aa2c31e9

View file

@ -292,6 +292,7 @@ pub fn scan_path(tab_path: &PathBuf, sizes: IconSizes) -> Vec<Item> {
pos_opt: Cell::new(None), pos_opt: Cell::new(None),
rect_opt: Cell::new(None), rect_opt: Cell::new(None),
selected: false, selected: false,
overlaps_drag_rect: false,
}); });
} }
} }
@ -384,6 +385,7 @@ pub fn scan_trash(sizes: IconSizes) -> Vec<Item> {
pos_opt: Cell::new(None), pos_opt: Cell::new(None),
rect_opt: Cell::new(None), rect_opt: Cell::new(None),
selected: false, selected: false,
overlaps_drag_rect: false,
}); });
} }
} }
@ -519,6 +521,7 @@ pub struct Item {
pub pos_opt: Cell<Option<(usize, usize)>>, pub pos_opt: Cell<Option<(usize, usize)>>,
pub rect_opt: Cell<Option<Rectangle>>, pub rect_opt: Cell<Option<Rectangle>>,
pub selected: bool, pub selected: bool,
pub overlaps_drag_rect: bool,
} }
impl Item { impl Item {
@ -710,6 +713,7 @@ pub struct Tab {
select_shift: Option<usize>, select_shift: Option<usize>,
cached_selected: RefCell<Option<bool>>, cached_selected: RefCell<Option<bool>>,
clicked: Option<usize>, clicked: Option<usize>,
selected_clicked: bool,
} }
impl Tab { impl Tab {
@ -734,6 +738,7 @@ impl Tab {
cached_selected: RefCell::new(None), cached_selected: RefCell::new(None),
clicked: None, clicked: None,
dnd_hovered: None, dnd_hovered: None,
selected_clicked: false,
} }
} }
@ -838,22 +843,33 @@ impl Tab {
if pos == (row, col) { if pos == (row, col) {
// Update focus if this is what we wanted to select // Update focus if this is what we wanted to select
self.select_focus = Some(i); self.select_focus = Some(i);
found = true;
} }
item.selected = true; item.selected = true;
found = true;
} }
} }
found found
} }
pub fn select_rect(&mut self, rect: Rectangle) { pub fn select_rect(&mut self, rect: Rectangle, mod_ctrl: bool, mod_shift: bool) {
*self.cached_selected.borrow_mut() = None; *self.cached_selected.borrow_mut() = None;
if let Some(ref mut items) = self.items_opt { if let Some(ref mut items) = self.items_opt {
for (_i, item) in items.iter_mut().enumerate() { for item in items.iter_mut() {
//TODO: modifiers let was_overlapped = item.overlaps_drag_rect;
item.selected = match item.rect_opt.get() { item.overlaps_drag_rect = item
Some(item_rect) => item_rect.intersects(&rect), .rect_opt
None => false, .get()
.map(|r| r.intersects(&rect))
.unwrap_or(false);
item.selected = if mod_ctrl || mod_shift {
if was_overlapped == item.overlaps_drag_rect {
item.selected
} else {
!item.selected
}
} else {
item.overlaps_drag_rect
}; };
} }
} }
@ -997,6 +1013,11 @@ impl Tab {
} }
Message::DragEnd(_) => { Message::DragEnd(_) => {
self.clicked = None; self.clicked = None;
if let Some(ref mut items) = self.items_opt {
for item in items.iter_mut() {
item.overlaps_drag_rect = false;
}
}
} }
Message::DoubleClick(click_i_opt) => { Message::DoubleClick(click_i_opt) => {
if let Some(clicked_item) = self if let Some(clicked_item) = self
@ -1018,11 +1039,13 @@ impl Tab {
} }
} }
Message::Click(click_i_opt) => { Message::Click(click_i_opt) => {
self.selected_clicked = false;
self.context_menu = None; self.context_menu = None;
if click_i_opt.is_none() { if click_i_opt.is_none() {
self.clicked = click_i_opt; self.clicked = click_i_opt;
} }
let dont_unset = mod_ctrl let dont_unset = mod_ctrl
|| mod_shift
|| self.column_sort().is_some_and(|l| { || self.column_sort().is_some_and(|l| {
l.iter() l.iter()
.any(|(e_i, e)| Some(e_i) == click_i_opt.as_ref() && e.selected) .any(|(e_i, e)| Some(e_i) == click_i_opt.as_ref() && e.selected)
@ -1075,7 +1098,7 @@ impl Tab {
Message::Drag(rect_opt) => match rect_opt { Message::Drag(rect_opt) => match rect_opt {
Some(rect) => { Some(rect) => {
self.context_menu = None; self.context_menu = None;
self.select_rect(rect); self.select_rect(rect, mod_ctrl, mod_shift);
if self.select_focus.take().is_some() { if self.select_focus.take().is_some() {
// Unfocus currently focused button // Unfocus currently focused button
commands.push(Command::FocusButton(widget::Id::unique())); commands.push(Command::FocusButton(widget::Id::unique()));
@ -1902,6 +1925,7 @@ impl Tab {
.map(|m| cosmic::app::Message::App(crate::app::Message::TabMessage(None, m))) .map(|m| cosmic::app::Message::App(crate::app::Message::TabMessage(None, m)))
}), }),
mouse_area::MouseArea::new(grid) mouse_area::MouseArea::new(grid)
.on_press(|_| Message::Click(None))
.on_drag(Message::Drag) .on_drag(Message::Drag)
.on_drag_end(|_| Message::DragEnd(None)) .on_drag_end(|_| Message::DragEnd(None))
.show_drag_rect(true) .show_drag_rect(true)
@ -2255,20 +2279,23 @@ impl Tab {
item_view, item_view,
Id::new("tab-view"), Id::new("tab-view"),
); );
let item_view = if let Some(drag_list) = drag_list {
let drag_list = ArcElementWrapper(Arc::new(Mutex::new(drag_list))); let item_view = match drag_list {
item_view Some(drag_list) if self.selected_clicked => {
.drag_content(move || { let drag_list = ArcElementWrapper(Arc::new(Mutex::new(drag_list)));
ClipboardCopy::new(crate::clipboard::ClipboardKind::Copy, &files) item_view
}) .drag_content(move || {
.drag_icon(move || { ClipboardCopy::new(crate::clipboard::ClipboardKind::Copy, &files)
let state: tree::State = })
Widget::<cosmic::app::Message<app::Message>, _, _>::state(&drag_list); .drag_icon(move || {
(drag_list.clone().into(), state) let state: tree::State =
}) Widget::<cosmic::app::Message<app::Message>, _, _>::state(&drag_list);
} else { (drag_list.clone().into(), state)
item_view })
}
_ => item_view,
}; };
let tab_location = self.location.clone(); let tab_location = self.location.clone();
let mut mouse_area = mouse_area::MouseArea::new(item_view) let mut mouse_area = mouse_area::MouseArea::new(item_view)
.on_press(move |_point_opt| Message::Click(None)) .on_press(move |_point_opt| Message::Click(None))