[gitg/wip/actions] Cleanly separate ref actions using interfaces



commit 7866963f20095beb3b37ecb962f35fdf37c19839
Author: Jesse van den Kieboom <jessevdk gmail com>
Date:   Sun Jan 19 19:17:31 2014 +0100

    Cleanly separate ref actions using interfaces

 gitg/Makefile.am                                |    2 +
 gitg/gitg-popup-menu.vala                       |   86 +++++++++++++++
 gitg/gitg-ref-action-delete.vala                |   15 +--
 gitg/gitg-ref-action-rename.vala                |   81 +++++++++++++-
 gitg/gitg-window.vala                           |    7 +-
 gitg/history/gitg-history-action-interface.vala |   64 +++++++++++
 gitg/history/gitg-history.vala                  |  131 +++-------------------
 libgitg-ext/Makefile.am                         |    2 +-
 libgitg-ext/gitg-ext-action-interface.vala      |   29 -----
 libgitg-ext/gitg-ext-action.vala                |    2 -
 libgitg-ext/gitg-ext-application.vala           |    7 +-
 libgitg-ext/gitg-ext-ref-action-interface.vala  |   38 +++++++
 libgitg-ext/gitg-ext-ref-action.vala            |    3 +-
 13 files changed, 295 insertions(+), 172 deletions(-)
---
diff --git a/gitg/Makefile.am b/gitg/Makefile.am
index 6968c0b..6d73f4b 100644
--- a/gitg/Makefile.am
+++ b/gitg/Makefile.am
@@ -57,6 +57,7 @@ gitg_gitg_VALASOURCES =                                               \
        gitg/gitg-resource.vala                                 \
        gitg/gitg-application.vala                              \
        gitg/gitg-plugins-engine.vala                           \
+       gitg/gitg-popup-menu.vala                               \
        gitg/gitg-ui-elements.vala                              \
        gitg/gitg-ref-action-rename.vala                        \
        gitg/gitg-ref-action-delete.vala                        \
@@ -65,6 +66,7 @@ gitg_gitg_VALASOURCES =                                               \
        gitg/preferences/gitg-preferences-interface.vala        \
        gitg/preferences/gitg-preferences-history.vala          \
        gitg/history/gitg-history.vala                          \
+       gitg/history/gitg-history-action-interface.vala         \
        gitg/history/gitg-history-refs-list.vala                \
        gitg/history/gitg-history-paned.vala                    \
        gitg/commit/gitg-commit.vala                            \
diff --git a/gitg/gitg-popup-menu.vala b/gitg/gitg-popup-menu.vala
new file mode 100644
index 0000000..46c9383
--- /dev/null
+++ b/gitg/gitg-popup-menu.vala
@@ -0,0 +1,86 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2014 - 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
+{
+
+class PopupMenu : Object
+{
+       public signal Gtk.Menu? populate_menu(Gdk.EventButton? event);
+
+       private Gtk.Widget? d_widget;
+
+       public PopupMenu(Gtk.Widget widget)
+       {
+               widget.button_press_event.connect(on_button_press_event);
+               widget.popup_menu.connect(on_popup_menu);
+
+               d_widget = widget;
+       }
+
+       public override void dispose()
+       {
+               if (d_widget != null)
+               {
+                       d_widget.button_press_event.disconnect(on_button_press_event);
+                       d_widget.popup_menu.disconnect(on_popup_menu);
+
+                       d_widget = null;
+               }
+       }
+
+       private bool popup_menu(Gtk.Widget widget, Gdk.EventButton? event)
+       {
+               var menu = populate_menu(event);
+
+               if (menu == null)
+               {
+                       return false;
+               }
+
+               var time = (event == null ? Gtk.get_current_event_time() : event.time);
+               var button = (event == null ? 0 : event.button);
+
+               menu.attach_to_widget(widget, null);
+               menu.popup(null, null, null, button, time);
+
+               return true;
+       }
+
+       private bool on_popup_menu(Gtk.Widget widget)
+       {
+               return popup_menu(widget, null);
+       }
+
+       private bool on_button_press_event(Gtk.Widget widget, Gdk.EventButton event)
+       {
+               Gdk.Event *ev = (Gdk.Event *)(&event);
+
+               if (!ev->triggers_context_menu())
+               {
+                       return false;
+               }
+
+               return popup_menu(widget, event);
+       }
+}
+
+}
+
+// ex:set ts=4 noet
diff --git a/gitg/gitg-ref-action-delete.vala b/gitg/gitg-ref-action-delete.vala
index cbc961e..e0016a1 100644
--- a/gitg/gitg-ref-action-delete.vala
+++ b/gitg/gitg-ref-action-delete.vala
@@ -25,10 +25,10 @@ class RefActionDelete : GitgExt.Action, GitgExt.RefAction, Object
        // Do this to pull in config.h before glib.h (for gettext...)
        private const string version = Gitg.Config.VERSION;
 
