[geary/wip/730682-refine-convo-list] Refine selection mode behaviour further.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/730682-refine-convo-list] Refine selection mode behaviour further.
- Date: Wed, 3 Jan 2018 09:03:31 +0000 (UTC)
commit 5aab1229e9fbba7797702edf85f6d8f8ee3b594e
Author: Michael James Gratton <mike vee net>
Date: Sun Dec 31 12:08:26 2017 +1100
Refine selection mode behaviour further.
* src/client/conversation-list/conversation-list.vala (ConversationList):
Mark the existing selected row when invoking selection mode with Shift
or Ctrl clicks. Calculate Shift-click marking from last marked row when
selection mode already enabled. Mark row when activated and selection
mode is enabled. Consume event when a row gets flagged.
* src/client/conversation-list/conversation-list-item.vala
(ConversationListItem): Move keypress event here so we know what row it
is aimed at - just toggle marked state and consume the event.
.../conversation-list/conversation-list-item.vala | 12 ++
.../conversation-list/conversation-list.vala | 130 +++++++++++---------
2 files changed, 86 insertions(+), 56 deletions(-)
---
diff --git a/src/client/conversation-list/conversation-list-item.vala
b/src/client/conversation-list/conversation-list-item.vala
index 49f4c0f..52de137 100644
--- a/src/client/conversation-list/conversation-list-item.vala
+++ b/src/client/conversation-list/conversation-list-item.vala
@@ -143,6 +143,18 @@ public class ConversationListItem : Gtk.ListBoxRow {
update();
}
+ public override bool key_press_event(Gdk.EventKey event) {
+ bool ret = Gdk.EVENT_PROPAGATE;
+ if ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0 &&
+ (event.keyval == Gdk.Key.Return || event.keyval == Gdk.Key.KP_Enter)) {
+ set_marked(true);
+ ret = Gdk.EVENT_STOP;
+ } else {
+ ret = base.key_press_event(event);
+ }
+ return ret;
+ }
+
public override void destroy() {
this.preview_cancellable.cancel();
base.destroy();
diff --git a/src/client/conversation-list/conversation-list.vala
b/src/client/conversation-list/conversation-list.vala
index 0a8cc0b..522cc40 100644
--- a/src/client/conversation-list/conversation-list.vala
+++ b/src/client/conversation-list/conversation-list.vala
@@ -50,6 +50,7 @@ public class ConversationList : Gtk.ListBox {
private bool selection_frozen = false;
private Gee.Map<Geary.App.Conversation,ConversationListItem> marked =
new Gee.HashMap<Geary.App.Conversation,ConversationListItem>();
+ private ConversationListItem? last_marked = null;
private Gee.Set<Geary.App.Conversation>? visible_conversations = null;
private Geary.Scheduler.Scheduled? update_visible_scheduled = null;
private bool enable_load_more = true;
@@ -96,10 +97,7 @@ public class ConversationList : Gtk.ListBox {
set_activate_on_single_click(true);
set_selection_mode(Gtk.SelectionMode.SINGLE);
- this.row_activated.connect((row) => {
- uint activated = row.get_index();
- this.conversation_activated(this.model.get_conversation(activated));
- });
+ this.row_activated.connect(on_row_activated);
this.selected_rows_changed.connect(() => {
selection_changed();
});
@@ -160,6 +158,7 @@ public class ConversationList : Gtk.ListBox {
this.selected = null;
this.selected_index = -1;
this.marked.clear();
+ this.last_marked = null;
this.visible_conversations = null;
Gee.List<Geary.RFC822.MailboxAddress> account_addresses =
displayed.account.information.get_all_mailboxes();
@@ -201,72 +200,70 @@ public class ConversationList : Gtk.ListBox {
}
public override bool button_press_event(Gdk.EventButton event) {
+ bool ret = Gdk.EVENT_PROPAGATE;
if (event.button == 1) {
- if ((event.state & Gdk.ModifierType.SHIFT_MASK) == 0) {
- // Shift isn't down
- if ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0 &&
- !this.is_selection_mode_enabled) {
- // Not currently in selection mode, but Ctrl is
- // down, so enable it
- set_selection_mode_enabled(true);
- selection_mode_enabled();
- }
- if (this.is_selection_mode_enabled) {
- // Are (now) currently in selection mode, so
- // toggle the row
- ConversationListItem? row =
- get_row_at_y((int) event.y) as ConversationListItem;
- if (row != null) {
- row.toggle_marked();
+ ConversationListItem? clicked =
+ get_row_at_y((int) event.y) as ConversationListItem;
+ // Only do something if the user actually clicked o a row,
+ // not e.g. empty space at the bottom of the list.
+ if (clicked != null) {
+ if ((event.state & Gdk.ModifierType.SHIFT_MASK) == 0) {
+ // Shift isn't down
+ if ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0 &&
+ !this.is_selection_mode_enabled) {
+ // Not currently in selection mode, but Ctrl
+ // is down, so enable it then select the
+ // clicked row
+ set_selection_mode_enabled(true);
+ selection_mode_enabled();
+
+ if (clicked != null) {
+ clicked.set_marked(true);
+ ret = Gdk.EVENT_STOP;
+ }
+ } else if (this.is_selection_mode_enabled) {
+ // Already in selection mode, so just toggle
+ // the clicked row
+ if (clicked != null) {
+ clicked.toggle_marked();
+ ret = Gdk.EVENT_STOP;
+ }
}
- }
- } else if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0) {
- // Shift is down, so emulate Gtk.TreeView-like
- // contiguous selection behaviour
- if (!this.is_selection_mode_enabled) {
- set_selection_mode_enabled(true);
- selection_mode_enabled();
- }
- ConversationListItem? clicked =
- get_row_at_y((int) event.y) as ConversationListItem;
- if (clicked != null) {
+ } else if ((event.state & Gdk.ModifierType.SHIFT_MASK) != 0) {
+ // Shift is down, so emulate Gtk.TreeView-like
+ // contiguous selection behaviour
+ ConversationListItem? anchor = null;
ConversationListItem? selected = get_selected_item();
- if (selected == null) {
- selected = get_item_at_index(0);
+ if (!this.is_selection_mode_enabled) {
+ set_selection_mode_enabled(true);
+ selection_mode_enabled();
+
+ // Use the current selection as the anchor
+ // point, or if no selection then the top row
+ anchor = selected;
+ if (anchor == null) {
+ anchor = get_item_at_index(0);
+ }
+ } else {
+ anchor = last_marked;
}
-
- int index = int.min(clicked.get_index(), selected.get_index());
- int end = index + (clicked.get_index() - selected.get_index()).abs();
+ int index = int.min(clicked.get_index(), anchor.get_index());
+ int end = index + (clicked.get_index() - anchor.get_index()).abs();
while (index <= end) {
ConversationListItem? row = get_item_at_index(index++);
if (row != null) {
row.set_marked(true);
}
}
+ ret = Gdk.EVENT_STOP;
}
}
}
- return base.button_press_event(event);
- }
- public override bool key_press_event(Gdk.EventKey event) {
- if (event.keyval == Gdk.Key.Return ||
- event.keyval == Gdk.Key.KP_Enter) {
- if ((event.state & Gdk.ModifierType.CONTROL_MASK) != 0 &&
- !this.is_selection_mode_enabled) {
- set_selection_mode_enabled(true);
- selection_mode_enabled();
- }
- if (this.is_selection_mode_enabled) {
- // Are (now) currently in selection mode, so
- // toggle the row
- ConversationListItem? row = get_selected_item();
- if (row != null) {
- row.toggle_marked();
- }
- }
+ if (ret == Gdk.EVENT_PROPAGATE) {
+ ret = base.button_press_event(event);
}
- return base.key_press_event(event);
+ return ret;
}
internal Gee.Set<Geary.App.Conversation> get_visible_conversations() {
@@ -276,6 +273,9 @@ public class ConversationList : Gtk.ListBox {
}
internal void set_selection_mode_enabled(bool enabled) {
+ // Note we don't fire the selection_mode_enabled signal here
+ // since this also gets called by classes that listen to that
+ // signal, and doing so would create a loop.
if (enabled) {
freeze_selection();
} else {
@@ -438,7 +438,7 @@ public class ConversationList : Gtk.ListBox {
if (removed >= 0) {
// Conversations were removed.
-
+
// Reset the last upper limit so scrolling to the bottom
// will always activate a reload (this is particularly
// important if the model is cleared)
@@ -457,9 +457,27 @@ public class ConversationList : Gtk.ListBox {
}
}
+ private void on_row_activated(Gtk.ListBoxRow row) {
+ ConversationListItem item = (ConversationListItem) row;
+ if (this.is_selection_mode_enabled) {
+ item.toggle_marked();
+ } else {
+ uint activated = row.get_index();
+ this.conversation_activated(this.model.get_conversation(activated));
+ }
+ }
+
private void on_item_marked(ConversationListItem item, bool marked) {
+ if (!this.is_selection_mode_enabled) {
+ // Selection mode not enabled, so the item would have
+ // been Ctrl-activated and we need to enable it
+ set_selection_mode_enabled(true);
+ selection_mode_enabled();
+ }
+
if (marked) {
this.marked.set(item.conversation, item);
+ this.last_marked = item;
} else {
this.marked.remove(item.conversation);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]