summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blocks.js34
-rw-r--r--byob.js47
-rwxr-xr-xhistory.txt5
-rw-r--r--store.js15
4 files changed, 83 insertions, 18 deletions
diff --git a/blocks.js b/blocks.js
index b2b38c4..8f675c4 100644
--- a/blocks.js
+++ b/blocks.js
@@ -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 () {
diff --git a/byob.js b/byob.js
index d282b07..3455171 100644
--- a/byob.js
+++ b/byob.js
@@ -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);
diff --git a/history.txt b/history.txt
index c82f6ff..3f63d3d 100755
--- a/history.txt
+++ b/history.txt
@@ -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
diff --git a/store.js b/store.js
index 0032919..5a5605f 100644
--- a/store.js
+++ b/store.js
@@ -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) : '',