diff options
Diffstat (limited to 'addon-sdk/source/lib/sdk/ui/toolbar/model.js')
-rw-r--r-- | addon-sdk/source/lib/sdk/ui/toolbar/model.js | 151 |
1 files changed, 0 insertions, 151 deletions
diff --git a/addon-sdk/source/lib/sdk/ui/toolbar/model.js b/addon-sdk/source/lib/sdk/ui/toolbar/model.js deleted file mode 100644 index 5c5428606..000000000 --- a/addon-sdk/source/lib/sdk/ui/toolbar/model.js +++ /dev/null @@ -1,151 +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"; - -module.metadata = { - "stability": "experimental", - "engines": { - "Firefox": "> 28" - } -}; - -const { Class } = require("../../core/heritage"); -const { EventTarget } = require("../../event/target"); -const { off, setListeners, emit } = require("../../event/core"); -const { Reactor, foldp, merges, send } = require("../../event/utils"); -const { Disposable } = require("../../core/disposable"); -const { InputPort } = require("../../input/system"); -const { OutputPort } = require("../../output/system"); -const { identify } = require("../id"); -const { pairs, object, map, each } = require("../../util/sequence"); -const { patch, diff } = require("diffpatcher/index"); -const { contract } = require("../../util/contract"); -const { id: addonID } = require("../../self"); - -// Input state is accumulated from the input received form the toolbar -// view code & local output. Merging local output reflects local state -// changes without complete roundloop. -const input = foldp(patch, {}, new InputPort({ id: "toolbar-changed" })); -const output = new OutputPort({ id: "toolbar-change" }); - -// Takes toolbar title and normalizes is to an -// identifier, also prefixes with add-on id. -const titleToId = title => - ("toolbar-" + addonID + "-" + title). - toLowerCase(). - replace(/\s/g, "-"). - replace(/[^A-Za-z0-9_\-]/g, ""); - -const validate = contract({ - title: { - is: ["string"], - ok: x => x.length > 0, - msg: "The `option.title` string must be provided" - }, - items: { - is:["undefined", "object", "array"], - msg: "The `options.items` must be iterable sequence of items" - }, - hidden: { - is: ["boolean", "undefined"], - msg: "The `options.hidden` must be boolean" - } -}); - -// Toolbars is a mapping between `toolbar.id` & `toolbar` instances, -// which is used to find intstance for dispatching events. -var toolbars = new Map(); - -const Toolbar = Class({ - extends: EventTarget, - implements: [Disposable], - initialize: function(params={}) { - const options = validate(params); - const id = titleToId(options.title); - - if (toolbars.has(id)) - throw Error("Toolbar with this id already exists: " + id); - - // Set of the items in the toolbar isn't mutable, as a matter of fact - // it just defines desired set of items, actual set is under users - // control. Conver test to an array and freeze to make sure users won't - // try mess with it. - const items = Object.freeze(options.items ? [...options.items] : []); - - const initial = { - id: id, - title: options.title, - // By default toolbars are visible when add-on is installed, unless - // add-on authors decides it should be hidden. From that point on - // user is in control. - collapsed: !!options.hidden, - // In terms of state only identifiers of items matter. - items: items.map(identify) - }; - - this.id = id; - this.items = items; - - toolbars.set(id, this); - setListeners(this, params); - - // Send initial state to the host so it can reflect it - // into a user interface. - send(output, object([id, initial])); - }, - - get title() { - const state = reactor.value[this.id]; - return state && state.title; - }, - get hidden() { - const state = reactor.value[this.id]; - return state && state.collapsed; - }, - - destroy: function() { - send(output, object([this.id, null])); - }, - // `JSON.stringify` serializes objects based of the return - // value of this method. For convinienc we provide this method - // to serialize actual state data. Note: items will also be - // serialized so they should probably implement `toJSON`. - toJSON: function() { - return { - id: this.id, - title: this.title, - hidden: this.hidden, - items: this.items - }; - } -}); -exports.Toolbar = Toolbar; -identify.define(Toolbar, toolbar => toolbar.id); - -const dispose = toolbar => { - toolbars.delete(toolbar.id); - emit(toolbar, "detach"); - off(toolbar); -}; - -const reactor = new Reactor({ - onStep: (present, past) => { - const delta = diff(past, present); - - each(([id, update]) => { - const toolbar = toolbars.get(id); - - // Remove - if (!update) - dispose(toolbar); - // Add - else if (!past[id]) - emit(toolbar, "attach"); - // Update - else - emit(toolbar, update.collapsed ? "hide" : "show", toolbar); - }, pairs(delta)); - } -}); -reactor.run(input); |