tuscany-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jsdelf...@apache.org
Subject svn commit: r1188045 [2/4] - in /tuscany/sca-cpp/trunk: ./ modules/edit/ modules/edit/htdocs/ modules/edit/htdocs/account/ modules/edit/htdocs/app/ modules/edit/htdocs/clone/ modules/edit/htdocs/create/ modules/edit/htdocs/data/ modules/edit/htdocs/gra...
Date Mon, 24 Oct 2011 08:45:56 GMT
Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/index.html?rev=1188045&r1=1188044&r2=1188045&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/index.html Mon Oct 24 08:45:54 2011
@@ -17,33 +17,8 @@
  * specific language governing permissions and limitations
  * under the License.    
 -->
-<html manifest="/cache-manifest.cmf">
-<head>
-<title></title>
-<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
-<meta name="apple-mobile-web-app-capable" content="yes"/>
-<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
-<link rel="apple-touch-icon" href="/public/touchicon.png"/>
-<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
-<script type="text/javascript" src="/all-min.js"></script>
-<script type="text/javascript" src="/menu.js"></script>
-<script type="text/javascript" src="graph.js"></script>
-</head>
-<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();">
 <div id="bodydiv" class="bodydiv" style="overflow: visible;">
 
-<div id="headdiv" class="hsection">
-<script type="text/javascript" src="/headconfig.js"></script>
-</div>
-
-<div id="menubackground" style="position: absolute; top: 0px; left: 0px; z-index: -1; width: 2500px;">
-<table cellpadding="0" cellspacing="0" width="100%" class="tbar"><tr><td class="dtbar">
-<table border="0" cellspacing="0" cellpadding="0"><tr><td class="ltbar"><span class="tbarsmenu">>&nbsp</span></td></tr></table>
-</td></tr></table>
-</div>
-
-<div id="menu"></div>
-
 <table style="width: 100%;">
 <tr>
 <td><h2><span id="appNameHeader"></span></h2></td>
@@ -59,10 +34,6 @@
 
 <table id="compValueTable" style="width: 100%;">
 <tr>
-<td class="thr thl" style="padding-left: 2px; padding-right: 2px; vertical-align: top; width: 100%">
-<input id="compValue" type="text" value="" title="Component value" autocapitalize="off" placeholder="Value" style="position: relative; width: 100%;"/>
-</td>
-
 <td class="thl thr" style="text-align: right; padding-right: 2px; vertical-align: top;">
 <span id="deleteCompButton" title="Delete a component" class="graybutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; text-align: center; margin-left: 0px; margin-right: 0px;">-</span>
 
@@ -72,36 +43,38 @@
 
 <span id="playCompButton" title="View component value" class="graybutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
 </td>
+
+<td class="thl thr" style="padding-left: 2px; padding-right: 2px; vertical-align: top; width: 100%">
+<input id="compValue" type="text" value="" title="Component value" autocapitalize="off" placeholder="Value" style="position: relative; visibility: hidden; width: 100%;"/>
+</td>
 </tr>
 </table>
 
 <div id="contentdiv" style="margin-top: 4px; width: 2500px;">
-<div id="playdiv" style="position:relative; top: 0x; left: 0px; right: 0px; width: 2500px; height: 5000px; visibility: hidden">
+<div id="playdiv" style="position: relative; top: 0x; left: 0px; right: 0px; width: 2500px; height: 5000px; visibility: hidden">
 </div>
 </div>
 
 <script type="text/javascript">
-ui.initbody();
 
 // Get the app name
