[gitg] Move navigation panel into history plugin



commit 523909d7f75dcaca8edea014994ba1cb8a6e0b85
Author: Techlive Zheng <techlivezheng gmail com>
Date:   Tue May 21 13:55:44 2013 +0800

    Move navigation panel into history plugin
    
    Resolve #700541

 data/org.gnome.gitg.gschema.xml.in.in              |    3 -
 gitg/gitg-window.vala                              |   35 +--
 gitg/resources/ui/gitg-window.ui                   |   67 +--
 libgitg-ext/Makefile.am                            |    2 -
 libgitg-ext/gitg-ext-navigation-tree-view.vala     |  504 ------------------
 libgitg-ext/gitg-ext-navigation.vala               |   42 --
 libgitg-ext/gitg-ext-ui-element.vala               |    7 -
 libgitg-ext/gitg-ext-view.vala                     |   16 +-
 plugins/history/gitg-history-navigation.vala       |  533 ++++++++++++++++++--
 plugins/history/gitg-history.vala                  |   61 ++-
 .../org.gnome.gitg.history.gschema.xml.in.in       |    6 +
 plugins/history/resources/view-history.ui          |  124 +++--
 12 files changed, 643 insertions(+), 757 deletions(-)
---
diff --git a/data/org.gnome.gitg.gschema.xml.in.in b/data/org.gnome.gitg.gschema.xml.in.in
index 551191b..999e19c 100644
--- a/data/org.gnome.gitg.gschema.xml.in.in
+++ b/data/org.gnome.gitg.gschema.xml.in.in
@@ -117,9 +117,6 @@
     <key name="size" type="(ii)">
       <default>(650, 500)</default>
     </key>
-    <key name="paned-views-position" type="i">
-      <default>200</default>
-    </key>
     <key name="paned-panels-position" type="i">
       <default>150</default>
     </key>
diff --git a/gitg/gitg-window.vala b/gitg/gitg-window.vala
index 7000840..136bb11 100644
--- a/gitg/gitg-window.vala
+++ b/gitg/gitg-window.vala
@@ -49,14 +49,11 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable, Gtk.
        private Gtk.ScrolledWindow d_dash_scrolled_window;
        private GitgGtk.DashView d_dash_view;
 
-       private Gtk.Paned d_paned_views;
        private Gtk.Paned d_paned_panels;
 
        private Gd.Stack d_stack_view;
        private Gd.Stack d_stack_panel;
 
-       private GitgExt.NavigationTreeView d_navigation;
-
        private static const ActionEntry[] win_entries = {
                {"search", on_search_activated, null, "false", null},
                {"gear-menu", on_gear_menu_activated, null, "false", null},
@@ -146,7 +143,7 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable, Gtk.
                        d_header_bar.set_subtitle(Markup.escape_text(head_name));
 
                        d_main_stack.transition_type = Gd.StackTransitionType.SLIDE_LEFT;
-                       d_main_stack.set_visible_child(d_paned_views);
+                       d_main_stack.set_visible_child(d_paned_panels);
                        d_commit_view_switcher.show();
                        d_button_dash.show();
                        d_dash_view.add_repository(d_repository);
@@ -436,7 +433,6 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable, Gtk.
                        repository = r;
                });
 
-               d_paned_views = builder.get_object("paned_views") as Gtk.Paned;
                d_paned_panels = builder.get_object("paned_panels") as Gtk.Paned;
 
                d_stack_view = builder.get_object("stack_view") as Gd.Stack;
@@ -444,7 +440,6 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable, Gtk.
                d_commit_view_switcher = builder.get_object("commit-view-switcher") as Gd.StackSwitcher;
                d_commit_view_switcher.stack = d_stack_panel;
 
-               d_navigation = builder.get_object("tree_view_navigation") as GitgExt.NavigationTreeView;
                d_gear_menu = builder.get_object("gear-menubutton") as Gtk.MenuButton;
 
                string menuname;
@@ -498,31 +493,14 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable, Gtk.
        {
                GitgExt.View? view = (GitgExt.View?)element;
 
-               // 1) Clear the navigation tree
-               d_navigation.model.clear();
-
-               if (view != null && view.navigation != null)
+               if (view != null)
                {
-                       d_navigation.set_show_expanders(view.navigation.show_expanders);
-
-                       if (view.navigation.show_expanders)
-                       {
-                               d_navigation.set_level_indentation(0);
-                       }
-                       else
-                       {
-                               d_navigation.set_level_indentation(12);
-                       }
-
-                       // 2) Populate the navigation tree for this view
-                       d_navigation.model.populate(view.navigation);
+                       view.on_view_activated();
                }
 
-               d_navigation.expand_all();
-               d_navigation.select_first();
-
                // Update panels
                d_panels.update();
+
                notify_property("current_view");
        }
 
