ZK Framework

Ken Webb 2010-04-02T22:48:42Z

ZK is an open-source Java framework for building Ajax web applications.

Generic ZK GUI

Any Xholon application can write itself out as a single file that implements a ZK application. The file includes a complete hierarchical GUI declared using the ZK XUL widgets, with supporting Java methods that are executed by ZK using Beanshell. This replaces the standard Xholon Swing-based GUI.

The combination Xholon/ZK application can be deployed using a server such as Tomcat or Jetty. The ZK GUI is used to start, pause/unpause, and stop the Xholon application, and to view the details of an Xholon node while running.

The following shows part of an automatically generated generic ZK GUI.

<?xml version="1.0" encoding="UTF-8"?>
<?page title="Cell - BioSystems paper"?>
<!-- To view this file, download free Gui/Ajax software ZK from http://www.zkoss.org/ -->
<!--
Automatically generated by Xholon version 0.7.1, using Xholon2Zuml.java
Fri Nov 09 18:46:45 EST 2007 1194652005562
model: Cell - BioSystems paper
www.primordion.com/Xholon
-->
<window title="Cell - BioSystems paper" border="normal">
<style src="/information/gui.css"/>
<menubar id="menubar">
<menu label="File">
...
</menu>
<menu label="Help">
<menupopup>
<menuitem label="About" onClick="about()"/>
<menuitem label="Information" onClick="information()"/>
</menupopup>
</menu>
</menubar>
<button label="Application" onClick="handleApplication(self.label)" context="nodePopup">
</button>
<groupbox width="350px" onClick="handleNodeSelection(self.getCaption().label)" context="nodePopup">
<caption label="Controller"/>
<button label="Start" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="Pause" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="Step" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="Stop" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="Refresh" onClick="refresh()" context="nodePopup">
</button>
</groupbox>
...
<groupbox width="600px" onClick="handleNodeSelection(self.getCaption().label)" context="nodePopup">
<caption label="extraCellularSpace_0"/>
<groupbox width="600px" onClick="handleNodeSelection(self.getCaption().label)" context="nodePopup">
<caption label="extraCellularSolution_1"/>
<button label="glucose_2" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
</groupbox>
<groupbox width="600px" onClick="handleNodeSelection(self.getCaption().label)" context="nodePopup">
<caption label="eukaryoticCell_3"/>
<groupbox width="600px" onClick="handleNodeSelection(self.getCaption().label)" context="nodePopup">
<caption label="cellMembrane_4"/>
<button label="cellBilayer_5" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
</groupbox>
<groupbox width="600px" onClick="handleNodeSelection(self.getCaption().label)" context="nodePopup">
<caption label="cytoplasm_6"/>
<groupbox width="600px" onClick="handleNodeSelection(self.getCaption().label)" context="nodePopup">
<caption label="cytosol_7"/>
<button label="glucose_8" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="glucose_6_Phosphate_9" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="fructose_6_Phosphate_10" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="fructose_1x6_Biphosphate_11" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="dihydroxyacetonePhosphate_12" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="glyceraldehyde_3_Phosphate_13" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="x1x3_BisphosphoGlycerate_14" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="x3_PhosphoGlycerate_15" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="x2_PhosphoGlycerate_16" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="phosphoEnolPyruvate_17" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="pyruvate_18" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
</groupbox>
<button label="hexokinase_19" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="phosphoGlucoIsomerase_20" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="phosphoFructokinase_21" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="aldolase_22" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="triosePhosphateIsomerase_23" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="glyceraldehyde_3_phosphateDehydrogenase_24" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="phosphoGlycerokinase_25" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="phosphoGlyceromutase_26" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="enolase_27" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
<button label="pyruvateKinase_28" onClick="handleNodeSelection(self.label)" context="nodePopup">
</button>
</groupbox>
</groupbox>
</groupbox>
<zscript>
void handleNodeSelection(String nodeName)
{
  descrip.value = new org.primordion.xholon.base.XPath()
   .evaluate("descendant-or-self::*[@name='" + nodeName + "']",
   org.primordion.xholon.app.Application.getApplication().getAppRoot()).handleNodeSelection();
}

...

void refresh()
{
  org.primordion.xholon.app.IApplication app = org.primordion.xholon.app.Application.getApplication();
  app.invokeXholon2Gui(app.getRoot(), "/jetty-6.1.5/webapps/xholon/temp.zul");
  Execution e = desktop.getExecution();
  page.removeComponents();
  e.createComponents("temp.zul", null, null);
}

void handleApplication(String nodeName)
{
  descrip.value = new org.primordion.xholon.base.XPath()
   .evaluate("descendant-or-self::*[@name='" + nodeName
   + "']",org.primordion.xholon.app.Application.getApplication().getAppRoot())
   .handleNodeSelection()+ " [timeStep=" + org.primordion.xholon.base.XholonTime.timeStep + "]";
}

...

void about()
{
  alert(org.primordion.xholon.app.Application.getApplication().getAbout());
}

...

</zscript>
<menupopup id="nodePopup">
<menuitem label="Attributes" onClick="alert(&quot;Attributes is not yet implemented.&quot;)"/>
</menupopup>
</window>

When ZK, the above ZK script, the Xholon framework, and the Xholon Cell application are run in a browser under Tomcat, the page looks like the following. It functions much the same as the desktop/Swing Xholon GUI. Any of the nodes can be clicked, and the server will get the current data for that node from the Xholon application. For example, if the Glucose_8 node is selected, then the display line on the page shows a current value of 51009 units of glucose and shows that that glucose node is referenced by the CellBilayer node and the Hexokinase node.

Domain-specific ZK GUI

It's also quite straight forward to write a more application-specific GUI for a Xholon application. This is especially true for Xholon apps that already have a Xholon Swing-based declarative GUI. A Xholon/Swing XML file is readily transformable into a ZK/Xul file, and can be done automatically in some cases.

The following two screens capture some of the details.

return to main page