Customizable angle pickers.

This commit is contained in:
Neil Fraser 2016-02-09 22:36:15 -08:00
parent f56dd7930b
commit a481c1cff8
3 changed files with 70 additions and 26 deletions

View file

@ -591,6 +591,9 @@ Blockly.Connection.prototype.closest = function(maxLimit, dx, dy) {
* @private
*/
Blockly.Connection.prototype.checkType_ = function(otherConnection) {
if (Blockly.OPPOSITE_TYPE[this.type] != otherConnection.type) {
return false;
}
// Don't split a connection where both sides are immovable.
var thisTargetBlock = this.targetBlock();
if (thisTargetBlock && !thisTargetBlock.isMovable() &&

View file

@ -68,7 +68,7 @@ Blockly.FieldAngle.prototype.setChangeHandler = function(handler) {
v1 = value;
}
var v2 = Blockly.FieldAngle.angleValidator.call(this, v1);
if (v2 !== undefined) {
if (v2 === undefined) {
v2 = v1;
}
}
@ -91,6 +91,36 @@ Blockly.FieldAngle.ROUND = 15;
*/
Blockly.FieldAngle.HALF = 100 / 2;
/* The following two settings work together to set the behaviour of the angle
* picker. While many combinations are possible, two modes are typical:
* Math mode.
* 0 deg is right, 90 is up. This is the style used by protractors.
* Blockly.FieldAngle.CLOCKWISE = false;
* Blockly.FieldAngle.OFFSET = 0;
* Compass mode.
* 0 deg is up, 90 is right. This is the style used by maps.
* Blockly.FieldAngle.CLOCKWISE = true;
* Blockly.FieldAngle.OFFSET = 90;
*/
/**
* Angle increases clockwise (true) or counterclockwise (false).
*/
Blockly.FieldAngle.CLOCKWISE = false;
/**
* Offset the location of 0 degrees (and all angles) by a constant.
* Usually either 0 (0 = right) or 90 (0 = up).
*/
Blockly.FieldAngle.OFFSET = 0;
/**
* Maximum allowed angle before wrapping.
* Usually either 360 (for 0 to 359.9) or 180 (for -179.9 to 180).
*/
Blockly.FieldAngle.WRAP = 360;
/**
* Radius of protractor circle. Slightly smaller than protractor size since
* otherwise SVG crops off half the border at the edges.
@ -196,15 +226,16 @@ Blockly.FieldAngle.prototype.onMouseMove = function(e) {
} else if (dy > 0) {
angle += 360;
}
if (Blockly.FieldAngle.CLOCKWISE) {
angle = Blockly.FieldAngle.OFFSET + 360 - angle;
} else {
angle -= Blockly.FieldAngle.OFFSET;
}
if (Blockly.FieldAngle.ROUND) {
angle = Math.round(angle / Blockly.FieldAngle.ROUND) *
Blockly.FieldAngle.ROUND;
}
if (angle >= 360) {
// Rounding may have rounded up to 360.
angle -= 360;
}
angle = String(angle);
angle = Blockly.FieldAngle.angleValidator(angle);
Blockly.FieldTextInput.htmlInput_.value = angle;
this.setValue(angle);
this.validate_();
@ -239,26 +270,33 @@ Blockly.FieldAngle.prototype.updateGraph_ = function() {
if (!this.gauge_) {
return;
}
var angleRadians = goog.math.toRadians(Number(this.getText()));
if (isNaN(angleRadians)) {
this.gauge_.setAttribute('d',
'M ' + Blockly.FieldAngle.HALF + ',' + Blockly.FieldAngle.HALF);
this.line_.setAttribute('x2', Blockly.FieldAngle.HALF);
this.line_.setAttribute('y2', Blockly.FieldAngle.HALF);
} else {
var x = Blockly.FieldAngle.HALF + Math.cos(angleRadians) *
Blockly.FieldAngle.RADIUS;
var y = Blockly.FieldAngle.HALF + Math.sin(angleRadians) *
-Blockly.FieldAngle.RADIUS;
var largeFlag = (angleRadians > Math.PI) ? 1 : 0;
this.gauge_.setAttribute('d',
'M ' + Blockly.FieldAngle.HALF + ',' + Blockly.FieldAngle.HALF +
' h ' + Blockly.FieldAngle.RADIUS +
' A ' + Blockly.FieldAngle.RADIUS + ',' + Blockly.FieldAngle.RADIUS +
' 0 ' + largeFlag + ' 0 ' + x + ',' + y + ' z');
this.line_.setAttribute('x2', x);
this.line_.setAttribute('y2', y);
var angleDegrees = Number(this.getText()) + Blockly.FieldAngle.OFFSET;
var angleRadians = goog.math.toRadians(angleDegrees);
var path = ['M ', Blockly.FieldAngle.HALF, ',', Blockly.FieldAngle.HALF];
var x2 = Blockly.FieldAngle.HALF;
var y2 = Blockly.FieldAngle.HALF;
if (!isNaN(angleRadians)) {
var angle0 = goog.math.toRadians(Blockly.FieldAngle.OFFSET);
var x1 = Math.cos(angle0) * Blockly.FieldAngle.RADIUS;
var y1 = Math.sin(angle0) * -Blockly.FieldAngle.RADIUS;
if (Blockly.FieldAngle.CLOCKWISE) {
angleRadians = 2 * angle0 - angleRadians;
}
x2 += Math.cos(angleRadians) * Blockly.FieldAngle.RADIUS;
y2 -= Math.sin(angleRadians) * Blockly.FieldAngle.RADIUS;
// Don't ask how the flag calculations work. They just do.
var largeFlag = Math.abs(Math.floor((angleRadians - angle0) / Math.PI) % 2);
if (Blockly.FieldAngle.CLOCKWISE) {
largeFlag = 1 - largeFlag;
}
var sweepFlag = Number(Blockly.FieldAngle.CLOCKWISE);
path.push(' l ', x1, ',', y1,
' A ', Blockly.FieldAngle.RADIUS, ',', Blockly.FieldAngle.RADIUS,
' 0 ', largeFlag, ' ', sweepFlag, ' ', x2, ',', y2, ' z');
}
this.gauge_.setAttribute('d', path.join(''));
this.line_.setAttribute('x2', x2);
this.line_.setAttribute('y2', y2);
};
/**
@ -273,6 +311,9 @@ Blockly.FieldAngle.angleValidator = function(text) {
if (n < 0) {
n += 360;
}
if (n > Blockly.FieldAngle.WRAP) {
n -= 360;
}
n = String(n);
}
return n;

View file

@ -66,7 +66,7 @@ Blockly.FieldVariable.prototype.setChangeHandler = function(handler) {
v1 = value;
}
var v2 = Blockly.FieldVariable.dropdownChange.call(this, v1);
if (v2 !== undefined) {
if (v2 === undefined) {
v2 = v1;
}
}