-var appname = ui.fragmentParams()['app'];
+var appname = ui.fragmentParams(location)['app'];
 var ispalette = false;
 if (isNil(appname)) {
     appname = ui.fragmentParams()['palette'];
-    if (isNil(appname))
-        window.open('/', '_self');
 
     // Edit a palette instead of a regular app
-    ispalette = true;
+    if (!isNil(appname))
+        ispalette = true;
 }
 
 /**
  * Return the link to an app.
  */
 function applink(appname) {
-    var protocol = window.location.protocol;
-    var host = window.location.hostname;
-    var port = ':' + window.location.port;
+    var protocol = location.protocol;
+    var host = location.hostname;
+    var port = ':' + location.port;
     if (port == ':80' || port == ':443' || port == ':')
         port = '';
     var link = protocol + '//' + appname + '.' + host + port + '/';
@@ -109,12 +82,9 @@ function applink(appname) {
 }
 
 // Set page titles
-document.title = windowtitle(window.location.hostname) + ' - ' + (isNil(config.compose)? 'Composition' : config.compose) + ' - ' + appname;
+document.title = ui.windowtitle(location.hostname) + ' - ' + (isNil(config.compose)? 'Composition' : config.compose) + ' - ' + appname;
 $('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
 
-// Load the menu bar
-displaymenu();
-
 /**
  * Component value field, add, delete and play buttons.
  */
@@ -125,10 +95,6 @@ var ccopy = $('copyCompButton');
 var cplay = $('playCompButton');
 
 // Position background divs
-var mbackground = $('menubackground');
-var menudiv = $('menu');
-mbackground.style.top = ui.pixpos(menudiv.offsetTop);
-
 var cvbackground = $('compValueBackground');
 var cvtable = $('compValueTable');
 cvbackground.style.top = ui.pixpos(cvtable.offsetTop);
@@ -154,6 +120,1764 @@ var composites = sca.reference(editWidge
 //rconsole = sca.defun(sca.reference(editWidget, "log"), "log");
 
 /**
+ * SVG composite rendering functions.
+ */
+var graph = {};
+
+/**
+ * Basic colors
+ */
+graph.colors = {};
+graph.colors.black = '#000000';
+graph.colors.blue = '#0000ff';
+graph.colors.cyan = '#00ffff';
+graph.colors.gray = '#808080'
+graph.colors.lightgray = '#dcdcdc'
+graph.colors.green = '#00ff00';
+graph.colors.magenta = '#ff00ff';
+graph.colors.orange = '#ffa500';
+graph.colors.pink = '#ffc0cb';
+graph.colors.purple = '#800080';
+graph.colors.red = '#ff0000';
+graph.colors.white = '#ffffff';
+graph.colors.yellow = '#ffff00';
+graph.colors.link = '#598edd';
+
+graph.colors.orange1 = '#ffd666';
+graph.colors.green1 = '#bbe082';
+graph.colors.blue1 = '#66dbdf';
+graph.colors.yellow1 = '#fdf57a';
+graph.colors.cyan1 = '#e6eafb';
+graph.colors.lightgray1 = '#eaeaea'
+graph.colors.pink1 = '#ffd9e0';
+graph.colors.red1 = '#d03f41';
+graph.colors.white1 = '#ffffff';
+
+graph.colors.orange2 = '#ffbb00';
+graph.colors.green2 = '#96d333';
+//graph.colors.blue2 = '#0d7cc1';
+graph.colors.blue2 = '#00c3c9';
+graph.colors.red2 = '#d03f41';
+graph.colors.yellow2 = '#fcee21';
+graph.colors.magenta2 = '#c0688a';
+graph.colors.cyan2 = '#d5dcf9';
+graph.colors.lightgray2 = '#dcdcdc'
+graph.colors.pink2 = '#ffc0cb';
+graph.colors.white2 = '#ffffff';
+
+graph.colors.orange3 = '#ffc700';
+graph.colors.green3 = '#92e120';
+graph.colors.blue3 = '#008fd1';
+graph.colors.yellow3 = '#fdf400';
+graph.colors.cyan3 = '#b4d3fd';
+graph.colors.lightgray3 = '#e3e3e3'
+graph.colors.pink3 = '#da749b';
+graph.colors.red3 = '#ed3f48';
+graph.colors.white3 = '#ffffff';
+
+/**
+ * Default positions and sizes.
+ */
+graph.palcx = 2500;
+graph.proxcx = 20;
+graph.proxcy = 20;
+graph.buttoncx = 55;
+graph.buttoncy = 23;
+graph.curvsz = 4;
+graph.tabsz = 2;
+graph.titlex = 4;
+graph.titley = 11;
+graph.titlew = ui.isMobile()? -2 : 0;
+
+/**
+ * SVG rendering functions.
+ */
+
+graph.svgns='http://www.w3.org/2000/svg';
+
+/**
+ * Make an SVG graph.
+ */
+graph.mkgraph = function(cdiv, pos, cvalue, cadd, ccopy, cdelete) {
+
+    // Create a div element to host the graph
+    var div = document.createElement('div');
+    div.id = 'svgdiv';
+    div.style.position = 'absolute';
+    div.style.left = ui.pixpos(pos.xpos() + cdiv.offsetLeft);
+    div.style.top = ui.pixpos(pos.ypos() + cdiv.offsetTop);
+    cdiv.appendChild(div);
+
+    // Create SVG element
+    var svg = document.createElementNS(graph.svgns, 'svg');
+    svg.style.height = ui.pixpos(5000);
+    svg.style.width = ui.pixpos(5000);
+    div.appendChild(svg);
+
+    // Track element dragging and selection
+    graph.dragging = null;
+    graph.dragged = false;
+    graph.moverenderer = null;
+    graph.selected = null;
+    cvalue.disabled = true;
+    cvalue.style.visibility = 'hidden';
+    ccopy.disabled = true;
+    cdelete.disabled = true;
+
+    /**
+     * Find the first draggable element in a hierarchy of elements.
+     */
+    function draggable(n) {
+        if (n == div || n == svg || n == null)
+            return null;
+        if (n.nodeName == 'g' && !isNil(n.id) && n.id != '')
+            return n;
+        return draggable(n.parentNode);
+    }
+
+    /**
+     * Handle a mouse down or touch start event.
+     */
+    function onmousedown(e) {
+
+        // Remember mouse or touch position
+        var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
+        graph.downX = pos.screenX;
+        graph.downY = pos.screenY;
+        graph.moveX = pos.screenX;
+        graph.moveY = pos.screenY;
+
+        // Engage the click component selection right away
+        // on mouse controlled devices
+        if (typeof e.touches == 'undefined')
+            onclick(e);
+
+        // Find and remember draggable component
+        var dragging = draggable(e.target);
+        if (dragging == null || dragging != graph.selected)
+            return true;
+        graph.dragging = dragging;
+        graph.dragged = false;
+
+        // Remember current drag position
+        graph.dragX = pos.screenX;
+        graph.dragY = pos.screenY;
+
+        e.preventDefault();
+        return true;
+    };
+
+    if (!ui.isMobile()) {
+        div.onmousedown = function(e) {
+            //log('onmousedown');
+            var suspend = svg.suspendRedraw(10);
+            var r = onmousedown(e);
+            svg.unsuspendRedraw(suspend);
+            return r;
+        }
+    } else {
+        div.ontouchstart = function(e) {
+            //log('ontouchstart');
+
+            // Clear current move renderer if it's running
+            if (!isNil(graph.moverenderer)) {
+                clearInterval(graph.moverenderer);
+                graph.moverenderer = null;
+            }
+
+            var suspend = svg.suspendRedraw(10);
+            var r = onmousedown(e);
+            svg.unsuspendRedraw(suspend);
+            return r;
+        }
+    }
+
+    /**
+     * Handle a mouse up or touch end event.
+     */
+    function onmouseup(e) {
+
+        // Engage the click component selection now on touch devices
+        if (ui.isMobile()) {
+            if (!graph.dragged && graph.moveX == graph.downX && graph.moveY == graph.downY)
+                return onclick(e);
+        }
+
+        // Stop here if the component was not dragged
+        if (graph.dragging == null)
+            return true;
+        if (!graph.dragged) {
+            graph.dragging = null;
+            return true;
+        }
+
+        if (graph.dragging.parentNode == svg && graph.dragging.id.substring(0, 8) != 'palette:') {
+
+            // Add new dragged component to the composite
+            if (isNil(graph.dragging.compos)) {
+                var compos = scdl.composite(svg.compos);
+                setElement(compos, graph.sortcompos(graph.addcomps(mklist(graph.dragging.comp), compos)));
+                graph.dragging.compos = svg.compos;
+            }
+
+            // Update component position
+            setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, svg)));
+
+            // Wire component to neighboring reference
+            if (!isNil(graph.dragging.svcpos)) {
+                var compos = scdl.composite(svg.compos);
+                setElement(compos, graph.sortcompos(graph.clonerefs(graph.wire(graph.dragging, compos, svg))));
+            }
+
+            // Snap top level component position to grid
+            if (graph.dragging.parentNode == svg) {
+                var gpos = graph.relpos(graph.dragging);
+                setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.mkpath().pos(graph.gridsnap(gpos.xpos()), graph.gridsnap(gpos.ypos()))));
+            }
+        }
+
+        // Forget current dragged component
+        graph.dragging = null;
+        graph.dragged = false;
+
+        // Refresh the composite
+        //log('onmouseup refresh');
+        var nodes = graph.refresh(svg);
+
+        // Reselected the previously selected component
+        if (!isNil(graph.selected)) {
+            graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes);
+            graph.compselect(graph.selected, true, cvalue, ccopy, cdelete);
+
+            // Trigger component select event
+            svg.oncompselect(graph.selected);
+        }
+
+        // Trigger composite change event
+        svg.oncomposchange(false);
+        return true;
+    };
+
+    if (!ui.isMobile()) {
+        div.onmouseup = function(e) {
+            //log('onmouseup');
+            var suspend = svg.suspendRedraw(10);
+            var r = onmouseup(e);
+            svg.unsuspendRedraw(suspend);
+            return r;
+        }
+    } else {
+        div.ontouchend = function(e) {
+            //log('ontouchend');
+
+            // Clear current move renderer if it's running
+            if (!isNil(graph.moverenderer)) {
+                clearInterval(graph.moverenderer);
+                graph.moverenderer = null;
+            }
+
+            var suspend = svg.suspendRedraw(10);
+            var r = onmouseup(e);
+            svg.unsuspendRedraw(suspend);
+            return r;
+        }
+    }
+
+    /**
+     * Handle a mouse or touch click event.
+     */
+    function onclick(e) {
+        //log('onclick logic');
+
+        // Find selected component
+        var selected = draggable(e.target);
+        if (selected == null) {
+            if (graph.selected != null) {
+
+                // Reset current selection
+                graph.compselect(graph.selected, false, cvalue, ccopy, cdelete);
+                graph.selected = null;
+
+                // Trigger component select event
+                svg.oncompselect(null);
+            }
+
+            // Dismiss the palette
+            if (e.target == div || e.target == svg && ui.numpos(div.style.left) != (graph.palcx * -1))
+            	div.style.left = ui.pixpos(graph.palcx * -1);
+
+            return true;
+        }
+
+        // Ignore multiple click events
+        if (selected == graph.selected)
+            return true;
+        if (selected.id.substring(0, 8) == 'palette:' && ui.numpos(div.style.left) != 0)
+            return true;
+
+        // Deselect previously selected component
+        graph.compselect(graph.selected, false, cvalue, ccopy, cdelete);
+
+        // Clone component from the palette
+        if (selected.id.substring(0, 8) == 'palette:') {
+            var compos = scdl.composite(svg.compos);
+            var comp = graph.clonepalette(selected, compos, svg);
+            setElement(compos, graph.sortcompos(graph.addcomps(mklist(comp), compos)));
+
+            // Move into the editing area and hide the palette
+            div.style.left = ui.pixpos(graph.palcx * -1);
+
+            // Refresh the composite
+            //log('onclick refresh');
+            var nodes = graph.refresh(svg);
+
+            // Reselect the previously selected component
+            graph.selected = graph.findcompnode(scdl.name(comp), nodes);
+            graph.compselect(graph.selected, true, cvalue, ccopy, cdelete);
+
+            // Trigger component select event
+            svg.oncompselect(graph.selected);
+
+            // Trigger composite change event
+            svg.oncomposchange(true);
+
+        } else {
+            graph.selected = selected;
+
+            // Select the component
+            graph.compselect(graph.selected, true, cvalue, ccopy, cdelete);
+
+            // Trigger component select event
+            svg.oncompselect(graph.selected);
+        }
+
+        //log('comp selected');
+
+        e.preventDefault();
+        return true;
+    }
+
+    if (!ui.isMobile()) {
+        div.onclick = function(e) {
+            //log('div onclick');
+            var suspend = svg.suspendRedraw(10);
+            var r = onclick(e);
+            svg.unsuspendRedraw(suspend);
+            return r;
+        }
+        svg.onclick = function(e) {
+            //log('svg onclick');
+            var suspend = svg.suspendRedraw(10);
+            var r = onclick(e);
+            svg.unsuspendRedraw(suspend);
+            return r;
+        }
+    }
+
+    /**
+     * Handle a mouse or touch move event.
+     */
+    function onmousemove(e) {
+        if (graph.dragging == null)
+            return true;
+
+        // Ignore duplicate  mouse move events
+        if (graph.moveX == graph.dragX && graph.moveY == graph.dragY)
+            return true;
+
+        // Remember that the component was dragged
+        graph.dragged = true;
+
+        // Cut wire to component
+        if (graph.dragging.parentNode != svg) {
+            var compos = scdl.composite(svg.compos);
+            setElement(compos, graph.sortcompos(graph.cutwire(graph.dragging, compos, svg)));
+
+            // Bring component to the top
+            graph.bringtotop(graph.dragging, svg);
+        }
+
+        // Calculate new position of dragged element
+        var gpos = graph.relpos(graph.dragging);
+        var newX = gpos.xpos() + (graph.moveX - graph.dragX);
+        var newY = gpos.ypos() + (graph.moveY - graph.dragY);
+        if (newX >= graph.palcx)
+            graph.dragX = graph.moveX
+        else
+            newX = graph.palcx;
+        if (newY >= 0)
+            graph.dragY = graph.moveY;
+        else
+            newY = 0;
+
+        // Detach child elements to speedup rendering
+        graph.compoutline(graph.dragging, true);
+
+        // Move the dragged element
+        graph.move(graph.dragging, graph.mkpath().pos(newX, newY));
+
+        return false;
+    };
+
+    if (!ui.isMobile()) {
+        window.onmousemove = function(e) {
+            //log('onmousemove');
+
+            // Remember mouse position
+            graph.moveX = e.screenX;
+            graph.moveY = e.screenY;
+
+            var suspend = svg.suspendRedraw(10);
+            var r = onmousemove(e);
+            svg.unsuspendRedraw(suspend);
+            return r;
+        }
+    } else {
+        div.ontouchmove = function(e) {
+            //log('ontouchmove');
+            
+            // Remember touch position
+            var pos = e.touches[0];
+            if (graph.moveX == pos.screenX && graph.moveY == pos.screenY)
+                return true;
+            graph.moveX = pos.screenX;
+            graph.moveY = pos.screenY;
+            if (graph.moveX == graph.dragX && graph.moveY == graph.dragY)
+                return true;
+
+            // Start async move renderer
+            if (graph.moverenderer == null) {
+                graph.moverenderer = setInterval(function() {
+                    var suspend = svg.suspendRedraw(10);
+                    onmousemove(e);
+                    svg.unsuspendRedraw(suspend);
+                }, 10);
+            }
+            return true;
+        }
+    }
+
+    /**
+     * Handle field on change events.
+     */
+    function onvaluechange() {
+        if (graph.selected == null)
+            return false;
+        if (g.parentNode.style.visibility == 'hidden')
+            return false;
+
+        // Change component name and refactor references to it
+        function changename() {
+            var compos = scdl.composite(svg.compos);
+            cvalue.value = graph.ucid(cvalue.value, compos, false);
+            graph.selected.id = cvalue.value;
+            setElement(compos, graph.sortcompos(graph.renamecomp(graph.selected.comp, compos, cvalue.value)));
+
+            // Refresh the composite
+            //log('onchangename refresh');
+            var nodes = graph.refresh(svg);
+
+            // Reselected the previously selected component
+            graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes);
+            graph.compselect(graph.selected, true, cvalue, ccopy, cdelete);
+
+            // Trigger component select event
+            svg.oncompselect(graph.selected);
+
+            // Trigger composite change event
+            svg.oncomposchange(true);
+            return false;
+        }
+
+        // Change the component property value
+        function changeprop() {
+            graph.setproperty(graph.selected.comp, cvalue.value);
+            var hasprop = graph.hasproperty(graph.selected.comp);
+            cvalue.disabled = hasprop? false : true;
+            cvalue.style.visibility = hasprop? 'visible' : 'hidden';
+            cvalue.value = graph.property(graph.selected.comp);
+
+            // Refresh the composite
+            //log('onchangeprop refresh');
+            var nodes = graph.refresh(svg);
+
+            // Reselected the previously selected component
+            graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes);
+            graph.compselect(graph.selected, true, cvalue, ccopy, cdelete);
+
+            // Trigger component select event
+            svg.oncompselect(graph.selected);
+
+            // Trigger composite change event
+            svg.oncomposchange(true);
+            return false;
+        }
+
+        return graph.hasproperty(graph.selected.comp)? changeprop() : changename();
+    };
+
+    cvalue.onchange = function() {
+        var suspend = svg.suspendRedraw(10);
+        var r = onvaluechange();
+        svg.unsuspendRedraw(suspend);
+        return r;
+    }
+    
+    // Handle delete event
+    function ondeleteclick() {
+        if (graph.selected == null)
+            return false;
+        if (graph.selected.id.substring(0, 8) != 'palette:') {
+
+            // Remove selected component
+            var compos = scdl.composite(svg.compos);
+            if (isNil(graph.selected.compos))
+                setElement(compos, graph.sortcompos(graph.cutwire(graph.selected, compos, svg)));
+            setElement(compos, graph.sortcompos(graph.clonerefs(graph.gcollect(graph.removecomp(graph.selected.comp, compos)))));
+
+            // Reset current selection
+            graph.compselect(graph.selected, false, cvalue, ccopy, cdelete);
+            graph.selected = null;
+
+            // Refresh the composite
+            //log('ondelete refresh');
+            graph.refresh(svg);
+
+            // Trigger component select event
+            svg.oncompselect(null);
+
+            // Trigger composite change event
+            svg.oncomposchange(true);
+        }
+        return false;
+    };
+
+    cdelete.onclick = function() {
+        var suspend = svg.suspendRedraw(10);
+        var r = ondeleteclick();
+        svg.unsuspendRedraw(suspend);
+        return r;
+    };
+
+    // Handle copy event
+    function oncopyclick() {
+        if (graph.selected == null)
+            return false;
+        if (graph.selected.id.substring(0, 8) == 'palette:')
+            return false;
+
+        // Clone the selected component
+        var compos = scdl.composite(svg.compos);
+        var comps = graph.clonecomp(graph.selected, compos, svg);
+        setElement(compos, graph.sortcompos(graph.addcomps(comps, compos)));
+
+        // Refresh the composite
+        //log('onclick refresh');
+        var nodes = graph.refresh(svg);
+
+        // Select the component clone
+        graph.selected = graph.findcompnode(scdl.name(car(comps)), nodes);
+        graph.compselect(graph.selected, true, cvalue, ccopy, cdelete);
+
+        // Trigger component select event
+        svg.oncompselect(graph.selected);
+
+        // Trigger composite change event
+        svg.oncomposchange(true);
+
+        return false;
+    };
+
+    ccopy.onclick = function() {
+        var suspend = svg.suspendRedraw(10);
+        var r = oncopyclick();
+        svg.unsuspendRedraw(suspend);
+        return r;
+    };
+
+    // Handle add event
+    cadd.onclick = function() {
+
+        // Show the palette
+        div.style.left = ui.pixpos(0);
+        return false;
+    };
+
+    // Create a hidden SVG element to help compute the width
+    // of component and reference titles
+    graph.svgtitles = document.createElementNS(graph.svgns, 'svg');
+    graph.svgtitles.style.visibility = 'hidden';
+    graph.svgtitles.style.height = ui.pixpos(0);
+    graph.svgtitles.style.width = ui.pixpos(0);
+    div.appendChild(graph.svgtitles);
+
+    return svg;
+};
+
+/**
+ * Point class.
+ */
+graph.Point = function(x, y) {
+    this.x = x;
+    this.y = y;
+};
+graph.Point.prototype.xpos = function() {
+    return this.x;
+};
+graph.Point.prototype.ypos = function() {
+    return this.y;
+};
+
+graph.mkpoint = function(x, y) {
+    return new graph.Point(x, y);
+};
+
+/**
+ * Path class.
+ */
+graph.Path = function() {
+    this.path = '';
+    this.x = 0;
+    this.y = 0;
+}
+graph.Path.prototype.pos = function(x, y) {
+    this.x = x;
+    this.y = y;
+    return this;
+};
+graph.Path.prototype.xpos = function() {
+    return this.x;
+};
+graph.Path.prototype.ypos = function() {
+    return this.y;
+};
+graph.Path.prototype.rmove = function(x, y) {
+    return this.move(this.x + x, this.y + y);
+};
+graph.Path.prototype.rline = function(x, y) {
+    return this.line(this.x + x, this.y + y);
+};
+graph.Path.prototype.rcurve = function(x1, y1, x, y) {
+    return this.curve(this.x + x1, this.y + y1, this.x + x1 + x, this.y + y1 + y);
+};
+graph.Path.prototype.str = function() {
+    return this.path;
+};
+graph.Path.prototype.clone = function() {
+    return graph.mkpath().pos(this.xpos(), this.ypos());
+};
+graph.Path.prototype.move = function(x, y) {
+    this.path += 'M' + x + ',' + y + ' '; 
+    return this.pos(x, y);
+};
+graph.Path.prototype.line = function(x, y) {
+    this.path += 'L' + x + ',' + y + ' ';
+    return this.pos(x, y);
+};
+graph.Path.prototype.curve = function(x1, y1, x, y) {
+    this.path += 'Q' + x1 + ',' + y1 + ' ' + x + ',' + y + ' ';
+    return this.pos(x, y);
+};
+graph.Path.prototype.end = function() {
+    this.path += 'Z';
+    return this;
+};
+
+graph.mkpath = function() {
+    return new graph.Path();
+};
+
+/**
+ * Return an element representing a title.
+ */
+graph.mktitle = function(t, x, y) {
+    var title = document.createElementNS(graph.svgns, 'text');
+    title.setAttribute('x', x);
+    title.setAttribute('y', y);
+    title.setAttribute('class', 'svgtitle');
+    title.setAttribute('pointer-events', 'none');
+    title.appendChild(document.createTextNode(t));
+    graph.svgtitles.appendChild(title);
+    return title;
+};
+
+/**
+ * Return an element representing the title of a component.
+ */
+graph.comptitle = function(comp) {
+    return memo(comp, 'title', function() {
+    	var ct = graph.title(comp);
+    	var pt = graph.propertytitle(comp);
+    	if (ct == '' && pt == '')
+    	    return null;
+        return graph.mktitle((ct != '' && pt != '')? ct + ' ' + pt : ct + pt, graph.titlex, graph.titley);
+    });
+};
+
+/**
+ * Return the width of the title of a component.
+ */
+graph.comptitlewidth = function(comp) {
+    var title = graph.comptitle(comp);
+    if (isNil(title))
+        return 0;
+    return title.getBBox().width + graph.titlew;
+};
+
+/**
+ * Draw a component shape selection.
+ */
+graph.compselect = function(g, s, cvalue, ccopy, cdelete) {
+    if (isNil(g) || !s) {
+        cvalue.value = '';
+        cvalue.disabled = true;
+        cvalue.style.visibility = 'hidden';
+        ccopy.disabled = true;
+        cdelete.disabled = true;
+        if (isNil(g))
+            return true;
+        g.shape.setAttribute('stroke', graph.colors.gray);
+        g.shape.setAttribute('stroke-width', '1');
+        return true;
+    }
+
+    cvalue.value = graph.hasproperty(g.comp)? graph.property(g.comp) : g.id;
+    cvalue.disabled = false;
+    cvalue.style.visibility = 'visible';
+    ccopy.disabled = false;
+    cdelete.disabled = false;
+
+    g.shape.setAttribute('stroke', graph.colors.link);
+    g.shape.setAttribute('stroke-width', '2');
+    g.parentNode.appendChild(g);
+    return true;
+};
+
+/**
+ * Draw a palette shape selection.
+ */
+graph.paletteselect = function(g, s) {
+    if (isNil(g))
+        return true;
+    if (!s) {
+        g.shape.setAttribute('stroke', graph.colors.gray);
+        g.shape.setAttribute('stroke-width', '1');
+        return true;
+    }
+
+    g.shape.setAttribute('stroke', graph.colors.link);
+    g.shape.setAttribute('stroke-width', '2');
+    g.parentNode.appendChild(g);
+    return true;
+};
+
+/**
+ * Draw a component outline for faster rendering.
+ */
+graph.compoutline = function(g, s) {
+    if (s == (isNil(g.outlined)? false : g.outlined))
+        return true;
+    g.outlined = s;
+
+    if (s) {
+        g.shape.setAttribute('fill', 'none');
+        if (!isNil(g.title))
+            g.removeChild(g.title);
+    } else {
+        g.shape.setAttribute('fill', graph.color(g.comp));
+        if (!isNil(g.title))
+            g.appendChild(g.title);
+    }
+
+    map(function(r) {
+            var n = caddr(r);
+            if (isNil(n))
+                return r;
+            graph.compoutline(n, s);
+            return r;
+        }, g.refpos);
+    return true;
+};
+
+/**
+ * Return a node representing a component.
+ */
+graph.compnode = function(comp, cassoc, pos, parentg) {
+
+    // Make the component title element
+    var title = graph.comptitle(comp);
+
+    // Compute the path of the component shape
+    var path = graph.comppath(comp, cassoc);
+
+    // Create the main component shape
+    var shape = document.createElementNS(graph.svgns, 'path');
+    shape.setAttribute('d', path.str());
+    shape.setAttribute('fill', graph.color(comp));
+    //shape.setAttribute('fill-opacity', '0.6');
+    shape.setAttribute('stroke', graph.colors.gray);
+    shape.setAttribute('stroke-width', '1');
+    shape.setAttribute('pointer-events', 'visible');
+
+    // Create an svg group and add the shape and title to it
+    var g = document.createElementNS(graph.svgns, 'g');
+    g.comp = comp;
+    g.id = scdl.name(comp);
+    g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
+    g.pos = pos.clone();
+    g.appendChild(shape);
+    g.shape = shape;
+    if (!isNil(title)) {
+        g.appendChild(title);
+        g.title = title;
+    }
+
+    // Store the the positions of the services and references
+    g.refpos = reverse(path.refpos);
+    g.svcpos = reverse(path.svcpos);
+
+    // Handle onclick events
+    g.onclick = parentg.onclick;
+
+    return g;
+};
+
+/**
+ * Find the node representing a component.
+ */
+graph.findcompnode = function(name, nodes) {
+    if (isNil(nodes))
+        return null;
+    if (isNil(car(nodes).comp))
+        return graph.findcompnode(name, cdr(nodes));
+    if (name == scdl.name(car(nodes).comp))
+        return car(nodes);
+    var node = graph.findcompnode(name, nodeList(car(nodes).childNodes));
+    if (!isNil(node))
+        return node;
+    return graph.findcompnode(name, cdr(nodes));
+}
+
+/**
+ * Return a graphical group.
+ */
+graph.mkgroup = function(pos) {
+    var g = document.createElementNS(graph.svgns, 'g');
+    g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
+    g.pos = pos.clone();
+    return g;
+};
+
+/**
+ * Return a node representing a button.
+ */
+graph.mkbutton = function(t, pos) {
+
+    // Make the button title
+    var title = graph.mktitle(t, graph.titlex, graph.titley);
+
+    // Compute the path of the button shape
+    var path = graph.buttonpath().str();
+
+    // Create the main button shape
+    var shape = document.createElementNS(graph.svgns, 'path');
+    shape.setAttribute('d', path);
+    shape.setAttribute('fill', graph.colors.lightgray1);
+    //shape.setAttribute('fill-opacity', '0.6');
+    shape.setAttribute('stroke', graph.colors.gray);
+    shape.setAttribute('stroke-width', '1');
+    shape.setAttribute('pointer-events', 'visible');
+
+    // Create a group and add the button shape to it
+    var g = document.createElementNS(graph.svgns, 'g');
+    g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
+    g.pos = pos.clone();
+    g.appendChild(shape);
+    g.appendChild(title);
+
+    // Store the button shape in the group
+    g.shape = shape;
+
+    return g;
+};
+
+/**
+ * Return the relative position of a node.
+ */
+graph.relpos = function(e) {
+    var pmatrix = e.parentNode != null? e.parentNode.getCTM() : null;
+    var matrix = e.getCTM();
+    var curX = pmatrix != null? (Number(matrix.e) - Number(pmatrix.e)): Number(matrix.e);
+    var curY = pmatrix != null? (Number(matrix.f) - Number(pmatrix.f)): Number(matrix.f);
+    return graph.mkpath().pos(curX, curY);
+};
+
+/**
+ * Move a node.
+ */
+graph.move = function(e, pos) {
+    e.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')');
+    e.pos = pos.clone();
+};
+
+/**
+ * Return the absolute position of a component node.
+ */
+graph.abspos = function(e, g) {
+    if (e == g)
+        return graph.mkpath();
+    var gpos = graph.relpos(e);
+    var pgpos = graph.abspos(e.parentNode, g);
+    return graph.mkpath().pos(gpos.xpos() + pgpos.xpos(), gpos.ypos() + pgpos.ypos());
+};
+
+/**
+ * Bring a component node to the top.
+ */
+graph.bringtotop = function(n, g) {
+    if (n == g)
+        return null;
+    graph.move(n, graph.abspos(n, g));
+    g.appendChild(n);
+}
+
+/**
+ * Return the title of a SCDL element.
+ */
+graph.title = function(e) {
+    var t = scdl.title(e);
+    if (t != null) {
+        if (t == 'gt')
+            return '>'
+        if (t == 'lt')
+            return '<';
+        if (t.indexOf('{propval}') != -1)
+            return '';
+        if (t.indexOf('{compname}') == -1)
+            return t;
+        return t.replace('{compname}', scdl.name(e));
+    }
+    return scdl.name(e);
+};
+
+/**
+ * Return the property value of a SCDL component.
+ */
+graph.property = function(e) {
+    var p = scdl.properties(e);
+    if (isNil(p))
+        return '';
+    if (scdl.visible(car(p)) == 'false')
+        return '';
+    var pv = scdl.propertyValue(car(p));
+    return pv;
+};
+
+/**
+ * Return the title of a property of a SCDL component.
+ */
+graph.propertytitle = function(e) {
+    var pv = graph.property(e);
+    var t = scdl.title(e);
+    if (t.indexOf('{propval}') == -1)
+        return pv;
+    return t[0] == ' '? t.substr(1).replace('{propval}', pv) : t.replace('{propval}', pv);
+};
+
+/**
+ * Return true if a SCDL component has a property.
+ */
+graph.hasproperty = function(e) {
+    var p = scdl.properties(e);
+    if (isNil(p))
+        return false;
+    if (scdl.visible(car(p)) == 'false')
+        return false;
+    return true;
+};
+
+/**
+ * Change the property value of a SCDL component.
+ */
+graph.setproperty = function(e, value) {
+    var p = scdl.properties(e);
+    if (isNil(p))
+        return '';
+    if (scdl.visible(car(p)) == 'false')
+        return '';
+    var name = scdl.name(car(p));
+    setElement(car(p), mklist(element, "'property", mklist(attribute, "'name", name != null? name : "property"), value));
+    return value;
+};
+
+/**
+ * Return the color of a SCDL component.
+ */
+graph.color = function(comp) {
+    return memo(comp, 'color', function() {
+        var c = scdl.color(comp);
+        return c == null? graph.colors.blue1 : graph.colors[c];
+    });
+};
+
+/**
+ * Return the services on the left side of a component.
+ */
+graph.lsvcs = function(comp) {
+    return memo(comp, 'lsvcs', function() {
+        var svcs = scdl.services(comp);
+        if (isNil(svcs))
+            return mklist(mklist("'element","'service","'attribute","'name",scdl.name(comp)));
+        var l = filter(function(s) {
+                var a = scdl.align(s);
+                var v = scdl.visible(s);
+                return (a == null || a == 'left') && v != 'false';
+            }, svcs);
+        if (isNil(l))
+            return mklist();
+        return mklist(car(l));
+    });
+};
+
+/**
+ * Return the references on the right side of a component.
+ */
+graph.rrefs = function(comp) {
+    return memo(comp, 'rrefs', function() {
+        return filter(function(r) {
+            var a = scdl.align(r);
+            var v = scdl.visible(r);
+            return (a == null || a == 'right') && v != 'false';
+        }, scdl.references(comp));
+    });
+};
+
+/**
+ * Return the height of a reference on the right side of a component.
+ */
+graph.rrefheight = function(ref, cassoc) {
+    return memo(ref, 'rheight', function() {
+        var target = assoc(scdl.target(ref), cassoc);
+        if (isNil(target))
+            return graph.tabsz * 8;
+        return graph.compclosureheight(cadr(target), cassoc);
+    });
+};
+
+/**
+ * Return the total height of the references on the right side of a component.
+ */
+graph.rrefsheight = function(refs, cassoc) {
+    if (isNil(refs))
+        return 0;
+    return graph.rrefheight(car(refs), cassoc) + graph.rrefsheight(cdr(refs), cassoc);
+};
+
+/**
+ * Return the height of a component node.
+ */
+graph.compheight = function(comp, cassoc) {
+    return memo(comp, 'height', function() {
+        var lsvcs = graph.lsvcs(comp);
+        var lsvcsh = Math.max(1, length(lsvcs)) * (graph.tabsz * 8) + (graph.tabsz * 4);
+        var rrefs = graph.rrefs(comp);
+        var rrefsh = graph.rrefsheight(rrefs, cassoc) + (graph.tabsz * 2);
+        return Math.max(lsvcsh, rrefsh);
+    });
+};
+
+/**
+ * Return the height of a component and the components wired to its bottom side.
+ */
+graph.compclosureheight = function(comp, cassoc) {
+    return memo(comp, 'closureheight', function() {
+        return graph.compheight(comp, cassoc);
+    });
+};
+
+/**
+ * Return the max width of the references on the right side of a component.
+ */
+graph.rrefswidth = function(refs, cassoc) {
+    if (isNil(refs))
+        return 0;
+    return Math.max(graph.rrefwidth(car(refs), cassoc), graph.rrefswidth(cdr(refs), cassoc));
+};
+
+/**
+ * Return the width of a component.
+ */
+graph.compwidth = function(comp, cassoc) {
+    return memo(comp, 'width', function() {
+        var ctw = graph.comptitlewidth(comp);
+        var rrefsw = (isNil(graph.rrefs(comp))? 0 : (graph.tabsz * 4));
+        var twidth = (graph.titlex * 2) + ctw + rrefsw;
+        var width = Math.max(twidth, (graph.tabsz * 8) + (graph.tabsz * 4));
+        return width;
+    });
+};
+
+/**
+ * Return a path representing a reference positioned to the right of a component.
+ */
+graph.rrefpath = function(ref, cassoc, path, maxheight) {
+    var height = graph.rrefheight(ref, cassoc);
+
+    // Record reference position in the path
+    var xpos = path.xpos();
+    var ypos = path.ypos();
+    path.refpos = cons(mklist(ref, graph.mkpath().pos(xpos, ypos + (graph.tabsz * 5))), path.refpos);
+
+    // Compute the reference path
+    return path.rline(0,graph.tabsz * 2).rcurve(0,graph.tabsz,-graph.tabsz,0).rcurve(-graph.tabsz,0,0,-graph.tabsz/2.0).rcurve(0,-graph.tabsz/2.0,-graph.tabsz,0).rcurve(-graph.tabsz,0,0,graph.tabsz/2.0).rline(0,graph.tabsz * 3).rcurve(0,graph.tabsz/2.0,graph.tabsz,0).rcurve(graph.tabsz,0,0,-graph.tabsz/2.0).rcurve(0,-graph.tabsz/2.0,graph.tabsz,0).rcurve(graph.tabsz,0,0,graph.tabsz).line(path.xpos(), Math.min(ypos + height, maxheight));
+};
+
+/**
+ * Return a path representing a service positioned to the left of a component.
+ */
+graph.lsvcpath = function(svc, cassoc, path, minheight) {
+    var height = graph.tabsz * 8;
+
+    // Record service position in the path
+    var xpos = path.xpos();
+    var ypos = path.ypos();
+    path.svcpos = cons(mklist(svc, graph.mkpath().pos(xpos, ypos - (graph.tabsz * 6))), path.svcpos);
+
+    // Compute the service path
+    return path.rline(0, -(graph.tabsz * 2)).rcurve(0,-graph.tabsz,-graph.tabsz,0).rcurve(-graph.tabsz,0,0,graph.tabsz/2.0).rcurve(0,graph.tabsz/2.0,-graph.tabsz,0).rcurve(-graph.tabsz,0,0,-graph.tabsz/2.0).rline(0,-(graph.tabsz * 3)).rcurve(0,-graph.tabsz/2.0,graph.tabsz,0).rcurve(graph.tabsz,0,0,graph.tabsz/2.0).rcurve(0,graph.tabsz/2.0,graph.tabsz,0).rcurve(graph.tabsz,0,0,-graph.tabsz).line(path.xpos(), Math.max(ypos - height, minheight));
+};
+
+/**
+ * Return a path representing a component node.
+ */
+graph.comppath = function(comp, cassoc) {
+
+    // Calculate the width and height of the component node
+    var width = graph.compwidth(comp, cassoc);
+    var height = graph.compheight(comp, cassoc);
+
+    /**
+     * Apply a path rendering function to a list of services or references.
+     */
+    function renderpath(x, f, cassoc, path, height) {
+        if (isNil(x))
+            return path;
+        return renderpath(cdr(x), f, cassoc, f(car(x), cassoc, path, height), height);
+    }
+
+    var path = graph.mkpath().move(graph.curvsz,0);
+
+    // Store the positions of services and references in the path
+    path.refpos = mklist();
+    path.svcpos = mklist();
+
+    // Render the references on the right side of the component
+    var rrefs = graph.rrefs(comp);
+    path = path.line(width - graph.curvsz,path.ypos()).rcurve(graph.curvsz,0,0,graph.curvsz);
+    path = renderpath(rrefs, graph.rrefpath, cassoc, path, height - graph.curvsz);
+
+    // Render the references on the bottom side of the component
+    var boffset = graph.curvsz;
+    path = path.line(path.xpos(),height - graph.curvsz).rcurve(0,graph.curvsz,graph.curvsz * -1,0).line(boffset, path.ypos());
+
+    // Render the services on the left side of the component
+    var lsvcs = graph.lsvcs(comp);
+    var loffset = graph.curvsz + (length(lsvcs) * (graph.tabsz * 8));
+    path = path.line(graph.curvsz,path.ypos()).rcurve(graph.curvsz * -1,0,0,graph.curvsz * -1).line(path.xpos(), loffset);
+    path = renderpath(lsvcs, graph.lsvcpath, cassoc, path, graph.curvsz);
+
+    // Close the component node path
+    path = path.line(0,graph.curvsz).rcurve(0,graph.curvsz * -1,graph.curvsz,0);
+
+    return path.end();
+};
+
+/**
+ * Return the position of a component.
+ */
+graph.comppos = function(comp, pos) {
+    var x = scdl.x(comp);
+    var y = scdl.y(comp);
+    return graph.mkpath().pos(x != null? Number(x) + graph.palcx : pos.xpos(), y != null? Number(y) : pos.ypos());
+};
+
+/**
+ * Return a path representing a button node.
+ */
+graph.buttonpath = function(t) {
+    var path = graph.mkpath().move(graph.curvsz,0);
+    path = path.line(graph.buttoncx - graph.curvsz,path.ypos()).rcurve(graph.curvsz,0,0,graph.curvsz);
+    path = path.line(path.xpos(),graph.buttoncy - graph.curvsz).rcurve(0,graph.curvsz,-graph.curvsz,0).line(graph.curvsz, path.ypos());
+    path = path.line(graph.curvsz,path.ypos()).rcurve(-graph.curvsz,0,0,-graph.curvsz).line(path.xpos(), graph.curvsz);
+    path = path.line(0,graph.curvsz).rcurve(0,-graph.curvsz,graph.curvsz,0);
+    return path.end();
+};
+
+/**
+ * Render a SCDL composite into a list of component nodes.
+ */
+graph.composite = function(compos, pos, aspalette, g) {
+    var name = scdl.name(scdl.composite(compos));
+    var comps = scdl.components(compos);
+    var cassoc = scdl.nameToElementAssoc(comps);
+    var proms = scdl.promotions(compos);
+
+    // Unmemoize any memoized info about components and their references.
+    map(function(c) {
+            unmemo(c);
+            map(function(r) {
+                    unmemo(r);
+                }, scdl.references(c));
+        }, comps);
+
+    /**
+     * Render a component.
+     */
+    function rendercomp(comp, cassoc, pos) {
+
+        /**
+         * Render the references on the right side of a component.
+         */
+        function renderrrefs(refs, cassoc, pos, gcomp) {
+
+            /**
+             * Render a reference on the right side of a component.
+             */
+            function renderrref(ref, cassoc, pos, gcomp) {
+                var target = assoc(scdl.target(ref), cassoc);
+                if (isNil(target))
+                    return null;
+
+                // Render the component target of the reference
+                return rendercomp(cadr(target), cassoc, pos);
+            }
+
+            /**
+             * Move the rendering cursor down below a reference.
+             */
+            function rendermove(ref, cassoc, pos) {
+                return pos.clone().rmove(0, graph.rrefheight(ref, cassoc));
+            }
+
+            if (isNil(refs))
+                return mklist();
+
+            // Return list of (ref, comp rendering) pairs
+            var grefcomp = renderrref(car(refs), cassoc, pos, gcomp);
+            return cons(mklist(car(refs), grefcomp), renderrrefs(cdr(refs), cassoc, rendermove(car(refs), cassoc, pos), gcomp));
+        }
+
+        // Compute the component shape
+        var gcomp = graph.compnode(comp, cassoc, pos, g);
+
+        // Render the components wired to the component references
+        var rrefs = graph.rrefs(comp);
+        var rpos = graph.mkpath().rmove(graph.compwidth(comp, cassoc), 0);
+        var grrefs = renderrrefs(rrefs, cassoc, rpos, gcomp);
+
+        // Store list of (ref, pos, component rendering) triplets in the component
+        function refposgcomp(refpos, grefs) {
+            if (isNil(refpos))
+                return mklist();
+
+            // Append component rendering to component
+            var gref = cadr(car(grefs));
+            if (gref != null)
+                gcomp.appendChild(gref);
+            return cons(mklist(car(car(refpos)), cadr(car(refpos)), gref), refposgcomp(cdr(refpos), cdr(grefs)));
+        }
+
+        gcomp.refpos = refposgcomp(gcomp.refpos, grrefs);
+
+        return gcomp;
+    }
+
+    /**
+     * Render a list of promoted service components.
+     */
+    function renderproms(svcs, cassoc, pos) {
+
+        /**
+         * Return the component promoted by a service.
+         */
+        function promcomp(svc, cassoc) {
+            var c = assoc(scdl.promote(svc), cassoc);
+            if (isNil(c))
+                return mklist();
+            return cadr(c);
+        }
+
+        /**
+         * Move the rendering cursor down below a component.
+         */
+        function rendermove(comp, cassoc, pos) {
+            return pos.clone().rmove(0, graph.compclosureheight(comp, cassoc) + Math.max((graph.tabsz * 2), 8));
+        }
+
+        if (isNil(svcs))
+            return mklist();
+
+        // Render the first promoted component in the list
+        // then recurse to render the rest of the list
+        var comp = promcomp(car(svcs), cassoc);
+        if (isNil(comp))
+            return renderproms(cdr(svcs), cassoc, rendermove(car(svcs), cassoc, pos));
+
+        var cpos = graph.comppos(comp, pos);
+        return cons(rendercomp(comp, cassoc, cpos), renderproms(cdr(svcs), cassoc, rendermove(comp, cassoc, cpos)));
+    }
+
+    // Render the promoted service components
+    var rproms = renderproms(proms, cassoc, pos.clone().rmove(graph.tabsz * 4, graph.tabsz * 4));
+
+    if (aspalette) {
+
+        // Prefix ids of palette component elements with 'palette:' and
+        // move them to the palette area
+        return map(function(r) {
+                r.id = 'palette:' + r.id;
+                var gpos = r.pos;
+                graph.move(r, graph.mkpath().pos(gpos.xpos() - graph.palcx, gpos.ypos()));
+                return r;
+            }, rproms);
+
+    } else {
+
+        // Link app component elements to the containing composite
+        return map(function(r) { r.compos = compos; return r; }, rproms);
+    }
+};
+
+/**
+ * Return a component unique id.
+ */
+graph.ucid = function(prefix, compos1, compos2, clone) {
+
+    // Build an assoc list keyed by component name
+    var comps = map(function(c) { return mklist(scdl.name(c), c); }, append(namedElementChildren("'component", compos1), namedElementChildren("'component", compos2)));
+
+    if (!clone && isNil(assoc(prefix, comps)))
+        return prefix;
+
+    /**
+     * Find a free component id.
+     */
+    function ucid(p, id) {
+        if (isNil(assoc(p + id, comps)))
+            return p + id;
+        return ucid(p, id + 1);
+    }
+
+    /**
+     * Remove trailing digits from a prefix.
+     */
+    function untrail(p) { 
+        if (p.length < 2 || p[p.length - 1] < '0' || p[p.length - 1] > '9')
+            return p;
+        return untrail(p.substring(0, p.length - 1));
+    }
+
+    return ucid(prefix == ''? 'comp' : (clone? untrail(prefix) : prefix), 1);
+};
+
+/**
+ * Clone a palette component node.
+ */
+graph.clonepalette = function(e, compos, g) {
+
+    // Clone the SCDL component and give it a unique name
+    var wcomp = append(mklist(element, "'component", mklist(attribute, "'name", graph.ucid(scdl.name(e.comp), compos, compos, true))),
+                filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e.comp)));
+    var x = '<composite>' + writeXML(mklist(wcomp), false) + '</composite>';
+    var rcompos = scdl.composite(readXML(mklist(x)));
+    var comp = car(scdl.components(mklist(rcompos)));
+
+    // Update component position
+    setElement(comp, graph.movecomp(comp, graph.abspos(e, g).rmove(graph.palcx, 0)));
+
+    return comp;
+};
+
+/**
+ * Move a SCDL component to the given position.
+ */
+graph.movecomp = function(comp, pos) {
+    if (isNil(pos))
+        return append(mklist(element, "'component"),
+                filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'x" || attributeName(e) == "'y")); }, elementChildren(comp)));
+    return append(mklist(element, "'component", mklist(attribute, "'x", '' + (pos.xpos() - graph.palcx)), mklist(attribute, "'y", '' + pos.ypos())),
+            filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'x" || attributeName(e) == "'y")); }, elementChildren(comp)));
+};
+
+/**
+ * Align a pos along a 10pixel grid.
+ */
+graph.gridsnap = function(x) {
+    return Math.round(x / 10) * 10;
+}
+
+/**
+ * Clone a component node and all the components it references.
+ */
+graph.clonecomp = function(e, compos, g) {
+
+    // Write the component and the components it references to XML
+    function collectcomp(e) {
+        function collectrefs(refpos) {
+            if (isNil(refpos))
+                return mklist();
+            var r = car(refpos);
+            var n = caddr(r);
+            if (isNil(n))
+                return collectrefs(cdr(refpos));
+            return append(collectcomp(n), collectrefs(cdr(refpos)));
+        }
+
+        return cons(e.comp, collectrefs(e.refpos));
+    }
+
+    var allcomps = collectcomp(e);
+    var ls = map(function(e) { return writeXML(mklist(e), false); }, allcomps);
+    var x = '<composite>' + writeStrings(ls) + '</composite>';
+
+    // Read them back from XML to clone them
+    var rcompos = scdl.composite(readXML(mklist(x)));
+    var comps = scdl.components(mklist(rcompos));
+
+    // Give them new unique names
+    map(function(e) {
+
+        // Rename each component
+        var oname = scdl.name(e);
+        var name = graph.ucid(oname, compos, rcompos, true);
+        setElement(e, append(mklist(element, "'component", mklist(attribute, "'name", name)),
+                        filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e))));
+
+        // Refactor references to the component
+        map(function(c) { return graph.refactorrefs(scdl.references(c), oname, name); }, comps);
+    }, comps);
+
+    // Update the top component position
+    var comp = car(comps);
+    setElement(comp, graph.movecomp(comp, graph.abspos(e, g).rmove(10, 10)));
+
+    return comps;
+};
+
+/**
+ * Sort elements of a composite.
+ */
+graph.sortcompos = function(compos) {
+    return append(mklist(element, "'composite"), elementChildren(compos).sort(function(a, b) {
+
+        // Sort attributes, place them at the top
+        var aa = isAttribute(a);
+        var ba = isAttribute(b);
+        if (aa && !ba) return -1;
+        if (!aa && ba) return 1;
+        if (aa && ba) {
+            var aan = attributeName(a);
+            var ban = attributeName(b);
+            if (aan < ban) return -1;
+            if (aan > ban) return 1;
+            return 0;
+        }
+
+        // Sort elements, place services before components
+        var aen = elementName(a);
+        var ben = elementName(b);
+        if (aen == "'service" && ben == "'component") return -1;
+        if (aen == "'component" && ben == "'service") return 1;
+        var an = scdl.name(a);
+        var bn = scdl.name(b);
+        if (an < bn) return -1;
+        if (an > bn) return 1;
+        return 0;
+    }));
+}
+
+/**
+ * Add a list of components to a SCDL composite. The first
+ * component in the list is a promoted component.
+ */
+graph.addcomps = function(comps, compos) {
+    var comp = car(comps);
+    var name = scdl.name(comp);
+    var prom = mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name));
+    return append(mklist(element, "'composite"), append(elementChildren(compos), cons(prom, comps)));
+};
+
+/**
+ * Remove a component from a SCDL composite.
+ */
+graph.removecomp = function(comp, compos) {
+    var name = scdl.name(comp);
+    return append(mklist(element, "'composite"),
+            filter(function(c) { return !(isElement(c) && scdl.name(c) == name); }, elementChildren(compos)));
+};
+
+/**
+ * Garbage collect components not referenced or promoted.
+ */
+graph.gcollect = function(compos) {
+
+    // List the promoted components
+    var proms = map(function(s) { return mklist(scdl.promote(s), true); }, scdl.promotions(mklist(compos)));
+
+    // List the referenced components
+    var refs = reduce(function(a, comp) {
+                return append(a,
+                    map(function(ref) { return mklist(scdl.target(ref), true); }, filter(function(ref) { return scdl.target(ref) != null; }, scdl.references(comp))));
+            }, mklist(), scdl.components(mklist(compos)));
+
+    // Filter out the unused components
+    var used = append(proms, refs);
+    return append(mklist(element, "'composite"),
+            filter(function(c) { return !(isElement(c) && elementName(c) == "'component" && isNil(assoc(scdl.name(c), used))); }, elementChildren(compos)));
+}
+
+/**
+ * Clone and cleanup clonable references.
+ */
+graph.clonerefs = function(compos) {
+    return append(mklist(element, "'composite"),
+            map(function(c) {
+                if (elementName(c) != "'component")
+                    return c;
+
+                // If the references are clonable
+                var refs = scdl.references(c);
+                if (isNil(refs))
+                    return c;
+                if (scdl.clonable(car(refs)) != 'true')
+                    return c;
+                    
+                // Filter out the unwired references and add a fresh unwired
+                // reference at the end of the list
+                var cc = append(
+                    filter(function(e) { return !(elementName(e) == "'reference" && scdl.target(e) == null); }, elementChildren(c)),
+                    mklist(mklist(element, "'reference", mklist(attribute, "'name", scdl.name(car(refs))), mklist(attribute, "'clonable", "true"))));
+                return append(mklist(element, "'component"), cc);
+            
+            }, elementChildren(compos)));
+}
+
+/**
+ * Refactor references to a component.
+ */
+graph.refactorrefs = function(refs, oname, nname) {
+    if (isNil(refs))
+        return true;
+    var ref = car(refs);
+    if (scdl.target(ref) != oname)
+        return graph.refactorrefs(cdr(refs), oname, nname);
+
+    // Change the reference's target attribute
+    setElement(ref, append(mklist(element, "'reference"),
+        append(filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'target"); }, elementChildren(ref)),
+            mklist(mklist(attribute, "'target", nname)))));
+
+    return graph.refactorrefs(cdr(refs), oname, nname);
+};
+
+/**
+ * Rename a component.
+ */
+graph.renamecomp = function(comp, compos, name) {
+
+    // Refactor all the references to the renamed component
+    var oname = scdl.name(comp);
+    map(function(c) { return graph.refactorrefs(scdl.references(c), oname, name); }, namedElementChildren("'component", compos));
+
+    // Rename the SCDL promoted service and component
+    var proms = filter(function(s) { return scdl.name(s) == oname }, scdl.services(compos));
+    if (!isNil(proms))
+        setElement(car(proms), mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name)));
+    setElement(comp, append(mklist(element, "'component"),
+        cons(mklist(attribute, "'name", name),
+            filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'name"); }, elementChildren(comp)))));
+
+    return append(mklist(element, "'composite"), elementChildren(compos));
+};
+
+/**
+ * Cut the wire to a component node and make that node a
+ * top level component node.
+ */
+graph.cutwire = function(node, compos, g) {
+
+    /**
+     * Find the reference wired to a node and cut its wire.
+     */
+    function cutref(refs, node) {
+        if (isNil(refs))
+            return true;
+        var ref = car(refs);
+        if (caddr(ref) == node) {
+            setlist(ref, mklist(car(ref), cadr(ref), null));
+            setElement(car(ref),
+                append(mklist(element, "'reference"),
+                    filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'target"); }, elementChildren(car(ref)))));
+        }
+        return cutref(cdr(refs), node);
+    }
+
+    // Cut any reference wire, if found
+    cutref(node.parentNode.refpos, node);
+
+    // Make the component node a top level node.
+    node.compos = g.compos;
+
+    // Update the SCDL composite, add a promote element for
+    // that component
+    var comp = node.comp;
+    var name = scdl.name(comp);
+    var prom = mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name));
+    return append(mklist(element, "'composite"),
+            append(mklist(prom), filter(function(c) { return !(isElement(c) && elementName(c) == "'service" && scdl.name(c) == name); }, elementChildren(compos))));
+}
+
+/**
+ * Wire a component to the closest neighbor reference.
+ */
+graph.wire = function(n, compos, g) {
+
+    // Compute position of the component's service node
+    var spos = cadr(car(n.svcpos));
+    var aspos = graph.abspos(n, g).rmove(spos.xpos(), spos.ypos());
+
+    /**
+     * Find closest unwired reference node among all the references
+     * of all the components.
+     */
+    function closecomprefs(nodes, spos, cref) {
+
+        /**
+         * Find the closest unwired reference node among all the
+         * references of a node.
+         */
+        function closerefs(npos, refs, spos, cref) {
+            if (isNil(refs))
+                return cref;
+            var fdist = cadddr(cref);
+            var ref = car(refs);
+
+            // Skip wired reference
+            if (!isNil(filter(function(n) { return isAttribute(n) && attributeName(n) == "'target"; }, car(ref))))
+                return closerefs(npos, cdr(refs), spos, cref);
+
+            // Compute distance between service node and reference node
+            var rpos = cadr(ref).clone().rmove(npos.xpos(), npos.ypos());
+            var dx = Math.pow(rpos.xpos() - spos.xpos(), 2);
+            var dy = Math.pow(rpos.ypos() - spos.ypos(), 2);
+
+            // Check for proximity threshold
+            var rdist = (dx < (graph.proxcx * graph.proxcx) && dy < (graph.proxcy * graph.proxcy))? Math.sqrt(dx + dy) : 25000000;
+
+            // Go through all the references in the component
+            return closerefs(npos, cdr(refs), spos, fdist < rdist? cref : mklist(car(ref), cadr(ref), caddr(ref), rdist));
+        }
+
+        if (isNil(nodes))
+            return cref;
+
+        // Skip non-component nodes
+        var node = car(nodes);
+        if (isNil(node.comp))
+            return closecomprefs(cdr(nodes), spos, cref);
+
+        // Compute the component absolute position
+        var npos = graph.abspos(node, g);
+
+        // Go through all the components and their references
+        return closecomprefs(append(nodeList(node.childNodes), cdr(nodes)), spos, closerefs(npos, node.refpos, spos, cref));
+    }
+
+    // Find closest reference node
+    var cref = closecomprefs(nodeList(g.childNodes), aspos, mklist(null, graph.mkpath(), null, 25000000));
+    if (car(cref) == null)
+        return compos;
+    if (cadddr(cref) == 25000000)
+        return compos;
+
+    // Wire component to that reference, un-promote it, and
+    // update the SCDL reference and composite
+    setElement(n.comp, graph.movecomp(graph.dragging.comp, null));
+    n.compos = null;
+    setElement(car(cref), append(mklist(element, "'reference", mklist(attribute, "'target", scdl.name(n.comp))), elementChildren(car(cref))));
+    var name = scdl.name(n.comp);
+    return append(mklist(element, "'composite"),
+            filter(function(c) { return !(isElement(c) && elementName(c) == "'service" && scdl.name(c) == name); }, elementChildren(compos)));
+}
+
+/**
+ * Display a list of graphical nodes.
+ */
+graph.display = function(nodes, g, svg) {
+    var suspend = svg.suspendRedraw(10);
+
+    // Append the nodes to the graphical canvas
+    appendNodes(nodes, g);
+    
+    svg.unsuspendRedraw(suspend);
+    return nodes;
+};
+
+/**
+ * Hide a graph.
+ */
+graph.hide = function(g) {
+
+    // Remove nodes from the graph
+    map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes));
+    return g;
+};
+
+/**
+ * Refresh a graph.
+ */
+graph.refresh = function(g) {
+    //log('refresh');
+
+    // Remove existing nodes from the graph
+    map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes));
+
+    // Redisplay the composite associated with the graph
+    var nodes = graph.composite(g.compos, graph.mkpath().pos(graph.palcx,0), false, g);
+    appendNodes(nodes, g);
+    return nodes;
+};
+
+/**
+ * Display and enable editing of a composite and the graphical
+ * nodes that represent it.
+ */
+graph.edit = function(appname, compos, nodes, onchange, onselect, g) {
+    var suspend = g.suspendRedraw(10);
+
+    // Store the appname and composite in the graphical canvas
+    g.appname = appname;
+    g.compos = compos;
+
+    // Sort the composite elements now to allow for change detection later
+    var scompos = scdl.composite(g.compos);
+    setElement(scompos, graph.sortcompos(scompos));
+
+    // Store event listeners
+    g.oncomposchange = onchange;
+    g.oncompselect = onselect;
+
+    // Remove existing nodes from the graph
+    map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes));
+
+    // Display the composite nodes
+    appendNodes(nodes, g);
+
+    g.unsuspendRedraw(suspend);
+    return nodes;
+};
+
+/**
  * Track the current app composite and corresponding saved XML content.
  */
 var savedcomposxml = '';
@@ -216,7 +1940,7 @@ function getapp(name, g) {
         }
 
         // Display the composite
-        graph.edit(name, composite, graph.composite(composite, graph.mkpath().move(palcx,0), false, g), oncomposchange, oncompselect, g);
+        graph.edit(name, composite, graph.composite(composite, graph.mkpath().move(graph.palcx,0), false, g), oncomposchange, oncompselect, g);
 
         // Track the saved composite XML
         savedcomposxml = car(writeXML(composite, false));
@@ -319,29 +2043,14 @@ function oncomposchange(prop) {
 }
 
 /**
- * Return the link to a component value.
- */
-function compdatalink(appname, cname) {
-    if (cname == '' || isNil(cname))
-        return '';
-    var protocol = window.location.protocol;
-    var host = window.location.hostname;
-    var port = ':' + window.location.port;
-    if (port == ':80' || port == ':443' || port == ':')
-        port = '';
-    var link = protocol + '//' + appname + '.' + host + port + '/data/#component=' + cname;
-    return link;
-}
-
-/**
  * Return the link to a component.
  */
 function complink(appname, cname) {
     if (cname == '' || isNil(cname))
         return '';
-    var protocol = window.location.protocol;
-    var host = window.location.hostname;
-    var port = ':' + window.location.port;
+    var protocol = location.protocol;
+    var host = location.hostname;
+    var port = ':' + location.port;
     if (port == ':80' || port == ':443' || port == ':')
         port = '';
     var link = protocol + '//' + appname + '.' + host + port + '/c/' + cname;
@@ -355,16 +2064,14 @@ function oncompselect(gsel) {
     if (gsel == gcomp)
         return true;
     gcomp = gsel;
-    var cname = isNil(gsel)? '' : gsel.id;
-    var link = compdatalink(appname, cname);
 
     function updateButton(b, v) {
         b.style.color = v? '#000000' : '#808080';
     }
 
-    updateButton(cdelete, link != '');
-    updateButton(ccopy, link != '');
-    updateButton(cplay, link != '');
+    updateButton(cdelete, !isNil(gsel));
+    updateButton(ccopy, !isNil(gsel));
+    updateButton(cplay, !isNil(gsel));
     return true;
 }
 
@@ -376,14 +2083,47 @@ function showdata(gcomp) {
         return true;
     if (isNil(gcomp))
         return true;
-    cvalue.value = complink(appname, gcomp.id);
+    var clink = complink(appname, gcomp.id);
+    cvalue.value = clink;
     cplay.innerHTML = '&lt;';
-    gdiv.style.visibility = 'hidden'
     gvisible = false;
-    pdiv.style.visibility = 'visible';
     pdiv.innerHTML = '';
-    pdiv.innerHTML = '<iframe id="dataFrame" style="position: relative; height: 5000px; width: 2500px; border: 0px;" scrolling="no" frameborder="0" src="' +
-                        compdatalink(appname, gcomp.id) + '"></iframe>';
+    pdiv.style.visibility = 'visible';
+
+    // Get the component result data
+    var comp = sca.component(gcomp.id, appname);
+    comp.getnocache('', function(doc) {
+        function displaydata(t, w) {
+            pdiv.style.width = w;
+            pdiv.innerHTML = t;
+            return true;
+        }
+
+        // Stop now if we didn't get the doc
+        if (doc == null)
+            return displaydata('No content', '2500px');
+
+        // Format data table
+        if (json.isJSON(mklist(doc)))
+            return displaydata(ui.datatable(json.readJSON(mklist(doc))), '2500px');
+
+        if (atom.isATOMEntry(mklist(doc)))
+            return displaydata(ui.datatable(atom.readATOMEntry(mklist(doc))), '2500px');
+
+        if (atom.isATOMFeed(mklist(doc)))
+            return display(ui.datatable(atom.readATOMFeed(mklist(doc))), '2500px');
+
+        // Insert the doc as is in an iframe
+        var t = '<table class="datatable" style="width: 100%;">' +
+                '<tr><td class="datatdltop">' + 'value' + '</td>' + '<td class="datatdr">' +
+                '<iframe style="width: 100%; height: 5000px;" scrolling="no" frameborder="0" src="' + clink + '"/>' +
+                '</td></tr></table>'
+        return displaydata(t, '100%');
+    });
+
+    setTimeout(function() {
+        gdiv.style.visibility = 'hidden'
+    }, 0);
     return true;
 }
 
@@ -394,11 +2134,13 @@ function showgraph(gcomp) {
     if (gvisible)
         return true;
     cplay.innerHTML = '&gt;';
-    pdiv.style.visibility = 'hidden';
-    pdiv.innerHTML = '';
     gdiv.style.visibility = 'visible'
     gvisible = true;
     graph.compselect(gcomp, true, cvalue, ccopy, cdelete);
+    setTimeout(function() {
+        pdiv.style.visibility = 'hidden';
+        pdiv.innerHTML = '';
+    }, 0);
     return true;
 }
 
@@ -437,13 +2179,7 @@ installpalette('python', pos.rmove(0, 28
 
 // Get and display the current app
 getapp(appname, g);
-</script>
 
-<div id="footdiv" class="fsection">
-<script type="text/javascript" src="/footconfig.js"></script>
-</div>
+</script>
 
 </div>
-</body>
-</html>
-

Added: tuscany/sca-cpp/trunk/modules/edit/htdocs/home/home.b64
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/home/home.b64?rev=1188045&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/home/home.b64 (added)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/home/home.b64 Mon Oct 24 08:45:54 2011
@@ -0,0 +1 @@
+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
\ No newline at end of file

Copied: tuscany/sca-cpp/trunk/modules/edit/htdocs/home/home.png (from r1175987, tuscany/sca-cpp/trunk/modules/edit/htdocs/home.png)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/home/home.png?p2=tuscany/sca-cpp/trunk/modules/edit/htdocs/home/home.png&p1=tuscany/sca-cpp/trunk/modules/edit/htdocs/home.png&r1=1175987&r2=1188045&rev=1188045&view=diff
==============================================================================
    (empty)

Copied: tuscany/sca-cpp/trunk/modules/edit/htdocs/home/index.html (from r1175987, tuscany/sca-cpp/trunk/modules/edit/htdocs/public/oops.html)
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/home/index.html?p2=tuscany/sca-cpp/trunk/modules/edit/htdocs/home/index.html&p1=tuscany/sca-cpp/trunk/modules/edit/htdocs/public/oops.html&r1=1175987&r2=1188045&rev=1188045&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/public/oops.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/home/index.html Mon Oct 24 08:45:54 2011
@@ -17,48 +17,47 @@
  * specific language governing permissions and limitations
  * under the License.    
 -->
-<html manifest="/cache-manifest.cmf">
-<head>
-<title>Oops</title>
-<meta name="viewport" content="width=device-width user-scalable=no initial-scale=1.0"/>
-<meta name="apple-mobile-web-app-capable" content="yes"/>
-<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
-<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
-<script type="text/javascript" src="/all-min.js"></script>
-<script type="text/javascript" src="/menu.js"></script>
-</head>
-<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();">
 <div id="bodydiv" class="bodydiv">
 
-<div id="headdiv" class="hsection">
-<script type="text/javascript" src="/headconfig.js"></script>
-</div>
-
-<div id="menu"></div>
-
 <table style="width: 100%;">
 <tr><td><h2><span id="h1"></span></h2></td></tr>
 </table>
 
 <div style="margin-left: auto; margin-right: auto; text-align: center;">
-<div class="hd2">Oops, something went wrong...</div>
+
+<div id="maintitle" style="font-size: 150%;"></div>
+
+<div id="maindiagram"><div id="diagram" style="width: 320px; height: 280px; padding: 0px; margin: 0px auto;"></div></div>
+
+<input type="button" class="greenbutton" style="font-size: 150%; font-weight: bold; font-style: italic; padding: 10px;" id="getstarted" title="Get Started" value="Get Started"/>
+
+<br/><br/>
+<div>Requires Safari 5+, Chrome 11+, Firefox 4+, IE 9+</div>
+
 </div>
 
 <script type="text/javascript">
-ui.initbody();
 
-// Set page title
-$('h1').innerHTML = hometitle(window.location.hostname);
+// Set page titles
+document.title = ui.windowtitle(location.hostname);
+$('h1').innerHTML = ui.hometitle(location.hostname);
+
+$('maintitle').innerHTML = isNil(config.maintitle)? 'Simple App Builder' : config.maintitle;
+$('getstarted').onclick = function() {
+    return ui.navigate('/#view=store', '_view');
+};
+
+// Display the main diagram
+var diagram = $('diagram');
+diagram.style.background = 'url(\'' + ui.b64img(appcache.get('/home/home.b64')) + '\')';
+var bgpos = 0;
+setInterval(function() {
+    bgpos = bgpos -280;
+    if (bgpos == -2800)
+        bgpos = 0;
+    diagram.style.backgroundPosition = '0px ' + ui.pixpos(bgpos);
+}, 2000);
 
-// Load the menu bar
-if (!issubdomain(window.location.hostname))
-    displaymenu();
 </script>
 
-<div id="footdiv" class="fsection">
-<script type="text/javascript" src="/footconfig.js"></script>
-</div>
-
 </div>
-</body>
-</html>



Mime
View raw message