Bug 896766 - Add metro_viewstate_changed handling to toggle grid selectability. r=rsilveira
authorSam Foster <sfoster@mozilla.com>
Mon, 29 Jul 2013 15:03:16 -0700
changeset 140457 7944ca804692c68a1bb69d2631ce9c05bbbc80a6
parent 140456 a297a9937018a7e54a11dc5e756103406a7205e0
child 140458 c2dc8dbb77ef08ca3da5dbcf76a04fd6c699228d
push id25030
push userryanvm@gmail.com
push dateTue, 30 Jul 2013 17:07:39 +0000
treeherdermozilla-central@129ce98f4cb2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrsilveira
bugs896766
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 896766 - Add metro_viewstate_changed handling to toggle grid selectability. r=rsilveira
browser/metro/base/content/RemoteTabs.js
browser/metro/base/content/TopSites.js
browser/metro/base/content/bindings/grid.xml
browser/metro/base/content/bookmarks.js
browser/metro/base/content/history.js
browser/metro/modules/View.jsm
--- a/browser/metro/base/content/RemoteTabs.js
+++ b/browser/metro/base/content/RemoteTabs.js
@@ -23,35 +23,41 @@ function RemoteTabsView(aSet, aSetUIAcce
   this._set = aSet;
   this._set.controller = this;
   this._uiAccessElements = aSetUIAccessList;
 
   // Sync uses special voodoo observers.
   // If you want to change this code, talk to the fx-si team
   Weave.Svc.Obs.add("weave:service:sync:finish", this);
   Weave.Svc.Obs.add("weave:service:start-over", this);
+
+  Services.obs.addObserver(this, "metro_viewstate_changed", false);
+
   if (this.isSyncEnabled() ) {
     this.populateGrid();
   }
   else {
     this.setUIAccessVisible(false);
   }
 }
 
-RemoteTabsView.prototype = {
+RemoteTabsView.prototype = Util.extend(Object.create(View.prototype), {
   _set: null,
   _uiAccessElements: [],
 
   handleItemClick: function tabview_handleItemClick(aItem) {
     let url = aItem.getAttribute("value");
     BrowserUI.goToURI(url);
   },
 
   observe: function(subject, topic, data) {
     switch (topic) {
+      case "metro_viewstate_changed":
+        this.onViewStateChange(data);
+        break;
       case "weave:service:sync:finish":
         this.populateGrid();
         break;
       case "weave:service:start-over":
         this.setUIAccessVisible(false);
         break;
     }
   },
@@ -89,25 +95,26 @@ RemoteTabsView.prototype = {
         item.setAttribute("iconURI", Weave.Utils.getIcon(icon));
 
       }, this);
     }
     this.setUIAccessVisible(show);
   },
 
   destruct: function destruct() {
+    Services.obs.removeObserver(this, "metro_viewstate_changed");
     Weave.Svc.Obs.remove("weave:engine:sync:finish", this);
     Weave.Svc.Obs.remove("weave:service:logout:start-over", this);
   },
 
   isSyncEnabled: function isSyncEnabled() {
     return (Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED);
   }
 
-};
+});
 
 let RemoteTabsStartView = {
   _view: null,
   get _grid() { return document.getElementById("start-remotetabs-grid"); },
 
   init: function init() {
     let vbox = document.getElementById("start-remotetabs");
     let uiList = [vbox];
--- a/browser/metro/base/content/TopSites.js
+++ b/browser/metro/base/content/TopSites.js
@@ -361,40 +361,41 @@ TopSitesView.prototype = Util.extend(Obj
   },
 
   isFirstRun: function isFirstRun() {
     return prefs.getBoolPref("browser.firstrun.show.localepicker");
   },
 
   destruct: function destruct() {
     Services.obs.removeObserver(this, "Metro:RefreshTopsiteThumbnail");
+    Services.obs.removeObserver(this, "metro_viewstate_changed");
     PageThumbs.removeExpirationFilter(this);
-    Services.obs.removeObserver(this, "metro_viewstate_changed");
     window.removeEventListener('MozAppbarDismissing', this, false);
   },
 
   // nsIObservers
   observe: function (aSubject, aTopic, aState) {
     switch(aTopic) {
       case "Metro:RefreshTopsiteThumbnail":
         this.forceReloadOfThumbnail(aState);
         break;
       case "metro_viewstate_changed":
+        this.onViewStateChange(aState);
         for (let item of this._set.children) {
           if (aState == "snapped") {
             item.removeAttribute("tiletype");
           } else {
             item.setAttribute("tiletype", "thumbnail");
           }
         }
         break;
     }
   },
+
   // nsINavHistoryObserver
-
   onBeginUpdateBatch: function() {
   },
 
   onEndUpdateBatch: function() {
   },
 
   onVisit: function(aURI, aVisitID, aTime, aSessionID,
                     aReferringID, aTransitionType) {
--- a/browser/metro/base/content/bindings/grid.xml
+++ b/browser/metro/base/content/bindings/grid.xml
@@ -96,28 +96,28 @@
               return;
 
             if ("single" == this.getAttribute("seltype")) {
               // we'll republish this as a selectionchange event on the grid
               aEvent.stopPropagation();
               this.selectItem(aItem);
             }
 
-	    if (this.controller && this.controller.handleItemClick)
+            if (this.controller && this.controller.handleItemClick)
               this.controller.handleItemClick(aItem, aEvent);
           ]]>
         </body>
       </method>
 
       <method name="handleItemContextMenu">
         <parameter name="aItem"/>
         <parameter name="aEvent"/>
         <body>
           <![CDATA[
-            if(!this.isBound)
+            if(!this.isBound || this.suppressOnSelect)
               return;
             // we'll republish this as a selectionchange event on the grid
             aEvent.stopPropagation();
             this.toggleItemSelection(aItem);
           ]]>
         </body>
       </method>
 
@@ -501,18 +501,16 @@
             this._scheduledArrangeItemsTries = 0;
             // pass over any params
             return this.arrangeItems.apply(this, arguments);
           ]]>
         </body>
       </method>
 
       <!-- Inteface to suppress selection events -->
-
-      <field name="_suppressOnSelect"/>
       <property name="suppressOnSelect"
                   onget="return this.getAttribute('suppressonselect') == 'true';"
                   onset="this.setAttribute('suppressonselect', val);"/>
       <property name="crossSlideBoundary"
           onget="return this.hasAttribute('crossslideboundary')? this.getAttribute('crossslideboundary') : Infinity;"/>
 
     <!-- Internal methods -->
       <field name="_xslideHandler"/>
@@ -634,17 +632,17 @@
 
       <method name="_fireEvent">
         <parameter name="aType"/>
         <body>
           <![CDATA[
             switch (aType) {
               case "select" :
               case "selectionchange" :
-                if (this.suppressOnSelect || this._suppressOnSelect)
+                if (this.suppressOnSelect)
                   return;
                 break;
               case "arranged" :
                 break;
             }
 
             let event = document.createEvent("Events");
             event.initEvent(aType, true, true);
@@ -785,16 +783,18 @@
               event.target.removeAttribute('crosssliding');
               event.target.style.removeProperty('transform');
               break;
           }
         ]]>
       </handler>
       <handler event="MozCrossSlideSelect">
         <![CDATA[
+          if (this.suppressOnSelect)
+            return;
           this.toggleItemSelection(event.target);
         ]]>
       </handler>
     </handlers>
   </binding>
 
   <binding id="richgrid-item">
     <content>
