fixed PianoMenu to work with block zoom etc.

upd4.1
Jens Mönig 2017-07-31 17:51:29 +02:00
rodzic 3338b0f017
commit 566c29fd66
3 zmienionych plików z 153 dodań i 131 usunięć

276
blocks.js
Wyświetl plik

@ -139,7 +139,7 @@
/*global Array, BoxMorph, /*global Array, BoxMorph,
Color, ColorPaletteMorph, FrameMorph, Function, HandleMorph, Math, MenuMorph, Color, ColorPaletteMorph, FrameMorph, Function, HandleMorph, Math, MenuMorph,
Morph, MorphicPreferences, Object, Point, ScrollFrameMorph, ShadowMorph, Morph, MorphicPreferences, Object, Point, ScrollFrameMorph, ShadowMorph,
String, StringMorph, TextMorph, WorldMorph, contains, degrees, detect, String, StringMorph, TextMorph, contains, degrees, detect, MenuItemMorph,
document, getDocumentPositionOf, isNaN, isString, newCanvas, nop, parseFloat, document, getDocumentPositionOf, isNaN, isString, newCanvas, nop, parseFloat,
radians, useBlurredShadows, SpeechBubbleMorph, modules, StageMorph, Sound, radians, useBlurredShadows, SpeechBubbleMorph, modules, StageMorph, Sound,
fontHeight, TableFrameMorph, SpriteMorph, Context, ListWatcherMorph, fontHeight, TableFrameMorph, SpriteMorph, Context, ListWatcherMorph,
@ -150,7 +150,7 @@ CustomCommandBlockMorph*/
// Global stuff //////////////////////////////////////////////////////// // Global stuff ////////////////////////////////////////////////////////
modules.blocks = '2017-July-27'; modules.blocks = '2017-July-31';
var SyntaxElementMorph; var SyntaxElementMorph;
var BlockMorph; var BlockMorph;
@ -178,9 +178,24 @@ var CommentMorph;
var ArgLabelMorph; var ArgLabelMorph;
var TextSlotMorph; var TextSlotMorph;
var ScriptFocusMorph; var ScriptFocusMorph;
var NoteInputMorph;
var PianoMenuMorph; var PianoMenuMorph;
var KeyItemMorph; var PianoKeyMorph;
/*
WorldMorph.prototype.customMorphs = function () {
// add examples to the world's demo menu
return [
new SymbolMorph(
'notes',
50,
new Color(250, 250, 250),
new Point(-1, -1),
new Color(20, 20, 20)
)
];
};
*/
// SyntaxElementMorph ////////////////////////////////////////////////// // SyntaxElementMorph //////////////////////////////////////////////////
@ -948,7 +963,12 @@ SyntaxElementMorph.prototype.labelPart = function (spec) {
part.setContents(90); part.setContents(90);
break; break;
case '%note': case '%note':
part = new NoteInputMorph(); part = new InputSlotMorph(
null, // test
true, // numeric
'pianoKeyboardMenu',
false // read-only
);
break; break;
case '%inst': case '%inst':
part = new InputSlotMorph( part = new InputSlotMorph(
@ -3205,7 +3225,11 @@ BlockMorph.prototype.refactorThisVar = function (justTheTemplate) {
function renameVarTo (newName) { function renameVarTo (newName) {
if (this.parent instanceof SyntaxElementMorph) { if (this.parent instanceof SyntaxElementMorph) {
if (this.parentThatIsA(BlockEditorMorph)) { if (this.parentThatIsA(BlockEditorMorph)) {
this.doRefactorBlockParameter(oldName, newName, justTheTemplate); this.doRefactorBlockParameter(
oldName,
newName,
justTheTemplate
);
} else if (this.parentThatIsA(RingMorph)) { } else if (this.parentThatIsA(RingMorph)) {
this.doRefactorRingParameter(oldName, newName, justTheTemplate); this.doRefactorRingParameter(oldName, newName, justTheTemplate);
} else { } else {
@ -3227,7 +3251,11 @@ BlockMorph.prototype.varExistsError = function (ide, where) {
); );
}; };
BlockMorph.prototype.doRefactorBlockParameter = function (oldName, newName, justTheTemplate) { BlockMorph.prototype.doRefactorBlockParameter = function (
oldName,
newName,
justTheTemplate
) {
var fragMorph = this.parentThatIsA(BlockInputFragmentMorph), var fragMorph = this.parentThatIsA(BlockInputFragmentMorph),
fragment = fragMorph.fragment.copy(), fragment = fragMorph.fragment.copy(),
definer = fragMorph.parent, definer = fragMorph.parent,
@ -3253,7 +3281,11 @@ BlockMorph.prototype.doRefactorBlockParameter = function (oldName, newName, just
}); });
}; };
BlockMorph.prototype.doRefactorRingParameter = function (oldName, newName, justTheTemplate) { BlockMorph.prototype.doRefactorRingParameter = function (
oldName,
newName,
justTheTemplate
) {
var ring = this.parentThatIsA(RingMorph), var ring = this.parentThatIsA(RingMorph),
script = ring.contents(), script = ring.contents(),
tb = this.topBlock(); tb = this.topBlock();
@ -3278,13 +3310,17 @@ BlockMorph.prototype.doRefactorRingParameter = function (oldName, newName, justT
tb.fullChanged(); tb.fullChanged();
}; };
BlockMorph.prototype.doRefactorScriptVar = function (oldName, newName, justTheTemplate) { BlockMorph.prototype.doRefactorScriptVar = function (
oldName,
newName,
justTheTemplate
) {
var definer = this.parentThatIsA(CommandBlockMorph), var definer = this.parentThatIsA(CommandBlockMorph),
receiver, ide; receiver, ide;
if (definer.definesScriptVariable(newName)) { if (definer.definesScriptVariable(newName)) {
receiver = this.scriptTarget(); receiver = this.scriptTarget();
ide = receiver.parentThatIsA(IDE_Morph), ide = receiver.parentThatIsA(IDE_Morph);
this.varExistsError(ide); this.varExistsError(ide);
return; return;
} }
@ -3298,7 +3334,11 @@ BlockMorph.prototype.doRefactorScriptVar = function (oldName, newName, justTheTe
definer.refactorVarInStack(oldName, newName, true); definer.refactorVarInStack(oldName, newName, true);
}; };
BlockMorph.prototype.doRefactorSpriteVar = function (oldName, newName, justTheTemplate) { BlockMorph.prototype.doRefactorSpriteVar = function (
oldName,
newName,
justTheTemplate
) {
var receiver = this.scriptTarget(), var receiver = this.scriptTarget(),
ide = receiver.parentThatIsA(IDE_Morph), ide = receiver.parentThatIsA(IDE_Morph),
oldWatcher = receiver.findVariableWatcher(oldName), oldWatcher = receiver.findVariableWatcher(oldName),
@ -3343,7 +3383,11 @@ BlockMorph.prototype.doRefactorSpriteVar = function (oldName, newName, justTheTe
ide.refreshPalette(); ide.refreshPalette();
}; };
BlockMorph.prototype.doRefactorGlobalVar = function (oldName, newName, justTheTemplate) { BlockMorph.prototype.doRefactorGlobalVar = function (
oldName,
newName,
justTheTemplate
) {
var receiver = this.scriptTarget(), var receiver = this.scriptTarget(),
ide = receiver.parentThatIsA(IDE_Morph), ide = receiver.parentThatIsA(IDE_Morph),
stage = ide ? ide.stage : null, stage = ide ? ide.stage : null,
@ -8022,6 +8066,9 @@ InputSlotMorph.prototype.userSetContents = function (aStringOrFloat) {
InputSlotMorph.prototype.dropDownMenu = function (enableKeyboard) { InputSlotMorph.prototype.dropDownMenu = function (enableKeyboard) {
var menu = this.menuFromDict(this.choices); var menu = this.menuFromDict(this.choices);
if (!menu) { // has already happened
return;
}
if (menu.items.length > 0) { if (menu.items.length > 0) {
if (enableKeyboard) { if (enableKeyboard) {
menu.popup(this.world(), this.bottomLeft()); menu.popup(this.world(), this.bottomLeft());
@ -8045,6 +8092,9 @@ InputSlotMorph.prototype.menuFromDict = function (choices, noEmptyOption) {
choices = choices.call(this); choices = choices.call(this);
} else if (isString(choices)) { } else if (isString(choices)) {
choices = this[choices](); choices = this[choices]();
if (!choices) { // menu has already happened
return;
}
} }
if (!noEmptyOption) { if (!noEmptyOption) {
menu.addItem(' ', null); menu.addItem(' ', null);
@ -8360,23 +8410,6 @@ InputSlotMorph.prototype.soundsMenu = function () {
return dict; return dict;
}; };
InputSlotMorph.prototype.setChoices = function (dict, readonly) {
// externally specify choices and read-only status,
// used for custom blocks
var cnts = this.contents();
this.choices = dict;
this.isReadOnly = readonly || false;
if (this.parent instanceof BlockMorph) {
this.parent.fixLabelColor();
if (!readonly) {
cnts.shadowOffset = new Point();
cnts.shadowColor = null;
cnts.setColor(new Color(0, 0, 0));
}
}
this.fixLayout();
};
InputSlotMorph.prototype.shadowedVariablesMenu = function () { InputSlotMorph.prototype.shadowedVariablesMenu = function () {
var block = this.parentThatIsA(BlockMorph), var block = this.parentThatIsA(BlockMorph),
vars, vars,
@ -8404,6 +8437,70 @@ InputSlotMorph.prototype.shadowedVariablesMenu = function () {
return dict; return dict;
}; };
InputSlotMorph.prototype.pianoKeyboardMenu = function () {
var choices, key, menu;
choices = {
'C (48)' : 48,
'D (50)' : 50,
'C# (49)' : 49,
'E (52)' : 52,
'Eb (51)' : 51,
'F (53)' : 53,
'G (55)' : 55,
'F# (54)' : 54,
'A (57)' : 57,
'G# (56)' : 56,
'B (59)' : 59,
'Bb (58)' : 58,
'C (60)' : 60,
'D (62)' : 62,
'C# (61)' : 61,
'E (64)' : 64,
'Eb (63)' : 63,
'F (65)' : 65,
'G (67)' : 67,
'F# (66)' : 66,
'A (69)' : 69,
'G# (68)' : 68,
'B (71)' : 71,
'Bb (70)' : 70,
'C (72)' : 72
};
menu = new PianoMenuMorph(
this.setContents,
null,
this,
this.fontSize
);
for (key in choices) {
if (Object.prototype.hasOwnProperty.call(choices, key)) {
menu.addItem(key, choices[key]);
}
}
menu.drawNew();
menu.popup(this.world(), new Point(
this.right() - (menu.width() / 2),
this.bottom()
));
};
InputSlotMorph.prototype.setChoices = function (dict, readonly) {
// externally specify choices and read-only status,
// used for custom blocks
var cnts = this.contents();
this.choices = dict;
this.isReadOnly = readonly || false;
if (this.parent instanceof BlockMorph) {
this.parent.fixLabelColor();
if (!readonly) {
cnts.shadowOffset = new Point();
cnts.shadowColor = null;
cnts.setColor(new Color(0, 0, 0));
}
}
this.fixLayout();
};
// InputSlotMorph layout: // InputSlotMorph layout:
InputSlotMorph.prototype.fixLayout = function () { InputSlotMorph.prototype.fixLayout = function () {
@ -9754,28 +9851,28 @@ PianoMenuMorph.prototype.drawNew = function () {
this.borderColor = new Color(60, 60, 60); this.borderColor = new Color(60, 60, 60);
this.silentSetExtent(new Point(0, 0)); this.silentSetExtent(new Point(0, 0));
x = this.left() + 4; x = this.left() + 1;
y = this.top() + 5; y = this.top() + (this.fontSize * 1.5) + 2;
label = new StringMorph(''); label = new StringMorph('', this.fontSize);
this.items.forEach(function (tuple) { this.items.forEach(function (tuple) {
blackkey = tuple[0][1] !== " "; blackkey = tuple[0][1] !== " ";
key = new BoxMorph(1, 2); key = new BoxMorph(1, 2);
if (blackkey) { if (blackkey) {
keycolor = new Color(0, 0, 0); keycolor = new Color(0, 0, 0);
keywidth = 9; keywidth = myself.fontSize; // 9;
keyheight = 25; keyheight = myself.fontSize * 2.5;
keyposition = new Point(x - 17, y); keyposition = new Point(x + 2 - (myself.fontSize * 2), y);
} else { } else {
keycolor = new Color(255, 255, 255); keycolor = new Color(255, 255, 255);
keywidth = 15; keywidth = myself.fontSize * 1.5;
keyheight = 40; keyheight = myself.fontSize * 4;
keyposition = new Point(x + 1, y); keyposition = new Point(x + 1, y);
x = x + keywidth - 1; x += keywidth - 1;
} }
key.setColor(keycolor); key.setColor(keycolor);
key.setWidth(keywidth); key.setWidth(keywidth);
key.setHeight(keyheight); key.setHeight(keyheight);
item = new KeyItemMorph( item = new PianoKeyMorph(
myself.target, myself.target,
tuple[1], tuple[1],
[key, tuple[0]], [key, tuple[0]],
@ -9792,100 +9889,21 @@ PianoMenuMorph.prototype.drawNew = function () {
item.setPosition(keyposition); item.setPosition(keyposition);
myself.add(item); myself.add(item);
}); });
label.setPosition(new Point(90, 2)); fb = this.fullBounds();
label.setPosition(new Point((fb.width() / 2) - this.fontSize, 2));
this.add(label); this.add(label);
fb = this.fullBounds(); fb = this.fullBounds();
this.silentSetExtent(fb.extent().add(4)); this.silentSetExtent(fb.extent().add(2));
this.adjustWidths();
MenuMorph.uber.drawNew.call(this); MenuMorph.uber.drawNew.call(this);
}; };
PianoMenuMorph.prototype.popUpAtHand = function (world) { // PianoKeyMorph ///////////////////////////////////////////////////////
var wrrld = world || this.world;
this.drawNew();
this.popup(wrrld,
wrrld.hand.position().subtract(new Point(this.extent().x / 2, 0)));
};
PianoKeyMorph.prototype = new MenuItemMorph();
PianoKeyMorph.prototype.constructor = PianoKeyMorph;
PianoKeyMorph.uber = MenuItemMorph.prototype;
// NoteInputMorph ////////////////////////////////////////////////////// function PianoKeyMorph(
/*
I am an inputslotmorph designed for selecting midi notes.
My block spec is
%note - midi notes
evaluate returns the integer value of the displayed midi note.
*/
// NoteInputMorph inherits from InputSlotMorph
NoteInputMorph.prototype = new InputSlotMorph();
NoteInputMorph.prototype.constructor = NoteInputMorph;
NoteInputMorph.uber = InputSlotMorph.prototype;
// NoteInputMorph instance creation:
function NoteInputMorph() {
this.init();
}
NoteInputMorph.prototype.init = function () {
NoteInputMorph.uber.init.call(this);
this.choices = {
'C (48)' : 48,
'D (50)' : 50,
'C# (49)' : 49,
'E (52)' : 52,
'Eb (51)' : 51,
'F (53)' : 53,
'G (55)' : 55,
'F# (54)' : 54,
'A (57)' : 57,
'G# (56)' : 56,
'B (59)' : 59,
'Bb (58)' : 58,
'C (60)' : 60,
'D (62)' : 62,
'C# (61)' : 61,
'E (64)' : 64,
'Eb (63)' : 63,
'F (65)' : 65,
'G (67)' : 67,
'F# (66)' : 66,
'A (69)' : 69,
'G# (68)' : 68,
'B (71)' : 71,
'Bb (70)' : 70,
'C (72)' : 72
};
this.isNumeric = true;
};
NoteInputMorph.prototype.dropDownMenu = function () {
var choices = this.choices,
key,
menu = new PianoMenuMorph(
this.setContents,
null,
this,
this.fontSize
);
for (key in choices) {
if (Object.prototype.hasOwnProperty.call(choices, key)) {
menu.addItem(key, choices[key]);
}
}
menu.popUpAtHand(this.world());
};
// KeyItemMorph ///////////////////////////////////////////////////////
KeyItemMorph.prototype = new MenuItemMorph();
KeyItemMorph.prototype.constructor = KeyItemMorph;
KeyItemMorph.uber = MenuItemMorph.prototype;
function KeyItemMorph(
target, target,
action, action,
labelString, // can also be a Morph or a Canvas or a tuple: [icon, string] labelString, // can also be a Morph or a Canvas or a tuple: [icon, string]
@ -9916,7 +9934,7 @@ function KeyItemMorph(
this.feedback = label; this.feedback = label;
} }
KeyItemMorph.prototype.createLabel = function () { PianoKeyMorph.prototype.createLabel = function () {
var icon; var icon;
if (this.label !== null) { if (this.label !== null) {
this.label.destroy(); this.label.destroy();
@ -9933,7 +9951,7 @@ KeyItemMorph.prototype.createLabel = function () {
this.add(this.label); this.add(this.label);
}; };
KeyItemMorph.prototype.mouseEnter = function () { PianoKeyMorph.prototype.mouseEnter = function () {
this.feedback.text = this.labelString[1]; this.feedback.text = this.labelString[1];
this.feedback.changed(); this.feedback.changed();
this.feedback.drawNew(); this.feedback.drawNew();
@ -9947,8 +9965,6 @@ KeyItemMorph.prototype.mouseEnter = function () {
// } // }
}; };
// TextSlotMorph ////////////////////////////////////////////////////// // TextSlotMorph //////////////////////////////////////////////////////
/* /*

Wyświetl plik

@ -3559,6 +3559,10 @@ Fixes:
* Blocks, Objects, Threads: fold two "stop" commands into one * Blocks, Objects, Threads: fold two "stop" commands into one
* Objects: Allow two-item lists as arguments for "point towards" and "go to" primitives * Objects: Allow two-item lists as arguments for "point towards" and "go to" primitives
170731
------
* fixed PianoMenu to work with block zoom etc.
Features: Features:
* polymorphic sprite-local custom blocks * polymorphic sprite-local custom blocks
@ -3581,6 +3585,7 @@ Features:
* programmatically hide and show primitives in the palette * programmatically hide and show primitives in the palette
* new "pen trails" reporter primitive and stage context menu entry * new "pen trails" reporter primitive and stage context menu entry
* two-item lists as x-y coordinate arguments for "point towards" and "go to" primitives * two-item lists as x-y coordinate arguments for "point towards" and "go to" primitives
* Piano keyboard as drop-down menu for entering musical notes, Thanks, Michael!
Fixes: Fixes:
* changed keyboard shortcut indicator for “find blocks” to “^” * changed keyboard shortcut indicator for “find blocks” to “^”
@ -3589,4 +3594,5 @@ Fixes:
* optimized thread-launch and script highlighting to a single frame instead of formerly two * optimized thread-launch and script highlighting to a single frame instead of formerly two
* changed direction attribute of sprites to automatically confine to 0-360 degrees * changed direction attribute of sprites to automatically confine to 0-360 degrees
* fixed rotation-bug when flipping costumes in "only turn left/right" mode" * fixed rotation-bug when flipping costumes in "only turn left/right" mode"
* fixed variable renaming (“refactoring”) bugs, thanks, Bernat!
* fixed some typos * fixed some typos

Wyświetl plik

@ -82,7 +82,7 @@ SpeechBubbleMorph, RingMorph, isNil, FileReader, TableDialogMorph,
BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize, BlockEditorMorph, BlockDialogMorph, PrototypeHatBlockMorph, localize,
TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph*/ TableMorph, TableFrameMorph, normalizeCanvas, BooleanSlotMorph, HandleMorph*/
modules.objects = '2017-July-27'; modules.objects = '2017-July-31';
var SpriteMorph; var SpriteMorph;
var StageMorph; var StageMorph;