„read-only“ option for editable custom block input slots

also custom block input slots reverting to default now show their
default value (useful in combination with the new "read-only" option
pull/3/merge
jmoenig 2013-11-15 11:18:45 +01:00
rodzic cc0bf15c1a
commit 81654e7299
4 zmienionych plików z 83 dodań i 18 usunięć

Wyświetl plik

@ -155,7 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/
// Global stuff ////////////////////////////////////////////////////////
modules.blocks = '2013-November-12';
modules.blocks = '2013-November-15';
var SyntaxElementMorph;
var BlockMorph;
@ -518,10 +518,13 @@ SyntaxElementMorph.prototype.revertToDefaultInput = function (arg, noValues) {
if (this instanceof BlockMorph) {
deflt = this.labelPart(this.parseSpec(this.blockSpec)[idx]);
if (deflt instanceof InputSlotMorph && this.definition) {
deflt.choices = this.definition.dropDownMenuOfInputIdx(
this.inputs().indexOf(arg)
deflt.setChoices.apply(
deflt,
this.definition.inputOptionsOfIdx(inp)
);
deflt.setContents(
this.definition.defaultValueOfInputIdx(inp)
);
deflt.fixLayout();
}
} else if (this instanceof MultiArgMorph) {
deflt = this.labelPart(this.slotSpec);
@ -1912,8 +1915,10 @@ BlockMorph.prototype.setSpec = function (spec) {
myself.add(myself.placeHolder());
}
if (part instanceof InputSlotMorph && myself.definition) {
part.choices = myself.definition.dropDownMenuOfInputIdx(inputIdx);
part.fixLayout(); // needed when de-serializing
part.setChoices.apply(
part,
myself.definition.inputOptionsOfIdx(inputIdx)
);
}
});
this.blockSpec = spec;
@ -6593,6 +6598,23 @@ InputSlotMorph.prototype.getVarNamesDict = function () {
return {};
};
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.prototype.fixLayout = function () {

47
byob.js
Wyświetl plik

@ -106,7 +106,7 @@ SymbolMorph, isNil*/
// Global stuff ////////////////////////////////////////////////////////
modules.byob = '2013-November-12';
modules.byob = '2013-November-15';
// Declarations
@ -137,7 +137,8 @@ function CustomBlockDefinition(spec, receiver) {
this.isGlobal = false;
this.type = 'command';
this.spec = spec || '';
this.declarations = {}; // {'inputName' : [type, default, options]}
// format: {'inputName' : [type, default, options, readonly]}
this.declarations = {};
this.comment = null;
this.codeMapping = null; // experimental, generate text code
this.codeHeader = null; // experimental, generate text code
@ -193,6 +194,7 @@ CustomBlockDefinition.prototype.prototypeInstance = function () {
part.fragment.type = slot[0];
part.fragment.defaultValue = slot[1];
part.fragment.options = slot[2];
part.fragment.isReadonly = slot[3] || false;
}
}
});
@ -271,6 +273,16 @@ CustomBlockDefinition.prototype.dropDownMenuOfInputIdx = function (idx) {
return this.dropDownMenuOf(inputName);
};
CustomBlockDefinition.prototype.isReadOnlyInputIdx = function (idx) {
var inputName = this.inputNames()[idx];
return this.isReadOnlyInput(inputName);
};
CustomBlockDefinition.prototype.inputOptionsOfIdx = function (idx) {
var inputName = this.inputNames()[idx];
return this.inputOptionsOf(inputName);
};
CustomBlockDefinition.prototype.dropDownMenuOf = function (inputName) {
var dict = {};
if (this.declarations[inputName] && this.declarations[inputName][2]) {
@ -283,6 +295,18 @@ CustomBlockDefinition.prototype.dropDownMenuOf = function (inputName) {
return null;
};
CustomBlockDefinition.prototype.isReadOnlyInput = function (inputName) {
return this.declarations[inputName] &&
this.declarations[inputName][3] === true;
};
CustomBlockDefinition.prototype.inputOptionsOf = function (inputName) {
return [
this.dropDownMenuOf(inputName),
this.isReadOnlyInput(inputName)
];
};
CustomBlockDefinition.prototype.inputNames = function () {
var vNames = [],
parts = this.parseSpec(this.spec);
@ -355,8 +379,7 @@ CustomCommandBlockMorph.prototype.refresh = function () {
} else { // update all input slots' drop-downs
this.inputs().forEach(function (inp, i) {
if (inp instanceof InputSlotMorph) {
inp.choices = def.dropDownMenuOfInputIdx(i);
inp.fixLayout();
inp.setChoices.apply(inp, def.inputOptionsOfIdx(i));
}
});
}
@ -565,7 +588,8 @@ CustomCommandBlockMorph.prototype.declarationsFromFragments = function () {
ans[part.fragment.labelString] = [
part.fragment.type,
part.fragment.defaultValue,
part.fragment.options
part.fragment.options,
part.fragment.isReadOnly
];
}
});
@ -1888,6 +1912,7 @@ function BlockLabelFragment(labelString) {
this.type = '%s'; // null for label, a spec for an input
this.defaultValue = '';
this.options = '';
this.isReadOnly = false; // for input slots
this.isDeleted = false;
}
@ -1938,6 +1963,7 @@ BlockLabelFragment.prototype.copy = function () {
ans.type = this.type;
ans.defaultValue = this.defaultValue;
ans.options = this.options;
ans.isReadOnly = this.isReadOnly;
return ans;
};
@ -2832,8 +2858,17 @@ InputSlotDialogMorph.prototype.addSlotsMenu = function () {
this.slots.userMenu = function () {
if (contains(['%s', '%n', '%txt', '%anyUE'], myself.fragment.type)) {
var menu = new MenuMorph(myself);
var menu = new MenuMorph(myself),
on = '\u2611 ',
off = '\u2610 ';
menu.addItem('options...', 'editSlotOptions');
menu.addItem(
(myself.fragment.isReadOnly ? on : off) +
localize('read-only'),
function () {myself.fragment.isReadOnly =
!myself.fragment.isReadOnly;
}
);
return menu;
}
return Morph.prototype.userMenu.call(myself);

Wyświetl plik

@ -1993,3 +1993,8 @@ ______
* Objects: fixed wrong NaN display for variable watchers
* Blocks: left-align multi-line text in value-bubbles
* Portuguese translation update, thanks, Manuel!
131115
------
* Blocks, BYOB, Store: „read-only“ option for editable custom block input slots
* BYOB, Blocks: custom block input slots reverting to default now show their default value

Wyświetl plik

@ -61,7 +61,7 @@ SyntaxElementMorph*/
// Global stuff ////////////////////////////////////////////////////////
modules.store = '2013-November-12';
modules.store = '2013-November-15';
// XML_Serializer ///////////////////////////////////////////////////////
@ -749,7 +749,8 @@ SnapSerializer.prototype.loadCustomBlocks = function (
definition.declarations[names[i]] = [
child.attributes.type,
child.contents,
options ? options.contents : undefined
options ? options.contents : undefined,
child.attributes.readonly === 'true'
];
});
}
@ -1663,13 +1664,15 @@ CustomBlockDefinition.prototype.toXML = function (serializer) {
this.codeMapping || '',
Object.keys(this.declarations).reduce(function (xml, decl) {
return xml + serializer.format(
'<input type="@">$%</input>',
'<input type="@"$>$%</input>',
myself.declarations[decl][0],
myself.declarations[decl][3] ?
' readonly="true"' : '',
myself.declarations[decl][1],
myself.declarations[decl][2] ?
'<options>' + myself.declarations[decl][2] +
'</options>'
: ''
'<options>' + myself.declarations[decl][2] +
'</options>'
: ''
);
}, ''),
this.body ? serializer.store(this.body.expression) : '',