Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic fonts #3698

Merged
merged 33 commits into from Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
200d67d
Draft of piping themes into the renderer and ensuring fields update t…
samelhusseini Feb 14, 2020
afd30bc
Update
samelhusseini Feb 14, 2020
3479a6e
Fix up fields.
samelhusseini Feb 18, 2020
974e264
Alter field
samelhusseini Feb 18, 2020
17754c2
Update fields
samelhusseini Feb 18, 2020
0161add
Rename to position
samelhusseini Feb 18, 2020
cdb7fad
Geras rendering compare
samelhusseini Feb 18, 2020
8c7d942
Use consistent height
samelhusseini Feb 18, 2020
cfef6ce
nit: Remove commented out code.
samelhusseini Feb 18, 2020
7d2a3c4
Better font measurement algo.
samelhusseini Feb 19, 2020
ee26d57
Fix update of auto style
samelhusseini Feb 19, 2020
263847f
Add flyout button font size.
samelhusseini Feb 19, 2020
87481aa
Remove geras compare tests
samelhusseini Feb 19, 2020
faf86ad
Fix build
samelhusseini Feb 19, 2020
e324a82
Fix mocha tests
samelhusseini Feb 19, 2020
820c55d
Fix flyout button baseline
samelhusseini Feb 19, 2020
7233906
Use vertical / horizontal margin
samelhusseini Feb 19, 2020
2461e8e
Better checkbox field positioning
samelhusseini Feb 19, 2020
0b78522
Update position logic
samelhusseini Feb 19, 2020
239c804
Fix mocha tests
samelhusseini Feb 19, 2020
a1e4bc6
PR comments
samelhusseini Feb 20, 2020
ba1bc81
PR comments
samelhusseini Feb 20, 2020
3aad169
Fix build
samelhusseini Feb 20, 2020
e6f798a
Move dynamic constants
samelhusseini Feb 20, 2020
5acd988
Move to third person
samelhusseini Feb 20, 2020
707fa52
Don't break getFastTextWidth
samelhusseini Feb 20, 2020
edae873
Update constant descriptions
samelhusseini Feb 20, 2020
5f03208
PR comments.
samelhusseini Feb 20, 2020
1ae33a4
Rename to. setDynamicProperties_
samelhusseini Feb 20, 2020
5769c37
Fix multiline field
samelhusseini Feb 20, 2020
cab3016
Revert field colour to static
samelhusseini Feb 20, 2020
a8351e2
Final cleanup
samelhusseini Feb 20, 2020
454fe0a
Merge branch 'develop' into dynamic_fonts
samelhusseini Feb 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 62 additions & 27 deletions core/field.js
Expand Up @@ -310,10 +310,6 @@ Blockly.Field.prototype.initModel = function() {
* @protected
*/
Blockly.Field.prototype.createBorderRect_ = function() {
this.size_.height =
Math.max(this.size_.height, this.constants_.FIELD_BORDER_RECT_HEIGHT);
this.size_.width =
Math.max(this.size_.width, this.constants_.FIELD_BORDER_RECT_X_PADDING * 2);
this.borderRect_ = /** @type {!SVGRectElement} **/
(Blockly.utils.dom.createSvgElement('rect',
{
Expand All @@ -334,24 +330,12 @@ Blockly.Field.prototype.createBorderRect_ = function() {
* @protected
*/
Blockly.Field.prototype.createTextElement_ = function() {
var xOffset = this.borderRect_ ?
this.constants_.FIELD_BORDER_RECT_X_PADDING : 0;
var baselineCenter = this.constants_.FIELD_TEXT_BASELINE_CENTER;
var baselineY = this.constants_.FIELD_TEXT_BASELINE_Y;
this.size_.height = Math.max(this.size_.height, baselineCenter ?
this.constants_.FIELD_TEXT_HEIGHT : baselineY);
if (this.size_.height > this.constants_.FIELD_TEXT_HEIGHT) {
baselineY += (this.size_.height - baselineY) / 2;
}
this.textElement_ = /** @type {!SVGTextElement} **/
(Blockly.utils.dom.createSvgElement('text',
{
'class': 'blocklyText',
'y': baselineCenter ? this.size_.height / 2 : baselineY,
'dy': this.constants_.FIELD_TEXT_Y_OFFSET,
'x': xOffset
}, this.fieldGroup_));
if (baselineCenter) {
if (this.constants_.FIELD_TEXT_BASELINE_CENTER) {
samelhusseini marked this conversation as resolved.
Show resolved Hide resolved
this.textElement_.setAttribute('dominant-baseline', 'central');
}
this.textContent_ = document.createTextNode('');
Expand Down Expand Up @@ -587,8 +571,8 @@ Blockly.Field.prototype.applyColour = function() {
Blockly.Field.prototype.render_ = function() {
if (this.textContent_) {
this.textContent_.nodeValue = this.getDisplayText_();
this.updateSize_();
}
this.updateSize_();
samelhusseini marked this conversation as resolved.
Show resolved Hide resolved
};

/**
Expand Down Expand Up @@ -619,22 +603,73 @@ Blockly.Field.prototype.updateWidth = function() {

/**
* Updates the size of the field based on the text.
* @param {number=} opt_margin margin to use when positioning the text element.
* @protected
*/
Blockly.Field.prototype.updateSize_ = function() {
var textWidth = Blockly.utils.dom.getFastTextWidth(
/** @type {!SVGTextElement} */ (this.textElement_),
this.constants_.FIELD_TEXT_FONTSIZE,
this.constants_.FIELD_TEXT_FONTWEIGHT,
this.constants_.FIELD_TEXT_FONTFAMILY);
var totalWidth = textWidth;
Blockly.Field.prototype.updateSize_ = function(opt_margin) {
var constants = this.constants_;
var xOffset = opt_margin != undefined ? opt_margin :
(this.borderRect_ ? this.constants_.FIELD_BORDER_RECT_X_PADDING : 0);
var totalWidth = xOffset * 2;
var totalHeight = constants.FIELD_TEXT_HEIGHT;

var contentWidth = 0;
if (this.textElement_) {
contentWidth = Blockly.utils.dom.getFastTextWidth(this.textElement_,
constants.FIELD_TEXT_FONTSIZE,
constants.FIELD_TEXT_FONTWEIGHT,
constants.FIELD_TEXT_FONTFAMILY);
totalWidth += contentWidth;
}
if (this.borderRect_) {
totalWidth += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
this.borderRect_.setAttribute('width', totalWidth);
totalHeight = Math.max(totalHeight, constants.FIELD_BORDER_RECT_HEIGHT);
}

this.size_.height = totalHeight;
this.size_.width = totalWidth;

this.positionTextElement_(xOffset, contentWidth);
this.positionBorderRect_();
};

/**
* Position a field's text element after a size change. This handles both LTR
* and RTL positioning.
* @param {number} xOffset x offset to use when positioning the text element.
* @param {number} contentWidth The content width.
* @protected
*/
Blockly.Field.prototype.positionTextElement_ = function(xOffset, contentWidth) {
samelhusseini marked this conversation as resolved.
Show resolved Hide resolved
if (!this.textElement_) {
return;
}
var constants = this.constants_;
var halfHeight = this.size_.height / 2;

this.textElement_.setAttribute('x', this.sourceBlock_.RTL ?
rachel-fenichel marked this conversation as resolved.
Show resolved Hide resolved
this.size_.width - contentWidth - xOffset : xOffset);
this.textElement_.setAttribute('y', constants.FIELD_TEXT_BASELINE_CENTER ?
halfHeight : halfHeight - constants.FIELD_TEXT_HEIGHT / 2 +
constants.FIELD_TEXT_BASELINE);
};

/**
* Position a field's border rect after a size change.
* @protected
*/
Blockly.Field.prototype.positionBorderRect_ = function() {
if (!this.borderRect_) {
return;
}
this.borderRect_.setAttribute('width', this.size_.width);
this.borderRect_.setAttribute('height', this.size_.height);
this.borderRect_.setAttribute('rx',
this.constants_.FIELD_BORDER_RECT_RADIUS);
this.borderRect_.setAttribute('ry',
this.constants_.FIELD_BORDER_RECT_RADIUS);
};


/**
* Returns the height and width of the field.
*
Expand Down
36 changes: 19 additions & 17 deletions core/field_checkbox.js
Expand Up @@ -82,15 +82,6 @@ Blockly.FieldCheckbox.prototype.SERIALIZABLE = true;
*/
Blockly.FieldCheckbox.prototype.CURSOR = 'default';

/**
* Used to tell if the field needs to be rendered the next time the block is
* rendered. Checkbox fields are statically sized, and only need to be
* rendered at initialization.
* @type {boolean}
* @protected
*/
Blockly.FieldCheckbox.prototype.isDirty_ = false;
samelhusseini marked this conversation as resolved.
Show resolved Hide resolved

/**
* Configure the field based on the given map of options.
* @param {!Object} config A map of options to configure the field based on.
Expand All @@ -108,19 +99,30 @@ Blockly.FieldCheckbox.prototype.configure_ = function(config) {
* @package
*/
Blockly.FieldCheckbox.prototype.initView = function() {
this.size_.width = this.constants_.FIELD_CHECKBOX_DEFAULT_WIDTH;
Blockly.FieldCheckbox.superClass_.initView.call(this);

this.textElement_.setAttribute('x', this.constants_.FIELD_CHECKBOX_X_OFFSET);
this.textElement_.setAttribute('y', this.constants_.FIELD_CHECKBOX_Y_OFFSET);
this.textElement_.removeAttribute('dominant-baseline');
Blockly.utils.dom.addClass(this.textElement_, 'blocklyCheckbox');

this.textContent_.nodeValue =
this.checkChar_ || Blockly.FieldCheckbox.CHECK_CHAR;
Blockly.utils.dom.addClass(
/** @type {!SVGTextElement} **/ (this.textElement_), 'blocklyCheckbox');
this.textElement_.style.display = this.value_ ? 'block' : 'none';
};

/**
* @override
*/
Blockly.FieldCheckbox.prototype.render_ = function() {
if (this.textContent_) {
this.textContent_.nodeValue = this.getDisplayText_();
}
this.updateSize_(this.constants_.FIELD_CHECKBOX_X_OFFSET);
rachel-fenichel marked this conversation as resolved.
Show resolved Hide resolved
};

/**
* @override
*/
Blockly.FieldCheckbox.prototype.getDisplayText_ = function() {
return this.checkChar_ || Blockly.FieldCheckbox.CHECK_CHAR;
};

/**
* Set the character used for the check mark.
* @param {?string} character The character to use for the check mark, or
Expand Down
38 changes: 14 additions & 24 deletions core/field_dropdown.js
Expand Up @@ -564,10 +564,8 @@ Blockly.FieldDropdown.prototype.render_ = function() {
} else {
this.renderSelectedText_();
}
if (this.borderRect_) {
this.borderRect_.setAttribute('height', this.size_.height);
this.borderRect_.setAttribute('width', this.size_.width);
}

this.positionBorderRect_();
samelhusseini marked this conversation as resolved.
Show resolved Hide resolved
};

/**
Expand All @@ -588,14 +586,13 @@ Blockly.FieldDropdown.prototype.renderSelectedImage_ = function(imageJson) {

// Height and width include the border rect.
var hasBorder = !!this.borderRect_;
this.size_.height = Math.max(
var height = Math.max(
hasBorder ? this.constants_.FIELD_DROPDOWN_BORDER_RECT_HEIGHT : 0,
imageHeight + Blockly.FieldDropdown.IMAGE_Y_PADDING);
var halfHeight = this.size_.height / 2;
var xPadding = hasBorder ? this.constants_.FIELD_BORDER_RECT_X_PADDING : 0;
var arrowWidth = 0;
if (this.svgArrow_) {
arrowWidth = this.positionSVGArrow_(imageWidth + xPadding, halfHeight -
arrowWidth = this.positionSVGArrow_(imageWidth + xPadding, height / 2 -
this.constants_.FIELD_DROPDOWN_SVG_ARROW_SIZE / 2);
} else {
arrowWidth = Blockly.utils.dom.getFastTextWidth(
Expand All @@ -605,19 +602,20 @@ Blockly.FieldDropdown.prototype.renderSelectedImage_ = function(imageJson) {
this.constants_.FIELD_TEXT_FONTFAMILY);
}
this.size_.width = imageWidth + arrowWidth + xPadding * 2;
this.size_.height = height;

var arrowX = 0;
if (this.sourceBlock_.RTL) {
var imageX = xPadding + arrowWidth;
var arrowX = xPadding - 1;
this.imageElement_.setAttribute('x', imageX);
this.textElement_.setAttribute('x', arrowX);
} else {
var arrowX = imageWidth + arrowWidth + xPadding + 1;
arrowX = imageWidth + arrowWidth;
this.textElement_.setAttribute('text-anchor', 'end');
this.textElement_.setAttribute('x', arrowX);
this.imageElement_.setAttribute('x', xPadding);
}
this.imageElement_.setAttribute('y', halfHeight - imageHeight / 2);
this.imageElement_.setAttribute('y', height / 2 - imageHeight / 2);

this.positionTextElement_(arrowX + xPadding, imageWidth + arrowWidth);
};

/**
Expand All @@ -633,31 +631,23 @@ Blockly.FieldDropdown.prototype.renderSelectedText_ = function() {

// Height and width include the border rect.
var hasBorder = !!this.borderRect_;
this.size_.height = Math.max(
var height = Math.max(
hasBorder ? this.constants_.FIELD_DROPDOWN_BORDER_RECT_HEIGHT : 0,
this.constants_.FIELD_TEXT_HEIGHT);
var halfHeight = this.size_.height / 2;
var textWidth = Blockly.utils.dom.getFastTextWidth(this.textElement_,
this.constants_.FIELD_TEXT_FONTSIZE,
this.constants_.FIELD_TEXT_FONTWEIGHT,
this.constants_.FIELD_TEXT_FONTFAMILY);
var xPadding = hasBorder ? this.constants_.FIELD_BORDER_RECT_X_PADDING : 0;
var arrowWidth = 0;
if (this.svgArrow_) {
arrowWidth = this.positionSVGArrow_(textWidth + xPadding, halfHeight -
arrowWidth = this.positionSVGArrow_(textWidth + xPadding, height / 2 -
this.constants_.FIELD_DROPDOWN_SVG_ARROW_SIZE / 2);
}
this.size_.width = textWidth + arrowWidth + xPadding * 2;
this.size_.height = height;

this.textElement_.setAttribute('x', this.sourceBlock_.RTL ?
this.size_.width - textWidth - xPadding : xPadding);
this.textElement_.setAttribute('y', halfHeight);
if (!this.constants_.FIELD_TEXT_BASELINE_CENTER) {
this.textElement_.setAttribute('dy',
this.constants_.FIELD_TEXT_BASELINE_Y -
this.constants_.FIELD_TEXT_HEIGHT / 2 +
this.constants_.FIELD_TEXT_Y_OFFSET);
}
this.positionTextElement_(xPadding, textWidth);
};

/**
Expand Down
7 changes: 7 additions & 0 deletions core/field_image.js
Expand Up @@ -186,6 +186,13 @@ Blockly.FieldImage.prototype.initView = function() {
}
};

/**
* @override
*/
Blockly.FieldImage.prototype.updateSize_ = function() {
// NOP
};

/**
* Ensure that the input value (the source URL) is a string.
* @param {*=} opt_newValue The input value.
Expand Down
51 changes: 17 additions & 34 deletions core/field_multilineinput.js
Expand Up @@ -60,13 +60,6 @@ Blockly.utils.object.inherits(Blockly.FieldMultilineInput,
Blockly.FieldTextInput);


/**
* The default height of a single line of text.
* @type {number}
* @const
*/
Blockly.FieldMultilineInput.LINE_HEIGHT = 20;

/**
* Construct a FieldMultilineInput from a JSON arg object,
* dereferencing any string table references.
Expand Down Expand Up @@ -143,14 +136,16 @@ Blockly.FieldMultilineInput.prototype.render_ = function() {
var lines = this.getDisplayText_().split('\n');
var y = 0;
for (var i = 0; i < lines.length; i++) {
var lineHeight = this.constants_.FIELD_TEXT_HEIGHT +
this.constants_.FIELD_BORDER_RECT_Y_PADDING;
var span = Blockly.utils.dom.createSvgElement('text', {
'class': 'blocklyText blocklyMultilineText',
x: this.constants_.FIELD_BORDER_RECT_X_PADDING,
y: y + this.constants_.FIELD_BORDER_RECT_Y_PADDING,
dy: Blockly.FieldMultilineInput.LINE_HEIGHT / 2
dy: this.constants_.FIELD_TEXT_BASELINE
}, this.textGroup_);
span.appendChild(document.createTextNode(lines[i]));
y += Blockly.FieldMultilineInput.LINE_HEIGHT;
y += lineHeight;
}

this.updateSize_();
Expand Down Expand Up @@ -191,34 +186,19 @@ Blockly.FieldMultilineInput.prototype.updateSize_ = function() {
if (textWidth > totalWidth) {
totalWidth = textWidth;
}
totalHeight += Blockly.FieldMultilineInput.LINE_HEIGHT;
totalHeight += this.constants_.FIELD_TEXT_HEIGHT +
(i > 0 ? this.constants_.FIELD_BORDER_RECT_Y_PADDING : 0);
}
if (this.borderRect_) {
totalHeight += this.constants_.FIELD_BORDER_RECT_Y_PADDING * 2;
totalWidth += this.constants_.FIELD_BORDER_RECT_X_PADDING * 2;
this.borderRect_.setAttribute('width', totalWidth);
this.borderRect_.setAttribute('height', totalHeight);
}
this.size_.width = totalWidth;
this.size_.height = totalHeight;
};

/**
* Resize the editor to fit the text.
* @protected
*/
Blockly.FieldMultilineInput.prototype.resizeEditor_ = function() {
var div = Blockly.WidgetDiv.DIV;
var bBox = this.getScaledBBox();
div.style.width = bBox.right - bBox.left + 'px';
div.style.height = bBox.bottom - bBox.top + 'px';

// In RTL mode block fields and LTR input fields the left edge moves,
// whereas the right edge is fixed. Reposition the editor.
var x = this.sourceBlock_.RTL ? bBox.right - div.offsetWidth : bBox.left;
var xy = new Blockly.utils.Coordinate(x, bBox.top);

div.style.left = xy.x + 'px';
div.style.top = xy.y + 'px';
this.positionBorderRect_();
};

/**
Expand All @@ -230,19 +210,22 @@ Blockly.FieldMultilineInput.prototype.widgetCreate_ = function() {
var div = Blockly.WidgetDiv.DIV;
var scale = this.workspace_.scale;

var htmlInput = /** @type {HTMLTextAreaElement} */ (document.createElement('textarea'));
var htmlInput =
/** @type {HTMLTextAreaElement} */ (document.createElement('textarea'));
htmlInput.className = 'blocklyHtmlInput blocklyHtmlTextAreaInput';
htmlInput.setAttribute('spellcheck', this.spellcheck_);
var fontSize = (this.constants_.FIELD_TEXT_FONTSIZE * scale) + 'pt';
div.style.fontSize = fontSize;
htmlInput.style.fontSize = fontSize;
var borderRadius = (Blockly.FieldTextInput.BORDERRADIUS * scale) + 'px';
htmlInput.style.borderRadius = borderRadius;
var padding = this.constants_.FIELD_BORDER_RECT_X_PADDING * scale;
htmlInput.style.paddingLeft = padding + 'px';
htmlInput.style.width = 'calc(100% - ' + padding + 'px)';
htmlInput.style.lineHeight =
(Blockly.FieldMultilineInput.LINE_HEIGHT * scale) + 'px';
var paddingX = this.constants_.FIELD_BORDER_RECT_X_PADDING * scale;
var paddingY = this.constants_.FIELD_BORDER_RECT_Y_PADDING * scale / 2;
htmlInput.style.padding = paddingY + 'px ' + paddingX + 'px ' + paddingY +
'px ' + paddingX + 'px';
var lineHeight = this.constants_.FIELD_TEXT_HEIGHT +
this.constants_.FIELD_BORDER_RECT_Y_PADDING;
htmlInput.style.lineHeight = (lineHeight * scale) + 'px';

div.appendChild(htmlInput);

Expand Down