listing: add set operations to range select actions
Add symmetric difference (default), union, difference and intersection modifiers for selecting ranges. That way you can quickly construct the selection set you need.jmap-eventsource
parent
05ef863a45
commit
594a2bd0dd
|
@ -43,6 +43,20 @@ pub use self::plain::*;
|
|||
mod offline;
|
||||
pub use self::offline::*;
|
||||
|
||||
#[derive(Debug, Copy, PartialEq, Clone)]
|
||||
pub enum Modifier {
|
||||
SymmetricDifference,
|
||||
Union,
|
||||
Difference,
|
||||
Intersection,
|
||||
}
|
||||
|
||||
impl Default for Modifier {
|
||||
fn default() -> Self {
|
||||
Modifier::SymmetricDifference
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct DataColumns {
|
||||
pub columns: [CellBuffer; 12],
|
||||
|
@ -372,7 +386,12 @@ pub trait ListingTrait: Component {
|
|||
_context: &Context,
|
||||
) {
|
||||
}
|
||||
fn set_command_modifier(&mut self, _is_active: bool) {}
|
||||
fn unfocused(&self) -> bool;
|
||||
fn set_modifier_active(&mut self, _new_val: bool) {}
|
||||
fn set_modifier_command(&mut self, _new_val: Option<Modifier>) {}
|
||||
fn modifier_command(&self) -> Option<Modifier> {
|
||||
None
|
||||
}
|
||||
fn set_movement(&mut self, mvm: PageMovement);
|
||||
}
|
||||
|
||||
|
@ -711,14 +730,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
amount
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -764,14 +783,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
amount
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -887,14 +906,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
amount
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -910,14 +929,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
amount
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -933,14 +952,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(mult) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
mult
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -956,14 +975,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(mult) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
mult
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -1022,6 +1041,31 @@ impl Component for Listing {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
UIEvent::Input(ref key)
|
||||
if !self.component.unfocused()
|
||||
&& shortcut!(key == shortcuts[Listing::DESCRIPTION]["union_modifier"])
|
||||
&& self.component.modifier_command().is_some() =>
|
||||
{
|
||||
self.component.set_modifier_command(Some(Modifier::Union));
|
||||
}
|
||||
UIEvent::Input(ref key)
|
||||
if !self.component.unfocused()
|
||||
&& shortcut!(key == shortcuts[Listing::DESCRIPTION]["diff_modifier"])
|
||||
&& self.component.modifier_command().is_some() =>
|
||||
{
|
||||
self.component
|
||||
.set_modifier_command(Some(Modifier::Difference));
|
||||
}
|
||||
UIEvent::Input(ref key)
|
||||
if !self.component.unfocused()
|
||||
&& shortcut!(
|
||||
key == shortcuts[Listing::DESCRIPTION]["intersection_modifier"]
|
||||
)
|
||||
&& self.component.modifier_command().is_some() =>
|
||||
{
|
||||
self.component
|
||||
.set_modifier_command(Some(Modifier::Intersection));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else if self.focus == ListingFocus::Menu {
|
||||
|
@ -1055,14 +1099,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
amount
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -1109,14 +1153,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
amount
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -1165,14 +1209,14 @@ impl Component for Listing {
|
|||
1
|
||||
} else if let Ok(amount) = self.cmd_buf.parse::<usize>() {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
amount
|
||||
} else {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -1240,7 +1284,7 @@ impl Component for Listing {
|
|||
}
|
||||
UIEvent::Input(Key::Esc) | UIEvent::Input(Key::Alt('')) if !self.cmd_buf.is_empty() => {
|
||||
self.cmd_buf.clear();
|
||||
self.component.set_command_modifier(false);
|
||||
self.component.set_modifier_active(false);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufClear));
|
||||
|
@ -1248,7 +1292,7 @@ impl Component for Listing {
|
|||
}
|
||||
UIEvent::Input(Key::Char(c)) if c >= '0' && c <= '9' => {
|
||||
self.cmd_buf.push(c);
|
||||
self.component.set_command_modifier(true);
|
||||
self.component.set_modifier_active(true);
|
||||
context
|
||||
.replies
|
||||
.push_back(UIEvent::StatusEvent(StatusEvent::BufSet(
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
* along with meli. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use super::EntryStrings;
|
||||
use super::*;
|
||||
use crate::components::PageMovement;
|
||||
use crate::jobs::JoinHandle;
|
||||
|
@ -153,7 +152,7 @@ pub struct CompactListing {
|
|||
|
||||
movement: Option<PageMovement>,
|
||||
modifier_active: bool,
|
||||
modifier_command: Option<char>,
|
||||
modifier_command: Option<Modifier>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
|
@ -595,7 +594,9 @@ impl ListingTrait for CompactListing {
|
|||
self.highlight_line(grid, new_area, *idx, context);
|
||||
context.dirty_areas.push_back(new_area);
|
||||
}
|
||||
return;
|
||||
if !self.force_draw {
|
||||
return;
|
||||
}
|
||||
} else if self.cursor_pos != self.new_cursor_pos {
|
||||
self.cursor_pos = self.new_cursor_pos;
|
||||
}
|
||||
|
@ -852,8 +853,20 @@ impl ListingTrait for CompactListing {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_command_modifier(&mut self, is_active: bool) {
|
||||
self.modifier_active = is_active;
|
||||
fn unfocused(&self) -> bool {
|
||||
self.unfocused
|
||||
}
|
||||
|
||||
fn set_modifier_active(&mut self, new_val: bool) {
|
||||
self.modifier_active = new_val;
|
||||
}
|
||||
|
||||
fn set_modifier_command(&mut self, new_val: Option<Modifier>) {
|
||||
self.modifier_command = new_val;
|
||||
}
|
||||
|
||||
fn modifier_command(&self) -> Option<Modifier> {
|
||||
self.modifier_command
|
||||
}
|
||||
|
||||
fn set_movement(&mut self, mvm: PageMovement) {
|
||||
|
@ -1406,8 +1419,7 @@ impl Component for CompactListing {
|
|||
let (upper_left, bottom_right) = area;
|
||||
let rows = get_y(bottom_right) - get_y(upper_left) + 1;
|
||||
|
||||
if let Some('s') = self.modifier_command.take() {
|
||||
self.set_command_modifier(false);
|
||||
if let Some(modifier) = self.modifier_command.take() {
|
||||
if let Some(mvm) = self.movement.as_ref() {
|
||||
match mvm {
|
||||
PageMovement::Up(amount) => {
|
||||
|
@ -1415,16 +1427,47 @@ impl Component for CompactListing {
|
|||
..=self.new_cursor_pos.2
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in (0..self.new_cursor_pos.2.saturating_sub(*amount))
|
||||
.chain((self.new_cursor_pos.2 + 2)..self.length)
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageMovement::PageUp(multiplier) => {
|
||||
for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier)
|
||||
..=self.new_cursor_pos.2
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
|
@ -1433,9 +1476,30 @@ impl Component for CompactListing {
|
|||
..std::cmp::min(self.length, self.new_cursor_pos.2 + amount + 1)
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in (0..self.new_cursor_pos.2).chain(
|
||||
(std::cmp::min(self.length, self.new_cursor_pos.2 + amount + 1)
|
||||
+ 1)..self.length,
|
||||
) {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageMovement::PageDown(multiplier) => {
|
||||
for c in self.new_cursor_pos.2
|
||||
|
@ -1445,27 +1509,87 @@ impl Component for CompactListing {
|
|||
)
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in (0..self.new_cursor_pos.2).chain(
|
||||
(std::cmp::min(
|
||||
self.new_cursor_pos.2 + rows * multiplier + 1,
|
||||
self.length,
|
||||
) + 1)..self.length,
|
||||
) {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageMovement::Right(_) | PageMovement::Left(_) => {}
|
||||
PageMovement::Home => {
|
||||
for c in 0..=self.new_cursor_pos.2 {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in (self.new_cursor_pos.2 + 1)..self.length {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageMovement::End => {
|
||||
for c in self.new_cursor_pos.2..self.length {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in 0..self.new_cursor_pos.2 {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.force_draw = true;
|
||||
}
|
||||
|
||||
if !self.row_updates.is_empty() {
|
||||
|
@ -1540,12 +1664,10 @@ impl Component for CompactListing {
|
|||
}
|
||||
UIEvent::Input(ref key)
|
||||
if !self.unfocused
|
||||
&& shortcut!(
|
||||
key == shortcuts[CompactListing::DESCRIPTION]["select_entry"]
|
||||
) =>
|
||||
&& shortcut!(key == shortcuts[Listing::DESCRIPTION]["select_entry"]) =>
|
||||
{
|
||||
if self.modifier_active {
|
||||
self.modifier_command = Some('s');
|
||||
if self.modifier_active && self.modifier_command.is_none() {
|
||||
self.modifier_command = Some(Modifier::default());
|
||||
} else {
|
||||
let thread_hash = self.get_thread_under_cursor(self.cursor_pos.2);
|
||||
self.selection.entry(thread_hash).and_modify(|e| *e = !*e);
|
||||
|
@ -1783,6 +1905,8 @@ impl Component for CompactListing {
|
|||
|
||||
let config_map = context.settings.shortcuts.compact_listing.key_values();
|
||||
map.insert(CompactListing::DESCRIPTION, config_map);
|
||||
let config_map = context.settings.shortcuts.listing.key_values();
|
||||
map.insert(Listing::DESCRIPTION, config_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ pub struct ConversationsListing {
|
|||
|
||||
movement: Option<PageMovement>,
|
||||
modifier_active: bool,
|
||||
modifier_command: Option<char>,
|
||||
modifier_command: Option<Modifier>,
|
||||
id: ComponentId,
|
||||
}
|
||||
|
||||
|
@ -868,8 +868,20 @@ impl ListingTrait for ConversationsListing {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_command_modifier(&mut self, is_active: bool) {
|
||||
self.modifier_active = is_active;
|
||||
fn unfocused(&self) -> bool {
|
||||
self.unfocused
|
||||
}
|
||||
|
||||
fn set_modifier_active(&mut self, new_val: bool) {
|
||||
self.modifier_active = new_val;
|
||||
}
|
||||
|
||||
fn set_modifier_command(&mut self, new_val: Option<Modifier>) {
|
||||
self.modifier_command = new_val;
|
||||
}
|
||||
|
||||
fn modifier_command(&self) -> Option<Modifier> {
|
||||
self.modifier_command
|
||||
}
|
||||
|
||||
fn set_movement(&mut self, mvm: PageMovement) {
|
||||
|
@ -1260,8 +1272,7 @@ impl Component for ConversationsListing {
|
|||
}
|
||||
let (upper_left, bottom_right) = area;
|
||||
let rows = (get_y(bottom_right) - get_y(upper_left) + 1) / 3;
|
||||
if let Some('s') = self.modifier_command.take() {
|
||||
self.set_command_modifier(false);
|
||||
if let Some(modifier) = self.modifier_command.take() {
|
||||
if let Some(mvm) = self.movement.as_ref() {
|
||||
match mvm {
|
||||
PageMovement::Up(amount) => {
|
||||
|
@ -1269,16 +1280,47 @@ impl Component for ConversationsListing {
|
|||
..=self.new_cursor_pos.2
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in (0..self.new_cursor_pos.2.saturating_sub(*amount))
|
||||
.chain((self.new_cursor_pos.2 + 2)..self.length)
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageMovement::PageUp(multiplier) => {
|
||||
for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier)
|
||||
..=self.new_cursor_pos.2
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
|
@ -1287,9 +1329,30 @@ impl Component for ConversationsListing {
|
|||
..std::cmp::min(self.length, self.new_cursor_pos.2 + amount + 1)
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in (0..self.new_cursor_pos.2).chain(
|
||||
(std::cmp::min(self.length, self.new_cursor_pos.2 + amount + 1)
|
||||
+ 1)..self.length,
|
||||
) {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageMovement::PageDown(multiplier) => {
|
||||
for c in self.new_cursor_pos.2
|
||||
|
@ -1299,24 +1362,83 @@ impl Component for ConversationsListing {
|
|||
)
|
||||
{
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in (0..self.new_cursor_pos.2).chain(
|
||||
(std::cmp::min(
|
||||
self.new_cursor_pos.2 + rows * multiplier + 1,
|
||||
self.length,
|
||||
) + 1)..self.length,
|
||||
) {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageMovement::Right(_) | PageMovement::Left(_) => {}
|
||||
PageMovement::Home => {
|
||||
for c in 0..=self.new_cursor_pos.2 {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in (self.new_cursor_pos.2 + 1)..self.length {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
PageMovement::End => {
|
||||
for c in self.new_cursor_pos.2..self.length {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
match modifier {
|
||||
Modifier::SymmetricDifference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = !*e);
|
||||
}
|
||||
Modifier::Union => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = true);
|
||||
}
|
||||
Modifier::Difference => {
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
}
|
||||
Modifier::Intersection => {}
|
||||
}
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
if modifier == Modifier::Intersection {
|
||||
for c in 0..self.new_cursor_pos.2 {
|
||||
let thread = self.get_thread_under_cursor(c);
|
||||
self.selection.entry(thread).and_modify(|e| *e = false);
|
||||
self.row_updates.push(thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1402,12 +1524,10 @@ impl Component for ConversationsListing {
|
|||
}
|
||||
UIEvent::Input(ref key)
|
||||
if !self.unfocused
|
||||
&& shortcut!(
|
||||
key == shortcuts[ConversationsListing::DESCRIPTION]["select_entry"]
|
||||
) =>
|
||||
&& shortcut!(key == shortcuts[Listing::DESCRIPTION]["select_entry"]) =>
|
||||
{
|
||||
if self.modifier_active {
|
||||
self.modifier_command = Some('s');
|
||||
if self.modifier_active && self.modifier_command.is_none() {
|
||||
self.modifier_command = Some(Modifier::default());
|
||||
} else {
|
||||
let thread_hash = self.get_thread_under_cursor(self.cursor_pos.2);
|
||||
self.selection.entry(thread_hash).and_modify(|e| *e = !*e);
|
||||
|
@ -1631,6 +1751,8 @@ impl Component for ConversationsListing {
|
|||
|
||||
let config_map = context.settings.shortcuts.compact_listing.key_values();
|
||||
map.insert(ConversationsListing::DESCRIPTION, config_map);
|
||||
let config_map = context.settings.shortcuts.listing.key_values();
|
||||
map.insert(Listing::DESCRIPTION, config_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -79,6 +79,10 @@ impl ListingTrait for OfflineListing {
|
|||
|
||||
fn draw_list(&mut self, _: &mut CellBuffer, _: Area, _: &mut Context) {}
|
||||
|
||||
fn unfocused(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn set_movement(&mut self, _: PageMovement) {}
|
||||
}
|
||||
|
||||
|
|
|
@ -703,6 +703,10 @@ impl ListingTrait for PlainListing {
|
|||
}
|
||||
}
|
||||
|
||||
fn unfocused(&self) -> bool {
|
||||
self.unfocused
|
||||
}
|
||||
|
||||
fn set_movement(&mut self, mvm: PageMovement) {
|
||||
self.movement = Some(mvm);
|
||||
self.set_dirty(true);
|
||||
|
@ -1182,9 +1186,7 @@ impl Component for PlainListing {
|
|||
}
|
||||
UIEvent::Input(ref key)
|
||||
if !self.unfocused
|
||||
&& shortcut!(
|
||||
key == shortcuts[PlainListing::DESCRIPTION]["select_entry"]
|
||||
) =>
|
||||
&& shortcut!(key == shortcuts[Listing::DESCRIPTION]["select_entry"]) =>
|
||||
{
|
||||
let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context);
|
||||
self.selection.entry(env_hash).and_modify(|e| *e = !*e);
|
||||
|
@ -1388,6 +1390,8 @@ impl Component for PlainListing {
|
|||
|
||||
let config_map = context.settings.shortcuts.compact_listing.key_values();
|
||||
map.insert(PlainListing::DESCRIPTION, config_map);
|
||||
let config_map = context.settings.shortcuts.listing.key_values();
|
||||
map.insert(Listing::DESCRIPTION, config_map);
|
||||
|
||||
map
|
||||
}
|
||||
|
|
|
@ -734,6 +734,10 @@ impl ListingTrait for ThreadListing {
|
|||
}
|
||||
}
|
||||
|
||||
fn unfocused(&self) -> bool {
|
||||
self.unfocused
|
||||
}
|
||||
|
||||
fn set_movement(&mut self, mvm: PageMovement) {
|
||||
self.movement = Some(mvm);
|
||||
self.set_dirty(true);
|
||||
|
|
|
@ -160,8 +160,7 @@ shortcut_key_values! { "compact-listing",
|
|||
/// Shortcut listing for a mail listing in compact mode.
|
||||
pub struct CompactListingShortcuts {
|
||||
exit_thread |> "Exit thread view." |> Key::Char('i'),
|
||||
open_thread |> "Open thread." |> Key::Char('\n'),
|
||||
select_entry |> "Select thread entry." |> Key::Char('v')
|
||||
open_thread |> "Open thread." |> Key::Char('\n')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,6 +180,10 @@ shortcut_key_values! { "listing",
|
|||
search |> "Search within list of e-mails." |> Key::Char('/'),
|
||||
refresh |> "Manually request a mailbox refresh." |> Key::F(5),
|
||||
set_seen |> "Set thread as seen." |> Key::Char('n'),
|
||||
union_modifier |> "Union modifier." |> Key::Ctrl('u'),
|
||||
diff_modifier |> "Difference modifier." |> Key::Ctrl('d'),
|
||||
intersection_modifier |> "Intersection modifier." |> Key::Ctrl('i'),
|
||||
select_entry |> "Select thread entry." |> Key::Char('v'),
|
||||
toggle_menu_visibility |> "Toggle visibility of side menu in mail list." |> Key::Char('`')
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue