[gitg/wip/commit: 24/28] Added sidebar widget



commit 1dbeca4fdc8308d6ca09001b9d9a38add36b8173
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Wed Jul 3 16:41:51 2013 +0200

    Added sidebar widget

 libgitg/Makefile.am               |    3 +-
 libgitg/gitg-sidebar.vala         |  418 +++++++++++++++++++++++++++++++++++++
 libgitg/resources/resources.xml   |    3 +
 libgitg/resources/sidebar-view.ui |   63 ++++++
 4 files changed, 486 insertions(+), 1 deletions(-)
---
diff --git a/libgitg/Makefile.am b/libgitg/Makefile.am
index 305a9a1..a440222 100644
--- a/libgitg/Makefile.am
+++ b/libgitg/Makefile.am
@@ -64,7 +64,8 @@ VALA_FILES =                                  \
        gitg-when-mapped.vala                   \
        gitg-progress-bin.vala                  \
        gitg-stage.vala                         \
-       gitg-stage-status-enumerator.vala
+       gitg-stage-status-enumerator.vala       \
+       gitg-sidebar.vala
 
 # Ignore all warnings for vala code...
 libgitg_1_0_la_CFLAGS =                \
diff --git a/libgitg/gitg-sidebar.vala b/libgitg/gitg-sidebar.vala
new file mode 100644
index 0000000..b5b4ea4
--- /dev/null
+++ b/libgitg/gitg-sidebar.vala
@@ -0,0 +1,418 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2013 - Jesse van den Kieboom
+ *
+ * gitg 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * gitg 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 gitg. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Gitg
+{
+
+public enum SidebarHint
+{
+       NONE,
+       HEADER,
+       DEFAULT,
+       SEPARATOR,
+       DUMMY
+}
+
+public enum SidebarColumn
+{
+       ICON_NAME,
+       NAME,
+       TEXT,
+       HEADER,
+       HINT,
+       SECTION,
+       OID
+}
+
+public delegate void SidebarActivated(int numclick);
+
+[GtkTemplate ( ui = "/org/gnome/gitg/gtk/sidebar/sidebar-store.ui" )]
+public class SidebarStore : Gtk.TreeStore
+{
+       private class Activated : Object
+       {
+               private SidebarActivated d_activated;
+
+               public Activated(owned SidebarActivated? activated)
+               {
+                       d_activated = (owned)activated;
+               }
+
+               public void activate(int numclick)
+               {
+                       if (d_activated != null)
+                       {
+                               d_activated(numclick);
+                       }
+               }
+       }
+
+       private Activated[] d_callbacks;
+       private uint d_oid;
+       private uint d_sections;
+       private SList<Gtk.TreeIter?> d_parents;
+
+       construct
+       {
+               d_callbacks = new Activated[100];
+               d_callbacks.length = 0;
+       }
+
+       private new void append(string                  text,
+                               string?                 name,
+                               string?                 icon_name,
+                               uint                    hint,
+                               owned SidebarActivated? callback,
+                               out Gtk.TreeIter        iter)
+       {
+               if (d_parents != null)
+               {
+                       base.append(out iter, d_parents.data);
+               }
+               else
+               {
+                       base.append(out iter, null);
+               }
+
+               @set(iter,
+                    SidebarColumn.ICON_NAME, icon_name,
+                    SidebarColumn.NAME, name,
+                    hint == SidebarHint.HEADER ? SidebarColumn.HEADER : SidebarColumn.TEXT, text,
+                    SidebarColumn.HINT, hint,
+                    SidebarColumn.SECTION, d_sections,
+                    SidebarColumn.OID, d_oid);
+
+               d_callbacks += new Activated((owned)callback);
+               ++d_oid;
+       }
+
+       public SidebarStore append_dummy(string                  text,
+                                        string?                 name = null,
+                                        string?                 icon_name = null,
+                                        owned SidebarActivated? callback = null)
+       {
+               Gtk.TreeIter iter;
+               append(text, name, icon_name, SidebarHint.DUMMY, (owned)callback, out iter);
+
+               return this;
+       }
+
+       public SidebarStore append_normal(string                  text,
+                                         string?                 name = null,
+                                         string?                 icon_name = null,
+                                         owned SidebarActivated? callback = null)
+       {
+               Gtk.TreeIter iter;
+               append(text, name, icon_name, SidebarHint.NONE, (owned)callback, out iter);
+
+               return this;
+       }
+
+       public SidebarStore append_default(string                  text,
+                                          string?                 name = null,
+                                          string?                 icon_name = null,
+                                          owned SidebarActivated? callback = null)
+       {
+               Gtk.TreeIter iter;
+               append(text, name, icon_name, SidebarHint.DEFAULT, (owned)callback, out iter);
+
+               return this;
+       }
+
+       public SidebarStore begin_header(string  text,
+                                        string? icon_name = null)
+       {
+               Gtk.TreeIter iter;
+
+               append(text, null, icon_name, SidebarHint.HEADER, null, out iter);
+               d_parents.prepend(iter);
+
+               return this;
+       }
+
+       public SidebarStore end_header()
+       {
+               if (d_parents != null)
+               {
+                       d_parents.delete_link(d_parents);
+               }
+
+               return this;
+       }
+
+       public uint begin_section()
+       {
+               d_parents = null;
+               return d_sections;
+       }
+
+       public void end_section()
+       {
+               ++d_sections;
+       }
+
+       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, SidebarColumn.OID, out oid);
+
+               if (d_callbacks[oid] != null)
+               {
+                       d_callbacks[oid].activate(numclick);
+               }
+       }
+}
+
+public class SidebarRendererText : 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);
+
+               var theme = Gtk.IconTheme.get_default();
+
+               Gtk.IconInfo? info = theme.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);
+               }
+       }
+}
+
+[GtkTemplate ( ui = "/org/gnome/gitg/gtk/sidebar/sidebar-view.ui" )]
+public class Sidebar : Gtk.TreeView
+{
+       [GtkChild (name = "column")]
+       private Gtk.TreeViewColumn d_column;
+
+       [GtkChild (name = "renderer_header")]
+       private SidebarRendererText d_renderer_header;
+
+       [GtkChild (name = "renderer_text")]
+       private SidebarRendererText d_renderer_text;
+
+       construct
+       {
+               d_column.set_cell_data_func(d_renderer_header, (layout, cell, model, iter) => {
+                       SidebarHint hint;
+                       model.get(iter, SidebarColumn.HINT, out hint);
+
+                       cell.visible = (hint == SidebarHint.HEADER);
+               });
+
+               d_column.set_cell_data_func(d_renderer_text, (layout, cell, model, iter) => {
+                       SidebarHint hint;
+                       model.get(iter, SidebarColumn.HINT, out hint);
+
+                       cell.visible = (hint != SidebarHint.HEADER);
+
+                       var r = (Gtk.CellRendererText)cell;
+
+                       if (hint == SidebarHint.DUMMY)
+                       {
+                               var col = get_style_context().get_color(Gtk.StateFlags.INSENSITIVE);
+                               r.foreground_rgba = col;
+                       }
+                       else
+                       {
+                               r.foreground_set = false;
+                       }
+               });
+
+               set_row_separator_func((model, iter) => {
+                       SidebarHint hint;
+                       model.get(iter, SidebarColumn.HINT, out hint);
+
+                       return hint == SidebarHint.SEPARATOR;
+               });
+
+               var sel = get_selection();
+
+               sel.set_select_function((sel, model, path, cursel) => {
+                       Gtk.TreeIter iter;
+                       model.get_iter(out iter, path);
+
+                       uint hint;
+
+                       model.get(iter, SidebarColumn.HINT, out hint);
+
+                       return hint != SidebarHint.HEADER && hint != SidebarHint.DUMMY;
+               });
+
+               sel.changed.connect((sel) => {
+                       Gtk.TreeIter iter;
+
+                       if (sel.get_selected(null, out iter))
+                       {
+                               model.activate(iter, 1);
+                       }
+               });
+       }
+
+       public new SidebarStore model
+       {
+               get { return base.get_model() as SidebarStore; }
+               set { base.set_model(value); }
+       }
+}
+
+}
+
+// ex: ts=4 noet
diff --git a/libgitg/resources/resources.xml b/libgitg/resources/resources.xml
index a94611d..4a29d03 100644
--- a/libgitg/resources/resources.xml
+++ b/libgitg/resources/resources.xml
@@ -10,6 +10,9 @@
   <gresource prefix="/org/gnome/gitg/gtk/dash-view">
     <file compressed="true" preprocess="xml-stripblanks">gitg-dash-view-row.ui</file>
   </gresource>
+  <gresource prefix="/org/gnome/gitg/gtk/sidebar">
+    <file compressed="true">sidebar-view.ui</file>
+  </gresource>
 </gresources>
 
 <!-- ex: et ts=2 -->
diff --git a/libgitg/resources/sidebar-view.ui b/libgitg/resources/sidebar-view.ui
new file mode 100644
index 0000000..ae8a86a
--- /dev/null
+++ b/libgitg/resources/sidebar-view.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.3 -->
+  <!-- interface-requires gitg 0.0 -->
+  <!-- interface-requires gd 1.0 -->
+  <template class="GitgSidebar">
+    <property name="model">sidebar_store</property>
+    <property name="show-expanders">False</property>
+    <property name="headers-visible">False</property>
+    <property name="level-indentation">12</property>
+    <child>
+      <object class="GtkTreeViewColumn" id="column">
+        <property name="visible">True</property>
+        <child>
+          <object class="GtkCellRendererText" id="renderer_padding">
+            <property name="xpad">6</property>
+            <property name="visible">True</property>
+          </object>
+          <cell-packing>
+            <property name="expand">False</property>
+          </cell-packing>
+        </child>
+        <child>
+          <object class="GitgSidebarRendererText" id="renderer_header">
+            <property name="ypad">6</property>
+            <property name="weight">700</property>
+          </object>
+          <attributes>
+            <attribute name="icon_name">0</attribute>
+            <attribute name="text">3</attribute>
+          </attributes>
+          <cell-packing>
+            <property name="expand">True</property>
+          </cell-packing>
+        </child>
+        <child>
+          <object class="GitgSidebarRendererText" id="renderer_text">
+          </object>
+          <attributes>
+            <attribute name="icon_name">0</attribute>
+            <attribute name="text">2</attribute>
+          </attributes>
+          <cell-packing>
+            <property name="expand">True</property>
+          </cell-packing>
+        </child>
+      </object>
+    </child>
+  </template>
+  <object class="GitgSidebarStore" id="sidebar_store">
+    <columns>
+      <column type="gchararray"/>
+      <column type="gchararray"/>
+      <column type="gchararray"/>
+      <column type="gchararray"/>
+      <column type="guint"/>
+      <column type="guint"/>
+      <column type="guint"/>
+    </columns>
+  </object>
+</interface>
+
+<!-- ex:set ts=2 et: -->


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