-       public GitgExt.ActionInterface action_interface { get; construct set; }
-       public Ggit.Ref reference { get; construct set; }
+       public GitgExt.RefActionInterface action_interface { get; construct set; }
+       public Gitg.Ref reference { get; construct set; }
 
-       public RefActionDelete(GitgExt.ActionInterface action_interface, Ggit.Ref reference)
+       public RefActionDelete(GitgExt.RefActionInterface action_interface, Gitg.Ref reference)
        {
                Object(action_interface: action_interface, reference: reference);
        }
@@ -42,12 +42,9 @@ class RefActionDelete : GitgExt.Action, GitgExt.RefAction, Object
        {
                get
                {
-                       var r = reference as Gitg.Ref;
-                       var rtype = r.parsed_name.rtype;
-
-                       return    rtype == RefType.BRANCH
-                              || rtype == RefType.TAG
-                              || rtype == RefType.REMOTE;
+                       return    reference.is_branch()
+                              || reference.is_tag()
+                              || reference.is_remote();
                }
        }
 
diff --git a/gitg/gitg-ref-action-rename.vala b/gitg/gitg-ref-action-rename.vala
index a83e19c..fec2021 100644
--- a/gitg/gitg-ref-action-rename.vala
+++ b/gitg/gitg-ref-action-rename.vala
@@ -25,10 +25,10 @@ class RefActionRename : GitgExt.Action, GitgExt.RefAction, Object
        // Do this to pull in config.h before glib.h (for gettext...)
        private const string version = Gitg.Config.VERSION;
 
-       public GitgExt.ActionInterface action_interface { get; construct set; }
-       public Ggit.Ref reference { get; construct set; }
+       public GitgExt.RefActionInterface action_interface { get; construct set; }
+       public Gitg.Ref reference { get; construct set; }
 
-       public RefActionRename(GitgExt.ActionInterface action_interface, Ggit.Ref reference)
+       public RefActionRename(GitgExt.RefActionInterface action_interface, Gitg.Ref reference)
        {
                Object(action_interface: action_interface, reference: reference);
        }
@@ -47,11 +47,80 @@ class RefActionRename : GitgExt.Action, GitgExt.RefAction, Object
        {
                get
                {
-                       var r = reference as Gitg.Ref;
-                       var rtype = r.parsed_name.rtype;
+                       return    reference.is_branch()
+                              || reference.is_tag();
+               }
+       }
+
+       public void activated()
+       {
+               action_interface.edit_ref_name(reference, on_ref_name_editing_done);
+       }
+
+       private void on_ref_name_editing_done(string new_text, bool cancelled)
+       {
+               if (cancelled)
+               {
+                       return;
+               }
+
+               string orig;
+               string? prefix;
+
+               var pn = reference.parsed_name;
+
+               if (pn.rtype == Gitg.RefType.REMOTE)
+               {
+                       orig = pn.remote_branch;
+                       prefix = pn.prefix + "/" + pn.remote_name + "/";
+               }
+               else
+               {
+                       orig = pn.shortname;
+                       prefix = pn.prefix;
+               }
+
+               if (orig == new_text)
+               {
+                       return;
+               }
 
-                       return rtype == RefType.BRANCH || rtype == RefType.TAG;
+               if (!Ggit.Ref.is_valid_name(@"$prefix$new_text"))
+               {
+                       var msg = _("The specified name ā€˜%sā€™ contains invalid characters").printf(new_text);
+
+                       action_interface.application.show_infobar(_("Invalid name"),
+                                                                 msg,
+                                                                 Gtk.MessageType.ERROR);
+
+                       return;
                }
+
+               var branch = reference as Ggit.Branch;
+               Gitg.Ref? new_ref = null;
+
+               try
+               {
+                       if (branch != null)
+                       {
+                               new_ref = branch.move(new_text, Ggit.CreateFlags.NONE) as Gitg.Ref;
+                       }
+                       else
+                       {
+                               new_ref = reference.rename(new_text, false) as Gitg.Ref;
+                       }
+               }
+               catch (Error e)
+               {
+                       action_interface.application.show_infobar(_("Failed to rename"),
+                                                                 e.message,
+                                                                 Gtk.MessageType.ERROR);
+
+                       return;
+               }
+
+               action_interface.application.repository.clear_refs_cache();
+               action_interface.replace_ref(reference, new_ref);
        }
 }
 
