listing: make {prev,next}_entry shortcut behavior consistent

prev_entry, next_entry shortcuts (default bindings: Ctrl+p and Ctrl+n)
were not behaving consistently in all different listing index styles. In
particular in some conditions the switch entry shortcuts worked at most
once because the cursor position was not updated properly. This commit
fixes that.

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/372/head
Manos Pitsidianakis 2 months ago
parent 38bca8f8bc
commit 475609fe92
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

@ -264,25 +264,21 @@ impl MailListingTrait for CompactListing {
Box::new(roots.into_iter()) as Box<dyn Iterator<Item = ThreadHash>>, Box::new(roots.into_iter()) as Box<dyn Iterator<Item = ThreadHash>>,
); );
if let Some((thread_hash, env_hash)) = self if self
.get_thread_under_cursor(self.cursor_pos.2) .get_thread_under_cursor(self.cursor_pos.2)
.and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0]))) .and_then(|thread| {
self.rows
.thread_to_env
.get(&thread)
.and_then(|e| Some((thread, e.first()?)))
})
.is_some()
{ {
if !force && old_cursor_pos == self.new_cursor_pos { if !force && old_cursor_pos == self.new_cursor_pos {
self.kick_parent(self.parent, ListingMessage::UpdateView, context); self.kick_parent(self.parent, ListingMessage::UpdateView, context);
} else if self.unfocused() { } else if self.unfocused() {
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.kick_parent(
self.parent,
ListingMessage::OpenEntryUnderCursor {
thread_hash,
env_hash,
show_thread: true,
go_to_first_unread: true,
},
context,
);
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
} }
} }
@ -568,38 +564,32 @@ impl ListingTrait for CompactListing {
fn next_entry(&mut self, context: &mut Context) { fn next_entry(&mut self, context: &mut Context) {
if self if self
.get_thread_under_cursor(self.cursor_pos.2 + 1) .get_thread_under_cursor(self.new_cursor_pos.2 + 1)
.is_some() .is_some()
{ {
// [ref:TODO]: makes this less ugly. // [ref:TODO]: makes this less ugly.
self.movement = Some(PageMovement::Down(1)); self.movement = Some(PageMovement::Down(1));
self.perform_movement(None);
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.cursor_pos.2 += 1;
self.new_cursor_pos.2 += 1;
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
self.cursor_pos.2 -= 1;
self.new_cursor_pos.2 -= 1;
} }
} }
fn prev_entry(&mut self, context: &mut Context) { fn prev_entry(&mut self, context: &mut Context) {
if self.cursor_pos.2 == 0 { if self.new_cursor_pos.2 == 0 {
return; return;
} }
if self if self
.get_thread_under_cursor(self.cursor_pos.2 - 1) .get_thread_under_cursor(self.new_cursor_pos.2 - 1)
.is_some() .is_some()
{ {
// [ref:TODO]: makes this less ugly. // [ref:TODO]: makes this less ugly.
self.movement = Some(PageMovement::Up(1)); self.movement = Some(PageMovement::Up(1));
self.perform_movement(None);
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.cursor_pos.2 -= 1;
self.new_cursor_pos.2 -= 1;
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
self.cursor_pos.2 += 1;
self.new_cursor_pos.2 += 1;
} }
} }
@ -665,52 +655,7 @@ impl ListingTrait for CompactListing {
return; return;
} }
if let Some(mvm) = self.movement.take() { self.perform_movement(Some(rows));
match mvm {
PageMovement::Up(amount) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount);
}
PageMovement::PageUp(multiplier) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier);
}
PageMovement::Down(amount) => {
if self.new_cursor_pos.2 + amount + 1 < self.length {
self.new_cursor_pos.2 += amount;
} else {
self.new_cursor_pos.2 = self.length - 1;
}
}
PageMovement::PageDown(multiplier) => {
if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length {
self.new_cursor_pos.2 += rows * multiplier;
} else if self.new_cursor_pos.2 + rows * multiplier > self.length {
self.new_cursor_pos.2 = self.length - 1;
} else {
self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows;
}
}
PageMovement::Right(amount) => {
self.data_columns.x_offset += amount;
self.data_columns.x_offset = self.data_columns.x_offset.min(
self.data_columns
.widths
.iter()
.map(|w| w + 2)
.sum::<usize>()
.saturating_sub(2),
);
}
PageMovement::Left(amount) => {
self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount);
}
PageMovement::Home => {
self.new_cursor_pos.2 = 0;
}
PageMovement::End => {
self.new_cursor_pos.2 = self.length - 1;
}
}
}
if self.force_draw { if self.force_draw {
grid.clear_area(area, self.color_cache.theme_default); grid.clear_area(area, self.color_cache.theme_default);
@ -876,7 +821,7 @@ impl ListingTrait for CompactListing {
} }
Focus::Entry => { Focus::Entry => {
if let Some((thread_hash, env_hash)) = self if let Some((thread_hash, env_hash)) = self
.get_thread_under_cursor(self.cursor_pos.2) .get_thread_under_cursor(self.new_cursor_pos.2)
.and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0]))) .and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0])))
{ {
self.force_draw = true; self.force_draw = true;
@ -891,6 +836,7 @@ impl ListingTrait for CompactListing {
}, },
context, context,
); );
self.cursor_pos.2 = self.new_cursor_pos.2;
} else { } else {
return; return;
} }
@ -1662,6 +1608,56 @@ impl CompactListing {
} }
} }
} }
fn perform_movement(&mut self, height: Option<usize>) {
let rows = height.unwrap_or(1);
if let Some(mvm) = self.movement.take() {
match mvm {
PageMovement::Up(amount) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount);
}
PageMovement::PageUp(multiplier) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier);
}
PageMovement::Down(amount) => {
if self.new_cursor_pos.2 + amount + 1 < self.length {
self.new_cursor_pos.2 += amount;
} else {
self.new_cursor_pos.2 = self.length - 1;
}
}
PageMovement::PageDown(multiplier) => {
if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length {
self.new_cursor_pos.2 += rows * multiplier;
} else if self.new_cursor_pos.2 + rows * multiplier > self.length {
self.new_cursor_pos.2 = self.length - 1;
} else {
self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows;
}
}
PageMovement::Right(amount) => {
self.data_columns.x_offset += amount;
self.data_columns.x_offset = self.data_columns.x_offset.min(
self.data_columns
.widths
.iter()
.map(|w| w + 2)
.sum::<usize>()
.saturating_sub(2),
);
}
PageMovement::Left(amount) => {
self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount);
}
PageMovement::Home => {
self.new_cursor_pos.2 = 0;
}
PageMovement::End => {
self.new_cursor_pos.2 = self.length - 1;
}
}
}
}
} }
impl Component for CompactListing { impl Component for CompactListing {
@ -1703,7 +1699,9 @@ impl Component for CompactListing {
if let Some(mvm) = self.movement.as_ref() { if let Some(mvm) = self.movement.as_ref() {
match mvm { match mvm {
PageMovement::Up(amount) => { PageMovement::Up(amount) => {
for c in self.cursor_pos.2.saturating_sub(*amount)..=self.cursor_pos.2 { for c in self.new_cursor_pos.2.saturating_sub(*amount)
..=self.new_cursor_pos.2
{
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
thread, thread,
@ -1719,8 +1717,8 @@ impl Component for CompactListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2.saturating_sub(*amount)) for c in (0..self.new_cursor_pos.2.saturating_sub(*amount))
.chain((self.cursor_pos.2 + 2)..self.length) .chain((self.new_cursor_pos.2 + 2)..self.length)
{ {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows self.rows
@ -1730,8 +1728,8 @@ impl Component for CompactListing {
} }
} }
PageMovement::PageUp(multiplier) => { PageMovement::PageUp(multiplier) => {
for c in self.cursor_pos.2.saturating_sub(rows * multiplier) for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier)
..=self.cursor_pos.2 ..=self.new_cursor_pos.2
{ {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
@ -1749,8 +1747,8 @@ impl Component for CompactListing {
} }
} }
PageMovement::Down(amount) => { PageMovement::Down(amount) => {
for c in for c in self.new_cursor_pos.2
self.cursor_pos.2..self.length.min(self.cursor_pos.2 + amount + 1) ..self.length.min(self.new_cursor_pos.2 + amount + 1)
{ {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
@ -1767,8 +1765,9 @@ impl Component for CompactListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2).chain( for c in (0..self.new_cursor_pos.2).chain(
self.length.min(self.cursor_pos.2 + amount) + 1..self.length, self.length.min(self.new_cursor_pos.2 + amount) + 1
..self.length,
) { ) {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows self.rows
@ -1778,8 +1777,10 @@ impl Component for CompactListing {
} }
} }
PageMovement::PageDown(multiplier) => { PageMovement::PageDown(multiplier) => {
for c in self.cursor_pos.2 for c in self.new_cursor_pos.2
..self.length.min(self.cursor_pos.2 + rows * multiplier + 1) ..self
.length
.min(self.new_cursor_pos.2 + rows * multiplier + 1)
{ {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
@ -1796,8 +1797,8 @@ impl Component for CompactListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2).chain( for c in (0..self.new_cursor_pos.2).chain(
self.length.min(self.cursor_pos.2 + rows * multiplier) + 1 self.length.min(self.new_cursor_pos.2 + rows * multiplier) + 1
..self.length, ..self.length,
) { ) {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
@ -1809,7 +1810,7 @@ impl Component for CompactListing {
} }
PageMovement::Right(_) | PageMovement::Left(_) => {} PageMovement::Right(_) | PageMovement::Left(_) => {}
PageMovement::Home => { PageMovement::Home => {
for c in 0..=self.cursor_pos.2 { for c in 0..=self.new_cursor_pos.2 {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
thread, thread,
@ -1825,7 +1826,7 @@ impl Component for CompactListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (self.cursor_pos.2)..self.length { for c in (self.new_cursor_pos.2)..self.length {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows self.rows
.update_selection_with_thread(thread, |e| *e = false); .update_selection_with_thread(thread, |e| *e = false);
@ -1834,7 +1835,7 @@ impl Component for CompactListing {
} }
} }
PageMovement::End => { PageMovement::End => {
for c in self.cursor_pos.2..self.length { for c in self.new_cursor_pos.2..self.length {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
thread, thread,
@ -1850,7 +1851,7 @@ impl Component for CompactListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in 0..self.cursor_pos.2 { for c in 0..self.new_cursor_pos.2 {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows self.rows
.update_selection_with_thread(thread, |e| *e = false); .update_selection_with_thread(thread, |e| *e = false);

@ -227,23 +227,20 @@ impl MailListingTrait for ConversationsListing {
if !force && old_cursor_pos == self.new_cursor_pos && old_mailbox_hash == self.cursor_pos.1 if !force && old_cursor_pos == self.new_cursor_pos && old_mailbox_hash == self.cursor_pos.1
{ {
self.kick_parent(self.parent, ListingMessage::UpdateView, context); self.kick_parent(self.parent, ListingMessage::UpdateView, context);
} else if self.unfocused() { } else if self.unfocused()
if let Some((thread_hash, env_hash)) = self && self
.get_thread_under_cursor(self.cursor_pos.2) .get_thread_under_cursor(self.cursor_pos.2)
.and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0]))) .and_then(|thread| {
{ self.rows
self.kick_parent( .thread_to_env
self.parent, .get(&thread)
ListingMessage::OpenEntryUnderCursor { .and_then(|e| Some((thread, e.first()?)))
thread_hash, })
env_hash, .is_some()
show_thread: true, {
go_to_first_unread: true, self.force_draw = true;
}, self.dirty = true;
context, self.set_focus(Focus::Entry, context);
);
self.set_focus(Focus::Entry, context);
}
} }
} }
@ -412,38 +409,32 @@ impl ListingTrait for ConversationsListing {
fn next_entry(&mut self, context: &mut Context) { fn next_entry(&mut self, context: &mut Context) {
if self if self
.get_thread_under_cursor(self.cursor_pos.2 + 1) .get_thread_under_cursor(self.new_cursor_pos.2 + 1)
.is_some() .is_some()
{ {
// [ref:TODO]: makes this less ugly. // [ref:TODO]: makes this less ugly.
self.movement = Some(PageMovement::Down(1)); self.movement = Some(PageMovement::Down(1));
self.perform_movement(None);
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.cursor_pos.2 += 1;
self.new_cursor_pos.2 += 1;
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
self.cursor_pos.2 -= 1;
self.new_cursor_pos.2 -= 1;
} }
} }
fn prev_entry(&mut self, context: &mut Context) { fn prev_entry(&mut self, context: &mut Context) {
if self.cursor_pos.2 == 0 { if self.new_cursor_pos.2 == 0 {
return; return;
} }
if self if self
.get_thread_under_cursor(self.cursor_pos.2 - 1) .get_thread_under_cursor(self.new_cursor_pos.2 - 1)
.is_some() .is_some()
{ {
// [ref:TODO]: makes this less ugly. // [ref:TODO]: makes this less ugly.
self.movement = Some(PageMovement::Up(1)); self.movement = Some(PageMovement::Up(1));
self.perform_movement(None);
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.cursor_pos.2 -= 1;
self.new_cursor_pos.2 -= 1;
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
self.cursor_pos.2 += 1;
self.new_cursor_pos.2 += 1;
} }
} }
@ -474,42 +465,12 @@ impl ListingTrait for ConversationsListing {
return; return;
} }
let rows = area.height() / 3; let rows = area.height() / 3;
if rows == 0 { if rows == 0 {
return; return;
} }
if let Some(mvm) = self.movement.take() {
match mvm { self.perform_movement(Some(rows));
PageMovement::Up(amount) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount);
}
PageMovement::PageUp(multiplier) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier);
}
PageMovement::Down(amount) => {
if self.new_cursor_pos.2 + amount + 1 < self.length {
self.new_cursor_pos.2 += amount;
} else {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
}
}
PageMovement::PageDown(multiplier) => {
if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length {
self.new_cursor_pos.2 += rows * multiplier;
} else if self.new_cursor_pos.2 + rows * multiplier > self.length {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
} else {
self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows;
}
}
PageMovement::Right(_) | PageMovement::Left(_) => {}
PageMovement::Home => {
self.new_cursor_pos.2 = 0;
}
PageMovement::End => {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
}
}
}
let prev_page_no = (self.cursor_pos.2).wrapping_div(rows); let prev_page_no = (self.cursor_pos.2).wrapping_div(rows);
let page_no = (self.new_cursor_pos.2).wrapping_div(rows); let page_no = (self.new_cursor_pos.2).wrapping_div(rows);
@ -643,8 +604,13 @@ impl ListingTrait for ConversationsListing {
} }
Focus::Entry => { Focus::Entry => {
if let Some((thread_hash, env_hash)) = self if let Some((thread_hash, env_hash)) = self
.get_thread_under_cursor(self.cursor_pos.2) .get_thread_under_cursor(self.new_cursor_pos.2)
.and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0]))) .and_then(|thread| {
self.rows
.thread_to_env
.get(&thread)
.and_then(|e| Some((thread, *e.first()?)))
})
{ {
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
@ -658,6 +624,7 @@ impl ListingTrait for ConversationsListing {
}, },
context, context,
); );
self.cursor_pos.2 = self.new_cursor_pos.2;
} else { } else {
return; return;
} }
@ -1003,6 +970,43 @@ impl ConversationsListing {
} }
} }
} }
fn perform_movement(&mut self, height: Option<usize>) {
let rows = height.unwrap_or(1);
if let Some(mvm) = self.movement.take() {
match mvm {
PageMovement::Up(amount) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount);
}
PageMovement::PageUp(multiplier) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier);
}
PageMovement::Down(amount) => {
if self.new_cursor_pos.2 + amount + 1 < self.length {
self.new_cursor_pos.2 += amount;
} else {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
}
}
PageMovement::PageDown(multiplier) => {
if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length {
self.new_cursor_pos.2 += rows * multiplier;
} else if self.new_cursor_pos.2 + rows * multiplier > self.length {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
} else {
self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows;
}
}
PageMovement::Right(_) | PageMovement::Left(_) => {}
PageMovement::Home => {
self.new_cursor_pos.2 = 0;
}
PageMovement::End => {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
}
}
}
}
} }
impl Component for ConversationsListing { impl Component for ConversationsListing {
@ -1046,7 +1050,9 @@ impl Component for ConversationsListing {
if let Some(mvm) = self.movement.as_ref() { if let Some(mvm) = self.movement.as_ref() {
match mvm { match mvm {
PageMovement::Up(amount) => { PageMovement::Up(amount) => {
for c in self.cursor_pos.2.saturating_sub(*amount)..=self.cursor_pos.2 { for c in self.new_cursor_pos.2.saturating_sub(*amount)
..=self.new_cursor_pos.2
{
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
thread, thread,
@ -1062,8 +1068,8 @@ impl Component for ConversationsListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2.saturating_sub(*amount)) for c in (0..self.new_cursor_pos.2.saturating_sub(*amount))
.chain((self.cursor_pos.2 + 2)..self.length) .chain((self.new_cursor_pos.2 + 2)..self.length)
{ {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows self.rows
@ -1073,8 +1079,8 @@ impl Component for ConversationsListing {
} }
} }
PageMovement::PageUp(multiplier) => { PageMovement::PageUp(multiplier) => {
for c in self.cursor_pos.2.saturating_sub(rows * multiplier) for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier)
..=self.cursor_pos.2 ..=self.new_cursor_pos.2
{ {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
@ -1092,8 +1098,8 @@ impl Component for ConversationsListing {
} }
} }
PageMovement::Down(amount) => { PageMovement::Down(amount) => {
for c in self.cursor_pos.2 for c in self.new_cursor_pos.2
..std::cmp::min(self.length, self.cursor_pos.2 + amount + 1) ..std::cmp::min(self.length, self.new_cursor_pos.2 + amount + 1)
{ {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
@ -1110,9 +1116,9 @@ impl Component for ConversationsListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2).chain( for c in (0..self.new_cursor_pos.2).chain(
(std::cmp::min(self.length, self.cursor_pos.2 + amount + 1) + 1) (std::cmp::min(self.length, self.new_cursor_pos.2 + amount + 1)
..self.length, + 1)..self.length,
) { ) {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows self.rows
@ -1122,9 +1128,9 @@ impl Component for ConversationsListing {
} }
} }
PageMovement::PageDown(multiplier) => { PageMovement::PageDown(multiplier) => {
for c in self.cursor_pos.2 for c in self.new_cursor_pos.2
..std::cmp::min( ..std::cmp::min(
self.cursor_pos.2 + rows * multiplier + 1, self.new_cursor_pos.2 + rows * multiplier + 1,
self.length, self.length,
) )
{ {
@ -1143,9 +1149,9 @@ impl Component for ConversationsListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2).chain( for c in (0..self.new_cursor_pos.2).chain(
(std::cmp::min( (std::cmp::min(
self.cursor_pos.2 + rows * multiplier + 1, self.new_cursor_pos.2 + rows * multiplier + 1,
self.length, self.length,
) + 1)..self.length, ) + 1)..self.length,
) { ) {
@ -1158,7 +1164,7 @@ impl Component for ConversationsListing {
} }
PageMovement::Right(_) | PageMovement::Left(_) => {} PageMovement::Right(_) | PageMovement::Left(_) => {}
PageMovement::Home => { PageMovement::Home => {
for c in 0..=self.cursor_pos.2 { for c in 0..=self.new_cursor_pos.2 {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
thread, thread,
@ -1174,7 +1180,7 @@ impl Component for ConversationsListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (self.cursor_pos.2 + 1)..self.length { for c in (self.new_cursor_pos.2 + 1)..self.length {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows self.rows
.update_selection_with_thread(thread, |e| *e = false); .update_selection_with_thread(thread, |e| *e = false);
@ -1183,7 +1189,7 @@ impl Component for ConversationsListing {
} }
} }
PageMovement::End => { PageMovement::End => {
for c in self.cursor_pos.2..self.length { for c in self.new_cursor_pos.2..self.length {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows.update_selection_with_thread( self.rows.update_selection_with_thread(
thread, thread,
@ -1199,7 +1205,7 @@ impl Component for ConversationsListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in 0..self.cursor_pos.2 { for c in 0..self.new_cursor_pos.2 {
if let Some(thread) = self.get_thread_under_cursor(c) { if let Some(thread) = self.get_thread_under_cursor(c) {
self.rows self.rows
.update_selection_with_thread(thread, |e| *e = false); .update_selection_with_thread(thread, |e| *e = false);
@ -1218,7 +1224,7 @@ impl Component for ConversationsListing {
self.update_line(context, row); self.update_line(context, row);
let row: usize = self.rows.env_order[&row]; let row: usize = self.rows.env_order[&row];
let page_no = (self.cursor_pos.2).wrapping_div(rows); let page_no = (self.new_cursor_pos.2).wrapping_div(rows);
let top_idx = page_no * rows; let top_idx = page_no * rows;
// Update row only if it's currently visible // Update row only if it's currently visible

@ -271,23 +271,12 @@ impl MailListingTrait for PlainListing {
self.redraw_list(context, items); self.redraw_list(context, items);
drop(env_lck); drop(env_lck);
if let Some(env_hash) = self.get_env_under_cursor(self.cursor_pos.2) { if self.get_env_under_cursor(self.new_cursor_pos.2).is_some() {
if !force && old_cursor_pos == self.new_cursor_pos { if !force && old_cursor_pos == self.new_cursor_pos {
self.kick_parent(self.parent, ListingMessage::UpdateView, context); self.kick_parent(self.parent, ListingMessage::UpdateView, context);
} else if self.unfocused() { } else if self.unfocused() {
let thread_hash = self.rows.env_to_thread[&env_hash];
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.kick_parent(
self.parent,
ListingMessage::OpenEntryUnderCursor {
thread_hash,
env_hash,
show_thread: false,
go_to_first_unread: false,
},
context,
);
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
} }
} }
@ -331,28 +320,32 @@ impl ListingTrait for PlainListing {
} }
fn next_entry(&mut self, context: &mut Context) { fn next_entry(&mut self, context: &mut Context) {
if self.get_env_under_cursor(self.cursor_pos.2 + 1).is_some() { if self
.get_env_under_cursor(self.new_cursor_pos.2 + 1)
.is_some()
{
// [ref:TODO]: makes this less ugly. // [ref:TODO]: makes this less ugly.
self.movement = Some(PageMovement::Down(1)); self.movement = Some(PageMovement::Down(1));
self.perform_movement(None);
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.cursor_pos.2 += 1;
self.new_cursor_pos.2 += 1;
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
} }
} }
fn prev_entry(&mut self, context: &mut Context) { fn prev_entry(&mut self, context: &mut Context) {
if self.cursor_pos.2 == 0 { if self.new_cursor_pos.2 == 0 {
return; return;
} }
if self.get_env_under_cursor(self.cursor_pos.2 - 1).is_some() { if self
.get_env_under_cursor(self.new_cursor_pos.2 - 1)
.is_some()
{
// [ref:TODO]: makes this less ugly. // [ref:TODO]: makes this less ugly.
self.movement = Some(PageMovement::Up(1)); self.movement = Some(PageMovement::Up(1));
self.perform_movement(None);
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.cursor_pos.2 -= 1;
self.new_cursor_pos.2 -= 1;
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
} }
} }
@ -418,52 +411,7 @@ impl ListingTrait for PlainListing {
return; return;
} }
if let Some(mvm) = self.movement.take() { self.perform_movement(Some(rows));
match mvm {
PageMovement::Up(amount) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount);
}
PageMovement::PageUp(multiplier) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier);
}
PageMovement::Down(amount) => {
if self.new_cursor_pos.2 + amount + 1 < self.length {
self.new_cursor_pos.2 += amount;
} else {
self.new_cursor_pos.2 = self.length - 1;
}
}
PageMovement::PageDown(multiplier) => {
if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length {
self.new_cursor_pos.2 += rows * multiplier;
} else if self.new_cursor_pos.2 + rows * multiplier > self.length {
self.new_cursor_pos.2 = self.length - 1;
} else {
self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows;
}
}
PageMovement::Right(amount) => {
self.data_columns.x_offset += amount;
self.data_columns.x_offset = self.data_columns.x_offset.min(
self.data_columns
.widths
.iter()
.map(|w| w + 2)
.sum::<usize>()
.saturating_sub(2),
);
}
PageMovement::Left(amount) => {
self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount);
}
PageMovement::Home => {
self.new_cursor_pos.2 = 0;
}
PageMovement::End => {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
}
}
}
if self.force_draw { if self.force_draw {
grid.clear_area(area, self.color_cache.theme_default); grid.clear_area(area, self.color_cache.theme_default);
@ -623,7 +571,7 @@ impl ListingTrait for PlainListing {
} }
Focus::Entry => { Focus::Entry => {
if let Some((thread_hash, env_hash)) = self if let Some((thread_hash, env_hash)) = self
.get_env_under_cursor(self.cursor_pos.2) .get_env_under_cursor(self.new_cursor_pos.2)
.map(|env_hash| (self.rows.env_to_thread[&env_hash], env_hash)) .map(|env_hash| (self.rows.env_to_thread[&env_hash], env_hash))
{ {
self.force_draw = true; self.force_draw = true;
@ -638,6 +586,7 @@ impl ListingTrait for PlainListing {
}, },
context, context,
); );
self.cursor_pos.2 = self.new_cursor_pos.2;
} else { } else {
return; return;
} }
@ -1317,6 +1266,56 @@ impl PlainListing {
} }
} }
} }
fn perform_movement(&mut self, height: Option<usize>) {
let rows = height.unwrap_or(1);
if let Some(mvm) = self.movement.take() {
match mvm {
PageMovement::Up(amount) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount);
}
PageMovement::PageUp(multiplier) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier);
}
PageMovement::Down(amount) => {
if self.new_cursor_pos.2 + amount + 1 < self.length {
self.new_cursor_pos.2 += amount;
} else {
self.new_cursor_pos.2 = self.length - 1;
}
}
PageMovement::PageDown(multiplier) => {
if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length {
self.new_cursor_pos.2 += rows * multiplier;
} else if self.new_cursor_pos.2 + rows * multiplier > self.length {
self.new_cursor_pos.2 = self.length - 1;
} else {
self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows;
}
}
PageMovement::Right(amount) => {
self.data_columns.x_offset += amount;
self.data_columns.x_offset = self.data_columns.x_offset.min(
self.data_columns
.widths
.iter()
.map(|w| w + 2)
.sum::<usize>()
.saturating_sub(2),
);
}
PageMovement::Left(amount) => {
self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount);
}
PageMovement::Home => {
self.new_cursor_pos.2 = 0;
}
PageMovement::End => {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
}
}
}
}
} }
impl Component for PlainListing { impl Component for PlainListing {
@ -1358,7 +1357,9 @@ impl Component for PlainListing {
if let Some(mvm) = self.movement.as_ref() { if let Some(mvm) = self.movement.as_ref() {
match mvm { match mvm {
PageMovement::Up(amount) => { PageMovement::Up(amount) => {
for c in self.cursor_pos.2.saturating_sub(*amount)..=self.cursor_pos.2 { for c in self.new_cursor_pos.2.saturating_sub(*amount)
..=self.new_cursor_pos.2
{
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
env_hash, env_hash,
@ -1374,8 +1375,8 @@ impl Component for PlainListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2.saturating_sub(*amount)) for c in (0..self.new_cursor_pos.2.saturating_sub(*amount))
.chain((self.cursor_pos.2 + 2)..self.length) .chain((self.new_cursor_pos.2 + 2)..self.length)
{ {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows self.rows
@ -1385,8 +1386,8 @@ impl Component for PlainListing {
} }
} }
PageMovement::PageUp(multiplier) => { PageMovement::PageUp(multiplier) => {
for c in self.cursor_pos.2.saturating_sub(rows * multiplier) for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier)
..=self.cursor_pos.2 ..=self.new_cursor_pos.2
{ {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
@ -1404,8 +1405,8 @@ impl Component for PlainListing {
} }
} }
PageMovement::Down(amount) => { PageMovement::Down(amount) => {
for c in for c in self.new_cursor_pos.2
self.cursor_pos.2..self.length.min(self.cursor_pos.2 + amount + 1) ..self.length.min(self.new_cursor_pos.2 + amount + 1)
{ {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
@ -1422,8 +1423,9 @@ impl Component for PlainListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2).chain( for c in (0..self.new_cursor_pos.2).chain(
self.length.min(self.cursor_pos.2 + amount) + 1..self.length, self.length.min(self.new_cursor_pos.2 + amount) + 1
..self.length,
) { ) {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows self.rows
@ -1433,8 +1435,8 @@ impl Component for PlainListing {
} }
} }
PageMovement::PageDown(multiplier) => { PageMovement::PageDown(multiplier) => {
for c in self.cursor_pos.2 for c in self.new_cursor_pos.2
..self.length.min(self.cursor_pos.2 + rows * multiplier) ..self.length.min(self.new_cursor_pos.2 + rows * multiplier)
{ {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
@ -1451,8 +1453,8 @@ impl Component for PlainListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2).chain( for c in (0..self.new_cursor_pos.2).chain(
self.length.min(self.cursor_pos.2 + rows * multiplier) + 1 self.length.min(self.new_cursor_pos.2 + rows * multiplier) + 1
..self.length, ..self.length,
) { ) {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
@ -1464,7 +1466,7 @@ impl Component for PlainListing {
} }
PageMovement::Right(_) | PageMovement::Left(_) => {} PageMovement::Right(_) | PageMovement::Left(_) => {}
PageMovement::Home => { PageMovement::Home => {
for c in 0..=self.cursor_pos.2 { for c in 0..=self.new_cursor_pos.2 {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
env_hash, env_hash,
@ -1480,7 +1482,7 @@ impl Component for PlainListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (self.cursor_pos.2)..self.length { for c in (self.new_cursor_pos.2)..self.length {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows self.rows
.update_selection_with_env(env_hash, |e| *e = false); .update_selection_with_env(env_hash, |e| *e = false);
@ -1489,7 +1491,7 @@ impl Component for PlainListing {
} }
} }
PageMovement::End => { PageMovement::End => {
for c in self.cursor_pos.2..self.length { for c in self.new_cursor_pos.2..self.length {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
env_hash, env_hash,
@ -1505,7 +1507,7 @@ impl Component for PlainListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in 0..self.cursor_pos.2 { for c in 0..self.new_cursor_pos.2 {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows self.rows
.update_selection_with_env(env_hash, |e| *e = false); .update_selection_with_env(env_hash, |e| *e = false);

@ -180,7 +180,7 @@ impl MailListingTrait for ThreadListing {
.any(std::convert::identity); .any(std::convert::identity);
if is_selection_empty { if is_selection_empty {
return self return self
.get_env_under_cursor(self.cursor_pos.2) .get_env_under_cursor(self.new_cursor_pos.2)
.into_iter() .into_iter()
.collect::<_>(); .collect::<_>();
} }
@ -251,12 +251,12 @@ impl MailListingTrait for ThreadListing {
context: &Context, context: &Context,
items: Box<dyn Iterator<Item = ThreadHash>>, items: Box<dyn Iterator<Item = ThreadHash>>,
) { ) {
let account = &context.accounts[&self.cursor_pos.0]; let account = &context.accounts[&self.new_cursor_pos.0];
let threads = account.collection.get_threads(self.cursor_pos.1); let threads = account.collection.get_threads(self.new_cursor_pos.1);
self.length = 0; self.length = 0;
self.rows.clear(); self.rows.clear();
if threads.len() == 0 { if threads.len() == 0 {
let message: String = account[&self.cursor_pos.1].status(); let message: String = account[&self.new_cursor_pos.1].status();
_ = self.data_columns.columns[0].resize_with_context(message.len(), 1, context); _ = self.data_columns.columns[0].resize_with_context(message.len(), 1, context);
let area = self.data_columns.columns[0].area(); let area = self.data_columns.columns[0].area();
self.data_columns.columns[0].grid_mut().write_string( self.data_columns.columns[0].grid_mut().write_string(
@ -296,7 +296,7 @@ impl MailListingTrait for ThreadListing {
let mut prev_group = ThreadHash::null(); let mut prev_group = ThreadHash::null();
let mut hide_from: bool = false; let mut hide_from: bool = false;
let threaded_repeat_identical_from_values: bool = *mailbox_settings!( let threaded_repeat_identical_from_values: bool = *mailbox_settings!(
context[self.cursor_pos.0][&self.cursor_pos.1] context[self.new_cursor_pos.0][&self.new_cursor_pos.1]
.listing .listing
.threaded_repeat_identical_from_values .threaded_repeat_identical_from_values
); );
@ -307,7 +307,7 @@ impl MailListingTrait for ThreadListing {
let envelope: EnvelopeRef = account.collection.get_env(env_hash); let envelope: EnvelopeRef = account.collection.get_env(env_hash);
use melib::search::QueryTrait; use melib::search::QueryTrait;
if let Some(filter_query) = mailbox_settings!( if let Some(filter_query) = mailbox_settings!(
context[self.cursor_pos.0][&self.cursor_pos.1] context[self.new_cursor_pos.0][&self.new_cursor_pos.1]
.listing .listing
.filter .filter
) )
@ -447,28 +447,32 @@ impl ListingTrait for ThreadListing {
} }
fn next_entry(&mut self, context: &mut Context) { fn next_entry(&mut self, context: &mut Context) {
if self.get_env_under_cursor(self.cursor_pos.2 + 1).is_some() { if self
.get_env_under_cursor(self.new_cursor_pos.2 + 1)
.is_some()
{
// [ref:TODO]: makes this less ugly. // [ref:TODO]: makes this less ugly.
self.movement = Some(PageMovement::Down(1)); self.movement = Some(PageMovement::Down(1));
self.perform_movement(None);
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.cursor_pos.2 += 1;
self.new_cursor_pos.2 += 1;
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
} }
} }
fn prev_entry(&mut self, context: &mut Context) { fn prev_entry(&mut self, context: &mut Context) {
if self.cursor_pos.2 == 0 { if self.new_cursor_pos.2 == 0 {
return; return;
} }
if self.get_env_under_cursor(self.cursor_pos.2 - 1).is_some() { if self
.get_env_under_cursor(self.new_cursor_pos.2 - 1)
.is_some()
{
// [ref:TODO]: makes this less ugly. // [ref:TODO]: makes this less ugly.
self.movement = Some(PageMovement::Up(1)); self.movement = Some(PageMovement::Up(1));
self.perform_movement(None);
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
self.cursor_pos.2 -= 1;
self.new_cursor_pos.2 -= 1;
self.set_focus(Focus::Entry, context); self.set_focus(Focus::Entry, context);
} }
} }
@ -502,52 +506,7 @@ impl ListingTrait for ThreadListing {
return; return;
} }
if let Some(mvm) = self.movement.take() { self.perform_movement(Some(rows));
match mvm {
PageMovement::Up(amount) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount);
}
PageMovement::PageUp(multiplier) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier);
}
PageMovement::Down(amount) => {
if self.new_cursor_pos.2 + amount + 1 < self.length {
self.new_cursor_pos.2 += amount;
} else {
self.new_cursor_pos.2 = self.length - 1;
}
}
PageMovement::PageDown(multiplier) => {
if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length {
self.new_cursor_pos.2 += rows * multiplier;
} else if self.new_cursor_pos.2 + rows * multiplier > self.length {
self.new_cursor_pos.2 = self.length - 1;
} else {
self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows;
}
}
PageMovement::Right(amount) => {
self.data_columns.x_offset += amount;
self.data_columns.x_offset = self.data_columns.x_offset.min(
self.data_columns
.widths
.iter()
.map(|w| w + 2)
.sum::<usize>()
.saturating_sub(2),
);
}
PageMovement::Left(amount) => {
self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount);
}
PageMovement::Home => {
self.new_cursor_pos.2 = 0;
}
PageMovement::End => {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
}
}
}
if self.force_draw { if self.force_draw {
grid.clear_area(area, self.color_cache.theme_default); grid.clear_area(area, self.color_cache.theme_default);
@ -729,8 +688,8 @@ impl ListingTrait for ThreadListing {
} }
Focus::Entry => { Focus::Entry => {
if let Some((thread_hash, env_hash)) = self if let Some((thread_hash, env_hash)) = self
.get_env_under_cursor(self.cursor_pos.2) .get_env_under_cursor(self.new_cursor_pos.2)
.map(|env_hash| (self.rows.env_to_thread[&env_hash], env_hash)) .and_then(|env_hash| Some((*self.rows.env_to_thread.get(&env_hash)?, env_hash)))
{ {
self.force_draw = true; self.force_draw = true;
self.dirty = true; self.dirty = true;
@ -744,6 +703,7 @@ impl ListingTrait for ThreadListing {
}, },
context, context,
); );
self.cursor_pos.2 = self.new_cursor_pos.2;
} else { } else {
return; return;
} }
@ -1226,6 +1186,56 @@ impl ThreadListing {
); );
} }
} }
fn perform_movement(&mut self, height: Option<usize>) {
let rows = height.unwrap_or(1);
if let Some(mvm) = self.movement.take() {
match mvm {
PageMovement::Up(amount) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount);
}
PageMovement::PageUp(multiplier) => {
self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier);
}
PageMovement::Down(amount) => {
if self.new_cursor_pos.2 + amount + 1 < self.length {
self.new_cursor_pos.2 += amount;
} else {
self.new_cursor_pos.2 = self.length - 1;
}
}
PageMovement::PageDown(multiplier) => {
if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length {
self.new_cursor_pos.2 += rows * multiplier;
} else if self.new_cursor_pos.2 + rows * multiplier > self.length {
self.new_cursor_pos.2 = self.length - 1;
} else {
self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows;
}
}
PageMovement::Right(amount) => {
self.data_columns.x_offset += amount;
self.data_columns.x_offset = self.data_columns.x_offset.min(
self.data_columns
.widths
.iter()
.map(|w| w + 2)
.sum::<usize>()
.saturating_sub(2),
);
}
PageMovement::Left(amount) => {
self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount);
}
PageMovement::Home => {
self.new_cursor_pos.2 = 0;
}
PageMovement::End => {
self.new_cursor_pos.2 = self.length.saturating_sub(1);
}
}
}
}
} }
impl Component for ThreadListing { impl Component for ThreadListing {
@ -1267,7 +1277,9 @@ impl Component for ThreadListing {
if let Some(mvm) = self.movement.as_ref() { if let Some(mvm) = self.movement.as_ref() {
match mvm { match mvm {
PageMovement::Up(amount) => { PageMovement::Up(amount) => {
for c in self.cursor_pos.2.saturating_sub(*amount)..=self.cursor_pos.2 { for c in self.new_cursor_pos.2.saturating_sub(*amount)
..=self.new_cursor_pos.2
{
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
env_hash, env_hash,
@ -1283,8 +1295,8 @@ impl Component for ThreadListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2.saturating_sub(*amount)) for c in (0..self.new_cursor_pos.2.saturating_sub(*amount))
.chain((self.cursor_pos.2 + 2)..self.length) .chain((self.new_cursor_pos.2 + 2)..self.length)
{ {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows self.rows
@ -1294,8 +1306,8 @@ impl Component for ThreadListing {
} }
} }
PageMovement::PageUp(multiplier) => { PageMovement::PageUp(multiplier) => {
for c in self.cursor_pos.2.saturating_sub(rows * multiplier) for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier)
..=self.cursor_pos.2 ..=self.new_cursor_pos.2
{ {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
@ -1313,8 +1325,8 @@ impl Component for ThreadListing {
} }
} }
PageMovement::Down(amount) => { PageMovement::Down(amount) => {
for c in for c in self.new_cursor_pos.2
self.cursor_pos.2..self.length.min(self.cursor_pos.2 + amount + 1) ..self.length.min(self.new_cursor_pos.2 + amount + 1)
{ {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
@ -1331,8 +1343,9 @@ impl Component for ThreadListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2).chain( for c in (0..self.new_cursor_pos.2).chain(
self.length.min(self.cursor_pos.2 + amount) + 1..self.length, self.length.min(self.new_cursor_pos.2 + amount) + 1
..self.length,
) { ) {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows self.rows
@ -1342,8 +1355,8 @@ impl Component for ThreadListing {
} }
} }
PageMovement::PageDown(multiplier) => { PageMovement::PageDown(multiplier) => {
for c in self.cursor_pos.2 for c in self.new_cursor_pos.2
..self.length.min(self.cursor_pos.2 + rows * multiplier) ..self.length.min(self.new_cursor_pos.2 + rows * multiplier)
{ {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
@ -1360,8 +1373,8 @@ impl Component for ThreadListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (0..self.cursor_pos.2).chain( for c in (0..self.new_cursor_pos.2).chain(
self.length.min(self.cursor_pos.2 + rows * multiplier) + 1 self.length.min(self.new_cursor_pos.2 + rows * multiplier) + 1
..self.length, ..self.length,
) { ) {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
@ -1373,7 +1386,7 @@ impl Component for ThreadListing {
} }
PageMovement::Right(_) | PageMovement::Left(_) => {} PageMovement::Right(_) | PageMovement::Left(_) => {}
PageMovement::Home => { PageMovement::Home => {
for c in 0..=self.cursor_pos.2 { for c in 0..=self.new_cursor_pos.2 {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
env_hash, env_hash,
@ -1389,7 +1402,7 @@ impl Component for ThreadListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in (self.cursor_pos.2)..self.length { for c in (self.new_cursor_pos.2)..self.length {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows self.rows
.update_selection_with_env(env_hash, |e| *e = false); .update_selection_with_env(env_hash, |e| *e = false);
@ -1398,7 +1411,7 @@ impl Component for ThreadListing {
} }
} }
PageMovement::End => { PageMovement::End => {
for c in self.cursor_pos.2..self.length { for c in self.new_cursor_pos.2..self.length {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows.update_selection_with_env( self.rows.update_selection_with_env(
env_hash, env_hash,
@ -1414,7 +1427,7 @@ impl Component for ThreadListing {
} }
} }
if modifier == Modifier::Intersection { if modifier == Modifier::Intersection {
for c in 0..self.cursor_pos.2 { for c in 0..self.new_cursor_pos.2 {
if let Some(env_hash) = self.get_env_under_cursor(c) { if let Some(env_hash) = self.get_env_under_cursor(c) {
self.rows self.rows
.update_selection_with_env(env_hash, |e| *e = false); .update_selection_with_env(env_hash, |e| *e = false);
@ -1434,7 +1447,7 @@ impl Component for ThreadListing {
while let Some(env_hash) = self.rows.row_updates.pop() { while let Some(env_hash) = self.rows.row_updates.pop() {
self.update_line(context, env_hash); self.update_line(context, env_hash);
let row: usize = self.rows.env_order[&env_hash]; let row: usize = self.rows.env_order[&env_hash];
let envelope: EnvelopeRef = context.accounts[&self.cursor_pos.0] let envelope: EnvelopeRef = context.accounts[&self.new_cursor_pos.0]
.collection .collection
.get_env(env_hash); .get_env(env_hash);
let row_attr = row_attr!( let row_attr = row_attr!(
@ -1536,17 +1549,17 @@ impl Component for ThreadListing {
return true; return true;
} }
UIEvent::MailboxUpdate((ref idxa, ref idxf)) UIEvent::MailboxUpdate((ref idxa, ref idxf))
if (*idxa, *idxf) == (self.new_cursor_pos.0, self.cursor_pos.1) => if (*idxa, *idxf) == (self.new_cursor_pos.0, self.new_cursor_pos.1) =>
{ {
self.refresh_mailbox(context, false); self.refresh_mailbox(context, false);
self.set_dirty(true); self.set_dirty(true);
} }
UIEvent::StartupCheck(ref f) if *f == self.cursor_pos.1 => { UIEvent::StartupCheck(ref f) if *f == self.new_cursor_pos.1 => {
self.refresh_mailbox(context, false); self.refresh_mailbox(context, false);
self.set_dirty(true); self.set_dirty(true);
} }
UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => { UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => {
let account = &context.accounts[&self.cursor_pos.0]; let account = &context.accounts[&self.new_cursor_pos.0];
if !account.collection.contains_key(new_hash) { if !account.collection.contains_key(new_hash) {
return false; return false;
} }
@ -1568,7 +1581,7 @@ impl Component for ThreadListing {
} }
} }
UIEvent::EnvelopeUpdate(ref env_hash) => { UIEvent::EnvelopeUpdate(ref env_hash) => {
let account = &context.accounts[&self.cursor_pos.0]; let account = &context.accounts[&self.new_cursor_pos.0];
if !account.collection.contains_key(env_hash) { if !account.collection.contains_key(env_hash) {
return false; return false;
} }
@ -1592,7 +1605,7 @@ impl Component for ThreadListing {
{ {
if self.modifier_active && self.modifier_command.is_none() { if self.modifier_active && self.modifier_command.is_none() {
self.modifier_command = Some(Modifier::default()); self.modifier_command = Some(Modifier::default());
} else if let Some(env_hash) = self.get_env_under_cursor(self.cursor_pos.2) { } else if let Some(env_hash) = self.get_env_under_cursor(self.new_cursor_pos.2) {
self.rows.update_selection_with_env(env_hash, |e| *e = !*e); self.rows.update_selection_with_env(env_hash, |e| *e = !*e);
self.set_dirty(true); self.set_dirty(true);
} }
@ -1612,13 +1625,13 @@ impl Component for ThreadListing {
return true; return true;
} }
Action::Listing(Search(ref filter_term)) if !self.unfocused() => { Action::Listing(Search(ref filter_term)) if !self.unfocused() => {
match context.accounts[&self.cursor_pos.0].search( match context.accounts[&self.new_cursor_pos.0].search(
filter_term, filter_term,
self.sort, self.sort,
self.cursor_pos.1, self.new_cursor_pos.1,
) { ) {
Ok(job) => { Ok(job) => {
let handle = context.accounts[&self.cursor_pos.0] let handle = context.accounts[&self.new_cursor_pos.0]
.main_loop_handler .main_loop_handler
.job_executor .job_executor
.spawn_specialized("search".into(), job); .spawn_specialized("search".into(), job);

Loading…
Cancel
Save