/* 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 {
assert } = require(
"resource://devtools/shared/DevToolsUtils.js");
const {
Component,
} = 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 { L10N } = require(
"resource://devtools/client/memory/utils.js");
const models = require(
"resource://devtools/client/memory/models.js");
const { viewState } = require(
"resource://devtools/client/memory/constants.js");
class Toolbar
extends Component {
static get propTypes() {
return {
censusDisplays: PropTypes.arrayOf(models.censusDisplay).isRequired,
censusDisplay: models.censusDisplay.isRequired,
onTakeSnapshotClick: PropTypes.func.isRequired,
onImportClick: PropTypes.func.isRequired,
onClearSnapshotsClick: PropTypes.func.isRequired,
onCensusDisplayChange: PropTypes.func.isRequired,
onToggleRecordAllocationStacks: PropTypes.func.isRequired,
allocations: models.allocations,
filterString: PropTypes.string,
setFilterString: PropTypes.func.isRequired,
diffing: models.diffingModel,
onToggleDiffing: PropTypes.func.isRequired,
view: models.view.isRequired,
onViewChange: PropTypes.func.isRequired,
labelDisplays: PropTypes.arrayOf(models.labelDisplay).isRequired,
labelDisplay: models.labelDisplay.isRequired,
onLabelDisplayChange: PropTypes.func.isRequired,
treeMapDisplays: PropTypes.arrayOf(models.treeMapDisplay).isRequired,
onTreeMapDisplayChange: PropTypes.func.isRequired,
snapshots: PropTypes.arrayOf(models.snapshot).isRequired,
};
}
render() {
const {
onTakeSnapshotClick,
onImportClick,
onClearSnapshotsClick,
onCensusDisplayChange,
censusDisplays,
censusDisplay,
labelDisplays,
labelDisplay,
onLabelDisplayChange,
treeMapDisplays,
onTreeMapDisplayChange,
onToggleRecordAllocationStacks,
allocations,
filterString,
setFilterString,
snapshots,
diffing,
onToggleDiffing,
view,
onViewChange,
} =
this.props;
let viewToolbarOptions;
if (view.state == viewState.CENSUS || view.state === viewState.DIFFING) {
viewToolbarOptions = dom.div(
{
className:
"toolbar-group",
},
dom.label(
{
className:
"display-by",
title: L10N.getStr(
"toolbar.displayBy.tooltip"),
},
L10N.getStr(
"toolbar.displayBy"),
dom.select(
{
id:
"select-display",
className:
"devtools-toolbar-select select-display",
onChange: e => {
const newDisplay = censusDisplays.find(
b => b.displayName === e.target.value
);
onCensusDisplayChange(newDisplay);
},
value: censusDisplay.displayName,
},
censusDisplays.map(({ tooltip, displayName }) =>
dom.option(
{
key: `display-${displayName}`,
value: displayName,
title: tooltip,
},
displayName
)
)
)
),
dom.span({ className:
"devtools-separator" }),
dom.input({
id:
"filter",
type:
"search",
className:
"devtools-filterinput",
placeholder: L10N.getStr(
"filter.placeholder"),
title: L10N.getStr(
"filter.tooltip"),
onChange: event => setFilterString(event.target.value),
value: filterString || undefined,
})
);
}
else if (view.state == viewState.TREE_MAP) {
assert(
treeMapDisplays.length >= 1,
"Should always have at least one tree map display"
);
// Only show the dropdown if there are multiple display options
viewToolbarOptions =
treeMapDisplays.length > 1
? dom.div(
{
className:
"toolbar-group",
},
dom.label(
{
className:
"display-by",
title: L10N.getStr(
"toolbar.displayBy.tooltip"),
},
L10N.getStr(
"toolbar.displayBy"),
dom.select(
{
id:
"select-tree-map-display",
onChange: e => {
const newDisplay = treeMapDisplays.find(
b => b.displayName === e.target.value
);
onTreeMapDisplayChange(newDisplay);
},
},
treeMapDisplays.map(({ tooltip, displayName }) =>
dom.option(
{
key: `tree-map-display-${displayName}`,
value: displayName,
title: tooltip,
},
displayName
)
)
)
)
)
:
null;
}
else {
assert(
view.state === viewState.DOMINATOR_TREE ||
view.state === viewState.INDIVIDUALS
);
viewToolbarOptions = dom.div(
{
className:
"toolbar-group",
},
dom.label(
{
className:
"label-by",
title: L10N.getStr(
"toolbar.labelBy.tooltip"),
},
L10N.getStr(
"toolbar.labelBy"),
dom.select(
{
id:
"select-label-display",
className:
"devtools-toolbar-select select-label-display",
onChange: e => {
const newDisplay = labelDisplays.find(
b => b.displayName === e.target.value
);
onLabelDisplayChange(newDisplay);
},
value: labelDisplay.displayName,
},
labelDisplays.map(({ tooltip, displayName }) =>
dom.option(
{
key: `label-display-${displayName}`,
value: displayName,
title: tooltip,
},
displayName
)
)
)
)
);
}
let viewSelect;
if (
view.state !== viewState.DIFFING &&
view.state !== viewState.INDIVIDUALS
) {
viewSelect = dom.label(
{
title: L10N.getStr(
"toolbar.view.tooltip"),
},
L10N.getStr(
"toolbar.view"),
dom.select(
{
id:
"select-view",
className:
"devtools-toolbar-select select-view",
onChange: e => onViewChange(e.target.value),
value: view.state,
},
dom.option(
{
value: viewState.TREE_MAP,
title: L10N.getStr(
"toolbar.view.treemap.tooltip"),
},
L10N.getStr(
"toolbar.view.treemap")
),
dom.option(
{
value: viewState.CENSUS,
title: L10N.getStr(
"toolbar.view.census.tooltip"),
},
L10N.getStr(
"toolbar.view.census")
),
dom.option(
{
value: viewState.DOMINATOR_TREE,
title: L10N.getStr(
"toolbar.view.dominators.tooltip"),
},
L10N.getStr(
"toolbar.view.dominators")
)
)
);
}
return dom.div(
{
className:
"devtools-toolbar",
},
dom.div(
{
className:
"toolbar-group",
},
dom.button({
id:
"clear-snapshots",
className:
"clear-snapshots devtools-button",
disabled: !snapshots.length,
onClick: onClearSnapshotsClick,
title: L10N.getStr(
"clear-snapshots.tooltip"),
}),
dom.button({
id:
"take-snapshot",
className:
"take-snapshot devtools-button",
onClick: onTakeSnapshotClick,
title: L10N.getStr(
"take-snapshot"),
}),
dom.button({
id:
"diff-snapshots",
className:
"devtools-button devtools-monospace" + (diffing ?
" checked" :
""),
disabled: snapshots.length < 2,
onClick: onToggleDiffing,
title: L10N.getStr(
"diff-snapshots.tooltip"),
}),
dom.button({
id:
"import-snapshot",
className:
"import-snapshot devtools-button",
onClick: onImportClick,
title: L10N.getStr(
"import-snapshot"),
})
),
dom.label(
{
id:
"record-allocation-stacks-label",
title: L10N.getStr(
"checkbox.recordAllocationStacks.tooltip"),
},
dom.input({
id:
"record-allocation-stacks-checkbox",
type:
"checkbox",
checked: allocations.recording,
disabled: allocations.togglingInProgress,
onChange: onToggleRecordAllocationStacks,
}),
L10N.getStr(
"checkbox.recordAllocationStacks")
),
viewSelect,
viewToolbarOptions
);
}
}
module.exports = Toolbar;