diff --git a/core/block_render_svg_horizontal.js b/core/block_render_svg_horizontal.js index c05e09acbf..a56762ce81 100644 --- a/core/block_render_svg_horizontal.js +++ b/core/block_render_svg_horizontal.js @@ -63,6 +63,13 @@ Blockly.BlockSvg.FIELD_HEIGHT = 8 * Blockly.BlockSvg.GRID_UNIT; * @const */ Blockly.BlockSvg.FIELD_WIDTH = 12 * Blockly.BlockSvg.GRID_UNIT; + +/** + * Top padding of user inputs + * @const + */ +Blockly.BlockSvg.FIELD_TOP_PADDING = 1.5 * Blockly.BlockSvg.GRID_UNIT; + /** * Corner radius of number inputs * @const @@ -308,11 +315,7 @@ Blockly.BlockSvg.prototype.renderCompute_ = function() { var fieldBBox = field.textElement_.getBBox(); metrics.fieldWidth = fieldBBox.width + Blockly.BlockSvg.SEP_SPACE_X; metrics.fieldHeight = fieldBBox.height; - if (field.sourceBlock_.type === 'math_number') { - metrics.fieldRadius = Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS; - } else { - metrics.fieldRadius = Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS; - } + metrics.fieldRadius = field.getBorderRadius(); } } } diff --git a/core/block_svg.js b/core/block_svg.js index bce852ab65..edd1ef5050 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -304,6 +304,11 @@ Blockly.BlockSvg.prototype.setParent = function(newParent) { var newXY = this.getRelativeToSurfaceXY(); // Move the connections to match the child's new position. this.moveConnections_(newXY.x - oldXY.x, newXY.y - oldXY.y); + // If we are a shadow block, inherit tertiary colour. + if (this.isShadow()) { + this.setColour(this.getColour(), this.getColourSecondary(), + newParent.getColourTertiary()); + } } }; diff --git a/core/css.js b/core/css.js index 26319ef8ba..5d1486e714 100644 --- a/core/css.js +++ b/core/css.js @@ -143,6 +143,13 @@ Blockly.Css.CONTENT = [ 'display: none;', 'position: absolute;', 'z-index: 999;', + 'overflow: hidden;', + 'border: 1px solid;', + 'box-sizing: border-box;', + 'transform-origin: 0 0;', + '-ms-transform-origin: 0 0;', + '-moz-transform-origin: 0 0;', + '-webkit-transform-origin: 0 0;', '}', '.blocklyNonSelectable {', @@ -288,14 +295,13 @@ Blockly.Css.CONTENT = [ '.blocklyHtmlInput {', 'border: none;', - 'border-radius: 4px;', 'font-family: sans-serif;', 'height: 100%;', 'margin: 0;', 'outline: none;', - 'padding: 0 1px;', + 'padding: 2px 0;', 'width: 100%;', - 'text-align: center', + 'text-align: center;', '}', '.blocklyMainBackground {', diff --git a/core/field.js b/core/field.js index 7b1de62d0c..1019974b13 100644 --- a/core/field.js +++ b/core/field.js @@ -134,18 +134,13 @@ Blockly.Field.prototype.init = function(block) { if (!this.visible_) { this.fieldGroup_.style.display = 'none'; } - this.borderRect_ = Blockly.createSvgElement('rect', - {'rx': 4, - 'ry': 4, - 'x': -Blockly.BlockSvg.SEP_SPACE_X / 2, - 'y': 0, - 'height': Blockly.BlockSvg.FIELD_HEIGHT}, this.fieldGroup_, this.sourceBlock_.workspace); + // Adjust X to be flipped for RTL. Position is relative to horizontal start of source block. + var fieldX = (this.sourceBlock_.RTL) ? -this.size_.width / 2 : this.size_.width / 2; /** @type {!Element} */ this.textElement_ = Blockly.createSvgElement('text', {'class': 'blocklyText', - 'y': this.size_.height/2 + 6.25, - 'x': Blockly.BlockSvg.FIELD_WIDTH / 2, - 'width': Blockly.BlockSvg.FIELD_WIDTH - Blockly.BlockSvg.SEP_SPACE_X, + 'x': fieldX, + 'y': this.size_.height / 2 + Blockly.BlockSvg.FIELD_TOP_PADDING, 'text-anchor': 'middle'}, this.fieldGroup_); @@ -174,7 +169,6 @@ Blockly.Field.prototype.dispose = function() { goog.dom.removeNode(this.fieldGroup_); this.fieldGroup_ = null; this.textElement_ = null; - this.borderRect_ = null; this.validator_ = null; }; @@ -264,10 +258,6 @@ Blockly.Field.prototype.render_ = function() { Blockly.Field.cacheWidths_[key] = width; } } - if (this.borderRect_) { - this.borderRect_.setAttribute('width', - width + Blockly.BlockSvg.SEP_SPACE_X); - } } else { var width = 0; } @@ -314,10 +304,10 @@ Blockly.Field.prototype.getSize = function() { * @private */ Blockly.Field.prototype.getScaledBBox_ = function() { - var bBox = this.borderRect_.getBBox(); - // Create new object, as getBBox can return an uneditable SVGRect in IE. - return new goog.math.Size(bBox.width * this.sourceBlock_.workspace.scale, - bBox.height * this.sourceBlock_.workspace.scale); + var size = this.getSize(); + // Create new object, so as to not return an uneditable SVGRect in IE. + return new goog.math.Size(size.width * this.sourceBlock_.workspace.scale, + size.height * this.sourceBlock_.workspace.scale); }; /** @@ -479,5 +469,5 @@ Blockly.Field.prototype.getClickTarget_ = function() { * @private */ Blockly.Field.prototype.getAbsoluteXY_ = function() { - return goog.style.getPageOffset(this.borderRect_); + return goog.style.getPageOffset(this.getClickTarget_()); }; diff --git a/core/field_colour.js b/core/field_colour.js index ee75f47366..96318b9eec 100644 --- a/core/field_colour.js +++ b/core/field_colour.js @@ -70,7 +70,12 @@ Blockly.FieldColour.prototype.columns_ = 0; */ Blockly.FieldColour.prototype.init = function(block) { Blockly.FieldColour.superClass_.init.call(this, block); - this.borderRect_.style['fillOpacity'] = 1; + // TODO(#163): borderRect_ has been removed from the field. + // When fixing field_colour, we should re-color the shadow block instead, + // or re-implement a rectangle in the field. + if (this.borderRect_) { + this.borderRect_.style['fillOpacity'] = 1; + } this.setValue(this.getValue()); }; diff --git a/core/field_textinput.js b/core/field_textinput.js index aeddd48724..236b5cb9e8 100644 --- a/core/field_textinput.js +++ b/core/field_textinput.js @@ -131,7 +131,7 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) { var htmlInput = goog.dom.createDom('input', 'blocklyHtmlInput'); htmlInput.setAttribute('spellcheck', this.spellcheck_); var fontSize = - (Blockly.FieldTextInput.FONTSIZE * this.workspace_.scale) + 'pt'; + (Blockly.FieldTextInput.FONTSIZE) + 'pt'; div.style.fontSize = fontSize; htmlInput.style.fontSize = fontSize; /** @type {!HTMLInputElement} */ @@ -225,40 +225,63 @@ Blockly.FieldTextInput.prototype.validate_ = function() { * @private */ Blockly.FieldTextInput.prototype.resizeEditor_ = function() { + var scale = this.sourceBlock_.workspace.scale; var div = Blockly.WidgetDiv.DIV; - var bBox = this.fieldGroup_.getBBox(); - var height = bBox.height * this.sourceBlock_.workspace.scale; - var width = Math.max( - bBox.width, Blockly.BlockSvg.FIELD_WIDTH-Blockly.BlockSvg.SEP_SPACE_X) * - this.sourceBlock_.workspace.scale - div.style.width = width + 'px'; - div.style.height = height + 'px'; + var bBox = this.getScaledBBox_(); + // The width of this box must be at least FIELD_WIDTH * scale. + // It may be smaller as bBox is based on the content size. + var width = Math.max(bBox.width, Blockly.BlockSvg.FIELD_WIDTH * scale); + // Add 1px to width and height to account for border (pre-scale) + div.style.width = (width / scale + 1) + 'px'; + div.style.height = (bBox.height / scale + 1) + 'px'; + div.style.transform = 'scale(' + scale + ')'; + + // Add 0.5px to account for slight difference between SVG and CSS border + var borderRadius = this.getBorderRadius() + 0.5; + div.style.borderRadius = borderRadius + 'px'; + // Pull stroke colour from the existing shadow block + var strokeColour = this.sourceBlock_.getColourTertiary(); + div.style.borderColor = strokeColour; + var xy = this.getAbsoluteXY_(); - xy.x += Blockly.BlockSvg.SEP_SPACE_X * this.sourceBlock_.workspace.scale; - // @todo Why 3? - xy.y += (Blockly.BlockSvg.FIELD_HEIGHT * this.sourceBlock_.workspace.scale)/2 - height/2 + 3; + // Account for border width, post-scale + xy.x -= scale / 2; + xy.y -= scale / 2; // In RTL mode block fields and LTR input fields the left edge moves, // whereas the right edge is fixed. Reposition the editor. if (this.sourceBlock_.RTL) { - var borderBBox = this.getScaledBBox_(); - xy.x += borderBBox.width; + xy.x += width; xy.x -= div.offsetWidth; } // Shift by a few pixels to line up exactly. - xy.y += 1; + xy.y += 1 * scale; if (goog.userAgent.GECKO && Blockly.WidgetDiv.DIV.style.top) { // Firefox mis-reports the location of the border by a pixel // once the WidgetDiv is moved into position. - xy.x -= 1; - xy.y -= 1; + xy.x += 2 * scale; + xy.y += 1 * scale; } if (goog.userAgent.WEBKIT) { - xy.y -= 3; + xy.x += 0.5; + xy.y -= 1 * scale; } + // Finally, set the actual style div.style.left = xy.x + 'px'; div.style.top = xy.y + 'px'; }; +/** + * Determine border radius based on the type of the owning shadow block. + * @return {Number} Border radius in px. +*/ +Blockly.Field.prototype.getBorderRadius = function() { + if (this.sourceBlock_.type === 'math_number') { + return Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS; + } else { + return Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS; + } +}; + /** * Close the editor, save the results, and dispose of the editable * text field's elements.