Bug 616729 - rearranging tabs in panorama won't match tab ordering on tab bar [r=ian, a=dolske]
authorTim Taubert <tim.taubert@gmx.de>
Sat, 22 Jan 2011 07:25:12 +0100
changeset 61159 b38ba02fdeb4cb44a36743be8e4ac25374d472e0
parent 61158 979d2ebe8b7e521807d7cd43d9a42c2d885092c0
child 61160 32738fd1cdfb5721bfe0f442d122a075c6e89f10
push id18252
push usereakhgari@mozilla.com
push dateMon, 24 Jan 2011 04:32:05 +0000
treeherdermozilla-central@4e57b18dd908 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersian, dolske
bugs616729
milestone2.0b10pre
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 616729 - rearranging tabs in panorama won't match tab ordering on tab bar [r=ian, a=dolske]
browser/base/content/tabview/groupitems.js
browser/base/content/test/tabview/Makefile.in
browser/base/content/test/tabview/browser_tabview_bug586553.js
browser/base/content/test/tabview/browser_tabview_bug616729.js
--- a/browser/base/content/tabview/groupitems.js
+++ b/browser/base/content/tabview/groupitems.js
@@ -19,16 +19,17 @@
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  * Ian Gilman <ian@iangilman.com>
  * Aza Raskin <aza@mozilla.com>
  * Michael Yoshitaka Erlewine <mitcho@mitcho.com>
  * Ehsan Akhgari <ehsan@mozilla.com>
  * Raymond Lee <raymond@appcoast.com>
+ * Tim Taubert <tim.taubert@gmx.de>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -1560,44 +1561,31 @@ GroupItem.prototype = Utils.extend(new I
     this.arrange({animate: false});
     // this.arrange calls this.save for us
   },
 
   // Function: reorderTabsBasedOnTabItemOrder
   // Reorders the tabs in the tab bar based on the arrangment of the tabs
   // shown in the groupItem.
   reorderTabsBasedOnTabItemOrder: function GroupItem_reorderTabsBasedOnTabItemOrder() {
-    let targetIndices = null;
+    let indices;
+    let tabs = this._children.map(function (tabItem) tabItem.tab);
+
+    tabs.forEach(function (tab, index) {
+      if (!indices)
+        indices = tabs.map(function (tab) tab._tPos);
 
-    let self = this;
-    this._children.some(function(tabItem, index) {
-      // if no targetIndices, or it was reset, recompute
-      if (!targetIndices) {
-        let currentIndices = [tabItem.tab._tPos for each (tabItem in self._children)];
-        targetIndices = currentIndices.concat().sort();
-        // if no resorting is required, we're done!
-        if (currentIndices == targetIndices)
-          return true;
+      let start = index ? indices[index - 1] + 1 : 0;
+      let end = index + 1 < indices.length ? indices[index + 1] - 1 : Infinity;
+      let targetRange = new Range(start, end);
+
+      if (!targetRange.contains(tab._tPos)) {
+        gBrowser.moveTabTo(tab, start);
+        indices = null;
       }
-    
-      // Compute a target range for this tab's index
-      let originalIndex = tabItem.tab._tPos;
-      let targetRange = new Range(index ? targetIndices[index - 1] : -1,
-                                  targetIndices[index + 1] || Infinity);
-
-      // If the originalIndex of this tab is not within its target,
-      // let's move it to the targetIndex.
-      if (!targetRange.contains(originalIndex)) {
-        let targetIndex = targetIndices[index];
-        gBrowser.moveTabTo(tabItem.tab, targetIndex);
-        // force recomputing targetIndices
-        targetIndices = null;
-      }
-      
-      return false;
     });
   },
 
   // ----------
   // Function: setTopChild
   // Sets the <Item> that should be displayed on top when in stack mode.
   setTopChild: function GroupItem_setTopChild(topChild) {
     this.topChild = topChild;
--- a/browser/base/content/test/tabview/Makefile.in
+++ b/browser/base/content/test/tabview/Makefile.in
@@ -75,16 +75,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_tabview_bug600812.js \
                  browser_tabview_bug604098.js \
                  browser_tabview_bug606657.js \
                  browser_tabview_bug606905.js \
                  browser_tabview_bug608037.js \
                  browser_tabview_bug608184.js \
                  browser_tabview_bug608158.js \
                  browser_tabview_bug610242.js \
+                 browser_tabview_bug616729.js \
                  browser_tabview_bug616967.js \
                  browser_tabview_bug618828.js \
                  browser_tabview_bug619937.js \
                  browser_tabview_bug622835.js \
                  browser_tabview_bug624265.js \
                  browser_tabview_bug624953.js \
                  browser_tabview_bug625269.js \
                  browser_tabview_dragdrop.js \
--- a/browser/base/content/test/tabview/browser_tabview_bug586553.js
+++ b/browser/base/content/test/tabview/browser_tabview_bug586553.js
@@ -78,18 +78,18 @@ function onTabViewWindowLoaded() {
 }
 
 function onTabViewWindowHidden() {
   window.removeEventListener("tabviewhidden", onTabViewWindowHidden, false);
   gBrowser.tabContainer.removeEventListener("TabMove", onTabMove, false);
   
   is(moves, 1, "Only one move should be necessary for this basic move.");
 
-  is(originalTab._tPos, 1, "Original tab is in position 0");
-  is(newTabs[0]._tPos, 2, "Robots is in position 1");
-  is(newTabs[1]._tPos, 3, "Mozilla is in position 2");
-  is(newTabs[2]._tPos, 0, "Credits is in position 3");
+  is(newTabs[2]._tPos, 0, "Credits is in position 0");
+  is(originalTab._tPos, 1, "Original tab is in position 1");
+  is(newTabs[0]._tPos, 2, "Robots is in position 2");
+  is(newTabs[1]._tPos, 3, "Mozilla is in position 3");
   
   gBrowser.removeTab(newTabs[0]);
   gBrowser.removeTab(newTabs[1]);
   gBrowser.removeTab(newTabs[2]);
   finish();
 }
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/tabview/browser_tabview_bug616729.js
@@ -0,0 +1,157 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is a test for bug 616729.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Tim Taubert <tim.taubert@gmx.de>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+function test() {
+  let cw;
+
+  let createGroupItem = function () {
+    let bounds = new cw.Rect(20, 20, 400, 200);
+    let groupItem = new cw.GroupItem([], {bounds: bounds, immediately: true});
+    cw.GroupItems.setActiveGroupItem(groupItem);
+
+    for (let i=0; i<5; i++)
+      gBrowser.loadOneTab('about:blank', {inBackground: true});
+
+    return groupItem;
+  }
+
+  let assertCorrectItemOrder = function (items) {
+    for (let i=1; i<items.length; i++) {
+      if (items[i-1].tab._tPos > items[i].tab._tPos) {
+        ok(false, 'tabs were correctly reordered');
+        break;
+      }
+    }
+  }
+
+  let testVariousTabOrders = function () {
+    let groupItem = createGroupItem();
+    let [tab1, tab2, tab3, tab4, tab5] = groupItem.getChildren();
+
+    // prepare tests
+    let tests = [];
+    tests.push([tab1, tab2, tab3, tab4, tab5]);
+    tests.push([tab5, tab4, tab3, tab2, tab1]);
+    tests.push([tab1, tab2, tab3, tab4]);
+    tests.push([tab4, tab3, tab2, tab1]);
+    tests.push([tab1, tab2, tab3]);
+    tests.push([tab1, tab2, tab3]);
+    tests.push([tab1, tab3, tab2]);
+    tests.push([tab2, tab1, tab3]);
+    tests.push([tab2, tab3, tab1]);
+    tests.push([tab3, tab1, tab2]);
+    tests.push([tab3, tab2, tab1]);
+    tests.push([tab1, tab2]);
+    tests.push([tab2, tab1]);
+    tests.push([tab1]);
+
+    // test reordering of empty groups - removes the last tab and causes
+    // the groupItem to close
+    tests.push([]);
+
+    while (tests.length) {
+      let test = tests.shift();
+
+      // prepare
+      let items = groupItem.getChildren();
+      while (test.length < items.length)
+        items[items.length-1].close();
+
+      let orig = cw.Utils.copy(items);
+      items.sort(function (a, b) test.indexOf(a) - test.indexOf(b));
+
+      // order and check
+      groupItem.reorderTabsBasedOnTabItemOrder();
+      assertCorrectItemOrder(items);
+
+      // revert to original item order
+      items.sort(function (a, b) orig.indexOf(a) - orig.indexOf(b));
+      groupItem.reorderTabsBasedOnTabItemOrder();
+    }
+
+    testMoveBetweenGroups();
+  }
+
+  let testMoveBetweenGroups = function () {
+    let groupItem = createGroupItem();
+    let groupItem2 = createGroupItem();
+    
+    afterAllTabsLoaded(function () {
+      // move item from group1 to group2
+      let child = groupItem.getChild(2);
+      groupItem.remove(child);
+
+      groupItem2.add(child, {index: 3});
+      groupItem2.reorderTabsBasedOnTabItemOrder();
+
+      assertCorrectItemOrder(groupItem.getChildren());
+      assertCorrectItemOrder(groupItem2.getChildren());
+
+      // move item from group2 to group1
+      child = groupItem2.getChild(1);
+      groupItem2.remove(child);
+
+      groupItem.add(child, {index: 1});
+      groupItem.reorderTabsBasedOnTabItemOrder();
+
+      assertCorrectItemOrder(groupItem.getChildren());
+      assertCorrectItemOrder(groupItem2.getChildren());
+
+      // cleanup
+      groupItem.addSubscriber(groupItem, 'groupHidden', function () {
+        groupItem.removeSubscriber(groupItem, 'groupHidden');
+        groupItem.closeHidden();
+        groupItem2.closeAll();
+      });
+
+      groupItem2.addSubscriber(groupItem, 'groupHidden', function () {
+        groupItem2.removeSubscriber(groupItem, 'groupHidden');
+        groupItem2.closeHidden();
+        hideTabView(finish);
+      });
+
+      groupItem.closeAll();
+    });
+  }
+
+  waitForExplicitFinish();
+
+  showTabView(function () {
+    cw = TabView.getContentWindow();
+    afterAllTabsLoaded(testVariousTabOrders);
+  });
+}