Proper handling of select by shift
This commit is contained in:
parent
a1558b20c6
commit
f0956f494a
2 changed files with 93 additions and 94 deletions
|
|
@ -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;
|
||||||
|
|
|
||||||
185
src/tab.rs
185
src/tab.rs
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue