You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by js...@apache.org on 2011/05/23 04:28:47 UTC

svn commit: r1126297 [1/2] - in /tuscany/sca-cpp/trunk: ./ modules/edit/htdocs/ modules/edit/htdocs/app/ modules/edit/htdocs/clone/ modules/edit/htdocs/create/ modules/edit/htdocs/data/ modules/edit/htdocs/graph/ modules/edit/htdocs/login/ modules/edit...

Author: jsdelfino
Date: Mon May 23 02:28:47 2011
New Revision: 1126297

URL: http://svn.apache.org/viewvc?rev=1126297&view=rev
Log:
Simplify page navigations and optimize layout and event handling on touch devices. Optimize caching and minimize Ajax calls.

Added:
    tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf.off
Removed:
    tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf
Modified:
    tuscany/sca-cpp/trunk/.gitignore
    tuscany/sca-cpp/trunk/modules/edit/htdocs/app/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf
    tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/create/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/data/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
    tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/login/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/logout/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/page/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/page/page.js
    tuscany/sca-cpp/trunk/modules/edit/htdocs/stats/index.html
    tuscany/sca-cpp/trunk/modules/edit/htdocs/store/index.html

Modified: tuscany/sca-cpp/trunk/.gitignore
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/.gitignore?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/.gitignore (original)
+++ tuscany/sca-cpp/trunk/.gitignore Mon May 23 02:28:47 2011
@@ -57,6 +57,7 @@ config.sub
 config.status
 config.js
 all.js
+intro*.png
 depcomp
 install-sh
 ltmain.sh

Added: tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf.off
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf.off?rev=1126297&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf.off (added)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf.off Mon May 23 02:28:47 2011
@@ -0,0 +1,25 @@
+CACHE MANIFEST
+
+# Common resources
+/all-min.js
+/config.js
+/ui-min.css
+
+# App resources
+/
+/app.html
+/data/index.html
+/favicon.ico
+/public/app.png
+/public/iframe.html
+/public/img.png
+/public/notauth.html
+/public/notfound.html
+/public/notyet.html
+/public/oops.html
+/public/touchicon.png
+/robots.txt
+
+NETWORK:
+*
+

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/app/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/app/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/app/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/app/index.html Mon May 23 02:28:47 2011
@@ -17,7 +17,7 @@
  * specific language governing permissions and limitations
  * under the License.    
 -->
-<html manifest="/cache-manifest.cmf">
+<html>
 <head>
 <title>App</title>
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/> 
@@ -37,20 +37,25 @@ document.title = window.location.hostnam
 
 <div id="app"></div>
 
-<span id="appFrame"></span>
+<span id="appbuffer"></span>
+<span id="appebuffer"></span>
 
 </div>
 
 <script type="text/javascript">
-if (ui.isIE()) $('bodydiv').style.right = -20;
 
 /**
- * Start, stop, timer and geolocation components.
+ * The main app div.
+ */
+var appdiv = $('app');
+
+/**
+ * Start, stop, timer and location components.
  */
 var startcomp = sca.httpclient('start', '/start');
 var stopcomp = sca.httpclient('stop', '/stop');
 var timercomp = sca.httpclient('timer', '/timer');
-var geolocationcomp = sca.httpclient('geolocation', '/geolocation');
+var locationcomp = sca.httpclient('location', '/location');
 
 /**
  * Find a named value in a tree of elements.
@@ -146,13 +151,13 @@ function setwidgetvalue(e, dv) {
         return t;
     }
     if (e.className == 'list') {
-        var t = ui.datalist(mklist(dv));
-        car(childElements(e)).innerHTML = t;
+        var t = ui.datalist(isNil(dv)? mklist() : mklist(dv));
+        e.innerHTML = t;
         return t;
     }
     if (e.className == 'table') {
-        var t = ui.datatable(mklist(dv));
-        car(childElements(e)).innerHTML = t;
+        var t = ui.datatable(isNil(dv)? mklist() : mklist(dv));
+        e.innerHTML = t;
         return t;
     }
     if (e.className == 'link') {
@@ -190,7 +195,7 @@ function displaydata(l) {
         return e;
     }
 
-    map(updatewidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID($('app'), 'page').childNodes)));
+    map(updatewidget, filter(function(e) { return !isNil(e.id) && e.id.substring(0, 5) != 'page:'; }, nodeList(ui.elementByID(appdiv, 'page').childNodes)));
     return true;
 }
 
@@ -219,10 +224,11 @@ function displaydoc(doc) {
 function bindwidgethandler(e) {
     if (e.className == 'button') {
         var b = car(childElements(e));
-        b.onclick = function() { return buttonClickHandler(e.id); };
+        b.name = e.id;
+        b.onclick = function() { return buttonClickHandler(b.value); };
         return e;
     }
-    if (e.className == 'button' || e.className == 'entry' || e.className == 'password' || e.className == 'checkbox') {
+    if (e.className == 'entry' || e.className == 'password' || e.className == 'checkbox') {
         car(childElements(e)).name = e.id;
         return e;
     }
@@ -263,6 +269,15 @@ function fixupwidget(e) {
 }
 
 /**
+ * Set initial value of a widget.
+ */
+function initwidget(e) {
+    if (!isNil(e.id) && e.id.substring(0, 5) != 'page:')
+        setwidgetvalue(e, mklist());
+    return e;
+}
+
+/**
  * Get app data from the main app page component.
  */
 function getpagedata() {
@@ -291,6 +306,7 @@ function getpagedata() {
 
         // Initial setup of a widget
         function setupwidget(e) {
+            initwidget(e);
             fixupwidget(e);
             bindwidgethandler(e);
         }
@@ -298,17 +314,24 @@ function getpagedata() {
         // Get the component app data
         var doc = startcomp.get(window.location.search);
         try {
-            $('app').innerHTML = $('appFrame').contentDocument.body.innerHTML;
+            var appFrame = $('appFrame');
+            if (!isNil(appFrame.contentDocument.body)) {
+                appdiv.innerHTML = appFrame.contentDocument.body.innerHTML;
+            } else {
+                $('appebuffer').appendChild(appFrame.contentDocument.documentElement);
+                appdiv.innerHTML = appebuffer.innerHTML;
+                appebuffer.innerHTML = '';
+            }
 
             // Initial setup of the widgets
-            map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID($('app'), 'page').childNodes)));
+            map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID(appdiv, 'page').childNodes)));
 
             // Display data on the page
             displaypage(doc);
 
             // Get and eval the optional timer and location watch setup scripts
             evalcompinit(timercomp.get('setup'));
