Bug 1478397 - Part 19: Show both the flex container and flex item sizing properties when the selected element is both a flex item and container. r=pbro

This commit is contained in:
Gabriel Luong 2018-10-05 15:30:00 -04:00
Родитель ae143565fe
Коммит 3e721cf4f1
15 изменённых файлов: 306 добавлений и 211 удалений

Просмотреть файл

@ -6,7 +6,6 @@
const {
CLEAR_FLEXBOX,
TOGGLE_FLEX_ITEM_SHOWN,
UPDATE_FLEXBOX,
UPDATE_FLEXBOX_COLOR,
UPDATE_FLEXBOX_HIGHLIGHTED,
@ -23,21 +22,6 @@ module.exports = {
};
},
/**
* Toggles the display of flex item sizing information shown for the given flex item
* actor ID.
*
* @param {NodeFront} nodeFront
* The NodeFront of the flex item to toggle the sizing information displayed
* for.
*/
toggleFlexItemShown(nodeFront) {
return {
type: TOGGLE_FLEX_ITEM_SHOWN,
nodeFront,
};
},
/**
* Updates the flexbox state with the newly selected flexbox.
*/

Просмотреть файл

@ -11,9 +11,6 @@ createEnum([
// Clears the flexbox state by resetting it back to the initial flexbox state.
"CLEAR_FLEXBOX",
// Toggles the display of flex item sizing information shown.
"TOGGLE_FLEX_ITEM_SHOWN",
// Updates the flexbox state with the newly selected flexbox.
"UPDATE_FLEXBOX",

Просмотреть файл

@ -12,6 +12,7 @@ const {
} = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const { translateNodeFrontToGrip } = require("devtools/client/inspector/shared/utils");
const { REPS, MODE } = require("devtools/client/shared/components/reps/reps");
@ -23,7 +24,8 @@ const Types = require("../types");
class FlexContainer extends PureComponent {
static get propTypes() {
return {
flexbox: PropTypes.shape(Types.flexbox).isRequired,
color: PropTypes.string.isRequired,
flexContainer: PropTypes.shape(Types.flexContainer).isRequired,
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
@ -43,23 +45,17 @@ class FlexContainer extends PureComponent {
}
componentDidMount() {
const {
flexbox,
getSwatchColorPickerTooltip,
onSetFlexboxOverlayColor,
} = this.props;
const tooltip = getSwatchColorPickerTooltip();
const tooltip = this.props.getSwatchColorPickerTooltip();
let previousColor;
tooltip.addSwatch(this.swatchEl.current, {
onCommit: this.setFlexboxColor,
onPreview: this.setFlexboxColor,
onRevert: () => {
onSetFlexboxOverlayColor(previousColor);
this.props.onSetFlexboxOverlayColor(previousColor);
},
onShow: () => {
previousColor = flexbox.color;
previousColor = this.props.color;
},
});
}
@ -75,21 +71,18 @@ class FlexContainer extends PureComponent {
}
onFlexboxInspectIconClick(nodeFront) {
const { setSelectedNode } = this.props;
setSelectedNode(nodeFront, { reason: "layout-panel" });
this.props.setSelectedNode(nodeFront, { reason: "layout-panel" });
nodeFront.scrollIntoView().catch(e => console.error(e));
}
render() {
const {
flexbox,
color,
flexContainer,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
} = this.props;
const {
color,
nodeFront,
} = flexbox;
const { nodeFront } = flexContainer;
return createElement(Fragment, null,
Rep({
@ -123,4 +116,10 @@ class FlexContainer extends PureComponent {
}
}
module.exports = FlexContainer;
const mapStateToProps = state => {
return {
color: state.flexbox.color,
};
};
module.exports = connect(mapStateToProps)(FlexContainer);

Просмотреть файл

@ -23,23 +23,19 @@ class FlexItem extends PureComponent {
static get propTypes() {
return {
flexItem: PropTypes.shape(Types.flexItem).isRequired,
onToggleFlexItemShown: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
};
}
render() {
const {
flexItem,
onToggleFlexItemShown,
} = this.props;
const { nodeFront } = flexItem;
const { nodeFront } = this.props.flexItem;
return (
dom.li({},
dom.button(
{
className: "devtools-button devtools-monospace",
onClick: () => onToggleFlexItemShown(nodeFront),
onClick: () => this.props.setSelectedNode(nodeFront),
},
Rep({
defaultRep: Rep.ElementNode,

Просмотреть файл

@ -16,14 +16,14 @@ class FlexItemList extends PureComponent {
static get propTypes() {
return {
flexItems: PropTypes.arrayOf(PropTypes.shape(Types.flexItem)).isRequired,
onToggleFlexItemShown: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
};
}
render() {
const {
flexItems,
onToggleFlexItemShown,
setSelectedNode,
} = this.props;
return (
@ -32,7 +32,7 @@ class FlexItemList extends PureComponent {
flexItems.map(flexItem => FlexItem({
key: flexItem.actorID,
flexItem,
onToggleFlexItemShown,
setSelectedNode,
}))
)
);

Просмотреть файл

@ -25,7 +25,7 @@ class FlexItemSelector extends PureComponent {
return {
flexItem: PropTypes.shape(Types.flexItem).isRequired,
flexItems: PropTypes.arrayOf(PropTypes.shape(Types.flexItem)).isRequired,
onToggleFlexItemShown: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
};
}
@ -38,7 +38,7 @@ class FlexItemSelector extends PureComponent {
const {
flexItem,
flexItems,
onToggleFlexItemShown,
setSelectedNode,
} = this.props;
const menuItems = [];
@ -48,7 +48,7 @@ class FlexItemSelector extends PureComponent {
label: getSelectorFromGrip(grip),
type: "checkbox",
checked: item === flexItem,
click: () => onToggleFlexItemShown(item.nodeFront),
click: () => setSelectedNode(item.nodeFront),
});
}

Просмотреть файл

@ -27,67 +27,68 @@ const Types = require("../types");
class Flexbox extends PureComponent {
static get propTypes() {
return {
flexbox: PropTypes.shape(Types.flexbox).isRequired,
flexContainer: PropTypes.shape(Types.flexContainer).isRequired,
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
onToggleFlexboxHighlighter: PropTypes.func.isRequired,
onToggleFlexItemShown: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
};
}
renderFlexItemList() {
const {
flexbox,
onToggleFlexItemShown,
} = this.props;
const {
flexItems,
flexItemShown,
} = flexbox;
if (flexItemShown || !flexItems.length) {
renderFlexContainerProperties() {
// Don't show the flex container properties for the parent flex container of the
// selected element.
if (this.props.flexContainer.isFlexItemContainer) {
return null;
}
return FlexItemList({
flexItems,
onToggleFlexItemShown,
return FlexContainerProperties({
properties: this.props.flexContainer.properties,
});
}
renderFlexItemSizingProperties() {
const { flexbox } = this.props;
renderFlexItemList() {
const { setSelectedNode } = this.props;
const { flexItems } = this.props.flexContainer;
return FlexItemList({
flexItems,
setSelectedNode,
});
}
renderFlexItemSizing() {
const {
flexItems,
flexItemShown,
} = flexbox;
properties,
} = this.props.flexContainer;
if (!flexItemShown) {
const flexItem = flexItems.find(item => item.nodeFront.actorID === flexItemShown);
if (!flexItem) {
return null;
}
return FlexItemSizingProperties({
flexDirection: flexbox.properties["flex-direction"],
flexItem: flexItems.find(item => item.nodeFront.actorID === flexItemShown),
flexDirection: properties["flex-direction"],
flexItem,
});
}
render() {
const {
flexbox,
flexContainer,
getSwatchColorPickerTooltip,
onHideBoxModelHighlighter,
onSetFlexboxOverlayColor,
onShowBoxModelHighlighterForNode,
onToggleFlexboxHighlighter,
onToggleFlexItemShown,
setSelectedNode,
} = this.props;
if (!flexbox.actorID) {
if (!flexContainer.actorID) {
return (
dom.div({ className: "devtools-sidepanel-no-result" },
getStr("flexbox.noFlexboxeOnThisPage")
@ -95,23 +96,25 @@ class Flexbox extends PureComponent {
);
}
const {
flexItems,
flexItemShown,
} = flexContainer;
return (
dom.div({ id: "layout-flexbox-container" },
Header({
flexbox,
flexContainer,
getSwatchColorPickerTooltip,
onHideBoxModelHighlighter,
onSetFlexboxOverlayColor,
onShowBoxModelHighlighterForNode,
onToggleFlexboxHighlighter,
onToggleFlexItemShown,
setSelectedNode,
}),
this.renderFlexItemList(),
this.renderFlexItemSizingProperties(),
FlexContainerProperties({
properties: flexbox.properties,
})
!flexItemShown && flexItems.length > 0 ? this.renderFlexItemList() : null,
flexItemShown ? this.renderFlexItemSizing() : null,
this.renderFlexContainerProperties()
)
);
}

Просмотреть файл

@ -4,9 +4,15 @@
"use strict";
const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
const {
createElement,
createFactory,
Fragment,
PureComponent,
} = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const FlexContainer = createFactory(require("./FlexContainer"));
const FlexItemSelector = createFactory(require("./FlexItemSelector"));
@ -16,13 +22,13 @@ const Types = require("../types");
class Header extends PureComponent {
static get propTypes() {
return {
flexbox: PropTypes.shape(Types.flexbox).isRequired,
flexContainer: PropTypes.shape(Types.flexContainer).isRequired,
getSwatchColorPickerTooltip: PropTypes.func.isRequired,
highlighted: PropTypes.bool.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
onToggleFlexboxHighlighter: PropTypes.func.isRequired,
onToggleFlexItemShown: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
};
}
@ -33,21 +39,34 @@ class Header extends PureComponent {
}
onFlexboxCheckboxClick() {
const {
flexbox,
onToggleFlexboxHighlighter,
} = this.props;
this.props.onToggleFlexboxHighlighter(this.props.flexContainer.nodeFront);
}
onToggleFlexboxHighlighter(flexbox.nodeFront);
renderFlexboxHighlighterToggle() {
// Don't show the flexbox highlighter toggle for the parent flex container of the
// selected element.
if (this.props.flexContainer.isFlexItemContainer) {
return null;
}
return createElement(Fragment, null,
dom.div({ className: "devtools-separator" }),
dom.input({
className: "devtools-checkbox-toggle",
checked: this.props.highlighted,
onChange: this.onFlexboxCheckboxClick,
type: "checkbox",
})
);
}
renderFlexContainer() {
if (this.props.flexbox.flexItemShown) {
if (this.props.flexContainer.flexItemShown) {
return null;
}
const {
flexbox,
flexContainer,
getSwatchColorPickerTooltip,
onHideBoxModelHighlighter,
onSetFlexboxOverlayColor,
@ -56,7 +75,7 @@ class Header extends PureComponent {
} = this.props;
return FlexContainer({
flexbox,
flexContainer,
getSwatchColorPickerTooltip,
onHideBoxModelHighlighter,
onSetFlexboxOverlayColor,
@ -66,42 +85,42 @@ class Header extends PureComponent {
}
renderFlexItemSelector() {
if (!this.props.flexbox.flexItemShown) {
if (!this.props.flexContainer.flexItemShown) {
return null;
}
const {
flexbox,
onToggleFlexItemShown,
flexContainer,
setSelectedNode,
} = this.props;
const {
flexItems,
flexItemShown,
} = flexbox;
} = flexContainer;
return FlexItemSelector({
flexItem: flexItems.find(item => item.nodeFront.actorID === flexItemShown),
flexItems,
onToggleFlexItemShown,
setSelectedNode,
});
}
render() {
const {
flexbox,
onToggleFlexItemShown,
flexContainer,
setSelectedNode,
} = this.props;
const {
flexItemShown,
highlighted,
} = flexbox;
nodeFront,
} = flexContainer;
return (
dom.div({ className: "flex-header devtools-monospace" },
flexItemShown ?
dom.button({
className: "flex-header-button-prev devtools-button",
onClick: () => onToggleFlexItemShown(),
onClick: () => setSelectedNode(nodeFront),
})
:
null,
@ -113,16 +132,16 @@ class Header extends PureComponent {
this.renderFlexContainer(),
this.renderFlexItemSelector()
),
dom.div({ className: "devtools-separator" }),
dom.input({
className: "devtools-checkbox-toggle",
checked: highlighted,
onChange: this.onFlexboxCheckboxClick,
type: "checkbox",
})
this.renderFlexboxHighlighterToggle()
)
);
}
}
module.exports = Header;
const mapStateToProps = state => {
return {
highlighted: state.flexbox.highlighted,
};
};
module.exports = connect(mapStateToProps)(Header);

Просмотреть файл

@ -9,7 +9,6 @@ const { throttle } = require("devtools/shared/throttle");
const {
clearFlexbox,
toggleFlexItemShown,
updateFlexbox,
updateFlexboxColor,
updateFlexboxHighlighted,
@ -35,7 +34,6 @@ class FlexboxInspector {
this.onSetFlexboxOverlayColor = this.onSetFlexboxOverlayColor.bind(this);
this.onSidebarSelect = this.onSidebarSelect.bind(this);
this.onToggleFlexboxHighlighter = this.onToggleFlexboxHighlighter.bind(this);
this.onToggleFlexItemShown = this.onToggleFlexItemShown.bind(this);
this.onUpdatePanel = this.onUpdatePanel.bind(this);
this.init();
@ -105,11 +103,55 @@ class FlexboxInspector {
this.walker = null;
}
/**
* If the current selected node is a flex container, check if it is also a flex item of
* a parent flex container and get its parent flex container if any and returns an
* object that consists of the parent flex container's items and properties.
*
* @param {NodeFront} containerNodeFront
* The current flex container of the selected node.
* @return {Object} consiting of the parent flex container's flex items and properties.
*/
async getAsFlexItem(containerNodeFront) {
// If the current selected node is not a flex container, we know it is a flex item.
// No need to look for the parent flex container.
if (containerNodeFront !== this.selection.nodeFront) {
return null;
}
const flexboxFront = await this.layoutInspector.getCurrentFlexbox(
this.selection.nodeFront, true);
if (!flexboxFront) {
return null;
}
containerNodeFront = flexboxFront.containerNodeFront;
if (!containerNodeFront) {
containerNodeFront = await this.walker.getNodeFromActor(flexboxFront.actorID,
["containerEl"]);
}
let flexItemContainer = null;
if (flexboxFront) {
const flexItems = await this.getFlexItems(flexboxFront);
flexItemContainer = {
actorID: flexboxFront.actorID,
flexItems,
flexItemShown: this.selection.nodeFront.actorID,
isFlexItemContainer: true,
nodeFront: containerNodeFront,
properties: flexboxFront.properties,
};
}
return flexItemContainer;
}
getComponentProps() {
return {
onSetFlexboxOverlayColor: this.onSetFlexboxOverlayColor,
onToggleFlexboxHighlighter: this.onToggleFlexboxHighlighter,
onToggleFlexItemShown: this.onToggleFlexItemShown,
};
}
@ -230,7 +272,8 @@ class FlexboxInspector {
onHighlighterChange(highlighted, nodeFront) {
const { flexbox } = this.store.getState();
if (flexbox.nodeFront === nodeFront && flexbox.highlighted !== highlighted) {
if (flexbox.flexContainer.nodeFront === nodeFront &&
flexbox.highlighted !== highlighted) {
this.store.dispatch(updateFlexboxHighlighted(highlighted));
}
}
@ -341,24 +384,6 @@ class FlexboxInspector {
this.highlighters.flexboxHighlighterShow));
}
/**
* Handler for a change in the input checkbox in the FlexItem and Header component.
* Toggles on/off the flex item highlighter for the provided flex item element and
* changes the selection to the given node.
*
* @param {NodeFront|null} node
* The NodeFront of the flex item element for which the flex item is toggled
* on/off for.
*/
onToggleFlexItemShown(node) {
this.highlighters.toggleFlexItemHighlighter(node);
this.store.dispatch(toggleFlexItemShown(node));
if (node) {
this.selection.setNodeFront(node);
}
}
/**
* Handler for "new-root" event fired by the inspector and "new-node-front" event fired
* by the inspector selection. Updates the flexbox panel if it is visible.
@ -412,6 +437,7 @@ class FlexboxInspector {
["containerEl"]);
}
const flexItemContainer = await this.getAsFlexItem(containerNodeFront);
const flexItems = await this.getFlexItems(flexboxFront);
// If the current selected node is a flex item, display its flex item sizing
// properties.
@ -422,13 +448,17 @@ class FlexboxInspector {
const color = await this.getOverlayColor();
this.store.dispatch(updateFlexbox({
actorID: flexboxFront.actorID,
color,
flexItems,
flexItemShown: flexItemShown ? flexItemShown.nodeFront.actorID : null,
flexContainer: {
actorID: flexboxFront.actorID,
flexItems,
flexItemShown: flexItemShown ? flexItemShown.nodeFront.actorID : null,
isFlexItemContainer: false,
nodeFront: containerNodeFront,
properties: flexboxFront.properties,
},
flexItemContainer,
highlighted,
nodeFront: containerNodeFront,
properties: flexboxFront.properties,
}));
} catch (e) {
// This call might fail if called asynchrously after the toolbox is finished

Просмотреть файл

@ -6,27 +6,51 @@
const {
CLEAR_FLEXBOX,
TOGGLE_FLEX_ITEM_SHOWN,
UPDATE_FLEXBOX,
UPDATE_FLEXBOX_COLOR,
UPDATE_FLEXBOX_HIGHLIGHTED,
} = require("../actions/index");
const INITIAL_FLEXBOX = {
// The actor ID of the flex container.
actorID: null,
// The color of the flexbox highlighter overlay.
color: "",
// An array of flex items belonging to the current flex container.
flexItems: [],
// The NodeFront actor ID of the flex item to display the flex item sizing properties.
flexItemShown: null,
// The flex container of the selected element.
flexContainer: {
// The actor ID of the selected flex container.
actorID: "",
// An array of flex items belonging to the selected flex container.
flexItems: [],
// The NodeFront actor ID of the flex item to display in the flex item sizing
// properties.
flexItemShown: null,
// This flag specifies that the flex container data represents the selected flex
// container.
isFlexItemContainer: false,
// The NodeFront of the selected flex container.
nodeFront: null,
// The computed style properties of the selected flex container.
properties: null,
},
// The selected flex container can also be a flex item. This object contains the
// parent flex container properties of the selected element.
flexItemContainer: {
// The actor ID of the parent flex container.
actorID: "",
// An array of flex items belonging to the parent flex container.
flexItems: [],
// The NodeFront actor ID of the flex item to display in the flex item sizing
// properties.
flexItemShown: null,
// This flag specifies that the flex container data represents the parent flex
// container of the selected element.
isFlexItemContainer: true,
// The NodeFront of the parent flex container.
nodeFront: null,
// The computed styles properties of the parent flex container.
properties: null,
},
// Whether or not the flexbox highlighter is highlighting the flex container.
highlighted: false,
// The NodeFront of the flex container.
nodeFront: null,
// The computed style properties of the flex container.
properties: {},
};
const reducers = {
@ -35,34 +59,22 @@ const reducers = {
return INITIAL_FLEXBOX;
},
[TOGGLE_FLEX_ITEM_SHOWN](flexbox, { nodeFront }) {
let flexItemShown = null;
// Get the NodeFront actor ID of the flex item.
if (nodeFront) {
const flexItem = flexbox.flexItems.find(item => item.nodeFront === nodeFront);
flexItemShown = flexItem.nodeFront.actorID;
}
return Object.assign({}, flexbox, {
flexItemShown,
});
},
[UPDATE_FLEXBOX](_, { flexbox }) {
return flexbox;
},
[UPDATE_FLEXBOX_COLOR](flexbox, { color }) {
return Object.assign({}, flexbox, {
return {
...flexbox,
color,
});
};
},
[UPDATE_FLEXBOX_HIGHLIGHTED](flexbox, { highlighted }) {
return Object.assign({}, flexbox, {
return {
...flexbox,
highlighted,
});
};
},
};

Просмотреть файл

@ -108,22 +108,22 @@ const flexContainerProperties = exports.flexContainerProperties = {
/**
* A flex container data.
*/
exports.flexbox = {
const flexContainer = exports.flexContainer = {
// The actor ID of the flex container.
actorID: PropTypes.string,
// The color of the flexbox highlighter overlay.
color: PropTypes.string,
// Array of flex container's flex items.
// An array of flex items belonging to the flex container.
flexItems: PropTypes.arrayOf(PropTypes.shape(flexItem)),
// The NodeFront actor ID of the flex item to display the flex item sizing properties.
flexItemShown: PropTypes.string,
// Whether or not the flex container data represents the selected flex container
// or the parent flex container. This is true if the flex container data represents
// the parent flex container.
isFlexItemContainer: PropTypes.bool,
// Whether or not the flexbox highlighter is highlighting the flex container.
highlighted: PropTypes.bool,
// The NodeFront actor ID of the flex item to display in the flex item sizing
// properties.
flexItemShown: PropTypes.string,
// The NodeFront of the flex container.
nodeFront: PropTypes.object,
@ -132,3 +132,23 @@ exports.flexbox = {
properties: PropTypes.shape(flexContainerProperties),
};
/**
* The Flexbox UI state.
*/
exports.flexbox = {
// The color of the flexbox highlighter overlay.
color: PropTypes.string,
// The selected flex container.
flexContainer: PropTypes.shape(flexContainer),
// The selected flex container can also be a flex item. This object contains the
// parent flex container properties.
flexItemContainer: PropTypes.shape(flexContainer),
// Whether or not the flexbox highlighter is highlighting the flex container.
highlighted: PropTypes.bool,
};

Просмотреть файл

@ -51,7 +51,6 @@ class LayoutApp extends PureComponent {
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
onShowGridOutlineHighlight: PropTypes.func.isRequired,
onToggleFlexboxHighlighter: PropTypes.func.isRequired,
onToggleFlexItemShown: PropTypes.func.isRequired,
onToggleGeometryEditor: PropTypes.func.isRequired,
onToggleGridHighlighter: PropTypes.func.isRequired,
onToggleShowGridAreas: PropTypes.func.isRequired,
@ -62,23 +61,21 @@ class LayoutApp extends PureComponent {
};
}
getFlexboxHeader() {
const { flexbox } = this.props;
if (!flexbox.actorID) {
getFlexboxHeader(flexContainer) {
if (!flexContainer.actorID) {
// No flex container or flex item selected.
return LAYOUT_L10N.getStr("flexbox.header");
} else if (!flexbox.flexItemShown) {
} else if (!flexContainer.flexItemShown) {
// No flex item selected.
return LAYOUT_L10N.getStr("flexbox.flexContainer");
}
const grip = translateNodeFrontToGrip(flexbox.nodeFront);
const grip = translateNodeFrontToGrip(flexContainer.nodeFront);
return LAYOUT_L10N.getFormatStr("flexbox.flexItemOf", getSelectorFromGrip(grip));
}
render() {
let items = [
const items = [
{
component: Grid,
componentProps: this.props,
@ -102,19 +99,43 @@ class LayoutApp extends PureComponent {
];
if (Services.prefs.getBoolPref(FLEXBOX_ENABLED_PREF)) {
items = [
{
// Since the flexbox panel is hidden behind a pref. We insert the flexbox container
// to the first index of the accordion item list.
items.splice(0, 0, {
component: Flexbox,
componentProps: {
...this.props,
flexContainer: this.props.flexbox.flexContainer,
},
header: this.getFlexboxHeader(this.props.flexbox.flexContainer),
opened: Services.prefs.getBoolPref(FLEXBOX_OPENED_PREF),
onToggled: () => {
const opened = Services.prefs.getBoolPref(FLEXBOX_OPENED_PREF);
Services.prefs.setBoolPref(FLEXBOX_OPENED_PREF, !opened);
}
});
// If the current selected node is both a flex container and flex item. Render
// an accordion with another Flexbox component where the flexbox to show is the
// parent flex container of the current selected node.
if (this.props.flexbox.flexItemContainer &&
this.props.flexbox.flexItemContainer.actorID) {
// Insert the parent flex container to the second index of the accordion item
// list.
items.splice(1, 0, {
component: Flexbox,
componentProps: this.props,
header: this.getFlexboxHeader(),
componentProps: {
...this.props,
flexContainer: this.props.flexbox.flexItemContainer,
},
header: this.getFlexboxHeader(this.props.flexbox.flexItemContainer),
opened: Services.prefs.getBoolPref(FLEXBOX_OPENED_PREF),
onToggled: () => {
const opened = Services.prefs.getBoolPref(FLEXBOX_OPENED_PREF);
Services.prefs.setBoolPref(FLEXBOX_OPENED_PREF, !opened);
}
},
...items
];
});
}
}
return (

Просмотреть файл

@ -47,7 +47,6 @@ class LayoutView {
const {
onSetFlexboxOverlayColor,
onToggleFlexboxHighlighter,
onToggleFlexItemShown,
} = this.flexboxInspector.getComponentProps();
this.gridInspector = new GridInspector(this.inspector, this.inspector.panelWin);
@ -70,7 +69,6 @@ class LayoutView {
onShowBoxModelHighlighterForNode,
onShowGridOutlineHighlight,
onToggleFlexboxHighlighter,
onToggleFlexItemShown,
onToggleGeometryEditor,
onToggleGridHighlighter,
onToggleShowGridAreas,

Просмотреть файл

@ -12,6 +12,7 @@ const {
gridSpec,
layoutSpec,
} = require("devtools/shared/specs/layout");
const { ELEMENT_NODE } = require("devtools/shared/dom-node-constants");
const { SHOW_ELEMENT } = require("devtools/shared/dom-node-filter-constants");
const { getStringifiableFragments } =
require("devtools/server/actors/utils/css-grid-utils");
@ -102,6 +103,10 @@ const FlexboxActor = ActorClassWithSpec(flexboxSpec, {
for (const line of flex.getLines()) {
for (const item of line.getItems()) {
if (item.node.nodeType !== ELEMENT_NODE) {
continue;
}
flexItemActors.push(new FlexItemActor(this, item.node, {
crossMaxSize: item.crossMaxSize,
crossMinSize: item.crossMinSize,
@ -152,17 +157,20 @@ const FlexItemActor = ActorClassWithSpec(flexItemSpec, {
return this.actorID;
}
const { flexDirection } = CssLogic.getComputedStyle(this.containerEl);
const styles = CssLogic.getComputedStyle(this.element);
const clientRect = this.element.getBoundingClientRect();
const dimension = flexDirection.startsWith("row") ? "width" : "height";
const form = {
actor: this.actorID,
// The flex item sizing data.
flexItemSizing: this.flexItemSizing,
};
if (this.element.nodeType === ELEMENT_NODE) {
const { flexDirection } = CssLogic.getComputedStyle(this.containerEl);
const styles = CssLogic.getComputedStyle(this.element);
const clientRect = this.element.getBoundingClientRect();
const dimension = flexDirection.startsWith("row") ? "width" : "height";
// The computed style properties of the flex item.
properties: {
form.properties = {
"flex-basis": styles.flexBasis,
"flex-grow": styles.flexGrow,
"flex-shrink": styles.flexShrink,
@ -172,8 +180,8 @@ const FlexItemActor = ActorClassWithSpec(flexItemSpec, {
[`max-${dimension}`]: styles[`max-${dimension}`],
// Computed width/height of the flex item element.
[dimension]: parseFloat(clientRect[dimension.toLowerCase()].toPrecision(6)),
},
};
};
}
// If the WalkerActor already knows the flex item element, then also return its
// ActorID so we avoid the client from doing another round trip to get it in many
@ -261,15 +269,15 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
},
/**
* Helper function for getCurrentGrid and getCurrentFlexbox. Returns the grid or
* flex container (whichever is requested) found by iterating on the given selected
* node. The current node can be a grid/flex container or grid/flex item. If it is a
* grid/flex item, returns the parent grid/flex container. Otherwise, returns null
* if the current or parent node is not a grid/flex container.
* Helper function for getAsFlexItem, getCurrentGrid and getCurrentFlexbox. Returns the
* grid or flex container (whichever is requested) found by iterating on the given
* selected node. The current node can be a grid/flex container or grid/flex item.
* If it is a grid/flex item, returns the parent grid/flex container. Otherwise, returns
* null if the current or parent node is not a grid/flex container.
*
* @param {Node|NodeActor} node
* The node to start iterating at.
* @param {String} type
* @param {String} type
* Can be "grid" or "flex", the display type we are searching for.
* @return {GridActor|FlexboxActor|null} The GridActor or FlexboxActor of the
* grid/flex container of the give node. Otherwise, returns null.
@ -300,7 +308,8 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
return new GridActor(this, currentNode);
}
// Otherwise, check if this is a flex item or the parent node is a flex container.
// Otherwise, check if this is a flex/grid item or the parent node is a flex/grid
// container.
while ((currentNode = treeWalker.parentNode())) {
if (!currentNode) {
break;
@ -333,7 +342,7 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
*
* @param {Node|NodeActor} node
* The node to start iterating at.
* @return {GridActor|null} The GridActor of the grid container of the give node.
* @return {GridActor|null} The GridActor of the grid container of the given node.
* Otherwise, returns null.
*/
getCurrentGrid(node) {
@ -348,10 +357,16 @@ const LayoutActor = ActorClassWithSpec(layoutSpec, {
*
* @param {Node|NodeActor} node
* The node to start iterating at.
* @return {FlexboxActor|null} The FlexboxActor of the flex container of the give node.
* @param {Boolean|null} onlyLookAtParents
* Whether or not to only consider the parent node of the given node.
* @return {FlexboxActor|null} The FlexboxActor of the flex container of the given node.
* Otherwise, returns null.
*/
getCurrentFlexbox(node) {
getCurrentFlexbox(node, onlyLookAtParents) {
if (onlyLookAtParents) {
node = node.rawNode.parentNode;
}
return this.getCurrentDisplay(node, "flex");
},

Просмотреть файл

@ -38,6 +38,7 @@ const layoutSpec = generateActorSpec({
getCurrentFlexbox: {
request: {
node: Arg(0, "domnode"),
onlyLookAtParents: Arg(1, "nullable:boolean"),
},
response: {
flexbox: RetVal("nullable:flexbox")