@@ -600,11 +578,6 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable, Gtk.
                d_state_settings.get ("size", "(ii)", out width, out height);
                resize (width, height);
 
-               d_state_settings.bind("paned-views-position",
-                                     d_paned_views,
-                                     "position",
-                                     SettingsBindFlags.GET | SettingsBindFlags.SET);
-
                d_state_settings.bind("paned-panels-position",
                                      d_paned_panels,
                                      "position",
diff --git a/gitg/resources/ui/gitg-window.ui b/gitg/resources/ui/gitg-window.ui
index 9fc5714..afb2b29 100644
--- a/gitg/resources/ui/gitg-window.ui
+++ b/gitg/resources/ui/gitg-window.ui
@@ -145,79 +145,34 @@
               </object>
             </child>
             <child>
-              <object class="GtkPaned" id="paned_views">
+              <object class="GtkPaned" id="paned_panels">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="hexpand">True</property>
-                <property name="vexpand">True</property>
-                <property name="position">200</property>
-                <property name="position_set">True</property>
+                <property name="position">300</property>
+                <property name="orientation">vertical</property>
                 <style>
-                  <class name="sidebar-paned"/>
+                  <class name="panels-paned"/>
                 </style>
                 <child>
-                  <object class="GtkScrolledWindow" id="scrolled_window_navigation">
+                  <object class="GdStack" id="stack_view">
                     <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>
-                    <property name="name">scrolled_window_navigation</property>
-                    <style>
-                      <class name="sidebar"/>
-                    </style>
-                    <child>
-                      <object class="GitgExtNavigationTreeView" id="tree_view_navigation">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="headers_visible">False</property>
-                        <property name="name">tree_view_navigation</property>
-                        <child internal-child="selection">
-                          <object class="GtkTreeSelection" id="gitgextnavigationtreeView-selection"/>
-                        </child>
-                      </object>
-                    </child>
+                    <property name="can_focus">False</property>
                   </object>
                   <packing>
-                    <property name="resize">False</property>
+                    <property name="resize">True</property>
                     <property name="shrink">True</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkPaned" id="paned_panels">
+                  <object class="GdStack" id="stack_panel">
                     <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="orientation">vertical</property>
-                    <property name="position">300</property>
-                    <style>
-                      <class name="panels-paned"/>
-                    </style>
-                    <child>
-                      <object class="GdStack" id="stack_view">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                      </object>
-                      <packing>
-                        <property name="resize">True</property>
-                        <property name="shrink">True</property>
-                      </packing>
-                    </child>
+                    <property name="can_focus">False</property>
                     <child>
-                      <object class="GdStack" id="stack_panel">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <child>
-                          <placeholder/>
-                        </child>
-                      </object>
-                      <packing>
-                        <property name="resize">False</property>
-                        <property name="shrink">True</property>
-                      </packing>
+                      <placeholder/>
                     </child>
                   </object>
                   <packing>
-                    <property name="resize">True</property>
+                    <property name="resize">False</property>
                     <property name="shrink">True</property>
                   </packing>
                 </child>
diff --git a/libgitg-ext/Makefile.am b/libgitg-ext/Makefile.am
index 42f05f3..264e280 100644
--- a/libgitg-ext/Makefile.am
+++ b/libgitg-ext/Makefile.am
@@ -40,8 +40,6 @@ VALA_FILES =                                  \
        gitg-ext-ui-element.vala                \
        gitg-ext-panel.vala                     \
        gitg-ext-view.vala                      \
-       gitg-ext-navigation.vala                \
-       gitg-ext-navigation-tree-view.vala      \
        gitg-ext-message-id.vala                \
        gitg-ext-message.vala                   \
        gitg-ext-message-bus.vala               \
diff --git a/libgitg-ext/gitg-ext-ui-element.vala b/libgitg-ext/gitg-ext-ui-element.vala
index 0ff435c..3211084 100644
--- a/libgitg-ext/gitg-ext-ui-element.vala
+++ b/libgitg-ext/gitg-ext-ui-element.vala
@@ -30,13 +30,6 @@ namespace GitgExt
  * Implementations of the GitgExtView interface will be integrated
  * automatically in the gitg interface according to the various interface
  * methods and properties that need to be implemented.
- *
- * To provide a default navigation when the view is active, the
- * #GitgExtView::navigation property should be implemented and should return a
- * non-null #GitgExtNavigation. This navigation section will always be present
- * at the top of the navigation menu. Note that you should normally ''not''
- * export this type to Peas because you will end up having the navigation
- * shown twice in the UI.
  */
 public interface UIElement : Object
 {
diff --git a/libgitg-ext/gitg-ext-view.vala b/libgitg-ext/gitg-ext-view.vala
index cf6758a..c8303bb 100644
--- a/libgitg-ext/gitg-ext-view.vala
+++ b/libgitg-ext/gitg-ext-view.vala
@@ -53,23 +53,17 @@ public enum ViewAction
  * Implementations of the GitgExtView interface will be integrated
  * automatically in the gitg interface according to the various interface
  * methods and properties that need to be implemented.
- *
- * To provide a default navigation when the view is active, the
- * #GitgExtView::navigation property should be implemented and should return a
- * non-null #GitgExtNavigation. This navigation section will always be present
- * at the top of the navigation menu. Note that you should normally ''not''
- * export this type to Peas because you will end up having the navigation
- * shown twice in the UI.
  */
 public interface View : Object, UIElement
 {
        /**
-        * Main navigation for the view.
+        * Give the view itself a chance to perform some actions after being
+        * activated.
+        *
+        * @return void
         *
-        * When provided, the corresponding navigation
-        * section will be added in the navigation panel when the view is activated.
         */
-       public abstract Navigation? navigation { owned get; }
+       public abstract void on_view_activated();
 
        /**
         * Check whether the view is the default view for a particular action.
diff --git a/plugins/history/gitg-history-navigation.vala b/plugins/history/gitg-history-navigation.vala
index 4aadbfa..5d76951 100644
--- a/plugins/history/gitg-history-navigation.vala
+++ b/plugins/history/gitg-history-navigation.vala
@@ -19,19 +19,75 @@
 
 namespace GitgHistory
 {
-       private class Navigation : Object, GitgExt.Navigation
+       private enum Hint
+       {
+               NONE,
+               HEADER,
+               DEFAULT,
+               SEPARATOR
+       }
+
+       private enum Column
+       {
+               ICON_NAME,
+               TEXT,
+               HEADER,
+               HINT,
+               SECTION,
+               OID
+       }
+
+       public enum NavigationSide
+       {
+               LEFT = 0,
+               TOP = 1
+       }
+
+       public delegate void NavigationActivated(int numclick);
+
+       private class Activated : Object
+       {
+               private NavigationActivated d_activated;
+
+               public Activated(owned NavigationActivated? activated)
+               {
+                       d_activated = (owned)activated;
+               }
+
+               public void activate(int numclick)
+               {
+                       if (d_activated != null)
+                       {
+                               d_activated(numclick);
+                       }
+               }
+       }
+
+       public class Navigation : Gtk.TreeStore
        {
                // Do this to pull in config.h before glib.h (for gettext...)
                private const string version = Gitg.Config.VERSION;
 
-               public GitgExt.Application? application { owned get; construct set; }
                private List<Gitg.Ref> d_all;
+               private uint d_oid;
+               private SList<Gtk.TreeIter?> d_parents;
+               private uint d_sections;
+               private Activated[] d_callbacks;
 
                public signal void ref_activated(Gitg.Ref? r);
 
-               public Navigation(GitgExt.Application app)
+               construct
                {
-                       Object(application: app);
+                       set_column_types({typeof(string),
+                                         typeof(string),
+                                         typeof(string),
+                                         typeof(uint),
+                                         typeof(uint),
+                                         typeof(uint)
+                       });
+
+                       d_callbacks = new Activated[100];
+                       d_callbacks.length = 0;
                }
 
                private static int sort_refs(Gitg.Ref a, Gitg.Ref b)
@@ -44,10 +100,8 @@ namespace GitgHistory
                        return a.parsed_name.remote_branch.ascii_casecmp(b.parsed_name.remote_branch);
                }
 
-               public void populate(GitgExt.NavigationTreeModel model)
+               public void populate(Gitg.Repository repo)
                {
-                       var repo = application.repository;
-
                        List<Gitg.Ref> branches = new List<Gitg.Ref>();
                        List<Gitg.Ref> tags = new List<Gitg.Ref>();
 
@@ -103,17 +157,19 @@ namespace GitgHistory
 
                        d_all.reverse();
 
+                       begin_section();
+
                        if (CommandLine.all)
                        {
-                               model.append_default(_("All commits"), null, (nc) => ref_activated(null));
+                               append_default(_("All commits"), null, (nc) => ref_activated(null));
                        }
                        else
                        {
-                               model.append(_("All commits"), null, (nc) => ref_activated(null));
+                               append(_("All commits"), null, (nc) => ref_activated(null));
                        }
 
                        // Branches
-                       model.begin_header(_("Branches"), null);
+                       begin_header(_("Branches"), null);
 
                        foreach (var item in branches)
                        {
@@ -137,26 +193,26 @@ namespace GitgHistory
 
                                if (isdef)
                                {
-                                       model.append_default(item.parsed_name.shortname,
-                                                            icon,
-                                                            (nc) => ref_activated(item));
+                                       append_default(item.parsed_name.shortname,
+                                                      icon,
+                                                      (nc) => ref_activated(item));
                                }
                                else
                                {
-                                       model.append(item.parsed_name.shortname,
-                                                    icon,
-                                                    (nc) => ref_activated(item));
+                                       append(item.parsed_name.shortname,
+                                              icon,
+                                              (nc) => ref_activated(item));
                                }
                        }
 
-                       model.end_header();
+                       end_header();
 
                        // Remotes
-                       model.begin_header(_("Remotes"), null);
+                       begin_header(_("Remotes"), null);
 
                        foreach (var rname in remotenames)
                        {
-                               model.begin_header(rname, null);
+                               begin_header(rname, null);
 
                                var rrefs = remotes.lookup(rname);
 
@@ -166,29 +222,31 @@ namespace GitgHistory
                                {
                                        var it = rref;
 
-                                       model.append(rref.parsed_name.remote_branch,
-                                                    null,
-                                                    (nc) => ref_activated(it));
+                                       append(rref.parsed_name.remote_branch,
+                                              null,
+                                              (nc) => ref_activated(it));
                                }
 
-                               model.end_header();
+                               end_header();
                        }
 
-                       model.end_header();
+                       end_header();
 
                        // Tags
-                       model.begin_header(_("Tags"), null);
+                       begin_header(_("Tags"), null);
 
                        foreach (var item in tags)
                        {
                                var it = item;
 
-                               model.append(item.parsed_name.shortname,
-                                            null,
-                                            (nc) => ref_activated(it));
+                               append(item.parsed_name.shortname,
+                                      null,
+                                      (nc) => ref_activated(it));
                        }
 
-                       model.end_header();
+                       end_header();
+
+                       end_section();
                }
 
                public List<Gitg.Ref> all
@@ -196,11 +254,6 @@ namespace GitgHistory
                        get { return d_all; }
                }
 
-               public GitgExt.NavigationSide navigation_side
-               {
-                       get { return GitgExt.NavigationSide.LEFT; }
-               }
-
                public bool available
                {
                        get { return true; }
@@ -210,6 +263,418 @@ namespace GitgHistory
                {
                        get { return false; }
                }
+
+               public NavigationSide navigation_side
+               {
+                       get { return NavigationSide.LEFT; }
+               }
+
+               private void append_one(string text,
+                                       string? icon_name,
+                                       uint hint,
+                                       owned NavigationActivated? callback,
+                                       out Gtk.TreeIter iter)
+               {
+                       if (d_parents != null)
+                       {
+                               base.append(out iter, d_parents.data);
+                       }
+                       else
+                       {
+                               base.append(out iter, null);
+                       }
+
+                       @set(iter,
+                            Column.ICON_NAME, icon_name,
+                            hint == Hint.HEADER ? Column.HEADER : Column.TEXT, text,
+                            Column.HINT, hint,
+                            Column.SECTION, d_sections,
+                            Column.OID, d_oid);
+
+                       d_callbacks += new Activated((owned)callback);
+                       ++d_oid;
+               }
+
+               public new Navigation append(string text,
+                                            string? icon_name,
+                                            owned NavigationActivated? callback)
+               {
+                       Gtk.TreeIter iter;
+                       append_one(text, icon_name, Hint.NONE, (owned)callback, out iter);
+
+                       return this;
+               }
+
+               public new Navigation append_default(string text,
+                                                    string? icon_name,
+                                                    owned NavigationActivated? callback)
+               {
+                       Gtk.TreeIter iter;
+                       append_one(text, icon_name, Hint.DEFAULT, (owned)callback, out iter);
+
+                       return this;
+               }
+
+               public new Navigation append_separator()
+               {
+                       Gtk.TreeIter iter;
+                       append_one("", null, Hint.SEPARATOR, null, out iter);
+
+                       return this;
+               }
+
+               public Navigation begin_header(string text,
+                                              string? icon_name)
+               {
+                       Gtk.TreeIter iter;
+
+                       append_one(text, icon_name, Hint.HEADER, null, out iter);
+                       d_parents.prepend(iter);
+
+                       return this;
+               }
+
+               public Navigation end_header()
+               {
+                       if (d_parents != null)
+                       {
+                               d_parents.remove_link(d_parents);
+                       }
+
+                       return this;
+               }
+
+               public uint begin_section()
+               {
+                       d_parents = null;
+                       return d_sections;
+               }
+
+               public void end_section()
+               {
+                       ++d_sections;
+               }
+
+               public void remove_section(uint section)
+               {
+                       Gtk.TreeIter iter;
+
+                       if (!get_iter_first(out iter))
+                       {
+                               return;
+                       }
+
+                       while (true)
+                       {
+                               uint s;
+
+                               @get(iter, Column.SECTION, out s);
+
+                               if (s == section)
+                               {
+                                       if (!base.remove(ref iter))
+                                       {
+                                               break;
+                                       }
+                               }
+                               else
+                               {
+                                       if (!iter_next(ref iter))
+                                       {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               public new void clear()
+               {
+                       base.clear();
+
+                       d_oid = 0;
+                       d_sections = 0;
+                       d_callbacks.length = 0;
+               }
+
+               public void activate(Gtk.TreeIter iter, int numclick)
+               {
+                       uint oid;
+
+                       @get(iter, Column.OID, out oid);
+
+                       if (d_callbacks[oid] != null)
+                       {
+                               d_callbacks[oid].activate(numclick);
+                       }
+               }
+       }
+
+       public class NavigationView : Gtk.TreeView
+       {
+               construct
+               {
+                       var model = new Navigation();
+                       set_model(model);
+
+                       var col = new Gtk.TreeViewColumn();
+
+                       var padcell = new Gtk.CellRendererText();
+                       var headercell = new NavigationRendererText();
+                       var cell = new NavigationRendererText();
+
+                       padcell.xpad = 6;
+                       headercell.ypad = 6;
+
+                       headercell.weight = Pango.Weight.BOLD;
+
+                       col.pack_start(padcell, false);
+                       col.pack_start(headercell, true);
+                       col.pack_start(cell, true);
+
+                       col.set_attributes(headercell,
+                                          "icon_name", Column.ICON_NAME,
+                                          "text", Column.HEADER);
+
+                       col.set_attributes(cell,
+                                          "icon_name", Column.ICON_NAME,
+                                          "text", Column.TEXT);
+
+                       col.set_cell_data_func(headercell, (layout, cell, model, iter) => {
+                               Hint hint;
+                               model.get(iter, Column.HINT, out hint);
+
+                               cell.visible = (hint == Hint.HEADER);
+                       });
+
+                       col.set_cell_data_func(cell, (layout, cell, model, iter) => {
+                               Hint hint;
+                               model.get(iter, Column.HINT, out hint);
+
+                               cell.visible = (hint != Hint.HEADER);
+                       });
+
+                       set_row_separator_func((model, iter) => {
+                               Hint hint;
+                               model.get(iter, Column.HINT, out hint);
+
+                               return hint == Hint.SEPARATOR;
+                       });
+
+                       append_column(col);
+
+                       get_selection().set_select_function((sel, model, path, cursel) => {
+                               Gtk.TreeIter iter;
+                               model.get_iter(out iter, path);
+
+                               uint hint;
+
+                               model.get(iter, Column.HINT, out hint);
+
+                               return hint != Hint.HEADER;
+                       });
+
+                       get_selection().changed.connect((sel) => {
+                               Gtk.TreeIter iter;
+
+                               if (sel.get_selected(null, out iter))
+                               {
+                                       model.activate(iter, 1);
+                               }
+                       });
+               }
+
+               public new Navigation model
+               {
+                       get { return base.get_model() as Navigation; }
+               }
+
+               private bool select_first_in(Gtk.TreeIter? parent, bool seldef)
+               {
+                       Gtk.TreeIter iter;
+
+                       if (!model.iter_children(out iter, parent))
+                       {
+                               return false;
+                       }
+
+                       while (true)
+                       {
+                               uint hint;
+                               model.get(iter, Column.HINT, out hint);
+
+                               if (hint == Hint.HEADER)
+                               {
+                                       if (select_first_in(iter, seldef))
+                                       {
+                                               return true;
+                                       }
+                               }
+
+                               if (!seldef || hint == Hint.DEFAULT)
+                               {
+                                       get_selection().select_iter(iter);
+                                       return true;
+                               }
+
+                               if (!model.iter_next(ref iter))
+                               {
+                                       return false;
+                               }
+                       }
+               }
+
+               public void select_first()
+               {
+                       select_first_in(null, true) || select_first_in(null, false);
+               }
+
+               protected override void row_activated(Gtk.TreePath path, Gtk.TreeViewColumn col)
+               {
+                       Gtk.TreeIter iter;
+                       model.get_iter(out iter, path);
+                       model.activate(iter, 2);
+               }
+       }
+
+       public class NavigationRendererText : Gtk.CellRendererText
+       {
+               private string d_icon_name;
+               private Gdk.Pixbuf d_pixbuf;
+               private Gtk.StateFlags d_state;
+
+               public string? icon_name
+               {
+                       get { return d_icon_name;}
+                       set
+                       {
+                               if (d_icon_name != value)
+                               {
+                                       d_icon_name = value;
+                                       reset_pixbuf();
+                               }
+                       }
+               }
+
+               public uint hint
+               { get; set; }
+
+               construct
+               {
+                       ellipsize = Pango.EllipsizeMode.MIDDLE;
+               }
+
+               private void reset_pixbuf()
+               {
+                       d_pixbuf = null;
+               }
+
+               private void ensure_pixbuf(Gtk.StyleContext ctx)
+               {
+                       if (d_icon_name == null || (d_pixbuf != null && d_state == ctx.get_state()))
+                       {
+                               return;
+                       }
+
+                       d_pixbuf = null;
+
+                       d_state = ctx.get_state();
+                       var screen = ctx.get_screen();
+                       var settings = Gtk.Settings.get_for_screen(screen);
+
+                       int w = 16;
+                       int h = 16;
+
+                       Gtk.icon_size_lookup_for_settings(settings, Gtk.IconSize.MENU, out w, out h);
+
+                       Gtk.IconInfo? info = Gtk.IconTheme.get_default().lookup_icon(d_icon_name,
+                                                                                    int.min(w, h),
+                                                                                    
Gtk.IconLookupFlags.USE_BUILTIN);
+
+                       if (info == null)
+                       {
+                               return;
+                       }
+
+                       bool symbolic = false;
+
+                       try
+                       {
+                               d_pixbuf = info.load_symbolic_for_context(ctx, out symbolic);
+                       } catch {};
+
+                       if (d_pixbuf != null)
+                       {
+                               var source = new Gtk.IconSource();
+                               source.set_pixbuf(d_pixbuf);
+
+                               source.set_size(Gtk.IconSize.SMALL_TOOLBAR);
+                               source.set_size_wildcarded(false);
+
+                               d_pixbuf = ctx.render_icon_pixbuf(source, Gtk.IconSize.SMALL_TOOLBAR);
+                       }
+               }
+
+               protected override void get_preferred_width(Gtk.Widget widget,
+                                                           out int minimum_width,
+                                                           out int minimum_height)
+               {
+                       ensure_pixbuf(widget.get_style_context());
+
+                       // Size of text
+                       base.get_preferred_width(widget, out minimum_width, out minimum_height);
+
+                       if (d_pixbuf != null)
+                       {
+                               minimum_width += d_pixbuf.get_width() + 3;
+                               minimum_height += d_pixbuf.get_height();
+                       }
+               }
+
+               protected override void get_preferred_height_for_width(Gtk.Widget widget,
+                                                                      int width,
+                                                                      out int minimum_height,
+                                                                      out int natural_height)
+               {
+                       base.get_preferred_height_for_width(widget, width,
+                                                           out minimum_height,
+                                                           out natural_height);
+
+                       ensure_pixbuf(widget.get_style_context());
+
+                       if (d_pixbuf != null)
+                       {
+                               minimum_height = int.max(minimum_height, d_pixbuf.height);
+                               natural_height = int.max(natural_height, d_pixbuf.height);
+                       }
+               }
+
+               protected override void render(Cairo.Context ctx,
+                                              Gtk.Widget widget,
+                                              Gdk.Rectangle background_area,
+                                              Gdk.Rectangle cell_area,
+                                              Gtk.CellRendererState state)
+               {
+                       var stx = widget.get_style_context();
+                       ensure_pixbuf(stx);
+
+                       if (d_pixbuf == null)
+                       {
+                               base.render(ctx, widget, background_area, cell_area, state);
+                       }
+                       else
+                       {
+                               // render the text with an additional padding
+                               Gdk.Rectangle area = cell_area;
+                               area.x += d_pixbuf.width + 3;
+
+                               base.render(ctx, widget, background_area, area, state);
+
+                               // render the pixbuf
+                               int yp = (cell_area.height - d_pixbuf.height) / 2;
+
+                               stx.render_icon(ctx, d_pixbuf, cell_area.x, cell_area.y + yp);
+                       }
+               }
        }
 }
 
diff --git a/plugins/history/gitg-history.vala b/plugins/history/gitg-history.vala
index 36bc2d3..f970071 100644
--- a/plugins/history/gitg-history.vala
+++ b/plugins/history/gitg-history.vala
@@ -29,13 +29,14 @@ namespace GitgHistory
 
                public GitgExt.Application? application { owned get; construct set; }
 
-               private Gtk.TreeView d_view;
                private GitgGtk.CommitModel? d_model;
                private Gee.HashSet<Ggit.OId> d_selected;
                private ulong d_insertsig;
                private Settings d_settings;
 
-               private Gtk.Widget d_main;
+               private Gtk.Paned d_main;
+               private GitgHistory.NavigationView d_navigation;
+               private Gtk.TreeView d_commit_list;
 
                public string id
                {
@@ -46,7 +47,7 @@ namespace GitgHistory
                {
                        bool breakit = false;
 
-                       d_view.get_selection().selected_foreach((model, path, iter) => {
+                       d_commit_list.get_selection().selected_foreach((model, path, iter) => {
                                if (!breakit)
                                {
                                        breakit = !func(d_model.commit_from_iter(iter));
@@ -102,7 +103,7 @@ namespace GitgHistory
 
                        if (d_selected.size == 0 || d_selected.remove(commit.get_id()))
                        {
-                               d_view.get_selection().select_path(path);
+                               d_commit_list.get_selection().select_path(path);
                        }
 
                        if (d_selected.size == 0)
@@ -153,21 +154,6 @@ namespace GitgHistory
                        }
                }
 
-               public GitgExt.Navigation? navigation
-               {
-                       owned get
-                       {
-                               // Create the sidebar navigation for the history. This navigation
-                               // will show branches, remotes and tags which can be used to
-                               // filter the history
-                               var ret = new Navigation(application);
-
-                               ret.ref_activated.connect((r) => on_ref_activated(ret, r));
-
-                               return ret;
-                       }
-               }
-
                public bool is_default_for(string action)
                {
                        return application.repository != null && (action == "" || action == "history");
@@ -178,25 +164,52 @@ namespace GitgHistory
                        update_walker(n, r);
                }
 
+               public void on_view_activated()
+               {
+                       d_navigation.expand_all();
+                       d_navigation.select_first();
+               }
+
                private void build_ui()
                {
                        var ret = GitgExt.UI.from_builder("history/view-history.ui",
-                                                         "scrolled_window_commit_list",
+                                                         "paned_views",
+                                                         "navigation_view",
                                                          "commit_list_view",
                                                          "renderer_commit_list_author",
                                                          "renderer_commit_list_author_date");
 
-                       d_main = ret["scrolled_window_commit_list"] as Gtk.Widget;
+                       d_main = ret["paned_views"] as Gtk.Paned;
+
+                       d_navigation = ret["navigation_view"] as GitgHistory.NavigationView;
+                       d_navigation.model.populate(application.repository);
+                       d_navigation.model.ref_activated.connect((r) => {
+                               on_ref_activated(d_navigation.model, r);
+                       });
+                       d_navigation.set_show_expanders(d_navigation.model.show_expanders);
+                       if (d_navigation.model.show_expanders)
+                       {
+                               d_navigation.set_level_indentation(0);
+                       }
+                       else
+                       {
+                               d_navigation.set_level_indentation(12);
+                       }
 
-                       d_view = ret["commit_list_view"] as Gtk.TreeView;
-                       d_view.model = d_model;
-                       d_view.get_selection().changed.connect((sel) => {
+                       d_commit_list = ret["commit_list_view"] as Gtk.TreeView;
+                       d_commit_list.model = d_model;
+                       d_commit_list.get_selection().changed.connect((sel) => {
                                selection_changed();
                        });
 
                        (ret["renderer_commit_list_author"] as Gd.StyledTextRenderer).add_class("dim-label");
                        (ret["renderer_commit_list_author_date"] as 
Gd.StyledTextRenderer).add_class("dim-label");
 
+                       var state_settings = new Settings("org.gnome.gitg.history.state");
+                       state_settings.bind("paned-views-position",
+                                           d_main,
+                                           "position",
+                                           SettingsBindFlags.GET | SettingsBindFlags.SET);
                }
 
                private void update_walker(Navigation n, Gitg.Ref? head)
diff --git a/plugins/history/org.gnome.gitg.history.gschema.xml.in.in 
b/plugins/history/org.gnome.gitg.history.gschema.xml.in.in
index 8525798..a876091 100644
--- a/plugins/history/org.gnome.gitg.history.gschema.xml.in.in
+++ b/plugins/history/org.gnome.gitg.history.gschema.xml.in.in
@@ -1,7 +1,13 @@
 <schemalist>
   <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.gitg.history" path="/org/gnome/gitg/history/">
+    <child name="state" schema="org.gnome.gitg.history.state"/>
     <child name="preferences" schema="org.gnome.gitg.history.preferences" />
   </schema>
+  <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.gitg.history.state" 
path="/org/gnome/gitg/history/state/">
+    <key name="paned-views-position" type="i">
+      <default>200</default>
+    </key>
+  </schema>
   <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.gitg.history.preferences" 
path="/org/gnome/gitg/history/preferences/">
     <key name="collapse-inactive-lanes" type="i">
       <default>2</default>
diff --git a/plugins/history/resources/view-history.ui b/plugins/history/resources/view-history.ui
index 7e7e1c7..e91b4d8 100644
--- a/plugins/history/resources/view-history.ui
+++ b/plugins/history/resources/view-history.ui
@@ -1,65 +1,103 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.3 -->
-  <object class="GtkScrolledWindow" id="scrolled_window_commit_list">
+  <object class="GtkPaned" id="paned_views">
     <property name="visible">True</property>
     <property name="hexpand">True</property>
     <property name="vexpand">True</property>
     <property name="can_focus">True</property>
-    <property name="shadow-type">none</property>
+    <property name="position">200</property>
+    <property name="position_set">True</property>
+    <style>
+      <class name="sidebar-paned"/>
+    </style>
     <child>
-      <object class="GitgGtkCommitListView" id="commit_list_view">
+      <object class="GtkScrolledWindow" id="scrolled_window_navigation">
         <property name="visible">True</property>
         <property name="can_focus">True</property>
-        <property name="rules_hint">True</property>
-        <property name="fixed-height-mode">True</property>
-        <property name="headers-visible">False</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="hscrollbar_policy">never</property>
+        <property name="name">scrolled_window_navigation</property>
+        <style>
+          <class name="sidebar"/>
+        </style>
         <child>
-          <object class="GtkTreeViewColumn" id="column_commit_list_subject">
-            <property name="title" translatable="yes">Subject</property>
-            <property name="sizing">fixed</property>
-            <property name="resizable">True</property>
-            <property name="expand">True</property>
-            <property name="fixed-width">600</property>
-            <child>
-              <object class="GitgGtkCellRendererLanes" id="renderer_commit_list_subject">
-                <property name="ellipsize">end</property>
-              </object>
-              <attributes>
-                <attribute name="text">1</attribute>
-              </attributes>
-            </child>
+          <object class="GitgHistoryNavigationView" id="navigation_view">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="headers_visible">False</property>
+            <property name="name">tree_view_navigation</property>
           </object>
         </child>
+      </object>
+      <packing>
+        <property name="resize">False</property>
+        <property name="shrink">True</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkScrolledWindow" id="scrolled_window_commit_list">
+        <property name="visible">True</property>
+        <property name="hexpand">True</property>
+        <property name="vexpand">True</property>
+        <property name="can_focus">True</property>
+        <property name="shadow-type">none</property>
         <child>
-          <object class="GtkTreeViewColumn" id="column_commit_list_author">
-            <property name="title" translatable="yes">Author</property>
-            <property name="sizing">fixed</property>
-            <property name="resizable">True</property>
-            <property name="fixed-width">200</property>
+          <object class="GitgGtkCommitListView" id="commit_list_view">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="rules_hint">True</property>
+            <property name="fixed-height-mode">True</property>
+            <property name="headers-visible">False</property>
             <child>
-              <object class="GdStyledTextRenderer" id="renderer_commit_list_author">
-                <property name="ellipsize">end</property>
+              <object class="GtkTreeViewColumn" id="column_commit_list_subject">
+                <property name="title" translatable="yes">Subject</property>
+                <property name="sizing">fixed</property>
+                <property name="resizable">True</property>
+                <property name="expand">True</property>
+                <property name="fixed-width">600</property>
+                <child>
+                  <object class="GitgGtkCellRendererLanes" id="renderer_commit_list_subject">
+                    <property name="ellipsize">end</property>
+                  </object>
+                  <attributes>
+                    <attribute name="text">1</attribute>
+                  </attributes>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkTreeViewColumn" id="column_commit_list_author">
+                <property name="title" translatable="yes">Author</property>
+                <property name="sizing">fixed</property>
+                <property name="resizable">True</property>
+                <property name="fixed-width">200</property>
+                <child>
+                  <object class="GdStyledTextRenderer" id="renderer_commit_list_author">
+                    <property name="ellipsize">end</property>
+                  </object>
+                  <attributes>
+                    <attribute name="text">4</attribute>
+                  </attributes>
+                </child>
               </object>
-              <attributes>
-                <attribute name="text">4</attribute>
-              </attributes>
             </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkTreeViewColumn" id="column_commit_list_author_date">
-            <property name="title" translatable="yes">Date</property>
-            <property name="sizing">fixed</property>
-            <property name="resizable">True</property>
-            <property name="fixed-width">250</property>
             <child>
-              <object class="GdStyledTextRenderer" id="renderer_commit_list_author_date">
-                <property name="ellipsize">end</property>
+              <object class="GtkTreeViewColumn" id="column_commit_list_author_date">
+                <property name="title" translatable="yes">Date</property>
+                <property name="sizing">fixed</property>
+                <property name="resizable">True</property>
+                <property name="fixed-width">250</property>
+                <child>
+                  <object class="GdStyledTextRenderer" id="renderer_commit_list_author_date">
+                    <property name="ellipsize">end</property>
+                  </object>
+                  <attributes>
+                    <attribute name="text">6</attribute>
+                  </attributes>
+                </child>
               </object>
-              <attributes>
-                <attribute name="text">6</attribute>
-              </attributes>
             </child>
           </object>
         </child>



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