diff -r 000000000000 -r 6474c204b198 browser/metro/modules/View.jsm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/browser/metro/modules/View.jsm Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,157 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +this.EXPORTED_SYMBOLS = ["View"]; + +Components.utils.import("resource://gre/modules/PlacesUtils.jsm"); +Components.utils.import("resource:///modules/colorUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/Task.jsm"); + +// -------------------------------- +// module helpers +// + +function makeURI(aURL, aOriginCharset, aBaseURI) { + return Services.io.newURI(aURL, aOriginCharset, aBaseURI); +} + +// -------------------------------- + + +// -------------------------------- +// View prototype for shared functionality + +function View(aSet) { + this._set = aSet; + this._set.controller = this; + this._window = aSet.ownerDocument.defaultView; + this._maxTiles = 8; + this._tilePrefName = "unknown"; + + this.onResize = () => this._adjustDOMforViewState(); + this._window.addEventListener("resize", this.onResize); + + ColorUtils.init(); + this._adjustDOMforViewState(); +} + +View.prototype = { + set maxTiles(aVal) { + this._maxTiles = aVal; + }, + + get maxTiles() { + return this._maxTiles; + }, + + set showing(aFlag) { + // 'vbox' must be defined on objects that inherit from us + this.vbox.setAttribute("hidden", aFlag ? "false" : "true"); + }, + + set tilePrefName(aStr) { + // Should be called once on init by objects that inherit from us + this._tilePrefName = aStr; + this._maxTiles = Services.prefs.getIntPref(this._tilePrefName); + Services.prefs.addObserver(this._tilePrefName, this, false); + }, + + destruct: function () { + this._window.removeEventListener("resize", this.onResize); + if (this._tilePrefName != "unknown") { + Services.prefs.removeObserver(this._tilePrefName, this); + } + }, + + _adjustDOMforViewState: function _adjustDOMforViewState(aState) { + let grid = this._set; + if (!grid) { + return; + } + if (!aState) { + aState = grid.getAttribute("viewstate"); + } + switch (aState) { + case "snapped": + grid.setAttribute("nocontext", true); + grid.selectNone(); + grid.disableCrossSlide(); + break; + case "portrait": + grid.removeAttribute("nocontext"); + grid.setAttribute("vertical", true); + grid.enableCrossSlide(); + break; + default: + grid.removeAttribute("nocontext"); + grid.removeAttribute("vertical"); + grid.enableCrossSlide(); + } + if ("arrangeItems" in grid) { + grid.arrangeItems(); + } + }, + + _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) { + if (!aIconUri) { + aItem.removeAttribute("iconURI"); + if (aItem.refresh) { + aItem.refresh(); + } + return; + } + if ("string" == typeof aIconUri) { + aIconUri = makeURI(aIconUri); + } + let faviconURL = (PlacesUtils.favicons.getFaviconLinkForIcon(aIconUri)).spec; + aItem.iconSrc = faviconURL; + + let xpFaviconURI = makeURI(faviconURL.replace("moz-anno:favicon:","")); + Task.spawn(function() { + let colorInfo = yield ColorUtils.getForegroundAndBackgroundIconColors(xpFaviconURI); + if (!(colorInfo && colorInfo.background && colorInfo.foreground)) { + return; + } + let { background, foreground } = colorInfo; + aItem.style.color = foreground; //color text + aItem.setAttribute("customColor", background); + let matteColor = 0xffffff; // white + let alpha = 0.04; // the tint weight + let [,r,g,b] = background.match(/rgb\((\d+),(\d+),(\d+)/); + // get the rgb value that represents this color at given opacity over a white matte + let tintColor = ColorUtils.addRgbColors(matteColor, ColorUtils.createDecimalColorWord(r,g,b,alpha)); + aItem.setAttribute("tintColor", ColorUtils.convertDecimalToRgbColor(tintColor)); + // when bound, use the setter to propogate the color change through the tile + if ('color' in aItem) { + aItem.color = background; + } + }); + }, + + refreshView: function () { + }, + + observe: function (aSubject, aTopic, aState) { + switch (aTopic) { + case "nsPref:changed": { + if (aState == this._tilePrefName) { + let count = Services.prefs.getIntPref(this._tilePrefName); + this.maxTiles = count; + this.showing = this.maxTiles > 0; + this.refreshView(); + } + break; + } + } + } +};