Bug 511493: Tab strip should dynamically reflow thumbnails based on screen size [r=pavlov]

This commit is contained in:
Vivien Nicolas 2009-09-09 23:32:13 -04:00
parent 4801c3bd9b
commit 8bfdf93d13
9 changed files with 101 additions and 123 deletions

View File

@ -303,14 +303,11 @@ var BrowserUI = {
return this.starButton = document.getElementById("tool-star");
},
_initControls : false,
sizeControls : function(windowW, windowH) {
let tabs = document.getElementById("tabs-container");
let controls = document.getElementById("browser-controls");
if (!this._initControls) {
this._initControls = true;
}
// tabs
document.getElementById("tabs").resize();
// awesomebar
let popup = document.getElementById("popup_autocomplete");
popup.top = this.toolbarH;
popup.height = windowH - this.toolbarH;

View File

@ -6,7 +6,7 @@
-moz-binding: url("chrome://browser/content/tabs.xml#tablist");
}
richlistitem[type="documenttab"] {
box[type="documenttab"] {
-moz-binding: url("chrome://browser/content/tabs.xml#documenttab");
}

View File

@ -659,10 +659,6 @@ var Browser = {
tab.destroy();
this._tabs.splice(tabIndex, 1);
// redraw the tabs
for (let t = tabIndex; t < this._tabs.length; t++)
this._tabs[t].updateThumbnail();
},
get selectedTab() {
@ -692,7 +688,7 @@ var Browser = {
bv.setBrowser(tab.browser, tab.browserViewportState, false);
bv.forceContainerResize();
document.getElementById("tabs").selectedItem = tab.chromeTab;
document.getElementById("tabs").selectedTab = tab.chromeTab;
if (!firstTab) {
let webProgress = this.selectedBrowser.webProgress;
@ -2428,13 +2424,10 @@ Tab.prototype = {
},
create: function() {
this._chromeTab = document.createElement("richlistitem");
this._chromeTab.setAttribute("type", "documenttab");
document.getElementById("tabs").addTab(this._chromeTab);
// Initialize a viewport state for BrowserView
this._browserViewportState = BrowserView.Util.createBrowserViewportState();
this._chromeTab = document.getElementById("tabs").addTab();
this._createBrowser();
},

View File

@ -186,8 +186,7 @@
<spacer class="sidebar-spacer"/>
<!-- Left toolbar -->
<vbox id="tabs-container" class="panel-dark" flex="1">
<richlistbox id="tabs" onselect="BrowserUI.selectTab(this.selectedItem);" onclick="BrowserUI.hideTabs();" onclosetab="BrowserUI.closeTab(this)"/>
<toolbarspring/>
<vbox id="tabs" onselect="BrowserUI.selectTab(this);" onclosetab="BrowserUI.closeTab(this)" flex="1"/>
<hbox id="tabs-controls">
<toolbarbutton id="newtab-button" class="button-image" command="cmd_newTab"/>
</hbox>

View File

@ -7,21 +7,36 @@
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="documenttab"
extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
<binding id="documenttab">
<content>
<xul:stack anonid="page" class="documenttab-container" flex="1">
<html:canvas anonid="canvas" class="documenttab-canvas" left="8" width="106" height="64"/>
<xul:image left="0" top="24" anonid="close" class="documenttab-close"/>
<html:canvas anonid="canvas" class="documenttab-canvas" left="8" width="106" height="64" moz-opaque="true"
onclick="document.getBindingParent(this)._onClick()"/>
<xul:image left="0" top="24" anonid="close" class="documenttab-close"
onclick="document.getBindingParent(this)._close()"/>
</xul:stack>
</content>
<implementation>
<constructor><![CDATA[
let close = document.getAnonymousElementByAttribute(this, "anonid", "close");
let closefn = new Function("event", this.control.getAttribute("onclosetab"));
var self = this;
close.addEventListener("mousedown", function(event) { closefn.call(self, event); event.stopPropagation(); }, true);
]]></constructor>
<implementation>
<method name="_onClick">
<body>
<![CDATA[
this.parentNode.selectedTab = this;
let selectFn = new Function("event", this.parentNode.getAttribute('onselect'));
selectFn.call(this);
]]>
</body>
</method>
<method name="_close">
<body>
<![CDATA[
let closeFn = new Function("event", this.parentNode.getAttribute('onclosetab'));
closeFn.call(this);
]]>
</body>
</method>
<method name="updateThumbnail">
<parameter name="browser"/>
@ -49,91 +64,81 @@
]]>
</body>
</method>
<method name="markInvalid">
<parameter name="browser"/>
<body>
<![CDATA[
let canvas = document.getAnonymousElementByAttribute(this, "anonid", "canvas");
let ctx = canvas.getContext("2d");
ctx.save();
ctx.strokeStyle = "red";
ctx.moveTo(63, 43);
ctx.lineTo(78, 58);
ctx.moveTo(78, 43);
ctx.lineTo(63, 58);
ctx.stroke();
ctx.restore();
]]>
</body>
</method>
</implementation>
</binding>
<!-- very hacky, used to display richlistitems in multiple columns -->
<binding id="tablist"
extends="chrome://global/content/bindings/richlistbox.xml#richlistbox">
<content>
<children includes="listheader"/>
<xul:scrollbox allowevents="true" orient="horizontal" anonid="main-box"
flex="1">
<children/>
</xul:scrollbox>
</content>
<binding id="tablist">
<implementation>
<field name="tabsPerColumn">4</field>
<property name="children" readonly="true">
<field name="_selectedTab">null</field>
<property name="selectedTab">
<getter>
<![CDATA[
var childNodes = [];
for (var box = this.firstChild; box; box = box.nextSibling) {
for (var child = box.firstChild; child; child = child.nextSibling) {
if (child instanceof Components.interfaces.nsIDOMXULSelectControlItemElement)
childNodes.push(child);
}
}
return childNodes;
return this._selectedTab;
]]>
</getter>
<setter>
<![CDATA[
if (this._selectedTab)
this._selectedTab.removeAttribute('selected');
if (val)
val.setAttribute('selected', 'true');
this._selectedTab = val;
]]>
</setter>
</property>
<method name="addTab">
<parameter name="tab"/>
<body>
<![CDATA[
if (this.children.length % this.tabsPerColumn == 0)
this.appendChild(document.createElement("vbox"));
this.lastChild.appendChild(tab);
let tab = document.createElement("box");
tab.setAttribute("type", "documenttab");
this.appendChild(tab);
this._updateWidth();
return tab;
]]>
</body>
</method>
<method name="removeTab">
<parameter name="tab"/>
<parameter name="aTab"/>
<body>
<![CDATA[
var idx = this.getIndexOfItem(tab);
if (idx == -1)
return;
// remove all later tabs and readd them so that there aren't empty columns
var count = this.itemCount - 1;
var tomove = [ ];
for (var c = count; c >= idx; c--) {
var tab = this.getItemAtIndex(c);
tomove.push(tab.parentNode.removeChild(tab));
if (!this.lastChild.hasChildNodes())
this.removeChild(this.lastChild);
}
// subtract 2 because the tab to remove should not be added back again
for (var m = tomove.length - 2; m >= 0; m--)
this.addTab(tomove[m]);
this.removeChild(aTab);
this._updateWidth();
]]>
</body>
</method>
<method name="resize">
<body>
<![CDATA[
if (this._verticalOccupation == undefined) {
this._verticalOccupation = this.getBoundingClientRect().height / window.innerHeight;
}
this.style.height = (window.innerHeight * this._verticalOccupation) + "px";
this._updateWidth();
]]>
</body>
</method>
<field name="_columnsCount">1</field>
<method name="_updateWidth">
<body>
<![CDATA[
let boundingBox = this.firstChild.getBoundingClientRect();
let columnsCount = Math.ceil(this.childNodes.length / Math.floor(this.style.height / boundingBox.height));
if (this._columnsCount != columnsCount) {
this.style.width = (this.lastChild.boxObject.x + boundingBox.width) + "px";
this._columnsCount = columnsCount;
}
]]>
</body>
</method>
</implementation>
</binding>

View File

@ -667,7 +667,9 @@ autocompleteresult.allbookmarks > .autocomplete-item-tags:after {
}
#tabs {
-moz-appearance: none;
display: block;
-moz-column-width: 128px;
-moz-column-gap: 0;
-moz-user-focus: none;
margin: 0;
padding: 0;
@ -679,33 +681,23 @@ autocompleteresult.allbookmarks > .autocomplete-item-tags:after {
-moz-box-pack: start;
}
richlistitem[type="documenttab"] {
-moz-appearance: none;
padding: 0;
border: none;
}
richlistitem[type="documenttab"] .documenttab-canvas {
box[type="documenttab"] .documenttab-canvas {
/* keep the unselected thumbnails aligned with the selected one */
border: 2mm solid transparent;
}
richlistitem[type="documenttab"][selected="true"] {
background-color: transparent;
}
richlistitem[type="documenttab"][selected="true"] .documenttab-canvas {
box[type="documenttab"][selected="true"] .documenttab-canvas {
border: 2mm solid #262629;
-moz-border-radius: 4px;
}
.documenttab-close {
box[type="documenttab"] .documenttab-close {
width: 28px;
height: 30px;
list-style-image: url("chrome://browser/skin/images/close-30.png");
}
vbox:first-child > richlistitem[type="documenttab"]:only-child .documenttab-close {
box[type="documenttab"]:only-child .documenttab-close {
display: none;
}

View File

@ -264,7 +264,7 @@ autocompleteresult.allbookmarks > .autocomplete-item-image {
list-style-image: url(images/bookmarks-30.png);
}
.documenttab-close {
box[type="documenttab"] .documenttab-close {
width: 28px;
height: 30px;
list-style-image: url("chrome://browser/skin/images/close-30.png");

View File

@ -264,7 +264,7 @@ autocompleteresult.allbookmarks > .autocomplete-item-image {
}
/* Left sidebar (tabs) ---------------------------------------------------- */
.documenttab-close {
box[type="documenttab"] .documenttab-close {
width: 16px;
height: 17px;
list-style-image: url("chrome://browser/skin/images/close-16.png");

View File

@ -431,7 +431,9 @@ autocompleteresult.allbookmarks > .autocomplete-item-tags:after {
}
#tabs {
-moz-appearance: none;
display: block;
-moz-column-width: 128px;
-moz-column-gap: 0;
-moz-user-focus: none;
margin: 0;
padding: 0;
@ -443,27 +445,17 @@ autocompleteresult.allbookmarks > .autocomplete-item-tags:after {
-moz-box-pack: start;
}
richlistitem[type="documenttab"] {
-moz-appearance: none;
padding: 0;
border: none;
}
richlistitem[type="documenttab"] .documenttab-canvas {
box[type="documenttab"] .documenttab-canvas {
/* keep the unselected thumbnails aligned with the selected one */
border: 1.0mm solid transparent;
}
richlistitem[type="documenttab"][selected="true"] {
background-color: transparent;
}
richlistitem[type="documenttab"][selected="true"] .documenttab-canvas {
box[type="documenttab"][selected="true"] .documenttab-canvas {
border: 1.0mm solid #262629;
-moz-border-radius: 4px;
}
vbox:first-child > richlistitem[type="documenttab"]:only-child .documenttab-close {
box[type="documenttab"]:only-child .documenttab-close {
display: none;
}