[geary/wip/714793-orientation: 3/3] WIP: Replace folder list with combo box in space-contrained layouts



commit 440e2a11d95a290b318c35ad0bc47656d500f221
Author: Robert Schroll <rschroll gmail com>
Date:   Thu Feb 12 23:27:11 2015 -0500

    WIP: Replace folder list with combo box in space-contrained layouts

 src/client/components/main-window.vala       |   13 +---
 src/client/folder-list/folder-list-tree.vala |  130 +++++++++++++++++++-------
 src/client/sidebar/sidebar-tree.vala         |    4 +-
 3 files changed, 100 insertions(+), 47 deletions(-)
---
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index cae6f86..caa8714 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -6,7 +6,6 @@
 
 public class MainWindow : Gtk.ApplicationWindow {
     private const int MESSAGE_LIST_WIDTH = 250;
-    private const int FOLDER_LIST_WIDTH = 100;
     private const int STATUS_BAR_HEIGHT = 18;
     
     /// Fired when the shift key is pressed or released.
@@ -196,16 +195,6 @@ public class MainWindow : Gtk.ApplicationWindow {
     private void create_layout() {
         Gtk.Box main_layout = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
         
-        // folder list
-        Gtk.ScrolledWindow folder_list_scrolled = new Gtk.ScrolledWindow(null, null);
-        folder_list_scrolled.set_size_request(FOLDER_LIST_WIDTH, -1);
-        folder_list_scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
-        folder_list_scrolled.add(folder_list);
-        Gtk.Frame folder_frame = new Gtk.Frame(null);
-        folder_frame.shadow_type = Gtk.ShadowType.IN;
-        folder_frame.get_style_context ().add_class ("folder_frame");
-        folder_frame.add(folder_list_scrolled);
-        
         // message list
         conversation_list_scrolled = new Gtk.ScrolledWindow(null, null);
         conversation_list_scrolled.set_size_request(MESSAGE_LIST_WIDTH, -1);
@@ -232,7 +221,7 @@ public class MainWindow : Gtk.ApplicationWindow {
         viewer_frame.add(conversation_viewer);
         
         // Folder list to the left of everything.
-        folder_paned.pack1(folder_frame, false, false);
+        folder_paned.pack1(folder_list, false, false);
         folder_paned.pack2(conversation_frame, true, false);
         
         Gtk.Box status_bar_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 0);
diff --git a/src/client/folder-list/folder-list-tree.vala b/src/client/folder-list/folder-list-tree.vala
index 64eb69a..64dcbc9 100644
--- a/src/client/folder-list/folder-list-tree.vala
+++ b/src/client/folder-list/folder-list-tree.vala
@@ -4,14 +4,28 @@
  * (version 2.1 or later).  See the COPYING file in this distribution.
  */
 
-public class FolderList.Tree : Sidebar.Tree {
+public class FolderList.Tree : Gtk.Box {
     public const Gtk.TargetEntry[] TARGET_ENTRY_LIST = {
         { "application/x-geary-mail", Gtk.TargetFlags.SAME_APP, 0 }
     };
     
+    private class FolderTree : Sidebar.Tree {
+        
+        public FolderTree(Gtk.TargetEntry[] target_entries, Gdk.DragAction actions,
+            Sidebar.Tree.ExternalDropHandler drop_handler, Gtk.IconTheme? theme = null) {
+            base(target_entries, actions, drop_handler, theme);
+        }
+        
+        public override bool accept_cursor_changed() {
+            return GearyApplication.instance.controller.can_switch_conversation_view();
+        }
+    }
+    
     private const int INBOX_ORDINAL = -2; // First account branch is zero
     private const int SEARCH_ORDINAL = -1;
     
+    private const int FOLDER_LIST_WIDTH = 100;
+    
     public signal void folder_selected(Geary.Folder? folder);
     public signal void copy_conversation(Geary.Folder folder);
     public signal void move_conversation(Geary.Folder folder);
@@ -21,13 +35,17 @@ public class FolderList.Tree : Sidebar.Tree {
     private InboxesBranch inboxes_branch = new InboxesBranch();
     private SearchBranch? search_branch = null;
     private NewMessagesMonitor? monitor = null;
+    private Sidebar.Tree tree;
+    private bool switching_folders = false;
     
     public Tree() {
-        base(new Gtk.TargetEntry[0], Gdk.DragAction.ASK, drop_handler);
-        entry_selected.connect(on_entry_selected);
+        Object(orientation: Gtk.Orientation.VERTICAL);
+        
+        tree = new FolderTree(new Gtk.TargetEntry[0], Gdk.DragAction.ASK, drop_handler);
+        tree.entry_selected.connect(on_entry_selected);
 
         // Set self as a drag destination.
-        Gtk.drag_dest_set(this, Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT,
+        Gtk.drag_dest_set(tree, Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT,
             TARGET_ENTRY_LIST, Gdk.DragAction.COPY | Gdk.DragAction.MOVE);
         
         // GtkTreeView binds Ctrl+N to "move cursor to next".  Not so interested in that, so we'll
@@ -35,6 +53,52 @@ public class FolderList.Tree : Sidebar.Tree {
         unowned Gtk.BindingSet? binding_set = Gtk.BindingSet.find("GtkTreeView");
         assert(binding_set != null);
         Gtk.BindingEntry.remove(binding_set, Gdk.Key.N, Gdk.ModifierType.CONTROL_MASK);
+        
+        // folder list
+        Gtk.ScrolledWindow folder_list_scrolled = new Gtk.ScrolledWindow(null, null);
+        folder_list_scrolled.set_size_request(FOLDER_LIST_WIDTH, -1);
+        folder_list_scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
+        folder_list_scrolled.add(tree);
+        Gtk.Frame folder_frame = new Gtk.Frame(null);
+        folder_frame.shadow_type = Gtk.ShadowType.IN;
+        folder_frame.get_style_context().add_class("folder_frame");
+        folder_frame.add(folder_list_scrolled);
+        
+        Gtk.ComboBox combo = new Gtk.ComboBox.with_model(tree.store);
+        Gtk.CellRendererText renderer = new Gtk.CellRendererText();
+        combo.pack_start(renderer, true);
+        combo.add_attribute(renderer, "markup", Sidebar.Tree.Columns.NAME);
+        Gtk.TreeSelection select = tree.get_selection();
+        select.changed.connect((selection) => {
+            Gtk.TreeModel model;
+            Gtk.TreeIter? iter = null;
+            if (!switching_folders && selection.get_selected(out model, out iter)) {
+                switching_folders = true;
+                combo.set_active_iter(iter);
+                switching_folders = false;
+            }
+        });
+        combo.changed.connect(() => {
+            Gtk.TreeIter? iter = null;
+            if (!switching_folders && combo.get_active_iter(out iter)) {
+                switching_folders = true;
+                tree.set_cursor(tree.store.get_path(iter), null, false);
+                switching_folders = false;
+            }
+        });
+        
+        pack_start(combo, false, false);
+        pack_start(folder_frame);
+        
+        size_allocate.connect((allocation) => {
+            if (allocation.height > 40) {
+                folder_frame.show();
+                combo.hide();
+            } else {
+                folder_frame.hide();
+                combo.show();
+            }
+        });
     }
     
     ~Tree() {
@@ -51,10 +115,6 @@ public class FolderList.Tree : Sidebar.Tree {
             account_branch.get_entry_for_path(folder.path));
     }
     
-    public override bool accept_cursor_changed() {
-        return GearyApplication.instance.controller.can_switch_conversation_view();
-    }
-    
     private void on_entry_selected(Sidebar.SelectableEntry selectable) {
         AbstractFolderEntry? abstract_folder_entry = selectable as AbstractFolderEntry;
         if (abstract_folder_entry != null)
@@ -66,7 +126,7 @@ public class FolderList.Tree : Sidebar.Tree {
         if (entry != null)
             entry.set_has_new(count > 0);
         
-        if (has_branch(inboxes_branch)) {
+        if (tree.has_branch(inboxes_branch)) {
             InboxFolderEntry? inbox_entry = inboxes_branch.get_entry_for_account(folder.account);
             if (inbox_entry != null)
                 inbox_entry.set_has_new(count > 0);
@@ -96,11 +156,11 @@ public class FolderList.Tree : Sidebar.Tree {
             account_branches.set(folder.account, new AccountBranch(folder.account));
         
         AccountBranch account_branch = account_branches.get(folder.account);
-        if (!has_branch(account_branch))
-            graft(account_branch, folder.account.information.ordinal);
+        if (!tree.has_branch(account_branch))
+            tree.graft(account_branch, folder.account.information.ordinal);
         
-        if (account_branches.size > 1 && !has_branch(inboxes_branch))
-            graft(inboxes_branch, INBOX_ORDINAL); // The Inboxes branch comes first.
+        if (account_branches.size > 1 && !tree.has_branch(inboxes_branch))
+            tree.graft(inboxes_branch, INBOX_ORDINAL); // The Inboxes branch comes first.
         if (folder.special_folder_type == Geary.SpecialFolderType.INBOX)
             inboxes_branch.add_inbox(folder);
         
@@ -111,20 +171,20 @@ public class FolderList.Tree : Sidebar.Tree {
     public void remove_folder(Geary.Folder folder) {
         AccountBranch? account_branch = account_branches.get(folder.account);
         assert(account_branch != null);
-        assert(has_branch(account_branch));
+        assert(tree.has_branch(account_branch));
         
         // If this is the current folder, unselect it.
         Sidebar.Entry? entry = account_branch.get_entry_for_path(folder.path);
         
         // if not found or found but not selected, see if the folder is in the Inboxes branch
-        if (has_branch(inboxes_branch) && (entry == null || !is_selected(entry))) {
+        if (tree.has_branch(inboxes_branch) && (entry == null || !tree.is_selected(entry))) {
             InboxFolderEntry? inbox_entry = inboxes_branch.get_entry_for_account(folder.account);
             if (inbox_entry != null && inbox_entry.folder == folder)
                 entry = inbox_entry;
         }
         
         // if found and selected, report nothing is selected in preparation for its removal
-        if (entry != null && is_selected(entry))
+        if (entry != null && tree.is_selected(entry))
             folder_selected(null);
         
         // if Inbox, remove from inboxes branch, selected or not
@@ -140,42 +200,42 @@ public class FolderList.Tree : Sidebar.Tree {
         if (account_branch != null) {
             // If a folder on this account is selected, unselect it.
             foreach (FolderEntry entry in account_branch.folder_entries.values) {
-                if (is_selected(entry)) {
+                if (tree.is_selected(entry)) {
                     folder_selected(null);
                     break;
                 }
             }
             
-            if (has_branch(account_branch))
-                prune(account_branch);
+            if (tree.has_branch(account_branch))
+                tree.prune(account_branch);
             account_branches.unset(account);
         }
         
         Sidebar.Entry? entry = inboxes_branch.get_entry_for_account(account);
-        if (entry != null && is_selected(entry))
+        if (entry != null && tree.is_selected(entry))
             folder_selected(null);
         
         inboxes_branch.remove_inbox(account);
         
-        if (account_branches.size <= 1 && has_branch(inboxes_branch))
-            prune(inboxes_branch);
+        if (account_branches.size <= 1 && tree.has_branch(inboxes_branch))
+            tree.prune(inboxes_branch);
     }
     
     public void select_folder(Geary.Folder folder) {
         FolderEntry? entry = get_folder_entry(folder);
         if (entry != null)
-            place_cursor(entry, false);
+            tree.place_cursor(entry, false);
     }
     
     public bool select_inbox(Geary.Account account) {
-        if (!has_branch(inboxes_branch))
+        if (!tree.has_branch(inboxes_branch))
             return false;
         
         InboxFolderEntry? entry = inboxes_branch.get_entry_for_account(account);
         if (entry == null)
             return false;
         
-        place_cursor(entry, false);
+        tree.place_cursor(entry, false);
         return true;
     }
     
@@ -202,24 +262,24 @@ public class FolderList.Tree : Sidebar.Tree {
         // Remove branches where the ordinal doesn't match the graft position.
         Gee.ArrayList<AccountBranch> branches_to_reorder = new Gee.ArrayList<AccountBranch>();
         foreach (AccountBranch branch in account_branches.values) {
-            if (get_position_for_branch(branch) != branch.account.information.ordinal) {
-                prune(branch);
+            if (tree.get_position_for_branch(branch) != branch.account.information.ordinal) {
+                tree.prune(branch);
                 branches_to_reorder.add(branch);
             }
         }
         
         // Re-add branches with new positions.
         foreach (AccountBranch branch in branches_to_reorder)
-            graft(branch, branch.account.information.ordinal);
+            tree.graft(branch, branch.account.information.ordinal);
     }
     
     public void set_search(Geary.SearchFolder search_folder) {
-        if (search_branch != null && has_branch(search_branch)) {
+        if (search_branch != null && tree.has_branch(search_branch)) {
             // We already have a search folder.  If it's the same one, just
             // select it.  If it's a new search folder, remove the old one and
             // continue.
             if (search_folder == search_branch.get_search_folder()) {
-                place_cursor(search_branch.get_root(), false);
+                tree.place_cursor(search_branch.get_root(), false);
                 return;
             } else {
                 remove_search();
@@ -227,15 +287,19 @@ public class FolderList.Tree : Sidebar.Tree {
         }
         
         search_branch = new SearchBranch(search_folder);
-        graft(search_branch, SEARCH_ORDINAL);
-        place_cursor(search_branch.get_root(), false);
+        tree.graft(search_branch, SEARCH_ORDINAL);
+        tree.place_cursor(search_branch.get_root(), false);
     }
     
     public void remove_search() {
         if (search_branch != null) {
-            prune(search_branch);
+            tree.prune(search_branch);
             search_branch = null;
         }
     }
+    
+    public bool is_any_selected() {
+        return tree.is_any_selected();
+    }
 }
 
diff --git a/src/client/sidebar/sidebar-tree.vala b/src/client/sidebar/sidebar-tree.vala
index 4ce3046..e471808 100644
--- a/src/client/sidebar/sidebar-tree.vala
+++ b/src/client/sidebar/sidebar-tree.vala
@@ -44,7 +44,7 @@ public class Sidebar.Tree : Gtk.TreeView {
         }
     }
     
-    private enum Columns {
+    public enum Columns {
         NAME,
         TOOLTIP,
         WRAPPER,
@@ -53,7 +53,7 @@ public class Sidebar.Tree : Gtk.TreeView {
         N_COLUMNS
     }
     
-    private Gtk.TreeStore store = new Gtk.TreeStore(Columns.N_COLUMNS,
+    public Gtk.TreeStore store = new Gtk.TreeStore(Columns.N_COLUMNS,
         typeof (string),            // NAME
         typeof (string?),           // TOOLTIP
         typeof (EntryWrapper),      // WRAPPER


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]