Ken Webb 2011-01-27T14:13:25Z
The Bestiary sample web app currently uses PulpCore graphics. Using the scripts on this page, the Bestiary web app can also use the HTML5 Canvas.
The first script is a HTML5 Canvas server. It's written in JavaScript and runs in a web browser such as Firefox. Copy the script from this wiki page, and paste it into the console in the Bestiary app. Then press the submit button.
<script implName="lang:BrowserJS:inline:"><![CDATA[
var drawScene_Function = "\
<script type='text/javascript'>\
/*\
* drawScene(context, dataFromClient)\
* id: 10=Cat 11=Human 3=Dog 4=Zombie 5=Termite\
* example of data: id,x,y\
* 1,13,20|\
* 1,16,31|\
* 2,17,15|\
* 3,17,16|\
* 1,17,21\
*/\
function drawScene(ctx, theData) {\
ctx.fillStyle = 'green';\
ctx.fillRect(0, 0, 499, 499);\
var rowItems = theData.split('|');\
for (i in rowItems) {\
var colItems = rowItems[i].split(',');\
if (colItems.length != 3) {continue;}\
var id = colItems[0];\
var x = colItems[1] * 5;\
var y = colItems[2] * 5;\
/* customized for Bestiary */\
switch (id) {\
case '11': ctx.fillStyle = 'tan'; break;\
case '10': ctx.fillStyle = 'lightgrey'; break;\
case '3': ctx.fillStyle = 'white'; break;\
case '4': ctx.fillStyle = 'pink'; break;\
case '5': ctx.fillStyle = 'yellow'; break;\
default: ctx.fillStyle = 'magenta'; break;\
}\
ctx.fillRect(x, y, 5, 5);\
}\
};\
</script>";
$('div#divHeadOne').html(drawScene_Function);
$('div#divOne').html("<canvas id='graphicsServerCanvas' width='500' height='500'></canvas>");
]]></script>
The second script is a client of the HTML5 Canvas server. It's written in the BeanShell variant of Java, which allows it to be dynamically added to a running app. Copy the script from this wiki page, and paste it into the console in the Bestiary app. Then press the submit button.
<AlternativeGui implName="org.primordion.xholon.base.XholonNull">
<HTML5Canvas implName="org.primordion.script.Behavior_beanshell"><![CDATA[
import org.primordion.xholon.app.Application;
import org.primordion.xholon.base.AbstractGrid;
import org.primordion.xholon.base.IGrid;
import org.primordion.xholon.base.IXholon;
import org.primordion.xholon.base.IXholonClass;
import org.primordion.xholon.service.IScriptService;
import org.primordion.xholon.service.IXholonService;
behavior() {
/** The current context node. */
//private IXholon context = null;
/** The xholon that owns the Row and GridCell xholons. */
private IXholon gridOwner = null;
/** The Xholon application. */
private Application app = null;
/** The xholon at upper left corner of the grid. */
private AbstractGrid upperLeft = null;
/** Default size of a grid cell, in pixels. */
private int cellSize = 5;
private int nRows = 0;
private int nCols = 0;
/** A service that knows how to evaluate BrowserJS and other scripts. */
private IScriptService scriptService = null;
public void postConfigure()
{
app = applicationKey;
scriptService = (IScriptService)app.getService(IXholonService.XHSRV_SCRIPT);
nRows = 100; //Stage.getHeight() / cellSize;
nCols = 100; //Stage.getWidth() / cellSize;
gridOwner = app.getRoot().getFirstChild().getNextSibling();
setUpperLeft();
writeGuiToCanvas();
}
public void act() {
writeGuiToCanvas();
}
protected void writeGuiToCanvas() {
String data = drawGrid();
String scriptContent = createBrowserScript(data);
scriptService.evalScript(contextNodeKey, "BrowserJS", scriptContent);
}
/**
* Draw the grid to a String.
* @return
*/
protected String drawGrid() {
StringBuffer sb = new StringBuffer();
AbstractGrid currentCell = upperLeft;
AbstractGrid startOfRow = upperLeft;
for (int i = 0; i < nRows; i++) {
//System.out.println("row:" + i);
for (int j = 0; j < nCols; j++) {
if (currentCell.hasChildNodes()) {
sb.append(currentCell.getLastChild().getXhcId()).append(",").append(j).append(",").append(i).append("|");
}
currentCell = (AbstractGrid)currentCell.port[1];
}
startOfRow = (AbstractGrid)startOfRow.port[2];
currentCell = startOfRow;
}
return sb.toString();
}
/**
* Create a BrowserJS script.
* @param data
* @return
*/
protected String createBrowserScript(String data) {
StringBuffer sb = new StringBuffer()
.append("var myData = '").append(data).append("';")
.append("var myCanvas = document.getElementById('graphicsServerCanvas');")
.append("var ctx = myCanvas.getContext('2d');")
.append("drawScene(ctx, myData);");
return sb.toString();
}
/**
* Set the xholon at the upper left corner of the grid.
*/
protected void setUpperLeft() {
AbstractGrid row = (AbstractGrid)gridOwner.getFirstChild();
AbstractGrid col = null;
while (row != null) {
if (row.getXhcName().equals("Row")
|| row.getXhType() == IXholonClass.XhtypeGridEntity
|| row.getRoleName().equals("row")) { // first child of type "Row"
col = (AbstractGrid)row.getFirstChild();
while (col != null) {
if (col.getXhcName().equals("GridCell")
|| col.getXhType() == IXholonClass.XhtypeGridEntityActivePassive
|| col.getRoleName().equals("gridcell")) { // first child of type "GridCell"
upperLeft = col; // found it
return;
}
col = (AbstractGrid)col.getNextSibling();
}
return;
}
row = (AbstractGrid)row.getNextSibling();
}
}
return this;
}
behaviorObject = behavior();
]]></HTML5Canvas>
</AlternativeGui>
With both GUIs running at the same time, the app is quite slow. It's a bit faster if you pause the PuplCore graphics. Click the mouse inside the PulpCore GUI (this is the original GUI on the page). Then press the P key on your keyboard, to toggle the PulpCore graphics off and on.
Internet Explorer
If you are using Internet Explorer (tested with IE 7 and 8), then the first script above cannot have any end-of-line characters in it. Here's a packed version of the first script.
<script implName="lang:BrowserJS:inline:"><![CDATA[var drawScene_Function="<script type='text/javascript'>function drawScene(ctx, theData) { ctx.fillStyle = 'green'; ctx.fillRect(0, 0, 499, 499); var rowItems = theData.split('|'); for (i in rowItems) { var colItems = rowItems[i].split(','); if (colItems.length != 3) {continue;} var id = colItems[0]; var x = colItems[1] * 5; var y = colItems[2] * 5; switch (id) { case '11': ctx.fillStyle = 'tan'; break; case '10': ctx.fillStyle = 'lightgrey'; break; case '3': ctx.fillStyle = 'white'; break; case '4': ctx.fillStyle = 'pink'; break; case '5': ctx.fillStyle = 'yellow'; break; default: ctx.fillStyle = 'magenta'; break; } ctx.fillRect(x, y, 5, 5); }};</script>";$('div#divHeadOne').html(drawScene_Function);$('div#divOne').html("<canvas id='graphicsServerCanvas' width='500' height='500'></canvas>");if(jQuery.browser.msie){var myEl=document.getElementById('graphicsServerCanvas');G_vmlCanvasManager.initElement(myEl)}]]></script>
New version with compiled Java client
server
<script implName="lang:BrowserJS:inline:"><![CDATA[
var drawScene_Function = "\
<script type='text/javascript'>\
/*\
* drawScene(context, dataFromClient)\
* id: 10=Cat 11=Human ?=Dog ?=Zombie ?=Termite\
* 15=Door 16=WallSection 17=HouseInteriorSection 18=Porch 19=Entrance\
* example of data: id,x,y\
* 1,13,20|\
* 1,16,31|\
* 2,17,15|\
* 3,17,16|\
* 1,17,21\
*/\
function drawScene(ctx, theData) {\
ctx.fillStyle = 'green';\
ctx.fillRect(0, 0, 499, 499);\
var rowItems = theData.split('|');\
for (i in rowItems) {\
var colItems = rowItems[i].split(',');\
if (colItems.length != 3) {continue;}\
var id = colItems[0];\
var x = colItems[1] * 5;\
var y = colItems[2] * 5;\
/* customized for Bestiary */\
switch (id) {\
case 'Cat': ctx.fillStyle = 'lightgrey'; break;\
case 'Hum': ctx.fillStyle = 'tan'; break;\
case 'Doo': ctx.fillStyle = 'lightgreen'; break;\
case 'Wal': ctx.fillStyle = 'orange'; break;\
case 'Hou': ctx.fillStyle = 'black'; break;\
case 'Por': ctx.fillStyle = 'lightgreen'; break;\
case 'Ent': ctx.fillStyle = 'lightgreen'; break;\
case 'Dog': ctx.fillStyle = 'white'; break;\
case 'Zom': ctx.fillStyle = 'pink'; break;\
case 'Ter': ctx.fillStyle = 'yellow'; break;\
default: ctx.fillStyle = 'magenta'; break;\
}\
ctx.fillRect(x, y, 5, 5);\
}\
};\
</script>";
$('div#divHeadOne').html(drawScene_Function);
$('div#divOne').html("<canvas id='graphicsServerCanvas' width='500' height='500'></canvas>");
if(jQuery.browser.msie) {
var myEl = document.getElementById('graphicsServerCanvas');
G_vmlCanvasManager.initElement(myEl);
}
]]></script>
use of the compiled client
<AlternativeGui implName="org.primordion.xholon.base.XholonNull"> <GridGuiDataProvider implName="org.primordion.xholon.io.GridGuiDataProvider" idType="3" idTypeAbbrevLen="3"> </GridGuiDataProvider> </AlternativeGui>
client script for testing the server
<script implName="lang:BrowserJS:inline:"><![CDATA[
var myData = 'Cat,13,20|Cat,16,31|Dog,17,15|Wal,17,16|Cat,17,21|Zom,33,33|Ter,40,40';
var myCanvas = document.getElementById('graphicsServerCanvas');
var ctx = myCanvas.getContext('2d');
drawScene(ctx, myData);
]]></script>