Commit e2af14c3 authored by Neil Fraser's avatar Neil Fraser

Replace drawn icons with images (issue 45).

parent 1916f235
This diff is collapsed.
......@@ -39,10 +39,15 @@ goog.require('goog.userAgent');
*/
Blockly.Comment = function(block) {
Blockly.Comment.superClass_.constructor.call(this, block);
this.createIcon_();
this.createIcon();
};
goog.inherits(Blockly.Comment, Blockly.Icon);
/**
* Icon in base64 format.
* @private
*/
Blockly.Comment.prototype.png_ = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAANyAAADcgBffIlqAAAAAd0SU1FB98DGgAnBf0Xj5sAAAIBSURBVDjLjZO9SxxRFMXPrFkWl2UFYSOIRtF210YtAiH/gGATRNZFgo19IBaB9Ipgk3SiEoKQgI19JIVgGaOIgpWJEAV1kZk3b1ad0V+KRYIzk5ALh1ecc88978tRSgHPg0Bjvq/BbFalMNR5oaBv+bzWHMfZjOudWPOg6+pDva6elRXlt7fVcnYmPX4sDQ3pdmpKQXu7frS16aXjON8T06OIMWOwtRp3jgNSEpkMTE5y5/v4UcSLePxnroutVNKb4xgYANfFAk/vDbLG8Gtk5P8M7jE6CsZwDDwSMLm5iYmLlpbg4ABOTmBjA4aHk0ZbWxigposLvlarScH5OSwvw9oaABwdJTW1GtTrfJHnUe/uTgqKxeZaKEAUgTEQP/CeHvA8LhRFhLlc+r6zWVhfbyaZn0/yuRxEEaGCAK9USjdZWGgarK5CS0uS7+gAa3EzjYaOy2WlludJi4vSzIx0e5vky2Xp6ko/M4WCPleruk4zsVa6vJSur9OHTEzoqljUJwEdQYDf25uMe3jY3E5fX5Lr7wdr8YGSJCkIeL23h9/a+lA4Pg7T039u6h75POzv4wcBrx5Ec11Wd3bwOzv//VK7umB3F991+Zj2/R1reWstdnaWm3L5YXOlAnNz3FiLbTR4Azj6WwFPjOG953EahoT1On4YEnoep8bwDuiO9/wG1sM4kG8A4fUAAAAASUVORK5CYII=';
/**
* Comment text (if bubble is not visible).
......@@ -62,28 +67,6 @@ Blockly.Comment.prototype.width_ = 160;
*/
Blockly.Comment.prototype.height_ = 80;
/**
* Create the icon on the block.
* @private
*/
Blockly.Comment.prototype.createIcon_ = function() {
Blockly.Icon.prototype.createIcon_.call(this);
/* Here's the markup that will be generated:
<circle class="blocklyIconShield" r="8" cx="8" cy="8"/>
<text class="blocklyIconMark" x="8" y="13">?</text>
*/
var iconShield = Blockly.createSvgElement('circle',
{'class': 'blocklyIconShield',
'r': Blockly.Icon.RADIUS,
'cx': Blockly.Icon.RADIUS,
'cy': Blockly.Icon.RADIUS}, this.iconGroup_);
this.iconMark_ = Blockly.createSvgElement('text',
{'class': 'blocklyIconMark',
'x': Blockly.Icon.RADIUS,
'y': 2 * Blockly.Icon.RADIUS - 3}, this.iconGroup_);
this.iconMark_.appendChild(document.createTextNode('?'));
};
/**
* Create the editor for the comment's bubble.
* @return {!Element} The top-level node of the editor.
......
......@@ -272,13 +272,9 @@ Blockly.Css.CONTENT = [
' stroke-width: 1px;',
'}',
'.blocklyIconGroup:hover>.blocklyIconShield {',
' fill: #00f;',
' stroke: #fff;',
'}',
'.blocklyIconGroup:hover>.blocklyIconMark {',
' fill: #fff;',
'.blocklyIconGroup:not(:hover),',
'.blocklyIconGroupReadonly {',
' opacity: .6;',
'}',
'.blocklyIconMark {',
......
......@@ -39,9 +39,15 @@ Blockly.Icon = function(block) {
};
/**
* Radius of icons.
* Icon in base64 format.
* @private
*/
Blockly.Icon.prototype.png_ = '';
/**
* Height and width of icons.
*/
Blockly.Icon.RADIUS = 8;
Blockly.Icon.prototype.SIZE = 17;
/**
* Bubble UI (if visible).
......@@ -64,17 +70,25 @@ Blockly.Icon.prototype.iconY_ = 0;
/**
* Create the icon on the block.
* @private
*/
Blockly.Icon.prototype.createIcon_ = function() {
Blockly.Icon.prototype.createIcon = function() {
if (this.iconGroup_) {
// Icon already exists.
return;
}
/* Here's the markup that will be generated:
<g class="blocklyIconGroup"></g>
<g class="blocklyIconGroup">
<image width="17" height="17"
xlink:href="data:image/png;base64,iVBOR..."></image>
</g>
*/
this.iconGroup_ = Blockly.createSvgElement('g', {}, null);
this.iconGroup_ = Blockly.createSvgElement('g',
{'class': 'blocklyIconGroup'}, null);
var img = Blockly.createSvgElement('image',
{'width': this.SIZE, 'height': this.SIZE},
this.iconGroup_);
img.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', this.png_);
this.block_.getSvgRoot().appendChild(this.iconGroup_);
Blockly.bindEvent_(this.iconGroup_, 'mouseup', this, this.iconClick_);
this.updateEditable();
......@@ -96,12 +110,12 @@ Blockly.Icon.prototype.dispose = function() {
* Add or remove the UI indicating if this icon may be clicked or not.
*/
Blockly.Icon.prototype.updateEditable = function() {
if (!this.block_.isInFlyout) {
if (this.block_.isInFlyout || !this.block_.isEditable()) {
Blockly.addClass_(/** @type {!Element} */ (this.iconGroup_),
'blocklyIconGroup');
'blocklyIconGroupReadonly');
} else {
Blockly.removeClass_(/** @type {!Element} */ (this.iconGroup_),
'blocklyIconGroup');
'blocklyIconGroupReadonly');
}
};
......@@ -147,9 +161,9 @@ Blockly.Icon.prototype.renderIcon = function(cursorX) {
this.iconGroup_.setAttribute('display', 'block');
var TOP_MARGIN = 5;
var diameter = 2 * Blockly.Icon.RADIUS;
var width = this.SIZE;
if (Blockly.RTL) {
cursorX -= diameter;
cursorX -= width;
}
this.iconGroup_.setAttribute('transform',
'translate(' + cursorX + ', ' + TOP_MARGIN + ')');
......@@ -157,7 +171,7 @@ Blockly.Icon.prototype.renderIcon = function(cursorX) {
if (Blockly.RTL) {
cursorX -= Blockly.BlockSvg.SEP_SPACE_X;
} else {
cursorX += diameter + Blockly.BlockSvg.SEP_SPACE_X;
cursorX += width + Blockly.BlockSvg.SEP_SPACE_X;
}
return cursorX;
};
......@@ -183,8 +197,8 @@ Blockly.Icon.prototype.computeIconLocation = function() {
// Find coordinates for the centre of the icon and update the arrow.
var blockXY = this.block_.getRelativeToSurfaceXY();
var iconXY = Blockly.getRelativeXY_(this.iconGroup_);
var newX = blockXY.x + iconXY.x + Blockly.Icon.RADIUS;
var newY = blockXY.y + iconXY.y + Blockly.Icon.RADIUS;
var newX = blockXY.x + iconXY.x + this.SIZE / 2;
var newY = blockXY.y + iconXY.y + this.SIZE / 2;
if (newX !== this.iconX_ || newY !== this.iconY_) {
this.setIconLocation(newX, newY);
}
......
......@@ -46,6 +46,12 @@ Blockly.Mutator = function(quarkNames) {
};
goog.inherits(Blockly.Mutator, Blockly.Icon);
/**
* Icon in base64 format.
* @private
*/
Blockly.Mutator.prototype.png_ = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAANyAAADcgBffIlqAAAAAd0SU1FB98DGgUkCK5AYg4AAAGlSURBVDjLnZS9SiRBFIVLunt+9gUU1EmFaSfQ0GCeRcTAwEDERHYTQUZ8l6F9Ad9gMzcVfwaxdzpxuHRVZNVncHfAnt5ply0oqjj33FP3FqfKGGMM8K0suRZhGgKehhECXoSpc1wBXTMXEOHXeIzr9yGKwJjlM4ogTSHLcCLcAV1TllyPx7imxGUzy3DWMjIiTPv9OiGOYXVV92tr0GrVOWkKIuQmBPxiC1EEz8/w8ADn53B/D6+vkCR1Xgh4A9XAygrs7IBfuF7vYW9PK/zMB6iIJIlW8P4O1sLZmSaenkJZqlCeQ7vdILKxAS8vGjg5qZ54fKz4ZAKbmw0ixsDFhQZ2d6v4YKD45eUX7ayvw+OjBo6OquTDQ8WfnrTipSLtNhQFhACzGRwcwNYW7O/D25viRQGdzhfttFowHGrCgt0ZDut+AfirT5JET5xMYDTStSjqPonjPz4RYZqmdTd2OtDr6b7Xq7bw+bJFyI1zXGXZ/72d21tKa/lugK4Idzc3uO3tf3vFg4EKzGb8BOL5d9C1lpEIv70nNP0n3hNEyK3lx1zgA46lEkSYoMBCAAAAAElFTkSuQmCC';
/**
* Width of workspace.
* @private
......@@ -58,33 +64,6 @@ Blockly.Mutator.prototype.workspaceWidth_ = 0;
*/
Blockly.Mutator.prototype.workspaceHeight_ = 0;
/**
* Create the icon on the block.
*/
Blockly.Mutator.prototype.createIcon = function() {
if (this.iconMark_) {
// Icon already exists.
return;
}
Blockly.Icon.prototype.createIcon_.call(this);
/* Here's the markup that will be generated:
<rect class="blocklyIconShield" width="16" height="16" rx="4" ry="4"/>
<text class="blocklyIconMark" x="8" y="12">★</text>
*/
var quantum = Blockly.Icon.RADIUS / 2;
var iconShield = Blockly.createSvgElement('rect',
{'class': 'blocklyIconShield',
'width': 4 * quantum,
'height': 4 * quantum,
'rx': quantum,
'ry': quantum}, this.iconGroup_);
this.iconMark_ = Blockly.createSvgElement('text',
{'class': 'blocklyIconMark',
'x': Blockly.Icon.RADIUS,
'y': 2 * Blockly.Icon.RADIUS - 4}, this.iconGroup_);
this.iconMark_.appendChild(document.createTextNode('\u2605'));
};
/**
* Clicking on the icon toggles if the mutator bubble is visible.
* Disable if block is uneditable.
......@@ -136,8 +115,8 @@ Blockly.Mutator.prototype.updateEditable = function() {
// Close any mutator bubble. Icon is not clickable.
this.setVisible(false);
if (this.iconGroup_) {
Blockly.removeClass_(/** @type {!Element} */ (this.iconGroup_),
'blocklyIconGroup');
Blockly.addClass_(/** @type {!Element} */ (this.iconGroup_),
'blocklyIconGroupReadonly');
}
}
};
......
......@@ -38,10 +38,15 @@ goog.require('Blockly.Icon');
*/
Blockly.Warning = function(block) {
Blockly.Warning.superClass_.constructor.call(this, block);
this.createIcon_();
this.createIcon();
};
goog.inherits(Blockly.Warning, Blockly.Icon);
/**
* Icon in base64 format.
* @private
*/
Blockly.Warning.prototype.png_ = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAANyAAADcgBffIlqAAAAAd0SU1FB98DGgApDBpIGrEAAAGfSURBVDjLnZM9S2NREIbfc2P8AF27BXshpIzK5g9ssUj8C2tnYyUoiBGSyk4sbCLs1vkRgoW1jYWFICwsMV2Se3JPboLe+FhcNCZcjXFgOMzHeec9M2ekDwTIAEUgo68IsOQczdNTIudoAksTg/g+5+UyDxKUyzz4PueTsvhZr+NmZkCC6Wmo1QiAX58FmLKWf4VCDPCiGxtgLf+B9FiQXo+9y0ucBIUCnJ3B+noMdHGBC0P2xrH4HoYEmUx8qVQCgMPD2F5ehjDEjTbZe2s4p5NKRenb2+Qid3dSpaK0tTp+j8VKq0VncXHQh2IxZrK/P/AtLECjQQf4McQEMNbq786O5qwdANfr8Xl/P/AFgbS7qzlr9Qcwr4EoYvPmBud5wxPJ5+HqCtbWhv3GwPU1Lor4/fKMeedo5vPDiRKsrsLWFuRyybFOhxbwTd0upWqVcDQpaTqjWq0SdruU5PvUkiol/ZNRzeXA96mp3aaRzSYnjdNsFtptGiYI2PY8HaVSmu33xWf3K5WS6ffVe3rSgXnzT+YlpSfY00djjJOkZ/wpr41bQMIsAAAAAElFTkSuQmCC';
/**
* Create the text for the warning's bubble.
......@@ -71,28 +76,6 @@ Blockly.Warning.textToDom_ = function(text) {
*/
Blockly.Warning.prototype.text_ = '';
/**
* Create the icon on the block.
* @private
*/
Blockly.Warning.prototype.createIcon_ = function() {
Blockly.Icon.prototype.createIcon_.call(this);
/* Here's the markup that will be generated:
<path class="blocklyIconShield" d="..."/>
<text class="blocklyIconMark" x="8" y="13">!</text>
*/
var iconShield = Blockly.createSvgElement('path',
{'class': 'blocklyIconShield',
'd': 'M 2,15 Q -1,15 0.5,12 L 6.5,1.7 Q 8,-1 9.5,1.7 L 15.5,12 ' +
'Q 17,15 14,15 z'},
this.iconGroup_);
this.iconMark_ = Blockly.createSvgElement('text',
{'class': 'blocklyIconMark',
'x': Blockly.Icon.RADIUS,
'y': 2 * Blockly.Icon.RADIUS - 3}, this.iconGroup_);
this.iconMark_.appendChild(document.createTextNode('!'));
};
/**
* Show or hide the warning bubble.
* @param {boolean} visible True if the bubble should be visible.
......
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="17px" height="57px">
<style type="text/css">
#background {
fill: none;
}
.shield {
fill: #00f;
stroke: #fff;
stroke-width: 1px;
}
.mark {
fill: #fff;
font-family: sans-serif;
font-size: 9pt;
font-weight: bold;
text-anchor: middle;
}
#gear {
fill:#fff;
}
</style>
<rect id="background" width="17" height="57" x="0" y="0" />
<g transform="translate(0.5, 0.5)">
<g class="comment" transform="translate(0, 0)">
<circle class="shield" r="8" cx="8" cy="8" />
<text class="mark" x="8" y="12.75">?</text>
</g>
<g class="mutator" transform="translate(0, 20)">
<rect class="shield" width="16" height="16" rx="4" ry="4" />
<path id="gear" transform="scale(.8, .8)"
d="m 11.45,4.05 a 1.4926864,1.4926414 0 0 1 -1.435182,1.0875 1.4926864,1.4926414 0 0 1 -1.436269,-1.0873 6.1766332,6.176447 0 0 0 -1.790178,0.745 1.4926864,1.4926414 0 0 1 -0.247387,1.7812 1.4926864,1.4926414 0 0 1 -1.783784,0.247 6.1766332,6.176447 0 0 0 -0.742282,1.7916 1.4926864,1.4926414 0 0 1 1.087144,1.4351 a 1.4926864,1.4926414 0 0 1 -1.1,1.4 a 6.1766332,6.176447 0 0 0 0.745056,1.7901 1.4926864,1.4926414 0 0 1 1.781211,0.2474 1.4926864,1.4926414 0 0 1 0.247106,1.7837 6.1766332,6.176447 0 0 0 1.791625,0.7423 1.4926864,1.4926414 0 0 1 1.435103,-1.0871 1.4926864,1.4926414 0 0 1 1.436268,1.0873 6.1766332,6.176447 0 0 0 1.790178,-0.745 1.4926864,1.4926414 0 0 1 0.247387,-1.7812 1.4926864,1.4926414 0 0 1 1.783784,-0.2471 6.1766332,6.176447 0 0 0 0.742282,-1.7916 1.4926864,1.4926414 0 0 1 -1.087144,-1.435 1.4926864,1.4926414 0 0 1 1.085737,-1.4358 6.1766332,6.176447 0 0 0 -0.746223,-1.7889 1.4926864,1.4926414 0 0 1 -1.778436,-0.249 1.4926864,1.4926414 0 0 1 -0.249317,-1.7793 6.1766332,6.176447 0 0 0 -1.789334,-0.7471 z m -1.435182,3.0457 a 2.9544896,2.9544005 0 0 1 2.954489,2.9544 2.9544896,2.9544005 0 0 1 -2.954489,2.9544 2.9544896,2.9544005 0 0 1 -2.95449,-2.9544 2.9544896,2.9544005 0 0 1 2.95449,-2.9544 z" />
</g>
<g class="warning" transform="translate(0, 40)">
<path class="shield" d="M 2,15 Q -1,15 0.5,12 L 6.5,1.7 Q 8,-1 9.5,1.7 L 15.5,12 Q 17,15 14,15 z" />
<text class="mark" x="8" y="13">!</text>
</g>
</g>
</svg>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment