Sometimes, when you look at a list/table monitor and right click it, there will be a blockify… option you can then press to generate a list reporter block with the contents of the list. However, if your list has a color or ring somewhere in it, the option wont appear at all. Looking through the code I can see this happens blockify… is only available when the list could be JSON (e.g. only text, numbers, objects, lists, and booleans) instead of also color and rings.
And actually, I just tried to code it in and I did it succesfully!
Might be advanced
My solution was to add a seperate canBeBlockified function to the List class that also allows colors and contexts, then I simply added those in the blockify function. Next, I updated the TableMorph and ListWatcherMorph to instead use this new function. Heres my code for that:
List.prototype.canBeBlockified = function (already = []) {
return this.itemsArray().every(value => !isNaN(+value) ||
isString(value) ||
value === true ||
value === false ||
value instanceof Color ||
value instanceof Context ||
(value instanceof List &&
!already.includes(value) &&
value.canBeBlockified(already.concat([value]))) // detect circularity
);
};
List.prototype.blockify = function (limit = 500, count = [0]) {
var block = SpriteMorph.prototype.blockForSelector('reportNewList'),
slots = block.inputs()[0],
len = this.length(),
itemBlock,
i, value;
block.isDraggable = true;
slots.removeInput();
// fill the slots with the data
for (i = 0; i < len && count[0] < limit; i += 1) {
value = this.at(i + 1);
if (value instanceof List) {
slots.replaceInput(
slots.addInput(),
value.blockify(limit, count)
);
} else if (typeof value === 'boolean') {
itemBlock = SpriteMorph.prototype.blockForSelector('reportBoolean');
itemBlock.inputs()[0].setContents(value);
itemBlock.isDraggable = true;
slots.replaceInput(
slots.addInput(),
itemBlock
);
} else if (value instanceof Color) {
itemBlock = SpriteMorph.prototype.blockForSelector('reportColor');
itemBlock.inputs()[0].setContents(value);
itemBlock.isDraggable = true;
slots.replaceInput(
slots.addInput(),
itemBlock
);
} else if (value instanceof Context) {
itemBlock = value.toBlock();
itemBlock.isDraggable = true;
slots.replaceInput(
slots.addInput(),
itemBlock
);
} else {
slots.addInput(value);
}
count[0] += 1;
}
slots.fixBlockColor(null, true);
return block;
};
ListWatcherMorph.prototype.userMenu = function () {
var world = this.world(),
ide = detect(world.children, m => m instanceof IDE_Morph);
if (!List.prototype.enableTables || ide.isAppMode) {
return this.escalateEvent('userMenu');
}
var menu = new MenuMorph(this);
menu.addItem('table view...', 'showTableView');
if (this.list.canBeBlockified()) {
menu.addItem(
'blockify',
() => {
this.list.blockify().pickUp(world);
world.hand.grabOrigin = {
origin: ide.palette,
position: ide.palette.center()
};
}
);
}
if (this.list.canBeJSON()) {
menu.addItem(
'export',
() => {
if (this.list.canBeCSV()) {
ide.saveFileAs(
this.list.asCSV(),
'text/csv;charset=utf-8', // RFC 4180
localize('data') // name
);
} else {
ide.saveFileAs(
this.list.asJSON(),
'text/json;charset=utf-8',
localize('data') // name
);
}
}
);
}
menu.addLine();
menu.addItem(
'open in dialog...',
() => new TableDialogMorph(this.list).popUp(this.world())
);
return menu;
};
TableMorph.prototype.userMenu = function () {
var menu = new MenuMorph(this),
world = this.world(),
ide = detect(world.children, m => m instanceof IDE_Morph);
if (ide.isAppMode) {return; }
if (this.parentThatIsA(TableDialogMorph)) {
if (this.colWidths.length) {
menu.addItem('reset columns', 'resetColumns');
menu.addLine();
}
if (this.table instanceof List && this.table.canBeJSON()) {
menu.addItem(
'blockify',
() => {
this.table.blockify().pickUp(world);
world.hand.grabOrigin = {
origin: ide.palette,
position: ide.palette.center()
};
}
);
menu.addItem(
'export',
() => {
if (this.table.canBeCSV()) {
ide.saveFileAs(
this.table.asCSV(),
'text/csv;charset=utf-8', // RFC 4180
localize('data') // name
);
} else {
ide.saveFileAs(
this.table.asJSON(true), // guessObjects
'text/json;charset=utf-8',
localize('data') // name
);
}
}
);
}
menu.addItem('open in another dialog...', 'openInDialog');
return menu;
}
if (this.colWidths.length) {
menu.addItem('reset columns', 'resetColumns');
}
menu.addItem('list view...', 'showListView');
if (this.table instanceof List) {
if (this.table.canBeBlockified()) {
menu.addItem(
'blockify',
() => {
this.table.blockify().pickUp(world);
world.hand.grabOrigin = {
origin: ide.palette,
position: ide.palette.center()
};
}
);
}
if (this.table.canBeJSON()) {
menu.addItem(
'export',
() => {
if (this.table.canBeCSV()) {
ide.saveFileAs(
this.table.asCSV(),
'text/csv;charset=utf-8', // RFC 4180
localize('data') // name
);
} else {
ide.saveFileAs(
this.table.asJSON(true), // guessObjects
'text/json;charset=utf-8',
localize('data') // name
);
}
}
);
}
}
menu.addLine();
menu.addItem('open in dialog...', 'openInDialog');
return menu;
};
Hope this gets added in Snap! 12!




