[gnome-todo/wip/gbsneto/plugins: 2/2] panels: add List selector panel



commit 8639b41c9d34d13e5ef9767ccf63fec785d3e18a
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Dec 28 18:27:01 2015 -0200

    panels: add List selector panel
    
    The list selector panel is the port of the
    old "Lists" tab to the new model, which is
    a GtdPanel implementation.
    
    This implements the basic grid view using
    a GtkFlowBox. Next logical step is to add
    a list view using GtkListBox.

 data/Makefile.am                    |    1 +
 data/todo.gresource.xml             |    1 +
 data/ui/list-selector-panel.ui      |  261 ++++++++++++++++
 data/ui/window.ui                   |  278 +-----------------
 src/Makefile.am                     |    4 +
 src/gtd-window.c                    |  551 ++---------------------------------
 src/views/gtd-list-selector-grid.c  |  413 ++++++++++++++++++++++++++
 src/views/gtd-list-selector-grid.h  |   36 +++
 src/views/gtd-list-selector-panel.c |  556 +++++++++++++++++++++++++++++++++++
 src/views/gtd-list-selector-panel.h |   36 +++
 10 files changed, 1334 insertions(+), 803 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index 3e8b513..f1b2ee7 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -32,6 +32,7 @@ EXTRA_DIST=                     \
   gtk/menus.ui \
   ui/edit-pane.ui \
   ui/initial-setup.ui \
+  ui/list-selector-panel.ui \
   ui/list-view.ui \
   ui/notification.ui \
   ui/provider-dialog.ui \
diff --git a/data/todo.gresource.xml b/data/todo.gresource.xml
index 46e12c4..c4d7648 100644
--- a/data/todo.gresource.xml
+++ b/data/todo.gresource.xml
@@ -4,6 +4,7 @@
     <file alias="gtk/menus.ui">gtk/menus.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/edit-pane.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/initial-setup.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">ui/list-selector-panel.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/list-view.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/notification.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/provider-dialog.ui</file>
diff --git a/data/ui/list-selector-panel.ui b/data/ui/list-selector-panel.ui
new file mode 100644
index 0000000..a5059fc
--- /dev/null
+++ b/data/ui/list-selector-panel.ui
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.19.0 -->
+<interface>
+  <requires lib="gtk+" version="3.16"/>
+  <template class="GtdListSelectorPanel" parent="GtkStack">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="transition_type">crossfade</property>
+    <signal name="key-press-event" handler="gtd_list_selector_panel_on_key_press_event" object="search_bar" 
swapped="no" />
+    <child>
+      <object class="GtkBox" id="lists">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="GtkSearchBar" id="search_bar">
+            <property name="visible">True</property>
+            <property name="app_paintable">True</property>
+            <property name="can_focus">False</property>
+            <property name="show_close_button">True</property>
+            <child>
+              <object class="GtkSearchEntry" id="search_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="width_chars">40</property>
+                <property name="primary_icon_name">edit-find-symbolic</property>
+                <property name="primary_icon_activatable">False</property>
+                <property name="primary_icon_sensitive">False</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <child>
+              <object class="GtkViewport" id="viewport">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="shadow_type">none</property>
+                <child>
+                  <object class="GtkStack" id="stack">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hhomogeneous">False</property>
+                    <property name="vhomogeneous">False</property>
+                    <property name="transition_type">crossfade</property>
+                    <child>
+                      <placeholder/>
+                    </child>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkActionBar" id="actionbar">
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkButton" id="rename_button">
+                <property name="label" translatable="yes">Rename</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+              </object>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="delete_button">
+                <property name="label" translatable="yes">Delete</property>
+                <property name="visible">True</property>
+                <property name="sensitive">False</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <signal name="clicked" handler="gtd_list_selector_panel_delete_button_clicked" 
object="GtdListSelectorPanel" swapped="no" />
+                <style>
+                  <class name="destructive-action"/>
+                </style>
+              </object>
+              <packing>
+                <property name="pack_type">end</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="name">lists</property>
+        <property name="title" translatable="yes">Lists</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtdTaskListView" id="tasklist_view">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="readonly">False</property>
+      </object>
+      <packing>
+        <property name="name">tasks</property>
+        <property name="title" translatable="yes">Tasks</property>
+        <property name="position">1</property>
+      </packing>
+    </child>
+  </template>
+  <object class="GtkPopover" id="rename_popover">
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <child>
+      <object class="GtkGrid" id="grid">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="row_spacing">12</property>
+        <property name="column_spacing">12</property>
+        <child>
+          <object class="GtkLabel" id="label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Name of the task list</property>
+            <property name="xalign">0</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+            <property name="width">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkEntry" id="rename_entry">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <signal name="notify::text" handler="gtd_list_selector_panel_rename_entry_text_changed" 
object="GtdListSelectorPanel" swapped="no" />
+            <signal name="activate" handler="gtd_list_selector_panel_rename_task_list" 
object="GtdListSelectorPanel" swapped="yes" />
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="save_rename_button">
+            <property name="label" translatable="yes">Rename</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <signal name="clicked" handler="gtd_list_selector_panel_rename_task_list" 
object="GtdListSelectorPanel" swapped="yes" />
+            <style>
+              <class name="suggested-action"/>
+            </style>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkButton" id="back_button">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="halign">start</property>
+    <child>
+      <object class="GtkImage">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="icon_name">go-previous-symbolic</property>
+      </object>
+    </child>
+  </object>
+  <object class="GtkToggleButton" id="search_button">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="halign">end</property>
+    <child>
+      <object class="GtkImage">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="icon_name">edit-find-symbolic</property>
+      </object>
+    </child>
+  </object>
+  <object class="GtkToggleButton" id="selection_button">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="halign">end</property>
+    <child>
+      <object class="GtkImage">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="icon_name">emblem-ok-symbolic</property>
+      </object>
+    </child>
+  </object>
+  <object class="GtkButton" id="view_button">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="halign">end</property>
+    <child>
+      <object class="GtkImage" id="view_button_image">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="icon_name">view-grid-symbolic</property>
+      </object>
+    </child>
+  </object>
+  <object class="GtkColorButton" id="color_button">
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="halign">end</property>
+    <signal name="color_set" handler="gtd_list_selector_panel_list_color_set" object="GtdListSelectorPanel" 
swapped="no" />
+  </object>
+  <object class="GtkMenuButton" id="new_list_button">
+    <property name="visible" bind-source="back_button" bind-property="visible" 
bind-flags="invert-boolean|sync-create"/>
+    <property name="can_focus">True</property>
+    <property name="receives_default">True</property>
+    <property name="popover">new_list_popover</property>
+    <property name="halign">start</property>
+    <child>
+      <object class="GtkLabel" id="new_list_button_label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">New List</property>
+      </object>
+    </child>
+  </object>
+  <object class="GtdProviderPopover" id="new_list_popover">
+    <property name="can_focus">False</property>
+    <property name="position">bottom</property>
+  </object>
+</interface>
diff --git a/data/ui/window.ui b/data/ui/window.ui
index 1d320d7..1a60fa5 100644
--- a/data/ui/window.ui
+++ b/data/ui/window.ui
@@ -2,10 +2,6 @@
 <!-- Generated with glade 3.18.1 -->
 <interface>
   <requires lib="gtk+" version="3.16"/>
-  <object class="GtdProviderPopover" id="new_list_popover">
-    <property name="can_focus">False</property>
-    <property name="position">bottom</property>
-  </object>
   <object class="GtdProviderDialog" id="provider_dialog">
     <property name="visible">False</property>
     <property name="modal">True</property>
@@ -15,7 +11,6 @@
     <property name="can_focus">False</property>
     <property name="default_width">800</property>
     <property name="default_height">600</property>
-    <signal name="key-press-event" handler="gtd_window__on_key_press_event" object="search_bar" swapped="no" 
/>
     <child>
       <object class="GtkOverlay" id="overlay">
         <property name="visible">True</property>
@@ -29,143 +24,17 @@
           </object>
         </child>
         <child>
-          <object class="GtkStack" id="main_stack">
+          <object class="GtkStack" id="stack">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="transition_duration">250</property>
             <property name="transition_type">crossfade</property>
             <signal name="notify::visible-child" handler="gtd_window__stack_visible_child_cb" 
