diff options
Diffstat (limited to 'devtools/client/shared/components/tabs/tabbar.js')
-rw-r--r-- | devtools/client/shared/components/tabs/tabbar.js | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/devtools/client/shared/components/tabs/tabbar.js b/devtools/client/shared/components/tabs/tabbar.js new file mode 100644 index 000000000..1e3aa4617 --- /dev/null +++ b/devtools/client/shared/components/tabs/tabbar.js @@ -0,0 +1,204 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* 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"; + +const { DOM, createClass, PropTypes, createFactory } = require("devtools/client/shared/vendor/react"); +const Tabs = createFactory(require("devtools/client/shared/components/tabs/tabs").Tabs); + +const Menu = require("devtools/client/framework/menu"); +const MenuItem = require("devtools/client/framework/menu-item"); + +// Shortcuts +const { div } = DOM; + +/** + * Renders Tabbar component. + */ +let Tabbar = createClass({ + displayName: "Tabbar", + + propTypes: { + onSelect: PropTypes.func, + showAllTabsMenu: PropTypes.bool, + toolbox: PropTypes.object, + }, + + getDefaultProps: function () { + return { + showAllTabsMenu: false, + }; + }, + + getInitialState: function () { + return { + tabs: [], + activeTab: 0 + }; + }, + + // Public API + + addTab: function (id, title, selected = false, panel, url) { + let tabs = this.state.tabs.slice(); + tabs.push({id, title, panel, url}); + + let newState = Object.assign({}, this.state, { + tabs: tabs, + }); + + if (selected) { + newState.activeTab = tabs.length - 1; + } + + this.setState(newState, () => { + if (this.props.onSelect && selected) { + this.props.onSelect(id); + } + }); + }, + + toggleTab: function (tabId, isVisible) { + let index = this.getTabIndex(tabId); + if (index < 0) { + return; + } + + let tabs = this.state.tabs.slice(); + tabs[index] = Object.assign({}, tabs[index], { + isVisible: isVisible + }); + + this.setState(Object.assign({}, this.state, { + tabs: tabs, + })); + }, + + removeTab: function (tabId) { + let index = this.getTabIndex(tabId); + if (index < 0) { + return; + } + + let tabs = this.state.tabs.slice(); + tabs.splice(index, 1); + + this.setState(Object.assign({}, this.state, { + tabs: tabs, + })); + }, + + select: function (tabId) { + let index = this.getTabIndex(tabId); + if (index < 0) { + return; + } + + let newState = Object.assign({}, this.state, { + activeTab: index, + }); + + this.setState(newState, () => { + if (this.props.onSelect) { + this.props.onSelect(tabId); + } + }); + }, + + // Helpers + + getTabIndex: function (tabId) { + let tabIndex = -1; + this.state.tabs.forEach((tab, index) => { + if (tab.id == tabId) { + tabIndex = index; + } + }); + return tabIndex; + }, + + getTabId: function (index) { + return this.state.tabs[index].id; + }, + + getCurrentTabId: function () { + return this.state.tabs[this.state.activeTab].id; + }, + + // Event Handlers + + onTabChanged: function (index) { + this.setState({ + activeTab: index + }); + + if (this.props.onSelect) { + this.props.onSelect(this.state.tabs[index].id); + } + }, + + onAllTabsMenuClick: function (event) { + let menu = new Menu(); + let target = event.target; + + // Generate list of menu items from the list of tabs. + this.state.tabs.forEach(tab => { + menu.append(new MenuItem({ + label: tab.title, + type: "checkbox", + checked: this.getCurrentTabId() == tab.id, + click: () => this.select(tab.id), + })); + }); + + // Show a drop down menu with frames. + // XXX Missing menu API for specifying target (anchor) + // and relative position to it. See also: + // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Method/openPopup + // https://bugzilla.mozilla.org/show_bug.cgi?id=1274551 + let rect = target.getBoundingClientRect(); + let screenX = target.ownerDocument.defaultView.mozInnerScreenX; + let screenY = target.ownerDocument.defaultView.mozInnerScreenY; + menu.popup(rect.left + screenX, rect.bottom + screenY, this.props.toolbox); + + return menu; + }, + + // Rendering + + renderTab: function (tab) { + if (typeof tab.panel === "function") { + return tab.panel({ + key: tab.id, + title: tab.title, + id: tab.id, + url: tab.url, + }); + } + + return tab.panel; + }, + + render: function () { + let tabs = this.state.tabs.map(tab => { + return this.renderTab(tab); + }); + + return ( + div({className: "devtools-sidebar-tabs"}, + Tabs({ + onAllTabsMenuClick: this.onAllTabsMenuClick, + showAllTabsMenu: this.props.showAllTabsMenu, + tabActive: this.state.activeTab, + onAfterChange: this.onTabChanged}, + tabs + ) + ) + ); + }, +}); + +module.exports = Tabbar; |