--- a/browser/metro/base/content/bookmarks.js
+++ b/browser/metro/base/content/bookmarks.js
@@ -82,16 +82,17 @@ function BookmarksView(aSet, aLimit, aRo
   this._limit = aLimit;
   this._filterUnpinned = aFilterUnpinned;
   this._bookmarkService = PlacesUtils.bookmarks;
   this._navHistoryService = gHistSvc;
 
   this._changes = new BookmarkChangeListener(this);
   this._pinHelper = new ItemPinHelper("metro.bookmarks.unpinned");
   this._bookmarkService.addObserver(this._changes, false);
+  Services.obs.addObserver(this, "metro_viewstate_changed", false);
   window.addEventListener('MozAppbarDismissing', this, false);
   window.addEventListener('BookmarksNeedsRefresh', this, false);
 
   this.root = aRoot;
 }
 
 BookmarksView.prototype = Util.extend(Object.create(View.prototype), {
   _limit: null,
@@ -259,16 +260,17 @@ BookmarksView.prototype = Util.extend(Ob
   removeBookmark: function bv_removeBookmark(aBookmarkId) {
     let item = this._getItemForBookmarkId(aBookmarkId);
     let index = this._set.getIndexOfItem(item);
     this._set.removeItemAt(index, this._inBatch);
   },
 
   destruct: function bv_destruct() {
     this._bookmarkService.removeObserver(this._changes);
+    Services.obs.removeObserver(this, "metro_viewstate_changed");
     window.removeEventListener('MozAppbarDismissing', this, false);
     window.removeEventListener('BookmarksNeedsRefresh', this, false);
   },
 
   doActionOnSelectedTiles: function bv_doActionOnSelectedTiles(aActionName, aEvent) {
     let tileGroup = this._set;
     let selectedTiles = tileGroup.selectedItems;
 
@@ -326,16 +328,25 @@ BookmarksView.prototype = Util.extend(Ob
       default:
         return;
     }
 
     // Send refresh event so all view are in sync.
     this._sendNeedsRefresh();
   },
 
+  // nsIObservers
+  observe: function (aSubject, aTopic, aState) {
+    switch(aTopic) {
+      case "metro_viewstate_changed":
+        this.onViewStateChange(aState);
+        break;
+    }
+  },
+
   handleEvent: function bv_handleEvent(aEvent) {
     switch (aEvent.type){
       case "MozAppbarDismissing":
         // If undo wasn't pressed, time to do definitive actions.
         if (this._toRemove) {
           for (let bookmarkId of this._toRemove) {
             this._bookmarkService.removeItem(bookmarkId);
           }
--- a/browser/metro/base/content/history.js
+++ b/browser/metro/base/content/history.js
@@ -11,16 +11,17 @@ function HistoryView(aSet, aLimit, aFilt
 
   this._limit = aLimit;
   this._filterUnpinned = aFilterUnpinned;
   this._historyService = PlacesUtils.history;
   this._navHistoryService = gHistSvc;
 
   this._pinHelper = new ItemPinHelper("metro.history.unpinned");
   this._historyService.addObserver(this, false);
+  Services.obs.addObserver(this, "metro_viewstate_changed", false);
   window.addEventListener('MozAppbarDismissing', this, false);
   window.addEventListener('HistoryNeedsRefresh', this, false);
 }
 
 HistoryView.prototype = Util.extend(Object.create(View.prototype), {
   _set: null,
   _toRemove: null,
 
@@ -86,16 +87,17 @@ HistoryView.prototype = Util.extend(Obje
     rootNode.containerOpen = false;
     this._set.arrangeItems();
     if (this._inBatch > 0)
       this._inBatch--;
   },
 
   destruct: function destruct() {
     this._historyService.removeObserver(this);
+    Services.obs.removeObserver(this, "metro_viewstate_changed");
     window.removeEventListener('MozAppbarDismissing', this, false);
     window.removeEventListener('HistoryNeedsRefresh', this, false);
   },
 
   addItemToSet: function addItemToSet(aURI, aTitle, aIcon, aPos) {
     let item = this._set.insertItemAt(aPos || 0, aTitle, aURI, this._inBatch);
     this._setContextActions(item);
     this._updateFavicon(item, aURI);
@@ -204,16 +206,25 @@ HistoryView.prototype = Util.extend(Obje
         break;
 
       case "HistoryNeedsRefresh":
         this.populateGrid(true);
         break;
     }
   },
 
+  // nsIObservers
+  observe: function (aSubject, aTopic, aState) {
+    switch(aTopic) {
+      case "metro_viewstate_changed":
+        this.onViewStateChange(aState);
+        break;
+    }
+  },
+
   // nsINavHistoryObserver & helpers
 
   onBeginUpdateBatch: function() {
     // Avoid heavy grid redraws while a batch is in process
     this._inBatch++;
   },
 
   onEndUpdateBatch: function() {
--- a/browser/metro/modules/View.jsm
+++ b/browser/metro/modules/View.jsm
@@ -23,16 +23,22 @@ function makeURI(aURL, aOriginCharset, a
 // --------------------------------
 // View prototype for shared functionality
 
 function View() {
 }
 
 View.prototype = {
 
+  onViewStateChange: function (aState) {
+    if (this._set) {
+      this._set.setAttribute("suppressonselect", (aState == "snapped"));
+    }
+  },
+
   _updateFavicon: function pv__updateFavicon(aItem, aUri) {
     if ("string" == typeof aUri) {
       aUri = makeURI(aUri);
     }
     PlacesUtils.favicons.getFaviconURLForPage(aUri, this._gotIcon.bind(this, aItem));
   },
 
   _gotIcon: function pv__gotIcon(aItem, aIconUri) {