object="GtdWindow" swapped="yes" />
-            <child>
-              <object class="GtkBox" id="main_box">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="hexpand">True</property>
-                <property name="vexpand">True</property>
-                <property name="orientation">vertical</property>
-                <child>
-                  <object class="GtkSearchBar" id="search_bar">
-                    <property name="visible">True</property>
-                    <property name="show_close_button">True</property>
-                    <property name="search_mode_enabled" bind-source="search_button" bind-property="active" 
bind-flags="default|bidirectional" />
-                    <child>
-                      <object class="GtkSearchEntry" id="search_entry">
-                        <property name="visible">True</property>
-                        <property name="width_request">400</property>
-                        <signal name="search-changed" handler="gtk_flow_box_invalidate_filter" 
object="lists_flowbox" swapped="yes" />
-                      </object>
-                    </child>
-                  </object>
-                </child>
-                <child>
-                  <object class="GtkStack" id="stack">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="hexpand">True</property>
-                    <property name="vexpand">True</property>
-                    <property name="transition_duration">250</property>
-                    <property name="transition_type">crossfade</property>
-                    <signal name="notify::visible-child" handler="gtd_window__stack_visible_child_cb" 
object="GtdWindow" swapped="yes" />
-                    <style>
-                      <class name="background" />
-                    </style>
-                    <child>
-                      <object class="GtkScrolledWindow" id="lists_scrolled_window">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="vexpand">True</property>
-                        <property name="hscrollbar_policy">never</property>
-                        <child>
-                          <object class="GtkViewport" id="lists_viewport">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="shadow_type">none</property>
-                            <child>
-                              <object class="GtkFlowBox" id="lists_flowbox">
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="has_focus">True</property>
-                                <property name="halign">start</property>
-                                <property name="valign">start</property>
-                                <property name="hexpand">True</property>
-                                <property name="vexpand">True</property>
-                                <property name="border_width">12</property>
-                                <property name="homogeneous">True</property>
-                                <property name="column_spacing">12</property>
-                                <property name="row_spacing">12</property>
-                                <property name="max_children_per_line">100</property>
-                                <property name="selection_mode">none</property>
-                                <signal name="child-activated" handler="gtd_window__list_selected" 
object="GtdWindow" swapped="no" />
-                              </object>
-                            </child>
-                          </object>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="name">lists</property>
-                        <property name="title" translatable="yes">Lists</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkActionBar" id="action_bar">
-                    <property name="can_focus">False</property>
-                    <child>
-                      <object class="GtkButton" id="rename_button">
-                        <property name="label" translatable="yes">Rename</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="sensitive">False</property>
-                        <signal name="clicked" handler="gtd_window__rename_button_clicked" 
object="GtdWindow" swapped="yes" />
-                      </object>
-                      <packing>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkButton" id="remove_button">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="sensitive">False</property>
-                        <property name="label" translatable="yes">Delete</property>
-                        <signal name="clicked" handler="gtd_window__remove_button_clicked" 
object="GtdWindow" swapped="yes" />
-                        <style>
-                          <class name="destructive-action"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="pack_type">end</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                  </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">2</property>
-                  </packing>
-                </child>
-              </object>
-              <packing>
-                <property name="name">overview</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtdTaskListView" id="list_view">
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="readonly">False</property>
-              </object>
-              <packing>
-                <property name="name">tasks</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
+            <style>
+              <class name="background" />
+            </style>
           </object>
         </child>
       </object>
@@ -175,38 +44,6 @@
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="show_close_button">True</property>
-        <child>
-          <object class="GtkButton" id="back_button">
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <signal name="clicked" handler="gtd_window__back_button_clicked" object="GtdWindow" swapped="no" 
/>
-            <child>
-              <object class="GtkImage" id="back_button_image">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="icon_name">go-previous-symbolic</property>
-              </object>
-            </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkMenuButton" id="new_list_button">
-            <property name="visible" bind-source="back_button" bind-property="visible" 
bind-flags="invert-boolean|sync-create"/>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="popover">new_list_popover</property>
-            <child>
-              <object class="GtkLabel" id="new_list_button_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes">New List</property>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="position">1</property>
-          </packing>
-        </child>
         <child type="title">
           <object class="GtkStackSwitcher" id="stack_switcher">
             <property name="visible">True</property>
@@ -244,108 +81,7 @@
             <property name="pack_type">end</property>
           </packing>
         </child>
-        <child>
-          <object class="GtkToggleButton" id="select_button">
-            <property name="visible" bind-source="back_button" bind-property="visible" 
bind-flags="default|invert-boolean|sync-create"/>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <signal name="toggled" handler="gtd_window__select_button_toggled" object="GtdWindow" 
swapped="no" />
-            <child>
-              <object class="GtkImage" id="select_button_image">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="icon_name">object-select-symbolic</property>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="pack_type">end</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkToggleButton" id="search_button">
-            <property name="visible" bind-source="back_button" bind-property="visible" 
bind-flags="invert-boolean|sync-create"/>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <child>
-              <object class="GtkImage" id="search_button_image">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="icon_name">edit-find-symbolic</property>
-              </object>
-            </child>
-          </object>
-          <packing>
-            <property name="pack_type">end</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkColorButton" id="color_button">
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <signal name="color_set" handler="gtd_window__list_color_set" object="GtdWindow" swapped="no" />
-          </object>
-          <packing>
-            <property name="pack_type">end</property>
-          </packing>
-        </child>
       </object>
     </child>
   </template>
-  <object class="GtkPopover" id="rename_popover">
-    <property name="can_focus">False</property>
-    <property name="border_width">12</property>
-    <child>
-      <object class="GtkGrid" id="grid">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="row_spacing">12</property>
-        <property name="column_spacing">12</property>
-        <child>
-          <object class="GtkLabel" id="label">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="label" translatable="yes">Name of the task list</property>
-            <property name="xalign">0</property>
-            <attributes>
-              <attribute name="weight" value="bold"/>
-            </attributes>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">0</property>
-            <property name="width">2</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkEntry" id="rename_entry">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <signal name="notify::text" handler="gtd_window__rename_entry_text_changed" object="GtdWindow" 
swapped="no" />
-            <signal name="activate" handler="gtd_window__rename_task_list" object="GtdWindow" swapped="yes" 
/>
-          </object>
-          <packing>
-            <property name="left_attach">0</property>
-            <property name="top_attach">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="save_rename_button">
-            <property name="label" translatable="yes">Rename</property>
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <signal name="clicked" handler="gtd_window__rename_task_list" object="GtdWindow" swapped="yes" />
-            <style>
-              <class name="suggested-action"/>
-            </style>
-          </object>
-          <packing>
-            <property name="left_attach">1</property>
-            <property name="top_attach">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
 </interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index 718d0d1..afbc54b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,6 +40,10 @@ gnome_todo_SOURCES = \
        provider/gtd-provider-selector.h \
        views/gtd-list-selector.c \
        views/gtd-list-selector.h \
+       views/gtd-list-selector-grid.c \
+       views/gtd-list-selector-grid.h \
+       views/gtd-list-selector-panel.c \
+       views/gtd-list-selector-panel.h \
        gtd-application.c \
        gtd-application.h \
        gtd-arrow-frame.c \
diff --git a/src/gtd-window.c b/src/gtd-window.c
index d0d6a2c..35b04d7 100644
--- a/src/gtd-window.c
+++ b/src/gtd-window.c
@@ -18,6 +18,7 @@
 
 #include "interfaces/gtd-provider.h"
 #include "interfaces/gtd-panel.h"
+#include "views/gtd-list-selector-panel.h"
 #include "gtd-application.h"
 #include "gtd-enum-types.h"
 #include "gtd-task-list-view.h"
@@ -34,32 +35,13 @@
 
 typedef struct
 {
-  GtkWidget                     *action_bar;
-  GtkButton                     *back_button;
   GtkWidget                     *cancel_selection_button;
-  GtkColorButton                *color_button;
   GtkWidget                     *gear_menu_button;
   GtkHeaderBar                  *headerbar;
-  GtkFlowBox                    *lists_flowbox;
-  GtkStack                      *main_stack;
-  GtkWidget                     *new_list_button;
-  GtkWidget                     *new_list_popover;
   GtdNotificationWidget         *notification_widget;
-  GtkWidget                     *remove_button;
-  GtkWidget                     *rename_button;
-  GtkSearchBar                  *search_bar;
-  GtkToggleButton               *search_button;
-  GtkSearchEntry                *search_entry;
-  GtkWidget                     *select_button;
   GtkStack                      *stack;
   GtkStackSwitcher              *stack_switcher;
   GtdProviderDialog             *provider_dialog;
-  GtdTaskListView               *list_view;
-
-  /* rename popover */
-  GtkWidget                     *rename_entry;
-  GtkWidget                     *rename_popover;
-  GtkWidget                     *save_rename_button;
 
   /* mode */
   GtdWindowMode                  mode;
@@ -81,10 +63,6 @@ struct _GtdWindow
 
 #define              SAVE_GEOMETRY_ID_TIMEOUT                    100 /* ms */
 
-static void          gtd_window__create_new_list                 (GSimpleAction         *simple,
-                                                                  GVariant              *parameter,
-                                                                  gpointer               user_data);
-
 static void          gtd_window__change_storage_action           (GSimpleAction         *simple,
                                                                   GVariant              *parameter,
                                                                   gpointer               user_data);
@@ -93,7 +71,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtdWindow, gtd_window, GTK_TYPE_APPLICATION_WINDOW)
 
 static const GActionEntry gtd_window_entries[] = {
   { "change-storage", gtd_window__change_storage_action },
-  { "new-list", gtd_window__create_new_list }
 };
 
 enum {
@@ -302,224 +279,14 @@ gtd_window__save_geometry (gpointer user_data)
   return FALSE;
 }
 
