[gnome-boxes] Start the basics of the selection mode



commit 9322602ea6933b89e09a5705125f733243e4eff7
Author: Marc-Andrà Lureau <marcandre lureau gmail com>
Date:   Sat Nov 5 04:16:22 2011 +0100

    Start the basics of the selection mode

 src/app.vala             |   24 +++++++++++++++++++++-
 src/collection-view.vala |   45 +++++++++++++++++++++++++++++++++++--------
 src/display-config.vala  |   12 +++++++++++
 src/selectionbar.vala    |   47 ++++++++++++++++++++++++++++++++++++++++++++-
 src/topbar.vala          |   18 ++++++++++++++++-
 5 files changed, 132 insertions(+), 14 deletions(-)
---
diff --git a/src/app.vala b/src/app.vala
index 0bde562..dd79942 100644
--- a/src/app.vala
+++ b/src/app.vala
@@ -222,9 +222,9 @@ private class Boxes.App: Boxes.UI {
         box.add_constraint (new Clutter.BindConstraint (stage, BindCoordinate.SIZE, 0));
         stage.add_actor (box);
 
-        topbar = new Topbar (this);
         sidebar = new Sidebar (this);
         view = new CollectionView (this, sidebar.category);
+        topbar = new Topbar (this);
 
         selectionbar = new Selectionbar (this);
         selectionbar.actor.add_constraint (new Clutter.AlignConstraint (view.actor, AlignAxis.X_AXIS, 0.5f));
@@ -268,6 +268,8 @@ private class Boxes.App: Boxes.UI {
 
         case UIState.COLLECTION:
             set_main_ui_state ("collection");
+            actor_unpin (topbar.actor);
+            actor_unpin (view.actor);
             actor_remove (topbar.actor);
             actor_remove (sidebar.actor);
             actor_remove (view.actor);
@@ -310,6 +312,24 @@ private class Boxes.App: Boxes.UI {
         return false;
     }
 
+    private bool _selection_mode;
+    public bool selection_mode { get { return _selection_mode; }
+        set {
+            return_if_fail (ui_state == UIState.COLLECTION);
+
+            _selection_mode = value;
+        }
+    }
+
+    public List<CollectionItem> selected_items {
+        owned get { return view.get_selected_items (); }
+    }
+
+    public void remove_item (CollectionItem item) {
+        debug ("FIXME: this is not yet fully implemented");
+        view.remove_item (item);
+    }
+
     private bool on_key_pressed (Widget widget, Gdk.EventKey event) {
         if (event.keyval == F11_KEY) {
             if (fullscreen)
@@ -324,7 +344,7 @@ private class Boxes.App: Boxes.UI {
     }
 
     public bool item_selected (CollectionItem item) {
-        if (ui_state == UIState.COLLECTION) {
+        if (ui_state == UIState.COLLECTION && !selection_mode) {
             current_item = item;
 
             if (current_item is Machine) {
diff --git a/src/collection-view.vala b/src/collection-view.vala
index ad5d119..fa17822 100644
--- a/src/collection-view.vala
+++ b/src/collection-view.vala
@@ -28,7 +28,12 @@ private class Boxes.CollectionView: Boxes.UI {
     public CollectionView (App app, Category category) {
         this.app = app;
         this.category = category;
+
         setup_view ();
+        app.notify["selection-mode"].connect (() => {
+            var mode = app.selection_mode ? Gtk.SelectionMode.MULTIPLE : Gtk.SelectionMode.SINGLE;
+            icon_view.set_selection_mode (mode);
+        });
     }
 
     public void set_over_boxes (Clutter.Actor actor, bool center = false) {
@@ -122,7 +127,7 @@ private class Boxes.CollectionView: Boxes.UI {
         model.set (iter, ModelColumns.TITLE, title);
         model.set (iter, ModelColumns.ITEM, item);
 
-        set_data<Gtk.TreeIter?> ("iter", iter);
+        item.set_data<Gtk.TreeIter?> ("iter", iter);
 
         return iter;
     }
@@ -136,10 +141,11 @@ private class Boxes.CollectionView: Boxes.UI {
         }
 
         var iter = append (machine.pixbuf, machine.name, item);
-        machine.notify["pixbuf"].connect (() => {
+        var pixbuf_id = machine.notify["pixbuf"].connect (() => {
             // apparently iter is stable after insertion/removal/sort
             model.set (iter, ModelColumns.SCREENSHOT, machine.pixbuf);
         });
+        item.set_data<ulong> ("pixbuf_id", pixbuf_id);
 
         item.ui_state = UIState.COLLECTION;
         actor_remove (item.actor);
@@ -147,12 +153,35 @@ private class Boxes.CollectionView: Boxes.UI {
         update_item_visible (item);
     }
 
+    public List<CollectionItem> get_selected_items () {
+        var list = new List<CollectionItem> ();
+        var selected = icon_view.get_selected_items ();
+
+        foreach (var path in selected)
+            list.append (get_item_for_path (path));
+
+        return list;
+    }
+
     public void remove_item (CollectionItem item) {
         var iter = item.get_data<Gtk.TreeIter?> ("iter");
+        var pixbuf_id = item.get_data<ulong> ("pixbuf_id");
+
         return_if_fail (iter != null);
 
         model.remove (iter);
         item.set_data<Gtk.TreeIter?> ("iter", null);
+        item.disconnect (pixbuf_id);
+    }
+
+    private CollectionItem get_item_for_path (Gtk.TreePath path) {
+        Gtk.TreeIter iter;
+        GLib.Value value;
+
+        model.get_iter (out iter, path);
+        model.get_value (iter, ModelColumns.ITEM, out value);
+
+        return (CollectionItem) value;
     }
 
     private void setup_view () {
@@ -180,14 +209,12 @@ private class Boxes.CollectionView: Boxes.UI {
         icon_view_activate_on_single_click (icon_view, true);
         icon_view.set_selection_mode (Gtk.SelectionMode.SINGLE);
         icon_view.item_activated.connect ((view, path) => {
-            Gtk.TreeIter iter;
-            GLib.Value value;
-
-            model.get_iter (out iter, path);
-            model.get_value (iter, ModelColumns.ITEM, out value);
-            app.item_selected ((CollectionItem) value);
+            var item = get_item_for_path (path);
+            app.item_selected (item);
+        });
+        icon_view.selection_changed.connect (() => {
+            app.notify_property ("selected-items");
         });
-
         var pixbuf_renderer = new Gtk.CellRendererPixbuf ();
         pixbuf_renderer.xalign = 0.5f;
         pixbuf_renderer.yalign = 0.5f;
diff --git a/src/display-config.vala b/src/display-config.vala
index 560e4d1..df787e9 100644
--- a/src/display-config.vala
+++ b/src/display-config.vala
@@ -30,6 +30,18 @@ private class Boxes.DisplayConfig: GLib.Object, Boxes.IConfig {
             this.group += " " + subgroup;
     }
 
+    public void add_category (string category) {
+        if (category in categories)
+            return;
+
+        // FIXME: vala bug if in one line
+        string[] categories = categories;
+        categories += category;
+        this.categories = categories;
+
+        save ();
+    }
+
     public void save_display_property (Object display, string property_name) {
         var value = Value (display.get_class ().find_property (property_name).value_type);
 
diff --git a/src/selectionbar.vala b/src/selectionbar.vala
index fdc61ba..1551a73 100644
--- a/src/selectionbar.vala
+++ b/src/selectionbar.vala
@@ -27,7 +27,11 @@ private class Boxes.Selectionbar: GLib.Object {
         toolbar.insert (favorite_btn, 0);
         favorite_btn.icon_name = "emblem-favorite-symbolic";
         favorite_btn.clicked.connect (() => {
-            message ("fixme");
+           foreach (var item in app.selected_items) {
+               var machine = item as Machine;
+               if (machine != null)
+                   machine.config.add_category ("favourite");
+           }
         });
 
         var separator = new Gtk.SeparatorToolItem();
@@ -37,13 +41,52 @@ private class Boxes.Selectionbar: GLib.Object {
         toolbar.insert (remove_btn, 2);
         remove_btn.icon_name = "edit-delete-symbolic";
         remove_btn.clicked.connect (() => {
-            message ("fixme");
+            foreach (var item in app.selected_items)
+                app.remove_item (item);
         });
         toolbar.show_all ();
 
         actor.reactive = true;
         actor.hide ();
 
+        app.notify["selection-mode"].connect (() => {
+            update_visible ();
+        });
+
+        app.notify["selected-items"].connect (() => {
+            update_visible ();
+        });
+
         app.stage.add (actor);
     }
+
+    private void update_visible () {
+        if (!app.selection_mode)
+            visible = false;
+        else
+            visible = app.selected_items.length () > 0;
+    }
+
+    private bool visible {
+        set {
+            if (value)
+                show ();
+            else
+                hide ();
+        }
+    }
+    private void show () {
+        actor.show ();
+        actor.queue_redraw ();
+        actor.animate (Clutter.AnimationMode.LINEAR, Boxes.App.duration,
+                       "opacity", 255);
+    }
+
+    private void hide () {
+        var anim = actor.animate (Clutter.AnimationMode.LINEAR, Boxes.App.duration,
+                                  "opacity", 0);
+        anim.completed.connect (() => {
+            actor.hide ();
+        });
+    }
 }
diff --git a/src/topbar.vala b/src/topbar.vala
index f1beb09..044d1a4 100644
--- a/src/topbar.vala
+++ b/src/topbar.vala
@@ -25,11 +25,16 @@ private class Boxes.Topbar: Boxes.UI {
     private Gtk.ToolButton spinner_btn;
     private Gtk.ToolButton back_btn;
     private Gtk.Button new_btn;
+    private Gtk.Label selection_label;
 
     public Topbar (App app) {
         this.app = app;
 
         setup_topbar ();
+
+        app.notify["selected-items"].connect (() => {
+            update_selection_label ();
+        });
     }
 
     private void setup_topbar () {
@@ -89,6 +94,7 @@ private class Boxes.Topbar: Boxes.UI {
         select_btn.valign = Gtk.Align.CENTER;
         select_btn.clicked.connect (() => {
             notebook.page = TopbarPage.SELECTION;
+            app.selection_mode = true;
         });
         toolbar_end.insert (select_btn, 1);
 
@@ -107,7 +113,8 @@ private class Boxes.Topbar: Boxes.UI {
         toolbar_selection.set_show_arrow (false);
         hbox.pack_start (toolbar_selection, true, true, 0);
 
-        var selection_label = new Gtk.Label ("<i>" + _("Click on items to select them") + "</i>");
+        selection_label = new Gtk.Label ("");
+        update_selection_label ();
         selection_label.use_markup = true;
         tool_item = new Gtk.ToolItem ();
         tool_item.set_expand (true);
@@ -120,6 +127,7 @@ private class Boxes.Topbar: Boxes.UI {
         toolbar_selection.insert (cancel_btn, 1);
         cancel_btn.clicked.connect (() => {
             select_btn.active = false;
+            app.selection_mode = false;
             notebook.page = TopbarPage.COLLECTION;
         });
 
@@ -141,6 +149,14 @@ private class Boxes.Topbar: Boxes.UI {
         app.state.set_key (null, "display", gtk_actor, "y", AnimationMode.EASE_OUT_QUAD, -(float) height, 0, 0);
     }
 
+    private void update_selection_label () {
+        var items = app.selected_items.length ();
+        if (items > 0)
+            selection_label.set_markup ("<b>" + _("%d selected").printf (items) + "</b>");
+        else
+            selection_label.set_markup ("<i>" + _("Click on items to select them") + "</i>");
+    }
+
     public override void ui_state_changed () {
         switch (ui_state) {
         case UIState.COLLECTION:



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