Better scroll in options
This commit is contained in:
parent
517c952606
commit
cf7aeff577
1 changed files with 46 additions and 25 deletions
|
|
@ -113,7 +113,7 @@ pub struct Options<T> {
|
||||||
// (score, option)
|
// (score, option)
|
||||||
pub options: Vec<T>,
|
pub options: Vec<T>,
|
||||||
pub ranking: Vec<usize>,
|
pub ranking: Vec<usize>,
|
||||||
pub last_height: usize,
|
last_area: Area,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Options<T> {
|
impl<T> Options<T> {
|
||||||
|
|
@ -124,7 +124,7 @@ impl<T> Options<T> {
|
||||||
selected: 0,
|
selected: 0,
|
||||||
options,
|
options,
|
||||||
ranking,
|
ranking,
|
||||||
last_height: 0,
|
last_area: Area::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,34 +156,55 @@ impl<T> Options<T> {
|
||||||
pub fn requested_height(&self) -> usize {
|
pub fn requested_height(&self) -> usize {
|
||||||
2 + self.ranking.len()
|
2 + self.ranking.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scroll(&mut self, dir: Dir, dist: Dist) {
|
||||||
|
let dist = match dist {
|
||||||
|
Dist::Char => 1,
|
||||||
|
Dist::Page => unimplemented!(),
|
||||||
|
Dist::Doc => self.ranking.len(),
|
||||||
|
};
|
||||||
|
match dir {
|
||||||
|
Dir::Up => {
|
||||||
|
if self.selected == 0 {
|
||||||
|
self.selected = self.ranking.len().saturating_sub(1);
|
||||||
|
} else {
|
||||||
|
self.selected = self.selected.saturating_sub(dist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Dir::Down => {
|
||||||
|
if self.selected == self.ranking.len().saturating_sub(1) {
|
||||||
|
self.selected = 0;
|
||||||
|
} else {
|
||||||
|
self.selected =
|
||||||
|
(self.selected + dist).min(self.ranking.len().saturating_sub(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone> Element<T> for Options<T> {
|
impl<T: Clone> Element<T> for Options<T> {
|
||||||
fn handle(&mut self, state: &mut State, event: Event) -> Result<Resp<T>, Event> {
|
fn handle(&mut self, state: &mut State, event: Event) -> Result<Resp<T>, Event> {
|
||||||
match event.to_action(|e| e.to_go().or_else(|| e.to_move())) {
|
match event.to_action(|e| e.to_go().or_else(|| e.to_move())) {
|
||||||
Some(Action::Move(dir, dist @ (Dist::Char | Dist::Doc), false, false)) => {
|
Some(Action::Move(dir, dist @ (Dist::Char | Dist::Doc), false, false)) => {
|
||||||
let dist = match dist {
|
self.scroll(dir, dist);
|
||||||
Dist::Char => 1,
|
Ok(Resp::handled(None))
|
||||||
Dist::Page => unimplemented!(),
|
}
|
||||||
Dist::Doc => self.ranking.len(),
|
Some(Action::Mouse(MouseAction::Click, pos, _, _))
|
||||||
};
|
if self.last_area.contains(pos).is_some() =>
|
||||||
match dir {
|
{
|
||||||
Dir::Up => {
|
if let Some(pos) = self.last_area.contains(pos) {
|
||||||
if self.selected == 0 {
|
self.selected =
|
||||||
self.selected = self.ranking.len().saturating_sub(1);
|
((pos[1] - self.focus as isize).max(0) as usize).min(self.ranking.len());
|
||||||
} else {
|
}
|
||||||
self.selected = self.selected.saturating_sub(dist);
|
Ok(Resp::handled(None))
|
||||||
}
|
}
|
||||||
}
|
Some(Action::Mouse(MouseAction::Scroll(dir), pos, _, _))
|
||||||
Dir::Down => {
|
if self.last_area.contains(pos).is_some() =>
|
||||||
if self.selected == self.ranking.len().saturating_sub(1) {
|
{
|
||||||
self.selected = 0;
|
if let Some(pos) = self.last_area.contains(pos) {
|
||||||
} else {
|
self.scroll(dir, Dist::Char);
|
||||||
self.selected =
|
|
||||||
(self.selected + dist).min(self.ranking.len().saturating_sub(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => return Err(event),
|
|
||||||
}
|
}
|
||||||
Ok(Resp::handled(None))
|
Ok(Resp::handled(None))
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +234,7 @@ impl<T: Visual> Visual for Options<T> {
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.last_height = frame.size()[1];
|
self.last_area = frame.area();
|
||||||
|
|
||||||
self.focus = self
|
self.focus = self
|
||||||
.focus
|
.focus
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue