CSS in renderers (#3446)

* Have each renderer declare some CSS that is specific to the renderer.
This commit is contained in:
Sam El-Husseini
2019-11-18 16:14:19 -08:00
committed by GitHub
parent 32e2f9ccdf
commit 70c24cf94e
9 changed files with 124 additions and 44 deletions

View File

@@ -77,6 +77,7 @@ Blockly.Css.inject = function(hasCss, pathToMedia) {
// Inject CSS tag at start of head.
var cssNode = document.createElement('style');
cssNode.id = 'blockly-common-style';
var cssTextNode = document.createTextNode(text);
cssNode.appendChild(cssTextNode);
document.head.insertBefore(cssNode, document.head.firstChild);
@@ -254,11 +255,6 @@ Blockly.Css.CONTENT = [
'stroke-width: 1;',
'}',
'.injectionDiv:not(.zelos-renderer) .blocklySelected>.blocklyPath {',
'stroke: #fc3;',
'stroke-width: 3px;',
'}',
'.blocklySelected>.blocklyPathLight {',
'display: none;',
'}',
@@ -334,13 +330,6 @@ Blockly.Css.CONTENT = [
'display: none;',
'}',
'.blocklyText {',
'cursor: default;',
'fill: #fff;',
'font-family: sans-serif;',
'font-size: 11pt;',
'}',
'.blocklyMultilineText {',
'font-family: monospace;',
'}',
@@ -349,22 +338,6 @@ Blockly.Css.CONTENT = [
'pointer-events: none;',
'}',
'.blocklyNonEditableText>rect,',
'.blocklyEditableText>rect {',
'fill: #fff;',
'fill-opacity: .6;',
'}',
'.blocklyNonEditableText>text,',
'.blocklyEditableText>text {',
'fill: #000;',
'}',
'.blocklyEditableText:not(.editing):hover>rect {',
'stroke: #fff;',
'stroke-width: 2;',
'}',
'.blocklyBubbleText {',
'fill: #000;',
'}',

View File

@@ -101,15 +101,16 @@ Blockly.blockRendering.init = function(name) {
/**
* Wrap the renderer constructor into a temporary constructor
* function so the closure compiler treats it as a constructor.
* @param {string} name The renderer name.
* @constructor
* @extends {Blockly.blockRendering.Renderer}
*/
var rendererCtor = function() {
rendererCtor.superClass_.constructor.call(this);
var rendererCtor = function(name) {
rendererCtor.superClass_.constructor.call(this, name);
};
Blockly.utils.object.inherits(rendererCtor,
Blockly.blockRendering.rendererMap_[name]);
var renderer = new rendererCtor();
var renderer = new rendererCtor(name);
renderer.init();
return renderer;
};

View File

@@ -161,7 +161,6 @@ Blockly.blockRendering.ConstantProvider = function() {
/**
* Point size of text. Should match blocklyText's font-size in CSS.
* @type {number}
* @const
*/
this.FIELD_TEXT_FONTSIZE = 11;
@@ -174,14 +173,12 @@ Blockly.blockRendering.ConstantProvider = function() {
/**
* Text font weight. Should match blocklyText's font-weight in CSS.
* @type {string}
* @const
*/
this.FIELD_TEXT_FONTWEIGHT = 'normal';
/**
* Text font family. Should match blocklyText's font-family in CSS.
* @type {string}
* @const
*/
this.FIELD_TEXT_FONTFAMILY = 'sans-serif';

View File

@@ -35,10 +35,18 @@ goog.requireType('Blockly.blockRendering.Debug');
/**
* The base class for a block renderer.
* @param {string} name The renderer name.
* @package
* @constructor
*/
Blockly.blockRendering.Renderer = function() {
Blockly.blockRendering.Renderer = function(name) {
/**
* The renderer name.
* @type {string}
* @protected
*/
this.name_ = name;
/**
* The renderer's constant provider.
@@ -55,6 +63,7 @@ Blockly.blockRendering.Renderer = function() {
Blockly.blockRendering.Renderer.prototype.init = function() {
this.constants_ = this.makeConstants_();
this.constants_.init();
this.injectCSS_(this.getCSS_());
};
/**
@@ -139,6 +148,66 @@ Blockly.blockRendering.Renderer.prototype.getConstants = function() {
(this.constants_));
};
/**
* Get any renderer specific CSS to inject when the renderer is initialized.
* @return {!Array.<string>} Array of CSS strings.
* @protected
*/
Blockly.blockRendering.Renderer.prototype.getCSS_ = function() {
var selector = '.' + this.name_ + '-renderer';
var constants = this.getConstants();
return [
/* eslint-disable indent */
selector + ' .blocklyText {',
'cursor: default;',
'fill: #fff;',
'font-family: ' + constants.FIELD_TEXT_FONTFAMILY + ';',
'font-size: ' + constants.FIELD_TEXT_FONTSIZE + 'pt;',
'font-weight: ' + constants.FIELD_TEXT_FONTWEIGHT + ';',
'}',
selector + ' .blocklyNonEditableText>rect,',
selector + ' .blocklyEditableText>rect {',
'fill: #fff;',
'fill-opacity: .6;',
'}',
selector + ' .blocklyNonEditableText>text,',
selector + ' .blocklyEditableText>text {',
'fill: #000;',
'}',
selector + ' .blocklyEditableText:not(.editing):hover>rect {',
'stroke: #fff;',
'stroke-width: 2;',
'}',
selector + ' .blocklySelected>.blocklyPath {',
'stroke: #fc3;',
'stroke-width: 3px;',
'}',
/* eslint-enable indent */
];
};
/**
* Get any renderer specific CSS to inject when the renderer is initialized.
* @param {!Array.<string>} cssArray Array of CSS strings.
* @private
*/
Blockly.blockRendering.Renderer.prototype.injectCSS_ = function(cssArray) {
var cssNodeId = 'blockly-renderer-style-' + this.name_;
if (document.getElementById(cssNodeId)) {
// Already injected.
return;
}
var text = cssArray.join('\n');
// Inject CSS tag at start of head.
var cssNode = document.createElement('style');
cssNode.id = cssNodeId;
var cssTextNode = document.createTextNode(text);
cssNode.appendChild(cssTextNode);
document.head.insertBefore(cssNode, document.head.firstChild);
};
/**
* Determine whether or not to highlight a connection.
* @param {Blockly.Connection} _conn The connection to determine whether or not

View File

@@ -35,12 +35,13 @@ goog.require('Blockly.utils.object');
/**
* The geras renderer.
* @param {string} name The renderer name.
* @package
* @constructor
* @extends {Blockly.blockRendering.Renderer}
*/
Blockly.geras.Renderer = function() {
Blockly.geras.Renderer.superClass_.constructor.call(this);
Blockly.geras.Renderer = function(name) {
Blockly.geras.Renderer.superClass_.constructor.call(this, name);
/**
* The renderer's highlight constant provider.

View File

@@ -30,12 +30,13 @@ goog.require('Blockly.utils.object');
/**
* The thrasos renderer.
* @param {string} name The renderer name.
* @package
* @constructor
* @extends {Blockly.blockRendering.Renderer}
*/
Blockly.thrasos.Renderer = function() {
Blockly.thrasos.Renderer.superClass_.constructor.call(this);
Blockly.thrasos.Renderer = function(name) {
Blockly.thrasos.Renderer.superClass_.constructor.call(this, name);
};
Blockly.utils.object.inherits(Blockly.thrasos.Renderer,
Blockly.blockRendering.Renderer);

View File

@@ -159,6 +159,16 @@ Blockly.zelos.ConstantProvider = function() {
*/
this.FULL_BLOCK_FIELDS = true;
/**
* @override
*/
this.FIELD_TEXT_FONTSIZE = 12;
/**
* @override
*/
this.FIELD_TEXT_FONTWEIGHT = 'bold';
/**
* @override
*/

View File

@@ -35,12 +35,13 @@ goog.require('Blockly.zelos.CursorSvg');
/**
* The zelos renderer.
* @param {string} name The renderer name.
* @package
* @constructor
* @extends {Blockly.blockRendering.Renderer}
*/
Blockly.zelos.Renderer = function() {
Blockly.zelos.Renderer.superClass_.constructor.call(this);
Blockly.zelos.Renderer = function(name) {
Blockly.zelos.Renderer.superClass_.constructor.call(this, name);
};
Blockly.utils.object.inherits(Blockly.zelos.Renderer,
Blockly.blockRendering.Renderer);
@@ -122,4 +123,27 @@ Blockly.zelos.Renderer.prototype.shouldInsertDraggedBlock = function(_block,
return false;
};
/**
* @override
*/
Blockly.zelos.Renderer.prototype.getCSS_ = function() {
var selector = '.' + this.name_ + '-renderer';
var constants = this.getConstants();
return [
/* eslint-disable indent */
selector + ' .blocklyText {',
'cursor: default;',
'fill: #fff;',
'font-family: ' + constants.FIELD_TEXT_FONTFAMILY + ';',
'font-size: ' + constants.FIELD_TEXT_FONTSIZE + 'pt;',
'font-weight: ' + constants.FIELD_TEXT_FONTWEIGHT + ';',
'}',
selector + ' .blocklyDropdownText {',
'fill: #fff !important;',
'}',
/* eslint-enable indent */
];
};
Blockly.blockRendering.register('zelos', Blockly.zelos.Renderer);

View File

@@ -80,15 +80,19 @@ function workspaceToSvg_(workspace, callback, customCss) {
svg.setAttribute('viewBox',
x + ' ' + y + ' ' + width + ' ' + height);
svg.setAttribute('class', 'blocklySvg');
svg.setAttribute('class', 'blocklySvg ' +
(workspace.options.renderer || 'geras') + '-renderer ' +
(workspace.getTheme ? workspace.getTheme().name + '-theme' : ''));
svg.setAttribute('width', width);
svg.setAttribute('height', height);
svg.setAttribute("style", 'background-color: transparent');
var css = [].slice.call(document.head.querySelectorAll('style'))
.filter(function(el) { return /\.blocklySvg/.test(el.innerText); })[0];
.filter(function(el) { return /\.blocklySvg/.test(el.innerText) ||
(el.id.indexOf('blockly-') === 0); }).map(function(el) {
return el.innerText; }).join('\n');
var style = document.createElement('style');
style.innerHTML = css.innerText + '\n' + customCss;
style.innerHTML = css + '\n' + customCss;
svg.insertBefore(style, svg.firstChild);
var svgAsXML = (new XMLSerializer).serializeToString(svg);