-            evalcompinit(geolocationcomp.get('setup'));
+            evalcompinit(locationcomp.get('setup'));
             return true;
 
         } catch(e) {
@@ -339,7 +362,7 @@ function compquery() {
         return append(nodeList(n.childNodes), reduce(append, mklist(), map(childrenList, nodeList(n.childNodes))));
     }
 
-    var args = map(queryarg, filter(function(e) { return !isNil(e.id) && !isNil(inputvalue(e)); }, childrenList(ui.elementByID($('app'), 'page'))));
+    var args = map(queryarg, filter(function(e) { return !isNil(e.id) && !isNil(inputvalue(e)); }, childrenList(ui.elementByID(appdiv, 'page'))));
 
     // Append current location properties if known
     if (!isNil(geoposition)) {
@@ -378,6 +401,7 @@ function intervalHandler() {
  * Setup an interval timer.
  */
 function setupIntervalHandler(msec) {
+    intervalHandler();
     try {
         return setInterval(intervalHandler, msec);
     } catch(e) {
@@ -394,7 +418,7 @@ var geoposition = null;
 function locationHandler(pos) {
     try {
         geoposition = pos;
-        return getcompdata(geolocationcomp, compquery());
+        return getcompdata(locationcomp, compquery());
     } catch(e) {
         locationErrorHandler(e);
     }
@@ -431,7 +455,7 @@ function setupLocationHandler() {
 }
 
 // Load the app frame
-$('app').innerHTML = '<iframe id="appFrame" class="widgetFrame" src="app.html" onload="getpagedata()"></iframe>';
+$('appbuffer').innerHTML = '<iframe id="appFrame" class="widgetframe" src="app.html" onload="getpagedata()"></iframe>';
 
 </script>
 </body>

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf Mon May 23 02:28:47 2011
@@ -1,36 +1,37 @@
 CACHE MANIFEST
 
 # Common resources
-all-min.js
-config.js
-ui-min.css
+/all-min.js
+/config.js
+/ui-min.css
 
 # App resources
-app/index.html
-clone/index.html
-data/index.html
-create/index.html
-data/index.html
-favicon.ico
-graph/graph.js
-graph/index.html
-home.png
-index.html
-menu.js
-page/index.html
-page/page.js
-public/app.png
-public/grid72.png
-public/iframe.html
-public/img.png
-public/notauth.html
-public/notfound.html
-public/notyet.html
-public/oops.html
-public/touchicon.png
-robots.txt
-stats/index.html
-store/index.html
+/
+/account/
+/app/
+/clone/
+/data/
+/create/
+/data/
+/favicon.ico
+/graph/graph.js
+/graph/
+/home.png
+/menu.js
+/page/
+/page/page.js
+/public/app.png
+/public/grid72.png
+/public/iframe.html
+/public/img.png
+/public/notauth.html
+/public/notfound.html
+/public/notyet.html
+/public/oops.html
+/public/touchicon.png
+/robots.txt
+/stats/
+/store/
 
 NETWORK:
 *

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/clone/index.html Mon May 23 02:28:47 2011
@@ -36,7 +36,7 @@
 
 <table style="width: 100%;">
 <tr>
-<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
+<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
 </tr>
 </table>
 
@@ -49,7 +49,7 @@
 <form id="cloneAppForm" style="position: absolute; top: 90px; left: 0px;">
 <table style="width: 100%;">
 <tr><td><b>New App Name:</b></td></tr>
-<tr><td><input type="text" id="appName" size="15" placeholder="Your app name"/>&nbsp;<span id="appDomain"></span></td></tr>
+<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/>&nbsp;<span id="appDomain"></span></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr>
 <tr><td><img src="/public/app.png" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr>
@@ -89,11 +89,11 @@ function applink(appname) {
 // Set page titles
 var tclone = isNil(config.clone)? 'Clone' : config.clone;
 document.title = windowtitle(window.location.hostname) + ' - ' + tclone + ' - ' + appname;
-$('h1').innerHTML = hometitle(window.location.hostname);
-$('appNameHeader').innerHTML = ' - <a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
+//$('h1').innerHTML = hometitle(window.location.hostname);
+$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '.' + window.location.hostname + '</a>';
 $('th').innerHTML = tclone + ' this App';
 $('cloneAppOKButton').value = tclone;
-$('cloneAppOKButton').title = tclone + ' the app';
+$('cloneAppOKButton').title = tclone + ' this app';
 
 // Load the menu bar
 displaymenu();
@@ -106,7 +106,7 @@ ui.showbody();
 
 // Init service references
 var editWidget = sca.component("EditWidget");
-var dashboard = sca.reference(editWidget, "dashboard");
+var dashboards = sca.reference(editWidget, "dashboards");
 var apps = sca.reference(editWidget, "apps");
 
 /**
@@ -138,11 +138,15 @@ $('cloneAppForm').onsubmit = function() 
     var name = $('appName').value;
     if (name == '')
         return false;
+
+    // Clone the app
     var title = $('appTitle').value;
     var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", appname)));
     var entry = atom.writeATOMEntry(valuesToElements(app));
-    dashboard.put(name, car(entry));
-    window.open('/store/', '_self');
+    dashboards.put(name, car(entry));
+
+    // Open it in the page editor
+    window.open('/page/?app=' + name, '_self');
     return false;
 };
 
@@ -150,7 +154,7 @@ $('cloneAppForm').onsubmit = function() 
  * Cancel cloning an app.
  */
 $('cloneAppCancelButton').onclick = function() {
-    return window.open('/store/', '_self');
+    window.open('/stats/?app=' + appname, '_self');
 };
 
 // Get the current app

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/create/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/create/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/create/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/create/index.html Mon May 23 02:28:47 2011
@@ -47,7 +47,7 @@
 <form id="createAppForm" style="position: absolute; top: 90px; left: 0px;">
 <table style="width: 100%;">
 <tr><td><b>App Name:</b></td></tr>
-<tr><td><input type="text" id="appName" size="15" placeholder="Your app name"/>&nbsp;<span id="appDomain"></span></td></tr>
+<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/>&nbsp;<span id="appDomain"></span></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr>
 <tr><td><img src="/public/app.png" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr>
@@ -81,7 +81,8 @@ ui.showbody();
 
 // Init service references
 var editWidget = sca.component("EditWidget");
-var dashboard = sca.reference(editWidget, "dashboard");
+var dashboards = sca.reference(editWidget, "dashboards");
+var apps = sca.reference(editWidget, "apps");
 
 /**
  * Create an app.
@@ -90,11 +91,15 @@ $('createAppForm').onsubmit = function()
     var name = $('appName').value;
     if (name == '')
         return false;
+
+    // Clone the '.new' app template
     var title = $('appTitle').value;
-    var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", name)));
+    var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", 'new')));
     var entry = atom.writeATOMEntry(valuesToElements(app));
-    dashboard.put(name, car(entry));
-    window.open('/store/', '_self');
+    dashboards.put(name, car(entry));
+
+    // Open it in the page editor
+    window.open('/page/?app=' + name, '_self');
     return false;
 };
 

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/data/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/data/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/data/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/data/index.html Mon May 23 02:28:47 2011
@@ -35,23 +35,25 @@ document.title = 'View - ' + window.loca
 <body class="delayed" onorientationchange="ui.reload();">
 
 <div id="bodydiv" style="position: absolute; top: 0px; left: 0px; right: 0px;">
-
+<div id="compLinkHeader" style="margin-top: 4px; margin-bottom: 4px;"></div>
+<div id="datadiv" style="position: relative; left: 0px; right: 0px;">
 </div>
 
 <script type="text/javascript">
-if (ui.isIE()) $('bodydiv').style.right = -20;
+
+// Get the component name
+var cname = ui.queryParams()['component'];
 
 /**
  * The current component.
  */
-var cname = ui.queryParams()['component'];
 var comp = sca.component(cname);
 
 /**
  * Display an HTML element.
  */
 function display(e) {
-    $('bodydiv').innerHTML = e;
+    $('datadiv').innerHTML = e;
 
     ui.showbody();
     return true;

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js Mon May 23 02:28:47 2011
@@ -41,6 +41,8 @@ graph.colors.red = '#ff0000';
 graph.colors.white = '#ffffff';
 graph.colors.yellow = '#ffff00';
 
+graph.colors.link = '#598edd';
+
 graph.colors.orange1 = '#ffbb00';
 graph.colors.green1 = '#96d333';
 graph.colors.blue1 = '#00c3c9';
@@ -54,7 +56,6 @@ graph.colors.lightgray1 = '#dcdcdc'
  * Default positions and sizes.
  */
 var palcx = 2500;
-var trashcx = 2480;
 var proxcx = 20;
 var proxcy = 20;
 var buttoncx = 65;
@@ -150,53 +151,22 @@ graph.mkgraph = function(pos, cvalue, ca
      */
     div.onmousedown = function(e) {
 
-        // Find draggable component
-        graph.dragging = draggable(e.target);
-        graph.selected = graph.dragging;
-        if (graph.dragging == null) {
+        // On mouse controlled devices, engage the click component selection
+        // logic right away
+        if (typeof e.touches == 'undefined')
+            div.onclick(e);
 
-            // Reset current selection
-            cvalue.value = '';
-            cvalue.disabled = true;
-            cdelete.disabled = true;
-
-            // Trigger component select event
-            svg.oncompselect('');
+        // Find draggable component
+        var dragging = draggable(e.target);
+        if (dragging == null || dragging != graph.selected)
             return true;
-        }
-
-        // Clone component from the palette
-        var compos = scdl.composite(svg.compos);
-        if (graph.dragging.id.substring(0, 8) == 'palette:') {
-            graph.dragging = graph.clonepalette(graph.dragging, compos);
-            graph.selected = graph.dragging;
-
-            // Move into the editing area and hide the palette
-            var gpos = graph.relpos(graph.dragging);
-            graph.move(graph.dragging, graph.mkpath().move(gpos.xpos() + palcx, gpos.ypos()));
-            div.style.left = ui.pixpos(palcx * -1);
-        }
-
-        // Cut wire to component
-        if (graph.dragging.parentNode != svg)
-            setElement(compos, graph.sortcompos(graph.cutwire(graph.dragging, compos, svg)));
-
-        // Bring component to the top
-        graph.bringtotop(graph.dragging, svg);
+        graph.dragging = dragging;
 
         // Remember current mouse position
         var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
         graph.dragX = pos.screenX;
         graph.dragY = pos.screenY;
 
-        // Update the component name and property value fields
-        cvalue.value = graph.hasproperty(graph.selected.comp)? graph.property(graph.selected.comp) : graph.selected.id;
-        cvalue.disabled = false;
-        cdelete.disabled = false;
-        
-        // Trigger component select event
-        svg.oncompselect(graph.selected.id);
-
         if (e.preventDefault)
             e.preventDefault();
         else
@@ -216,45 +186,28 @@ graph.mkgraph = function(pos, cvalue, ca
 
         if (graph.dragging.parentNode == svg && graph.dragging.id.substring(0, 8) != 'palette:') {
             var gpos = graph.relpos(graph.dragging);
-            if (gpos.xpos() >= trashcx) {
-
-                // If component close enough to editing area, move it there
-                if (gpos.xpos() < palcx)
-                    graph.move(graph.dragging, graph.mkpath().move(palcx, gpos.ypos()));
-
-                // Add new dragged component to the composite
-                if (isNil(graph.dragging.compos)) {
-                    var compos = scdl.composite(svg.compos);
-                    setElement(compos, graph.sortcompos(graph.addcomp(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)));
+            // Add new dragged component to the composite
+            if (isNil(graph.dragging.compos)) {
+                var compos = scdl.composite(svg.compos);
+                setElement(compos, graph.sortcompos(graph.addcomp(graph.dragging.comp, compos)));
+                graph.dragging.compos = svg.compos;
+            }
 
-                // 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))));
-                }
-
-            } else {
-
-                // Discard component dragged out of composite
-                svg.removeChild(graph.dragging);
-                if (!isNil(graph.dragging.compos)) {
-                    var compos = scdl.composite(svg.compos);
-                    setElement(compos, graph.sortcompos(graph.clonerefs(graph.gcollect(graph.removecomp(graph.dragging.comp, compos)))));
-                }
+            // Update component position
+            setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, svg)));
 
-                // Reset current selection
-                graph.selected = null;
-                cvalue.value = '';
-                cvalue.disabled = true;
-                cdelete.disabled = true;
+            // 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))));
+            }
 
-                // Trigger component select event
-                svg.oncompselect('');
+            // Snap top level component position to grid
+            if (graph.dragging.parentNode == svg) {
+                var gpos = graph.relpos(graph.dragging);
+                graph.move(graph.dragging, graph.mkpath().move(graph.gridsnap(gpos.xpos()), graph.gridsnap(gpos.ypos())));
+                setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, svg)));
             }
         }
 
@@ -262,7 +215,14 @@ graph.mkgraph = function(pos, cvalue, ca
         graph.dragging = null;
 
         // Refresh the composite
-        graph.refresh(svg);
+        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, cdelete);
+
+        // Trigger component select event
+        svg.oncompselect(graph.selected);
 
         // Trigger composite change event
         svg.oncomposchange(false);
@@ -273,13 +233,79 @@ graph.mkgraph = function(pos, cvalue, ca
     div.ontouchend = div.onmouseup;
 
     // Handle a mouse click event.
-    div.onclick = function(e) {
-        if (graph.dragging == null && (e.target == div || e.target == svg)) {
+    div.onclick = svg.onclick = function(e) {
+
+        // Find selected component
+        var selected = draggable(e.target);
+        if (selected == null) {
+            if (graph.selected != null) {
+
+                // Reset current selection
+                graph.compselect(graph.selected, false, cvalue, cdelete);
+                graph.selected = null;
+
+                // Trigger component select event
+                svg.oncompselect(null);
+            }
 
             // Dismiss the palette
-            if (ui.numpos(div.style.left) != (palcx * -1))
+            if (e.target == div || e.target == svg && ui.numpos(div.style.left) != (palcx * -1))
             	div.style.left = ui.pixpos(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, cdelete);
+
+        // Clone component from the palette
+        if (selected.id.substring(0, 8) == 'palette:') {
+            var compos = scdl.composite(svg.compos);
+            graph.selected = graph.clonepalette(selected, compos, svg);
+            setElement(compos, graph.sortcompos(graph.addcomp(graph.selected.comp, compos)));
+            graph.selected.compos = svg.compos;
+
+            // Move into the editing area and hide the palette
+            var gpos = graph.relpos(graph.selected);
+            graph.move(graph.selected, graph.mkpath().move(gpos.xpos() + palcx, gpos.ypos()));
+            div.style.left = ui.pixpos(palcx * -1);
+
+            // Update component position
+            setElement(graph.selected.comp, graph.movecomp(graph.selected.comp, graph.abspos(graph.selected, svg)));
+
+            // Refresh the composite
+            var nodes = graph.refresh(svg);
+
+            // Reselect the previously selected component
+            graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes);
+            graph.compselect(graph.selected, true, cvalue, 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, cdelete);
+
+            // Trigger component select event
+            svg.oncompselect(graph.selected);
         }
+
+        if (e.preventDefault)
+            e.preventDefault();
+        else
+            e.returnValue = false;
         return true;
     }
 
@@ -290,15 +316,28 @@ graph.mkgraph = function(pos, cvalue, ca
         if (graph.dragging == null)
             return true;
 
+        // Get the mouse position
+        var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
+        if (pos.screenX == graph.dragX && pos.screenY == graph.dragY)
+            return 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 pos = typeof e.touches != "undefined" ? e.touches[0] : e;
         var newX = gpos.xpos() + (pos.screenX - graph.dragX);
         var newY = gpos.ypos() + (pos.screenY - graph.dragY);
-        if (newX >= 0)
+        if (newX >= palcx)
             graph.dragX = pos.screenX;
         else
-            newX = 0;
+            newX = palcx;
         if (newY >= 0)
             graph.dragY = pos.screenY;
         else
@@ -319,19 +358,25 @@ graph.mkgraph = function(pos, cvalue, ca
     cvalue.onchange = function() {
         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);
+            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)));
 
-            // Trigger component select event
-            svg.oncompselect(graph.selected.id);
-
             // Refresh the composite
-            graph.refresh(svg);
+            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, cdelete);
+
+            // Trigger component select event
+            svg.oncompselect(graph.selected);
 
             // Trigger composite change event
             svg.oncomposchange(true);
@@ -345,7 +390,14 @@ graph.mkgraph = function(pos, cvalue, ca
             cvalue.disabled = !graph.hasproperty(graph.selected.comp);
 
             // Refresh the composite
-            graph.refresh(svg);
+            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, cdelete);
+
+            // Trigger component select event
+            svg.oncompselect(graph.selected);
 
             // Trigger composite change event
             svg.oncomposchange(true);
@@ -359,23 +411,23 @@ graph.mkgraph = function(pos, cvalue, ca
     cdelete.onclick = function() {
         if (graph.selected == null)
             return false;
-        if (graph.selected.id.substring(0, 8) != 'palette:' && !isNil(graph.selected.compos)) {
+        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, cdelete);
             graph.selected = null;
-            cvalue.value = '';
-            cvalue.disabled = true;
-            cdelete.disabled = true;
 
             // Refresh the composite
             graph.refresh(svg);
 
             // Trigger component select event
-            svg.oncompselect('');
+            svg.oncompselect(null);
 
             // Trigger composite change event
             svg.oncomposchange(true);
@@ -512,9 +564,40 @@ graph.proptitlewidth = function(comp) {
 };
 
 /**
+ * Draw a component shape selection.
+ */
+graph.compselect = function(g, s, cvalue, cdelete) {
+    if (isNil(g) || !s) {
+        if (!isNil(cvalue)) {
+            cvalue.value = '';
+            cvalue.disabled = true;
+        }
+        if (!isNil(cdelete))
+            cdelete.disabled = true;
+        if (isNil(g))
+            return true;
+        g.contour.setAttribute('stroke', graph.colors.gray);
+        g.contour.setAttribute('stroke-opacity', '0.20');
+        return true;
+    }
+
+    if (!isNil(cvalue)) {
+        cvalue.value = graph.hasproperty(g.comp)? graph.property(g.comp) : g.id;
+        cvalue.disabled = false;
+    }
+    if (!isNil(cdelete))
+        cdelete.disabled = false;
+
+    g.contour.setAttribute('stroke', graph.colors.link);
+    g.contour.setAttribute('stroke-opacity', '0.80');
+    g.parentNode.appendChild(g);
+    return true;
+};
+
+/**
  * Return a node representing a component.
  */
-graph.compnode = function(comp, cassoc, pos) {
+graph.compnode = function(comp, cassoc, pos, parentg) {
 
     // Make the component and property title elements
     var title = graph.comptitle(comp);
@@ -554,10 +637,32 @@ graph.compnode = function(comp, cassoc, 
     g.refpos = reverse(path.refpos);
     g.svcpos = reverse(path.svcpos);
 
+    // Store the contour in the component shape
+    g.contour = contour;
+
+    // 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) {
@@ -598,6 +703,10 @@ graph.mkbutton = function(t, pos) {
     g.appendChild(shape);
     g.appendChild(contour);
     g.appendChild(title);
+
+    // Store the contour in the button shape
+    g.contour = contour;
+
     return g;
 };
 
@@ -605,7 +714,7 @@ graph.mkbutton = function(t, pos) {
  * Return the relative position of a node.
  */
 graph.relpos = function(e) {
-    var pmatrix = e.parentNode.getCTM();
+    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);
@@ -1048,12 +1157,20 @@ graph.buttonpath = function(t) {
 /**
  * Render a SCDL composite into a list of component nodes.
  */
-graph.composite = function(compos, pos) {
+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.
      */
@@ -1124,7 +1241,7 @@ graph.composite = function(compos, pos) 
         }
 
         // Compute the component shape
-        var gcomp = graph.compnode(comp, cassoc, pos);
+        var gcomp = graph.compnode(comp, cassoc, pos, g);
 
         // Render the components wired to the component references
         var rrefs = graph.rrefs(comp);
@@ -1201,10 +1318,17 @@ graph.composite = function(compos, pos) 
     // Render the promoted service components
     var rproms = renderproms(proms, cassoc, pos.clone().rmove(tabsz * 4, tabsz * 4));
 
-    if (name == 'palette') {
+    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 = graph.relpos(r);
+                graph.move(r, graph.mkpath().move(gpos.xpos() - palcx, gpos.ypos()));
+                return r;
+            }, rproms);
 
-        // Prefix ids of palette component elements with 'palette:'
-        return map(function(r) { r.id = 'palette:' + r.id; return r; }, rproms);
     } else {
 
         // Link app component elements to the containing composite
@@ -1215,11 +1339,14 @@ graph.composite = function(compos, pos) 
 /**
  * Return a component unique id.
  */
-graph.ucid = function(prefix, compos) {
+graph.ucid = function(prefix, compos, clone) {
 
     // Build an assoc list keyed by component name
     var comps = map(function(c) { return mklist(scdl.name(c), c); }, namedElementChildren("'component", compos));
 
+    if (!clone && isNil(assoc(prefix, comps)))
+        return prefix;
+
     /**
      * Find a free component id.
      */
@@ -1229,26 +1356,23 @@ graph.ucid = function(prefix, compos) {
         return ucid(p, id + 1);
     }
 
-    if (isNil(assoc(prefix, comps)))
-        return prefix;
-
-    return ucid(prefix == ''? 'comp' : prefix, 2);
+    return ucid(prefix == ''? 'comp' : prefix, 1);
 };
 
 /**
  * Clone a palette component node.
  */
-graph.clonepalette = function(e, compos) {
+graph.clonepalette = function(e, compos, g) {
 
-    // Clone the SCDL component and give it a unique name
-    var comp = append(mklist(element, "'component", mklist(attribute, "'name", graph.ucid(scdl.name(e.comp), compos))),
+         // 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, true))),
                 filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e.comp)));
-    var x = '<composite xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1">' + writeXML(mklist(comp), false) + '</composite>';
-    var compos = readXML(mklist(x));
-    comp = car(scdl.components(compos));
+    var x = '<composite>' + writeXML(mklist(wcomp), false) + '</composite>';
+    var rcompos = readXML(mklist(x));
+    var comp = car(scdl.components(rcompos));
 
     // Make a component node
-    var gcomp = graph.compnode(comp, mklist(), graph.mkpath());
+    var gcomp = graph.compnode(comp, mklist(), graph.mkpath(), g);
     graph.move(gcomp, graph.relpos(e));
     e.parentNode.appendChild(gcomp);
 
@@ -1261,12 +1385,19 @@ graph.clonepalette = function(e, compos)
 graph.movecomp = function(comp, pos) {
     if (isNil(pos))
         return append(mklist(element, "'component"),
-                filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'t:x" || attributeName(e) == "'t:y")); }, elementChildren(comp)));
-    return append(mklist(element, "'component", mklist(attribute, "'t:x", '' + (pos.xpos() - palcx)), mklist(attribute, "'t:y", '' + pos.ypos())),
-            filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'t:x" || attributeName(e) == "'t:y")); }, elementChildren(comp)));
+                filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'x" || attributeName(e) == "'y")); }, elementChildren(comp)));
+    return append(mklist(element, "'component", mklist(attribute, "'x", '' + (pos.xpos() - 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;
+}
+
+/**
  * Sort elements of a composite.
  */
 graph.sortcompos = function(compos) {
@@ -1356,7 +1487,7 @@ graph.clonerefs = function(compos) {
                 // 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, "'t:clonable", "true"))));
+                    mklist(mklist(element, "'reference", mklist(attribute, "'name", scdl.name(car(refs))), mklist(attribute, "'clonable", "true"))));
                 return append(mklist(element, "'component"), cc);
             
             }, elementChildren(compos)));
@@ -1535,10 +1666,11 @@ graph.hide = function(g) {
  */
 graph.refresh = function(g) {
 
-    // Remove nodes and redisplay the composite associated with the graph
+    // 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));
-    graph.display(graph.composite(g.compos, graph.mkpath().move(palcx,0)), g);
-    return g;
+
+    // Redisplay the composite associated with the graph
+    return graph.display(graph.composite(g.compos, graph.mkpath().move(palcx,0), false, g), g);
 };
 
 /**

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=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/graph/index.html Mon May 23 02:28:47 2011
@@ -37,32 +37,45 @@
 
 <table style="width: 100%;">
 <tr>
-<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
-<td style="vertical-align: middle; text-align: right;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
+<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
+<td style="vertical-align: middle; text-align: right; padding-right: 2px;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
 </tr>
 </table>
 
 <table style="width: 100%;">
 <tr>
-<th class="thr thl" style="padding-left: 2px; padding-right: 2px;">
-<input id="compValue" type="text" value="" title="Component value" placeholder="Name" style="position: relative; width: 170px;"/>
-<span id="deleteComponentButton" title="Delete a component" class="redbutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">-</span>
-<span id="addComponentButton" title="Add a component" class="greenbutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">+</span>
-<span id="playComponentButton" title="View component value" class="bluebutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
+<th class="thr thl" style="padding-left: 2px; padding-right: 2px; width: 100%">
+<input id="compValue" type="text" value="" title="Component value" autocapitalize="off" placeholder="Value" style="position: relative; width: 100%;"/>
+</th>
+
+<th class="thl thr" style="text-align: right; padding-right: 2px;">
+<span id="deleteCompButton" title="Delete a component" class="redbutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">-</span>
+
+<span id="addCompButton" title="Add a component" class="greenbutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">+</span>
+
+<span id="playCompButton" title="View component value" class="bluebutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
 </th>
 </tr>
 </table>
 
-<div id="dataDiv" style="position:absolute; top: 95px; left: 0px; right: 0px; height: 5000px; visibility: hidden">
+<div id="playdiv" style="position:absolute; top: 95px; left: 0px; right: 0px; height: 5000px; visibility: hidden">
 </div>
 
 </div>
 
 <script type="text/javascript">
+
 // Get the app name
 var appname = ui.queryParams()['app'];
-if (isNil(appname))
-    window.open('/', '_self');
+var ispalette = false;
+if (isNil(appname)) {
+    appname = ui.queryParams()['palette'];
+    if (isNil(appname))
+        window.open('/', '_self');
+
+    // Edit a palette instead of a regular app
+    ispalette = true;
+}
 
 /**
  * Return the link to an app.
@@ -79,41 +92,65 @@ function applink(appname) {
 
 // Set page titles
 document.title = windowtitle(window.location.hostname) + ' - ' + (isNil(config.compose)? 'Composition' : config.compose) + ' - ' + appname;
-$('h1').innerHTML = hometitle(window.location.hostname);
-$('appNameHeader').innerHTML = ' - <a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
+//$('h1').innerHTML = hometitle(window.location.hostname);
+$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '.' + window.location.hostname + '</a>';
 
 // Load the menu bar
 displaymenu();
 
+/**
+ * Component value field, add, delete and play buttons.
+ */
+var cvalue = $('compValue');
+var cadd = $('addCompButton');
+var cdelete = $('deleteCompButton');
+var cplay = $('playCompButton');
+
+/**
+ * Adjust field size.
+ */
+function resizeFields() {
+    cvalue.style.width = '0px';
+    cvalue.style.width = ui.pixpos(cvalue.parentNode.clientWidth - 18);
+    return true;
+}
+
+resizeFields();
+window.onresize = resizeFields;
+
 // Show the page
 ui.showbody();
 
 // Init componnent references
 var editWidget = sca.component("EditWidget");
 var palettes = sca.reference(editWidget, "palettes");
-var composites = sca.reference(editWidget, "composites");
+var composites = sca.reference(editWidget, ispalette? "palettes" : "composites");
 
 // Setup remote log
 //rconsole = sca.defun(sca.reference(editWidget, "log"), "log");
 
 /**
- * The current app composite, corresponding saved XML content and component name.
+ * Track the current app composite and corresponding saved XML content.
  */
 var savedcomposxml = '';
 var composite;
-var compname = '';
 
 /**
- * Track the composition graph and whether it's visible or not.
+ * Track the composition graph, whether it's visible or not and the selected component.
  */
 var g;
 var gdiv;
 var bg;
 var gvisible = true;
+var gcomp = null;
+var pdiv = $('playdiv');
 
-// Track the palettes
+/**
+ * Track the palettes.
+ */
 var gpalettes = new Array();
 var spalette = 'control';
+var bpalette = null;
 
 /**
  * Return the composite in an ATOM entry.
@@ -139,11 +176,13 @@ function getapp(name, g) {
         if (isNil(composite)) {
 
             // Create a default empty composite if necessary
-            var x = '<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"' +
+            var x = '<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" ' +
                 'targetNamespace="http://app" name="app"></composite>';
             composite = readXML(mklist(x));
         }
-        graph.edit(name, composite, graph.composite(composite, graph.mkpath().move(palcx,0)), oncomposchange, oncompselect, g);
+
+        // Display the composite
+        graph.edit(name, composite, graph.composite(composite, graph.mkpath().move(palcx,0), false, g), oncomposchange, oncompselect, g);
 
         // Track the saved composite XML
         savedcomposxml = car(writeXML(composite, false));
@@ -161,7 +200,7 @@ function displaypalette(name, g, palette
 
         // Get the palette from the server
         var doc = palettes.get(name);
-        gpalettes[name] = graph.composite(atomcomposite(doc), graph.mkpath().move(80,0));
+        gpalettes[name] = graph.composite(atomcomposite(doc), graph.mkpath().move(2580,0), true, g);
     }
     graph.display(gpalettes[name], g);
     return true;
@@ -177,7 +216,10 @@ function installpalette(name, pos, g, bg
     b.onclick = function(e) {
 
         // Swap the selected palette
+        graph.compselect(bpalette, false);
         displaypalette(spalette, bg, palette, gpalettes);
+        bpalette = b;
+        graph.compselect(b, true, null, null);
         spalette = name;
         return displaypalette(spalette, g, palette, gpalettes);
     };
@@ -190,7 +232,10 @@ function installpalette(name, pos, g, bg
     }
 
     // Display the selected palette
-    return displaypalette(name, g, palette, gpalettes);
+    graph.compselect(b, true, null, null);
+    displaypalette(name, g, palette, gpalettes);
+
+    return b;
 }
 
 /**
@@ -202,8 +247,9 @@ function save(savexml) {
     var entry = '<entry xmlns="http://www.w3.org/2005/Atom">' +
         '<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml">' +
         savedcomposxml + '</content></entry>';
-    composites.put(appname, entry);
-    $('saveStatus').innerHTML = 'Saved';
+    composites.put(appname, entry, function(r) {
+        $('saveStatus').innerHTML = 'Saved';
+    });
     return true;
 }
 
@@ -220,15 +266,14 @@ function oncomposchange(prop) {
     if (prop)
         return save(newxml);
 
-    // Autosave other changes after 3 seconds
+    // Autosave other changes after 1 second
     $('saveStatus').innerHTML = 'Modified';
     setTimeout(function() {
-        var savexml = car(writeXML(composite, false));
-        if (savedcomposxml == savexml) {
+        if (savedcomposxml == newxml) {
             $('saveStatus').innerHTML = 'Saved';
             return false;
         }
-        return save(savexml);
+        return save(newxml);
     }, 1000);
     return true;
 }
@@ -236,7 +281,7 @@ function oncomposchange(prop) {
 /**
  * Return the link to a component value.
  */
-function compvaluelink(appname, cname) {
+function compdatalink(appname, cname) {
     if (cname == '' || isNil(cname))
         return '';
     var protocol = window.location.protocol;
@@ -249,9 +294,9 @@ function compvaluelink(appname, cname) {
 }
 
 /**
- * Return the link to a component raw data.
+ * Return the link to a component.
  */
-function compdebuglink(appname, cname) {
+function complink(appname, cname) {
     if (cname == '' || isNil(cname))
         return '';
     var protocol = window.location.protocol;
@@ -259,78 +304,81 @@ function compdebuglink(appname, cname) {
     var port = ':' + window.location.port;
     if (port == ':80' || port == ':443' || port == ':')
         port = '';
-    var link = protocol + '//' + appname + '.' + host + port + '/components/' + cname;
+    var link = protocol + '//' + appname + '.' + host + port + '/c/' + cname;
     return link;
 }
 
 /**
  * Handle a component select event.
  */
-function oncompselect(cname) {
-    if (cname == compname)
+function oncompselect(gsel) {
+    if (gsel == gcomp)
         return true;
-    compname = cname;
-    var link = compvaluelink(appname, cname);
+    gcomp = gsel;
+    var cname = isNil(gsel)? '' : gsel.id;
+    var link = compdatalink(appname, cname);
 
     function updateButton(b, v) {
         b.style.color = v? '#000000' : '#808080';
     }
 
-    updateButton($('deleteComponentButton'), link != '');
-    updateButton($('playComponentButton'), link != '');
+    updateButton(cdelete, link != '');
+    updateButton(cplay, link != '');
     return true;
 }
 
 /**
  * Show the result data of a component.
  */
-function showdata(cname) {
+function showdata(gcomp) {
     if (!gvisible)
         return true;
-    gvisible = false;
-    $('playComponentButton').innerHTML = '&lt;';
+    if (isNil(gcomp))
+        return true;
+    cvalue.value = complink(appname, gcomp.id);
+    cplay.innerHTML = '&lt;';
     gdiv.style.visibility = 'hidden'
-    var rdiv = $('dataDiv');
-    rdiv.style.visibility = 'visible';
-    rdiv.innerHTML = '<iframe id="dataFrame" style="position: relative; height: 5000px; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="' +
-                        compvaluelink(appname, cname) + '"></iframe>';
+    gvisible = false;
+    pdiv.style.visibility = 'visible';
+    pdiv.innerHTML = '<iframe id="dataFrame" style="position: relative; height: 5000px; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="' +
+                        compdatalink(appname, gcomp.id) + '"></iframe>';
     return true;
 }
 
 /**
  * Show the composition graph.
  */
-function showgraph() {
+function showgraph(gcomp) {
     if (gvisible)
         return true;
-    gvisible = true;
-    $('playComponentButton').innerHTML = '&gt;';
-    var rdiv = $('dataDiv');
-    rdiv.style.visibility = 'hidden';
-    rdiv.innerHTML = '';
+    cplay.innerHTML = '&gt;';
+    pdiv.style.visibility = 'hidden';
+    pdiv.innerHTML = '';
     gdiv.style.visibility = 'visible'
+    gvisible = true;
+    graph.compselect(gcomp, true, cvalue, cdelete);
     return true;
 }
 
 /**
- * Play the current component.
+ * Handle play component button event.
  */
-$('playComponentButton').onclick = function() {
-    if (compname == '')
+cplay.onclick = function() {
+    if (gcomp == null)
         return false;
     if (!gvisible)
-        return showgraph();
-    return showdata(compname);
+        return showgraph(gcomp);
+    return showdata(gcomp);
 }
 
 // Create editor graph area
-g = graph.mkgraph(graph.mkpath().move(-2500,95), $('compValue'), $('addComponentButton'), $('deleteComponentButton'));
+g = graph.mkgraph(graph.mkpath().move(-2500,95), cvalue, cadd, cdelete);
 gdiv = g.parentNode;
 bg = graph.mkgroup(graph.mkpath());
 
 // Install the palettes
-var pos = graph.mkpath();
-installpalette('control', pos.rmove(5,0), g, bg, spalette, gpalettes);
+var pos = graph.mkpath().move(0, 0);
+bpalette = installpalette('control', pos.rmove(5,0), g, bg, spalette, gpalettes);
 installpalette('values', pos.rmove(0,35), g, bg, spalette, gpalettes);
 installpalette('lists', pos.rmove(0, 35), g, bg, spalette, gpalettes);
 installpalette('transform', pos.rmove(0, 35), g, bg, spalette, gpalettes);

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/index.html Mon May 23 02:28:47 2011
@@ -37,20 +37,18 @@
 <table style="width: 100%;">
 <tr><td><h1><span id="h1"></span></h1></td></tr>
 </table>
-<br/>
 
 <div style="margin-left: auto; margin-right: auto; text-align: center;">
 
-<h1><span id="maintitle"><span></h1>
-<br/><br/><br/><br/>
+<div id="maintitle" style="font-size: 150%;"></div>
 
-<div id="maindiagram"></div>
-<br/><br/><br/><br/>
+<div id="maindiagram"><div id="diagram" style="width: 320px; height: 280px; background: url(home.png); padding: 0px; margin: 0px auto;"></div></div>
+<br/>
 
 <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/><br/>
-<div>Safari, Chrome, Firefox only for now.</div>
+<br/><br/>
+<div>Requires Safari 5+, Chrome 11+, Firefox 4+, IE 9+</div>
 
 </div>
 
@@ -65,13 +63,23 @@ $('h1').innerHTML = hometitle(window.loc
 displaymenu();
 
 $('maintitle').innerHTML = isNil(config.maintitle)? 'Simple App Builder' : config.maintitle;
-$('maindiagram').innerHTML = isNil(config.maindiagram)? '&lt;&lt insert diagram here &gt;&gt;' : config.maindiagram;
 $('getstarted').onclick = function() {
     return window.open('/store/', '_self');
 };
 
+// Display the main diagram
+var diagram = $('diagram');
+var bgpos = 0;
+setInterval(function() {
+    bgpos = bgpos -280;
+    if (bgpos == -2800)
+        bgpos = 0;
+    diagram.style.backgroundPosition = '0px ' + ui.pixpos(bgpos);
+}, 2000);
+
 // Show the page
 ui.showbody();
+
 </script>
 
 </body>

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/login/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/login/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/login/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/login/index.html Mon May 23 02:28:47 2011
@@ -27,13 +27,15 @@
 <link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <script type="text/javascript" src="/all-min.js"></script>
 </head>
-<body onorientationchange="ui.reload();">
+<body class="delayed" onorientationchange="ui.reload();">
+<div id="bodydiv" class="devicewidth">
+
 <h1>Sign in</h1>
 
 <form name="formSignin" onsubmit="submitSignin();" method="POST" action="/login/dologin/">
 <table border="0">
 <tr><td><b>Username:</b></td></tr>
-<tr><td><input type="text" id="httpd_username" name="httpd_username" value="" size="15" placeholder="Enter your user name" style="width: 300px;"/></td></tr>
+<tr><td><input type="text" id="httpd_username" name="httpd_username" value="" size="15" autocapitalize="off" placeholder="Enter your user name" style="width: 300px;"/></td></tr>
 <tr><td><b>Password:</b></td></tr>
 <tr><td><input type="password" name="httpd_password" value="" size="15" placeholder="Enter your password" style="width: 300px;"/></td></tr>
 <tr><td><input type="submit" value="Sign in" class="greenbutton" style="font-weight: bold;"/></td><td></td></tr>
@@ -41,7 +43,13 @@
 <input type="hidden" name="httpd_location" value="/"/>
 </form>
 
+</div>
+
 <script type="text/javascript">
+
+// Show the page
+ui.showbody();
+
 function queryParams() {
     qp = new Array();
     qs = window.location.search.substring(1).split('&');

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/logout/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/logout/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/logout/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/logout/index.html Mon May 23 02:28:47 2011
@@ -27,14 +27,22 @@
 <link rel="stylesheet" type="text/css" href="/ui-min.css"/>
 <script type="text/javascript" src="/all-min.js"></script>
 </head>
-<body onorientationchange="ui.reload();">
+<body class="delayed" onorientationchange="ui.reload();">
+<div id="bodydiv" class="devicewidth">
+
 <h1>Sign out</h1>
 
 <form name="signout" onsubmit="submitSignout();" action="/" method="GET">
 <input type="submit" id="signOut" value="Sign out" class="greenbutton" style="font-weight: bold"/>
 </form>
 
+</div>
+
 <script type="text/javascript">
+
+// Show the page
+ui.showbody();
+
 function submitSignout() {
     var reset = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';domain=.' + domainname(window.location.hostname) + ';path=/;secure=TRUE';
     document.cookie = reset;

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/page/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/page/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/page/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/page/index.html Mon May 23 02:28:47 2011
@@ -37,26 +37,28 @@
 
 <table style="width: 100%;">
 <tr>
-<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
-<td style="vertical-align: middle; text-align: right;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
+<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
+<td style="vertical-align: middle; text-align: right; padding-right: 2px;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
 </tr>
 </table>
 
 <table style="width: 100%;">
 <tr>
-<th class="thr thl" style="padding-left: 2px; padding-right: 2px;">
-<input id="widgetName" type="text" value="" title="Widget name" placeholder="Name" style="position: relative; width: 65px;"/>
-<input id="widgetText" type="text" value="" title="Widget text" placeholder="Text" style="position: relative; width: 120px;"/>
+<th class="thr thl" style="padding-left: 2px; padding-right: 2px; width: 100%;">
+<input id="widgetValue" type="text" value="" title="Widget value" autocapitalize="off" placeholder="Value" style="position: relative; width: 100%;"/>
+</th>
+
+<th class="thl thr" style="text-align: right; padding-right: 2px;">
 <span id="deleteWidgetButton" title="Delete a Widget" class="redbutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">-</span>
+
 <span id="addWidgetButton" title="Add a Widget" class="greenbutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">+</span>
-<!--
-<span id="playWidgetButton" title="View" class="bluebutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
--->
+
+<span id="playPageButton" title="View page" class="bluebutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
 </th>
 </tr>
 </table>
 
-<div id="page" style="position: absolute; top: 95px; left: -2500px; right: 0px; height: 5000px;">
+<div id="editdiv" style="position: absolute; top: 95px; left: -2500px; right: 0px; height: 5000px;">
 
 <div style="position: absolute; left: 2500px; top: 0px; right: 0px; height: 5000px; border:1px; border-style: solid; border-color: #a2bae7; background: url(/public/grid72.png);"></div>
 <div class="guide" style="position: absolute; left: 2500px; top: 0px; width: 320px; height: 460px;"></div>
@@ -85,6 +87,8 @@
 
 </div>
 
+<div id="playdiv" style="visibility: hidden; position: absolute; top: 95px; left: 0px; right: 0px; height: 5000px;"></div>
+
 <div id="buffer" style="visibility: hidden; position: absolute; top: 0px; left: 0px; width: 0px; height: 0px"></div>
 
 </div>
@@ -111,12 +115,35 @@ function applink(appname) {
 
 // Set page titles
 document.title = windowtitle(window.location.hostname) + ' - Page - ' + appname;
-$('h1').innerHTML = hometitle(window.location.hostname);
-$('appNameHeader').innerHTML = ' - <a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
+//$('h1').innerHTML = hometitle(window.location.hostname);
+$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '.' + window.location.hostname + '</a>';
 
 // Load the menu bar
 displaymenu();
 
+/**
+ * Page editor area, widget value field, add, delete and play page buttons.
+ */
+var ediv = $('editdiv');
+var evisible = true;
+var pdiv = $('playdiv');
+var wvalue = $('widgetValue');
+var wadd = $('addWidgetButton');
+var wdelete = $('deleteWidgetButton');
+var pplay = $('playPageButton');
+
+/**
+ * Adjust fields sizes.
+ */
+function resizeFields() {
+    wvalue.style.width = '0px';
+    wvalue.style.width = ui.pixpos(wvalue.parentNode.clientWidth - 18);
+    return true;
+}
+
+resizeFields();
+window.onresize = resizeFields;
+
 // Show the page
 ui.showbody();
 
@@ -138,15 +165,19 @@ function atompage(doc) {
 }
 
 /**
- * Track the current widget and page saved XHTML content.
+ * Track the current page saved XHTML content.
  */
-var widgetname = '';
 var savedpagexhtml = '';
 
 /**
+ * Track the current widget.
+ */
+var widget = null;
+
+/**
  * Get and display an app page.
  */
-function getpage(name, edit) {
+function getpage(name, ediv) {
     if (isNil(name))
         return false;
     return pages.get(name, function(doc) {
@@ -157,19 +188,19 @@ function getpage(name, edit) {
 
         // Create a default empty page if necessary
         if (isNil(el))
-            buffer.innerHTML = '<DIV id="page">\n</DIV>\n';
+            buffer.innerHTML = '<div id="page"></div>';
         else
             buffer.innerHTML = writeStrings(writeXML(atompage(doc), false));
 
         // Append page nodes to editor
         map(function(e) {
-                edit.appendChild(e);
+                ediv.appendChild(e);
                 if (!isNil(e.style))
                     e.style.left = ui.pixpos(ui.numpos(e.style.left) + 2500);
                 return page.cover(e);
             }, nodeList(buffer.childNodes[0].childNodes));
 
-        savedpagexhtml = pagexhtml();
+        savedpagexhtml = pagexhtml(ediv);
         return true;
     });
 }
@@ -177,22 +208,28 @@ function getpage(name, edit) {
 /**
  * Handle add widget button click event.
  */
-$('addWidgetButton').onclick = function(e) {
+wadd.onclick = function(e) {
     // Show the widget palette
-    $('page').style.left = ui.pixpos(0);
+    ediv.style.left = ui.pixpos(0);
 };
 
 /**
  * Return the current page XHTML content.
  */
-function pagexhtml() {
+function pagexhtml(ediv) {
 
     // Copy page DOM to hidden buffer
-    var edit = $('page');
     var buffer = $('buffer');
-    buffer.innerHTML = '<DIV id="page">\n</DIV>\n'
+    buffer.innerHTML = '<div id="page"></div>'
     var div = buffer.childNodes[0];
-    div.innerHTML = edit.innerHTML;
+
+    // Capture the nodes inside the page div
+    div.innerHTML = ediv.innerHTML;
+    var nodes = nodeList(div.childNodes);
+    map(function(e) {
+        div.removeChild(e);
+        return e;
+    }, nodes);
 
     // Filter out palette and editor artifacts, which are not
     // part of the page, as well as nodes positioned out the
@@ -204,7 +241,7 @@ function pagexhtml() {
         if (x < 0 || ui.numpos(e.style.top) < 0)
             return false;
         return true;
-    }, nodeList(div.childNodes));
+    }, nodes);
 
     // Reposition nodes
     map(function(e) {
@@ -226,8 +263,7 @@ function pagexhtml() {
         return 0;
     });
 
-    // Append them back to the div in order
-    div.innerHTML = '';
+    // Append the sorted nodes back to the div in order
     map(function(e) {
         div.appendChild(e);
         return e;
@@ -242,20 +278,20 @@ function pagexhtml() {
 /**
  * Save the current page.
  */
-function save() {
+function save(newxml) {
     $('saveStatus').innerHTML = 'Saving';
 
     // Get the current page XHTML content
-    savedpagexhtml = pagexhtml();
+    savedpagexhtml = newxml;
 
     // Update the page ATOM entry
     var entry = '<entry xmlns="http://www.w3.org/2005/Atom">' +
         '<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml">' +
-        savedpagexhtml + '</content></entry>';
+        newxml + '</content></entry>';
 
-    pages.put(appname, entry);
-    if (savedpagexhtml == pagexhtml())
+    pages.put(appname, entry, function(r) {
         $('saveStatus').innerHTML = 'Saved';
+    });
     return true;
 };
 
@@ -263,19 +299,22 @@ function save() {
  * Handle a page change event
  */
 function onpagechange(prop) {
-    if (savedpagexhtml == pagexhtml())
+    var newxml = pagexhtml(ediv);
+    if (savedpagexhtml == newxml)
         return false;
     $('saveStatus').innerHTML = 'Modified';
 
     // Save property changes right away
     if (prop)
-        return save();
+        return save(newxml);
 
-    // Autosave other changes after 3 seconds
+    // Autosave other changes after 1 second
     setTimeout(function() {
-        if (savedpagexhtml == pagexhtml())
+        if (savedpagexhtml == newxml) {
+            $('saveStatus').innerHTML = 'Saved';
             return false;
-        return save();
+        }
+        return save(newxml);
     }, 1000);
     return true;
 }
@@ -298,40 +337,68 @@ function compvaluelink(appname, cname) {
 /**
  * Handle a widget select event.
  */
-function onwidgetselect(wname) {
-    if (wname == widgetname)
+function onwidgetselect(w) {
+    if (w == widget)
         return true;
-    widgetname = wname;
-    var link = compvaluelink(appname, wname);
+    widget = w;
+    var link = compvaluelink(appname, isNil(w)? '' : w.id);
 
     function updateButton(b, v) {
         b.style.color = v? '#000000' : '#808080';
     }
 
-    updateButton($('deleteWidgetButton'), link != '');
-    //updateButton($('playWidgetButton'), link != '');
+    updateButton(wdelete, link != '');
+    return true;
+}
+
+/**
+ * Play page in a frame.
+ */
+function playpage() {
+    if (!evisible)
+        return true;
+    page.widgetselect(widget, false, wvalue, wdelete);
+    page.selected = null;
+    wvalue.value = applink(appname);
+    pplay.innerHTML = '&lt;';
+    ediv.style.visibility = 'hidden'
+    evisible = false;
+    pdiv.style.visibility = 'visible';
+    pdiv.innerHTML = '<iframe id="appFrame" style="position: relative; height: 5000px; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="' +
+                        applink(appname) + '"></iframe>';
+    return true;
+}
 
+/**
+ * Show the page editor.
+ */
+function showedit() {
+    if (evisible)
+        return true;
+    pplay.innerHTML = '&gt;';
+    pdiv.style.visibility = 'hidden';
+    pdiv.innerHTML = '';
+    ediv.style.visibility = 'visible'
+    evisible = true;
+    page.widgetselect(widget, true, wvalue, wdelete);
+    page.selected = widget;
     return true;
 }
 
 /**
- * Play the component associated with the current widget.
+ * Handle play page button event.
  */
-/*
-$('playWidgetButton').onclick = function() {
-    var link = compvaluelink(appname, widgetname);
-    if (link == '')
-        return;
-    return window.open(link, '_' + appname + '_' + widgetname);
+pplay.onclick = function() {
+    if (!evisible)
+        return showedit();
+    return playpage();
 }
-*/
 
 // Initialize the page editor
-var edit = $('page');
-page.edit(edit, $('widgetName'), $('widgetText'), $('addWidgetButton'), $('deleteWidgetButton'), onpagechange, onwidgetselect);
+page.edit(ediv, wvalue, wadd, wdelete, onpagechange, onwidgetselect);
 
 // Get and display the current app page
-getpage(appname, edit);
+getpage(appname, ediv);
 
 </script>
 </body>

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/page/page.js
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/page/page.js?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/page/page.js (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/page/page.js Mon May 23 02:28:47 2011
@@ -26,18 +26,16 @@ var page = {};
  * Default positions and sizes.
  */
 var palcx = 2500;
-var trashcx = 2480;
 
 /**
  * Init a page editor. Works with all browsers except IE.
  */
-page.edit = function(elem, wname, wtext, wadd, wdelete, onchange, onselect) {
+page.edit = function(elem, wvalue, wadd, wdelete, onchange, onselect) {
 
     // Track element dragging and selection
     page.dragging = null;
     page.selected = null;
-    wname.disabled = true;
-    wtext.disabled = true;
+    wvalue.disabled = true;
     wdelete.disabled = true;
 
     // Trigger widget select and page change events
@@ -49,59 +47,22 @@ page.edit = function(elem, wname, wtext,
      */
     elem.onmousedown = function(e) {
 
-        // Find a draggable element
-        page.dragging = page.draggable(e.target, elem);
-        page.selected = page.dragging;
-        if (page.dragging == null) {
-
-            // Reset current selection
-            wname.value = '';
-            wname.disabled = true;
-            wtext.value = '';
-            wtext.disabled = true;
-            wdelete.disabled = true;
+        // On mouse controlled devices, engage the click component selection
+        // logic right away
+        if (typeof e.touches == 'undefined')
+            elem.onclick(e);
 
-            // Trigger widget select event
-            page.onwidgetselect('');
+        // Find a draggable element
+        var dragging = page.draggable(e.target, elem);
+        if (dragging == null || dragging != page.selected)
             return true;
-        }
-
-        // Clone element dragged from palette
-        if (page.dragging.id.substring(0, 8) == 'palette:') {
-            page.dragging = page.clone(page.dragging);
-            page.selected = page.dragging;
-
-            // Move into the editing area and hide the palette
-            page.selected.style.left = ui.pixpos(ui.numpos(page.selected.style.left) + palcx);
-            elem.style.left = ui.pixpos(palcx * -1);
-        
-            // Bring it to the top
-            page.bringtotop(page.dragging);
-
-            // Trigger page change event
-            page.onpagechange(true);
-
-        } else {
-
-            // Bring it to the top
-            page.bringtotop(page.dragging);
-        }
+        page.dragging = dragging;
 
         // Remember mouse position
         var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
         page.dragX = pos.screenX;
         page.dragY = pos.screenY;
 
-        // Update the widget name and text fields
-        wname.value = page.selected.id;
-        wname.disabled = false;
-        wtext.value = page.text(page.selected);
-        wtext.disabled = !page.hastext(page.selected);
-        wdelete.disabled = false;
-
-        // Trigger widget select event
-        page.onwidgetselect(page.selected.id);
-
         if (e.preventDefault)
             e.preventDefault();
         else
@@ -130,29 +91,6 @@ page.edit = function(elem, wname, wtext,
         // Fixup widget style
         page.fixupwidget(page.dragging);
 
-        // Discard element dragged out of page area
-        if (ui.numpos(page.dragging.style.left) < palcx && page.dragging.id.substring(0, 8) != 'palette:') {
-            if (ui.numpos(page.dragging.style.left) >= trashcx) {
-
-                // Unless it's close enough to page area, then move it there
-                page.dragging.style.left = ui.pixpos(palcx);
-                page.dragging.cover.style.left = ui.pixpos(palcx);
-            } else {
-                page.dragging.parentNode.removeChild(page.dragging);
-
-                // Reset current selection
-                page.selected = null;
-                wname.value = '';
-                wname.disabled = true;
-                wtext.value = '';
-                wtext.disabled = true;
-                wdelete.disabled = true;
-
-                // Trigger widget select event
-                page.onwidgetselect('');
-            }
-        }
-
         // Forget dragged element
         page.dragging = null;
 
@@ -171,16 +109,20 @@ page.edit = function(elem, wname, wtext,
         if (page.dragging == null)
             return true;
 
+        // Get the mouse position
+        var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
+        if (pos.screenX == page.dragX && pos.screenY == page.dragY)
+            return true;
+
         // Compute position of dragged element
         var curX = ui.numpos(page.dragging.style.left);
         var curY = ui.numpos(page.dragging.style.top);
-        var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
         var newX = curX + (pos.screenX - page.dragX);
         var newY = curY + (pos.screenY - page.dragY);
-        if (newX >= 0)
+        if (newX >= palcx)
             page.dragX = pos.screenX;
         else
-            newX = 0;
+            newX = palcx;
         if (newY >= 0)
             page.dragY = pos.screenY;
         else
@@ -201,32 +143,70 @@ page.edit = function(elem, wname, wtext,
      * Handle a mouse click event.
      */
     elem.onclick = function(e) {
-        if (page.dragging == null) {
+
+        // Find selected element
+        var selected = page.draggable(e.target, elem);
+        if (selected == null) {
+            if (page.selected != null) {
+
+                // Reset current selection
+                page.widgetselect(page.selected, false, wvalue, wdelete);
+                page.selected = null;
+
+                // Trigger widget select event
+                page.onwidgetselect(null);
+            }
 
             // Dismiss the palette
             if (ui.numpos(elem.style.left) != (palcx * -1))
                 elem.style.left = ui.pixpos(palcx * -1);
+
+            return true;
+        }
+
+        // Deselect the previously selected element
+        page.widgetselect(page.selected, false, wvalue, wdelete);
+
+        // Clone element dragged from palette
+        if (selected.id.substring(0, 8) == 'palette:') {
+            page.selected = page.clone(selected);
+
+            // Move into the editing area and hide the palette
+            page.selected.style.left = ui.pixpos(ui.numpos(page.selected.style.left) + palcx);
+            page.selected.cover.style.left = ui.pixpos(ui.numpos(page.selected.cover.style.left) + palcx);
+            elem.style.left = ui.pixpos(palcx * -1);
+        
+            // Bring it to the top
+            page.bringtotop(page.selected);
+
+            // Trigger page change event
+            page.onpagechange(true);
+
+        } else {
+
+            // Bring selected element to the top
+            page.selected = selected;
+            page.bringtotop(page.selected);
         }
+
+        // Select the element
+        page.widgetselect(page.selected, true, wvalue, wdelete);
+
+        // Trigger widget select event
+        page.onwidgetselect(page.selected);
+
         return true;
     };
 
     /**
      * Handle field on change events.
      */
-    wname.onchange = wname.onblur = function() {
-        if (page.selected == null)
-            return false;
-        page.selected.id = wname.value;
-
-        // Trigger page change event
-        page.onpagechange(true);
-        return false;
-    };
-
-    wtext.onchange = wtext.onblur = function() {
+    wvalue.onchange = wvalue.onblur = function() {
         if (page.selected == null)
             return false;
-        page.settext(page.selected, wtext.value);
+        page.settext(page.selected, wvalue.value);
+        page.selected.cover.style.width = ui.pixpos(page.selected.clientWidth + 4);
+        page.selected.cover.style.height = ui.pixpos(page.selected.clientHeight + 4);
 
         // Trigger page change event
         page.onpagechange(true);
@@ -246,19 +226,16 @@ page.edit = function(elem, wname, wtext,
         if (page.selected == null)
             return false;
 
+        // Reset current selection
+        page.widgetselect(page.selected, false, wvalue, wdelete);
+
         // Remove selected widget
         page.selected.parentNode.removeChild(page.selected);
-
-        // Reset current selection
+        page.selected.cover.parentNode.removeChild(page.selected.cover);
         page.selected = null;
-        wname.value = '';
-        wname.disabled = true;
-        wtext.value = '';
-        wtext.disabled = true;
-        wdelete.disabled = true;
 
         // Trigger widget select event
-        page.onwidgetselect('');
+        page.onwidgetselect(null);
 
         // Trigger page change event
         page.onpagechange(true);
@@ -276,6 +253,11 @@ page.edit = function(elem, wname, wtext,
  * Return the text of a widget.
  */
 page.text = function(e) {
+    var formula = e.id;
+    if (formula.substring(0, 5) != 'page:') {
+        return '=' + formula;
+    }
+
     if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section')
         return car(childElements(e)).innerHTML;
     if (e.className == 'button' || e.className == 'checkbox')
@@ -331,6 +313,9 @@ page.hastext = function(e) {
  * Set the text of a widget.
  */
 page.settext = function(e, t) {
+    var formula = t.length > 1 && t.substring(0, 1) == '=';
+    e.id = formula? t.substring(1) : 'page:' + e.className;
+
     if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') {
         car(childElements(e)).innerHTML = t;
         return t;
@@ -351,10 +336,12 @@ page.settext = function(e, t) {
         return t;
     }
     if (e.className == 'list') {
+        e.innerHTML = '<table class="datatable" style="width: 100%;;"><tr><td class="datatd">' + t + '</td></tr><tr><td class="datatd">...</td></tr></table>';
         return '';
     }
     if (e.className == 'table') {
-        return '';
+        e.innerHTML = '<table class="datatable" style="width: 100%;"><tr><td class="datatdl">' + t + '</td><td class="datatdr">...</td></tr><tr><td class="datatdl">...</td><td class="datatdr">...</td></tr></table>';
+        return t;
     }
     if (e.className == 'link') {
         var l = t.split(',');
@@ -364,11 +351,11 @@ page.settext = function(e, t) {
         return t;
     }
     if (e.className == 'img') {
-        car(childElements(e)).src = t;
+        car(childElements(e)).src = formula? '/public/img.png' : t;
         return t;
     }
     if (e.className == 'iframe') {
-        car(childElements(e)).href = t;
+        car(childElements(e)).href = formula? '/public/iframe.html' : t;
         return t;
     }
     return '';
@@ -388,10 +375,12 @@ page.fixupwidget = function(e) {
         return e;
     }
     if (e.className == 'list') {
+        e.style.width = '100%';
         car(childElements(e)).style.width = '100%';
         return e;
     }
     if (e.className == 'table') {
+        e.style.width = '100%';
         car(childElements(e)).style.width = '100%';
         return e;
     }
@@ -427,19 +416,51 @@ page.bringtotop = function(n) {
 }
 
 /**
+ * Draw widget selection.
+ */
+page.widgetselect = function(n, s, wvalue, wdelete) {
+    if (isNil(n) || !s) {
+        // Clear the widget value field
+        wvalue.value = '';
+        wvalue.disabled = true;
+        wdelete.disabled = true;
+
+        // Clear the widget outline
+        if (!isNil(n))
+            n.cover.style.borderWidth = '0px';
+    }
+    if (isNil(n))
+        return true;
+
+    // Update the widget value field
+    wvalue.value = page.text(n);
+    wvalue.disabled = false;
+    wdelete.disabled = false;
+
+    // Outline the widget
+    n.cover.style.borderWidth = s? '2px' : '0px';
+    return true;
+};
+
+/**
  * Cover a page element with a <span> element to prevent
  * any input events to reach it.
  */
 page.cover = function(e) {
     if (e.id == '' || isNil(e.style))
         return e;
-    var cover = document.createElement('span');
+    var cover = document.createElement('div');
     cover.style.position = 'absolute';
-    cover.style.left = ui.pixpos(ui.numpos(e.style.left) - 5);
-    cover.style.top = ui.pixpos(ui.numpos(e.style.top) - 5);
-    cover.style.width = e.clientWidth + 10;
-    cover.style.height = e.clientHeight + 10;
-    cover.style.visibility = 'visible';
+    cover.style.left = ui.pixpos(ui.numpos(e.style.left) - 2);
+    cover.style.top = ui.pixpos(ui.numpos(e.style.top) - 2);
+    cover.style.width = ui.pixpos(e.clientWidth + 4);
+    cover.style.height = ui.pixpos(e.clientHeight + 4);
+    cover.style.visibility = 'inherit';
+    cover.style.borderStyle = 'solid';
+    cover.style.borderWidth = '0px';
+    cover.style.borderColor = '#598edd';
+    cover.style.padding = '0px';
+    cover.style.margin = '0px';
     cover.covered = e;
     e.cover = cover;
     e.parentNode.appendChild(cover);
@@ -458,11 +479,15 @@ page.clone = function(e) {
         var ne = document.createElement('span');
 
         // Skip the palette: prefix
-        ne.id = e.id.substr(8);
+        ne.id = 'page:' + e.id.substr(8);
 
         // Copy the class and HTML content
         ne.className = e.className;
         ne.innerHTML = e.innerHTML;
+
+        // Fixup the widget style
+        page.fixupwidget(ne);
+
         return ne;
     }
 

Modified: tuscany/sca-cpp/trunk/modules/edit/htdocs/stats/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/edit/htdocs/stats/index.html?rev=1126297&r1=1126296&r2=1126297&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/edit/htdocs/stats/index.html (original)
+++ tuscany/sca-cpp/trunk/modules/edit/htdocs/stats/index.html Mon May 23 02:28:47 2011
@@ -36,14 +36,18 @@
 
 <table style="width: 100%;">
 <tr>
-<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
+<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
 <td style="vertical-align: middle; text-align: right;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
 </tr>
 </table>
 
 <table style="width: 100%;">
 <tr>
-<th class="thl thr" style="padding-top: 4px; padding-bottom: 4px;">Stats</th>
+<th class="thl thr" style="padding-top: 4px; padding-bottom: 4px; padding-left: 2px; padding-right: 2px; ">Stats</th>
+
+<th class="thl thr" style="width: 100%; text-align: right; padding-right: 2px; padding-top: 0px; padding-bottom: 0px;">
+<input type="button" class="greenbutton" style="font-weight: bold; margin-top: 0px; margin-bottom: 0px; height: 24px;" id="cloneApp" value="Clone" title="Clone this app"/>
+</th>
 </tr>
 </table>
 
@@ -85,8 +89,11 @@ function applink(appname) {
 
 // Set page titles
 document.title = windowtitle(window.location.hostname) + ' - Stats - ' + appname;
-$('h1').innerHTML = hometitle(window.location.hostname);
-$('appNameHeader').innerHTML = ' - <a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
+//$('h1').innerHTML = hometitle(window.location.hostname);
+$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '.' + window.location.hostname + '</a>';
+var tclone = isNil(config.clone)? 'Clone' : config.clone;
+$('cloneApp').value = tclone;
+$('cloneApp').title = tclone + ' this app';
 
 // Load the menu bar
 displaymenu();
@@ -96,7 +103,7 @@ ui.showbody();
 
 // Init service references
 var editWidget = sca.component("EditWidget");
-var dashboard = sca.reference(editWidget, "dashboard");
+var dashboards = sca.reference(editWidget, "dashboards");
 
 /**
  * The current app entry and corresponding saved XML content.
@@ -110,7 +117,7 @@ var savedappentryxml = '';
 function getapp(name) {
     if (isNil(name))
         return false;
-    return dashboard.get(name, function(doc) {
+    return dashboards.get(name, function(doc) {
         appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
         var title = cadr(assoc("'title", cdr(appentry)));
         $('appTitle').value = title;
@@ -127,7 +134,7 @@ function getapp(name) {
 function save(entryxml) {
     $('saveStatus').innerHTML = 'Saving';
     savedappentryxml = entryxml;
-    dashboard.put(appname, savedappentryxml);
+    dashboards.put(appname, savedappentryxml);
     $('saveStatus').innerHTML = 'Saved';
     return true;
 }
@@ -156,6 +163,13 @@ $('appForm').onsubmit = function() {
     return false;
 };
 
+/**
+ * Handle Clone button event.
+ */
+$('cloneApp').onclick = function() {
+    return window.open('/clone/?app=' + appname, '_self');
+}
+
 // Get the current app
 getapp(appname);