Fix shift click sorting when items sorted by name, fixes #1135
This commit is contained in:
parent
0c081b79fd
commit
e2c446b73a
1 changed files with 51 additions and 64 deletions
115
src/tab.rs
115
src/tab.rs
|
|
@ -3007,73 +3007,60 @@ impl Tab {
|
||||||
.select_range
|
.select_range
|
||||||
.map_or(Some((click_i, click_i)), |r| Some((r.0, click_i)));
|
.map_or(Some((click_i, click_i)), |r| Some((r.0, click_i)));
|
||||||
if let Some(range) = self.select_range {
|
if let Some(range) = self.select_range {
|
||||||
let min = range.0.min(range.1);
|
let range_min = range.0.min(range.1);
|
||||||
let max = range.0.max(range.1);
|
let range_max = range.0.max(range.1);
|
||||||
let (sort_name, sort_direction, _) = self.sort_options();
|
// A sorted tab's items can't be linearly selected
|
||||||
//TODO: this assumes the default sort order!
|
// Let's say we have:
|
||||||
if sort_name == HeadingOptions::Name && sort_direction {
|
// index | file
|
||||||
// A default/unsorted tab's view is consistent with how the
|
// 0 | file0
|
||||||
// Items are laid out internally (items_opt), so Items can be
|
// 1 | file1
|
||||||
// linearly selected
|
// 2 | file2
|
||||||
if let Some(ref mut items) = self.items_opt {
|
// This is both the default sort and internal ordering
|
||||||
for item in items.iter_mut().skip(min).take(max - min + 1) {
|
// When sorted it may be displayed as:
|
||||||
|
// 1 | file1
|
||||||
|
// 0 | file0
|
||||||
|
// 2 | file2
|
||||||
|
// However, the internal ordering is still the same thus
|
||||||
|
// linearly selecting items doesn't work. Shift selecting
|
||||||
|
// file0 and file2 would select indices 0 to 2 when it should
|
||||||
|
// select indices 0 AND 2 from items_opt
|
||||||
|
let indices: Vec<_> = self
|
||||||
|
.column_sort()
|
||||||
|
.map(|sorted| sorted.into_iter().map(|(i, _)| i).collect())
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
let len = self
|
||||||
|
.items_opt
|
||||||
|
.as_deref()
|
||||||
|
.map(|items| items.len())
|
||||||
|
.unwrap_or_default();
|
||||||
|
(0..len).collect()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Find the true indices for the min and max element w.r.t.
|
||||||
|
// a sorted tab.
|
||||||
|
let min = indices
|
||||||
|
.iter()
|
||||||
|
.position(|&offset| offset == range_min)
|
||||||
|
.unwrap_or_default();
|
||||||
|
// We can't skip `min_real` elements here because the index of
|
||||||
|
// `max` may actually be before `min` in a sorted tab
|
||||||
|
let max = indices
|
||||||
|
.iter()
|
||||||
|
.position(|&offset| offset == range_max)
|
||||||
|
.unwrap_or(indices.len());
|
||||||
|
let min_real = min.min(max);
|
||||||
|
let max_real = max.max(min);
|
||||||
|
|
||||||
|
if let Some(ref mut items) = self.items_opt {
|
||||||
|
for index in indices
|
||||||
|
.into_iter()
|
||||||
|
.skip(min_real)
|
||||||
|
.take(max_real - min_real + 1)
|
||||||
|
{
|
||||||
|
if let Some(item) = items.get_mut(index) {
|
||||||
item.selected = true;
|
item.selected = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// A sorted tab's items can't be linearly selected
|
|
||||||
// Let's say we have:
|
|
||||||
// index | file
|
|
||||||
// 0 | file0
|
|
||||||
// 1 | file1
|
|
||||||
// 2 | file2
|
|
||||||
// This is both the default sort and internal ordering
|
|
||||||
// When sorted it may be displayed as:
|
|
||||||
// 1 | file1
|
|
||||||
// 0 | file0
|
|
||||||
// 2 | file2
|
|
||||||
// However, the internal ordering is still the same thus
|
|
||||||
// linearly selecting items doesn't work. Shift selecting
|
|
||||||
// file0 and file2 would select indices 0 to 2 when it should
|
|
||||||
// select indices 0 AND 2 from items_opt
|
|
||||||
let indices: Vec<_> = self
|
|
||||||
.column_sort()
|
|
||||||
.map(|sorted| sorted.into_iter().map(|(i, _)| i).collect())
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
let len = self
|
|
||||||
.items_opt
|
|
||||||
.as_deref()
|
|
||||||
.map(|items| items.len())
|
|
||||||
.unwrap_or_default();
|
|
||||||
(0..len).collect()
|
|
||||||
});
|
|
||||||
|
|
||||||
// Find the true indices for the min and max element w.r.t.
|
|
||||||
// a sorted tab.
|
|
||||||
let min = indices
|
|
||||||
.iter()
|
|
||||||
.position(|&offset| offset == min)
|
|
||||||
.unwrap_or_default();
|
|
||||||
// We can't skip `min_real` elements here because the index of
|
|
||||||
// `max` may actually be before `min` in a sorted tab
|
|
||||||
let max = indices
|
|
||||||
.iter()
|
|
||||||
.position(|&offset| offset == max)
|
|
||||||
.unwrap_or(indices.len());
|
|
||||||
let min_real = min.min(max);
|
|
||||||
let max_real = max.max(min);
|
|
||||||
|
|
||||||
if let Some(ref mut items) = self.items_opt {
|
|
||||||
for index in indices
|
|
||||||
.into_iter()
|
|
||||||
.skip(min_real)
|
|
||||||
.take(max_real - min_real + 1)
|
|
||||||
{
|
|
||||||
if let Some(item) = items.get_mut(index) {
|
|
||||||
item.selected = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.clicked = click_i_opt;
|
self.clicked = click_i_opt;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue