Bug 593871 - Panorama should do the right thing when tabs become pinned/unpinned [r=dietrich, a=blocking betaN]

--HG--
extra : rebase_source : 44c6456c6eebac798dcc7f6e64938f50d448151b
This commit is contained in:
Ian Gilman 2010-09-13 11:45:02 +08:00
parent 320c1ddfe8
commit 8fcaa81c49
4 changed files with 141 additions and 16 deletions

View File

@ -882,6 +882,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
addAppTab: function GroupItem_addAppTab(xulTab) {
let self = this;
// add the icon
let icon = xulTab.image || Utils.defaultFaviconURL;
let $appTab = iQ("<img>")
.addClass("appTabIcon")
@ -897,6 +898,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
UI.goToTab(iQ(this).data("xulTab"));
});
// adjust the tray
let columnWidth = $appTab.width();
if (parseInt(this.$appTabTray.css("width")) != columnWidth) {
this.$appTabTray.css({width: columnWidth});
@ -904,6 +906,25 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
}
},
// ----------
// Removes the given xul:tab as an app tab in this group's apptab tray
removeAppTab: function GroupItem_removeAppTab(xulTab) {
// remove the icon
iQ(".appTabIcon", this.$appTabTray).each(function(icon) {
let $icon = iQ(icon);
if ($icon.data("xulTab") != xulTab)
return;
$icon.remove();
});
// adjust the tray
if (!iQ(".appTabIcon", this.$appTabTray).length) {
this.$appTabTray.css({width: 0});
this.arrange();
}
},
// ----------
// Function: hideExpandControl
// Hide the control which expands a stacked groupItem into a quick-look view.
@ -1502,12 +1523,14 @@ let GroupItems = {
// ----------
// Function: uninit
uninit : function GroupItems_uninit () {
// call our cleanup functions
this._cleanupFunctions.forEach(function(func) {
func();
});
this._cleanupFunctions = [];
// additional clean up
this.groupItems = null;
},
@ -1530,6 +1553,22 @@ let GroupItems = {
});
},
// ----------
// when a tab becomes pinned, add it to the app tab tray in all groups
handleTabPin: function GroupItems_handleTabPin(xulTab) {
this.groupItems.forEach(function(groupItem) {
groupItem.addAppTab(xulTab);
});
},
// ----------
// when a tab becomes unpinned, remove it from the app tab tray in all groups
handleTabUnpin: function GroupItems_handleTabUnpin(xulTab) {
this.groupItems.forEach(function(groupItem) {
groupItem.removeAppTab(xulTab);
});
},
// ----------
// Function: getNextID
// Returns the next unused groupItem ID.

View File

@ -831,8 +831,8 @@ let TabItems = {
unlink: function TabItems_unlink(tab) {
try {
Utils.assertThrow(tab, "tab");
Utils.assertThrow(!tab.pinned, "shouldn't be an app tab");
Utils.assertThrow(tab.tabItem, "should already be linked");
// note that it's ok to unlink an app tab; see .handleTabUnpin
this.unregister(tab.tabItem);
tab.tabItem._sendToSubscribers("close");
@ -851,6 +851,19 @@ let TabItems = {
}
},
// ----------
// when a tab becomes pinned, destroy its TabItem
handleTabPin: function TabItems_handleTabPin(xulTab) {
this.unlink(xulTab);
},
// ----------
// when a tab becomes unpinned, create a TabItem for it
handleTabUnpin: function TabItems_handleTabUnpin(xulTab) {
this.link(xulTab);
this.update(xulTab);
},
// ----------
// Function: heartbeat
// Allows us to spreadout update calls over a period of time.

View File

@ -83,6 +83,10 @@ let UI = {
// Keeps track of event listeners added to the AllTabs object.
_eventListeners: {},
// Variable: _cleanupFunctions
// An array of functions to be called at uninit time
_cleanupFunctions: [],
// ----------
// Function: init
// Must be called after the object is created.
@ -233,6 +237,14 @@ let UI = {
},
uninit: function UI_uninit() {
// call our cleanup functions
this._cleanupFunctions.forEach(function(func) {
func();
});
this._cleanupFunctions = [];
// additional clean up
TabItems.uninit();
GroupItems.uninit();
Storage.uninit();
@ -459,6 +471,28 @@ let UI = {
for (let name in this._eventListeners)
AllTabs.register(name, this._eventListeners[name]);
// Start watching for tab pin events, and set up our uninit for same.
function handleTabPin(event) {
TabItems.handleTabPin(event.originalTarget);
GroupItems.handleTabPin(event.originalTarget);
}
gBrowser.tabContainer.addEventListener("TabPinned", handleTabPin, false);
this._cleanupFunctions.push(function() {
gBrowser.tabContainer.removeEventListener("TabPinned", handleTabPin, false);
});
// Start watching for tab unpin events, and set up our uninit for same.
function handleTabUnpin(event) {
TabItems.handleTabUnpin(event.originalTarget);
GroupItems.handleTabUnpin(event.originalTarget);
}
gBrowser.tabContainer.addEventListener("TabUnpinned", handleTabUnpin, false);
this._cleanupFunctions.push(function() {
gBrowser.tabContainer.removeEventListener("TabUnpinned", handleTabUnpin, false);
});
},
// ----------
@ -582,7 +616,7 @@ let UI = {
function getClosestTabBy(norm) {
var centers =
[[item.bounds.center(), item]
[[item.bounds.center(), item]
for each(item in TabItems.getItems()) if (!item.parent || !item.parent.hidden)];
var myCenter = self.getActiveTab().bounds.center();
var matches = centers

View File

@ -52,38 +52,77 @@ function onTabViewWindowLoaded() {
// establish initial state
is(contentWindow.GroupItems.groupItems.length, 1, "we start with one group (the default)");
is(gBrowser.tabs.length, 1, "we start with one tab");
let originalTab = gBrowser.tabs[0];
// create an app tab
let appXulTab = gBrowser.loadOneTab("about:blank");
gBrowser.pinTab(appXulTab);
is(gBrowser.tabs.length, 2, "we now have two tabs");
// Create a group
// create a group
let box = new contentWindow.Rect(20, 20, 180, 180);
let groupItem = new contentWindow.GroupItem([], { bounds: box });
let groupItemOne = new contentWindow.GroupItem([], { bounds: box, title: "test1" });
is(contentWindow.GroupItems.groupItems.length, 2, "we now have two groups");
contentWindow.GroupItems.setActiveGroupItem(groupItemOne);
// create a tab
let xulTab = gBrowser.loadOneTab("about:blank");
is(gBrowser.tabs.length, 2, "we now have two tabs");
is(groupItemOne._children.length, 1, "the new tab was added to the group");
// make sure the group has no app tabs
let appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 0, "there are no app tab icons");
// pin the tab, make sure the TabItem goes away and the icon comes on
gBrowser.pinTab(xulTab);
is(groupItemOne._children.length, 0, "the app tab's TabItem was removed from the group");
appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 1, "there's now one app tab icon");
// create a second group and make sure it gets the icon too
box.offset(box.width + 20, 0);
let groupItemTwo = new contentWindow.GroupItem([], { bounds: box, title: "test2" });
is(contentWindow.GroupItems.groupItems.length, 3, "we now have three groups");
appTabIcons = groupItemTwo.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 1, "there's an app tab icon in the second group");
// unpin the tab, make sure the icon goes away and the TabItem comes on
gBrowser.unpinTab(xulTab);
is(groupItemOne._children.length, 1, "the app tab's TabItem is back");
appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 0, "the icon is gone from group one");
appTabIcons = groupItemTwo.container.getElementsByClassName("appTabIcon");
is(appTabIcons.length, 0, "the icon is gone from group 2");
// pin the tab again
gBrowser.pinTab(xulTab);
// close the second group
groupItemTwo.close();
// find app tab in group and hit it
let onTabViewHidden = function() {
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
ok(!TabView.isVisible(), "Tab View is hidden because we clicked on the app tab");
// clean up
gBrowser.unpinTab(appXulTab);
gBrowser.removeTab(appXulTab);
gBrowser.selectedTab = originalTab;
gBrowser.unpinTab(xulTab);
gBrowser.removeTab(xulTab);
is(gBrowser.tabs.length, 1, "we finish with one tab");
groupItem.close();
groupItemOne.close();
is(contentWindow.GroupItems.groupItems.length, 1, "we finish with one group");
ok(!TabView.isVisible(), "Tab View is not visible");
ok(!TabView.isVisible(), "we finish with Tab View not visible");
finish();
};
window.addEventListener("tabviewhidden", onTabViewHidden, false);
let appTabButtons = groupItem.$appTabTray[0].getElementsByTagName("img");
ok(appTabButtons.length == 1, "there is one app tab button");
EventUtils.sendMouseEvent({ type: "click" }, appTabButtons[0], contentWindow);
appTabIcons = groupItemOne.container.getElementsByClassName("appTabIcon");
EventUtils.sendMouseEvent({ type: "click" }, appTabIcons[0], contentWindow);
}