[gnome-shell: 2/4] Fixes for GenericDisplay



commit 2161e90cda3806c922b73049a8ce70618fbc4e6e
Author: Colin Walters <walters space-ghost verbum org>
Date:   Sat Jul 11 12:26:36 2009 -0400

    Fixes for GenericDisplay
    
    GenericDisplay wasn't quite completely converted to the ShellOverflowList
    model.  Since the list now holds all actors, the indexing/wrapping
    was incorrect.
    
    Add a property which lets us keep track of how many items are displayed,
    use this in genericDisplay.
    
    Avoid setting selectedIndex to -2 when going up with no items.
    
    If we're not displaying any results at all, don't attempt keynav (for now).

 js/ui/genericDisplay.js   |   39 ++++++++++++---------
 js/ui/overlay.js          |    6 +++
 src/shell-overflow-list.c |   81 +++++++++++++++++++++++++++++++++++++++++----
 src/shell-overflow-list.h |    2 +
 4 files changed, 104 insertions(+), 24 deletions(-)
---
diff --git a/js/ui/genericDisplay.js b/js/ui/genericDisplay.js
index 56325c9..3ce3fa5 100644
--- a/js/ui/genericDisplay.js
+++ b/js/ui/genericDisplay.js
@@ -351,7 +351,6 @@ GenericDisplay.prototype = {
         this._matchedItems = [];
         // map<itemId, GenericDisplayItem>
         this._displayedItems = {};
-        this._displayedItemsCount = 0;
         this._selectedIndex = -1;
         // These two are public - .actor is the normal "actor subclass" property,
         // but we also expose a .displayControl actor which is separate.
@@ -397,10 +396,11 @@ GenericDisplay.prototype = {
     // to the bottom one. Returns true if the selection actually moved up, false if it wrapped 
     // around to the bottom.
     selectUp: function() {
+        let count = this._list.displayedCount;
         let selectedUp = true;
         let prev = this._selectedIndex - 1;
         if (this._selectedIndex <= 0) {
-            prev = this._displayedItemsCount - 1; 
+            prev = count - 1;
             selectedUp = false; 
         }
         this._selectIndex(prev);
@@ -411,9 +411,10 @@ GenericDisplay.prototype = {
     // to the top one. Returns true if the selection actually moved down, false if it wrapped 
     // around to the top.
     selectDown: function() {
+        let count = this._list.displayedCount;
         let selectedDown = true;
         let next = this._selectedIndex + 1;
-        if (this._selectedIndex == this._displayedItemsCount - 1) {
+        if (this._selectedIndex == count - 1) {
             next = 0;
             selectedDown = false;
         }
@@ -429,8 +430,9 @@ GenericDisplay.prototype = {
 
     // Selects the last item among the displayed items.
     selectLastItem: function() {
+        let count = this._list.displayedCount;
         if (this.hasItems())
-            this._selectIndex(this._displayedItemsCount - 1);
+            this._selectIndex(count - 1);
     },
 
     // Returns true if the display has some item selected.
@@ -445,7 +447,7 @@ GenericDisplay.prototype = {
 
     // Returns true if the display has any displayed items.
     hasItems: function() {
-        return this._displayedItemsCount > 0;
+        return this._list.displayedCount > 0;
     },
 
     // Updates the displayed items and makes the display actor visible.
@@ -541,15 +543,15 @@ GenericDisplay.prototype = {
                                       }));
         this._list.add_actor(displayItem.actor);
         this._displayedItems[itemId] = displayItem;
-        this._displayedItemsCount++;
     },
 
     // Removes an item identifed by the itemId from the displayed items.
     _removeDisplayItem: function(itemId) {
+        let count = this._list.displayedCount;
         let displayItem = this._displayedItems[itemId];
         let displayItemIndex = this._getIndexOfDisplayedActor(displayItem.actor);
 
-        if (this.hasSelected() && (this._displayedItemsCount == 1 || !this._list.visible)) {
+        if (this.hasSelected() && (count == 1 || !this._list.visible)) {
             this.unsetSelected();
         } else if (this.hasSelected() && displayItemIndex < this._selectedIndex) {
             this.selectUp();
@@ -558,7 +560,6 @@ GenericDisplay.prototype = {
         displayItem.destroy();
 
         delete this._displayedItems[itemId];
-        this._displayedItemsCount--;        
     },
 
     // Removes all displayed items.
@@ -707,6 +708,7 @@ GenericDisplay.prototype = {
      */
     _updateDisplayControl: function(resetDisplayControl) {
         if (resetDisplayControl) {
+            this._selectedIndex = -1;
             this.displayControl.remove_all();
             let nPages = this._list.n_pages;
             let pageNumber = this._list.page;
@@ -744,8 +746,7 @@ GenericDisplay.prototype = {
     // Returns a display item based on its index in the ordering of the
     // display children.
     _findDisplayedByIndex: function(index) {
-        let displayedActors = this._list.get_children();
-        let actor = displayedActors[index];
+        let actor = this._list.get_displayed_actor(index);
         return this._findDisplayedByActor(actor);
     },
 
@@ -775,7 +776,8 @@ GenericDisplay.prototype = {
     // Selects (e.g. highlights) a display item at the provided index,
     // updates this.selectedItemDetails actor, and emits 'selected' signal.
     _selectIndex: function(index) {
-        if (this._selectedIndex != -1) {
+        let count = this._list.displayedCount;
+        if (this._selectedIndex >= 0) {
             let prev = this._findDisplayedByIndex(this._selectedIndex);
             prev.markSelected(false);
             // Calling destroy() gets large image previews released as quickly as
@@ -787,12 +789,15 @@ GenericDisplay.prototype = {
     
             this.selectedItemDetails.remove_all();
         }
-        this._selectedIndex = index;
-        if (index != -1 && index < this._displayedItemsCount) {
-            let item = this._findDisplayedByIndex(index);
-            item.markSelected(true);
-            this.selectedItemDetails.append(item.createDetailsActor(this._availableWidthForItemDetails, this._availableHeightForItemDetails), Big.BoxPackFlags.NONE);  
-            this.emit('selected'); 
+        if (index < count) {
+            this._selectedIndex = index;
+            if (index >= 0) {
+                let item = this._findDisplayedByIndex(index);
+                item.markSelected(true);
+                this.selectedItemDetails.append(item.createDetailsActor(this._availableWidthForItemDetails,
+                   this._availableHeightForItemDetails), Big.BoxPackFlags.NONE);
+                this.emit('selected');
+            }
         }
     }
 };
diff --git a/js/ui/overlay.js b/js/ui/overlay.js
index 999dd05..3c8fb53 100644
--- a/js/ui/overlay.js
+++ b/js/ui/overlay.js
@@ -332,6 +332,8 @@ Dash.prototype = {
                     me.emit('activated');
                 return true;
             } else if (symbol == Clutter.Up) {
+                if (!me._resultsShowing())
+                    return true;
                 // selectUp and selectDown wrap around in their respective displays
                 // too, but there doesn't seem to be any flickering if we first select
                 // something in one display, but then unset the selection, and move
@@ -342,13 +344,17 @@ Dash.prototype = {
                   me._resultsAppsSection.display.selectUp();
                 else
                   me._resultsDocsSection.display.selectUp();
+                return true;
             } else if (symbol == Clutter.Down) {
+                if (!me._resultsShowing())
+                    return true;
                 if (me._resultsDocsSection.display.hasSelected())
                   me._resultsDocsSection.display.selectDown();
                 else if (me._resultsAppsSection.display.hasItems())
                   me._resultsAppsSection.display.selectDown();
                 else
                   me._resultsDocsSection.display.selectDown();
+                return true;
             }
             return false;
         });
diff --git a/src/shell-overflow-list.c b/src/shell-overflow-list.c
index b1f418e..8565a33 100644
--- a/src/shell-overflow-list.c
+++ b/src/shell-overflow-list.c
@@ -10,6 +10,7 @@ enum {
   PROP_0,
   PROP_SPACING,
   PROP_ITEM_HEIGHT,
+  PROP_DISPLAYED_COUNT,
   PROP_PAGE,
   PROP_N_PAGES
 };
@@ -20,9 +21,37 @@ struct _ShellOverflowListPrivate {
   guint page;
   guint n_pages;
   guint items_per_page;
+  guint displayed_count;
 };
 
 static void
+recalc_displayed_count (ShellOverflowList *self)
+{
+  GList *children;
+  int n_children;
+  int displayed_count;
+  int page, n_pages;
+
+  children = clutter_container_get_children (CLUTTER_CONTAINER (self));
+  n_children = g_list_length (children);
+  g_list_free (children);
+
+  page = self->priv->page;
+  n_pages = self->priv->n_pages;
+  if (page < n_pages-1)
+    displayed_count = self->priv->items_per_page;
+  else if (n_pages > 0)
+    displayed_count = n_children - (self->priv->items_per_page * (n_pages-1));
+  else
+    displayed_count = 0;
+  if (displayed_count != self->priv->displayed_count)
+    {
+      self->priv->displayed_count = displayed_count;
+      g_object_notify (G_OBJECT (self), "displayed-count");
+    }
+}
+
+static void
 shell_overflow_list_set_property(GObject         *object,
                                  guint            prop_id,
                                  const GValue    *value,
@@ -43,6 +72,7 @@ shell_overflow_list_set_property(GObject         *object,
         break;
       case PROP_PAGE:
         priv->page = g_value_get_uint (value);
+        recalc_displayed_count (self);
         clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
         break;
     default:
@@ -68,6 +98,9 @@ shell_overflow_list_get_property(GObject         *object,
     case PROP_ITEM_HEIGHT:
       g_value_set_float (value, priv->spacing);
       break;
+    case PROP_DISPLAYED_COUNT:
+      g_value_set_uint (value, priv->displayed_count);
+      break;
     case PROP_PAGE:
       g_value_set_uint (value, priv->page);
       break;
@@ -135,12 +168,15 @@ shell_overflow_list_allocate (ClutterActor           *actor,
     }
 
   priv->items_per_page = n_fits;
+
   if (n_pages != priv->n_pages)
     {
       priv->n_pages = n_pages;
       g_object_notify (G_OBJECT (self), "n-pages");
     }
 
+  recalc_displayed_count (self);
+
   g_list_free (children);
 }
 
@@ -173,14 +209,9 @@ static void
 shell_overflow_list_pick (ClutterActor       *actor,
                           const ClutterColor *color)
 {
-  ShellOverflowList *self = SHELL_OVERFLOW_LIST (actor);
-  ShellOverflowListPrivate *priv = self->priv;
-  GList *children, *iter;
-  int i;
-
   (CLUTTER_ACTOR_CLASS (g_type_class_peek (clutter_actor_get_type ())))->pick (actor, color);
 
-  shell_overflow_list_paint (self);
+  shell_overflow_list_paint (actor);
 }
 
 
@@ -290,6 +321,14 @@ shell_overflow_list_class_init (ShellOverflowListClass *klass)
                                                         G_PARAM_READWRITE));
 
   g_object_class_install_property (gobject_class,
+                                   PROP_DISPLAYED_COUNT,
+                                   g_param_spec_uint ("displayed-count",
+                                                      "Displayed count",
+                                                      "Number of items displayed on current page",
+                                                      0, G_MAXUINT, 0,
+                                                      G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class,
                                    PROP_PAGE,
                                    g_param_spec_uint ("page",
                                                       "Page number",
@@ -301,7 +340,7 @@ shell_overflow_list_class_init (ShellOverflowListClass *klass)
                                    PROP_N_PAGES,
                                    g_param_spec_uint ("n-pages",
                                                       "Number of pages",
-                                                      "Number of pagest",
+                                                      "Number of pages",
                                                        0, G_MAXUINT, 0,
                                                        G_PARAM_READABLE));
 
@@ -318,3 +357,31 @@ shell_overflow_list_init (ShellOverflowList *self)
   self->priv->n_pages = 1;
   self->priv->page = 0;
 }
+
+/**
+ * shell_overflow_list_get_displayed_actor:
+ * @self:
+ * @index: 0-based index for displayed list
+ *
+ * Returns the actor at the given index on the current page.
+ *
+ * Return value: (transfer none): #ClutterActor at index
+ */
+ClutterActor *
+shell_overflow_list_get_displayed_actor (ShellOverflowList *self,
+                                         guint              index)
+{
+  GList *children, *iter;
+
+  children = clutter_container_get_children (CLUTTER_CONTAINER (self));
+
+  if (children == NULL)
+    return NULL;
+
+  iter = g_list_nth (children, index + (self->priv->page * self->priv->items_per_page));
+
+  if (!iter)
+    return NULL;
+
+  return iter->data;
+}
diff --git a/src/shell-overflow-list.h b/src/shell-overflow-list.h
index 9d9ea89..c8a912e 100644
--- a/src/shell-overflow-list.h
+++ b/src/shell-overflow-list.h
@@ -36,6 +36,8 @@ struct _ShellOverflowListClass
 
 GType shell_overflow_list_get_type (void) G_GNUC_CONST;
 
+ClutterActor *shell_overflow_list_get_displayed_actor (ShellOverflowList *list, guint index);
+
 G_END_DECLS
 
 #endif /* __SHELL_OVERFLOW_LIST_H__ */



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