summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/components/tabs/tabbar.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/shared/components/tabs/tabbar.js')
-rw-r--r--devtools/client/shared/components/tabs/tabbar.js204
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;