Proper handling of select by shift

This commit is contained in:
Jeremy Soller 2024-02-29 15:21:59 -07:00
parent a1558b20c6
commit f0956f494a
No known key found for this signature in database
GPG key ID: D02FD439211AF56F
2 changed files with 93 additions and 94 deletions

View file

@ -447,7 +447,7 @@ impl Application for App {
} }
Message::Filename(new_filename) => { Message::Filename(new_filename) => {
// Select based on filename // Select based on filename
self.tab.select_by_name(&new_filename); self.tab.select_name(&new_filename);
if let DialogKind::SaveFile { filename } = &mut self.flags.kind { if let DialogKind::SaveFile { filename } = &mut self.flags.kind {
*filename = new_filename; *filename = new_filename;

View file

@ -562,6 +562,8 @@ pub struct Tab {
pub history: Vec<Location>, pub history: Vec<Location>,
pub config: TabConfig, pub config: TabConfig,
items_opt: Option<Vec<Item>>, items_opt: Option<Vec<Item>>,
select_focus: Option<usize>,
select_shift: Option<usize>,
sort_name: HeadingOptions, sort_name: HeadingOptions,
sort_direction: bool, sort_direction: bool,
} }
@ -584,6 +586,8 @@ impl Tab {
history, history,
config, config,
items_opt: None, items_opt: None,
select_focus: None,
select_shift: None,
sort_name, sort_name,
sort_direction, sort_direction,
} }
@ -607,9 +611,11 @@ impl Tab {
pub fn set_items(&mut self, items: Vec<Item>) { pub fn set_items(&mut self, items: Vec<Item>) {
self.items_opt = Some(items); self.items_opt = Some(items);
self.select_focus = None;
} }
pub fn select_all(&mut self) { pub fn select_all(&mut self) {
self.select_focus = None;
if let Some(ref mut items) = self.items_opt { if let Some(ref mut items) = self.items_opt {
for item in items.iter_mut() { for item in items.iter_mut() {
if !self.config.show_hidden && item.hidden { if !self.config.show_hidden && item.hidden {
@ -623,6 +629,7 @@ impl Tab {
} }
pub fn select_none(&mut self) -> bool { pub fn select_none(&mut self) -> bool {
self.select_focus = None;
let mut had_selection = false; let mut had_selection = false;
if let Some(ref mut items) = self.items_opt { if let Some(ref mut items) = self.items_opt {
for item in items.iter_mut() { for item in items.iter_mut() {
@ -635,102 +642,92 @@ impl Tab {
had_selection had_selection
} }
pub fn select_by_drag(&mut self, rect: Rectangle) { pub fn select_name(&mut self, name: &str) {
let items = match &mut self.items_opt { self.select_focus = None;
Some(some) => some,
None => return,
};
for (_i, item) in items.iter_mut().enumerate() {
//TODO: modifiers
item.selected = match item.rect_opt.get() {
Some(item_rect) => item_rect.intersects(&rect),
None => false,
};
}
}
pub fn select_by_name(&mut self, name: &str) {
if let Some(ref mut items) = self.items_opt { if let Some(ref mut items) = self.items_opt {
for item in items.iter_mut() { for (i, item) in items.iter_mut().enumerate() {
item.selected = item.name == name; if item.name == name {
} self.select_focus = Some(i);
}
}
fn selection_first(&self) -> Option<(usize, usize)> {
let items = self.items_opt.as_ref()?;
let mut first = None;
for item in items.iter() {
if !item.selected {
continue;
}
let (row, col) = match item.pos_opt.get() {
Some(some) => some,
None => continue,
};
first = Some(match first {
Some((first_row, first_col)) => {
if row < first_row {
(row, col)
} else if row == first_row {
(row, col.min(first_row))
} else {
(first_row, first_col)
}
}
None => (row, col),
});
}
first
}
fn selection_last(&self) -> Option<(usize, usize)> {
let items = self.items_opt.as_ref()?;
let mut last = None;
for item in items.iter() {
if !item.selected {
continue;
}
let (row, col) = match item.pos_opt.get() {
Some(some) => some,
None => continue,
};
last = Some(match last {
Some((last_row, last_col)) => {
if row > last_row {
(row, col)
} else if row == last_row {
(row, col.max(last_row))
} else {
(last_row, last_col)
}
}
None => (row, col),
});
}
last
}
fn select_position(&mut self, row: usize, col: usize, mod_shift: bool) -> bool {
let mut found = false;
if let Some(ref mut items) = self.items_opt {
for item in items.iter_mut() {
if item.pos_opt.get() == Some((row, col)) {
item.selected = true; item.selected = true;
found = true; } else {
} else if !mod_shift {
item.selected = false; item.selected = false;
} }
} }
} }
}
fn select_position(&mut self, row: usize, col: usize, mod_shift: bool) -> bool {
let mut start = (row, col);
let mut end = (row, col);
if mod_shift {
if self.select_focus.is_none() || self.select_shift.is_none() {
// Set select shift to initial state if necessary
self.select_shift = self.select_focus;
}
if let Some(pos) = self.select_shift_pos_opt() {
if pos.0 < row || (pos.0 == row && pos.1 < col) {
start = pos;
} else {
end = pos;
}
}
} else {
// Clear select shift if the modifier is not set
self.select_shift = None;
};
let mut found = false;
if let Some(ref mut items) = self.items_opt {
for (i, item) in items.iter_mut().enumerate() {
item.selected = false;
let pos = match item.pos_opt.get() {
Some(some) => some,
None => continue,
};
if pos.0 < start.0 || (pos.0 == start.0 && pos.1 < start.1) {
// Before start
continue;
}
if pos.0 > end.0 || (pos.0 == end.0 && pos.1 > end.1) {
// After end
continue;
}
if pos == (row, col) {
// Update focus if this is what we wanted to select
self.select_focus = Some(i);
}
item.selected = true;
found = true;
}
}
found found
} }
pub fn select_rect(&mut self, rect: Rectangle) {
self.select_focus = None;
if let Some(ref mut items) = self.items_opt {
for (_i, item) in items.iter_mut().enumerate() {
//TODO: modifiers
item.selected = match item.rect_opt.get() {
Some(item_rect) => item_rect.intersects(&rect),
None => false,
};
}
}
}
fn select_focus_pos_opt(&self) -> Option<(usize, usize)> {
let items = self.items_opt.as_ref()?;
let item = items.get(self.select_focus?)?;
item.pos_opt.get()
}
fn select_shift_pos_opt(&self) -> Option<(usize, usize)> {
let items = self.items_opt.as_ref()?;
let item = items.get(self.select_shift?)?;
item.pos_opt.get()
}
pub fn update(&mut self, message: Message, modifiers: Modifiers) -> Vec<Command> { pub fn update(&mut self, message: Message, modifiers: Modifiers) -> Vec<Command> {
let mut commands = Vec::new(); let mut commands = Vec::new();
let mut cd = None; let mut cd = None;
@ -741,6 +738,7 @@ impl Tab {
&& self.dialog.as_ref().map_or(true, |x| x.multiple()); && self.dialog.as_ref().map_or(true, |x| x.multiple());
match message { match message {
Message::Click(click_i_opt) => { Message::Click(click_i_opt) => {
self.select_focus = 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 (i, item) in items.iter_mut().enumerate() {
if Some(i) == click_i_opt { if Some(i) == click_i_opt {
@ -756,7 +754,7 @@ impl Tab {
} }
} }
} }
self.select_focus = Some(i);
item.selected = true; item.selected = true;
if let Some(click_time) = item.click_time { if let Some(click_time) = item.click_time {
if click_time.elapsed() < DOUBLE_CLICK_DURATION { if click_time.elapsed() < DOUBLE_CLICK_DURATION {
@ -802,7 +800,7 @@ impl Tab {
} }
Message::Drag(rect_opt) => match rect_opt { Message::Drag(rect_opt) => match rect_opt {
Some(rect) => { Some(rect) => {
self.select_by_drag(rect); self.select_rect(rect);
} }
None => {} None => {}
}, },
@ -829,7 +827,7 @@ impl Tab {
} }
} }
Message::ItemDown => { Message::ItemDown => {
if let Some((row, col)) = self.selection_last() { if let Some((row, col)) = self.select_focus_pos_opt() {
//TODO: Shift modifier should select items in between //TODO: Shift modifier should select items in between
// Try to select item in next row // Try to select item in next row
if !self.select_position(row + 1, col, mod_shift) { if !self.select_position(row + 1, col, mod_shift) {
@ -842,7 +840,7 @@ impl Tab {
} }
} }
Message::ItemLeft => { Message::ItemLeft => {
if let Some((row, col)) = self.selection_first() { if let Some((row, col)) = self.select_focus_pos_opt() {
// Try to select previous item in current row // Try to select previous item in current row
if !col if !col
.checked_sub(1) .checked_sub(1)
@ -873,7 +871,7 @@ impl Tab {
} }
} }
Message::ItemRight => { Message::ItemRight => {
if let Some((row, col)) = self.selection_last() { if let Some((row, col)) = self.select_focus_pos_opt() {
// Try to select next item in current row // Try to select next item in current row
if !self.select_position(row, col + 1, mod_shift) { if !self.select_position(row, col + 1, mod_shift) {
// Try to select first item in next row // Try to select first item in next row
@ -888,7 +886,7 @@ impl Tab {
} }
} }
Message::ItemUp => { Message::ItemUp => {
if let Some((row, col)) = self.selection_first() { if let Some((row, col)) = self.select_focus_pos_opt() {
//TODO: Shift modifier should select items in between //TODO: Shift modifier should select items in between
// Try to select item in last row // Try to select item in last row
if !row if !row
@ -998,6 +996,7 @@ impl Tab {
if location != self.location { if location != self.location {
self.location = location.clone(); self.location = location.clone();
self.items_opt = None; self.items_opt = None;
self.select_focus = None;
self.edit_location = None; self.edit_location = None;
if let Some(history_i) = history_i_opt { if let Some(history_i) = history_i_opt {
// Navigating in history // Navigating in history