зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1336198 - Part 7: Refactor box model logic into box-model.js. r=jdescottes
This commit is contained in:
Родитель
6998b44518
Коммит
c1527a2908
|
@ -0,0 +1,285 @@
|
||||||
|
/* 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 { Task } = require("devtools/shared/task");
|
||||||
|
const { getCssProperties } = require("devtools/shared/fronts/css-properties");
|
||||||
|
const { ReflowFront } = require("devtools/shared/fronts/reflow");
|
||||||
|
|
||||||
|
const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
|
||||||
|
|
||||||
|
const { updateLayout } = require("./actions/box-model");
|
||||||
|
|
||||||
|
const EditingSession = require("./utils/editing-session");
|
||||||
|
|
||||||
|
const NUMERIC = /^-?[\d\.]+$/;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A singleton instance of the box model controllers.
|
||||||
|
*
|
||||||
|
* @param {Inspector} inspector
|
||||||
|
* An instance of the Inspector currently loaded in the toolbox.
|
||||||
|
* @param {Window} window
|
||||||
|
* The document window of the toolbox.
|
||||||
|
*/
|
||||||
|
function BoxModel(inspector, window) {
|
||||||
|
this.document = window.document;
|
||||||
|
this.inspector = inspector;
|
||||||
|
this.store = inspector.store;
|
||||||
|
|
||||||
|
this.updateBoxModel = this.updateBoxModel.bind(this);
|
||||||
|
|
||||||
|
this.onHideBoxModelHighlighter = this.onHideBoxModelHighlighter.bind(this);
|
||||||
|
this.onNewSelection = this.onNewSelection.bind(this);
|
||||||
|
this.onShowBoxModelEditor = this.onShowBoxModelEditor.bind(this);
|
||||||
|
this.onShowBoxModelHighlighter = this.onShowBoxModelHighlighter.bind(this);
|
||||||
|
this.onSidebarSelect = this.onSidebarSelect.bind(this);
|
||||||
|
|
||||||
|
this.inspector.selection.on("new-node-front", this.onNewSelection);
|
||||||
|
this.inspector.sidebar.on("select", this.onSidebarSelect);
|
||||||
|
}
|
||||||
|
|
||||||
|
BoxModel.prototype = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destruction function called when the inspector is destroyed. Removes event listeners
|
||||||
|
* and cleans up references.
|
||||||
|
*/
|
||||||
|
destroy() {
|
||||||
|
this.inspector.selection.off("new-node-front", this.onNewSelection);
|
||||||
|
this.inspector.sidebar.off("select", this.onSidebarSelect);
|
||||||
|
|
||||||
|
if (this.reflowFront) {
|
||||||
|
this.untrackReflows();
|
||||||
|
this.reflowFront.destroy();
|
||||||
|
this.reflowFront = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.document = null;
|
||||||
|
this.inspector = null;
|
||||||
|
this.walker = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object containing the box model's handler functions used in the box
|
||||||
|
* model's React component props.
|
||||||
|
*/
|
||||||
|
getComponentProps() {
|
||||||
|
return {
|
||||||
|
onHideBoxModelHighlighter: this.onHideBoxModelHighlighter,
|
||||||
|
onShowBoxModelEditor: this.onShowBoxModelEditor,
|
||||||
|
onShowBoxModelHighlighter: this.onShowBoxModelHighlighter,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the layout panel is visible, and false otherwise.
|
||||||
|
*/
|
||||||
|
isPanelVisible() {
|
||||||
|
return this.inspector.toolbox.currentToolId === "inspector" &&
|
||||||
|
this.inspector.sidebar &&
|
||||||
|
this.inspector.sidebar.getCurrentTabID() === "layoutview";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the layout panel is visible and the current node is valid to
|
||||||
|
* be displayed in the view.
|
||||||
|
*/
|
||||||
|
isPanelVisibleAndNodeValid() {
|
||||||
|
return this.isPanelVisible() &&
|
||||||
|
this.inspector.selection.isConnected() &&
|
||||||
|
this.inspector.selection.isElementNode();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts listening to reflows in the current tab.
|
||||||
|
*/
|
||||||
|
trackReflows() {
|
||||||
|
if (!this.reflowFront) {
|
||||||
|
let { target } = this.inspector;
|
||||||
|
if (target.form.reflowActor) {
|
||||||
|
this.reflowFront = ReflowFront(target.client,
|
||||||
|
target.form);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reflowFront.on("reflows", this.updateBoxModel);
|
||||||
|
this.reflowFront.start();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops listening to reflows in the current tab.
|
||||||
|
*/
|
||||||
|
untrackReflows() {
|
||||||
|
if (!this.reflowFront) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reflowFront.off("reflows", this.updateBoxModel);
|
||||||
|
this.reflowFront.stop();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the box model panel by dispatching the new layout data.
|
||||||
|
*/
|
||||||
|
updateBoxModel() {
|
||||||
|
let lastRequest = Task.spawn((function* () {
|
||||||
|
if (!(this.isPanelVisible() &&
|
||||||
|
this.inspector.selection.isConnected() &&
|
||||||
|
this.inspector.selection.isElementNode())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = this.inspector.selection.nodeFront;
|
||||||
|
let layout = yield this.inspector.pageStyle.getLayout(node, {
|
||||||
|
autoMargins: true,
|
||||||
|
});
|
||||||
|
let styleEntries = yield this.inspector.pageStyle.getApplied(node, {});
|
||||||
|
this.elementRules = styleEntries.map(e => e.rule);
|
||||||
|
|
||||||
|
// Update the redux store with the latest layout properties and update the box
|
||||||
|
// model view.
|
||||||
|
this.store.dispatch(updateLayout(layout));
|
||||||
|
|
||||||
|
// If a subsequent request has been made, wait for that one instead.
|
||||||
|
if (this._lastRequest != lastRequest) {
|
||||||
|
return this._lastRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._lastRequest = null;
|
||||||
|
|
||||||
|
this.inspector.emit("boxmodel-view-updated");
|
||||||
|
return null;
|
||||||
|
}).bind(this)).catch(console.error);
|
||||||
|
|
||||||
|
this._lastRequest = lastRequest;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selection 'new-node-front' event handler.
|
||||||
|
*/
|
||||||
|
onNewSelection: function () {
|
||||||
|
if (!this.isPanelVisibleAndNodeValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateBoxModel();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the box-model highlighter on the currently selected element.
|
||||||
|
*/
|
||||||
|
onHideBoxModelHighlighter() {
|
||||||
|
let toolbox = this.inspector.toolbox;
|
||||||
|
toolbox.highlighterUtils.unhighlight();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the inplace editor when a box model editable value is clicked on the
|
||||||
|
* box model panel.
|
||||||
|
*
|
||||||
|
* @param {DOMNode} element
|
||||||
|
* The element that was clicked.
|
||||||
|
* @param {Event} event
|
||||||
|
* The event object.
|
||||||
|
* @param {String} property
|
||||||
|
* The name of the property.
|
||||||
|
*/
|
||||||
|
onShowBoxModelEditor(element, event, property) {
|
||||||
|
let session = new EditingSession({
|
||||||
|
inspector: this.inspector,
|
||||||
|
doc: this.document,
|
||||||
|
elementRules: this.elementRules,
|
||||||
|
});
|
||||||
|
let initialValue = session.getProperty(property);
|
||||||
|
|
||||||
|
let editor = new InplaceEditor({
|
||||||
|
element: element,
|
||||||
|
initial: initialValue,
|
||||||
|
contentType: InplaceEditor.CONTENT_TYPES.CSS_VALUE,
|
||||||
|
property: {
|
||||||
|
name: property
|
||||||
|
},
|
||||||
|
start: self => {
|
||||||
|
self.elt.parentNode.classList.add("boxmodel-editing");
|
||||||
|
},
|
||||||
|
change: value => {
|
||||||
|
if (NUMERIC.test(value)) {
|
||||||
|
value += "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
let properties = [
|
||||||
|
{ name: property, value: value }
|
||||||
|
];
|
||||||
|
|
||||||
|
if (property.substring(0, 7) == "border-") {
|
||||||
|
let bprop = property.substring(0, property.length - 5) + "style";
|
||||||
|
let style = session.getProperty(bprop);
|
||||||
|
if (!style || style == "none" || style == "hidden") {
|
||||||
|
properties.push({ name: bprop, value: "solid" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
session.setProperties(properties).catch(e => console.error(e));
|
||||||
|
},
|
||||||
|
done: (value, commit) => {
|
||||||
|
editor.elt.parentNode.classList.remove("boxmodel-editing");
|
||||||
|
if (!commit) {
|
||||||
|
session.revert().then(() => {
|
||||||
|
session.destroy();
|
||||||
|
}, e => console.error(e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let node = this.inspector.selection.nodeFront;
|
||||||
|
this.inspector.pageStyle.getLayout(node, {
|
||||||
|
autoMargins: true,
|
||||||
|
}).then(layout => {
|
||||||
|
this.store.dispatch(updateLayout(layout));
|
||||||
|
}, e => console.error(e));
|
||||||
|
},
|
||||||
|
contextMenu: this.inspector.onTextBoxContextMenu,
|
||||||
|
cssProperties: getCssProperties(this.inspector.toolbox)
|
||||||
|
}, event);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the box-model highlighter on the currently selected element.
|
||||||
|
*
|
||||||
|
* @param {Object} options
|
||||||
|
* Options passed to the highlighter actor.
|
||||||
|
*/
|
||||||
|
onShowBoxModelHighlighter(options = {}) {
|
||||||
|
let toolbox = this.inspector.toolbox;
|
||||||
|
let nodeFront = this.inspector.selection.nodeFront;
|
||||||
|
|
||||||
|
toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for the inspector sidebar select event. Starts listening for
|
||||||
|
* "grid-layout-changed" if the layout panel is visible. Otherwise, stop
|
||||||
|
* listening for grid layout changes. Finally, refresh the layout view if
|
||||||
|
* it is visible.
|
||||||
|
*/
|
||||||
|
onSidebarSelect() {
|
||||||
|
if (!this.isPanelVisible()) {
|
||||||
|
this.untrackReflows();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.inspector.selection.isConnected() &&
|
||||||
|
this.inspector.selection.isElementNode()) {
|
||||||
|
this.trackReflows();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateBoxModel();
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = BoxModel;
|
|
@ -12,5 +12,6 @@ DIRS += [
|
||||||
]
|
]
|
||||||
|
|
||||||
DevToolsModules(
|
DevToolsModules(
|
||||||
|
'box-model.js',
|
||||||
'types.js',
|
'types.js',
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,6 +23,7 @@ const Menu = require("devtools/client/framework/menu");
|
||||||
const MenuItem = require("devtools/client/framework/menu-item");
|
const MenuItem = require("devtools/client/framework/menu-item");
|
||||||
|
|
||||||
const {HTMLBreadcrumbs} = require("devtools/client/inspector/breadcrumbs");
|
const {HTMLBreadcrumbs} = require("devtools/client/inspector/breadcrumbs");
|
||||||
|
const BoxModel = require("devtools/client/inspector/boxmodel/box-model");
|
||||||
const {ComputedViewTool} = require("devtools/client/inspector/computed/computed");
|
const {ComputedViewTool} = require("devtools/client/inspector/computed/computed");
|
||||||
const {FontInspector} = require("devtools/client/inspector/fonts/fonts");
|
const {FontInspector} = require("devtools/client/inspector/fonts/fonts");
|
||||||
const {InspectorSearch} = require("devtools/client/inspector/inspector-search");
|
const {InspectorSearch} = require("devtools/client/inspector/inspector-search");
|
||||||
|
@ -573,6 +574,7 @@ Inspector.prototype = {
|
||||||
|
|
||||||
this.ruleview = new RuleViewTool(this, this.panelWin);
|
this.ruleview = new RuleViewTool(this, this.panelWin);
|
||||||
this.computedview = new ComputedViewTool(this, this.panelWin);
|
this.computedview = new ComputedViewTool(this, this.panelWin);
|
||||||
|
this.boxmodel = new BoxModel(this, this.panelWin);
|
||||||
|
|
||||||
if (Services.prefs.getBoolPref("devtools.layoutview.enabled")) {
|
if (Services.prefs.getBoolPref("devtools.layoutview.enabled")) {
|
||||||
const LayoutView = this.browserRequire("devtools/client/inspector/layout/layout");
|
const LayoutView = this.browserRequire("devtools/client/inspector/layout/layout");
|
||||||
|
|
|
@ -11,9 +11,10 @@ const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
const { LocalizationHelper } = require("devtools/shared/l10n");
|
||||||
|
|
||||||
const Accordion = createFactory(require("./Accordion"));
|
const Accordion = createFactory(require("./Accordion"));
|
||||||
const BoxModel = createFactory(require("./BoxModel"));
|
|
||||||
const Grid = createFactory(require("./Grid"));
|
const Grid = createFactory(require("./Grid"));
|
||||||
|
|
||||||
|
const BoxModel = createFactory(require("devtools/client/inspector/boxmodel/components/BoxModel"));
|
||||||
|
|
||||||
const Types = require("../types");
|
const Types = require("../types");
|
||||||
const { getStr } = require("../utils/l10n");
|
const { getStr } = require("../utils/l10n");
|
||||||
|
|
||||||
|
|
|
@ -6,16 +6,10 @@
|
||||||
|
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const { Task } = require("devtools/shared/task");
|
const { Task } = require("devtools/shared/task");
|
||||||
const { getCssProperties } = require("devtools/shared/fronts/css-properties");
|
|
||||||
const { ReflowFront } = require("devtools/shared/fronts/reflow");
|
|
||||||
|
|
||||||
const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
|
|
||||||
const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
|
const { createFactory, createElement } = require("devtools/client/shared/vendor/react");
|
||||||
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
const { Provider } = require("devtools/client/shared/vendor/react-redux");
|
||||||
|
|
||||||
const {
|
|
||||||
updateLayout,
|
|
||||||
} = require("./actions/box-model");
|
|
||||||
const {
|
const {
|
||||||
updateGridHighlighted,
|
updateGridHighlighted,
|
||||||
updateGrids,
|
updateGrids,
|
||||||
|
@ -27,13 +21,10 @@ const {
|
||||||
|
|
||||||
const App = createFactory(require("./components/App"));
|
const App = createFactory(require("./components/App"));
|
||||||
|
|
||||||
const EditingSession = require("./utils/editing-session");
|
|
||||||
|
|
||||||
const { LocalizationHelper } = require("devtools/shared/l10n");
|
const { LocalizationHelper } = require("devtools/shared/l10n");
|
||||||
const INSPECTOR_L10N =
|
const INSPECTOR_L10N =
|
||||||
new LocalizationHelper("devtools/client/locales/inspector.properties");
|
new LocalizationHelper("devtools/client/locales/inspector.properties");
|
||||||
|
|
||||||
const NUMERIC = /^-?[\d\.]+$/;
|
|
||||||
const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
|
const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
|
||||||
const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
|
const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
|
||||||
|
|
||||||
|
@ -44,18 +35,14 @@ function LayoutView(inspector, window) {
|
||||||
this.store = inspector.store;
|
this.store = inspector.store;
|
||||||
this.walker = this.inspector.walker;
|
this.walker = this.inspector.walker;
|
||||||
|
|
||||||
this.updateBoxModel = this.updateBoxModel.bind(this);
|
|
||||||
|
|
||||||
this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
|
this.onGridLayoutChange = this.onGridLayoutChange.bind(this);
|
||||||
this.onHighlighterChange = this.onHighlighterChange.bind(this);
|
this.onHighlighterChange = this.onHighlighterChange.bind(this);
|
||||||
this.onNewSelection = this.onNewSelection.bind(this);
|
|
||||||
this.onSidebarSelect = this.onSidebarSelect.bind(this);
|
this.onSidebarSelect = this.onSidebarSelect.bind(this);
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
|
this.highlighters.on("grid-highlighter-hidden", this.onHighlighterChange);
|
||||||
this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
|
this.highlighters.on("grid-highlighter-shown", this.onHighlighterChange);
|
||||||
this.inspector.selection.on("new-node-front", this.onNewSelection);
|
|
||||||
this.inspector.sidebar.on("select", this.onSidebarSelect);
|
this.inspector.sidebar.on("select", this.onSidebarSelect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +57,12 @@ LayoutView.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
onHideBoxModelHighlighter,
|
||||||
|
onShowBoxModelEditor,
|
||||||
|
onShowBoxModelHighlighter,
|
||||||
|
} = this.inspector.boxmodel.getComponentProps();
|
||||||
|
|
||||||
this.layoutInspector = yield this.inspector.walker.getLayoutInspector();
|
this.layoutInspector = yield this.inspector.walker.getLayoutInspector();
|
||||||
|
|
||||||
this.loadHighlighterSettings();
|
this.loadHighlighterSettings();
|
||||||
|
@ -81,95 +74,9 @@ LayoutView.prototype = {
|
||||||
*/
|
*/
|
||||||
showBoxModelProperties: true,
|
showBoxModelProperties: true,
|
||||||
|
|
||||||
/**
|
onHideBoxModelHighlighter,
|
||||||
* Hides the box-model highlighter on the currently selected element.
|
onShowBoxModelEditor,
|
||||||
*/
|
onShowBoxModelHighlighter,
|
||||||
onHideBoxModelHighlighter: () => {
|
|
||||||
let toolbox = this.inspector.toolbox;
|
|
||||||
toolbox.highlighterUtils.unhighlight();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the inplace editor when a box model editable value is clicked on the
|
|
||||||
* box model panel.
|
|
||||||
*
|
|
||||||
* @param {DOMNode} element
|
|
||||||
* The element that was clicked.
|
|
||||||
* @param {Event} event
|
|
||||||
* The event object.
|
|
||||||
* @param {String} property
|
|
||||||
* The name of the property.
|
|
||||||
*/
|
|
||||||
onShowBoxModelEditor: (element, event, property) => {
|
|
||||||
let session = new EditingSession({
|
|
||||||
inspector: this.inspector,
|
|
||||||
doc: this.document,
|
|
||||||
elementRules: this.elementRules,
|
|
||||||
});
|
|
||||||
let initialValue = session.getProperty(property);
|
|
||||||
|
|
||||||
let editor = new InplaceEditor({
|
|
||||||
element: element,
|
|
||||||
initial: initialValue,
|
|
||||||
contentType: InplaceEditor.CONTENT_TYPES.CSS_VALUE,
|
|
||||||
property: {
|
|
||||||
name: property
|
|
||||||
},
|
|
||||||
start: self => {
|
|
||||||
self.elt.parentNode.classList.add("boxmodel-editing");
|
|
||||||
},
|
|
||||||
change: value => {
|
|
||||||
if (NUMERIC.test(value)) {
|
|
||||||
value += "px";
|
|
||||||
}
|
|
||||||
|
|
||||||
let properties = [
|
|
||||||
{ name: property, value: value }
|
|
||||||
];
|
|
||||||
|
|
||||||
if (property.substring(0, 7) == "border-") {
|
|
||||||
let bprop = property.substring(0, property.length - 5) + "style";
|
|
||||||
let style = session.getProperty(bprop);
|
|
||||||
if (!style || style == "none" || style == "hidden") {
|
|
||||||
properties.push({ name: bprop, value: "solid" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
session.setProperties(properties).catch(e => console.error(e));
|
|
||||||
},
|
|
||||||
done: (value, commit) => {
|
|
||||||
editor.elt.parentNode.classList.remove("boxmodel-editing");
|
|
||||||
if (!commit) {
|
|
||||||
session.revert().then(() => {
|
|
||||||
session.destroy();
|
|
||||||
}, e => console.error(e));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let node = this.inspector.selection.nodeFront;
|
|
||||||
this.inspector.pageStyle.getLayout(node, {
|
|
||||||
autoMargins: true,
|
|
||||||
}).then(layout => {
|
|
||||||
this.store.dispatch(updateLayout(layout));
|
|
||||||
}, e => console.error(e));
|
|
||||||
},
|
|
||||||
contextMenu: this.inspector.onTextBoxContextMenu,
|
|
||||||
cssProperties: getCssProperties(this.inspector.toolbox)
|
|
||||||
}, event);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the box-model highlighter on the currently selected element.
|
|
||||||
*
|
|
||||||
* @param {Object} options
|
|
||||||
* Options passed to the highlighter actor.
|
|
||||||
*/
|
|
||||||
onShowBoxModelHighlighter: (options = {}) => {
|
|
||||||
let toolbox = this.inspector.toolbox;
|
|
||||||
let nodeFront = this.inspector.selection.nodeFront;
|
|
||||||
|
|
||||||
toolbox.highlighterUtils.highlightNodeFront(nodeFront, options);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for a change in the input checkboxes in the GridList component.
|
* Handler for a change in the input checkboxes in the GridList component.
|
||||||
|
@ -253,16 +160,9 @@ LayoutView.prototype = {
|
||||||
destroy() {
|
destroy() {
|
||||||
this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
|
this.highlighters.off("grid-highlighter-hidden", this.onHighlighterChange);
|
||||||
this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
|
this.highlighters.off("grid-highlighter-shown", this.onHighlighterChange);
|
||||||
this.inspector.selection.off("new-node-front", this.onNewSelection);
|
|
||||||
this.inspector.sidebar.off("select", this.onSidebarSelect);
|
this.inspector.sidebar.off("select", this.onSidebarSelect);
|
||||||
this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
|
this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
|
||||||
|
|
||||||
if (this.reflowFront) {
|
|
||||||
this.untrackReflows();
|
|
||||||
this.reflowFront.destroy();
|
|
||||||
this.reflowFront = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.document = null;
|
this.document = null;
|
||||||
this.inspector = null;
|
this.inspector = null;
|
||||||
this.layoutInspector = null;
|
this.layoutInspector = null;
|
||||||
|
@ -279,16 +179,6 @@ LayoutView.prototype = {
|
||||||
this.inspector.sidebar.getCurrentTabID() === "layoutview";
|
this.inspector.sidebar.getCurrentTabID() === "layoutview";
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the layout panel is visible and the current node is valid to
|
|
||||||
* be displayed in the view.
|
|
||||||
*/
|
|
||||||
isPanelVisibleAndNodeValid() {
|
|
||||||
return this.isPanelVisible() &&
|
|
||||||
this.inspector.selection.isConnected() &&
|
|
||||||
this.inspector.selection.isElementNode();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the grid highligher display settings into the store from the stored preferences.
|
* Load the grid highligher display settings into the store from the stored preferences.
|
||||||
*/
|
*/
|
||||||
|
@ -302,72 +192,6 @@ LayoutView.prototype = {
|
||||||
dispatch(updateShowInfiniteLines(showInfinteLines));
|
dispatch(updateShowInfiniteLines(showInfinteLines));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts listening to reflows in the current tab.
|
|
||||||
*/
|
|
||||||
trackReflows() {
|
|
||||||
if (!this.reflowFront) {
|
|
||||||
let { target } = this.inspector;
|
|
||||||
if (target.form.reflowActor) {
|
|
||||||
this.reflowFront = ReflowFront(target.client,
|
|
||||||
target.form);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.reflowFront.on("reflows", this.updateBoxModel);
|
|
||||||
this.reflowFront.start();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops listening to reflows in the current tab.
|
|
||||||
*/
|
|
||||||
untrackReflows() {
|
|
||||||
if (!this.reflowFront) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.reflowFront.off("reflows", this.updateBoxModel);
|
|
||||||
this.reflowFront.stop();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the box model panel by dispatching the new layout data.
|
|
||||||
*/
|
|
||||||
updateBoxModel() {
|
|
||||||
let lastRequest = Task.spawn((function* () {
|
|
||||||
if (!(this.isPanelVisible() &&
|
|
||||||
this.inspector.selection.isConnected() &&
|
|
||||||
this.inspector.selection.isElementNode())) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let node = this.inspector.selection.nodeFront;
|
|
||||||
let layout = yield this.inspector.pageStyle.getLayout(node, {
|
|
||||||
autoMargins: true,
|
|
||||||
});
|
|
||||||
let styleEntries = yield this.inspector.pageStyle.getApplied(node, {});
|
|
||||||
this.elementRules = styleEntries.map(e => e.rule);
|
|
||||||
|
|
||||||
// Update the redux store with the latest layout properties and update the box
|
|
||||||
// model view.
|
|
||||||
this.store.dispatch(updateLayout(layout));
|
|
||||||
|
|
||||||
// If a subsequent request has been made, wait for that one instead.
|
|
||||||
if (this._lastRequest != lastRequest) {
|
|
||||||
return this._lastRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._lastRequest = null;
|
|
||||||
|
|
||||||
this.inspector.emit("boxmodel-view-updated");
|
|
||||||
return null;
|
|
||||||
}).bind(this)).catch(console.error);
|
|
||||||
|
|
||||||
this._lastRequest = lastRequest;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the grid panel by dispatching the new grid data. This is called when the
|
* Updates the grid panel by dispatching the new grid data. This is called when the
|
||||||
* layout view becomes visible or the view needs to be updated with new grid data.
|
* layout view becomes visible or the view needs to be updated with new grid data.
|
||||||
|
@ -429,17 +253,6 @@ LayoutView.prototype = {
|
||||||
this.store.dispatch(updateGridHighlighted(nodeFront, highlighted));
|
this.store.dispatch(updateGridHighlighted(nodeFront, highlighted));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Selection 'new-node-front' event handler.
|
|
||||||
*/
|
|
||||||
onNewSelection: function () {
|
|
||||||
if (!this.isPanelVisibleAndNodeValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updateBoxModel();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for the inspector sidebar select event. Starts listening for
|
* Handler for the inspector sidebar select event. Starts listening for
|
||||||
* "grid-layout-changed" if the layout panel is visible. Otherwise, stop
|
* "grid-layout-changed" if the layout panel is visible. Otherwise, stop
|
||||||
|
@ -449,17 +262,10 @@ LayoutView.prototype = {
|
||||||
onSidebarSelect() {
|
onSidebarSelect() {
|
||||||
if (!this.isPanelVisible()) {
|
if (!this.isPanelVisible()) {
|
||||||
this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
|
this.layoutInspector.off("grid-layout-changed", this.onGridLayoutChange);
|
||||||
this.untrackReflows();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.inspector.selection.isConnected() &&
|
|
||||||
this.inspector.selection.isElementNode()) {
|
|
||||||
this.trackReflows();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
|
this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
|
||||||
this.updateBoxModel();
|
|
||||||
this.updateGridPanel();
|
this.updateGridPanel();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ const Services = devtools.require("Services");
|
||||||
const { AppConstants } = devtools.require("resource://gre/modules/AppConstants.jsm");
|
const { AppConstants } = devtools.require("resource://gre/modules/AppConstants.jsm");
|
||||||
|
|
||||||
const BROWSER_BASED_DIRS = [
|
const BROWSER_BASED_DIRS = [
|
||||||
|
"resource://devtools/client/inspector/boxmodel",
|
||||||
"resource://devtools/client/inspector/layout",
|
"resource://devtools/client/inspector/layout",
|
||||||
"resource://devtools/client/jsonview",
|
"resource://devtools/client/jsonview",
|
||||||
"resource://devtools/client/shared/vendor",
|
"resource://devtools/client/shared/vendor",
|
||||||
|
|
Загрузка…
Ссылка в новой задаче