diff --git a/gitg/gitg-window.vala b/gitg/gitg-window.vala
index e506bea..85c14ba 100644
--- a/gitg/gitg-window.vala
+++ b/gitg/gitg-window.vala
@@ -21,7 +21,7 @@ namespace Gitg
 {
 
 [GtkTemplate (ui = "/org/gnome/gitg/ui/gitg-window.ui")]
-public class Window : Gtk.ApplicationWindow, GitgExt.Application, GitgExt.ActionInterface, Initable
+public class Window : Gtk.ApplicationWindow, GitgExt.Application, Initable
 {
        private Settings d_state_settings;
        private Settings d_interface_settings;
@@ -625,11 +625,6 @@ public class Window : Gtk.ApplicationWindow, GitgExt.Application, GitgExt.Action
        {
                owned get { return d_environment; }
        }
-
-       public GitgExt.ActionInterface action_interface
-       {
-               owned get { return this; }
-       }
 }
 
 }
diff --git a/gitg/history/gitg-history-action-interface.vala b/gitg/history/gitg-history-action-interface.vala
new file mode 100644
index 0000000..6ca9360
--- /dev/null
+++ b/gitg/history/gitg-history-action-interface.vala
@@ -0,0 +1,64 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2014 - 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 GitgHistory
+{
+
+class ActionInterface : Object, GitgExt.RefActionInterface
+{
+       public GitgExt.Application application { owned get; construct set; }
+
+       private RefsList d_refs_list;
+
+       public ActionInterface(GitgExt.Application application, RefsList refs_list)
+       {
+               Object(application: application);
+
+               d_refs_list = refs_list;
+       }
+
+       public void add_ref(Gitg.Ref reference)
+       {
+               d_refs_list.add_ref(reference);
+       }
+
+       public void remove_ref(Gitg.Ref reference)
+       {
+               d_refs_list.remove_ref(reference);
+       }
+
+       public void replace_ref(Gitg.Ref old_ref, Gitg.Ref new_ref)
+       {
+               d_refs_list.replace_ref(old_ref, new_ref);
+       }
+
+       public void set_busy(Gitg.Ref reference, bool busy)
+       {
+               // TODO
+       }
+
+       public void edit_ref_name(Gitg.Ref reference, owned GitgExt.RefNameEditingDone done)
+       {
+               d_refs_list.edit(reference, (owned)done);
+       }
+}
+
+}
+
+// ex: ts=4 noet
diff --git a/gitg/history/gitg-history.vala b/gitg/history/gitg-history.vala
index a2aa319..d8cff0d 100644
--- a/gitg/history/gitg-history.vala
+++ b/gitg/history/gitg-history.vala
@@ -36,6 +36,7 @@ namespace GitgHistory
                private Settings d_settings;
 
                private Paned d_main;
+               private Gitg.PopupMenu d_refs_list_popup;
 
                private Gitg.UIElements<GitgExt.HistoryPanel> d_panels;
 
@@ -196,10 +197,8 @@ namespace GitgHistory
                        d_panels = new Gitg.UIElements<GitgExt.HistoryPanel>(extset,
                                                                             d_main.stack_panel);
 
-                       d_main.refs_list.popup_menu.connect(on_refs_list_popup_menu);
-                       d_main.refs_list.button_press_event.connect(on_refs_list_button_press_event);
-
-                       d_main.refs_list.editing_done.connect(on_ref_edited);
+                       d_refs_list_popup = new Gitg.PopupMenu(d_main.refs_list);
+                       d_refs_list_popup.populate_menu.connect(on_refs_list_populate_menu);
 
                        d_main.refs_list.notify["selection"].connect(() => {
                                update_walker();
@@ -211,71 +210,6 @@ namespace GitgHistory
                                                  BindingFlags.SYNC_CREATE);
                }
 