-static GtdTaskListItem*
-get_selected_list (GtdWindow *window)
-{
-  GtdWindowPrivate *priv;
-  GtdTaskListItem *item;
-  GList *children;
-  GList *l;
-
-  priv = window->priv;
-  item = NULL;
-
-  /* Retrieve the only selected task list */
-  children = gtk_container_get_children (GTK_CONTAINER (priv->lists_flowbox));
-
-  for (l = children; l != NULL; l = l->next)
-    {
-      if (gtd_task_list_item_get_selected (l->data))
-        {
-          item = l->data;
-          break;
-        }
-    }
-
-  g_list_free (children);
-
-  return item;
-}
-
-static void
-gtd_window__remove_button_clicked (GtdWindow *window)
-{
-  GtdWindowPrivate *priv;
-  GtkWidget *dialog;
-  GtkWidget *button;
-  GList *children;
-  GList *l;
-  gint response;
-
-  priv = window->priv;
-  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
-                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | 
GTK_DIALOG_USE_HEADER_BAR,
-                                   GTK_MESSAGE_QUESTION,
-                                   GTK_BUTTONS_NONE,
-                                   _("Remove the selected task lists?"));
-
-  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                                            _("Once removed, the task lists cannot be recovered."));
-
-  /* Focus the Cancel button by default */
-  gtk_dialog_add_button (GTK_DIALOG (dialog),
-                         _("Cancel"),
-                         GTK_RESPONSE_CANCEL);
-
-  button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
-  gtk_widget_grab_focus (button);
-
-  /* Make the Remove button visually destructive */
-  gtk_dialog_add_button (GTK_DIALOG (dialog),
-                         _("Remove task lists"),
-                         GTK_RESPONSE_ACCEPT);
-
-  button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
-  gtk_style_context_add_class (gtk_widget_get_style_context (button), "destructive-action");
-
-  response = gtk_dialog_run (GTK_DIALOG (dialog));
-
-  /* Remove selected lists */
-  if (response == GTK_RESPONSE_ACCEPT)
-    {
-      children = gtk_container_get_children (GTK_CONTAINER (priv->lists_flowbox));
-
-      for (l = children; l != NULL; l = l->next)
-        {
-          if (gtd_task_list_item_get_selected (l->data))
-            {
-              GtdTaskList *list;
-
-              list = gtd_task_list_item_get_list (l->data);
-
-              if (gtd_task_list_is_removable (list))
-                gtd_manager_remove_task_list (priv->manager, list);
-            }
-        }
-
-      g_list_free (children);
-    }
-
-  gtk_widget_destroy (dialog);
-
-  /* After removing the lists, exit SELECTION mode */
-  gtd_window_set_mode (window, GTD_WINDOW_MODE_NORMAL);
-}
-
-static void
-gtd_window__rename_button_clicked (GtdWindow *window)
-{
-  GtdWindowPrivate *priv;
-  GtdTaskListItem *item;
-
-  priv = window->priv;
-  item = get_selected_list (window);
-
-  if (item)
-    {
-      GtdTaskList *list;
-
-      list = gtd_task_list_item_get_list (item);
-
-      gtk_popover_set_relative_to (GTK_POPOVER (priv->rename_popover), GTK_WIDGET (item));
-      gtk_entry_set_text (GTK_ENTRY (priv->rename_entry), gtd_task_list_get_name (list));
-      gtk_widget_show (priv->rename_popover);
-
-      gtk_widget_grab_focus (priv->rename_entry);
-    }
-}
-
-static void
-gtd_window__rename_entry_text_changed (GObject *object,
-                                       GParamSpec *pspec,
-                                       GtdWindow *window)
-{
-  gtk_widget_set_sensitive (window->priv->save_rename_button,
-                            gtk_entry_get_text_length (GTK_ENTRY (object)) > 0);
-}
-
-static void
-gtd_window__rename_task_list (GtdWindow *window)
-{
-  GtdWindowPrivate *priv;
-  GtdTaskListItem *item;
-
-  priv = window->priv;
-
-  /*
-   * If the save_rename_button is insensitive, the list name is
-   * empty and cannot be saved.
-   */
-  if (!gtk_widget_get_sensitive (priv->save_rename_button))
-    return;
-
-  item = get_selected_list (window);
-
-  if (item)
-    {
-      GtdTaskList *list;
-
-      list = gtd_task_list_item_get_list (item);
-
-      gtd_task_list_set_name (list, gtk_entry_get_text (GTK_ENTRY (priv->rename_entry)));
-      gtk_flow_box_invalidate_sort (GTK_FLOW_BOX (priv->lists_flowbox));
-      gtd_window_set_mode (window, GTD_WINDOW_MODE_NORMAL);
-
-      gtk_widget_hide (priv->rename_popover);
-    }
-}
-
-static void
-gtd_window__stack_visible_child_cb (GtdWindow *window)
-{
-  GtdWindowPrivate *priv;
-  gboolean is_list_view;
-
-  priv = window->priv;
-  is_list_view = g_strcmp0 (gtk_stack_get_visible_child_name (priv->main_stack), "overview") == 0 &&
-                 g_strcmp0 (gtk_stack_get_visible_child_name (priv->stack), "lists") == 0;
-
-  gtk_widget_set_visible (GTK_WIDGET (priv->search_button), is_list_view);
-  gtk_widget_set_visible (GTK_WIDGET (priv->select_button), is_list_view);
-  gtk_widget_set_visible (priv->gear_menu_button, !is_list_view);
-}
-
-static void
-update_action_bar_buttons (GtdWindow *window)
-{
-  GtdWindowPrivate *priv;
-  GList *children;
-  GList *l;
-  gboolean all_lists_removable;
-  gint selected_lists;
-
-  priv = window->priv;
-  children = gtk_container_get_children (GTK_CONTAINER (priv->lists_flowbox));
-  selected_lists = 0;
-  all_lists_removable = TRUE;
-
-  for (l = children; l != NULL; l = l->next)
-    {
-      GtdTaskList *list;
-
-      list = gtd_task_list_item_get_list (l->data);
-
-      if (gtd_task_list_item_get_selected (l->data))
-        {
-          selected_lists++;
-
-          if (!gtd_task_list_is_removable (list))
-            all_lists_removable = FALSE;
-        }
-    }
-
-  gtk_widget_set_sensitive (priv->remove_button, selected_lists > 0 && all_lists_removable);
-  gtk_widget_set_sensitive (priv->rename_button, selected_lists == 1);
-}
-
-static void
-gtd_window__select_button_toggled (GtkToggleButton *button,
-                                   GtdWindow       *window)
-{
-  gtd_window_set_mode (window, gtk_toggle_button_get_active (button) ? GTD_WINDOW_MODE_SELECTION : 
GTD_WINDOW_MODE_NORMAL);
-}
-
 static void
 gtd_window__cancel_selection_button_clicked (GtkWidget *button,
                                              GtdWindow *window)
 {
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (window->priv->select_button), FALSE);
+  gtd_window_set_mode (window, GTD_WINDOW_MODE_NORMAL);
 }
 
+/*
 static void
 gtd_window__create_new_list (GSimpleAction *simple,
                              GVariant      *parameter,
@@ -533,6 +300,7 @@ gtd_window__create_new_list (GSimpleAction *simple,
 
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->new_list_button), TRUE);
 }
+ */
 
 static void
 gtd_window__change_storage_action (GSimpleAction *simple,
@@ -549,113 +317,6 @@ gtd_window__change_storage_action (GSimpleAction *simple,
 }
 
 static void
-gtd_window__list_color_set (GtkColorChooser *button,
-                            gpointer         user_data)
-{
-  GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
-  GtdTaskList *list;
-  GdkRGBA new_color;
-
-  g_return_if_fail (GTD_IS_WINDOW (user_data));
-  g_return_if_fail (gtd_task_list_view_get_task_list (priv->list_view));
-
-  list = gtd_task_list_view_get_task_list (priv->list_view);
-
-  g_debug ("%s: %s: %s",
-           G_STRFUNC,
-           _("Setting new color for task list"),
-           gtd_task_list_get_name (list));
-
-  gtk_color_chooser_get_rgba (button, &new_color);
-  gtd_task_list_set_color (list, &new_color);
-
-  gtd_manager_save_task_list (priv->manager, list);
-}
-
-static gboolean
-gtd_window__on_key_press_event (GtkWidget    *widget,
-                                GdkEvent     *event,
-                                GtkSearchBar *bar)
-{
-  GtdWindowPrivate *priv;
-
-  g_return_val_if_fail (GTD_IS_WINDOW (widget), TRUE);
-
-  priv = GTD_WINDOW (widget)->priv;
-
-  if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (priv->main_stack)), "overview") == 0 &&
-      g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (priv->stack)), "lists") == 0)
-    {
-      return gtk_search_bar_handle_event (bar, event);
-    }
-
-  return FALSE;
-}
-
-static gint
-gtd_window__flowbox_sort_func (GtdTaskListItem *a,
-                               GtdTaskListItem *b,
-                               gpointer         user_data)
-{
-  GtdProvider *p1;
-  GtdProvider *p2;
-  GtdTaskList *l1;
-  GtdTaskList *l2;
-  gint retval = 0;
-
-  l1 = gtd_task_list_item_get_list (a);
-  p1 = gtd_task_list_get_provider (l1);
-
-  l2 = gtd_task_list_item_get_list (b);
-  p2 = gtd_task_list_get_provider (l2);
-
-  retval = g_strcmp0 (gtd_provider_get_description (p1), gtd_provider_get_description (p2));
-
-  if (retval != 0)
-    return retval;
-
-  return g_strcmp0 (gtd_task_list_get_name (l1), gtd_task_list_get_name (l2));
-}
-
-static gboolean
-gtd_window__flowbox_filter_func (GtdTaskListItem *item,
-                                 GtdWindow       *window)
-{
-  GtdWindowPrivate *priv;
-  GtdTaskList *list;
-  gboolean return_value;
-  gchar *search_folded;
-  gchar *list_name_folded;
-  gchar *haystack;
-
-  g_return_val_if_fail (GTD_IS_WINDOW (window), FALSE);
-
-  priv = window->priv;
-  list = gtd_task_list_item_get_list (item);
-  haystack = NULL;
-  search_folded = g_utf8_casefold (gtk_entry_get_text (GTK_ENTRY (priv->search_entry)), -1);
-  list_name_folded = g_utf8_casefold (gtd_task_list_get_name (list), -1);
-
-  if (!search_folded || search_folded[0] == '\0')
-    {
-      return_value = TRUE;
-      goto out;
-    }
-
-  haystack = g_strstr_len (list_name_folded,
-                           -1,
-                           search_folded);
-
-  return_value = (haystack != NULL);
-
-out:
-  g_free (search_folded);
-  g_free (list_name_folded);
-
-  return return_value;
-}
-
-static void
 gtd_window__manager_ready_changed (GObject    *source,
                                    GParamSpec *spec,
                                    gpointer    user_data)
@@ -675,117 +336,6 @@ gtd_window__manager_ready_changed (GObject    *source,
 }
 
 static void
-gtd_window__back_button_clicked (GtkButton *button,
-                                 gpointer   user_data)
-{
-  GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
-
-  g_return_if_fail (GTD_IS_WINDOW (user_data));
-
-  gtk_stack_set_visible_child_name (priv->main_stack, "overview");
-  gtk_header_bar_set_custom_title (priv->headerbar, GTK_WIDGET (priv->stack_switcher));
-  gtk_header_bar_set_title (priv->headerbar, _("To Do"));
-  gtk_widget_hide (GTK_WIDGET (priv->back_button));
-  gtk_widget_hide (GTK_WIDGET (priv->color_button));
-}
-
-static void
-gtd_window__list_selected (GtkFlowBox      *flowbox,
-                           GtdTaskListItem *item,
-                           gpointer         user_data)
-{
-  GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
-  GtdProvider *provider;
-  GtdTaskList *list;
-  GdkRGBA *list_color;
-
-  g_return_if_fail (GTD_IS_WINDOW (user_data));
-  g_return_if_fail (GTD_IS_TASK_LIST_ITEM (item));
-
-  switch (priv->mode)
-    {
-    case GTD_WINDOW_MODE_SELECTION:
-      gtd_task_list_item_set_selected (item, !gtd_task_list_item_get_selected (item));
-      update_action_bar_buttons (GTD_WINDOW (user_data));
-      break;
-
-    case GTD_WINDOW_MODE_NORMAL:
-      list = gtd_task_list_item_get_list (item);
-      provider = gtd_task_list_get_provider (list);
-      list_color = gtd_task_list_get_color (list);
-
-      g_signal_handlers_block_by_func (priv->color_button,
-                                       gtd_window__list_color_set,
-                                       user_data);
-
-      gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (priv->color_button), list_color);
-
-      gtk_stack_set_visible_child_name (priv->main_stack, "tasks");
-      gtk_header_bar_set_title (priv->headerbar, gtd_task_list_get_name (list));
-      gtk_header_bar_set_subtitle (priv->headerbar, gtd_provider_get_description (provider));
-      gtk_header_bar_set_custom_title (priv->headerbar, NULL);
-      gtk_search_bar_set_search_mode (priv->search_bar, FALSE);
-      gtd_task_list_view_set_task_list (priv->list_view, list);
-      gtd_task_list_view_set_show_completed (priv->list_view, FALSE);
-      gtk_widget_show (GTK_WIDGET (priv->back_button));
-      gtk_widget_show (GTK_WIDGET (priv->color_button));
-
-      g_signal_handlers_unblock_by_func (priv->color_button,
-                                         gtd_window__list_color_set,
-                                         user_data);
-
-      gdk_rgba_free (list_color);
-      break;
-
-    default:
-      g_assert_not_reached ();
-    }
-}
-
-static void
-gtd_window__list_added (GtdManager  *manager,
-                        GtdTaskList *list,
-                        gpointer     user_data)
-{
-  GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
-  GtkWidget *item;
-
-  item = gtd_task_list_item_new (list);
-
-  g_object_bind_property (user_data,
-                          "mode",
-                          item,
-                          "mode",
-                          G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
-
-  gtk_widget_show (item);
-
-  gtk_flow_box_insert (priv->lists_flowbox,
-                       item,
-                       -1);
-}
-
-static void
-gtd_window__list_removed (GtdManager  *manager,
-                          GtdTaskList *list,
-                          gpointer     user_data)
-{
-  GtdWindowPrivate *priv = GTD_WINDOW (user_data)->priv;
-  GList *children;
-  GList *l;
-
-  children = gtk_container_get_children (GTK_CONTAINER (priv->lists_flowbox));
-
-  for (l = children; l != NULL; l = l->next)
-    {
-      if (gtd_task_list_item_get_list (l->data) == list)
-        gtk_widget_destroy (l->data);
-    }
-
-  g_list_free (children);
-}
-
-static void
 gtd_window__show_error_message (GtdManager  *manager,
                                 const gchar *primary_text,
                                 const gchar *secondary_text,
@@ -880,27 +430,6 @@ gtd_window_constructed (GObject *object)
   app = GTK_APPLICATION (g_application_get_default ());
   menu = gtk_application_get_menu_by_id (app, "gear-menu");
   gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->gear_menu_button), G_MENU_MODEL (menu));
-
-  gtk_flow_box_set_sort_func (priv->lists_flowbox,
-                              (GtkFlowBoxSortFunc) gtd_window__flowbox_sort_func,
-                              NULL,
-                              NULL);
-
-  gtk_flow_box_set_filter_func (priv->lists_flowbox,
-                                (GtkFlowBoxFilterFunc) gtd_window__flowbox_filter_func,
-                                object,
-                                NULL);
-
-  g_object_bind_property (object,
-                          "manager",
-                          priv->new_list_popover,
-                          "manager",
-                          G_BINDING_DEFAULT);
-  g_object_bind_property (object,
-                          "manager",
-                          priv->provider_dialog,
-                          "manager",
-                          G_BINDING_DEFAULT);
 }
 
 GtkWidget*
@@ -961,14 +490,6 @@ gtd_window_set_property (GObject      *object,
                         G_CALLBACK (gtd_window__manager_ready_changed),
                         self);
       g_signal_connect (self->priv->manager,
-                        "list-added",
-                        G_CALLBACK (gtd_window__list_added),
-                        self);
-      g_signal_connect (self->priv->manager,
-                        "list-removed",
-                        G_CALLBACK (gtd_window__list_removed),
-                        self);
-      g_signal_connect (self->priv->manager,
                         "panel-added",
                         G_CALLBACK (gtd_window__panel_added),
                         self);
