Quelle toolbox-tabs-order-manager.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/. */
"use strict";
const { AddonManager } = ChromeUtils.importESModule( "resource://gre/modules/AddonManager.sys.mjs", // AddonManager is a singleton, never create two instances of it.
{ global: "shared" }
); const {
gDevTools,
} = require("resource://devtools/client/framework/devtools.js"); const PREFERENCE_NAME = "devtools.toolbox.tabsOrder";
/** * Manage the order of devtools tabs.
*/ class ToolboxTabsOrderManager {
constructor(toolbox, onOrderUpdated, panelDefinitions) { this.toolbox = toolbox; this.onOrderUpdated = onOrderUpdated; this.currentPanelDefinitions = panelDefinitions || [];
async saveOrderPreference() { const tabs = [...this.toolboxTabsElement.querySelectorAll(".devtools-tab")]; const tabIds = tabs.map(tab => tab.dataset.extensionId || tab.dataset.id); // Concat the overflowed tabs id since they are not contained in visible tabs. // The overflowed tabs cannot be reordered so we just append the id from current // panel definitions on their order. const overflowedTabIds = this.currentPanelDefinitions
.filter(definition => !tabs.some(tab => tab.dataset.id === definition.id))
.map(definition => definition.extensionId || definition.id); const currentTabIds = tabIds.concat(overflowedTabIds); const dragTargetId = this.dragTarget.dataset.extensionId || this.dragTarget.dataset.id; const prefIds = getTabsOrderFromPreference(); const absoluteIds = toAbsoluteOrder(prefIds, currentTabIds, dragTargetId);
// Remove panel id which is not in panel definitions and addons list. const extensions = await AddonManager.getAllAddons(); const definitions = gDevTools.getToolDefinitionArray(); const result = absoluteIds.filter(
id =>
definitions.find(d => id === (d.extensionId || d.id)) ||
extensions.find(e => id === e.id)
);
// Calculate the minimum and maximum X-offset that can be valid for the drag target. const firstElement = tabElements[0]; const firstElementCenterX =
firstElement.offsetLeft + firstElement.clientWidth / 2; const lastElement = tabElements[tabElements.length - 1]; const lastElementCenterX =
lastElement.offsetLeft + lastElement.clientWidth / 2; const max = Math.max(firstElementCenterX, lastElementCenterX); const min = Math.min(firstElementCenterX, lastElementCenterX);
// Normalize the target center X so to remain between the first and last tab.
dragTargetCenterX = Math.min(max, dragTargetCenterX);
dragTargetCenterX = Math.max(min, dragTargetCenterX);
for (const tabElement of tabElements) { if (tabElement === this.dragTarget) {
isDragTargetPreviousSibling = true; continue;
}
// Is the dragTarget near the center of the other tab? const anotherCenterX = tabElement.offsetLeft + tabElement.clientWidth / 2; const distanceWithDragTarget = Math.abs(
dragTargetCenterX - anotherCenterX
); const isReplaceable = distanceWithDragTarget < tabElement.clientWidth / 3;
// To accomodate for RTL locales, we cannot rely on the first/last element of the // NodeList. We cannot have negative distances for the leftmost tab, and we cannot // have positive distances for the rightmost tab. const isFirstTab = this.isFirstTab(this.dragTarget); const isLastTab = this.isLastTab(this.dragTarget); const isLeftmostTab = this.isRTL() ? isLastTab : isFirstTab; const isRightmostTab = this.isRTL() ? isFirstTab : isLastTab;
if ((isLeftmostTab && distance < 0) || (isRightmostTab && distance > 0)) { // If the drag target is already edge of the tabs and the mouse will make the // element to move to same direction more, keep the position.
distance = 0;
}
async onMouseUp() { if (!this.dragTarget) { // The case in here has two type: // 1. Although destroy method was called, it was not during reordering. // 2. Although mouse event occur, destroy method was called during reordering. return;
}
if (this.isOrderUpdated) {
await this.saveOrderPreference();
// Log which tabs reordered. The question we want to answer is: // "How frequently are the tabs re-ordered, also which tabs get re-ordered?" const toolId = this.dragTarget.dataset.extensionId || this.dragTarget.dataset.id;
Glean.devtoolsToolbox.tabsReordered[toolId].add(1);
}
/* * This function returns absolute tab ids that were merged the both ids that are in * preference and tabs. * Some tabs added with add-ons etc show/hide depending on conditions. * However, all of tabs that include hidden tab always keep the relationship with * left side tab, except in case the left tab was target of dragging. If the left * tab has been moved, it keeps its relationship with the tab next to it. * * Case 1: Drag a tab to left * currentTabIds: [T1, T2, T3, T4, T5] * prefIds : [T1, T2, T3, E1(hidden), T4, T5] * drag T4 : [T1, T2, T4, T3, T5] * result : [T1, T2, T4, T3, E1, T5] * * Case 2: Drag a tab to right * currentTabIds: [T1, T2, T3, T4, T5] * prefIds : [T1, T2, T3, E1(hidden), T4, T5] * drag T2 : [T1, T3, T4, T2, T5] * result : [T1, T3, E1, T4, T2, T5] * * Case 3: Hidden tab was left end and drag a tab to left end * currentTabIds: [T1, T2, T3, T4, T5] * prefIds : [E1(hidden), T1, T2, T3, T4, T5] * drag T4 : [T4, T1, T2, T3, T5] * result : [E1, T4, T1, T2, T3, T5] * * Case 4: Hidden tab was right end and drag a tab to right end * currentTabIds: [T1, T2, T3, T4, T5] * prefIds : [T1, T2, T3, T4, T5, E1(hidden)] * drag T1 : [T2, T3, T4, T5, T1] * result : [T2, T3, T4, T5, E1, T1] * * @param Array - prefIds: id array of preference * @param Array - currentTabIds: id array of appearanced tabs * @param String - dragTargetId: id of dragged target * @return Array
*/ function toAbsoluteOrder(prefIds, currentTabIds, dragTargetId) {
currentTabIds = [...currentTabIds];
let indexAtCurrentTabs = 0;
for (const prefId of prefIds) { if (prefId === dragTargetId) { // do nothing
} elseif (currentTabIds.includes(prefId)) {
indexAtCurrentTabs = currentTabIds.indexOf(prefId) + 1;
} else {
currentTabIds.splice(indexAtCurrentTabs, 0, prefId);
indexAtCurrentTabs += 1;
}
}
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 ist noch experimentell.