[gnome-documents] selections: Revamp the OrganizeCollectionView as per new designs



commit 99de476f6adbc6333d9580e45cf375a56be8487a
Author: Debarshi Ray <debarshir gnome org>
Date:   Tue May 21 18:07:25 2013 +0200

    selections: Revamp the OrganizeCollectionView as per new designs
    
    collections-placeholder icon made by Andreas Nilsson.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=687651

 src/gnome-documents.gresource.xml         |    1 +
 src/resources/collections-placeholder.png |  Bin 0 -> 686 bytes
 src/selections.js                         |  247 +++++++++++++++--------------
 3 files changed, 130 insertions(+), 118 deletions(-)
---
diff --git a/src/gnome-documents.gresource.xml b/src/gnome-documents.gresource.xml
index 4b2fe7d..aee6f70 100644
--- a/src/gnome-documents.gresource.xml
+++ b/src/gnome-documents.gresource.xml
@@ -5,6 +5,7 @@
     <file alias="preview-menu.ui" preprocess="xml-stripblanks">resources/preview-menu.ui</file>
     <file alias="selection-menu.ui" preprocess="xml-stripblanks">resources/selection-menu.ui</file>
     <file alias="preview-context-menu.ui" 
preprocess="xml-stripblanks">resources/preview-context-menu.ui</file>
+    <file alias="collections-placeholder.png" 
preprocess="to-pixdata">resources/collections-placeholder.png</file>
     <file alias="thumbnail-frame.png" preprocess="to-pixdata">resources/thumbnail-frame.png</file>
   </gresource>
 </gresources>
diff --git a/src/resources/collections-placeholder.png b/src/resources/collections-placeholder.png
new file mode 100644
index 0000000..1012965
Binary files /dev/null and b/src/resources/collections-placeholder.png differ
diff --git a/src/selections.js b/src/selections.js
index 0dc0a5d..41b795d 100644
--- a/src/selections.js
+++ b/src/selections.js
@@ -43,6 +43,7 @@ const Lang = imports.lang;
 const Signals = imports.signals;
 
 const _COLLECTION_PLACEHOLDER_ID = 'collection-placeholder';
