-
Notifications
You must be signed in to change notification settings - Fork 10k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
135 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
pub struct ScrollState { | ||
n_rows: usize, | ||
max_n_rows_to_display: usize, | ||
selected: Option<usize>, | ||
offset: usize, | ||
scroll_padding: usize, | ||
max_scroll_padding: usize, | ||
} | ||
|
||
impl ScrollState { | ||
pub fn new(n_rows: usize, selected: Option<usize>, max_scroll_padding: usize) -> Self { | ||
Self { | ||
n_rows, | ||
max_n_rows_to_display: 0, | ||
selected, | ||
offset: selected.map_or(0, |selected| selected.saturating_sub(max_scroll_padding)), | ||
scroll_padding: 0, | ||
max_scroll_padding, | ||
} | ||
} | ||
|
||
#[inline] | ||
pub fn offset(&self) -> usize { | ||
self.offset | ||
} | ||
|
||
fn update_offset(&mut self) { | ||
let Some(selected) = self.selected else { | ||
return; | ||
}; | ||
|
||
let min_offset = (selected + self.scroll_padding) | ||
.saturating_sub(self.max_n_rows_to_display.saturating_sub(1)); | ||
let max_offset = selected.saturating_sub(self.scroll_padding); | ||
let global_max_offset = self.n_rows.saturating_sub(self.max_n_rows_to_display); | ||
|
||
self.offset = self | ||
.offset | ||
.max(min_offset) | ||
.min(max_offset) | ||
.min(global_max_offset); | ||
} | ||
|
||
#[inline] | ||
pub fn selected(&self) -> Option<usize> { | ||
self.selected | ||
} | ||
|
||
fn set_selected(&mut self, selected: usize) { | ||
self.selected = Some(selected); | ||
self.update_offset(); | ||
} | ||
|
||
pub fn select_next(&mut self) { | ||
if let Some(selected) = self.selected { | ||
self.set_selected((selected + 1).min(self.n_rows - 1)); | ||
} | ||
} | ||
|
||
pub fn select_previous(&mut self) { | ||
if let Some(selected) = self.selected { | ||
self.set_selected(selected.saturating_sub(1)); | ||
} | ||
} | ||
|
||
pub fn select_first(&mut self) { | ||
if self.n_rows > 0 { | ||
self.set_selected(0); | ||
} | ||
} | ||
|
||
pub fn select_last(&mut self) { | ||
if self.n_rows > 0 { | ||
self.set_selected(self.n_rows - 1); | ||
} | ||
} | ||
|
||
pub fn set_n_rows(&mut self, n_rows: usize) { | ||
self.n_rows = n_rows; | ||
|
||
if self.n_rows == 0 { | ||
self.selected = None; | ||
return; | ||
} | ||
|
||
self.set_selected(self.selected.map_or(0, |selected| selected.min(n_rows - 1))); | ||
} | ||
|
||
#[inline] | ||
fn update_scroll_padding(&mut self) { | ||
self.scroll_padding = (self.max_n_rows_to_display / 4).min(self.max_scroll_padding); | ||
} | ||
|
||
#[inline] | ||
pub fn max_n_rows_to_display(&self) -> usize { | ||
self.max_n_rows_to_display | ||
} | ||
|
||
pub fn set_max_n_rows_to_display(&mut self, max_n_rows_to_display: usize) { | ||
self.max_n_rows_to_display = max_n_rows_to_display; | ||
self.update_scroll_padding(); | ||
self.update_offset(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters