diff options
Diffstat (limited to 'addon-sdk/source/lib/sdk/ui/state.js')
-rw-r--r-- | addon-sdk/source/lib/sdk/ui/state.js | 239 |
1 files changed, 0 insertions, 239 deletions
diff --git a/addon-sdk/source/lib/sdk/ui/state.js b/addon-sdk/source/lib/sdk/ui/state.js deleted file mode 100644 index 152ce696d..000000000 --- a/addon-sdk/source/lib/sdk/ui/state.js +++ /dev/null @@ -1,239 +0,0 @@ -/* 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'; - -// The Button module currently supports only Firefox. -// See: https://bugzilla.mozilla.org/show_bug.cgi?id=jetpack-panel-apps -module.metadata = { - 'stability': 'experimental', - 'engines': { - 'Firefox': '*', - 'SeaMonkey': '*', - 'Thunderbird': '*' - } -}; - -const { Ci } = require('chrome'); - -const events = require('../event/utils'); -const { events: browserEvents } = require('../browser/events'); -const { events: tabEvents } = require('../tab/events'); -const { events: stateEvents } = require('./state/events'); - -const { windows, isInteractive, getFocusedBrowser } = require('../window/utils'); -const { getActiveTab, getOwnerWindow } = require('../tabs/utils'); - -const { ignoreWindow } = require('../private-browsing/utils'); - -const { freeze } = Object; -const { merge } = require('../util/object'); -const { on, off, emit } = require('../event/core'); - -const { add, remove, has, clear, iterator } = require('../lang/weak-set'); -const { isNil } = require('../lang/type'); - -const { viewFor } = require('../view/core'); - -const components = new WeakMap(); - -const ERR_UNREGISTERED = 'The state cannot be set or get. ' + - 'The object may be not be registered, or may already have been unloaded.'; - -const ERR_INVALID_TARGET = 'The state cannot be set or get for this target.' + - 'Only window, tab and registered component are valid targets.'; - -const isWindow = thing => thing instanceof Ci.nsIDOMWindow; -const isTab = thing => thing.tagName && thing.tagName.toLowerCase() === 'tab'; -const isActiveTab = thing => isTab(thing) && thing === getActiveTab(getOwnerWindow(thing)); -const isEnumerable = window => !ignoreWindow(window); -const browsers = _ => - windows('navigator:browser', { includePrivate: true }).filter(isInteractive); -const getMostRecentTab = _ => getActiveTab(getFocusedBrowser()); - -function getStateFor(component, target) { - if (!isRegistered(component)) - throw new Error(ERR_UNREGISTERED); - - if (!components.has(component)) - return null; - - let states = components.get(component); - - if (target) { - if (isTab(target) || isWindow(target) || target === component) - return states.get(target) || null; - else - throw new Error(ERR_INVALID_TARGET); - } - - return null; -} -exports.getStateFor = getStateFor; - -function getDerivedStateFor(component, target) { - if (!isRegistered(component)) - throw new Error(ERR_UNREGISTERED); - - if (!components.has(component)) - return null; - - let states = components.get(component); - - let componentState = states.get(component); - let windowState = null; - let tabState = null; - - if (target) { - // has a target - if (isTab(target)) { - windowState = states.get(getOwnerWindow(target), null); - - if (states.has(target)) { - // we have a tab state - tabState = states.get(target); - } - } - else if (isWindow(target) && states.has(target)) { - // we have a window state - windowState = states.get(target); - } - } - - return freeze(merge({}, componentState, windowState, tabState)); -} -exports.getDerivedStateFor = getDerivedStateFor; - -function setStateFor(component, target, state) { - if (!isRegistered(component)) - throw new Error(ERR_UNREGISTERED); - - let isComponentState = target === component; - let targetWindows = isWindow(target) ? [target] : - isActiveTab(target) ? [getOwnerWindow(target)] : - isComponentState ? browsers() : - isTab(target) ? [] : - null; - - if (!targetWindows) - throw new Error(ERR_INVALID_TARGET); - - // initialize the state's map - if (!components.has(component)) - components.set(component, new WeakMap()); - - let states = components.get(component); - - if (state === null && !isComponentState) // component state can't be deleted - states.delete(target); - else { - let base = isComponentState ? states.get(target) : null; - states.set(target, freeze(merge({}, base, state))); - } - - render(component, targetWindows); -} -exports.setStateFor = setStateFor; - -function render(component, targetWindows) { - targetWindows = targetWindows ? [].concat(targetWindows) : browsers(); - - for (let window of targetWindows.filter(isEnumerable)) { - let tabState = getDerivedStateFor(component, getActiveTab(window)); - - emit(stateEvents, 'data', { - type: 'render', - target: component, - window: window, - state: tabState - }); - - } -} -exports.render = render; - -function properties(contract) { - let { rules } = contract; - let descriptor = Object.keys(rules).reduce(function(descriptor, name) { - descriptor[name] = { - get: function() { return getDerivedStateFor(this)[name] }, - set: function(value) { - let changed = {}; - changed[name] = value; - - setStateFor(this, this, contract(changed)); - } - } - return descriptor; - }, {}); - - return Object.create(Object.prototype, descriptor); -} -exports.properties = properties; - -function state(contract) { - return { - state: function state(target, state) { - let nativeTarget = target === 'window' ? getFocusedBrowser() - : target === 'tab' ? getMostRecentTab() - : target === this ? null - : viewFor(target); - - if (!nativeTarget && target !== this && !isNil(target)) - throw new Error(ERR_INVALID_TARGET); - - target = nativeTarget || target; - - // jquery style - return arguments.length < 2 - ? getDerivedStateFor(this, target) - : setStateFor(this, target, contract(state)) - } - } -} -exports.state = state; - -const register = (component, state) => { - add(components, component); - setStateFor(component, component, state); -} -exports.register = register; - -const unregister = component => { - remove(components, component); -} -exports.unregister = unregister; - -const isRegistered = component => has(components, component); -exports.isRegistered = isRegistered; - -var tabSelect = events.filter(tabEvents, e => e.type === 'TabSelect'); -var tabClose = events.filter(tabEvents, e => e.type === 'TabClose'); -var windowOpen = events.filter(browserEvents, e => e.type === 'load'); -var windowClose = events.filter(browserEvents, e => e.type === 'close'); - -var close = events.merge([tabClose, windowClose]); -var activate = events.merge([windowOpen, tabSelect]); - -on(activate, 'data', ({target}) => { - let [window, tab] = isWindow(target) - ? [target, getActiveTab(target)] - : [getOwnerWindow(target), target]; - - if (ignoreWindow(window)) return; - - for (let component of iterator(components)) { - emit(stateEvents, 'data', { - type: 'render', - target: component, - window: window, - state: getDerivedStateFor(component, tab) - }); - } -}); - -on(close, 'data', function({target}) { - for (let component of iterator(components)) { - components.get(component).delete(target); - } -}); |