Bug 1443846 - Part 2: Add skeleton for font editor panel. r=gl

- Implement basic React component & Redux store and actions for font editor.
- Move font overview rendering from FontsApp into its own component: FontOverview. FontsApp remains just a wrapper for FontEditor and FontOverview.
- Listen to rule selection events to toggle the display of the font editor and font overview panels.

MozReview-Commit-ID: 496LHPqpnKL
This commit is contained in:
Razvan Caliman 2018-03-13 21:15:52 +01:00
Родитель 3c6bdde9b9
Коммит 07521a682a
13 изменённых файлов: 268 добавлений и 62 удалений

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

@ -0,0 +1,21 @@
/* 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 {
UPDATE_EDITOR_VISIBILITY,
} = require("./index");
module.exports = {
toggleFontEditor(isVisible, selector = "") {
return {
type: UPDATE_EDITOR_VISIBILITY,
isVisible,
selector,
};
},
};

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

@ -8,6 +8,9 @@ const { createEnum } = require("devtools/client/shared/enum");
createEnum([
// Toggle the visibiltiy of the font editor
"UPDATE_EDITOR_VISIBILITY",
// Update the list of fonts.
"UPDATE_FONTS",

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

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'font-editor.js',
'font-options.js',
'fonts.js',
'index.js',

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

@ -0,0 +1,32 @@
/* 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 { 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 Types = require("../types");
class FontEditor extends PureComponent {
static get propTypes() {
return {
fontEditor: PropTypes.shape(Types.fontEditor).isRequired,
};
}
render() {
const { selector } = this.props.fontEditor;
return dom.div(
{
className: "theme-sidebar inspector-tabpanel",
id: "sidebar-panel-fonteditor"
}, `Placeholder for Font Editor panel for selector: ${selector}`
);
}
}
module.exports = FontEditor;

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

@ -0,0 +1,88 @@
/* 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, 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 Accordion = createFactory(require("devtools/client/inspector/layout/components/Accordion"));
const FontList = createFactory(require("./FontList"));
const { getStr } = require("../utils/l10n");
const Types = require("../types");
class FontOverview extends PureComponent {
static get propTypes() {
return {
fontData: PropTypes.shape(Types.fontData).isRequired,
fontOptions: PropTypes.shape(Types.fontOptions).isRequired,
onPreviewFonts: PropTypes.func.isRequired,
};
}
renderElementFonts() {
let {
fontData,
fontOptions,
onPreviewFonts,
} = this.props;
let { fonts } = fontData;
return fonts.length ?
FontList({
fonts,
fontOptions,
onPreviewFonts
})
:
dom.div(
{
className: "devtools-sidepanel-no-result"
},
getStr("fontinspector.noFontsOnSelectedElement")
);
}
renderOtherFonts() {
let {
fontData,
onPreviewFonts,
fontOptions,
} = this.props;
let { otherFonts } = fontData;
if (!otherFonts.length) {
return null;
}
return Accordion({
items: [
{
header: getStr("fontinspector.otherFontsInPageHeader"),
component: FontList,
componentProps: {
fontOptions,
fonts: otherFonts,
onPreviewFonts
},
opened: false
}
]
});
}
render() {
return dom.div(
{
id: "font-container",
},
this.renderElementFonts(),
this.renderOtherFonts()
);
}
}
module.exports = FontOverview;

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

@ -9,85 +9,44 @@ 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 Accordion = createFactory(require("devtools/client/inspector/layout/components/Accordion"));
const FontList = createFactory(require("./FontList"));
const FontEditor = createFactory(require("./FontEditor"));
const FontOverview = createFactory(require("./FontOverview"));
const { getStr } = require("../utils/l10n");
const Types = require("../types");
class FontsApp extends PureComponent {
static get propTypes() {
return {
fontData: PropTypes.shape(Types.fontData).isRequired,
fontEditor: PropTypes.shape(Types.fontEditor).isRequired,
fontOptions: PropTypes.shape(Types.fontOptions).isRequired,
onPreviewFonts: PropTypes.func.isRequired,
};
}
renderElementFonts() {
let {
fontData,
fontOptions,
onPreviewFonts,
} = this.props;
let { fonts } = fontData;
return fonts.length ?
FontList({
fonts,
fontOptions,
onPreviewFonts
})
:
dom.div(
{
className: "devtools-sidepanel-no-result"
},
getStr("fontinspector.noFontsOnSelectedElement")
);
}
renderOtherFonts() {
let {
fontData,
onPreviewFonts,
fontOptions,
} = this.props;
let { otherFonts } = fontData;
if (!otherFonts.length) {
return null;
}
return Accordion({
items: [
{
header: getStr("fontinspector.otherFontsInPageHeader"),
component: FontList,
componentProps: {
fontOptions,
fonts: otherFonts,
onPreviewFonts
},
opened: false
}
]
});
}
render() {
const {
fontData,
fontEditor,
fontOptions,
onPreviewFonts
} = this.props;
return dom.div(
{
className: "theme-sidebar inspector-tabpanel",
id: "sidebar-panel-fontinspector"
},
dom.div(
{
id: "font-container"
},
this.renderElementFonts(),
this.renderOtherFonts()
)
fontEditor.isVisible ?
FontEditor({
fontEditor,
})
:
FontOverview({
fontData,
fontOptions,
onPreviewFonts,
})
);
}
}

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

@ -6,7 +6,9 @@
DevToolsModules(
'Font.js',
'FontEditor.js',
'FontList.js',
'FontOverview.js',
'FontPreview.js',
'FontsApp.js',
)

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

@ -19,18 +19,24 @@ const INSPECTOR_L10N =
const { updateFonts } = require("./actions/fonts");
const { updatePreviewText } = require("./actions/font-options");
const { toggleFontEditor } = require("./actions/font-editor");
const FONT_EDITOR_ID = "fonteditor";
class FontInspector {
constructor(inspector, window) {
this.document = window.document;
this.inspector = inspector;
this.pageStyle = this.inspector.pageStyle;
this.ruleView = this.inspector.getPanel("ruleview").view;
this.selectedRule = null;
this.store = this.inspector.store;
this.update = this.update.bind(this);
this.onNewNode = this.onNewNode.bind(this);
this.onPreviewFonts = this.onPreviewFonts.bind(this);
this.onRuleSelected = this.onRuleSelected.bind(this);
this.onRuleUnselected = this.onRuleUnselected.bind(this);
this.onThemeChanged = this.onThemeChanged.bind(this);
this.init();
@ -57,6 +63,8 @@ class FontInspector {
this.inspector.selection.on("new-node-front", this.onNewNode);
this.inspector.sidebar.on("fontinspector-selected", this.onNewNode);
this.ruleView.on("ruleview-rule-selected", this.onRuleSelected);
this.ruleView.on("ruleview-rule-unselected", this.onRuleUnselected);
// Listen for theme changes as the color of the previews depend on the theme
gDevTools.on("theme-switched", this.onThemeChanged);
@ -89,11 +97,15 @@ class FontInspector {
destroy() {
this.inspector.selection.off("new-node-front", this.onNewNode);
this.inspector.sidebar.off("fontinspector-selected", this.onNewNode);
this.ruleView.off("ruleview-rule-selected", this.onRuleSelected);
this.ruleView.off("ruleview-rule-unselected", this.onRuleUnselected);
gDevTools.off("theme-switched", this.onThemeChanged);
this.document = null;
this.inspector = null;
this.pageStyle = null;
this.ruleView = null;
this.selectedRule = null;
this.store = null;
}
@ -150,6 +162,45 @@ class FontInspector {
this.update();
}
/**
* Handler for "ruleview-rule-selected" event emitted from the rule view when a rule is
* marked as selected for an editor.
* If selected for the font editor, hold a reference to the rule so we know where to
* put property changes coming from the font editor and show the font editor panel.
*
* @param {Object} eventData
* Data payload for the event. Contains:
* - {String} editorId - id of the editor for which the rule was selected
* - {Rule} rule - reference to rule that was selected
*/
onRuleSelected(eventData) {
const { editorId, rule } = eventData;
if (editorId === FONT_EDITOR_ID) {
const selector = rule.matchedSelectors[0];
this.selectedRule = rule;
this.store.dispatch(toggleFontEditor(true, selector));
}
}
/**
* Handler for "ruleview-rule-unselected" event emitted from the rule view when a rule
* was released from being selected for an editor.
* If previously selected for the font editor, release the reference to the rule and
* hide the font editor panel.
*
* @param {Object} eventData
* Data payload for the event. Contains:
* - {String} editorId - id of the editor for which the rule was released
* - {Rule} rule - reference to rule that was released
*/
onRuleUnselected(eventData) {
const { editorId, rule } = eventData;
if (editorId === FONT_EDITOR_ID && rule == this.selectedRule) {
this.selectedRule = null;
this.store.dispatch(toggleFontEditor(false));
}
}
/**
* Handler for the "theme-switched" event.
*/

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