@@ -993,17 +514,6 @@ gtd_window_set_property (GObject      *object,
 
       g_list_free (lists);
 
-      /* Add already loaded lists */
-      lists = gtd_manager_get_task_lists (self->priv->manager);
-
-      for (l = lists; l != NULL; l = l->next)
-        {
-          gtd_window__list_added (self->priv->manager,
-                                  l->data,
-                                  object);
-        }
-
-      g_list_free (lists);
       g_object_notify (object, "manager");
       break;
 
@@ -1061,47 +571,22 @@ gtd_window_class_init (GtdWindowClass *klass)
 
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/todo/ui/window.ui");
 
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, action_bar);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, back_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, cancel_selection_button);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, color_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, gear_menu_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, headerbar);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, lists_flowbox);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, list_view);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, main_stack);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, new_list_button);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, new_list_popover);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, notification_widget);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, provider_dialog);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, remove_button);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, rename_button);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, rename_entry);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, rename_popover);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, save_rename_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, stack);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, search_bar);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, search_button);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, search_entry);
-  gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, select_button);
   gtk_widget_class_bind_template_child_private (widget_class, GtdWindow, stack_switcher);
 
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__back_button_clicked);
   gtk_widget_class_bind_template_callback (widget_class, gtd_window__cancel_selection_button_clicked);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__list_color_set);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__list_selected);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__on_key_press_event);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__remove_button_clicked);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__rename_button_clicked);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__rename_entry_text_changed);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__rename_task_list);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__select_button_toggled);
-  gtk_widget_class_bind_template_callback (widget_class, gtd_window__stack_visible_child_cb);
 }
 
 static void
 gtd_window_init (GtdWindow *self)
 {
+  GtkWidget *panel;
+
   self->priv = gtd_window_get_instance_private (self);
 
   self->priv->loading_notification = gtd_notification_new (_("Loading your task lists…"), 0);
@@ -1114,6 +599,19 @@ gtd_window_init (GtdWindow *self)
                                    self);
 
   gtk_widget_init_template (GTK_WIDGET (self));
+
+  /* Add the default 'Lists' panel before everything else */
+  panel = gtd_list_selector_panel_new ();
+
+  gtd_window__panel_added (gtd_manager_get_default (),
+                           GTD_PANEL (panel),
+                           self);
+
+  g_object_bind_property (self,
+                          "mode",
+                          panel,
+                          "mode",
+                          G_BINDING_BIDIRECTIONAL);
 }
 
 /**
@@ -1220,11 +718,7 @@ gtd_window_set_mode (GtdWindow     *window,
       context = gtk_widget_get_style_context (GTK_WIDGET (priv->headerbar));
       is_selection_mode = (mode == GTD_WINDOW_MODE_SELECTION);
 
-      gtk_widget_set_visible (priv->select_button, !is_selection_mode);
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->select_button), is_selection_mode);
       gtk_widget_set_visible (priv->cancel_selection_button, is_selection_mode);
-      gtk_widget_set_visible (GTK_WIDGET (priv->new_list_button), !is_selection_mode);
-      gtk_widget_set_visible (GTK_WIDGET (priv->action_bar), is_selection_mode);
       gtk_header_bar_set_show_close_button (priv->headerbar, !is_selection_mode);
       gtk_header_bar_set_subtitle (priv->headerbar, NULL);
 
@@ -1233,16 +727,9 @@ gtd_window_set_mode (GtdWindow     *window,
           gtk_style_context_add_class (context, "selection-mode");
           gtk_header_bar_set_custom_title (priv->headerbar, NULL);
           gtk_header_bar_set_title (priv->headerbar, _("Click a task list to select"));
-
-          update_action_bar_buttons (window);
         }
       else
         {
-          /* Unselect all items when leaving selection mode */
-          gtk_container_foreach (GTK_CONTAINER (priv->lists_flowbox),
-                                 (GtkCallback) gtd_task_list_item_set_selected,
-                                 FALSE);
-
           gtk_style_context_remove_class (context, "selection-mode");
           gtk_header_bar_set_custom_title (priv->headerbar, GTK_WIDGET (priv->stack_switcher));
           gtk_header_bar_set_title (priv->headerbar, _("To Do"));
diff --git a/src/views/gtd-list-selector-grid.c b/src/views/gtd-list-selector-grid.c
new file mode 100644
index 0000000..0a0f816
--- /dev/null
+++ b/src/views/gtd-list-selector-grid.c
@@ -0,0 +1,413 @@
+/* gtd-list-selector-grid.c
+ *
+ * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "interfaces/gtd-provider.h"
+#include "gtd-list-selector.h"
+#include "gtd-list-selector-grid.h"
+#include "gtd-manager.h"
+#include "gtd-task-list.h"
+#include "gtd-task-list-item.h"
+
+struct _GtdListSelectorGrid
+{
+  GtkFlowBox          parent;
+
+  gchar              *search_query;
+
+  GtdWindowMode       mode;
+};
+
+static void          gtd_list_selector_iface_init                (GtdListSelectorInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GtdListSelectorGrid, gtd_list_selector_grid, GTK_TYPE_FLOW_BOX,
+                        0,
+                        G_IMPLEMENT_INTERFACE (GTD_TYPE_LIST_SELECTOR,
+                                               gtd_list_selector_iface_init))
+
+enum {
+  PROP_0,
+  PROP_MODE,
+  PROP_SEARCH_QUERY,
+  N_PROPS
+};
+
+static void
+gtd_list_selector_grid_list_added (GtdManager          *manager,
+                                   GtdTaskList         *list,
+                                   GtdListSelectorGrid *selector)
+{
+  GtkWidget *item;
+
+  item = gtd_task_list_item_new (list);
+
+  g_object_bind_property (selector,
+                          "mode",
+                          item,
+                          "mode",
+                          G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
+  gtk_widget_show (item);
+
+  gtk_flow_box_insert (GTK_FLOW_BOX (selector),
+                       item,
+                       -1);
+}
+
+static void
+gtd_list_selector_grid_list_removed (GtdManager          *manager,
+                                     GtdTaskList         *list,
+                                     GtdListSelectorGrid *selector)
+{
+  GList *children;
+  GList *l;
+
+  children = gtk_container_get_children (GTK_CONTAINER (selector));
+
+  for (l = children; l != NULL; l = l->next)
+    {
+      if (gtd_task_list_item_get_list (l->data) == list)
+        gtk_widget_destroy (l->data);
+    }
+
+  g_list_free (children);
+}
+
+
+static gint
+gtd_list_selector_grid_sort_func (GtdTaskListItem     *a,
+                                  GtdTaskListItem     *b,
+                                  GtdListSelectorGrid *selector)
+{
+  GtdProvider *p1;
+  GtdProvider *p2;
+  GtdTaskList *l1;
+  GtdTaskList *l2;
+  gint retval = 0;
+
+  l1 = gtd_task_list_item_get_list (a);
+  p1 = gtd_task_list_get_provider (l1);
+
+  l2 = gtd_task_list_item_get_list (b);
+  p2 = gtd_task_list_get_provider (l2);
+
+  retval = g_strcmp0 (gtd_provider_get_description (p1), gtd_provider_get_description (p2));
+
+  if (retval != 0)
+    return retval;
+
+  return g_strcmp0 (gtd_task_list_get_name (l1), gtd_task_list_get_name (l2));
+}
+
+static gboolean
+gtd_list_selector_grid_filter_func (GtdTaskListItem     *item,
+                                    GtdListSelectorGrid *selector)
+{
+  GtdTaskList *list;
+  gboolean return_value;
+  gchar *search_folded;
+  gchar *list_name_folded;
+  gchar *haystack;
+
+  /*
+   * When no search query is set, we obviously don't
+   * filter out anything.
+   */
+  if (!selector->search_query)
+    return TRUE;
+
+  list = gtd_task_list_item_get_list (item);
+  haystack = NULL;
+  search_folded = g_utf8_casefold (selector->search_query, -1);
+  list_name_folded = g_utf8_casefold (gtd_task_list_get_name (list), -1);
+
+  if (!search_folded || search_folded[0] == '\0')
+    {
+      return_value = TRUE;
+      goto out;
+    }
+
+  haystack = g_strstr_len (list_name_folded,
+                           -1,
+                           search_folded);
+
+  return_value = (haystack != NULL);
+
+out:
+  g_free (search_folded);
+  g_free (list_name_folded);
+
+  return return_value;
+}
+
+/******************************
+ * GtdListSelector iface init *
+ ******************************/
+static GtdWindowMode
+gtd_list_selector_grid_get_mode (GtdListSelector *selector)
+{
+  g_return_val_if_fail (GTD_IS_LIST_SELECTOR_GRID (selector), GTD_WINDOW_MODE_NORMAL);
+
+  return GTD_LIST_SELECTOR_GRID (selector)->mode;
+}
+
+static void
+gtd_list_selector_grid_set_mode (GtdListSelector *selector,
+                                 GtdWindowMode    mode)
+{
+  GtdListSelectorGrid *self;
+
+  g_return_if_fail (GTD_IS_LIST_SELECTOR_GRID (selector));
+
+  self = GTD_LIST_SELECTOR_GRID (selector);
+
+  if (self->mode != mode)
+    {
+      self->mode = mode;
+
+      /* Unselect all items when leaving selection mode */
+      if (mode != GTD_WINDOW_MODE_SELECTION)
+        {
+          gtk_container_foreach (GTK_CONTAINER (self),
+                                 (GtkCallback) gtd_task_list_item_set_selected,
+                                 FALSE);
+        }
+
+
+      g_object_notify (G_OBJECT (self), "mode");
+    }
+}
+
+static const gchar*
+gtd_list_selector_grid_get_search_query (GtdListSelector *selector)
+{
+  g_return_val_if_fail (GTD_IS_LIST_SELECTOR_GRID (selector), NULL);
+
+  return GTD_LIST_SELECTOR_GRID (selector)->search_query;
+}
+
+static void
+gtd_list_selector_grid_set_search_query (GtdListSelector *selector,
+                                         const gchar     *search_query)
+{
+  GtdListSelectorGrid *self;
+
+  g_return_if_fail (GTD_IS_LIST_SELECTOR_GRID (selector));
+
+  self = GTD_LIST_SELECTOR_GRID (selector);
+
+  if (g_strcmp0 (self->search_query, search_query) != 0)
+    {
+      g_clear_pointer (&self->search_query, g_free);
+      self->search_query = g_strdup (search_query);
+
+      gtk_flow_box_invalidate_filter (GTK_FLOW_BOX (self));
+
+      g_object_notify (G_OBJECT (self), "search-query");
+    }
+}
+
+static GList*
+gtd_list_selector_grid_get_selected_lists (GtdListSelector *selector)
+{
+  GList *selected;
+  GList *children;
+  GList *l;
+
+  /* Retrieve the only selected task list */
+  children = gtk_container_get_children (GTK_CONTAINER (selector));
+  selected = NULL;
+
+  for (l = children; l != NULL; l = l->next)
+    {
+      if (gtd_task_list_item_get_selected (l->data))
+        selected = g_list_append (selected, l->data);
+    }
+
+  g_list_free (children);
+
+  return selected;
+}
+
+static void
+gtd_list_selector_iface_init (GtdListSelectorInterface *iface)
+{
+  iface->get_mode = gtd_list_selector_grid_get_mode;
+  iface->set_mode = gtd_list_selector_grid_set_mode;
+  iface->get_search_query = gtd_list_selector_grid_get_search_query;
+  iface->set_search_query = gtd_list_selector_grid_set_search_query;
+  iface->get_selected_lists = gtd_list_selector_grid_get_selected_lists;
+}
+
+static void
+gtd_list_selector_grid_finalize (GObject *object)
+{
+  GtdListSelectorGrid *self = (GtdListSelectorGrid *)object;
+
+  g_clear_pointer (&self->search_query, g_free);
+
+  G_OBJECT_CLASS (gtd_list_selector_grid_parent_class)->finalize (object);
+}
+
+static void
+gtd_list_selector_grid_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  GtdListSelectorGrid *self = GTD_LIST_SELECTOR_GRID (object);
+
+  switch (prop_id)
+    {
+    case PROP_MODE:
+      g_value_set_enum (value, self->mode);
+      break;
+
+    case PROP_SEARCH_QUERY:
+      g_value_set_string (value, self->search_query);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_list_selector_grid_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  GtdListSelector *self = GTD_LIST_SELECTOR (object);
+
+  switch (prop_id)
+    {
+    case PROP_MODE:
+      gtd_list_selector_set_mode (self, g_value_get_enum (value));
+      break;
+
+    case PROP_SEARCH_QUERY:
+      gtd_list_selector_set_search_query (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_list_selector_grid_child_activated (GtkFlowBox      *flowbox,
+                                        GtkFlowBoxChild *child)
+{
+  GtdTaskListItem *item;
+
+  if (!GTD_IS_TASK_LIST_ITEM (child))
+    return;
+
+  item = GTD_TASK_LIST_ITEM (child);
+
+  gtd_task_list_item_set_selected (item, !gtd_task_list_item_get_selected (item));
+
+  g_signal_emit_by_name (flowbox, "list-selected", gtd_task_list_item_get_list (item));
+}
+
+static void
+gtd_list_selector_grid_class_init (GtdListSelectorGridClass *klass)
+{
+  GtkFlowBoxClass *flowbox_class = GTK_FLOW_BOX_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  flowbox_class->child_activated = gtd_list_selector_grid_child_activated;
+
+  object_class->finalize = gtd_list_selector_grid_finalize;
+  object_class->get_property = gtd_list_selector_grid_get_property;
+  object_class->set_property = gtd_list_selector_grid_set_property;
+
+  g_object_class_override_property (object_class,
+                                    PROP_MODE,
+                                    "mode");
+
+  g_object_class_override_property (object_class,
+                                    PROP_SEARCH_QUERY,
+                                    "search-query");
+}
+
+static void
+gtd_list_selector_grid_init (GtdListSelectorGrid *self)
+{
+  GtdManager *manager;
+  GtkFlowBox *flowbox;
+  GtkWidget *widget;
+  GList *lists;
+  GList *l;
+
+  manager = gtd_manager_get_default ();
+
+  g_signal_connect (manager,
+                    "list-added",
+                    G_CALLBACK (gtd_list_selector_grid_list_added),
+                    self);
+  g_signal_connect (manager,
+                    "list-removed",
+                    G_CALLBACK (gtd_list_selector_grid_list_removed),
+                    self);
+
+  /* Add already loaded lists */
+  lists = gtd_manager_get_task_lists (manager);
+
+  for (l = lists; l != NULL; l = l->next)
+    {
+      gtd_list_selector_grid_list_added (manager,
+                                         l->data,
+                                         self);
+    }
+
+  g_list_free (lists);
+
+  /* Setup filter and sorting functions */
+  gtk_flow_box_set_sort_func (GTK_FLOW_BOX (self),
+                              (GtkFlowBoxSortFunc) gtd_list_selector_grid_sort_func,
+                              NULL,
+                              NULL);
+
+  gtk_flow_box_set_filter_func (GTK_FLOW_BOX (self),
+                                (GtkFlowBoxFilterFunc) gtd_list_selector_grid_filter_func,
+                                self,
+                                NULL);
+  /* Setup some properties */
+  widget = GTK_WIDGET (self);
+  flowbox = GTK_FLOW_BOX (self);
+
+  gtk_flow_box_set_max_children_per_line (flowbox, 100);
+  gtk_flow_box_set_selection_mode (flowbox, GTK_SELECTION_NONE);
+  gtk_flow_box_set_column_spacing (flowbox, 12);
+  gtk_flow_box_set_row_spacing (flowbox, 12);
+  gtk_flow_box_set_homogeneous (flowbox, TRUE);
+  gtk_container_set_border_width (GTK_CONTAINER (self), 12);
+  gtk_widget_set_hexpand (widget, TRUE);
+  gtk_widget_set_vexpand (widget, TRUE);
+  gtk_widget_set_halign (widget, GTK_ALIGN_START);
+  gtk_widget_set_valign (widget, GTK_ALIGN_START);
+  gtk_widget_show_all (widget);
+}
+
+GtkWidget*
+gtd_list_selector_grid_new (void)
+{
+  return g_object_new (GTD_TYPE_LIST_SELECTOR_GRID, NULL);
+}
+
diff --git a/src/views/gtd-list-selector-grid.h b/src/views/gtd-list-selector-grid.h
new file mode 100644
index 0000000..4488b55
--- /dev/null
+++ b/src/views/gtd-list-selector-grid.h
@@ -0,0 +1,36 @@
+/* gtd-list-selector-grid.h
+ *
+ * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_LIST_SELECTOR_GRID_H
+#define GTD_LIST_SELECTOR_GRID_H
+
+#include <glib-object.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_LIST_SELECTOR_GRID (gtd_list_selector_grid_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdListSelectorGrid, gtd_list_selector_grid, GTD, LIST_SELECTOR_GRID, GtkFlowBox)
+
+GtkWidget*           gtd_list_selector_grid_new                  (void);
+
+G_END_DECLS
+
+#endif /* GTD_LIST_SELECTOR_GRID_H */
diff --git a/src/views/gtd-list-selector-panel.c b/src/views/gtd-list-selector-panel.c
new file mode 100644
index 0000000..247f9e4
--- /dev/null
+++ b/src/views/gtd-list-selector-panel.c
@@ -0,0 +1,556 @@
+/* gtd-list-selector-panel.c
+ *
+ * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "interfaces/gtd-panel.h"
+#include "gtd-enum-types.h"
+#include "gtd-list-selector.h"
+#include "gtd-list-selector-grid.h"
+#include "gtd-list-selector-panel.h"
+#include "gtd-manager.h"
+#include "gtd-task-list.h"
+#include "gtd-task-list-item.h"
+#include "gtd-task-list-view.h"
+#include "gtd-window.h"
+
+#include <glib/gi18n.h>
+
+struct _GtdListSelectorPanel
+{
+  GtkBox              parent;
+
+  GtkWidget          *stack;
+  GtkWidget          *tasklist_view;
+
+  GtkWidget          *grid_selector;
+
+  /* Action bar widgets */
+  GtkWidget          *actionbar;
+  GtkWidget          *delete_button;
+  GtkWidget          *rename_button;
+
+  /* Header widgets */
+  GtkWidget          *back_button;
+  GtkWidget          *color_button;
+  GtkWidget          *new_list_button;
+  GtkWidget          *search_button;
+  GtkWidget          *selection_button;
+  GtkWidget          *view_button;
+
+  /* Rename widgets */
+  GtkWidget          *rename_entry;
+  GtkWidget          *rename_popover;
+  GtkWidget          *save_rename_button;
+
+  /* Search bar widgets */
+  GtkWidget          *search_bar;
+
+  GtdWindowMode       mode;
+};
+
+static void          gtd_panel_iface_init                        (GtdPanelInterface  *iface);
+
+G_DEFINE_TYPE_EXTENDED (GtdListSelectorPanel, gtd_list_selector_panel, GTK_TYPE_STACK,
+                        0,
+                        G_IMPLEMENT_INTERFACE (GTD_TYPE_PANEL,
+                                               gtd_panel_iface_init))
+
+enum {
+  PROP_0,
+  PROP_HEADER_WIDGETS,
+  PROP_MODE,
+  PROP_MENU,
+  PROP_NAME,
+  PROP_TITLE,
+  N_PROPS
+};
+
+
+static void
+gtd_list_selector_panel_select_button_toggled (GtkToggleButton      *button,
+                                               GtdListSelectorPanel *panel)
+{
+  GtdWindowMode mode;
+  GtdWindow *window;
+
+  window = GTD_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+  mode = gtk_toggle_button_get_active (button) ? GTD_WINDOW_MODE_SELECTION : GTD_WINDOW_MODE_NORMAL;
+
+  gtd_window_set_mode (window, mode);
+}
+
+
+static gboolean
+gtd_list_selector_panel_on_key_press_event (GtdListSelectorPanel *panel,
+                                            GdkEvent             *event,
+                                            GtkSearchBar         *bar)
+{
+  if (g_strcmp0 (gtk_stack_get_visible_child_name (GTK_STACK (panel)), "lists") == 0)
+    {
+      return gtk_search_bar_handle_event (bar, event);
+    }
+
+  return FALSE;
+}
+
+static void
+gtd_list_selector_panel_list_color_set (GtkColorChooser      *button,
+                                        GtdListSelectorPanel *panel)
+{
+  GtdTaskList *list;
+  GtdManager *manager;
+  GdkRGBA new_color;
+
+  manager = gtd_manager_get_default ();
+  list = gtd_task_list_view_get_task_list (GTD_TASK_LIST_VIEW (panel->tasklist_view));
+
+  g_debug ("%s: %s: %s",
+           G_STRFUNC,
+           _("Setting new color for task list"),
+           gtd_task_list_get_name (list));
+
+  gtk_color_chooser_get_rgba (button, &new_color);
+  gtd_task_list_set_color (list, &new_color);
+
+  gtd_manager_save_task_list (manager, list);
+}
+
+static void
+update_action_bar_buttons (GtdListSelectorPanel *panel)
+{
+  GList *selection;
+  GList *l;
+  gboolean all_lists_removable;
+  gint selected_lists;
+
+  selection = gtd_list_selector_get_selected_lists (GTD_LIST_SELECTOR (panel->grid_selector));
+  selected_lists = g_list_length (selection);
+  all_lists_removable = TRUE;
+
+  for (l = selection; l != NULL; l = l->next)
+    {
+      GtdTaskList *list;
+
+      list = gtd_task_list_item_get_list (l->data);
+
+      if (!gtd_task_list_is_removable (list))
+        {
+          all_lists_removable = FALSE;
+          break;
+        }
+    }
+
+  gtk_widget_set_sensitive (panel->delete_button, selected_lists > 0 && all_lists_removable);
+  gtk_widget_set_sensitive (panel->rename_button, selected_lists == 1);
+}
+
+static void
+gtd_list_selector_panel_list_selected (GtdListSelector      *selector,
+                                       GtdTaskList          *list,
+                                       GtdListSelectorPanel *panel)
+{
+  GtdWindow *window;
+  GdkRGBA *list_color;
+
+  window = GTD_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+
+  switch (gtd_window_get_mode (window))
+    {
+    case GTD_WINDOW_MODE_SELECTION:
+      update_action_bar_buttons (panel);
+      break;
+
+    case GTD_WINDOW_MODE_NORMAL:
+      list_color = gtd_task_list_get_color (list);
+
+      g_signal_handlers_block_by_func (panel->color_button,
+                                       gtd_list_selector_panel_list_color_set,
+                                       panel);
+
+      gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (panel->color_button), list_color);
+
+      gtk_stack_set_visible_child_name (GTK_STACK (panel), "tasks");
+      gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (panel->search_bar), FALSE);
+      gtd_task_list_view_set_task_list (GTD_TASK_LIST_VIEW (panel->tasklist_view), list);
+      gtd_task_list_view_set_show_completed (GTD_TASK_LIST_VIEW (panel->tasklist_view), FALSE);
+      gtk_widget_show (panel->back_button);
+      gtk_widget_show (panel->color_button);
+
+      g_signal_handlers_unblock_by_func (panel->color_button,
+                                         gtd_list_selector_panel_list_color_set,
+                                         panel);
+
+      gdk_rgba_free (list_color);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+gtd_list_selector_panel_back_button_clicked (GtkButton            *button,
+                                             GtdListSelectorPanel *panel)
+{
+  // TODO: add a way to set custom title on GtdWindow's headerbar
+  gtk_stack_set_visible_child_name (GTK_STACK (panel), "lists");
+  gtk_widget_hide (panel->back_button);
+  gtk_widget_hide (panel->color_button);
+}
+
+static void
+gtd_list_selector_panel_rename_entry_text_changed (GObject              *object,
+                                                   GParamSpec           *pspec,
+                                                   GtdListSelectorPanel *panel)
+{
+  gtk_widget_set_sensitive (panel->save_rename_button,
+                            gtk_entry_get_text_length (GTK_ENTRY (object)) > 0);
+}
+
+static void
+gtd_list_selector_panel_rename_task_list (GtdListSelectorPanel *panel)
+{
+  GList *selection;
+
+  /*
+   * If the save_rename_button is insensitive, the list name is
+   * empty and cannot be saved.
+   */
+  if (!gtk_widget_get_sensitive (panel->save_rename_button))
+    return;
+
+  selection = gtd_list_selector_get_selected_lists (GTD_LIST_SELECTOR (panel->grid_selector));
+
+  if (selection && selection->data)
+    {
+      GtdTaskListItem *item;
+      GtdTaskList *list;
+      GtdWindow *window;
+
+      item = selection->data;
+      list = gtd_task_list_item_get_list (item);
+      window = GTD_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+
+      gtd_task_list_set_name (list, gtk_entry_get_text (GTK_ENTRY (panel->rename_entry)));
+      gtd_window_set_mode (window, GTD_WINDOW_MODE_NORMAL);
+
+      gtk_widget_hide (panel->rename_popover);
+    }
+
+  g_list_free (selection);
+}
+
+static void
+gtd_list_selector_panel_rename_button_clicked (GtdListSelectorPanel *panel)
+{
+  GList *selection;
+
+  selection = gtd_list_selector_get_selected_lists (GTD_LIST_SELECTOR (panel->grid_selector));
+
+  if (selection && selection->data)
+    {
+      GtdTaskListItem *item;
+      GtdTaskList *list;
+
+      item = selection->data;
+      list = gtd_task_list_item_get_list (item);
+
+      gtk_popover_set_relative_to (GTK_POPOVER (panel->rename_popover), GTK_WIDGET (item));
+      gtk_entry_set_text (GTK_ENTRY (panel->rename_entry), gtd_task_list_get_name (list));
+      gtk_widget_show (panel->rename_popover);
+
+      gtk_widget_grab_focus (panel->rename_entry);
+    }
+
+  g_list_free (selection);
+}
+
+static void
+gtd_list_selector_panel_delete_button_clicked (GtdListSelectorPanel *panel)
+{
+  GtkWindow *toplevel;
+  GtkWidget *dialog;
+  GtkWidget *button;
+  GList *children;
+  GList *l;
+  gint response;
+
+  toplevel = GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (panel)));
+
+  dialog = gtk_message_dialog_new (toplevel,
+                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT | 
GTK_DIALOG_USE_HEADER_BAR,
+                                   GTK_MESSAGE_QUESTION,
+                                   GTK_BUTTONS_NONE,
+                                   _("Remove the selected task lists?"));
+
+  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+                                            _("Once removed, the task lists cannot be recovered."));
+
+  /* Focus the Cancel button by default */
+  gtk_dialog_add_button (GTK_DIALOG (dialog),
+                         _("Cancel"),
+                         GTK_RESPONSE_CANCEL);
+
+  button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
+  gtk_widget_grab_focus (button);
+
+  /* Make the Remove button visually destructive */
+  gtk_dialog_add_button (GTK_DIALOG (dialog),
+                         _("Remove task lists"),
+                         GTK_RESPONSE_ACCEPT);
+
+  button = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+  gtk_style_context_add_class (gtk_widget_get_style_context (button), "destructive-action");
+
+  response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+  /* Remove selected lists */
+  if (response == GTK_RESPONSE_ACCEPT)
+    {
+      children = gtd_list_selector_get_selected_lists (GTD_LIST_SELECTOR (panel->grid_selector));
+
+      for (l = children; l != NULL; l = l->next)
+        {
+          GtdTaskList *list;
+
+          list = gtd_task_list_item_get_list (l->data);
+
+          if (gtd_task_list_is_removable (list))
+            gtd_manager_remove_task_list (gtd_manager_get_default (), list);
+        }
+
+      g_list_free (children);
+    }
+
+  gtk_widget_destroy (dialog);
+
+  /* After removing the lists, exit SELECTION mode */
+  gtd_window_set_mode (GTD_WINDOW (toplevel), GTD_WINDOW_MODE_NORMAL);
+}
+
+/***********************
+ * GtdPanel iface init *
+ ***********************/
+static GList*
+gtd_list_selector_panel_get_header_widgets (GtdPanel *panel)
+{
+  GtdListSelectorPanel *self = GTD_LIST_SELECTOR_PANEL (panel);
+  GList *widgets;
+
+  widgets = g_list_append (NULL, self->search_button);
+  widgets = g_list_append (widgets, self->selection_button);
+  widgets = g_list_append (widgets, self->view_button);
+
+  return widgets;
+}
+
+static const GMenu*
+gtd_list_selector_panel_get_menu (GtdPanel *panel)
+{
+  /* TODO: add a menu for GtdListSelectorPanel */
+  return NULL;
+}
+
+static const gchar*
+gtd_list_selector_panel_get_name (GtdPanel *panel)
+{
+  return "panel-lists";
+}
+
+static const gchar*
+gtd_list_selector_panel_get_title (GtdPanel *panel)
+{
+  return _("Lists");
+}
+
+static void
+gtd_panel_iface_init (GtdPanelInterface *iface)
+{
+  iface->get_header_widgets = gtd_list_selector_panel_get_header_widgets;
+  iface->get_menu = gtd_list_selector_panel_get_menu;
+  iface->get_name = gtd_list_selector_panel_get_name;
+  iface->get_title = gtd_list_selector_panel_get_title;
+}
+
+static void
+gtd_list_selector_panel_get_property (GObject    *object,
+                                      guint       prop_id,
+                                      GValue     *value,
+                                      GParamSpec *pspec)
+{
+  GtdPanel *self = GTD_PANEL (object);
+
+  switch (prop_id)
+    {
+    case PROP_HEADER_WIDGETS:
+      g_value_set_pointer (value, gtd_list_selector_panel_get_header_widgets (self));
+      break;
+
+    case PROP_MODE:
+      g_value_set_enum (value, GTD_LIST_SELECTOR_PANEL (object)->mode);
+      break;
+
+    case PROP_MENU:
+      g_value_set_object (value, (GMenu*) gtd_list_selector_panel_get_menu (self));
+      break;
+
+    case PROP_NAME:
+      g_value_set_string (value, gtd_list_selector_panel_get_name (self));
+      break;
+
+    case PROP_TITLE:
+      g_value_set_string (value, gtd_list_selector_panel_get_title (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_list_selector_panel_set_mode (GtdListSelectorPanel *panel,
+                                  GtdWindowMode         mode)
+{
+  if (panel->mode != mode)
+    {
+      panel->mode = mode;
+
+      gtk_widget_set_visible (panel->actionbar, mode == GTD_WINDOW_MODE_SELECTION);
+
+      g_object_notify (G_OBJECT (panel), "mode");
+    }
+}
+
+static void
+gtd_list_selector_panel_set_property (GObject      *object,
+                                      guint         prop_id,
+                                      const GValue *value,
+                                      GParamSpec   *pspec)
+{
+  GtdListSelectorPanel *self = GTD_LIST_SELECTOR_PANEL (object);
+
+  switch (prop_id)
+    {
+    case PROP_MODE:
+      gtd_list_selector_panel_set_mode (self, g_value_get_enum (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gtd_list_selector_panel_class_init (GtdListSelectorPanelClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = gtd_list_selector_panel_get_property;
+  object_class->set_property = gtd_list_selector_panel_set_property;
+
+  g_object_class_override_property (object_class,
+                                    PROP_HEADER_WIDGETS,
+                                    "header-widgets");
+
+  g_object_class_override_property (object_class,
+                                    PROP_MENU,
+                                    "menu");
+
+  g_object_class_override_property (object_class,
+                                    PROP_NAME,
+                                    "name");
+
+  g_object_class_override_property (object_class,
+                                    PROP_TITLE,
+                                    "title");
+
+  /**
+   * GtdListSelectorPanel::mode:
+   *
+   * This is a utility property so we can chain the "mode"
+   * property all the way up/down from window to the list
+   * items.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_MODE,
+                                   g_param_spec_enum ("mode",
+                                                      "Mode of the selector",
+                                                      "The mode of the selector",
+                                                      GTD_TYPE_WINDOW_MODE,
+                                                      GTD_WINDOW_MODE_NORMAL,
+                                                      G_PARAM_READWRITE));
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/todo/ui/list-selector-panel.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, actionbar);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, back_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, color_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, delete_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, new_list_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, rename_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, rename_entry);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, rename_popover);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, save_rename_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, search_bar);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, search_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, selection_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, stack);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, tasklist_view);
+  gtk_widget_class_bind_template_child (widget_class, GtdListSelectorPanel, view_button);
+
+  gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_back_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_delete_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_list_color_set);
+  gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_on_key_press_event);
+  gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_rename_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_rename_entry_text_changed);
+  gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_rename_task_list);
+  gtk_widget_class_bind_template_callback (widget_class, gtd_list_selector_panel_select_button_toggled);
+}
+
+static void
+gtd_list_selector_panel_init (GtdListSelectorPanel *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  /* Grid selector */
+  self->grid_selector = gtd_list_selector_grid_new ();
+
+  g_object_bind_property (self,
+                          "mode",
+                          self->grid_selector,
+                          "mode",
+                          G_BINDING_BIDIRECTIONAL);
+
+  g_signal_connect (self->grid_selector,
+                    "list-selected",
+                    G_CALLBACK (gtd_list_selector_panel_list_selected),
+                    self);
+
+  gtk_stack_add_titled (GTK_STACK (self->stack),
+                        self->grid_selector,
+                        "grid",
+                        "Grid");
+}
+
+GtkWidget*
+gtd_list_selector_panel_new (void)
+{
+  return g_object_new (GTD_TYPE_LIST_SELECTOR_PANEL, NULL);
+}
+
diff --git a/src/views/gtd-list-selector-panel.h b/src/views/gtd-list-selector-panel.h
new file mode 100644
index 0000000..7bbe413
--- /dev/null
+++ b/src/views/gtd-list-selector-panel.h
@@ -0,0 +1,36 @@
+/* gtd-list-selector-panel.h
+ *
+ * Copyright (C) 2015 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_LIST_SELECTOR_PANEL_H
+#define GTD_LIST_SELECTOR_PANEL_H
+
+#include <glib-object.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_LIST_SELECTOR_PANEL (gtd_list_selector_panel_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdListSelectorPanel, gtd_list_selector_panel, GTD, LIST_SELECTOR_PANEL, GtkStack)
+
+GtkWidget*           gtd_list_selector_panel_new                 (void);
+
+G_END_DECLS
+
+#endif /* GTD_LIST_SELECTOR_PANEL_H */



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