[geary] Use Popover for Move/Label menu. Bug 767431.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary] Use Popover for Move/Label menu. Bug 767431.
- Date: Mon, 20 Jun 2016 05:27:56 +0000 (UTC)
commit 7e446b1580a76e5c9a962dd32a168fcbd493348f
Author: Niels De Graef <nielsdegraef gmail com>
Date: Mon Jun 20 05:43:07 2016 +0200
Use Popover for Move/Label menu. Bug 767431.
Signed-off-by: Niels De Graef <nielsdegraef gmail com>
src/CMakeLists.txt | 2 +-
src/client/components/folder-menu.vala | 74 ----------------
src/client/components/folder-popover.vala | 131 +++++++++++++++++++++++++++++
src/client/components/main-toolbar.vala | 8 +-
src/client/components/pill-toolbar.vala | 21 +++++
ui/CMakeLists.txt | 1 +
ui/folder-popover.ui | 62 ++++++++++++++
ui/geary.css | 10 ++
8 files changed, 230 insertions(+), 79 deletions(-)
---
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ad1b34f..5335e9e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -332,7 +332,7 @@ client/accounts/login-dialog.vala
client/components/conversation-find-bar.vala
client/components/count-badge.vala
-client/components/folder-menu.vala
+client/components/folder-popover.vala
client/components/icon-factory.vala
client/components/main-toolbar.vala
client/components/main-window.vala
diff --git a/src/client/components/folder-popover.vala b/src/client/components/folder-popover.vala
new file mode 100644
index 0000000..9b377c8
--- /dev/null
+++ b/src/client/components/folder-popover.vala
@@ -0,0 +1,131 @@
+/* Copyright 2016 Software Freedom Conservancy Inc.
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+[GtkTemplate (ui = "/org/gnome/Geary/folder-popover.ui")]
+public class FolderPopover : Gtk.Popover {
+
+ [GtkChild]
+ private Gtk.SearchEntry search_entry;
+ [GtkChild]
+ private Gtk.ListBox list_box;
+
+ private int filtered_folder_count = 0;
+
+ public signal void folder_selected(Geary.Folder folder);
+
+ public FolderPopover() {
+ list_box.set_filter_func(row_filter);
+ list_box.set_sort_func(row_sort);
+ this.show.connect(() => search_entry.grab_focus());
+ this.hide.connect(() => {
+ search_entry.set_text("");
+ invalidate_filter();
+ });
+ }
+
+ public bool has_folder(Geary.Folder folder) {
+ return get_row_with_folder(folder) != null;
+ }
+
+ public void add_folder(Geary.Folder folder) {
+ // don't allow multiples and don't allow folders that can't be opened (that means they
+ // support almost no operations and have no content)
+ if (has_folder(folder) || folder.properties.is_openable.is_impossible())
+ return;
+
+ // also don't allow local-only or virtual folders, which also have a limited set of
+ // operations
+ if (folder.properties.is_local_only || folder.properties.is_virtual)
+ return;
+
+ list_box.add(build_row(folder));
+ list_box.invalidate_sort();
+ }
+
+ public void enable_disable_folder(Geary.Folder folder, bool sensitive) {
+ Gtk.ListBoxRow row = get_row_with_folder(folder);
+ if (row != null)
+ row.sensitive = sensitive;
+ }
+
+ public void remove_folder(Geary.Folder folder) {
+ Gtk.ListBoxRow row = get_row_with_folder(folder);
+ if (row != null)
+ list_box.remove(row);
+ }
+
+ public Gtk.ListBoxRow? get_row_with_folder(Geary.Folder folder) {
+ Gtk.ListBoxRow result = null;
+ list_box.foreach((row) => {
+ if (row.get_data<Geary.Folder>("folder") == folder)
+ result = row as Gtk.ListBoxRow;
+ });
+ return result;
+ }
+
+ public void clear() {
+ list_box.foreach((row) => list_box.remove(row));
+ }
+
+ private Gtk.ListBoxRow build_row(Geary.Folder folder) {
+ Gtk.ListBoxRow row = new Gtk.ListBoxRow();
+ row.get_style_context().add_class("geary-folder-popover-list-row");
+ row.set_data("folder", folder);
+
+ Gtk.Label label = new Gtk.Label(folder.path.to_string());
+ label.set_halign(Gtk.Align.START);
+ row.add(label);
+
+ return row;
+ }
+
+ [GtkCallback]
+ private void on_row_activated(Gtk.ListBoxRow? row) {
+ if (row != null) {
+ Geary.Folder folder = row.get_data<Geary.Folder>("folder");
+ folder_selected(folder);
+ }
+
+ this.hide();
+ }
+
+ [GtkCallback]
+ private void on_search_entry_activate() {
+ if (filtered_folder_count == 1) {
+ // Don't use get_row_at_index(0), or you will get the first row of the unfiltered list.
+ Gtk.ListBoxRow? row = list_box.get_row_at_y(0);
+ if (row != null)
+ on_row_activated(row);
+ } else if (filtered_folder_count > 0) {
+ list_box.get_row_at_y(0).grab_focus();
+ }
+ }
+
+ [GtkCallback]
+ private void on_search_entry_search_changed() {
+ invalidate_filter();
+ }
+
+ private void invalidate_filter() {
+ filtered_folder_count = 0;
+ list_box.invalidate_filter();
+ }
+
+ private bool row_filter(Gtk.ListBoxRow row) {
+ Gtk.Label label = row.get_child() as Gtk.Label;
+ if (label.label.down().contains(search_entry.text.down())) {
+ filtered_folder_count++;
+ return true;
+ }
+ return false;
+ }
+
+ private int row_sort(Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) {
+ Geary.Folder folder1 = row1.get_data<Geary.Folder>("folder");
+ Geary.Folder folder2 = row2.get_data<Geary.Folder>("folder");
+ return folder1.path.compare_to(folder2.path);
+ }
+}
diff --git a/src/client/components/main-toolbar.vala b/src/client/components/main-toolbar.vala
index 01eb8c4..0827a6e 100644
--- a/src/client/components/main-toolbar.vala
+++ b/src/client/components/main-toolbar.vala
@@ -6,8 +6,8 @@
// Draws the main toolbar.
public class MainToolbar : Gtk.Box {
- public FolderMenu copy_folder_menu { get; private set; default = new FolderMenu(); }
- public FolderMenu move_folder_menu { get; private set; default = new FolderMenu(); }
+ public FolderPopover copy_folder_menu { get; private set; default = new FolderPopover(); }
+ public FolderPopover move_folder_menu { get; private set; default = new FolderPopover(); }
public string account { get; set; }
public string folder { get; set; }
public bool show_close_button { get; set; default = false; }
@@ -103,9 +103,9 @@ public class MainToolbar : Gtk.Box {
insert.clear();
insert.add(conversation_header.create_menu_button("marker-symbolic", mark_menu,
GearyController.ACTION_MARK_AS_MENU));
- insert.add(conversation_header.create_menu_button(rtl ? "tag-rtl-symbolic" : "tag-symbolic",
+ insert.add(conversation_header.create_popover_button(rtl ? "tag-rtl-symbolic" : "tag-symbolic",
copy_folder_menu, GearyController.ACTION_COPY_MENU));
- insert.add(conversation_header.create_menu_button("folder-symbolic", move_folder_menu,
+ insert.add(conversation_header.create_popover_button("folder-symbolic", move_folder_menu,
GearyController.ACTION_MOVE_MENU));
conversation_header.add_start(conversation_header.create_pill_buttons(insert));
diff --git a/src/client/components/pill-toolbar.vala b/src/client/components/pill-toolbar.vala
index 79f4b50..78d911b 100644
--- a/src/client/components/pill-toolbar.vala
+++ b/src/client/components/pill-toolbar.vala
@@ -103,6 +103,27 @@ public interface PillBar : Gtk.Container {
}
/**
+ * Given an icon, popover, and action, creates a button that triggers the popover and the action.
+ */
+ public virtual Gtk.MenuButton create_popover_button(string? icon_name, Gtk.Popover? popover, string
action_name) {
+ Gtk.MenuButton b = new Gtk.MenuButton();
+ setup_button(b, icon_name, action_name);
+ b.set_popover(popover);
+ b.clicked.connect(() => popover.show_all());
+
+ if (b.related_action != null) {
+ b.related_action.activate.connect(() => {
+ b.clicked();
+ });
+ // Null out the action since by connecting it to clicked
+ // above, invoking would cause an infinite loop otherwise.
+ b.related_action = null;
+ }
+
+ return b;
+ }
+
+ /**
* Given a list of buttons, creates a "pill-style" tool item that can be appended to this
* toolbar. Optionally adds spacers "before" and "after" the buttons (those terms depending
* on Gtk.TextDirection)
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index 9841d61..20efd37 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -10,6 +10,7 @@ set(RESOURCE_LIST
STRIPBLANKS "composer_accelerators.ui"
STRIPBLANKS "edit_alternate_emails.glade"
STRIPBLANKS "find_bar.glade"
+ STRIPBLANKS "folder-popover.ui"
STRIPBLANKS "login.glade"
STRIPBLANKS "password-dialog.glade"
STRIPBLANKS "preferences.glade"
diff --git a/ui/folder-popover.ui b/ui/folder-popover.ui
new file mode 100644
index 0000000..06a0f98
--- /dev/null
+++ b/ui/folder-popover.ui
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.14"/>
+ <template class="FolderPopover" parent="GtkPopover">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="container">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkSearchEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="primary_icon_name">edit-find-symbolic</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">False</property>
+ <signal name="activate" handler="on_search_entry_activate" swapped="no"/>
+ <signal name="search_changed" handler="on_search_entry_search_changed" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolled">
+ <property name="min_content_width">200</property>
+ <property name="min_content_height">320</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <property name="hscrollbar_policy">never</property>
+ <child>
+ <object class="GtkListBox" id="list_box">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activate_on_single_click">True</property>
+ <signal name="row_activated" handler="on_row_activated" swapped="no"/>
+ <style>
+ <class name="geary-folder-popover-list"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/ui/geary.css b/ui/geary.css
index 88a8e8c..10a0085 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -45,3 +45,13 @@ GtkBox.vertical GtkHeaderBar {
.geary-titlebar-left:dir(rtl) {
border-top-left-radius: 0px;
}
+
+row.geary-folder-popover-list-row {
+ padding: 6px;
+ border-color: @borders;
+ border-style: groove;
+ border-bottom-width: 1px;
+}
+row.geary-folder-popover-list-row > label {
+ color: @theme_text_color;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]