1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/ui/button/action.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,111 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +'use strict'; 1.8 + 1.9 +module.metadata = { 1.10 + 'stability': 'experimental', 1.11 + 'engines': { 1.12 + 'Firefox': '> 28' 1.13 + } 1.14 +}; 1.15 + 1.16 +const { Class } = require('../../core/heritage'); 1.17 +const { merge } = require('../../util/object'); 1.18 +const { Disposable } = require('../../core/disposable'); 1.19 +const { on, off, emit, setListeners } = require('../../event/core'); 1.20 +const { EventTarget } = require('../../event/target'); 1.21 +const { getNodeView } = require('../../view/core'); 1.22 + 1.23 +const view = require('./view'); 1.24 +const { buttonContract, stateContract } = require('./contract'); 1.25 +const { properties, render, state, register, unregister, 1.26 + getDerivedStateFor } = require('../state'); 1.27 +const { events: stateEvents } = require('../state/events'); 1.28 +const { events: viewEvents } = require('./view/events'); 1.29 +const events = require('../../event/utils'); 1.30 + 1.31 +const { getActiveTab } = require('../../tabs/utils'); 1.32 + 1.33 +const { id: addonID } = require('../../self'); 1.34 +const { identify } = require('../id'); 1.35 + 1.36 +const buttons = new Map(); 1.37 + 1.38 +const toWidgetId = id => 1.39 + ('action-button--' + addonID.toLowerCase()+ '-' + id). 1.40 + replace(/[^a-z0-9_-]/g, ''); 1.41 + 1.42 +const ActionButton = Class({ 1.43 + extends: EventTarget, 1.44 + implements: [ 1.45 + properties(stateContract), 1.46 + state(stateContract), 1.47 + Disposable 1.48 + ], 1.49 + setup: function setup(options) { 1.50 + let state = merge({ 1.51 + disabled: false 1.52 + }, buttonContract(options)); 1.53 + 1.54 + let id = toWidgetId(options.id); 1.55 + 1.56 + register(this, state); 1.57 + 1.58 + // Setup listeners. 1.59 + setListeners(this, options); 1.60 + 1.61 + buttons.set(id, this); 1.62 + 1.63 + view.create(merge({}, state, { id: id })); 1.64 + }, 1.65 + 1.66 + dispose: function dispose() { 1.67 + let id = toWidgetId(this.id); 1.68 + buttons.delete(id); 1.69 + 1.70 + off(this); 1.71 + 1.72 + view.dispose(id); 1.73 + 1.74 + unregister(this); 1.75 + }, 1.76 + 1.77 + get id() this.state().id, 1.78 + 1.79 + click: function click() { view.click(toWidgetId(this.id)) } 1.80 +}); 1.81 +exports.ActionButton = ActionButton; 1.82 + 1.83 +identify.define(ActionButton, ({id}) => toWidgetId(id)); 1.84 + 1.85 +getNodeView.define(ActionButton, button => 1.86 + view.nodeFor(toWidgetId(button.id)) 1.87 +); 1.88 + 1.89 +let actionButtonStateEvents = events.filter(stateEvents, 1.90 + e => e.target instanceof ActionButton); 1.91 + 1.92 +let actionButtonViewEvents = events.filter(viewEvents, 1.93 + e => buttons.has(e.target)); 1.94 + 1.95 +let clickEvents = events.filter(actionButtonViewEvents, e => e.type === 'click'); 1.96 +let updateEvents = events.filter(actionButtonViewEvents, e => e.type === 'update'); 1.97 + 1.98 +on(clickEvents, 'data', ({target: id, window}) => { 1.99 + let button = buttons.get(id); 1.100 + let state = getDerivedStateFor(button, getActiveTab(window)); 1.101 + 1.102 + emit(button, 'click', state); 1.103 +}); 1.104 + 1.105 +on(updateEvents, 'data', ({target: id, window}) => { 1.106 + render(buttons.get(id), window); 1.107 +}); 1.108 + 1.109 +on(actionButtonStateEvents, 'data', ({target, window, state}) => { 1.110 + let id = toWidgetId(target.id); 1.111 + view.setIcon(id, window, state.icon); 1.112 + view.setLabel(id, window, state.label); 1.113 + view.setDisabled(id, window, state.disabled); 1.114 +});