kopia lustrzana https://github.com/backface/turtlestitch
new dial widget
* Blocks: added dial widget to POINT IN DIRECTION's drop-down menu * Objects: added "rotate" option to Sprite context menu * Threads, Blocks: fixed Joan's fix for #1972, because it broke HOFsupd4.2
rodzic
79c43e7bdc
commit
72cb4c02d4
31
blocks.js
31
blocks.js
|
@ -144,11 +144,11 @@ fontHeight, TableFrameMorph, SpriteMorph, Context, ListWatcherMorph,
|
||||||
CellMorph, DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph,
|
CellMorph, DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph,
|
||||||
Costume, IDE_Morph, BlockDialogMorph, BlockEditorMorph, localize, isNil,
|
Costume, IDE_Morph, BlockDialogMorph, BlockEditorMorph, localize, isNil,
|
||||||
isSnapObject, PushButtonMorph, SpriteIconMorph, Process, AlignmentMorph,
|
isSnapObject, PushButtonMorph, SpriteIconMorph, Process, AlignmentMorph,
|
||||||
CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph*/
|
CustomCommandBlockMorph, SymbolMorph, ToggleButtonMorph, DialMorph*/
|
||||||
|
|
||||||
// Global stuff ////////////////////////////////////////////////////////
|
// Global stuff ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
modules.blocks = '2018-January-22';
|
modules.blocks = '2018-January-25';
|
||||||
|
|
||||||
var SyntaxElementMorph;
|
var SyntaxElementMorph;
|
||||||
var BlockMorph;
|
var BlockMorph;
|
||||||
|
@ -934,6 +934,7 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
|
||||||
null,
|
null,
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
|
'§_dir': null,
|
||||||
'(90) right' : 90,
|
'(90) right' : 90,
|
||||||
'(-90) left' : -90,
|
'(-90) left' : -90,
|
||||||
'(0) up' : '0',
|
'(0) up' : '0',
|
||||||
|
@ -4067,6 +4068,9 @@ BlockMorph.prototype.situation = function () {
|
||||||
|
|
||||||
BlockMorph.prototype.prepareToBeGrabbed = function (hand) {
|
BlockMorph.prototype.prepareToBeGrabbed = function (hand) {
|
||||||
var myself = this;
|
var myself = this;
|
||||||
|
this.allInputs().forEach(function (input) {
|
||||||
|
delete input.bindingID;
|
||||||
|
});
|
||||||
this.allComments().forEach(function (comment) {
|
this.allComments().forEach(function (comment) {
|
||||||
comment.startFollowing(myself, hand.world);
|
comment.startFollowing(myself, hand.world);
|
||||||
});
|
});
|
||||||
|
@ -8257,7 +8261,8 @@ InputSlotMorph.prototype.menuFromDict = function (
|
||||||
noEmptyOption,
|
noEmptyOption,
|
||||||
enableKeyboard)
|
enableKeyboard)
|
||||||
{
|
{
|
||||||
var key,
|
var key, dial,
|
||||||
|
myself = this,
|
||||||
menu = new MenuMorph(
|
menu = new MenuMorph(
|
||||||
this.userSetContents,
|
this.userSetContents,
|
||||||
null,
|
null,
|
||||||
|
@ -8265,6 +8270,11 @@ InputSlotMorph.prototype.menuFromDict = function (
|
||||||
this.fontSize
|
this.fontSize
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function update (num) {
|
||||||
|
myself.setContents(num);
|
||||||
|
myself.reactToSliderEdit();
|
||||||
|
}
|
||||||
|
|
||||||
if (choices instanceof Function) {
|
if (choices instanceof Function) {
|
||||||
choices = choices.call(this);
|
choices = choices.call(this);
|
||||||
} else if (isString(choices)) {
|
} else if (isString(choices)) {
|
||||||
|
@ -8282,6 +8292,17 @@ InputSlotMorph.prototype.menuFromDict = function (
|
||||||
menu.addLine();
|
menu.addLine();
|
||||||
} else if (key.indexOf('§_def') === 0) {
|
} else if (key.indexOf('§_def') === 0) {
|
||||||
menu.addItem(choices[key], choices[key]);
|
menu.addItem(choices[key], choices[key]);
|
||||||
|
} else if (key.indexOf('§_dir') === 0) {
|
||||||
|
dial = new DialMorph();
|
||||||
|
dial.rootForGrab = function () {return this; };
|
||||||
|
dial.target = this;
|
||||||
|
dial.action = update;
|
||||||
|
dial.fillColor = this.parent.color;
|
||||||
|
dial.setRadius(this.fontSize * 3);
|
||||||
|
dial.setValue(this.evaluate(), false, true);
|
||||||
|
menu.addLine();
|
||||||
|
menu.items.push(dial);
|
||||||
|
menu.addLine();
|
||||||
} else if (choices[key] instanceof Object &&
|
} else if (choices[key] instanceof Object &&
|
||||||
!(choices[key] instanceof Array) &&
|
!(choices[key] instanceof Array) &&
|
||||||
(typeof choices[key] !== 'function')) {
|
(typeof choices[key] !== 'function')) {
|
||||||
|
@ -9199,10 +9220,6 @@ InputSlotMorph.prototype.drawRoundBorder = function (context) {
|
||||||
context.stroke();
|
context.stroke();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TemplateSlotMorph ///////////////////////////////////////////////////
|
// TemplateSlotMorph ///////////////////////////////////////////////////
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
8
gui.js
8
gui.js
|
@ -75,7 +75,7 @@ isRetinaSupported, SliderMorph, Animation*/
|
||||||
|
|
||||||
// Global stuff ////////////////////////////////////////////////////////
|
// Global stuff ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
modules.gui = '2018-January-23';
|
modules.gui = '2018-January-25';
|
||||||
|
|
||||||
// Declarations
|
// Declarations
|
||||||
|
|
||||||
|
@ -301,7 +301,8 @@ IDE_Morph.prototype.openIn = function (world) {
|
||||||
// prevent non-DialogBoxMorphs from being dropped
|
// prevent non-DialogBoxMorphs from being dropped
|
||||||
// onto the World in user-mode
|
// onto the World in user-mode
|
||||||
world.reactToDropOf = function (morph) {
|
world.reactToDropOf = function (morph) {
|
||||||
if (!(morph instanceof DialogBoxMorph)) {
|
if (!(morph instanceof DialogBoxMorph ||
|
||||||
|
(morph instanceof MenuMorph))) {
|
||||||
if (world.hand.grabOrigin) {
|
if (world.hand.grabOrigin) {
|
||||||
morph.slideBackTo(world.hand.grabOrigin);
|
morph.slideBackTo(world.hand.grabOrigin);
|
||||||
} else {
|
} else {
|
||||||
|
@ -4454,7 +4455,8 @@ IDE_Morph.prototype.switchToUserMode = function () {
|
||||||
// prevent non-DialogBoxMorphs from being dropped
|
// prevent non-DialogBoxMorphs from being dropped
|
||||||
// onto the World in user-mode
|
// onto the World in user-mode
|
||||||
world.reactToDropOf = function (morph) {
|
world.reactToDropOf = function (morph) {
|
||||||
if (!(morph instanceof DialogBoxMorph)) {
|
if (!(morph instanceof DialogBoxMorph ||
|
||||||
|
(morph instanceof MenuMorph))) {
|
||||||
if (world.hand.grabOrigin) {
|
if (world.hand.grabOrigin) {
|
||||||
morph.slideBackTo(world.hand.grabOrigin);
|
morph.slideBackTo(world.hand.grabOrigin);
|
||||||
} else {
|
} else {
|
||||||
|
|
10
history.txt
10
history.txt
|
@ -3868,6 +3868,14 @@ Fixes:
|
||||||
* fixed #1972, thanks, Joan!
|
* fixed #1972, thanks, Joan!
|
||||||
* Objects, GUI: When deleting a temporary clone, detach all its parts and delete the temporary ones
|
* Objects, GUI: When deleting a temporary clone, detach all its parts and delete the temporary ones
|
||||||
|
|
||||||
|
180125
|
||||||
|
------
|
||||||
|
* Morphic: new DialMorph widget
|
||||||
|
* Blocks: added dial widget to POINT IN DIRECTION's drop-down menu
|
||||||
|
* Objects: added "rotate" option to Sprite context menu
|
||||||
|
* Threads, Blocks: fixed Joan's fix for #1972, because it broke HOFs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
v4.1.1 New Features:
|
v4.1.1 New Features:
|
||||||
* translation support for custom blocks
|
* translation support for custom blocks
|
||||||
|
@ -3875,6 +3883,8 @@ v4.1.1 New Features:
|
||||||
* included local methods in the OF-block's left drop-down menu
|
* included local methods in the OF-block's left drop-down menu
|
||||||
* added "width" and "height" selectors to Pixels library
|
* added "width" and "height" selectors to Pixels library
|
||||||
* added scroll events, thanks, Bernat!
|
* added scroll events, thanks, Bernat!
|
||||||
|
* new dial widget POINT IN DIRECTION's drop-down menu
|
||||||
|
* new "rotate" option for sprite context menu
|
||||||
|
|
||||||
Notable Changes:
|
Notable Changes:
|
||||||
* global and local variables are now separat in the palette, each sorted alphabetically, local vars marked with location pin (only in palette)
|
* global and local variables are now separat in the palette, each sorted alphabetically, local vars marked with location pin (only in palette)
|
||||||
|
|
|
@ -185,7 +185,7 @@ SnapTranslator.dict.de = {
|
||||||
'translator_e-mail':
|
'translator_e-mail':
|
||||||
'jens@moenig.org', // optional
|
'jens@moenig.org', // optional
|
||||||
'last_changed':
|
'last_changed':
|
||||||
'2018-01-22', // this, too, will appear in the Translators tab
|
'2018-01-25', // this, too, will appear in the Translators tab
|
||||||
|
|
||||||
// GUI
|
// GUI
|
||||||
// control bar:
|
// control bar:
|
||||||
|
@ -969,6 +969,8 @@ SnapTranslator.dict.de = {
|
||||||
'Angelpunkt',
|
'Angelpunkt',
|
||||||
'edit the costume\'s\nrotation center':
|
'edit the costume\'s\nrotation center':
|
||||||
'Drehpunkt des Kostüms\nanzeigen und verschieben',
|
'Drehpunkt des Kostüms\nanzeigen und verschieben',
|
||||||
|
'rotate':
|
||||||
|
'Drehen',
|
||||||
'detach from':
|
'detach from':
|
||||||
'Abtrennen von',
|
'Abtrennen von',
|
||||||
'detach all parts':
|
'detach all parts':
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
/*global modules, contains*/
|
/*global modules, contains*/
|
||||||
|
|
||||||
modules.locale = '2018-January-22';
|
modules.locale = '2018-January-25';
|
||||||
|
|
||||||
// Global stuff
|
// Global stuff
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ SnapTranslator.dict.de = {
|
||||||
'translator_e-mail':
|
'translator_e-mail':
|
||||||
'jens@moenig.org',
|
'jens@moenig.org',
|
||||||
'last_changed':
|
'last_changed':
|
||||||
'2018-01-22'
|
'2018-01-25'
|
||||||
};
|
};
|
||||||
|
|
||||||
SnapTranslator.dict.it = {
|
SnapTranslator.dict.it = {
|
||||||
|
|
375
morphic.js
375
morphic.js
|
@ -85,6 +85,7 @@
|
||||||
ColorPaletteMorph
|
ColorPaletteMorph
|
||||||
GrayPaletteMorph
|
GrayPaletteMorph
|
||||||
ColorPickerMorph
|
ColorPickerMorph
|
||||||
|
DialMorph
|
||||||
FrameMorph
|
FrameMorph
|
||||||
ScrollFrameMorph
|
ScrollFrameMorph
|
||||||
ListMorph
|
ListMorph
|
||||||
|
@ -126,6 +127,7 @@
|
||||||
CursorMorph
|
CursorMorph
|
||||||
BoxMorph
|
BoxMorph
|
||||||
SpeechBubbleMorph
|
SpeechBubbleMorph
|
||||||
|
DialMorph
|
||||||
CircleBoxMorph
|
CircleBoxMorph
|
||||||
SliderButtonMorph
|
SliderButtonMorph
|
||||||
SliderMorph
|
SliderMorph
|
||||||
|
@ -1161,7 +1163,7 @@
|
||||||
|
|
||||||
/*global window, HTMLCanvasElement, FileReader, Audio, FileList*/
|
/*global window, HTMLCanvasElement, FileReader, Audio, FileList*/
|
||||||
|
|
||||||
var morphicVersion = '2018-January-22';
|
var morphicVersion = '2018-January-25';
|
||||||
var modules = {}; // keep track of additional loaded modules
|
var modules = {}; // keep track of additional loaded modules
|
||||||
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug
|
||||||
|
|
||||||
|
@ -4843,6 +4845,52 @@ PenMorph.prototype.setHeading = function (degrees) {
|
||||||
this.changed();
|
this.changed();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PenMorph.prototype.numericalSetters = function () {
|
||||||
|
// for context menu demo purposes
|
||||||
|
return [
|
||||||
|
'setLeft',
|
||||||
|
'setTop',
|
||||||
|
'setWidth',
|
||||||
|
'setHeight',
|
||||||
|
'setAlphaScaled',
|
||||||
|
'setHeading'
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
// PenMorph menu:
|
||||||
|
|
||||||
|
PenMorph.prototype.developersMenu = function () {
|
||||||
|
var menu = PenMorph.uber.developersMenu.call(this);
|
||||||
|
menu.addLine();
|
||||||
|
menu.addItem(
|
||||||
|
'set rotation',
|
||||||
|
"setRotation",
|
||||||
|
'interactively turn this morph\nusing a dial widget'
|
||||||
|
);
|
||||||
|
return menu;
|
||||||
|
};
|
||||||
|
|
||||||
|
PenMorph.prototype.setRotation = function () {
|
||||||
|
var menu, dial,
|
||||||
|
name = this.name || this.constructor.name;
|
||||||
|
if (name.length > 10) {
|
||||||
|
name = name.slice(0, 9) + '...';
|
||||||
|
}
|
||||||
|
menu = new MenuMorph(this, name);
|
||||||
|
dial = new DialMorph(null, null, this.heading);
|
||||||
|
dial.rootForGrab = function () {return this; };
|
||||||
|
dial.target = this;
|
||||||
|
dial.action = 'setHeading';
|
||||||
|
menu.items.push(dial);
|
||||||
|
menu.addLine();
|
||||||
|
menu.addItem('(90) right', function () {this.setHeading(90); });
|
||||||
|
menu.addItem('(-90) left', function () {this.setHeading(-90); });
|
||||||
|
menu.addItem('(0) up', function () {this.setHeading(0); });
|
||||||
|
menu.addItem('(180) down', function () {this.setHeading(180); });
|
||||||
|
menu.isDraggable = true;
|
||||||
|
menu.popUpAtHand(this.world());
|
||||||
|
};
|
||||||
|
|
||||||
// PenMorph drawing:
|
// PenMorph drawing:
|
||||||
|
|
||||||
PenMorph.prototype.drawLine = function (start, dest) {
|
PenMorph.prototype.drawLine = function (start, dest) {
|
||||||
|
@ -6245,6 +6293,315 @@ SpeechBubbleMorph.prototype.fixLayout = function () {
|
||||||
this.addShadow(new Point(2, 2), 80);
|
this.addShadow(new Point(2, 2), 80);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// DialMorph //////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// I am a knob than can be turned to select a number
|
||||||
|
|
||||||
|
var DialMorph;
|
||||||
|
|
||||||
|
// DialMorph inherits from Morph:
|
||||||
|
|
||||||
|
DialMorph.prototype = new Morph();
|
||||||
|
DialMorph.prototype.constructor = DialMorph;
|
||||||
|
DialMorph.uber = Morph.prototype;
|
||||||
|
|
||||||
|
function DialMorph(min, max, value, tick, radius) {
|
||||||
|
this.init(min, max, value, tick, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
DialMorph.prototype.init = function (min, max, value, tick, radius) {
|
||||||
|
this.target = null;
|
||||||
|
this.action = null;
|
||||||
|
this.min = min || 0;
|
||||||
|
this.max = max || 360;
|
||||||
|
this.value = Math.max(this.min, (value || 0) % this.max);
|
||||||
|
this.tick = tick || 15;
|
||||||
|
this.fillColor = null;
|
||||||
|
|
||||||
|
DialMorph.uber.init.call(this);
|
||||||
|
|
||||||
|
this.color = new Color(230, 230, 230);
|
||||||
|
this.noticesTransparentClick = true;
|
||||||
|
this.setRadius(radius || MorphicPreferences.menuFontSize * 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
DialMorph.prototype.setRadius = function (radius) {
|
||||||
|
this.radius = radius;
|
||||||
|
this.setExtent(new Point(this.radius * 2, this.radius * 2));
|
||||||
|
};
|
||||||
|
|
||||||
|
DialMorph.prototype.setValue = function (value, snapToTick, noUpdate) {
|
||||||
|
var range = this.max - this.min;
|
||||||
|
value = value || 0;
|
||||||
|
this.value = this.min + (((+value % range) + range) % range);
|
||||||
|
if (snapToTick) {
|
||||||
|
if (this.value < this.tick) {
|
||||||
|
this.value = this.min;
|
||||||
|
} else {
|
||||||
|
this.value -= this.value % this.tick % this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.drawNew();
|
||||||
|
this.changed();
|
||||||
|
if (noUpdate) {return; }
|
||||||
|
this.updateTarget();
|
||||||
|
};
|
||||||
|
|
||||||
|
DialMorph.prototype.getValueOf = function (point) {
|
||||||
|
var range = this.max - this.min,
|
||||||
|
center = this.center(),
|
||||||
|
deltaX = point.x - center.x,
|
||||||
|
deltaY = center.y - point.y,
|
||||||
|
angle = Math.abs(deltaX) < 0.001 ? (deltaY < 0 ? 90 : 270)
|
||||||
|
: Math.round(
|
||||||
|
(deltaX >= 0 ? 0 : 180)
|
||||||
|
- (Math.atan(deltaY / deltaX) * 57.2957795131)
|
||||||
|
),
|
||||||
|
value = angle + 90 % 360,
|
||||||
|
ratio = value / 360;
|
||||||
|
return range * ratio + this.min;
|
||||||
|
};
|
||||||
|
|
||||||
|
DialMorph.prototype.setExtent = function (aPoint) {
|
||||||
|
var size = Math.min(aPoint.x, aPoint.y);
|
||||||
|
this.radius = size / 2;
|
||||||
|
DialMorph.uber.setExtent.call(this, new Point(size, size));
|
||||||
|
};
|
||||||
|
|
||||||
|
DialMorph.prototype.drawNew = function () {
|
||||||
|
var ctx, i, angle, x1, y1, x2, y2,
|
||||||
|
light = this.color.lighter().toString(),
|
||||||
|
range = this.max - this.min,
|
||||||
|
ticks = range / this.tick,
|
||||||
|
face = this.radius * 0.75,
|
||||||
|
inner = face * 0.85,
|
||||||
|
outer = face * 0.95;
|
||||||
|
|
||||||
|
this.image = newCanvas(this.extent());
|
||||||
|
ctx = this.image.getContext('2d');
|
||||||
|
|
||||||
|
// draw a light border:
|
||||||
|
ctx.fillStyle = light;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(
|
||||||
|
this.radius,
|
||||||
|
this.radius,
|
||||||
|
face + Math.min(1, this.radius - face),
|
||||||
|
0,
|
||||||
|
2 * Math.PI,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// fill circle:
|
||||||
|
ctx.fillStyle = this.color.toString();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(
|
||||||
|
this.radius,
|
||||||
|
this.radius,
|
||||||
|
face,
|
||||||
|
0,
|
||||||
|
2 * Math.PI,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// fill value
|
||||||
|
angle = (this.value - this.min) * (Math.PI * 2) / range - Math.PI / 2;
|
||||||
|
ctx.fillStyle = (this.fillColor || this.color.darker()).toString();
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(
|
||||||
|
this.radius,
|
||||||
|
this.radius,
|
||||||
|
face,
|
||||||
|
Math.PI / -2,
|
||||||
|
angle,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
ctx.lineTo(this.radius, this.radius);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// draw ticks:
|
||||||
|
ctx.strokeStyle = new Color(35, 35, 35).toString();
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
for (i = 0; i < ticks; i += 1) {
|
||||||
|
angle = (i - 3) * (Math.PI * 2) / ticks - Math.PI / 2;
|
||||||
|
ctx.beginPath();
|
||||||
|
x1 = this.radius + Math.cos(angle) * inner;
|
||||||
|
y1 = this.radius + Math.sin(angle) * inner;
|
||||||
|
x2 = this.radius + Math.cos(angle) * outer;
|
||||||
|
y2 = this.radius + Math.sin(angle) * outer;
|
||||||
|
ctx.moveTo(x1, y1);
|
||||||
|
ctx.lineTo(x2, y2);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw a filled center:
|
||||||
|
inner = face * 0.05;
|
||||||
|
ctx.fillStyle = 'black';
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(
|
||||||
|
this.radius,
|
||||||
|
this.radius,
|
||||||
|
inner,
|
||||||
|
0,
|
||||||
|
2 * Math.PI,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
|
||||||
|
// draw the inner hand:
|
||||||
|
ctx.strokeStyle = 'black';
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
angle = (this.value - this.min) * (Math.PI * 2) / range - Math.PI / 2;
|
||||||
|
outer = face * 0.8;
|
||||||
|
x1 = this.radius + Math.cos(angle) * inner;
|
||||||
|
y1 = this.radius + Math.sin(angle) * inner;
|
||||||
|
x2 = this.radius + Math.cos(angle) * outer;
|
||||||
|
y2 = this.radius + Math.sin(angle) * outer;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(x1, y1);
|
||||||
|
ctx.lineTo(x2, y2);
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
// draw a read-out circle:
|
||||||
|
inner = inner * 2;
|
||||||
|
x2 = this.radius + Math.cos(angle) * (outer + inner);
|
||||||
|
y2 = this.radius + Math.sin(angle) * (outer + inner);
|
||||||
|
ctx.fillStyle = 'black';
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(
|
||||||
|
x2,
|
||||||
|
y2,
|
||||||
|
inner,
|
||||||
|
0,
|
||||||
|
2 * Math.PI,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
// draw the outer hand:
|
||||||
|
angle = (this.value - this.min) * (Math.PI * 2) / range - Math.PI / 2;
|
||||||
|
x1 = this.radius + Math.cos(angle) * face;
|
||||||
|
y1 = this.radius + Math.sin(angle) * face;
|
||||||
|
x2 = this.radius + Math.cos(angle) * (this.radius - 1);
|
||||||
|
y2 = this.radius + Math.sin(angle) * (this.radius - 1);
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(x1, y1);
|
||||||
|
ctx.lineTo(x2, y2);
|
||||||
|
ctx.lineWidth = 3;
|
||||||
|
ctx.strokeStyle = light;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.strokeStyle = 'black';
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
// draw arrow tip:
|
||||||
|
angle = radians(degrees(angle) - 4);
|
||||||
|
x1 = this.radius + Math.cos(angle) * this.radius * 0.9;
|
||||||
|
y1 = this.radius + Math.sin(angle) * this.radius * 0.9;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(x1, y1);
|
||||||
|
angle = radians(degrees(angle) + 8);
|
||||||
|
x1 = this.radius + Math.cos(angle) * this.radius * 0.9;
|
||||||
|
y1 = this.radius + Math.sin(angle) * this.radius * 0.9;
|
||||||
|
ctx.lineTo(x1, y1);
|
||||||
|
ctx.lineTo(x2, y2);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.lineWidth = 3;
|
||||||
|
ctx.strokeStyle = light;
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.strokeStyle = 'black';
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fill();
|
||||||
|
};
|
||||||
|
|
||||||
|
// DialMorph stepping:
|
||||||
|
|
||||||
|
DialMorph.prototype.step = null;
|
||||||
|
|
||||||
|
DialMorph.prototype.mouseDownLeft = function (pos) {
|
||||||
|
var world, myself = this;
|
||||||
|
world = this.root();
|
||||||
|
this.step = function () {
|
||||||
|
if (world.hand.mouseButton) {
|
||||||
|
myself.setValue(
|
||||||
|
myself.getValueOf(world.hand.bounds.origin),
|
||||||
|
world.currentKey !== 16 // snap to tick
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.step = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// DialMorph menu:
|
||||||
|
|
||||||
|
DialMorph.prototype.developersMenu = function () {
|
||||||
|
var menu = DialMorph.uber.developersMenu.call(this);
|
||||||
|
menu.addLine();
|
||||||
|
menu.addItem(
|
||||||
|
'set target',
|
||||||
|
"setTarget",
|
||||||
|
'select another morph\nwhose numerical property\nwill be ' +
|
||||||
|
'controlled by this one'
|
||||||
|
);
|
||||||
|
return menu;
|
||||||
|
};
|
||||||
|
|
||||||
|
DialMorph.prototype.setTarget = function () {
|
||||||
|
var choices = this.overlappedMorphs(),
|
||||||
|
menu = new MenuMorph(this, 'choose target:'),
|
||||||
|
myself = this;
|
||||||
|
|
||||||
|
choices.push(this.world());
|
||||||
|
choices.forEach(function (each) {
|
||||||
|
menu.addItem(each.toString().slice(0, 50), function () {
|
||||||
|
myself.target = each;
|
||||||
|
myself.setTargetSetter();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (choices.length === 1) {
|
||||||
|
this.target = choices[0];
|
||||||
|
this.setTargetSetter();
|
||||||
|
} else if (choices.length > 0) {
|
||||||
|
menu.popUpAtHand(this.world());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DialMorph.prototype.setTargetSetter = function () {
|
||||||
|
var choices = this.target.numericalSetters(),
|
||||||
|
menu = new MenuMorph(this, 'choose target property:'),
|
||||||
|
myself = this;
|
||||||
|
|
||||||
|
choices.forEach(function (each) {
|
||||||
|
menu.addItem(each, function () {
|
||||||
|
myself.action = each;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (choices.length === 1) {
|
||||||
|
this.action = choices[0];
|
||||||
|
} else if (choices.length > 0) {
|
||||||
|
menu.popUpAtHand(this.world());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DialMorph.prototype.updateTarget = function () {
|
||||||
|
if (this.action) {
|
||||||
|
if (typeof this.action === 'function') {
|
||||||
|
this.action.call(this.target, this.value);
|
||||||
|
} else { // assume it's a String
|
||||||
|
this.target[this.action](this.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// CircleBoxMorph //////////////////////////////////////////////////////
|
// CircleBoxMorph //////////////////////////////////////////////////////
|
||||||
|
|
||||||
// I can be used for sliders
|
// I can be used for sliders
|
||||||
|
@ -7672,7 +8029,8 @@ MenuMorph.prototype.drawNew = function () {
|
||||||
isLine = false;
|
isLine = false;
|
||||||
if (tuple instanceof StringFieldMorph ||
|
if (tuple instanceof StringFieldMorph ||
|
||||||
tuple instanceof ColorPickerMorph ||
|
tuple instanceof ColorPickerMorph ||
|
||||||
tuple instanceof SliderMorph) {
|
tuple instanceof SliderMorph ||
|
||||||
|
tuple instanceof DialMorph) {
|
||||||
item = tuple;
|
item = tuple;
|
||||||
} else if (tuple[0] === 0) {
|
} else if (tuple[0] === 0) {
|
||||||
isLine = true;
|
isLine = true;
|
||||||
|
@ -7729,7 +8087,8 @@ MenuMorph.prototype.maxWidth = function () {
|
||||||
);
|
);
|
||||||
} else if ((item instanceof StringFieldMorph) ||
|
} else if ((item instanceof StringFieldMorph) ||
|
||||||
(item instanceof ColorPickerMorph) ||
|
(item instanceof ColorPickerMorph) ||
|
||||||
(item instanceof SliderMorph)) {
|
(item instanceof SliderMorph) ||
|
||||||
|
(item instanceof DialMorph)) {
|
||||||
w = Math.max(w, item.width());
|
w = Math.max(w, item.width());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -7744,7 +8103,9 @@ MenuMorph.prototype.adjustWidths = function () {
|
||||||
isSelected,
|
isSelected,
|
||||||
myself = this;
|
myself = this;
|
||||||
this.children.forEach(function (item) {
|
this.children.forEach(function (item) {
|
||||||
|
if (!(item instanceof DialMorph)) {
|
||||||
item.silentSetWidth(w);
|
item.silentSetWidth(w);
|
||||||
|
}
|
||||||
if (item instanceof MenuItemMorph) {
|
if (item instanceof MenuItemMorph) {
|
||||||
item.fixLayout();
|
item.fixLayout();
|
||||||
isSelected = (item.image === item.pressImage);
|
isSelected = (item.image === item.pressImage);
|
||||||
|
@ -10745,7 +11106,9 @@ HandMorph.prototype.grab = function (aMorph) {
|
||||||
if (this.children.length === 0) {
|
if (this.children.length === 0) {
|
||||||
this.world.stopEditing();
|
this.world.stopEditing();
|
||||||
this.grabOrigin = aMorph.situation();
|
this.grabOrigin = aMorph.situation();
|
||||||
|
if (!(aMorph instanceof MenuMorph)) {
|
||||||
aMorph.addShadow();
|
aMorph.addShadow();
|
||||||
|
}
|
||||||
if (aMorph.prepareToBeGrabbed) {
|
if (aMorph.prepareToBeGrabbed) {
|
||||||
aMorph.prepareToBeGrabbed(this);
|
aMorph.prepareToBeGrabbed(this);
|
||||||
}
|
}
|
||||||
|
@ -10770,7 +11133,9 @@ HandMorph.prototype.drop = function () {
|
||||||
morphToDrop.cachedFullImage = null;
|
morphToDrop.cachedFullImage = null;
|
||||||
morphToDrop.cachedFullBounds = null;
|
morphToDrop.cachedFullBounds = null;
|
||||||
morphToDrop.changed();
|
morphToDrop.changed();
|
||||||
|
if (!(morphToDrop instanceof MenuMorph)) {
|
||||||
morphToDrop.removeShadow();
|
morphToDrop.removeShadow();
|
||||||
|
}
|
||||||
this.children = [];
|
this.children = [];
|
||||||
this.setExtent(new Point());
|
this.setExtent(new Point());
|
||||||
if (morphToDrop.justDropped) {
|
if (morphToDrop.justDropped) {
|
||||||
|
@ -11895,6 +12260,10 @@ WorldMorph.prototype.userCreateMorph = function () {
|
||||||
menu.addItem('slider', function () {
|
menu.addItem('slider', function () {
|
||||||
create(new SliderMorph());
|
create(new SliderMorph());
|
||||||
});
|
});
|
||||||
|
menu.addItem('dial', function () {
|
||||||
|
newMorph = new DialMorph();
|
||||||
|
newMorph.pickUp(this);
|
||||||
|
});
|
||||||
menu.addItem('frame', function () {
|
menu.addItem('frame', function () {
|
||||||
newMorph = new FrameMorph();
|
newMorph = new FrameMorph();
|
||||||
newMorph.setExtent(new Point(350, 250));
|
newMorph.setExtent(new Point(350, 250));
|
||||||
|
|
|
@ -83,7 +83,7 @@ BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
|
||||||
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph,
|
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph,
|
||||||
AlignmentMorph*/
|
AlignmentMorph*/
|
||||||
|
|
||||||
modules.objects = '2018-January-23';
|
modules.objects = '2018-January-25';
|
||||||
|
|
||||||
var SpriteMorph;
|
var SpriteMorph;
|
||||||
var StageMorph;
|
var StageMorph;
|
||||||
|
@ -3227,6 +3227,7 @@ SpriteMorph.prototype.userMenu = function () {
|
||||||
}
|
}
|
||||||
menu.addItem("delete", 'remove');
|
menu.addItem("delete", 'remove');
|
||||||
menu.addItem("move", 'moveCenter');
|
menu.addItem("move", 'moveCenter');
|
||||||
|
menu.addItem("rotate", 'setRotation');
|
||||||
if (this.costume) {
|
if (this.costume) {
|
||||||
menu.addItem(
|
menu.addItem(
|
||||||
"pivot",
|
"pivot",
|
||||||
|
|
|
@ -61,7 +61,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy,
|
||||||
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph,
|
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph,
|
||||||
TableFrameMorph, ColorSlotMorph, isSnapObject*/
|
TableFrameMorph, ColorSlotMorph, isSnapObject*/
|
||||||
|
|
||||||
modules.threads = '2018-January-23';
|
modules.threads = '2018-January-25';
|
||||||
|
|
||||||
var ThreadManager;
|
var ThreadManager;
|
||||||
var Process;
|
var Process;
|
||||||
|
@ -855,7 +855,6 @@ Process.prototype.evaluateInput = function (input) {
|
||||||
} else {
|
} else {
|
||||||
ans = this.context.variables.getVar(input.bindingID);
|
ans = this.context.variables.getVar(input.bindingID);
|
||||||
}
|
}
|
||||||
delete input.bindingID;
|
|
||||||
} else {
|
} else {
|
||||||
ans = input.evaluate();
|
ans = input.evaluate();
|
||||||
if (ans) {
|
if (ans) {
|
||||||
|
|
Ładowanie…
Reference in New Issue