-               private void on_ref_edited(Gitg.Ref reference, string new_text, bool cancelled)
-               {
-                       if (cancelled)
-                       {
-                               return;
-                       }
-
-                       string orig;
-                       string? prefix;
-
-                       var pn = reference.parsed_name;
-
-                       if (pn.rtype == Gitg.RefType.REMOTE)
-                       {
-                               orig = pn.remote_branch;
-                               prefix = pn.prefix + "/" + pn.remote_name + "/";
-                       }
-                       else
-                       {
-                               orig = pn.shortname;
-                               prefix = pn.prefix;
-                       }
-
-                       if (orig == new_text)
-                       {
-                               return;
-                       }
-
-                       if (!Ggit.Ref.is_valid_name(@"$prefix$new_text"))
-                       {
-                               var msg = _("The specified name ā€˜%sā€™ contains invalid 
characters").printf(new_text);
-
-                               application.show_infobar(_("Invalid name"),
-                                                        msg,
-                                                        Gtk.MessageType.ERROR);
-
-                               return;
-                       }
-
-                       var branch = reference as Ggit.Branch;
-                       Gitg.Ref? new_ref = null;
-
-                       try
-                       {
-                               if (branch != null)
-                               {
-                                       new_ref = branch.move(new_text, Ggit.CreateFlags.NONE) as Gitg.Ref;
-                               }
-                               else
-                               {
-                                       new_ref = reference.rename(new_text, false) as Gitg.Ref;
-                               }
-                       }
-                       catch (Error e)
-                       {
-                               application.show_infobar(_("Failed to rename"),
-                                                        e.message,
-                                                        Gtk.MessageType.ERROR);
-
-                               return;
-                       }
-
-                       d_main.refs_list.replace_ref(reference, new_ref);
-               }
-
                private void add_ref_action(Gee.LinkedList<GitgExt.RefAction> actions, GitgExt.RefAction? 
action)
                {
                        if (action.visible)
@@ -284,36 +218,33 @@ namespace GitgHistory
                        }
                }
 
-               private bool refs_list_popup_menu(Gtk.Widget widget, Gdk.EventButton? event)
+               private Gtk.Menu? on_refs_list_populate_menu(Gdk.EventButton? event)
                {
-                       var button = (event == null ? 0 : event.button);
-                       var time = (event == null ? Gtk.get_current_event_time() : event.time);
+                       if (event != null)
+                       {
+                               var row = d_main.refs_list.get_row_at_y((int)event.y);
+                               d_main.refs_list.select_row(row);
+                       }
 
                        var actions = new Gee.LinkedList<GitgExt.RefAction>();
                        var references = d_main.refs_list.selection;
 
                        if (references.is_empty || references.first() != references.last())
                        {
-                               return false;
+                               return null;
                        }
 
                        var reference = references.first();
 
-                       var rename = new Gitg.RefActionRename(application.action_interface,
-                                                             reference);
-
-                       rename.activated.connect(() => { on_rename_activated(rename); });
+                       var af = new ActionInterface(application, d_main.refs_list);
 
-                       add_ref_action(actions, rename);
-
-                       add_ref_action(actions,
-                                      new Gitg.RefActionDelete(application.action_interface,
-                                                               reference));
+                       add_ref_action(actions, new Gitg.RefActionRename(af, reference));
+                       add_ref_action(actions, new Gitg.RefActionDelete(af, reference));
 
                        var exts = new Peas.ExtensionSet(Gitg.PluginsEngine.get_default(),
                                                         typeof(GitgExt.RefAction),
                                                         "action_interface",
-                                                        application.action_interface,
+                                                        af,
                                                         "reference",
                                                         reference);
 
@@ -323,7 +254,7 @@ namespace GitgHistory
 
                        if (actions.is_empty)
                        {
-                               return false;
+                               return null;
                        }
 
                        Gtk.Menu menu = new Gtk.Menu();
@@ -333,35 +264,9 @@ namespace GitgHistory
                                ac.populate_menu(menu);
                        }
 
-                       menu.attach_to_widget(widget, null);
-                       menu.popup(null, null, null, button, time);
-
-                       return true;
-               }
-
-               private void on_rename_activated(Gitg.RefActionRename action)
-               {
-                       d_main.refs_list.begin_editing(action.reference as Gitg.Ref);
-               }
-
-               private bool on_refs_list_popup_menu(Gtk.Widget widget)
-               {
-                       return refs_list_popup_menu(widget, null);
-               }
-
-               private bool on_refs_list_button_press_event(Gtk.Widget widget, Gdk.EventButton event)
-               {
-                       Gdk.Event *ev = (Gdk.Event *)(&event);
-
-                       if (!ev->triggers_context_menu())
-                       {
-                               return false;
-                       }
-
-                       var row = d_main.refs_list.get_row_at_y((int)event.y);
-                       d_main.refs_list.select_row(row);
-
-                       return refs_list_popup_menu(widget, event);
+                       // To keep actions alive as long as the menu is alive
+                       menu.set_data("gitg-ext-actions", actions);
+                       return menu;
                }
 
                private void update_walker()
diff --git a/libgitg-ext/Makefile.am b/libgitg-ext/Makefile.am
index 416d1d7..45663cb 100644
--- a/libgitg-ext/Makefile.am
+++ b/libgitg-ext/Makefile.am
@@ -43,7 +43,7 @@ libgitg_ext_libgitg_ext_1_0_la_LIBADD =       \
 
 libgitg_ext_libgitg_ext_1_0_la_VALASOURCES =           \
        libgitg-ext/gitg-ext-assembly-info.vala         \
-       libgitg-ext/gitg-ext-action-interface.vala      \
+       libgitg-ext/gitg-ext-ref-action-interface.vala  \
        libgitg-ext/gitg-ext-action.vala                \
        libgitg-ext/gitg-ext-commit-action.vala         \
        libgitg-ext/gitg-ext-ref-action.vala            \
diff --git a/libgitg-ext/gitg-ext-action.vala b/libgitg-ext/gitg-ext-action.vala
index d89a1a9..d44fa05 100644
--- a/libgitg-ext/gitg-ext-action.vala
+++ b/libgitg-ext/gitg-ext-action.vala
@@ -22,8 +22,6 @@ namespace GitgExt
 
 public interface Action : Object
 {
-       public abstract ActionInterface action_interface { get; construct set; }
-
        public abstract string label { get; }
        public abstract bool enabled { get; }
        public abstract bool visible { get; }
diff --git a/libgitg-ext/gitg-ext-application.vala b/libgitg-ext/gitg-ext-application.vala
index e22f5d6..f6a9b6c 100644
--- a/libgitg-ext/gitg-ext-application.vala
+++ b/libgitg-ext/gitg-ext-application.vala
@@ -46,11 +46,6 @@ public interface Application : Object
        public abstract GitgExt.Activity? current_activity { owned get; }
 
        /**
-        * The application action interface.
-        */
-       public abstract GitgExt.ActionInterface action_interface { owned get; }
-
-       /**
         * Set the current application main activity.
         *
         * @param id the id of the activity { link UIElement.id}.
@@ -64,6 +59,8 @@ public interface Application : Object
                                          string          secondary_msg,
                                          Gtk.MessageType type);
 
+       public abstract void user_query(UserQuery query);
+
        public abstract Gee.Map<string, string> environment { owned get; }
 }
 
diff --git a/libgitg-ext/gitg-ext-ref-action-interface.vala b/libgitg-ext/gitg-ext-ref-action-interface.vala
new file mode 100644
index 0000000..30ce09a
--- /dev/null
+++ b/libgitg-ext/gitg-ext-ref-action-interface.vala
@@ -0,0 +1,38 @@
+/*
+ * This file is part of gitg
+ *
+ * Copyright (C) 2014 - 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 GitgExt
+{
+
+public delegate void RefNameEditingDone(string new_name, bool cancelled);
+
+public interface RefActionInterface : Object
+{
+       public abstract Application application { owned get; construct set; }
+
+       public abstract void add_ref(Gitg.Ref reference);
+       public abstract void remove_ref(Gitg.Ref reference);
+       public abstract void replace_ref(Gitg.Ref old_ref, Gitg.Ref new_ref);
+       public abstract void set_busy(Gitg.Ref reference, bool busy);
+       public abstract void edit_ref_name(Gitg.Ref reference, owned RefNameEditingDone callback);
+}
+
+}
+
+// ex: ts=4 noet
diff --git a/libgitg-ext/gitg-ext-ref-action.vala b/libgitg-ext/gitg-ext-ref-action.vala
index f5c9ea6..7ed09f4 100644
--- a/libgitg-ext/gitg-ext-ref-action.vala
+++ b/libgitg-ext/gitg-ext-ref-action.vala
@@ -22,7 +22,8 @@ namespace GitgExt
 
 public interface RefAction : Action
 {
-       public abstract Ggit.Ref reference { get; construct set; }
+       public abstract RefActionInterface action_interface { get; construct set; }
+       public abstract Gitg.Ref reference { get; construct set; }
 }
 
 }


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