Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/devtools/client/shared/components/tabs/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 9 kB image not shown  

Impressum TabBar.js   Sprache: JAVA

 
/* 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/. */


/* eslint-env browser */

"use strict";

const {
  Component,
  createFactory,
  createRef,
} = require("resource://devtools/client/shared/vendor/react.js");
const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js");
const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");

const Sidebar = createFactory(
  require("resource://devtools/client/shared/components/Sidebar.js")
);

loader.lazyRequireGetter(
  this,
  "Menu",
  "resource://devtools/client/framework/menu.js"
);
loader.lazyRequireGetter(
  this,
  "MenuItem",
  "resource://devtools/client/framework/menu-item.js"
);

// Shortcuts
const { div } = dom;

/**
 * Renders Tabbar component.
 */

class Tabbar extends Component {
  static get propTypes() {
    return {
      children: PropTypes.array,
      menuDocument: PropTypes.object,
      onSelect: PropTypes.func,
      showAllTabsMenu: PropTypes.bool,
      allTabsMenuButtonTooltip: PropTypes.string,
      activeTabId: PropTypes.string,
      renderOnlySelected: PropTypes.bool,
      sidebarToggleButton: PropTypes.shape({
        // Set to true if collapsed.
        collapsed: PropTypes.bool.isRequired,
        // Tooltip text used when the button indicates expanded state.
        collapsePaneTitle: PropTypes.string.isRequired,
        // Tooltip text used when the button indicates collapsed state.
        expandPaneTitle: PropTypes.string.isRequired,
        // Click callback
        onClick: PropTypes.func.isRequired,
        // align toggle button to right
        alignRight: PropTypes.bool,
        // if set to true toggle-button rotate 90
        canVerticalSplit: PropTypes.bool,
      }),
    };
  }

  static get defaultProps() {
    return {
      menuDocument: window.parent.document,
      showAllTabsMenu: false,
    };
  }

  constructor(props, context) {
    super(props, context);
    const { activeTabId, children = [] } = props;
    const tabs = this.createTabs(children);
    const activeTab = tabs.findIndex(tab => tab.id === activeTabId);

    this.state = {
      activeTab: activeTab === -1 ? 0 : activeTab,
      tabs,
    };

    // Array of queued tabs to add to the Tabbar.
    this.queuedTabs = [];

    this.createTabs = this.createTabs.bind(this);
    this.addTab = this.addTab.bind(this);
    this.addAllQueuedTabs = this.addAllQueuedTabs.bind(this);
    this.queueTab = this.queueTab.bind(this);
    this.toggleTab = this.toggleTab.bind(this);
    this.removeTab = this.removeTab.bind(this);
    this.select = this.select.bind(this);
    this.getTabIndex = this.getTabIndex.bind(this);
    this.getTabId = this.getTabId.bind(this);
    this.getCurrentTabId = this.getCurrentTabId.bind(this);
    this.onTabChanged = this.onTabChanged.bind(this);
    this.onAllTabsMenuClick = this.onAllTabsMenuClick.bind(this);
    this.renderTab = this.renderTab.bind(this);
    this.tabbarRef = createRef();
  }

  // FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=1774507
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { activeTabId, children = [] } = nextProps;
    const tabs = this.createTabs(children);
    const activeTab = tabs.findIndex(tab => tab.id === activeTabId);

