202 lines
6.7 KiB
JavaScript
202 lines
6.7 KiB
JavaScript
/* 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 {
|
|
createFactory,
|
|
createRef,
|
|
PureComponent,
|
|
} = require("resource://devtools/client/shared/vendor/react.mjs");
|
|
const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
|
|
const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");
|
|
const {
|
|
connect,
|
|
} = require("resource://devtools/client/shared/vendor/react-redux.js");
|
|
const {
|
|
getSelectorFromGrip,
|
|
translateNodeFrontToGrip,
|
|
} = require("resource://devtools/client/inspector/shared/utils.js");
|
|
const { LocalizationHelper } = require("resource://devtools/shared/l10n.js");
|
|
|
|
const Accordion = createFactory(
|
|
require("resource://devtools/client/shared/components/Accordion.js")
|
|
);
|
|
const BoxModel = createFactory(
|
|
require("resource://devtools/client/inspector/boxmodel/components/BoxModel.js")
|
|
);
|
|
const Flexbox = createFactory(
|
|
require("resource://devtools/client/inspector/flexbox/components/Flexbox.js")
|
|
);
|
|
const Grid = createFactory(
|
|
require("resource://devtools/client/inspector/grids/components/Grid.js")
|
|
);
|
|
|
|
const BoxModelTypes = require("resource://devtools/client/inspector/boxmodel/types.js");
|
|
const FlexboxTypes = require("resource://devtools/client/inspector/flexbox/types.js");
|
|
const GridTypes = require("resource://devtools/client/inspector/grids/types.js");
|
|
|
|
const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
|
|
const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
|
|
|
|
const LAYOUT_STRINGS_URI = "devtools/client/locales/layout.properties";
|
|
const LAYOUT_L10N = new LocalizationHelper(LAYOUT_STRINGS_URI);
|
|
|
|
const FLEXBOX_OPENED_PREF = "devtools.layout.flexbox.opened";
|
|
const FLEX_CONTAINER_OPENED_PREF = "devtools.layout.flex-container.opened";
|
|
const FLEX_ITEM_OPENED_PREF = "devtools.layout.flex-item.opened";
|
|
const GRID_OPENED_PREF = "devtools.layout.grid.opened";
|
|
const BOXMODEL_OPENED_PREF = "devtools.layout.boxmodel.opened";
|
|
|
|
class LayoutApp extends PureComponent {
|
|
static get propTypes() {
|
|
return {
|
|
boxModel: PropTypes.shape(BoxModelTypes.boxModel).isRequired,
|
|
dispatch: PropTypes.func.isRequired,
|
|
flexbox: PropTypes.shape(FlexboxTypes.flexbox).isRequired,
|
|
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
|
|
grids: PropTypes.arrayOf(PropTypes.shape(GridTypes.grid)).isRequired,
|
|
highlighterSettings: PropTypes.shape(GridTypes.highlighterSettings)
|
|
.isRequired,
|
|
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
|
|
onSetGridOverlayColor: PropTypes.func.isRequired,
|
|
onShowBoxModelEditor: PropTypes.func.isRequired,
|
|
onShowGridOutlineHighlight: PropTypes.func,
|
|
onToggleGeometryEditor: PropTypes.func.isRequired,
|
|
onToggleGridHighlighter: PropTypes.func.isRequired,
|
|
onToggleShowGridAreas: PropTypes.func.isRequired,
|
|
onToggleShowGridLineNumbers: PropTypes.func.isRequired,
|
|
onToggleShowInfiniteLines: PropTypes.func.isRequired,
|
|
setSelectedNode: PropTypes.func.isRequired,
|
|
showBoxModelProperties: PropTypes.bool.isRequired,
|
|
};
|
|
}
|
|
|
|
constructor(props) {
|
|
super(props);
|
|
this.containerRef = createRef();
|
|
|
|
this.scrollToTop = this.scrollToTop.bind(this);
|
|
}
|
|
|
|
getBoxModelSection() {
|
|
return {
|
|
component: BoxModel,
|
|
componentProps: this.props,
|
|
contentClassName: "layout-content",
|
|
header: BOXMODEL_L10N.getStr("boxmodel.title"),
|
|
id: "layout-section-boxmodel",
|
|
opened: Services.prefs.getBoolPref(BOXMODEL_OPENED_PREF),
|
|
onToggle: opened => {
|
|
Services.prefs.setBoolPref(BOXMODEL_OPENED_PREF, opened);
|
|
},
|
|
};
|
|
}
|
|
|
|
getFlexAccordionData(flexContainer) {
|
|
if (!flexContainer.actorID) {
|
|
// No flex container or flex item selected.
|
|
return {
|
|
pref: FLEXBOX_OPENED_PREF,
|
|
id: "layout-section-flex",
|
|
header: LAYOUT_L10N.getStr("flexbox.header"),
|
|
};
|
|
} else if (!flexContainer.flexItemShown) {
|
|
// No flex item selected.
|
|
return {
|
|
pref: FLEX_CONTAINER_OPENED_PREF,
|
|
id: "layout-section-flex-container",
|
|
header: LAYOUT_L10N.getStr("flexbox.flexContainer"),
|
|
};
|
|
}
|
|
|
|
return {
|
|
pref: FLEX_ITEM_OPENED_PREF,
|
|
id: "layout-section-flex-item",
|
|
header: LAYOUT_L10N.getFormatStr(
|
|
"flexbox.flexItemOf",
|
|
getSelectorFromGrip(translateNodeFrontToGrip(flexContainer.nodeFront))
|
|
),
|
|
};
|
|
}
|
|
|
|
getFlexSection(flexContainer) {
|
|
const { pref, id, header } = this.getFlexAccordionData(flexContainer);
|
|
|
|
return {
|
|
className: "flex-accordion",
|
|
component: Flexbox,
|
|
componentProps: {
|
|
...this.props,
|
|
flexContainer,
|
|
scrollToTop: this.scrollToTop,
|
|
},
|
|
contentClassName: "layout-content",
|
|
header,
|
|
id,
|
|
opened: Services.prefs.getBoolPref(pref),
|
|
onToggle: opened => {
|
|
Services.prefs.setBoolPref(pref, opened);
|
|
},
|
|
};
|
|
}
|
|
|
|
getGridSection() {
|
|
return {
|
|
component: Grid,
|
|
componentProps: this.props,
|
|
contentClassName: "layout-content",
|
|
header: LAYOUT_L10N.getStr("layout.header"),
|
|
id: "layout-grid-section",
|
|
opened: Services.prefs.getBoolPref(GRID_OPENED_PREF),
|
|
onToggle: opened => {
|
|
Services.prefs.setBoolPref(GRID_OPENED_PREF, opened);
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Scrolls to the top of the layout container.
|
|
*/
|
|
scrollToTop() {
|
|
this.containerRef.current.scrollTop = 0;
|
|
}
|
|
|
|
render() {
|
|
const { flexContainer, flexItemContainer } = this.props.flexbox;
|
|
|
|
const items = [
|
|
this.getFlexSection(flexContainer),
|
|
this.getGridSection(),
|
|
this.getBoxModelSection(),
|
|
];
|
|
|
|
// If the current selected node is both a flex container and flex item. Render
|
|
// an extra accordion with another Flexbox component where the node is shown as an
|
|
// item of its parent flex container.
|
|
// If the node was selected from the markup-view, then show this accordion after the
|
|
// container accordion. Otherwise show it first.
|
|
// The reason is that if the user selects an item-container in the markup view, it
|
|
// is assumed that they want to primarily see that element as a container, so the
|
|
// container info should be at the top.
|
|
if (flexItemContainer?.actorID) {
|
|
items.splice(
|
|
this.props.flexbox.initiatedByMarkupViewSelection ? 1 : 0,
|
|
0,
|
|
this.getFlexSection(flexItemContainer)
|
|
);
|
|
}
|
|
|
|
return dom.div(
|
|
{
|
|
className: "layout-container",
|
|
ref: this.containerRef,
|
|
role: "document",
|
|
},
|
|
Accordion({ items })
|
|
);
|
|
}
|
|
}
|
|
|
|
module.exports = connect(state => state)(LayoutApp);
|