summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjmoenig <jens@moenig.org>2013-04-25 16:52:59 +0200
committerjmoenig <jens@moenig.org>2013-04-25 16:52:59 +0200
commit4580aa1e0d58b4f7f5aa27f5360416d6cc4697d8 (patch)
treeefddff05674e7c4454c38eab2869d2c9c3bd8d76
parentd0878399fe0a85a05642a223dd4796badd212c5c (diff)
downloadsnap-4580aa1e0d58b4f7f5aa27f5360416d6cc4697d8.tar.gz
snap-4580aa1e0d58b4f7f5aa27f5360416d6cc4697d8.zip
Hide Primitives feature
Primitive blocks in the palette can now be hidden in the project via their context menu. Each palette's context menu further lets you hide or show all its primitives depending on whether any primitives are left to hide or show. Hidden primitives are stored in the project data. This lets instructors create "simplified" examples and problem sets.
-rw-r--r--blocks.js26
-rw-r--r--gui.js3
-rwxr-xr-xhistory.txt4
-rw-r--r--objects.js109
-rw-r--r--store.js18
5 files changed, 156 insertions, 4 deletions
diff --git a/blocks.js b/blocks.js
index 449bd14..2f1c5fc 100644
--- a/blocks.js
+++ b/blocks.js
@@ -153,7 +153,7 @@ DialogBoxMorph, BlockInputFragmentMorph, PrototypeHatBlockMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.blocks = '2013-April-23';
+modules.blocks = '2013-April-25';
var SyntaxElementMorph;
var BlockMorph;
@@ -1784,6 +1784,12 @@ BlockMorph.prototype.userMenu = function () {
'showHelp'
);
if (this.isTemplate) {
+ if (this.selector !== 'evaluateCustomBlock') {
+ menu.addItem(
+ "hide",
+ 'hidePrimitive'
+ );
+ }
return menu;
}
menu.addLine();
@@ -1883,6 +1889,24 @@ BlockMorph.prototype.developersMenu = function () {
return menu;
};
+BlockMorph.prototype.hidePrimitive = function () {
+ // passing a selector is optional
+ var ide = this.parentThatIsA(IDE_Morph),
+ cat;
+ if (!ide) {return; }
+ StageMorph.prototype.hiddenPrimitives[this.selector] = true;
+ cat = {
+ doWarp: 'control',
+ reifyScript: 'operators',
+ reifyReporter: 'operators',
+ reifyPredicate: 'operators',
+ doDeclareVariables: 'variables'
+ }[this.selector] || this.category;
+ if (cat === 'lists') {cat = 'variables'; }
+ ide.flushBlocksCache(cat);
+ ide.refreshPalette();
+};
+
BlockMorph.prototype.deleteBlock = function () {
// delete just this one block, keep inputs and next block around
var scripts = this.parentThatIsA(ScriptsMorph),
diff --git a/gui.js b/gui.js
index 8ac5234..27a33d9 100644
--- a/gui.js
+++ b/gui.js
@@ -68,7 +68,7 @@ sb, CommentMorph, CommandBlockMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.gui = '2013-April-24';
+modules.gui = '2013-April-25';
// Declarations
@@ -2244,6 +2244,7 @@ IDE_Morph.prototype.newProject = function () {
this.globalVariables = new VariableFrame();
this.currentSprite = new SpriteMorph(this.globalVariables);
this.sprites = new List([this.currentSprite]);
+ StageMorph.prototype.hiddenPrimitives = {};
this.setProjectName('');
this.projectNotes = '';
this.createStage();
diff --git a/history.txt b/history.txt
index 8b7aa5f..b631df5 100755
--- a/history.txt
+++ b/history.txt
@@ -1663,3 +1663,7 @@ ______
130424
------
* Widgets, BYOB, GUI: prevent multiple block editors on the same block definition, allow multiple dialogs on different objects, handle dialog instances in DialogBoxMorph.prototype
+
+130425
+------
+* Objects, Blocks, GUI, Store: Hide primitives feature
diff --git a/objects.js b/objects.js
index f0a8697..03068a2 100644
--- a/objects.js
+++ b/objects.js
@@ -120,7 +120,7 @@ PrototypeHatBlockMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.objects = '2013-April-23';
+modules.objects = '2013-April-25';
var SpriteMorph;
var StageMorph;
@@ -1363,6 +1363,9 @@ SpriteMorph.prototype.blockTemplates = function (category) {
cat = category || 'motion', txt;
function block(selector) {
+ if (StageMorph.prototype.hiddenPrimitives[selector]) {
+ return null;
+ }
var newBlock = SpriteMorph.prototype.blockForSelector(selector, true);
newBlock.isTemplate = true;
return newBlock;
@@ -1376,6 +1379,9 @@ SpriteMorph.prototype.blockTemplates = function (category) {
}
function watcherToggle(selector) {
+ if (StageMorph.prototype.hiddenPrimitives[selector]) {
+ return null;
+ }
var info = SpriteMorph.prototype.blocks[selector];
return new ToggleMorph(
'checkbox',
@@ -1804,6 +1810,7 @@ SpriteMorph.prototype.freshPalette = function (category) {
y = 5,
ry = 0,
blocks,
+ hideNextSpace = false,
myself = this,
stage = this.parentThatIsA(StageMorph),
oldFlag = Morph.prototype.trackChanges;
@@ -1814,6 +1821,90 @@ SpriteMorph.prototype.freshPalette = function (category) {
palette.padding = unit / 2;
palette.color = this.paletteColor;
+ // menu:
+
+ palette.userMenu = function () {
+ var menu = new MenuMorph(),
+ ide = this.parentThatIsA(IDE_Morph),
+ more = {
+ operators:
+ ['reifyScript', 'reifyReporter', 'reifyPredicate'],
+ control:
+ ['doWarp'],
+ variables:
+ [
+ 'doDeclareVariables',
+ 'reportNewList',
+ 'reportCONS',
+ 'reportListItem',
+ 'reportCDR',
+ 'reportListLength',
+ 'reportListContainsItem',
+ 'doAddToList',
+ 'doDeleteFromList',
+ 'doInsertInList',
+ 'doReplaceInList'
+ ]
+ };
+
+ function hasHiddenPrimitives() {
+ var defs = SpriteMorph.prototype.blocks,
+ hiddens = StageMorph.prototype.hiddenPrimitives;
+ return Object.keys(hiddens).some(function (any) {
+ return defs[any].category === category ||
+ contains((more[category] || []), any);
+ });
+ }
+
+ function canHidePrimitives() {
+ return palette.contents.children.some(function (any) {
+ return contains(
+ Object.keys(SpriteMorph.prototype.blocks),
+ any.selector
+ );
+ });
+ }
+
+ if (canHidePrimitives()) {
+ menu.addItem(
+ 'hide primitives',
+ function () {
+ var defs = SpriteMorph.prototype.blocks;
+ Object.keys(defs).forEach(function (sel) {
+ if (defs[sel].category === category) {
+ StageMorph.prototype.hiddenPrimitives[sel] = true;
+ }
+ });
+ (more[category] || []).forEach(function (sel) {
+ StageMorph.prototype.hiddenPrimitives[sel] = true;
+ });
+ ide.flushBlocksCache(category);
+ ide.refreshPalette();
+ }
+ );
+ }
+ if (hasHiddenPrimitives()) {
+ menu.addItem(
+ 'show primitives',
+ function () {
+ var hiddens = StageMorph.prototype.hiddenPrimitives,
+ defs = SpriteMorph.prototype.blocks;
+ Object.keys(hiddens).forEach(function (sel) {
+ if (defs[sel].category === category) {
+ delete StageMorph.prototype.hiddenPrimitives[sel];
+ }
+ });
+ (more[category] || []).forEach(function (sel) {
+ delete StageMorph.prototype.hiddenPrimitives[sel];
+ });
+ ide.flushBlocksCache(category);
+ ide.refreshPalette();
+ }
+ );
+ }
+ return menu;
+ };
+
// primitives:
blocks = this.blocksCache[category];
@@ -1825,14 +1916,22 @@ SpriteMorph.prototype.freshPalette = function (category) {
}
blocks.forEach(function (block) {
+ if (block === null) {
+ return;
+ }
if (block === '-') {
+ if (hideNextSpace) {return; }
y += unit * 0.8;
+ hideNextSpace = true;
} else if (block === '=') {
+ if (hideNextSpace) {return; }
y += unit * 1.6;
+ hideNextSpace = true;
} else if (block === '#') {
x = 0;
y = ry;
} else {
+ hideNextSpace = false;
if (x === 0) {
y += unit * 0.3;
}
@@ -3063,6 +3162,8 @@ StageMorph.prototype.isCachingPrimitives
StageMorph.prototype.sliderColor
= SpriteMorph.prototype.sliderColor;
+StageMorph.prototype.hiddenPrimitives = {};
+
// StageMorph instance creation
function StageMorph(globals) {
@@ -3545,6 +3646,9 @@ StageMorph.prototype.blockTemplates = function (category) {
cat = category || 'motion', txt;
function block(selector) {
+ if (myself.hiddenPrimitives[selector]) {
+ return null;
+ }
var newBlock = SpriteMorph.prototype.blockForSelector(selector, true);
newBlock.isTemplate = true;
return newBlock;
@@ -3558,6 +3662,9 @@ StageMorph.prototype.blockTemplates = function (category) {
}
function watcherToggle(selector) {
+ if (myself.hiddenPrimitives[selector]) {
+ return null;
+ }
var info = SpriteMorph.prototype.blocks[selector];
return new ToggleMorph(
'checkbox',
diff --git a/store.js b/store.js
index c0cd7b6..061b1be 100644
--- a/store.js
+++ b/store.js
@@ -61,7 +61,7 @@ SyntaxElementMorph*/
// Global stuff ////////////////////////////////////////////////////////
-modules.store = '2013-April-19';
+modules.store = '2013-April-25';
// XML_Serializer ///////////////////////////////////////////////////////
@@ -368,6 +368,17 @@ SnapSerializer.prototype.loadProjectModel = function (xmlNode) {
project.stage.isThreadSafe =
model.stage.attributes.threadsafe === 'true';
+ model.hiddenPrimitives = model.project.childNamed('hidden');
+ if (model.hiddenPrimitives) {
+ model.hiddenPrimitives.contents.split(' ').forEach(
+ function (sel) {
+ if (sel) {
+ StageMorph.prototype.hiddenPrimitives[sel] = true;
+ }
+ }
+ );
+ }
+
model.globalBlocks = model.project.childNamed('blocks');
if (model.globalBlocks) {
this.loadCustomBlocks(project.stage, model.globalBlocks, true);
@@ -1246,6 +1257,7 @@ StageMorph.prototype.toXML = function (serializer) {
'<blocks>%</blocks>' +
'<scripts>%</scripts><sprites>%</sprites>' +
'</stage>' +
+ '<hidden>$</hidden>' +
'<blocks>%</blocks>' +
'<variables>%</variables>' +
'</project>',
@@ -1266,6 +1278,10 @@ StageMorph.prototype.toXML = function (serializer) {
serializer.store(this.customBlocks),
serializer.store(this.scripts),
serializer.store(this.children),
+ Object.keys(StageMorph.prototype.hiddenPrimitives).reduce(
+ function(a, b) {return a + ' ' + b; },
+ ''
+ ),
serializer.store(this.globalBlocks),
(ide && ide.globalVariables) ?
serializer.store(ide.globalVariables) : ''