    if (
      activeTab !== this.state.activeTab ||
      children !== this.props.children
    ) {
      this.setState({
        activeTab: activeTab === -1 ? 0 : activeTab,
        tabs,
      });
    }
  }

  createTabs(children) {
    return children
      .filter(panel => panel)
      .map((panel, index) =>
        Object.assign({}, children[index], {
          id: panel.props.id || index,
          panel,
          title: panel.props.title,
        })
      );
  }

  // Public API

  addTab(id, title, selected = false, panel, url, index = -1) {
    const tabs = this.state.tabs.slice();

    if (index >= 0) {
      tabs.splice(index, 0, { id, title, panel, url });
    } else {
      tabs.push({ id, title, panel, url });
    }

    const newState = Object.assign({}, this.state, {
      tabs,
    });

    if (selected) {
      newState.activeTab = index >= 0 ? index : tabs.length - 1;
    }

    this.setState(newState, () => {
      if (this.props.onSelect && selected) {
        this.props.onSelect(id);
      }
    });
  }

  addAllQueuedTabs() {
    if (!this.queuedTabs.length) {
      return;
    }

    const tabs = this.state.tabs.slice();

    // Preselect the first sidebar tab if none was explicitly selected.
    let activeTab = 0;
    let activeId = this.queuedTabs[0].id;

    for (const { id, index, panel, selected, title, url } of this.queuedTabs) {
      if (index >= 0) {
        tabs.splice(index, 0, { id, title, panel, url });
      } else {
        tabs.push({ id, title, panel, url });
      }

      if (selected) {
        activeId = id;
        activeTab = index >= 0 ? index : tabs.length - 1;
      }
    }

    const newState = Object.assign({}, this.state, {
      activeTab,
      tabs,
    });

    this.setState(newState, () => {
      if (this.props.onSelect) {
        this.props.onSelect(activeId);
      }
    });

    this.queuedTabs = [];
  }

  /**
   * Queues a tab to be added. This is more performant than calling addTab for every
   * single tab to be added since we will limit the number of renders happening when
   * a new state is set. Once all the tabs to be added have been queued, call
   * addAllQueuedTabs() to populate the TabBar with all the queued tabs.
   */

  queueTab(id, title, selected = false, panel, url, index = -1) {
    this.queuedTabs.push({
      id,
      index,
      panel,
      selected,
      title,
      url,
    });
  }

  toggleTab(tabId, isVisible) {
    const index = this.getTabIndex(tabId);
    if (index < 0) {
      return;
    }

    const tabs = this.state.tabs.slice();
    tabs[index] = Object.assign({}, tabs[index], {
      isVisible,
    });

    this.setState(
      Object.assign({}, this.state, {
        tabs,
      })
    );
  }

  removeTab(tabId) {
    const index = this.getTabIndex(tabId);
    if (index < 0) {
      return;
    }

    const tabs = this.state.tabs.slice();
    tabs.splice(index, 1);

    let activeTab = this.state.activeTab - 1;
    activeTab = activeTab === -1 ? 0 : activeTab;

    this.setState(
      Object.assign({}, this.state, {
        activeTab,
        tabs,
      }),
      () => {
        // Select the next active tab and force the select event handler to initialize
        // the panel if needed.
        if (tabs.length && this.props.onSelect) {
          this.props.onSelect(this.getTabId(activeTab));
        }
      }
    );
  }

  select(tabId) {
    const docRef = this.tabbarRef.current.ownerDocument;

    const index = this.getTabIndex(tabId);
    if (index < 0) {
      return;
    }

    const newState = Object.assign({}, this.state, {
      activeTab: index,
    });

    const tabDomElement = docRef.querySelector(`[data-tab-index="${index}"]`);

    if (tabDomElement) {
      tabDomElement.scrollIntoView();
    }

    this.setState(newState, () => {
      if (this.props.onSelect) {
        this.props.onSelect(tabId);
      }
    });
  }

  // Helpers

  getTabIndex(tabId) {
    let tabIndex = -1;
    this.state.tabs.forEach((tab, index) => {
      if (tab.id === tabId) {
        tabIndex = index;
      }
    });
    return tabIndex;
  }

  getTabId(index) {
    return this.state.tabs[index].id;
  }

  getCurrentTabId() {
    return this.state.tabs[this.state.activeTab].id;
  }

  // Event Handlers

  onTabChanged(index) {
    this.setState(
      {
        activeTab: index,
      },
      () => {
        if (this.props.onSelect) {
          this.props.onSelect(this.state.tabs[index].id);
        }
      }
    );
  }

  onAllTabsMenuClick(event) {
    const menu = new Menu();
    const 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.
    menu.popupAtTarget(target);

    return menu;
  }

  // Rendering

  renderTab(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() {
    const tabs = this.state.tabs.map(tab => this.renderTab(tab));

    return div(
      {
        className: "devtools-sidebar-tabs",
        ref: this.tabbarRef,
      },
      Sidebar(
        {
          onAllTabsMenuClick: this.onAllTabsMenuClick,
          renderOnlySelected: this.props.renderOnlySelected,
          showAllTabsMenu: this.props.showAllTabsMenu,
          allTabsMenuButtonTooltip: this.props.allTabsMenuButtonTooltip,
          sidebarToggleButton: this.props.sidebarToggleButton,
          activeTab: this.state.activeTab,
          onAfterChange: this.onTabChanged,
        },
        tabs
      )
    );
  }
}

module.exports = Tabbar;

Messung V0.5
C=97 H=98 G=97

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.