+const _SEPARATOR_PLACEHOLDER_ID = 'separator-placeholder';
 
 // fetch all the collections a given item is part of
 const FetchCollectionsJob = new Lang.Class({
@@ -324,13 +325,26 @@ const OrganizeCollectionModel = new Lang.Class({
             [ GObject.TYPE_STRING,
               GObject.TYPE_STRING,
               GObject.TYPE_INT ]);
-        this._placeholderRef = null;
 
         this._collAddedId = Application.collectionManager.connect('item-added',
             Lang.bind(this, this._onCollectionAdded));
         this._collRemovedId = Application.collectionManager.connect('item-removed',
             Lang.bind(this, this._onCollectionRemoved));
 
+        let iter;
+
+        // add the placeholder
+        iter = this.model.append();
+        this.model.set(iter,
+            [ 0, 1, 2 ],
+            [ _COLLECTION_PLACEHOLDER_ID, '', OrganizeCollectionState.ACTIVE ]);
+
+        // add the separator
+        iter = this.model.append();
+        this.model.set(iter,
+            [ 0, 1, 2 ],
+            [ _SEPARATOR_PLACEHOLDER_ID, '', OrganizeCollectionState.ACTIVE ]);
+
         // populate the model
         let job = new FetchCollectionStateForSelectionJob();
         job.run(Lang.bind(this, this._onFetchCollectionStateForSelection));
@@ -358,8 +372,6 @@ const OrganizeCollectionModel = new Lang.Class({
     },
 
     _onFetchCollectionStateForSelection: function(collectionState) {
-        this.removePlaceholder();
-
         for (idx in collectionState) {
             let item = Application.collectionManager.getItemById(idx);
 
@@ -397,45 +409,6 @@ const OrganizeCollectionModel = new Lang.Class({
         this._refreshState();
     },
 
-    addPlaceholder: function() {
-        this.removePlaceholder();
-
-        let iter = this.model.append();
-        this.model.set(iter,
-            [ 0, 1, 2 ],
-            [ _COLLECTION_PLACEHOLDER_ID, '', OrganizeCollectionState.ACTIVE ]);
-
-        let placeholderPath = this.model.get_path(iter);
-        if (placeholderPath != null)
-            this._placeholderRef = Gtk.TreeRowReference.new(this.model, placeholderPath);
-
-        return placeholderPath;
-    },
-
-    removePlaceholder: function() {
-        // remove the placeholder if it's here
-        if (this._placeholderRef) {
-            let placeholderPath = this._placeholderRef.get_path();
-            let placeholderIter = this.model.get_iter(placeholderPath)[1];
-
-            if (placeholderIter)
-                this.model.remove(placeholderIter);
-
-            this._placeholderRef = null;
-        }
-    },
-
-    getPlaceholder: function(forget) {
-        let ret = null;
-
-        if (this._placeholderRef)
-            ret = this._placeholderRef.get_path();
-        if (forget)
-            this._placeholderRef = null;
-
-        return ret;
-    },
-
     destroy: function() {
         if (this._collAddedId != 0) {
             Application.collectionManager.disconnect(this._collAddedId);
@@ -455,19 +428,68 @@ const OrganizeCollectionView = new Lang.Class({
     _init: function() {
         this._choiceConfirmed = false;
 
+        this.widget = new Gtk.Overlay();
+
+        this._sw = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN,
+                                            margin_left: 5,
+                                            margin_right: 5,
+                                            margin_bottom: 3 });
+        this.widget.add(this._sw);
+
         this._model = new OrganizeCollectionModel();
-        this.widget = new Gtk.TreeView({ headers_visible: false,
-                                         vexpand: true,
-                                         hexpand: true });
-        this.widget.set_model(this._model.model);
+        this._view = new Gtk.TreeView({ headers_visible: false,
+                                        vexpand: true,
+                                        hexpand: true });
+        this._view.set_model(this._model.model);
+        this._view.set_row_separator_func(Lang.bind(this,
+            function(model, iter) {
+                let id = model.get_value(iter, OrganizeModelColumns.ID);
+                return (id == _SEPARATOR_PLACEHOLDER_ID);
+            }));
+        this._sw.add(this._view);
+
+        this._msgGrid = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL,
+                                       row_spacing: 12,
+                                       halign: Gtk.Align.CENTER,
+                                       margin_top: 64 });
+        this.widget.add_overlay(this._msgGrid);
+
+        this._icon = new Gtk.Image({ resource: '/org/gnome/documents/collections-placeholder.png' });
+        this._msgGrid.add(this._icon);
+
+        this._label = new Gtk.Label({
+            justify: Gtk.Justification.CENTER,
+            label: _("You don't have any collections yet. Enter a new collection name above."),
+            max_width_chars: 32,
+            wrap: true });
+        this._label.get_style_context().add_class('dim-label');
+        this._msgGrid.add(this._label);
+
+        // show the overlay only if there aren't any collections in the model
+        this._msgGrid.visible = (this._model.model.iter_n_children(null) < 2);
+        this._model.model.connect('row-inserted', Lang.bind(this,
+            function() {
+                this._msgGrid.hide();
+            }));
+
+        // force the editable row to be unselected
+        this.selection = this._view.get_selection();
+        let selectionChangedId = this.selection.connect('changed', Lang.bind(this,
+            function() {
+                this.selection.unselect_all();
+                if (selectionChangedId != 0) {
+                    this.selection.disconnect(selectionChangedId);
+                    selectionChangedId = 0;
+                }
+            }));
 
-        this.widget.connect('destroy', Lang.bind(this,
+        this._view.connect('destroy', Lang.bind(this,
             function() {
                 this._model.destroy();
             }));
 
         this._viewCol = new Gtk.TreeViewColumn();
-        this.widget.append_column(this._viewCol);
+        this._view.append_column(this._viewCol);
 
         // checkbox
         this._rendererCheck = new Gtk.CellRendererToggle();
@@ -476,11 +498,17 @@ const OrganizeCollectionView = new Lang.Class({
                                          Lang.bind(this, this._checkCellFunc));
         this._rendererCheck.connect('toggled', Lang.bind(this, this._onCheckToggled));
 
+        // icon
+        this._rendererIcon = new Gtk.CellRendererPixbuf();
+        this._viewCol.pack_start(this._rendererIcon, false);
+        this._viewCol.set_cell_data_func(this._rendererIcon,
+                                         Lang.bind(this, this._iconCellFunc));
+
         // item name
         this._rendererText = new Gtk.CellRendererText();
         this._viewCol.pack_start(this._rendererText, true);
-        this._viewCol.add_attribute(this._rendererText,
-                                    'text', OrganizeModelColumns.NAME);
+        this._viewCol.set_cell_data_func(this._rendererText,
+                                         Lang.bind(this, this._textCellFunc));
 
         this._rendererDetail = new Gd.StyledTextRenderer({ xpad: 16 });
         this._rendererDetail.add_class('dim-label');
@@ -491,7 +519,7 @@ const OrganizeCollectionView = new Lang.Class({
         this._rendererText.connect('edited', Lang.bind(this, this._onTextEdited));
         this._rendererText.connect('editing-canceled', Lang.bind(this, this._onTextEditCanceled));
 
-        this.widget.show();
+        this._view.show();
     },
 
     _onCheckToggled: function(renderer, pathStr) {
@@ -508,43 +536,37 @@ const OrganizeCollectionView = new Lang.Class({
             }));
     },
 
-    _onNewCollectionCreated: function(createdUrn) {
-        if (!createdUrn) {
-            this._model.removePlaceholder();
-            return;
-        }
-
-        let path = this._model.getPlaceholder(true);
-        if (!path)
-            return;
-
-        let iter = this._model.model.get_iter(path)[1];
-        this._model.model.set_value(iter, OrganizeModelColumns.ID, createdUrn);
-
-        let job = new SetCollectionForSelectionJob(createdUrn, true);
-        job.run(null);
-    },
-
-    _onTextEditedReal: function(cell, path, newText) {
-        cell.editable = false;
+    _onTextEditedReal: function(cell, newText) {
+        //cell.editable = false;
 
         if (!newText || newText == '') {
             // don't insert collections with empty names
-            this._model.removePlaceholder();
             return;
         }
 
         // update the new name immediately
-        let iter = this._model.model.get_iter(path)[1];
+        let iter = this._model.model.append();
         this._model.model.set_value(iter, OrganizeModelColumns.NAME, newText);
 
+        // force the editable row to be unselected
+        this.selection.unselect_all();
+
         // actually create the new collection
         let job = new CreateCollectionJob(newText);
-        job.run(Lang.bind(this, this._onNewCollectionCreated));
+        job.run(Lang.bind(this,
+            function(createdUrn) {
+                if (!createdUrn)
+                    return;
+
+                this._model.model.set_value(iter, OrganizeModelColumns.ID, createdUrn);
+
+                let job = new SetCollectionForSelectionJob(createdUrn, true);
+                job.run(null);
+            }));
     },
 
     _onTextEdited: function(cell, pathStr, newText) {
-        this._onTextEditedReal(cell, Gtk.TreePath.new_from_string(pathStr), newText);
+        this._onTextEditedReal(cell, newText);
     },
 
     _onTextEditCanceled: function(cell) {
@@ -552,12 +574,8 @@ const OrganizeCollectionView = new Lang.Class({
             this._choiceConfirmed = false;
 
             let entry = this._viewCol.cell_area.get_edit_widget();
-            let path = this._model.getPlaceholder(false);
-
-            if (entry && path)
-                this._onTextEditedReal(cell, path, entry.get_text());
-        } else {
-            this._model.removePlaceholder();
+            if (entry)
+                this._onTextEditedReal(cell, entry.get_text());
         }
     },
 
@@ -570,6 +588,27 @@ const OrganizeCollectionView = new Lang.Class({
         cell.visible = (id != _COLLECTION_PLACEHOLDER_ID);
     },
 
+    _iconCellFunc: function(col, cell, model, iter) {
+        let id = model.get_value(iter, OrganizeModelColumns.ID);
+
+        cell.icon_name = "gtk-add";
+        cell.visible = (id == _COLLECTION_PLACEHOLDER_ID);
+    },
+
+    _textCellFunc: function(col, cell, model, iter) {
+        let id = model.get_value(iter, OrganizeModelColumns.ID);
+        let name = model.get_value(iter, OrganizeModelColumns.NAME);
+
+        if (id == _COLLECTION_PLACEHOLDER_ID) {
+            cell.editable = true;
+            cell.text = '';
+            cell.placeholder_text = _("Create new collection");
+        } else {
+            cell.editable = false;
+            cell.text = name;
+        }
+    },
+
     _detailCellFunc: function(col, cell, model, iter) {
         let id = model.get_value(iter, OrganizeModelColumns.ID);
         let item = Application.collectionManager.getItemById(id);
@@ -583,25 +622,11 @@ const OrganizeCollectionView = new Lang.Class({
         }
     },
 
-    addCollection: function() {
-        let path = this._model.addPlaceholder();
-
-        if (!path)
-            return;
-
-        this._rendererText.editable = true;
-        this.widget.set_cursor_on_cell(path, this._viewCol, this._rendererText, true);
-    },
-
     confirmedChoice: function() {
         this._choiceConfirmed = true;
     }
 });
 
-const OrganizeCollectionDialogResponse = {
-    ADD: 1
-};
-
 const OrganizeCollectionDialog = new Lang.Class({
     Name: 'OrganizeCollectionDialog',
 
@@ -611,43 +636,31 @@ const OrganizeCollectionDialog = new Lang.Class({
                                        destroy_with_parent: true,
                                        default_width: 400,
                                        default_height: 250,
-        // Translators: "Organize" refers to documents in this context
-                                       title: C_("Dialog Title", "Organize") });
+        // Translators: "Collections" refers to documents in this context
+                                       title: C_("Dialog Title", "Collections") });
 
-        this.widget.add_button('gtk-add', OrganizeCollectionDialogResponse.ADD);
-        let okButton = this.widget.add_button('gtk-ok', Gtk.ResponseType.OK);
-        this.widget.set_default_response(Gtk.ResponseType.OK);
+        let closeButton = this.widget.add_button('gtk-close', Gtk.ResponseType.CLOSE);
+        this.widget.set_default_response(Gtk.ResponseType.CLOSE);
 
         let contentArea = this.widget.get_content_area();
-        let sw = new Gtk.ScrolledWindow({ shadow_type: Gtk.ShadowType.IN,
-                                          margin_left: 5,
-                                          margin_right: 5,
-                                          margin_bottom: 3 });
         let collView = new OrganizeCollectionView();
-
-        sw.add(collView.widget);
-        contentArea.add(sw);
+        contentArea.add(collView.widget);
 
         // HACK:
-        // - We want clicking on "OK" to add the typed-in collection if we're editing.
+        // - We want clicking on "Close" to add the typed-in collection if we're
+        //   editing.
         // - Unfortunately, since we focus out of the editable entry in order to
         //   click the button, we'll get an editing-canceled signal on the renderer
         //   from GTK. As this handler will run before focus-out, we here signal the
         //   view to ignore the next editing-canceled signal and add the collection in
         //   that case instead.
         //
-        okButton.connect('button-press-event', Lang.bind(this,
+        closeButton.connect('button-press-event', Lang.bind(this,
             function() {
                 collView.confirmedChoice();
                 return false;
             }));
 
-        this.widget.connect('response', Lang.bind(this,
-            function(widget, response) {
-                if (response == OrganizeCollectionDialogResponse.ADD)
-                    collView.addCollection();
-            }));
-
         this.widget.show_all();
     }
 });
@@ -898,10 +911,8 @@ const SelectionToolbar = new Lang.Class({
 
         dialog.widget.connect('response', Lang.bind(this,
             function(widget, response) {
-                if (response == Gtk.ResponseType.OK) {
-                    dialog.widget.destroy();
-                    this._fadeIn();
-                }
+                dialog.widget.destroy();
+                this._fadeIn();
             }));
     },
 


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