Compare commits
5 Commits
feat-inlin
...
540/patch-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a4897d2b3 | ||
|
|
0dc25e7c2a | ||
|
|
57389c5b55 | ||
|
|
a7202307ae | ||
|
|
0c0c396c61 |
@@ -1,3 +1,5 @@
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use crate::{
|
||||
buffer::Buffer,
|
||||
layout::{Corner, Rect},
|
||||
@@ -10,28 +12,38 @@ use unicode_width::UnicodeWidthStr;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ListState {
|
||||
offset: usize,
|
||||
selected: Option<usize>,
|
||||
selected: BTreeSet<usize>,
|
||||
}
|
||||
|
||||
impl Default for ListState {
|
||||
fn default() -> ListState {
|
||||
ListState {
|
||||
offset: 0,
|
||||
selected: None,
|
||||
selected: BTreeSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ListState {
|
||||
pub fn selected(&self) -> Option<usize> {
|
||||
self.selected
|
||||
pub fn offset(mut self, offset: usize) -> Self {
|
||||
self.offset = offset;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn selected(&self) -> &BTreeSet<usize> {
|
||||
&self.selected
|
||||
}
|
||||
|
||||
pub fn select(&mut self, index: Option<usize>) {
|
||||
self.selected = index;
|
||||
if index.is_none() {
|
||||
self.offset = 0;
|
||||
}
|
||||
pub fn select(&mut self, index: usize) {
|
||||
self.selected.insert(index);
|
||||
}
|
||||
|
||||
pub fn deselect(&mut self, index: usize) {
|
||||
self.selected.remove(&index);
|
||||
}
|
||||
|
||||
pub fn deselect_all(&mut self) {
|
||||
self.selected.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +143,6 @@ impl<'a> List<'a> {
|
||||
|
||||
fn get_items_bounds(
|
||||
&self,
|
||||
selected: Option<usize>,
|
||||
offset: usize,
|
||||
max_height: usize,
|
||||
) -> (usize, usize) {
|
||||
@@ -139,6 +150,9 @@ impl<'a> List<'a> {
|
||||
let mut start = offset;
|
||||
let mut end = offset;
|
||||
let mut height = 0;
|
||||
|
||||
// Fills forwards until max_height is reached
|
||||
// or no more items are left.
|
||||
for item in self.items.iter().skip(offset) {
|
||||
if height + item.height() > max_height {
|
||||
break;
|
||||
@@ -146,24 +160,17 @@ impl<'a> List<'a> {
|
||||
height += item.height();
|
||||
end += 1;
|
||||
}
|
||||
|
||||
let selected = selected.unwrap_or(0).min(self.items.len() - 1);
|
||||
while selected >= end {
|
||||
height = height.saturating_add(self.items[end].height());
|
||||
end += 1;
|
||||
while height > max_height {
|
||||
height = height.saturating_sub(self.items[start].height());
|
||||
start += 1;
|
||||
|
||||
// Fills backwards, if offset is too large
|
||||
// and we have insufficient items.
|
||||
for item in self.items[..start].iter().rev() {
|
||||
if height + item.height() > max_height {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while selected < start {
|
||||
height += item.height();
|
||||
start -= 1;
|
||||
height = height.saturating_add(self.items[start].height());
|
||||
while height > max_height {
|
||||
end -= 1;
|
||||
height = height.saturating_sub(self.items[end].height());
|
||||
}
|
||||
}
|
||||
|
||||
(start, end)
|
||||
}
|
||||
}
|
||||
@@ -191,19 +198,18 @@ impl<'a> StatefulWidget for List<'a> {
|
||||
}
|
||||
let list_height = list_area.height as usize;
|
||||
|
||||
let (start, end) = self.get_items_bounds(state.selected, state.offset, list_height);
|
||||
state.offset = start;
|
||||
let (start, end) = self.get_items_bounds(state.offset, list_height);
|
||||
|
||||
let highlight_symbol = self.highlight_symbol.unwrap_or("");
|
||||
let blank_symbol = " ".repeat(highlight_symbol.width());
|
||||
|
||||
let mut current_height = 0;
|
||||
let has_selection = state.selected.is_some();
|
||||
let has_selection = !state.selected.is_empty();
|
||||
for (i, item) in self
|
||||
.items
|
||||
.iter_mut()
|
||||
.enumerate()
|
||||
.skip(state.offset)
|
||||
.skip(start)
|
||||
.take(end - start)
|
||||
{
|
||||
let (x, y) = match self.start_corner {
|
||||
@@ -226,7 +232,7 @@ impl<'a> StatefulWidget for List<'a> {
|
||||
let item_style = self.style.patch(item.style);
|
||||
buf.set_style(area, item_style);
|
||||
|
||||
let is_selected = state.selected.map(|s| s == i).unwrap_or(false);
|
||||
let is_selected = state.selected.contains(&i);
|
||||
let elem_x = if has_selection {
|
||||
let symbol = if is_selected {
|
||||
highlight_symbol
|
||||
|
||||
Reference in New Issue
Block a user