@ -0,0 +1,32 @@
/* 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 {
UPDATE_EDITOR_VISIBILITY,
} = require("../actions/index");
const INITIAL_STATE = {
// Whether or not the font editor is visible.
isVisible: false,
// Selector text of the rule where font properties will be written.
selector: "",
};
let reducers = {
[UPDATE_EDITOR_VISIBILITY](state, { isVisible, selector }) {
return { ...state, isVisible, selector };
},
};
module.exports = function(state = INITIAL_STATE, action) {
let reducer = reducers[action.type];
if (!reducer) {
return state;
}
return reducer(state, action);
};

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

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DevToolsModules(
'font-editor.js',
'font-options.js',
'fonts.js',
)

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

@ -79,6 +79,17 @@ exports.fontOptions = {
previewText: PropTypes.string,
};
exports.fontEditor = {
// Font currently being edited
font: PropTypes.shape(font),
// Whether or not the font editor is visible
isVisible: PropTypes.bool,
// Selector text of the rule where font properties will be written
selector: PropTypes.string,
};
/**
* Font data.
*/

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

@ -15,5 +15,6 @@ exports.extensionsSidebar = require("devtools/client/inspector/extensions/reduce
exports.flexbox = require("devtools/client/inspector/flexbox/reducers/flexbox");
exports.fontOptions = require("devtools/client/inspector/fonts/reducers/font-options");
exports.fontData = require("devtools/client/inspector/fonts/reducers/fonts");
exports.fontEditor = require("devtools/client/inspector/fonts/reducers/font-editor");
exports.grids = require("devtools/client/inspector/grids/reducers/grids");
exports.highlighterSettings = require("devtools/client/inspector/grids/reducers/highlighter-settings");

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

@ -10,6 +10,10 @@
height: 100%;
}
#sidebar-panel-fonteditor {
padding: 1em;
}
#font-container {
overflow: auto;
flex: auto;