summaryrefslogtreecommitdiff
path: root/src/sidebar
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2015-04-03 13:14:53 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2015-04-03 13:14:53 +0200
commitc43dfb815a4951b8248f4f0e98babe4f80204f03 (patch)
tree82745ed2353757c41ea1865bad9ac7a1b0a8a366 /src/sidebar
parent2785a691b958a79a1dd606c445188c71c3f58b3c (diff)
Imported Upstream version 0.22.0upstream/0.22.0
Diffstat (limited to 'src/sidebar')
-rw-r--r--src/sidebar/Branch.vala64
-rw-r--r--src/sidebar/Entry.vala21
-rw-r--r--src/sidebar/Sidebar.vala2
-rw-r--r--src/sidebar/Tree.vala295
-rw-r--r--src/sidebar/common.vala59
5 files changed, 245 insertions, 196 deletions
diff --git a/src/sidebar/Branch.vala b/src/sidebar/Branch.vala
index 23badda..a6c3ee8 100644
--- a/src/sidebar/Branch.vala
+++ b/src/sidebar/Branch.vala
@@ -1,4 +1,4 @@
-/* Copyright 2011-2014 Yorba Foundation
+/* Copyright 2011-2015 Yorba Foundation
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
@@ -39,23 +39,22 @@ public class Sidebar.Branch : Object {
public Sidebar.Entry entry;
public weak Node? parent;
- public CompareDataFunc<Sidebar.Entry> comparator;
+ public CompareFunc<Sidebar.Entry> comparator;
public Gee.SortedSet<Node>? children = null;
- public Node(Sidebar.Entry entry, Node? parent,
- owned CompareDataFunc<Sidebar.Entry> comparator) {
+ public Node(Sidebar.Entry entry, Node? parent, CompareFunc<Sidebar.Entry> comparator) {
this.entry = entry;
this.parent = parent;
- this.comparator = (owned) comparator;
+ this.comparator = comparator;
}
- private static int comparator_wrapper(Node? a, Node? b) {
- if (a == b)
+ private static int comparator_wrapper(Node anode, Node bnode) {
+ if (anode == bnode)
return 0;
- assert(a.parent == b.parent);
+ assert(anode.parent == bnode.parent);
- return a.parent.comparator(a.entry, b.entry);
+ return anode.parent.comparator(anode.entry, bnode.entry);
}
public bool has_children() {
@@ -172,16 +171,16 @@ public class Sidebar.Branch : Object {
cb(this);
}
- public void change_comparator(owned CompareDataFunc<Sidebar.Entry> comparator, bool recursive,
+ public void change_comparator(CompareFunc<Sidebar.Entry> comparator, bool recursive,
ChildrenReorderedCallback cb) {
- this.comparator = (owned) comparator;
+ this.comparator = comparator;
// reorder children, but need to do manual recursion to set comparator
reorder_children(false, cb);
if (recursive) {
foreach (Node child in children)
- child.change_comparator((owned) comparator, true, cb);
+ child.change_comparator(comparator, true, cb);
}
}
}
@@ -189,7 +188,7 @@ public class Sidebar.Branch : Object {
private Node root;
private Options options;
private bool shown = true;
- private CompareDataFunc<Sidebar.Entry> default_comparator;
+ private CompareFunc<Sidebar.Entry> default_comparator;
private Gee.HashMap<Sidebar.Entry, Node> map = new Gee.HashMap<Sidebar.Entry, Node>();
public signal void entry_added(Sidebar.Entry entry);
@@ -204,19 +203,11 @@ public class Sidebar.Branch : Object {
public signal void show_branch(bool show);
- public Branch(Sidebar.Entry root, Options options,
- owned CompareDataFunc<Sidebar.Entry> default_comparator,
- owned CompareDataFunc<Sidebar.Entry>? root_comparator = null) {
- this.default_comparator = (owned) default_comparator;
-
- CompareDataFunc<Sidebar.Entry>? broken_ternary_workaround;
-
- if (root_comparator != null)
- broken_ternary_workaround = (owned) root_comparator;
- else
- broken_ternary_workaround = (owned) default_comparator;
-
- this.root = new Node(root, null, (owned) broken_ternary_workaround);
+ public Branch(Sidebar.Entry root, Options options, CompareFunc<Sidebar.Entry> default_comparator,
+ CompareFunc<Sidebar.Entry>? root_comparator = null) {
+ this.default_comparator = default_comparator;
+ this.root = new Node(root, null,
+ (root_comparator != null) ? root_comparator : default_comparator);
this.options = options;
map.set(root, this.root);
@@ -254,7 +245,7 @@ public class Sidebar.Branch : Object {
}
public void graft(Sidebar.Entry parent, Sidebar.Entry entry,
- owned CompareDataFunc<Sidebar.Entry>? comparator = null) {
+ CompareFunc<Sidebar.Entry>? comparator = null) {
assert(map.has_key(parent));
assert(!map.has_key(entry));
@@ -262,15 +253,8 @@ public class Sidebar.Branch : Object {
set_show_branch(true);
Node parent_node = map.get(parent);
-
- CompareDataFunc<Sidebar.Entry>? broken_ternary_workaround;
-
- if (comparator != null)
- broken_ternary_workaround = (owned) comparator;
- else
- broken_ternary_workaround = (owned) default_comparator;
-
- Node entry_node = new Node(entry, parent_node, (owned) broken_ternary_workaround);
+ Node entry_node = new Node(entry, parent_node,
+ (comparator != null) ? comparator : default_comparator);
parent_node.add_child(entry_node);
map.set(entry, entry_node);
@@ -347,16 +331,16 @@ public class Sidebar.Branch : Object {
entry_node.reorder_children(recursive, children_reordered_callback);
}
- public void change_all_comparators(owned CompareDataFunc<Sidebar.Entry>? comparator) {
- root.change_comparator((owned) comparator, true, children_reordered_callback);
+ public void change_all_comparators(CompareFunc<Sidebar.Entry>? comparator) {
+ root.change_comparator(comparator, true, children_reordered_callback);
}
public void change_comparator(Sidebar.Entry entry, bool recursive,
- owned CompareDataFunc<Sidebar.Entry>? comparator) {
+ CompareFunc<Sidebar.Entry>? comparator) {
Node? entry_node = map.get(entry);
assert(entry_node != null);
- entry_node.change_comparator((owned) comparator, recursive, children_reordered_callback);
+ entry_node.change_comparator(comparator, recursive, children_reordered_callback);
}
public int get_child_count(Sidebar.Entry parent) {
diff --git a/src/sidebar/Entry.vala b/src/sidebar/Entry.vala
index 4162f21..5a84f74 100644
--- a/src/sidebar/Entry.vala
+++ b/src/sidebar/Entry.vala
@@ -1,4 +1,4 @@
-/* Copyright 2011-2014 Yorba Foundation
+/* Copyright 2011-2015 Yorba Foundation
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
@@ -7,13 +7,13 @@
public interface Sidebar.Entry : Object {
public signal void sidebar_tooltip_changed(string? tooltip);
- public signal void sidebar_icon_changed(Icon? icon);
+ public signal void sidebar_icon_changed(string? icon);
public abstract string get_sidebar_name();
public abstract string? get_sidebar_tooltip();
- public abstract Icon? get_sidebar_icon();
+ public abstract string? get_sidebar_icon();
public abstract string to_string();
@@ -25,12 +25,6 @@ public interface Sidebar.Entry : Object {
}
public interface Sidebar.ExpandableEntry : Sidebar.Entry {
- public signal void sidebar_open_closed_icons_changed(Icon? open, Icon? closed);
-
- public abstract Icon? get_sidebar_open_icon();
-
- public abstract Icon? get_sidebar_closed_icon();
-
public abstract bool expand_on_select();
}
@@ -53,6 +47,15 @@ public interface Sidebar.RenameableEntry : Sidebar.Entry {
public signal void sidebar_name_changed(string name);
public abstract void rename(string new_name);
+
+ // Return true to allow the user to rename the sidebar entry in the UI.
+ public abstract bool is_user_renameable();
+}
+
+public interface Sidebar.EmphasizableEntry : Sidebar.Entry {
+ public signal void is_emphasized_changed(bool emphasized);
+
+ public abstract bool is_emphasized();
}
public interface Sidebar.DestroyableEntry : Sidebar.Entry {
diff --git a/src/sidebar/Sidebar.vala b/src/sidebar/Sidebar.vala
index 8f6904b..0b4c0da 100644
--- a/src/sidebar/Sidebar.vala
+++ b/src/sidebar/Sidebar.vala
@@ -1,4 +1,4 @@
-/* Copyright 2011-2014 Yorba Foundation
+/* Copyright 2011-2015 Yorba Foundation
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
diff --git a/src/sidebar/Tree.vala b/src/sidebar/Tree.vala
index 37da7e0..a020b18 100644
--- a/src/sidebar/Tree.vala
+++ b/src/sidebar/Tree.vala
@@ -1,4 +1,4 @@
-/* Copyright 2011-2014 Yorba Foundation
+/* Copyright 2011-2015 Yorba Foundation
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
@@ -37,8 +37,7 @@ public class Sidebar.Tree : Gtk.TreeView {
private class RootWrapper : EntryWrapper {
public int root_position;
- public RootWrapper(Gtk.TreeModel model, Sidebar.Entry entry, Gtk.TreePath path, int root_position)
- requires (root_position >= 0) {
+ public RootWrapper(Gtk.TreeModel model, Sidebar.Entry entry, Gtk.TreePath path, int root_position) {
base (model, entry, path);
this.root_position = root_position;
@@ -49,9 +48,7 @@ public class Sidebar.Tree : Gtk.TreeView {
NAME,
TOOLTIP,
WRAPPER,
- PIXBUF,
- CLOSED_PIXBUF,
- OPEN_PIXBUF,
+ ICON,
N_COLUMNS
}
@@ -59,17 +56,13 @@ public class Sidebar.Tree : Gtk.TreeView {
typeof (string), // NAME
typeof (string?), // TOOLTIP
typeof (EntryWrapper), // WRAPPER
- typeof (Gdk.Pixbuf?), // PIXBUF
- typeof (Gdk.Pixbuf?), // CLOSED_PIXBUF
- typeof (Gdk.Pixbuf?) // OPEN_PIXBUF
+ typeof (string?) // ICON
);
private Gtk.UIManager ui = new Gtk.UIManager();
- private Gtk.IconTheme icon_theme;
private Gtk.CellRendererText text_renderer;
private unowned ExternalDropHandler drop_handler;
private Gtk.Entry? text_entry = null;
- private Gee.HashMap<string, Gdk.Pixbuf> icon_cache = new Gee.HashMap<string, Gdk.Pixbuf>();
private Gee.HashMap<Sidebar.Entry, EntryWrapper> entry_map =
new Gee.HashMap<Sidebar.Entry, EntryWrapper>();
private Gee.HashMap<Sidebar.Branch, int> branches = new Gee.HashMap<Sidebar.Branch, int>();
@@ -77,8 +70,11 @@ public class Sidebar.Tree : Gtk.TreeView {
private bool mask_entry_selected_signal = false;
private weak EntryWrapper? selected_wrapper = null;
private Gtk.Menu? default_context_menu = null;
+ private bool expander_called_manually = false;
+ private int expander_special_count = 0;
private bool is_internal_drag_in_progress = false;
private Sidebar.Entry? internal_drag_source_entry = null;
+ private Gtk.TreeRowReference? old_path_ref = null;
public signal void entry_selected(Sidebar.SelectableEntry selectable);
@@ -97,15 +93,17 @@ public class Sidebar.Tree : Gtk.TreeView {
public Tree(Gtk.TargetEntry[] target_entries, Gdk.DragAction actions,
ExternalDropHandler drop_handler) {
set_model(store);
+ get_style_context().add_class("sidebar");
Gtk.TreeViewColumn text_column = new Gtk.TreeViewColumn();
- text_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED);
+ text_column.set_expand(true);
Gtk.CellRendererPixbuf icon_renderer = new Gtk.CellRendererPixbuf();
+ icon_renderer.follow_state = true;
text_column.pack_start(icon_renderer, false);
- text_column.add_attribute(icon_renderer, "pixbuf", Columns.PIXBUF);
- text_column.add_attribute(icon_renderer, "pixbuf_expander_closed", Columns.CLOSED_PIXBUF);
- text_column.add_attribute(icon_renderer, "pixbuf_expander_open", Columns.OPEN_PIXBUF);
+ text_column.add_attribute(icon_renderer, "icon_name", Columns.ICON);
+ text_column.set_cell_data_func(icon_renderer, icon_renderer_function);
text_renderer = new Gtk.CellRendererText();
+ text_renderer.ellipsize = Pango.EllipsizeMode.END;
text_renderer.editing_canceled.connect(on_editing_canceled);
text_renderer.editing_started.connect(on_editing_started);
text_column.pack_start(text_renderer, true);
@@ -131,6 +129,9 @@ public class Sidebar.Tree : Gtk.TreeView {
selection.set_mode(Gtk.SelectionMode.BROWSE);
selection.set_select_function(on_selection);
+ test_expand_row.connect(on_toggle_row);
+ test_collapse_row.connect(on_toggle_row);
+
// It Would Be Nice if the target entries and actions were gleaned by querying each
// Sidebar.Entry as it was added, but that's a tad too complicated for our needs
// currently
@@ -145,9 +146,6 @@ public class Sidebar.Tree : Gtk.TreeView {
popup_menu.connect(on_context_menu_keypress);
- icon_theme = Resources.get_icon_theme_engine();
- icon_theme.changed.connect(on_theme_change);
-
setup_default_context_menu();
drag_begin.connect(on_drag_begin);
@@ -158,7 +156,14 @@ public class Sidebar.Tree : Gtk.TreeView {
~Tree() {
text_renderer.editing_canceled.disconnect(on_editing_canceled);
text_renderer.editing_started.disconnect(on_editing_started);
- icon_theme.changed.disconnect(on_theme_change);
+ }
+
+ public void icon_renderer_function(Gtk.CellLayout layout, Gtk.CellRenderer renderer, Gtk.TreeModel model, Gtk.TreeIter iter) {
+ EntryWrapper? wrapper = get_wrapper_at_iter(iter);
+ if (wrapper == null) {
+ return;
+ }
+ renderer.visible = !(wrapper.entry is Sidebar.Header);
}
private void on_drag_begin(Gdk.DragContext ctx) {
@@ -270,41 +275,72 @@ public class Sidebar.Tree : Gtk.TreeView {
public bool is_selected(Sidebar.Entry entry) {
EntryWrapper? wrapper = get_wrapper(entry);
- return (wrapper != null) ? get_selection().path_is_selected(wrapper.get_path()) : false;
+ // Even though get_selection() does not report its return type as nullable, it can be null
+ // if the window has been destroyed.
+ Gtk.TreeSelection selection = get_selection();
+ if (selection == null)
+ return false;
+
+ return (wrapper != null) ? selection.path_is_selected(wrapper.get_path()) : false;
}
public bool is_any_selected() {
return get_selection().count_selected_rows() != 0;
}
-
+
private Gtk.TreePath? get_selected_path() {
Gtk.TreeModel model;
- GLib.List<Gtk.TreePath> rows = get_selection().get_selected_rows(out model);
+ Gtk.TreeSelection? selection = get_selection();
+ if (selection == null){
+ return null;
+ }
+ GLib.List<Gtk.TreePath> rows = selection.get_selected_rows(out model);
assert(rows.length() == 0 || rows.length() == 1);
-
+
return rows.length() != 0 ? rows.nth_data(0) : null;
}
+
+ private string get_name_for_entry(Sidebar.Entry entry) {
+ string name = guarded_markup_escape_text(entry.get_sidebar_name());
+
+ Sidebar.EmphasizableEntry? emphasizable_entry = entry as Sidebar.EmphasizableEntry;
+ if (emphasizable_entry != null && emphasizable_entry.is_emphasized())
+ name = "<b>%s</b>".printf(name);
+
+ return name;
+ }
+
+ public virtual bool accept_cursor_changed() {
+ return true;
+ }
public override void cursor_changed() {
Gtk.TreePath? path = get_selected_path();
if (path == null) {
if (base.cursor_changed != null)
base.cursor_changed();
-
return;
}
EntryWrapper? wrapper = get_wrapper_at_path(path);
-
- selected_wrapper = wrapper;
-
- if (editing_disabled == 0 && wrapper != null)
- text_renderer.editable = wrapper.entry is Sidebar.RenameableEntry;
- if (wrapper != null && !mask_entry_selected_signal) {
- Sidebar.SelectableEntry? selectable = wrapper.entry as Sidebar.SelectableEntry;
- if (selectable != null)
- entry_selected(selectable);
+ if (selected_wrapper != wrapper) {
+ EntryWrapper old_wrapper = selected_wrapper;
+ selected_wrapper = wrapper;
+
+ if (editing_disabled == 0 && wrapper != null && wrapper.entry is Sidebar.RenameableEntry)
+ text_renderer.editable = ((Sidebar.RenameableEntry) wrapper.entry).is_user_renameable();
+
+ if (wrapper != null && !mask_entry_selected_signal) {
+ Sidebar.SelectableEntry? selectable = wrapper.entry as Sidebar.SelectableEntry;
+ if (selectable != null) {
+ if (accept_cursor_changed()) {
+ entry_selected(selectable);
+ } else {
+ place_cursor(old_wrapper.entry, true);
+ }
+ }
+ }
}
if (base.cursor_changed != null)
@@ -320,11 +356,14 @@ public class Sidebar.Tree : Gtk.TreeView {
Gtk.TreePath? path = get_selected_path();
if (path != null && editing_disabled > 0 && --editing_disabled == 0) {
EntryWrapper? wrapper = get_wrapper_at_path(path);
- text_renderer.editable = (wrapper != null && (wrapper.entry is Sidebar.RenameableEntry));
+ if (wrapper != null && (wrapper.entry is Sidebar.RenameableEntry))
+ text_renderer.editable = ((Sidebar.RenameableEntry) wrapper.entry).
+ is_user_renameable();
}
}
public void toggle_branch_expansion(Gtk.TreePath path, bool expand_all) {
+ expander_called_manually = true;
if (is_row_expanded(path))
collapse_row(path);
else
@@ -332,6 +371,7 @@ public class Sidebar.Tree : Gtk.TreeView {
}
public bool expand_to_entry(Sidebar.Entry entry) {
+ expander_called_manually = true;
EntryWrapper? wrapper = get_wrapper(entry);
if (wrapper == null)
return false;
@@ -342,6 +382,7 @@ public class Sidebar.Tree : Gtk.TreeView {
}
public void expand_to_first_child(Sidebar.Entry entry) {
+ expander_called_manually = true;
EntryWrapper? wrapper = get_wrapper(entry);
if (wrapper == null)
return;
@@ -445,7 +486,7 @@ public class Sidebar.Tree : Gtk.TreeView {
assert(!entry_map.has_key(entry));
entry_map.set(entry, wrapper);
- store.set(assoc_iter, Columns.NAME, guarded_markup_escape_text(entry.get_sidebar_name()));
+ store.set(assoc_iter, Columns.NAME, get_name_for_entry(entry));
store.set(assoc_iter, Columns.TOOLTIP, guarded_markup_escape_text(entry.get_sidebar_tooltip()));
store.set(assoc_iter, Columns.WRAPPER, wrapper);
load_entry_icons(assoc_iter);
@@ -458,15 +499,15 @@ public class Sidebar.Tree : Gtk.TreeView {
pageable.page_created.connect(on_sidebar_page_created);
pageable.destroying_page.connect(on_sidebar_destroying_page);
}
+
+ Sidebar.EmphasizableEntry? emphasizable = entry as Sidebar.EmphasizableEntry;
+ if (emphasizable != null)
+ emphasizable.is_emphasized_changed.connect(on_is_emphasized_changed);
Sidebar.RenameableEntry? renameable = entry as Sidebar.RenameableEntry;
if (renameable != null)
renameable.sidebar_name_changed.connect(on_sidebar_name_changed);
-
- Sidebar.ExpandableEntry? expandable = entry as Sidebar.ExpandableEntry;
- if (expandable != null)
- expandable.sidebar_open_closed_icons_changed.connect(on_sidebar_open_closed_icons_changed);
-
+
entry.grafted(this);
}
@@ -479,7 +520,7 @@ public class Sidebar.Tree : Gtk.TreeView {
EntryWrapper new_wrapper = new EntryWrapper(store, entry, store.get_path(new_iter));
entry_map.set(entry, new_wrapper);
- store.set(new_iter, Columns.NAME, guarded_markup_escape_text(entry.get_sidebar_name()));
+ store.set(new_iter, Columns.NAME, get_name_for_entry(entry));
store.set(new_iter, Columns.TOOLTIP, guarded_markup_escape_text(entry.get_sidebar_tooltip()));
store.set(new_iter, Columns.WRAPPER, new_wrapper);
load_entry_icons(new_iter);
@@ -571,9 +612,9 @@ public class Sidebar.Tree : Gtk.TreeView {
if (renameable != null)
renameable.sidebar_name_changed.disconnect(on_sidebar_name_changed);
- Sidebar.ExpandableEntry? expandable = entry as Sidebar.ExpandableEntry;
- if (expandable != null)
- expandable.sidebar_open_closed_icons_changed.disconnect(on_sidebar_open_closed_icons_changed);
+ Sidebar.EmphasizableEntry? emphasizable = entry as Sidebar.EmphasizableEntry;
+ if (emphasizable != null)
+ emphasizable.is_emphasized_changed.disconnect(on_is_emphasized_changed);
bool removed = entry_map.unset(entry);
assert(removed);
@@ -703,88 +744,42 @@ public class Sidebar.Tree : Gtk.TreeView {
store.set(wrapper.get_iter(), Columns.TOOLTIP, guarded_markup_escape_text(tooltip));
}
- private void on_sidebar_icon_changed(Sidebar.Entry entry, Icon? icon) {
+ private void on_sidebar_icon_changed(Sidebar.Entry entry, string? icon) {
EntryWrapper? wrapper = get_wrapper(entry);
assert(wrapper != null);
- store.set(wrapper.get_iter(), Columns.PIXBUF, fetch_icon_pixbuf(icon));
+ store.set(wrapper.get_iter(), Columns.ICON, icon);
}
-
- private void on_sidebar_page_created(Sidebar.PageRepresentative entry, Page page) {
- page_created(entry, page);
+
+ private void rename_entry(Sidebar.Entry entry) {
+ EntryWrapper? wrapper = get_wrapper(entry);
+ assert(wrapper != null);
+
+ store.set(wrapper.get_iter(), Columns.NAME, get_name_for_entry(entry));
}
- private void on_sidebar_destroying_page(Sidebar.PageRepresentative entry, Page page) {
- destroying_page(entry, page);
+ private void on_sidebar_name_changed(Sidebar.Entry entry, string name) {
+ rename_entry(entry);
}
- private void on_sidebar_open_closed_icons_changed(Sidebar.ExpandableEntry entry, Icon? open,
- Icon? closed) {
- EntryWrapper? wrapper = get_wrapper(entry);
- assert(wrapper != null);
-
- store.set(wrapper.get_iter(), Columns.OPEN_PIXBUF, fetch_icon_pixbuf(open));
- store.set(wrapper.get_iter(), Columns.CLOSED_PIXBUF, fetch_icon_pixbuf(closed));
+ private void on_sidebar_page_created(Sidebar.PageRepresentative entry, Page page) {
+ page_created(entry, page);
}
- private void on_sidebar_name_changed(Sidebar.RenameableEntry entry, string name) {
- EntryWrapper? wrapper = get_wrapper(entry);
- assert(wrapper != null);
-
- store.set(wrapper.get_iter(), Columns.NAME, guarded_markup_escape_text(name));
+ private void on_is_emphasized_changed(Sidebar.EmphasizableEntry entry, bool is_emphasized) {
+ rename_entry(entry);
}
- private Gdk.Pixbuf? fetch_icon_pixbuf(GLib.Icon? gicon) {
- if (gicon == null)
- return null;
-
- try {
- Gdk.Pixbuf? icon = icon_cache.get(gicon.to_string());
- if (icon != null)
- return icon;
-
- Gtk.IconInfo? info = icon_theme.lookup_by_gicon(gicon, ICON_SIZE, 0);
- if (info == null)
- return null;
-
- icon = info.load_icon();
- if (icon == null)
- return null;
-
- icon_cache.set(gicon.to_string(), icon);
-
- return icon;
- } catch (Error err) {
- warning("Unable to load icon %s: %s", gicon.to_string(), err.message);
-
- return null;
- }
+ private void on_sidebar_destroying_page(Sidebar.PageRepresentative entry, Page page) {
+ destroying_page(entry, page);
}
private void load_entry_icons(Gtk.TreeIter iter) {
EntryWrapper? wrapper = get_wrapper_at_iter(iter);
if (wrapper == null)
return;
-
- Icon? icon = wrapper.entry.get_sidebar_icon();
- Icon? open = null;
- Icon? closed = null;
-
- Sidebar.ExpandableEntry? expandable = wrapper.entry as Sidebar.ExpandableEntry;
- if (expandable != null) {
- open = expandable.get_sidebar_open_icon();
- closed = expandable.get_sidebar_closed_icon();
- }
-
- if (open == null)
- open = icon;
-
- if (closed == null)
- closed = icon;
-
- store.set(iter, Columns.PIXBUF, fetch_icon_pixbuf(icon));
- store.set(iter, Columns.OPEN_PIXBUF, fetch_icon_pixbuf(open));
- store.set(iter, Columns.CLOSED_PIXBUF, fetch_icon_pixbuf(closed));
+ string? icon = wrapper.entry.get_sidebar_icon();
+ store.set(iter, Columns.ICON, icon);
}
private void load_branch_icons(Gtk.TreeIter iter) {
@@ -798,15 +793,6 @@ public class Sidebar.Tree : Gtk.TreeView {
}
}
- private void on_theme_change() {
- Gtk.TreeIter iter;
- if (store.get_iter_first(out iter)) {
- do {
- load_branch_icons(iter);
- } while (store.iter_next(ref iter));
- }
- }
-
private bool on_selection(Gtk.TreeSelection selection, Gtk.TreeModel model, Gtk.TreePath path,
bool path_currently_selected) {
// only allow selection if a page is selectable
@@ -879,6 +865,42 @@ public class Sidebar.Tree : Gtk.TreeView {
return true;
}
+ public bool on_toggle_row(Gtk.TreeIter iter, Gtk.TreePath path) {
+ // Determine whether to allow the row to toggle
+ EntryWrapper? wrapper = get_wrapper_at_iter(iter);
+ if (wrapper == null) {
+ return false; // don't affect things
+ }
+
+ // Most of the time, only allow manual toggles
+ bool should_allow_toggle = expander_called_manually;
+
+ // Cancel out the manual flag
+ expander_called_manually = false;
+
+ // If we are an expanded parent entry with content
+ if (is_row_expanded(path) && store.iter_has_child(iter) && wrapper.entry is Sidebar.SelectableEntry) {
+ // We are taking a special action
+ expander_special_count++;
+ if (expander_special_count == 1) {
+ // Workaround that prevents arrows from double-toggling
+ return true;
+ } else {
+ // Toggle only if non-manual, as opposed to the usual behavior
+ should_allow_toggle = !should_allow_toggle;
+ }
+ } else {
+ // Reset the special behavior count
+ expander_special_count = 0;
+ }
+
+ if (should_allow_toggle) {
+ return false;
+ }
+ // Prevent branch expansion toggle
+ return true;
+ }
+
public override bool button_press_event(Gdk.EventButton event) {
Gtk.TreePath? path = get_path_from_event(event);
@@ -893,19 +915,29 @@ public class Sidebar.Tree : Gtk.TreeView {
popup_context_menu(path, event);
else
popup_default_context_menu(event);
- } else if (event.button == 1 && event.type == Gdk.EventType.2BUTTON_PRESS) {
- // double left click
- if (path != null) {
+ } else if (event.button == 1 && event.type == Gdk.EventType.BUTTON_PRESS) {
+ if (path == null) {
+ old_path_ref = null;
+ return base.button_press_event(event);
+ }
+
+ EntryWrapper? wrapper = get_wrapper_at_path(path);
+
+ if (wrapper == null) {
+ old_path_ref = null;
+ return base.button_press_event(event);
+ }
+
+ // Enable single click to toggle tree entries (bug 4985)
+ if (wrapper.entry is Sidebar.ExpandableEntry
+ || wrapper.entry is Sidebar.InternalDropTargetEntry) {
+ // all labels are InternalDropTargetEntries
toggle_branch_expansion(path, false);
-
- if (can_rename_path(path))
- return false;
}
- } else if (event.button == 1 && event.type == Gdk.EventType.BUTTON_PRESS) {
+
// Is this a click on an already-highlighted tree item?
- Gtk.TreePath? cursor_path = null;
- get_cursor(out cursor_path, null);
- if ((cursor_path != null) && (cursor_path.compare(path) == 0)) {
+ if ((old_path_ref != null) && (old_path_ref.get_path() != null)
+ && (old_path_ref.get_path().compare(path) == 0)) {
// yes, don't allow single-click editing, but
// pass the event on for dragging.
text_renderer.editable = false;
@@ -914,9 +946,13 @@ public class Sidebar.Tree : Gtk.TreeView {
// Got click on different tree item, make sure it is editable
// if it needs to be.
- if (path != null && get_wrapper_at_path(path).entry is Sidebar.RenameableEntry) {
+ if (wrapper.entry is Sidebar.RenameableEntry &&
+ ((Sidebar.RenameableEntry) wrapper.entry).is_user_renameable()) {
text_renderer.editable = true;
}
+
+ // Remember what tree item is highlighted for next time.
+ old_path_ref = new Gtk.TreeRowReference(store, path);
}
return base.button_press_event(event);
@@ -1106,6 +1142,9 @@ public class Sidebar.Tree : Gtk.TreeView {
if (renameable == null)
return false;
+ if (wrapper.entry is Sidebar.Header)
+ return false;
+
get_selection().select_path(path);
return true;
diff --git a/src/sidebar/common.vala b/src/sidebar/common.vala
index 36adfff..0f1bc05 100644
--- a/src/sidebar/common.vala
+++ b/src/sidebar/common.vala
@@ -1,39 +1,42 @@
-/* Copyright 2011-2014 Yorba Foundation
+/* Copyright 2011-2015 Yorba Foundation
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
*/
// A simple grouping Entry that is only expandable
-public class Sidebar.Grouping : Object, Sidebar.Entry, Sidebar.ExpandableEntry {
+public class Sidebar.Grouping : Object, Sidebar.Entry, Sidebar.ExpandableEntry,
+ Sidebar.RenameableEntry {
+
private string name;
- private Icon? open_icon;
- private Icon? closed_icon;
+ private string? tooltip;
+ private string? icon;
- public Grouping(string name, Icon? open_icon, Icon? closed_icon = null) {
+ public Grouping(string name, string? icon, string? tooltip = null) {
this.name = name;
- this.open_icon = open_icon;
- this.closed_icon = closed_icon ?? open_icon;
+ this.icon = icon;
+ this.tooltip = tooltip;
}
- public string get_sidebar_name() {
- return name;
+ public void rename(string name) {
+ this.name = name;
+ sidebar_name_changed(name);
}
- public string? get_sidebar_tooltip() {
- return name;
+ public bool is_user_renameable() {
+ return false;
}
- public Icon? get_sidebar_icon() {
- return null;
+ public string get_sidebar_name() {
+ return name;
}
- public Icon? get_sidebar_open_icon() {
- return open_icon;
+ public string? get_sidebar_tooltip() {
+ return tooltip;
}
- public Icon? get_sidebar_closed_icon() {
- return closed_icon;
+ public string? get_sidebar_icon() {
+ return icon;
}
public string to_string() {
@@ -61,7 +64,7 @@ public abstract class Sidebar.SimplePageEntry : Object, Sidebar.Entry, Sidebar.S
return get_sidebar_name();
}
- public abstract Icon? get_sidebar_icon();
+ public abstract string? get_sidebar_icon();
public virtual string to_string() {
return get_sidebar_name();
@@ -107,6 +110,26 @@ public class Sidebar.RootOnlyBranch : Sidebar.Branch {
}
}
+/**
+ * A header is an entry that is visually distinguished from its children. Bug 6397 recommends
+ * headers to appear bolded and without any icons. To prevent the icons from rendering, we set the
+ * icons to null in the base class @see Sidebar.Grouping. But we also go a step further by
+ * using a custom cell_data_function (@see Sidebar.Tree::icon_renderer_function) which ensures that
+ * header icons won't be rendered. This approach avoids the blank icon spacing issues.
+ */
+public class Sidebar.Header : Sidebar.Grouping, Sidebar.EmphasizableEntry {
+ private bool emphasized;
+
+ public Header(string name, bool emphasized = true) {
+ base(name, null);
+ this.emphasized = emphasized;
+ }
+
+ public bool is_emphasized() {
+ return emphasized;
+ }
+}
+
public interface Sidebar.Contextable : Object {
// Return null if the context menu should not be invoked for this event
public abstract Gtk.Menu? get_sidebar_context_menu(Gdk.EventButton? event);