From 4acf1896bd9fa57d3dbe3f4721b6790c6f3b0d56 Mon Sep 17 00:00:00 2001 From: Jens Mönig Date: Sat, 21 Mar 2015 11:12:43 +0100 Subject: Prototypal inheritance of sprite-local variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (experimental) slotwise inheritance à la Henry Lieberman for sprite-local variables. see http://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/Delegation.htm l Let a sprite inherit another sprite’s local variables by making it the “parent” in the sprite-icon’s context menu (the button icon in the sprite corral underneath the stage). The child not only inherits the variable slot but also - dynamically - the parent variable’s value. Changing the parent’s variable value also changes it for every child. If a child uses SET or CHANGE on an inherited variable it automatically “shadows” it with its own value, thereby stopping dynamic participation in the parent slot’s value (in effect dis-inheriting that slot). Deleting a shadowed variable slot once again reinstates its inheritance status. inherited variables are shown as “ghosted” both in the child’s variables palette and in such stage watchers. “Shadowing” them un-ghosts both the variable blob template in the palette and the watcher onstage (if any). Deleting a shadowed variable once again ghosts the watcher and the palette block template. Delete a (shadowed) variable either via the “Delete a variable” button in the IDE or using the new “Delete” block in the variables category --- history.txt | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'history.txt') diff --git a/history.txt b/history.txt index b53e59c..e02d368 100755 --- a/history.txt +++ b/history.txt @@ -2476,3 +2476,7 @@ ______ ------ * Store: fixed #743 * GUI, html: switch from beta to release candidate + +150321 +------ +* OOP: Prototypal inheritance of sprite-local variables -- cgit v1.3.1 From af9b3dec293c45ac4b109f4ef3c21ba2f5bc55c3 Mon Sep 17 00:00:00 2001 From: Jens Mönig Date: Mon, 23 Mar 2015 12:44:46 +0100 Subject: OOP: Tweaks for scope conflicts when adding / removing vars --- blocks.js | 29 +++++++++++++++++++++++++++-- history.txt | 4 ++++ objects.js | 38 ++++++++++++++++++++++---------------- threads.js | 9 ++++++--- 4 files changed, 59 insertions(+), 21 deletions(-) (limited to 'history.txt') diff --git a/blocks.js b/blocks.js index 711976f..45f1049 100644 --- a/blocks.js +++ b/blocks.js @@ -155,7 +155,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph, Costume*/ // Global stuff //////////////////////////////////////////////////////// -modules.blocks = '2015-March-21'; +modules.blocks = '2015-March-23'; var SyntaxElementMorph; @@ -1191,6 +1191,15 @@ SyntaxElementMorph.prototype.labelPart = function (spec) { ); part.isStatic = true; break; + case '%shd': + part = new InputSlotMorph( + null, + false, + 'shadowedVariablesMenu', + true + ); + part.isStatic = true; + break; case '%lst': part = new InputSlotMorph( null, @@ -1889,7 +1898,8 @@ SyntaxElementMorph.prototype.endLayout = function () { %att - chameleon colored rectangular drop-down for attributes %fun - chameleon colored rectangular drop-down for math functions %typ - chameleon colored rectangular drop-down for data types - %var - chameleon colored rectangular drop-down for variable names + %var - chameleon colored rectangular drop-down for variable names + %shd - Chameleon colored rectuangular drop-down for shadowed var names %lst - chameleon colored rectangular drop-down for list names %b - chameleon colored hexagonal slot (for predicates) %l - list icon @@ -6902,6 +6912,21 @@ InputSlotMorph.prototype.getVarNamesDict = function () { return {}; }; +InputSlotMorph.prototype.shadowedVariablesMenu = function () { + var block = this.parentThatIsA(BlockMorph), + rcvr, + dict = {}; + + if (!block) {return dict; } + rcvr = block.receiver(); + if (rcvr) { + rcvr.inheritedVariableNames(true).forEach(function (name) { + dict[name] = name; + }); + } + return dict; +}; + InputSlotMorph.prototype.setChoices = function (dict, readonly) { // externally specify choices and read-only status, // used for custom blocks diff --git a/history.txt b/history.txt index e02d368..fc54386 100755 --- a/history.txt +++ b/history.txt @@ -2480,3 +2480,7 @@ ______ 150321 ------ * OOP: Prototypal inheritance of sprite-local variables + +150321 +------ +* OOP: Objects, Blocks, Threads - tweaks diff --git a/objects.js b/objects.js index 56e5806..2ea8427 100644 --- a/objects.js +++ b/objects.js @@ -125,7 +125,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2015-March-21'; +modules.objects = '2015-March-23'; var SpriteMorph; var StageMorph; @@ -1107,7 +1107,7 @@ SpriteMorph.prototype.initBlocks = function () { doDeleteAttr: { type: 'command', category: 'variables', - spec: 'delete %var' + spec: 'delete %shd' }, // Lists @@ -1720,12 +1720,14 @@ SpriteMorph.prototype.blockTemplates = function (category) { function addVar(pair) { var ide; if (pair) { - if (myself.isVariableNameInUse(pair[0])) { + if (myself.isVariableNameInUse(pair[0], pair[1])) { myself.inform('that name is already in use'); } else { ide = myself.parentThatIsA(IDE_Morph); myself.addVariable(pair[0], pair[1]); - myself.toggleVariableWatcher(pair[0], pair[1]); + if (!myself.showingVariableWatcher(pair[0])) { + myself.toggleVariableWatcher(pair[0], pair[1]); + } ide.flushBlocksCache('variables'); // b/c of inheritance ide.refreshPalette(); } @@ -4203,7 +4205,10 @@ SpriteMorph.prototype.allSpecimens = function () { // SpriteMorph inheritance - variables -SpriteMorph.prototype.isVariableNameInUse = function (vName) { +SpriteMorph.prototype.isVariableNameInUse = function (vName, isGlobal) { + if (isGlobal) { + return contains(this.variables.allNames(), vName); + } if (contains(this.variables.names(), vName)) {return true; } return contains(this.globalVariables().names(), vName); }; @@ -4243,8 +4248,14 @@ SpriteMorph.prototype.inheritedVariableNames = function (shadowedOnly) { }; SpriteMorph.prototype.deletableVariableNames = function () { - return this.variables.names().concat( - this.globalVariables().names() + var locals = this.variables.names(), + inherited = this.inheritedVariableNames(); + return locals.concat( + this.globalVariables().names().filter( + function (each) { + return !contains(locals, each) && !contains(inherited, each); + } + ) ); }; @@ -5406,16 +5417,7 @@ StageMorph.prototype.blockTemplates = function (category) { blocks.push(block('doShowVar')); blocks.push(block('doHideVar')); blocks.push(block('doDeclareVariables')); - - // inheritance: - - blocks.push('-'); - blocks.push(block('doDeleteAttr')); - - /////////////////////////////// - blocks.push('='); - blocks.push(block('reportNewList')); blocks.push('-'); blocks.push(block('reportCONS')); @@ -5813,6 +5815,10 @@ StageMorph.prototype.isVariableNameInUse StageMorph.prototype.globalVariables = SpriteMorph.prototype.globalVariables; +StageMorph.prototype.inheritedVariableNames = function () { + return []; +}; + // SpriteBubbleMorph //////////////////////////////////////////////////////// /* diff --git a/threads.js b/threads.js index d3dcfc9..82f7ab0 100644 --- a/threads.js +++ b/threads.js @@ -83,7 +83,7 @@ ArgLabelMorph, localize, XML_Element, hex_sha512*/ // Global stuff //////////////////////////////////////////////////////// -modules.threads = '2015-March-21'; +modules.threads = '2015-March-23'; var ThreadManager; var Process; @@ -1299,14 +1299,17 @@ Process.prototype.doRemoveTemporaries = function () { Process.prototype.doDeleteAttr = function (attrName) { // currently only variables are deletable - var name = attrName; + var name = attrName, + rcvr = this.blockReceiver(); if (name instanceof Context) { if (name.expression.selector === 'reportGetVar') { name = name.expression.blockSpec; } } - this.blockReceiver().deleteVariable(name); + if (contains(rcvr.inheritedVariableNames(true), name)) { + rcvr.deleteVariable(name); + } }; // Process lists primitives -- cgit v1.3.1 From 457224dd620eea4f20f24ebc62391363333cd00f Mon Sep 17 00:00:00 2001 From: Jens Mönig Date: Tue, 24 Mar 2015 17:16:00 +0100 Subject: tweak inherited variable watcher slider deserialization --- history.txt | 6 +++++- morphic.js | 14 +++++++------- objects.js | 24 +++++++++++++----------- store.js | 6 +++--- 4 files changed, 28 insertions(+), 22 deletions(-) (limited to 'history.txt') diff --git a/history.txt b/history.txt index fc54386..fda02a3 100755 --- a/history.txt +++ b/history.txt @@ -2481,6 +2481,10 @@ ______ ------ * OOP: Prototypal inheritance of sprite-local variables -150321 +150323 ------ * OOP: Objects, Blocks, Threads - tweaks + +150323 +------ +* OOP: Morphic, Objects, Store - tweak inherited variable watcher slider deserialization diff --git a/morphic.js b/morphic.js index 359e552..c725209 100644 --- a/morphic.js +++ b/morphic.js @@ -1048,7 +1048,7 @@ /*global window, HTMLCanvasElement, getMinimumFontHeight, FileReader, Audio, FileList, getBlurredShadowSupport*/ -var morphicVersion = '2015-March-21'; +var morphicVersion = '2015-March-24'; var modules = {}; // keep track of additional loaded modules var useBlurredShadows = getBlurredShadowSupport(); // check for Chrome-bug @@ -5933,7 +5933,7 @@ SliderMorph.prototype.userSetStart = function (num) { this.start = Math.max(num, this.stop); }; -SliderMorph.prototype.setStart = function (num) { +SliderMorph.prototype.setStart = function (num, noUpdate) { // for context menu demo purposes var newStart; if (typeof num === 'number') { @@ -5951,12 +5951,12 @@ SliderMorph.prototype.setStart = function (num) { } } this.value = Math.max(this.value, this.start); - this.updateTarget(); + if (!noUpdate) {this.updateTarget(); } this.drawNew(); this.changed(); }; -SliderMorph.prototype.setStop = function (num) { +SliderMorph.prototype.setStop = function (num, noUpdate) { // for context menu demo purposes var newStop; if (typeof num === 'number') { @@ -5968,12 +5968,12 @@ SliderMorph.prototype.setStop = function (num) { } } this.value = Math.min(this.value, this.stop); - this.updateTarget(); + if (!noUpdate) {this.updateTarget(); } this.drawNew(); this.changed(); }; -SliderMorph.prototype.setSize = function (num) { +SliderMorph.prototype.setSize = function (num, noUpdate) { // for context menu demo purposes var newSize; if (typeof num === 'number') { @@ -5991,7 +5991,7 @@ SliderMorph.prototype.setSize = function (num) { } } this.value = Math.min(this.value, this.stop - this.size); - this.updateTarget(); + if (!noUpdate) {this.updateTarget(); } this.drawNew(); this.changed(); }; diff --git a/objects.js b/objects.js index 4ade0fa..66726a1 100644 --- a/objects.js +++ b/objects.js @@ -125,7 +125,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2015-March-23'; +modules.objects = '2015-March-24'; var SpriteMorph; var StageMorph; @@ -4224,8 +4224,10 @@ SpriteMorph.prototype.globalVariables = function () { SpriteMorph.prototype.shadowVar = function (name, value) { var ide = this.parentThatIsA(IDE_Morph); this.variables.addVar(name, value); - ide.flushBlocksCache('variables'); - ide.refreshPalette(); + if (ide) { + ide.flushBlocksCache('variables'); + ide.refreshPalette(); + } }; SpriteMorph.prototype.inheritedVariableNames = function (shadowedOnly) { @@ -7032,19 +7034,19 @@ WatcherMorph.prototype.isGlobal = function (selector) { // WatcherMorph slider accessing: -WatcherMorph.prototype.setSliderMin = function (num) { +WatcherMorph.prototype.setSliderMin = function (num, noUpdate) { if (this.target instanceof VariableFrame) { - this.sliderMorph.setSize(1); - this.sliderMorph.setStart(num); - this.sliderMorph.setSize(this.sliderMorph.rangeSize() / 5); + this.sliderMorph.setSize(1, noUpdate); + this.sliderMorph.setStart(num, noUpdate); + this.sliderMorph.setSize(this.sliderMorph.rangeSize() / 5, noUpdate); } }; -WatcherMorph.prototype.setSliderMax = function (num) { +WatcherMorph.prototype.setSliderMax = function (num, noUpdate) { if (this.target instanceof VariableFrame) { - this.sliderMorph.setSize(1); - this.sliderMorph.setStop(num); - this.sliderMorph.setSize(this.sliderMorph.rangeSize() / 5); + this.sliderMorph.setSize(1, noUpdate); + this.sliderMorph.setStop(num, noUpdate); + this.sliderMorph.setSize(this.sliderMorph.rangeSize() / 5, noUpdate); } }; diff --git a/store.js b/store.js index b2bb0a3..138dc24 100644 --- a/store.js +++ b/store.js @@ -61,7 +61,7 @@ SyntaxElementMorph, Variable*/ // Global stuff //////////////////////////////////////////////////////// -modules.store = '2015-March-21'; +modules.store = '2015-March-24'; // XML_Serializer /////////////////////////////////////////////////////// @@ -540,8 +540,8 @@ SnapSerializer.prototype.rawLoadProjectModel = function (xmlNode) { } watcher.setStyle(model.attributes.style || 'normal'); if (watcher.style === 'slider') { - watcher.setSliderMin(model.attributes.min || '1'); - watcher.setSliderMax(model.attributes.max || '100'); + watcher.setSliderMin(model.attributes.min || '1', true); + watcher.setSliderMax(model.attributes.max || '100', true); } watcher.setPosition( project.stage.topLeft().add(new Point( -- cgit v1.3.1